simplify inetboxapp code.

This commit is contained in:
Your Name 2023-03-20 12:27:16 +01:00
parent 975797a300
commit 6689ee5c00
10 changed files with 155 additions and 223 deletions

View File

@ -9,41 +9,16 @@ namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.TrumaiNetBoxApp"; static const char *const TAG = "truma_inetbox.TrumaiNetBoxApp";
TrumaiNetBoxApp::TrumaiNetBoxApp(u_int8_t expected_listener_count) {
this->listeners_heater_.reserve(expected_listener_count);
}
void TrumaiNetBoxApp::update() { void TrumaiNetBoxApp::update() {
// Call listeners in after method 'lin_multiframe_recieved' call. // Call listeners in after method 'lin_multiframe_recieved' call.
// Because 'lin_multiframe_recieved' is time critical an all these sensors can take some time. // Because 'lin_multiframe_recieved' is time critical an all these sensors can take some time.
if (this->status_heater_updated_ || this->status_timer_updated_ || this->status_clock_updated_ ||
this->status_config_updated_) {
// Run through listeners
for (auto &listener : this->listeners_heater_) {
if (this->status_heater_updated_ && listener.on_heater_change != nullptr) {
listener.on_heater_change(&this->status_heater_);
}
if (this->status_timer_updated_ && listener.on_timer_change != nullptr) {
listener.on_timer_change(&this->status_timer_);
}
if (this->status_clock_updated_ && listener.on_clock_change != nullptr) {
listener.on_clock_change(&this->status_clock_);
}
if (this->status_config_updated_ && listener.on_config_change != nullptr) {
listener.on_config_change(&this->status_config_);
}
}
// Run through callbacks // Run through callbacks
if (this->status_heater_updated_) { heater_.update();
this->state_heater_callback_.call(&this->status_heater_); timer_.update();
} clock_.update();
// update is handeld config_.update();
this->status_heater_updated_ = false;
this->status_timer_updated_ = false;
this->status_clock_updated_ = false;
this->status_config_updated_ = false;
}
LinBusProtocol::update(); LinBusProtocol::update();
#ifdef USE_TIME #ifdef USE_TIME
@ -60,6 +35,13 @@ void TrumaiNetBoxApp::update() {
#endif // USE_TIME #endif // USE_TIME
} }
template<typename T> void TrumaStausFrameStorage<T>::update() {
if (this->data_updated_) {
this->state_callback_.call(&this->data_);
}
this->data_updated_ = false;
}
const std::array<uint8_t, 4> TrumaiNetBoxApp::lin_identifier() { const std::array<uint8_t, 4> TrumaiNetBoxApp::lin_identifier() {
// Supplier Id: 0x4617 - Truma (Phone: +49 (0)89 4617-0) // Supplier Id: 0x4617 - Truma (Phone: +49 (0)89 4617-0)
// Unknown: // Unknown:
@ -86,110 +68,73 @@ void TrumaiNetBoxApp::lin_reset_device() {
this->device_registered_ = micros(); this->device_registered_ = micros();
this->init_recieved_ = 0; this->init_recieved_ = 0;
this->status_heater_valid_ = false; this->heater_.reset();
this->status_heater_updated_ = false; this->timer_.reset();
this->status_timer_valid_ = false; this->clock_.reset();
this->status_timer_updated_ = false; this->config_.reset();
this->status_clock_valid_ = false;
this->status_clock_updated_ = false;
this->status_config_valid_ = false;
this->status_config_updated_ = false;
this->update_time_ = 0; this->update_time_ = 0;
this->update_status_heater_prepared_ = false;
this->update_status_heater_unsubmitted_ = false;
this->update_status_heater_stale_ = false;
this->update_status_aircon_prepared_ = false; this->update_status_aircon_prepared_ = false;
this->update_status_aircon_unsubmitted_ = false; this->update_status_aircon_unsubmitted_ = false;
this->update_status_aircon_stale_ = false; this->update_status_aircon_stale_ = false;
this->update_status_timer_prepared_ = false;
this->update_status_timer_unsubmitted_ = false;
this->update_status_timer_stale_ = false;
} }
void TrumaiNetBoxApp::register_listener(const std::function<void(const StatusFrameHeater *)> &func) { template<typename T> void TrumaStausFrameStorage<T>::reset() {
StatusFrameListener listener = {}; this->data_valid_ = false;
listener.on_heater_change = func; this->data_updated_ = false;
this->listeners_heater_.push_back(std::move(listener)); }
if (this->status_heater_valid_) { template<typename T, typename TResponse> void TrumaStausFrameResponseStorage<T, TResponse>::reset() {
func(&this->status_heater_); TrumaStausFrameStorage<T>::reset();
} this->update_status_prepared_ = false;
} this->update_status_unsubmitted_ = false;
void TrumaiNetBoxApp::register_listener(const std::function<void(const StatusFrameTimer *)> &func) { this->update_status_stale_ = false;
StatusFrameListener listener = {};
listener.on_timer_change = func;
this->listeners_heater_.push_back(std::move(listener));
if (this->status_timer_valid_) {
func(&this->status_timer_);
}
}
void TrumaiNetBoxApp::register_listener(const std::function<void(const StatusFrameClock *)> &func) {
StatusFrameListener listener = {};
listener.on_clock_change = func;
this->listeners_heater_.push_back(std::move(listener));
if (this->status_clock_valid_) {
func(&this->status_clock_);
}
}
void TrumaiNetBoxApp::register_listener(const std::function<void(const StatusFrameConfig *)> &func) {
StatusFrameListener listener = {};
listener.on_config_change = func;
this->listeners_heater_.push_back(std::move(listener));
if (this->status_config_valid_) {
func(&this->status_config_);
}
} }
StatusFrameHeaterResponse *TrumaiNetBoxApp::update_heater_prepare() { StatusFrameHeaterResponse *TrumaiNetBoxApp::update_heater_prepare() {
// An update is currently going on. // An update is currently going on.
if (this->update_status_heater_prepared_ || this->update_status_heater_stale_) { if (this->heater_.update_status_prepared_ || this->heater_.update_status_stale_) {
return &this->update_status_heater_; return &this->heater_.update_status_;
} }
// prepare status heater response // prepare status heater response
this->update_status_heater_ = {}; this->heater_.update_status_ = {};
this->update_status_heater_.target_temp_room = this->status_heater_.target_temp_room; this->heater_.update_status_.target_temp_room = this->heater_.data_.target_temp_room;
this->update_status_heater_.heating_mode = this->status_heater_.heating_mode; this->heater_.update_status_.heating_mode = this->heater_.data_.heating_mode;
this->update_status_heater_.el_power_level_a = this->status_heater_.el_power_level_a; this->heater_.update_status_.el_power_level_a = this->heater_.data_.el_power_level_a;
this->update_status_heater_.target_temp_water = this->status_heater_.target_temp_water; this->heater_.update_status_.target_temp_water = this->heater_.data_.target_temp_water;
this->update_status_heater_.el_power_level_b = this->status_heater_.el_power_level_b; this->heater_.update_status_.el_power_level_b = this->heater_.data_.el_power_level_b;
this->update_status_heater_.energy_mix_a = this->status_heater_.energy_mix_a; this->heater_.update_status_.energy_mix_a = this->heater_.data_.energy_mix_a;
this->update_status_heater_.energy_mix_b = this->status_heater_.energy_mix_b; this->heater_.update_status_.energy_mix_b = this->heater_.data_.energy_mix_b;
this->update_status_heater_prepared_ = true; this->heater_.update_status_prepared_ = true;
return &this->update_status_heater_; return &this->heater_.update_status_;
} }
StatusFrameTimerResponse *TrumaiNetBoxApp::update_timer_prepare() { StatusFrameTimerResponse *TrumaiNetBoxApp::update_timer_prepare() {
// An update is currently going on. // An update is currently going on.
if (this->update_status_timer_prepared_ || this->update_status_timer_stale_) { if (this->timer_.update_status_prepared_ || this->timer_.update_status_stale_) {
return &this->update_status_timer_; return &this->timer_.update_status_;
} }
// prepare status heater response // prepare status heater response
this->update_status_timer_ = {}; this->timer_.update_status_ = {};
this->update_status_timer_.timer_target_temp_room = this->status_timer_.timer_target_temp_room; this->timer_.update_status_.timer_target_temp_room = this->timer_.data_.timer_target_temp_room;
this->update_status_timer_.timer_heating_mode = this->status_timer_.timer_heating_mode; this->timer_.update_status_.timer_heating_mode = this->timer_.data_.timer_heating_mode;
this->update_status_timer_.timer_el_power_level_a = this->status_timer_.timer_el_power_level_a; this->timer_.update_status_.timer_el_power_level_a = this->timer_.data_.timer_el_power_level_a;
this->update_status_timer_.timer_target_temp_water = this->status_timer_.timer_target_temp_water; this->timer_.update_status_.timer_target_temp_water = this->timer_.data_.timer_target_temp_water;
this->update_status_timer_.timer_el_power_level_b = this->status_timer_.timer_el_power_level_b; this->timer_.update_status_.timer_el_power_level_b = this->timer_.data_.timer_el_power_level_b;
this->update_status_timer_.timer_energy_mix_a = this->status_timer_.timer_energy_mix_a; this->timer_.update_status_.timer_energy_mix_a = this->timer_.data_.timer_energy_mix_a;
this->update_status_timer_.timer_energy_mix_b = this->status_timer_.timer_energy_mix_b; this->timer_.update_status_.timer_energy_mix_b = this->timer_.data_.timer_energy_mix_b;
this->update_status_timer_.timer_resp_active = this->status_timer_.timer_active; this->timer_.update_status_.timer_resp_active = this->timer_.data_.timer_active;
this->update_status_timer_.timer_resp_start_minutes = this->status_timer_.timer_start_minutes; this->timer_.update_status_.timer_resp_start_minutes = this->timer_.data_.timer_start_minutes;
this->update_status_timer_.timer_resp_start_hours = this->status_timer_.timer_start_hours; this->timer_.update_status_.timer_resp_start_hours = this->timer_.data_.timer_start_hours;
this->update_status_timer_.timer_resp_stop_minutes = this->status_timer_.timer_stop_minutes; this->timer_.update_status_.timer_resp_stop_minutes = this->timer_.data_.timer_stop_minutes;
this->update_status_timer_.timer_resp_stop_hours = this->status_timer_.timer_stop_hours; this->timer_.update_status_.timer_resp_stop_hours = this->timer_.data_.timer_stop_hours;
this->update_status_timer_prepared_ = true; this->timer_.update_status_prepared_ = true;
return &this->update_status_timer_; return &this->timer_.update_status_;
} }
StatusFrameAirconResponse *TrumaiNetBoxApp::update_aircon_prepare() { StatusFrameAirconResponse *TrumaiNetBoxApp::update_aircon_prepare() {
@ -272,32 +217,32 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message
ESP_LOGD(TAG, "Requested read: Sending init"); ESP_LOGD(TAG, "Requested read: Sending init");
status_frame_create_init(response_frame, return_len, this->message_counter++); status_frame_create_init(response_frame, return_len, this->message_counter++);
return response; return response;
} else if (this->update_status_heater_unsubmitted_) { } else if (this->heater_.update_status_unsubmitted_) {
ESP_LOGD(TAG, "Requested read: Sending heater update"); ESP_LOGD(TAG, "Requested read: Sending heater update");
status_frame_create_update_heater( status_frame_create_update_heater(
response_frame, return_len, this->message_counter++, this->update_status_heater_.target_temp_room, response_frame, return_len, this->message_counter++, this->heater_.update_status_.target_temp_room,
this->update_status_heater_.target_temp_water, this->update_status_heater_.heating_mode, this->heater_.update_status_.target_temp_water, this->heater_.update_status_.heating_mode,
this->update_status_heater_.energy_mix_a, this->update_status_heater_.el_power_level_a); this->heater_.update_status_.energy_mix_a, this->heater_.update_status_.el_power_level_a);
this->update_time_ = 0; this->update_time_ = 0;
this->update_status_heater_prepared_ = false; this->heater_.update_status_prepared_ = false;
this->update_status_heater_unsubmitted_ = false; this->heater_.update_status_unsubmitted_ = false;
this->update_status_heater_stale_ = true; this->heater_.update_status_stale_ = true;
return response; return response;
} else if (this->update_status_timer_unsubmitted_) { } else if (this->timer_.update_status_unsubmitted_) {
ESP_LOGD(TAG, "Requested read: Sending timer update"); ESP_LOGD(TAG, "Requested read: Sending timer update");
status_frame_create_update_timer( status_frame_create_update_timer(
response_frame, return_len, this->message_counter++, this->update_status_timer_.timer_resp_active, response_frame, return_len, this->message_counter++, this->timer_.update_status_.timer_resp_active,
this->update_status_timer_.timer_resp_start_hours, this->update_status_timer_.timer_resp_start_minutes, this->timer_.update_status_.timer_resp_start_hours, this->timer_.update_status_.timer_resp_start_minutes,
this->update_status_timer_.timer_resp_stop_hours, this->update_status_timer_.timer_resp_stop_minutes, this->timer_.update_status_.timer_resp_stop_hours, this->timer_.update_status_.timer_resp_stop_minutes,
this->update_status_timer_.timer_target_temp_room, this->update_status_timer_.timer_target_temp_water, this->timer_.update_status_.timer_target_temp_room, this->timer_.update_status_.timer_target_temp_water,
this->update_status_timer_.timer_heating_mode, this->update_status_timer_.timer_energy_mix_a, this->timer_.update_status_.timer_heating_mode, this->timer_.update_status_.timer_energy_mix_a,
this->update_status_timer_.timer_el_power_level_a); this->timer_.update_status_.timer_el_power_level_a);
this->update_time_ = 0; this->update_time_ = 0;
this->update_status_timer_prepared_ = false; this->timer_.update_status_prepared_ = false;
this->update_status_timer_unsubmitted_ = false; this->timer_.update_status_unsubmitted_ = false;
this->update_status_timer_stale_ = true; this->timer_.update_status_stale_ = true;
return response; return response;
} else if (this->update_status_aircon_unsubmitted_) { } else if (this->update_status_aircon_unsubmitted_) {
ESP_LOGD(TAG, "Requested read: Sending aircon update"); ESP_LOGD(TAG, "Requested read: Sending aircon update");
@ -327,7 +272,7 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message
auto now = this->time_->now(); auto now = this->time_->now();
status_frame_create_update_clock(response_frame, return_len, this->message_counter++, now.hour, now.minute, status_frame_create_update_clock(response_frame, return_len, this->message_counter++, now.hour, now.minute,
now.second, this->status_clock_.clock_mode); now.second, this->clock_.data_.clock_mode);
} }
this->update_status_clock_unsubmitted_ = false; this->update_status_clock_unsubmitted_ = false;
return response; return response;
@ -359,11 +304,11 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message
// Example: // Example:
// SID<---------PREAMBLE---------->|<---MSG_HEAD---->|tRoom|mo| |elecA|tWate|elecB|mi|mi|cWate|cRoom|st|err | | // SID<---------PREAMBLE---------->|<---MSG_HEAD---->|tRoom|mo| |elecA|tWate|elecB|mi|mi|cWate|cRoom|st|err | |
// BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.14.33.00.12.00.00.00.00.00.00.00.00.00.00.01.01.CC.0B.6C.0B.00.00.00.00 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.14.33.00.12.00.00.00.00.00.00.00.00.00.00.01.01.CC.0B.6C.0B.00.00.00.00
this->status_heater_ = statusFrame->inner.heater; this->heater_.data_ = statusFrame->inner.heater;
this->status_heater_valid_ = true; this->heater_.data_valid_ = true;
this->status_heater_updated_ = true; this->heater_.data_updated_ = true;
this->update_status_heater_stale_ = false; this->heater_.update_status_stale_ = false;
return response; return response;
} else if (header->message_type == STATUS_FRAME_AIRCON && header->message_length == sizeof(StatusFrameAircon)) { } else if (header->message_type == STATUS_FRAME_AIRCON && header->message_length == sizeof(StatusFrameAircon)) {
ESP_LOGI(TAG, "StatusFrameAircon"); ESP_LOGI(TAG, "StatusFrameAircon");
@ -418,17 +363,17 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message
// SID<---------PREAMBLE---------->|<---MSG_HEAD---->|tRoom|mo|??|elecA|tWate|elecB|mi|mi|<--response-->|??|??|on|start|stop-| // SID<---------PREAMBLE---------->|<---MSG_HEAD---->|tRoom|mo|??|elecA|tWate|elecB|mi|mi|<--response-->|??|??|on|start|stop-|
// BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.18.3D.00.1D.18.0B.01.00.00.00.00.00.00.00.01.01.00.00.00.00.00.00.00.01.00.08.00.09 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.18.3D.00.1D.18.0B.01.00.00.00.00.00.00.00.01.01.00.00.00.00.00.00.00.01.00.08.00.09
// BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.18.3D.00.13.18.0B.0B.00.00.00.00.00.00.00.01.01.00.00.00.00.00.00.00.01.00.08.00.09 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.18.3D.00.13.18.0B.0B.00.00.00.00.00.00.00.01.01.00.00.00.00.00.00.00.01.00.08.00.09
this->status_timer_ = statusFrame->inner.timer; this->timer_.data_ = statusFrame->inner.timer;
this->status_timer_valid_ = true; this->timer_.data_valid_ = true;
this->status_timer_updated_ = true; this->timer_.data_updated_ = true;
this->update_status_timer_stale_ = false; this->timer_.update_status_stale_ = false;
ESP_LOGD(TAG, "StatusFrameTimer target_temp_room: %f target_temp_water: %f %02u:%02u -> %02u:%02u %s", ESP_LOGD(TAG, "StatusFrameTimer target_temp_room: %f target_temp_water: %f %02u:%02u -> %02u:%02u %s",
temp_code_to_decimal(this->status_timer_.timer_target_temp_room), temp_code_to_decimal(this->timer_.data_.timer_target_temp_room),
temp_code_to_decimal(this->status_timer_.timer_target_temp_water), this->status_timer_.timer_start_hours, temp_code_to_decimal(this->timer_.data_.timer_target_temp_water), this->timer_.data_.timer_start_hours,
this->status_timer_.timer_start_minutes, this->status_timer_.timer_stop_hours, this->timer_.data_.timer_start_minutes, this->timer_.data_.timer_stop_hours,
this->status_timer_.timer_stop_minutes, ((u_int8_t) this->status_timer_.timer_active ? " ON" : " OFF")); this->timer_.data_.timer_stop_minutes, ((u_int8_t) this->timer_.data_.timer_active ? " ON" : " OFF"));
return response; return response;
} else if (header->message_type == STATUS_FRAME_RESPONSE_ACK && } else if (header->message_type == STATUS_FRAME_RESPONSE_ACK &&
@ -460,12 +405,12 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message
// BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.15.00.5B.0D.20.00.01.01.00.00.01.00.00 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.15.00.5B.0D.20.00.01.01.00.00.01.00.00
// BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.15.00.71.16.00.00.01.01.00.00.02.00.00 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.15.00.71.16.00.00.01.01.00.00.02.00.00
// BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.15.00.2B.16.1F.28.01.01.00.00.01.00.00 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.15.00.2B.16.1F.28.01.01.00.00.01.00.00
this->status_clock_ = statusFrame->inner.clock; this->clock_.data_ = statusFrame->inner.clock;
this->status_clock_valid_ = true; this->clock_.data_valid_ = true;
this->status_clock_updated_ = true; this->clock_.data_updated_ = true;
ESP_LOGD(TAG, "StatusFrameClock %02d:%02d:%02d", this->status_clock_.clock_hour, this->status_clock_.clock_minute, ESP_LOGD(TAG, "StatusFrameClock %02d:%02d:%02d", this->clock_.data_.clock_hour, this->clock_.data_.clock_minute,
this->status_clock_.clock_second); this->clock_.data_.clock_second);
return response; return response;
} else if (header->message_type == STAUTS_FRAME_CONFIG && header->message_length == sizeof(StatusFrameConfig)) { } else if (header->message_type == STAUTS_FRAME_CONFIG && header->message_length == sizeof(StatusFrameConfig)) {
@ -475,11 +420,11 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message
// BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.17.00.0F.06.01.B4.0A.AA.0A.00.00.00.00 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.17.00.0F.06.01.B4.0A.AA.0A.00.00.00.00
// BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.17.00.41.06.01.B4.0A.78.0A.00.00.00.00 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.17.00.41.06.01.B4.0A.78.0A.00.00.00.00
// BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.17.00.0F.06.01.B4.0A.AA.0A.00.00.00.00 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0A.17.00.0F.06.01.B4.0A.AA.0A.00.00.00.00
this->status_config_ = statusFrame->inner.config; this->config_.data_ = statusFrame->inner.config;
this->status_config_valid_ = true; this->config_.data_valid_ = true;
this->status_config_updated_ = true; this->config_.data_updated_ = true;
ESP_LOGD(TAG, "StatusFrameConfig Offset: %.1f", temp_code_to_decimal(this->status_config_.temp_offset)); ESP_LOGD(TAG, "StatusFrameConfig Offset: %.1f", temp_code_to_decimal(this->config_.data_.temp_offset));
return response; return response;
} else if (header->message_type == STATUS_FRAME_DEVICES && header->message_length == sizeof(StatusFrameDevice)) { } else if (header->message_type == STATUS_FRAME_DEVICES && header->message_length == sizeof(StatusFrameDevice)) {
@ -556,7 +501,7 @@ bool TrumaiNetBoxApp::has_update_to_submit_() {
this->init_requested_ = micros(); this->init_requested_ = micros();
return true; return true;
} }
} else if (this->update_status_heater_unsubmitted_ || this->update_status_timer_unsubmitted_ || } else if (this->heater_.update_status_unsubmitted_ || this->timer_.update_status_unsubmitted_ ||
this->update_status_clock_unsubmitted_ || this->update_status_aircon_unsubmitted_) { this->update_status_clock_unsubmitted_ || this->update_status_aircon_unsubmitted_) {
if (this->update_time_ == 0) { if (this->update_time_ == 0) {
// ESP_LOGD(TAG, "Notify CP Plus I got updates."); // ESP_LOGD(TAG, "Notify CP Plus I got updates.");

View File

@ -477,56 +477,80 @@ union StatusFrame { // NOLINT(altera-struct-pack-align)
} inner; } inner;
} __attribute__((packed)); } __attribute__((packed));
struct StatusFrameListener { template<typename T> class TrumaStausFrameStorage {
std::function<void(const StatusFrameHeater *)> on_heater_change = nullptr; public:
std::function<void(const StatusFrameTimer *)> on_timer_change = nullptr; CallbackManager<void(const T *)> state_callback_{};
std::function<void(const StatusFrameClock *)> on_clock_change = nullptr; T data_;
std::function<void(const StatusFrameConfig *)> on_config_change = nullptr; bool data_valid_ = false;
// Value has changed notify listeners.
bool data_updated_ = false;
// bool get_status_valid() { return this->data_valid_; }
// const T *get_status() { return &this->data_; }
void update();
void reset();
};
template<typename T, typename TResponse> class TrumaStausFrameResponseStorage : public TrumaStausFrameStorage<T> {
public:
void reset();
// Prepared means `update_status_` was copied from `data_`.
bool update_status_prepared_ = false;
// Prepared means an update is already awating fetch from CP plus.
bool update_status_unsubmitted_ = false;
// I have submitted my update request to CP plus, but I have not recieved an update with new heater values from CP
// plus.
bool update_status_stale_ = false;
TResponse update_status_;
}; };
class TrumaiNetBoxApp : public LinBusProtocol { class TrumaiNetBoxApp : public LinBusProtocol {
public: public:
TrumaiNetBoxApp(u_int8_t expected_listener_count);
void update() override; void update() override;
const std::array<u_int8_t, 4> lin_identifier() override; const std::array<u_int8_t, 4> lin_identifier() override;
void lin_heartbeat() override; void lin_heartbeat() override;
void lin_reset_device() override; void lin_reset_device() override;
bool get_status_heater_valid() { return this->status_heater_valid_; } bool get_status_heater_valid() { return this->heater_.data_valid_; }
const StatusFrameHeater *get_status_heater() { return &this->status_heater_; } const StatusFrameHeater *get_status_heater() { return &this->heater_.data_; }
void register_listener(const std::function<void(const StatusFrameHeater *)> &func);
bool get_status_timer_valid() { return this->status_timer_valid_; } bool get_status_timer_valid() { return this->timer_.data_valid_; }
const StatusFrameTimer *get_status_timer() { return &this->status_timer_; } const StatusFrameTimer *get_status_timer() { return &this->timer_.data_; }
void register_listener(const std::function<void(const StatusFrameTimer *)> &func);
bool get_status_clock_valid() { return this->status_clock_valid_; } bool get_status_clock_valid() { return this->clock_.data_valid_; }
const StatusFrameClock *get_status_clock() { return &this->status_clock_; } const StatusFrameClock *get_status_clock() { return &this->clock_.data_; }
void register_listener(const std::function<void(const StatusFrameClock *)> &func);
bool get_status_config_valid() { return this->status_config_valid_; } bool get_status_config_valid() { return this->config_.data_valid_; }
const StatusFrameConfig *get_status_config() { return &this->status_config_; } const StatusFrameConfig *get_status_config() { return &this->config_.data_; }
void register_listener(const std::function<void(const StatusFrameConfig *)> &func);
bool truma_heater_can_update() { return this->status_heater_valid_; } bool truma_heater_can_update() { return this->heater_.data_valid_; }
StatusFrameHeaterResponse *update_heater_prepare(); StatusFrameHeaterResponse *update_heater_prepare();
void update_heater_submit() { this->update_status_heater_unsubmitted_ = true; } void update_heater_submit() { this->heater_.update_status_unsubmitted_ = true; }
bool truma_aircon_can_update() { return this->status_aircon_valid_; } bool truma_aircon_can_update() { return this->status_aircon_valid_; }
StatusFrameAirconResponse *update_aircon_prepare(); StatusFrameAirconResponse *update_aircon_prepare();
void update_aircon_submit() { this->update_status_aircon_unsubmitted_ = true; } void update_aircon_submit() { this->update_status_aircon_unsubmitted_ = true; }
bool truma_timer_can_update() { return this->status_timer_valid_; } bool truma_timer_can_update() { return this->timer_.data_valid_; }
StatusFrameTimerResponse *update_timer_prepare(); StatusFrameTimerResponse *update_timer_prepare();
void update_timer_submit() { this->update_status_timer_unsubmitted_ = true; } void update_timer_submit() { this->timer_.update_status_unsubmitted_ = true; }
int64_t get_last_cp_plus_request() { return this->device_registered_; } int64_t get_last_cp_plus_request() { return this->device_registered_; }
// Automation // Automation
void add_on_heater_message_callback(std::function<void(const StatusFrameHeater *)> callback) { void add_on_heater_message_callback(std::function<void(const StatusFrameHeater *)> callback) {
this->state_heater_callback_.add(std::move(callback)); this->heater_.state_callback_.add(std::move(callback));
}
void add_on_timer_message_callback(std::function<void(const StatusFrameTimer *)> callback) {
this->timer_.state_callback_.add(std::move(callback));
}
void add_on_clock_message_callback(std::function<void(const StatusFrameClock *)> callback) {
this->clock_.state_callback_.add(std::move(callback));
}
void add_on_config_message_callback(std::function<void(const StatusFrameConfig *)> callback) {
this->config_.state_callback_.add(std::move(callback));
} }
bool action_heater_room(u_int8_t temperature, HeatingMode mode = HeatingMode::HEATING_MODE_OFF); bool action_heater_room(u_int8_t temperature, HeatingMode mode = HeatingMode::HEATING_MODE_OFF);
bool action_heater_water(u_int8_t temperature); bool action_heater_water(u_int8_t temperature);
@ -542,7 +566,7 @@ class TrumaiNetBoxApp : public LinBusProtocol {
#ifdef USE_TIME #ifdef USE_TIME
void set_time(time::RealTimeClock *time) { time_ = time; } void set_time(time::RealTimeClock *time) { time_ = time; }
bool truma_clock_can_update() { return this->status_clock_valid_; } bool truma_clock_can_update() { return this->clock_.data_valid_; }
void update_clock_submit() { this->update_status_clock_unsubmitted_ = true; } void update_clock_submit() { this->update_status_clock_unsubmitted_ = true; }
bool action_write_time(); bool action_write_time();
#endif // USE_TIME #endif // USE_TIME
@ -558,59 +582,24 @@ class TrumaiNetBoxApp : public LinBusProtocol {
TRUMA_DEVICE heater_device_ = TRUMA_DEVICE::HEATER_COMBI4; TRUMA_DEVICE heater_device_ = TRUMA_DEVICE::HEATER_COMBI4;
TRUMA_DEVICE aircon_device_ = TRUMA_DEVICE::UNKNOWN; TRUMA_DEVICE aircon_device_ = TRUMA_DEVICE::UNKNOWN;
std::vector<StatusFrameListener> listeners_heater_; TrumaStausFrameResponseStorage<StatusFrameHeater, StatusFrameHeaterResponse> heater_;
CallbackManager<void(const StatusFrameHeater *)> state_heater_callback_{}; TrumaStausFrameResponseStorage<StatusFrameTimer, StatusFrameTimerResponse> timer_;
TrumaStausFrameStorage<StatusFrameConfig> config_;
bool status_heater_valid_ = false; TrumaStausFrameStorage<StatusFrameClock> clock_;
// Value has changed notify listeners.
bool status_heater_updated_ = false;
StatusFrameHeater status_heater_;
bool status_aircon_valid_ = false; bool status_aircon_valid_ = false;
// Value has changed notify listeners. // Value has changed notify listeners.
bool status_aircon_updated_ = false; bool status_aircon_updated_ = false;
StatusFrameAircon status_aircon_; StatusFrameAircon status_aircon_;
bool status_timer_valid_ = false;
// Value has changed notify listeners.
bool status_timer_updated_ = false;
StatusFrameTimer status_timer_;
bool status_clock_valid_ = false;
// Value has changed notify listeners.
bool status_clock_updated_ = false;
StatusFrameClock status_clock_;
bool status_config_valid_ = false;
// Value has changed notify listeners.
bool status_config_updated_ = false;
StatusFrameConfig status_config_;
// last time CP plus was informed I got an update msg. // last time CP plus was informed I got an update msg.
uint32_t update_time_ = 0; uint32_t update_time_ = 0;
// Prepared means `update_status_heater_` was copied from `status_heater_`.
bool update_status_heater_prepared_ = false;
// Prepared means an update is already awating fetch from CP plus.
bool update_status_heater_unsubmitted_ = false;
// I have submitted my update request to CP plus, but I have not recieved an update with new heater values from CP
// plus.
bool update_status_heater_stale_ = false;
StatusFrameHeaterResponse update_status_heater_;
bool update_status_aircon_prepared_ = false; bool update_status_aircon_prepared_ = false;
bool update_status_aircon_unsubmitted_ = false; bool update_status_aircon_unsubmitted_ = false;
bool update_status_aircon_stale_ = false; bool update_status_aircon_stale_ = false;
StatusFrameAirconResponse update_status_aircon_; StatusFrameAirconResponse update_status_aircon_;
// Prepared means `update_status_timer_` was copied from `status_timer_`.
bool update_status_timer_prepared_ = false;
// Prepared means an update is already awating fetch from CP plus.
bool update_status_timer_unsubmitted_ = false;
// I have submitted my update request to CP plus, but I have not recieved an update with new timer values from CP
// plus.
bool update_status_timer_stale_ = false;
StatusFrameTimerResponse update_status_timer_;
#ifdef USE_TIME #ifdef USE_TIME
time::RealTimeClock *time_ = nullptr; time::RealTimeClock *time_ = nullptr;

View File

@ -226,8 +226,6 @@ CONFIG_SCHEMA = cv.All(
FINAL_VALIDATE_SCHEMA = cv.All( FINAL_VALIDATE_SCHEMA = cv.All(
final_validate_device_schema( final_validate_device_schema(
"truma_inetbox", baud_rate=9600, require_tx=True, require_rx=True, stop_bits=2, data_bits=8, parity="NONE", require_hardware_uart=True), "truma_inetbox", baud_rate=9600, require_tx=True, require_rx=True, stop_bits=2, data_bits=8, parity="NONE", require_hardware_uart=True),
count_id_usage(CONF_NUMBER_OF_CHILDREN, [
CONF_TRUMA_INETBOX_ID, CONF_ID], TrumaINetBoxApp),
) )
async def to_code(config): async def to_code(config):
@ -237,7 +235,7 @@ async def to_code(config):
# Default Stack Size is 2048. Not enough for my operation. # Default Stack Size is 2048. Not enough for my operation.
cg.add_build_flag("-DARDUINO_SERIAL_EVENT_TASK_STACK_SIZE=4096") cg.add_build_flag("-DARDUINO_SERIAL_EVENT_TASK_STACK_SIZE=4096")
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NUMBER_OF_CHILDREN]) var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config) await cg.register_component(var, config)
await uart.register_uart_device(var, config) await uart.register_uart_device(var, config)
if (CONF_TIME_ID in config): if (CONF_TIME_ID in config):

View File

@ -8,7 +8,7 @@ namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.heater_binary_sensor"; static const char *const TAG = "truma_inetbox.heater_binary_sensor";
void TrumaHeaterBinarySensor::setup() { void TrumaHeaterBinarySensor::setup() {
this->parent_->register_listener([this](const StatusFrameHeater *status_heater) { this->parent_->add_on_heater_message_callback([this](const StatusFrameHeater *status_heater) {
switch (this->type_) { switch (this->type_) {
case TRUMA_BINARY_SENSOR_TYPE::HEATER_ROOM: case TRUMA_BINARY_SENSOR_TYPE::HEATER_ROOM:
this->publish_state(status_heater->target_temp_room != TargetTemp::TARGET_TEMP_OFF); this->publish_state(status_heater->target_temp_room != TargetTemp::TARGET_TEMP_OFF);

View File

@ -8,7 +8,7 @@ namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.timer_binary_sensor"; static const char *const TAG = "truma_inetbox.timer_binary_sensor";
void TrumaTimerBinarySensor::setup() { void TrumaTimerBinarySensor::setup() {
this->parent_->register_listener([this](const StatusFrameTimer *status_timer) { this->parent_->add_on_timer_message_callback([this](const StatusFrameTimer *status_timer) {
switch (this->type_) { switch (this->type_) {
case TRUMA_BINARY_SENSOR_TYPE::TIMER_ACTIVE: case TRUMA_BINARY_SENSOR_TYPE::TIMER_ACTIVE:
this->publish_state(status_timer->timer_active == TimerActive::TIMER_ACTIVE_ON); this->publish_state(status_timer->timer_active == TimerActive::TIMER_ACTIVE_ON);

View File

@ -6,7 +6,7 @@ namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.room_climate"; static const char *const TAG = "truma_inetbox.room_climate";
void TrumaRoomClimate::setup() { void TrumaRoomClimate::setup() {
this->parent_->register_listener([this](const StatusFrameHeater *status_heater) { this->parent_->add_on_heater_message_callback([this](const StatusFrameHeater *status_heater) {
// Publish updated state // Publish updated state
this->target_temperature = temp_code_to_decimal(status_heater->target_temp_room); this->target_temperature = temp_code_to_decimal(status_heater->target_temp_room);
this->current_temperature = temp_code_to_decimal(status_heater->current_temp_room); this->current_temperature = temp_code_to_decimal(status_heater->current_temp_room);

View File

@ -6,7 +6,7 @@ namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.water_climate"; static const char *const TAG = "truma_inetbox.water_climate";
void TrumaWaterClimate::setup() { void TrumaWaterClimate::setup() {
this->parent_->register_listener([this](const StatusFrameHeater *status_heater) { this->parent_->add_on_heater_message_callback([this](const StatusFrameHeater *status_heater) {
// Publish updated state // Publish updated state
this->target_temperature = temp_code_to_decimal(status_heater->target_temp_water); this->target_temperature = temp_code_to_decimal(status_heater->target_temp_water);
this->current_temperature = temp_code_to_decimal(status_heater->current_temp_water); this->current_temperature = temp_code_to_decimal(status_heater->current_temp_water);

View File

@ -8,7 +8,7 @@ namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.heater_number"; static const char *const TAG = "truma_inetbox.heater_number";
void TrumaHeaterNumber::setup() { void TrumaHeaterNumber::setup() {
this->parent_->register_listener([this](const StatusFrameHeater *status_heater) { this->parent_->add_on_heater_message_callback([this](const StatusFrameHeater *status_heater) {
switch (this->type_) { switch (this->type_) {
case TRUMA_NUMBER_TYPE::TARGET_ROOM_TEMPERATURE: case TRUMA_NUMBER_TYPE::TARGET_ROOM_TEMPERATURE:
this->publish_state(temp_code_to_decimal(status_heater->target_temp_room, 0)); this->publish_state(temp_code_to_decimal(status_heater->target_temp_room, 0));

View File

@ -8,7 +8,7 @@ namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.sensor"; static const char *const TAG = "truma_inetbox.sensor";
void TrumaSensor::setup() { void TrumaSensor::setup() {
this->parent_->register_listener([this](const StatusFrameHeater *status_heater) { this->parent_->add_on_heater_message_callback([this](const StatusFrameHeater *status_heater) {
switch (this->type_) { switch (this->type_) {
case TRUMA_SENSOR_TYPE::CURRENT_ROOM_TEMPERATURE: case TRUMA_SENSOR_TYPE::CURRENT_ROOM_TEMPERATURE:
this->publish_state(temp_code_to_decimal(status_heater->current_temp_room)); this->publish_state(temp_code_to_decimal(status_heater->current_temp_room));

View File

@ -8,7 +8,7 @@ namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.time"; static const char *const TAG = "truma_inetbox.time";
void TrumaTime::setup() { void TrumaTime::setup() {
this->parent_->register_listener([this](const StatusFrameClock *status_clock) { this->parent_->add_on_clock_message_callback([this](const StatusFrameClock *status_clock) {
if (this->auto_disable_count_ > 0) { if (this->auto_disable_count_ > 0) {
if (this->read_time() && this->auto_disable_) { if (this->read_time() && this->auto_disable_) {
this->auto_disable_count_--; this->auto_disable_count_--;