diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 656ff50e5..d5540c261 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -29,39 +29,39 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const LOG_DEBUG(F("Adding new Boiler with device ID 0x%02X"), device_id); // the telegram handlers... - register_telegram_type(0x10, F("UBAErrorMessage1"), false, std::bind(&Boiler::process_UBAErrorMessage, this, _1)); - register_telegram_type(0x11, F("UBAErrorMessage2"), false, std::bind(&Boiler::process_UBAErrorMessage, this, _1)); - register_telegram_type(0x18, F("UBAMonitorFast"), false, std::bind(&Boiler::process_UBAMonitorFast, this, _1)); - register_telegram_type(0x19, F("UBAMonitorSlow"), true, std::bind(&Boiler::process_UBAMonitorSlow, this, _1)); - register_telegram_type(0x34, F("UBAMonitorWW"), false, std::bind(&Boiler::process_UBAMonitorWW, this, _1)); - register_telegram_type(0x1C, F("UBAMaintenanceStatus"), false, std::bind(&Boiler::process_UBAMaintenanceStatus, this, _1)); - register_telegram_type(0x2A, F("MC10Status"), false, std::bind(&Boiler::process_MC10Status, this, _1)); - register_telegram_type(0x33, F("UBAParameterWW"), true, std::bind(&Boiler::process_UBAParameterWW, this, _1)); - register_telegram_type(0x14, F("UBATotalUptime"), false, std::bind(&Boiler::process_UBATotalUptime, this, _1)); - register_telegram_type(0x35, F("UBAFlags"), false, std::bind(&Boiler::process_UBAFlags, this, _1)); - register_telegram_type(0x15, F("UBAMaintenanceData"), false, std::bind(&Boiler::process_UBAMaintenanceData, this, _1)); - register_telegram_type(0x16, F("UBAParameters"), true, std::bind(&Boiler::process_UBAParameters, this, _1)); - register_telegram_type(0x1A, F("UBASetPoints"), false, std::bind(&Boiler::process_UBASetPoints, this, _1)); - register_telegram_type(0xD1, F("UBAOutdoorTemp"), false, std::bind(&Boiler::process_UBAOutdoorTemp, this, _1)); - register_telegram_type(0xE3, F("UBAMonitorSlowPlus"), false, std::bind(&Boiler::process_UBAMonitorSlowPlus2, this, _1)); - register_telegram_type(0xE4, F("UBAMonitorFastPlus"), false, std::bind(&Boiler::process_UBAMonitorFastPlus, this, _1)); - register_telegram_type(0xE5, F("UBAMonitorSlowPlus"), false, std::bind(&Boiler::process_UBAMonitorSlowPlus, this, _1)); - register_telegram_type(0xE9, F("UBADHWStatus"), false, std::bind(&Boiler::process_UBADHWStatus, this, _1)); + register_telegram_type(0x10, F("UBAErrorMessage1"), false, [&](std::shared_ptr t) { process_UBAErrorMessage(t); }); + register_telegram_type(0x11, F("UBAErrorMessage2"), false, [&](std::shared_ptr t) { process_UBAErrorMessage(t); }); + register_telegram_type(0x18, F("UBAMonitorFast"), false, [&](std::shared_ptr t) { process_UBAMonitorFast(t); }); + register_telegram_type(0x19, F("UBAMonitorSlow"), true, [&](std::shared_ptr t) { process_UBAMonitorSlow(t); }); + register_telegram_type(0x34, F("UBAMonitorWW"), false, [&](std::shared_ptr t) { process_UBAMonitorWW(t); }); + register_telegram_type(0x1C, F("UBAMaintenanceStatus"), false, [&](std::shared_ptr t) { process_UBAMaintenanceStatus(t); }); + register_telegram_type(0x2A, F("MC10Status"), false, [&](std::shared_ptr t) { process_MC10Status(t); }); + register_telegram_type(0x33, F("UBAParameterWW"), true, [&](std::shared_ptr t) { process_UBAParameterWW(t); }); + register_telegram_type(0x14, F("UBATotalUptime"), false, [&](std::shared_ptr t) { process_UBATotalUptime(t); }); + register_telegram_type(0x35, F("UBAFlags"), false, [&](std::shared_ptr t) { process_UBAFlags(t); }); + register_telegram_type(0x15, F("UBAMaintenanceData"), false, [&](std::shared_ptr t) { process_UBAMaintenanceData(t); }); + register_telegram_type(0x16, F("UBAParameters"), true, [&](std::shared_ptr t) { process_UBAParameters(t); }); + register_telegram_type(0x1A, F("UBASetPoints"), false, [&](std::shared_ptr t) { process_UBASetPoints(t); }); + register_telegram_type(0xD1, F("UBAOutdoorTemp"), false, [&](std::shared_ptr t) { process_UBAOutdoorTemp(t); }); + register_telegram_type(0xE3, F("UBAMonitorSlowPlus"), false, [&](std::shared_ptr t) { process_UBAMonitorSlowPlus2(t); }); + register_telegram_type(0xE4, F("UBAMonitorFastPlus"), false, [&](std::shared_ptr t) { process_UBAMonitorFastPlus(t); }); + register_telegram_type(0xE5, F("UBAMonitorSlowPlus"), false, [&](std::shared_ptr t) { process_UBAMonitorSlowPlus(t); }); + register_telegram_type(0xE9, F("UBADHWStatus"), false, [&](std::shared_ptr t) { process_UBADHWStatus(t); }); // MQTT commands for boiler_cmd topic - register_mqtt_cmd(F("comfort"), std::bind(&Boiler::set_warmwater_mode, this, _1, _2)); - register_mqtt_cmd(F("wwactivated"), std::bind(&Boiler::set_warmwater_activated, this, _1, _2)); - register_mqtt_cmd(F("wwtapactivated"), std::bind(&Boiler::set_tapwarmwater_activated, this, _1, _2)); - register_mqtt_cmd(F("wwonetime"), std::bind(&Boiler::set_warmwater_onetime, this, _1, _2)); - register_mqtt_cmd(F("wwcirculation"), std::bind(&Boiler::set_warmwater_circulation, this, _1, _2)); - register_mqtt_cmd(F("flowtemp"), std::bind(&Boiler::set_flow_temp, this, _1, _2)); - register_mqtt_cmd(F("wwtemp"), std::bind(&Boiler::set_warmwater_temp, this, _1, _2)); - register_mqtt_cmd(F("burnmaxpower"), std::bind(&Boiler::set_max_power, this, _1, _2)); - register_mqtt_cmd(F("burnminpower"), std::bind(&Boiler::set_min_power, this, _1, _2)); - register_mqtt_cmd(F("boilhyston"), std::bind(&Boiler::set_hyst_on, this, _1, _2)); - register_mqtt_cmd(F("boilhystoff"), std::bind(&Boiler::set_hyst_off, this, _1, _2)); - register_mqtt_cmd(F("burnperiod"), std::bind(&Boiler::set_burn_period, this, _1, _2)); - register_mqtt_cmd(F("pumpdelay"), std::bind(&Boiler::set_pump_delay, this, _1, _2)); + register_mqtt_cmd(F("comfort"), [&](const char * value, const int8_t id) { set_warmwater_mode(value, id); }); + register_mqtt_cmd(F("wwactivated"), [&](const char * value, const int8_t id) { set_warmwater_activated(value, id); }); + register_mqtt_cmd(F("wwtapactivated"), [&](const char * value, const int8_t id) { set_tapwarmwater_activated(value, id); }); + register_mqtt_cmd(F("wwonetime"), [&](const char * value, const int8_t id) { set_warmwater_onetime(value, id); }); + register_mqtt_cmd(F("wwcirculation"), [&](const char * value, const int8_t id) { set_warmwater_circulation(value, id); }); + register_mqtt_cmd(F("flowtemp"), [&](const char * value, const int8_t id) { set_flow_temp(value, id); }); + register_mqtt_cmd(F("wwtemp"), [&](const char * value, const int8_t id) { set_warmwater_temp(value, id); }); + register_mqtt_cmd(F("burnmaxpower"), [&](const char * value, const int8_t id) { set_max_power(value, id); }); + register_mqtt_cmd(F("burnminpower"), [&](const char * value, const int8_t id) { set_min_power(value, id); }); + register_mqtt_cmd(F("boilhyston"), [&](const char * value, const int8_t id) { set_hyst_on(value, id); }); + register_mqtt_cmd(F("boilhystoff"), [&](const char * value, const int8_t id) { set_hyst_off(value, id); }); + register_mqtt_cmd(F("burnperiod"), [&](const char * value, const int8_t id) { set_burn_period(value, id); }); + register_mqtt_cmd(F("pumpdelay"), [&](const char * value, const int8_t id) { set_pump_delay(value, id); }); } // add submenu context @@ -99,8 +99,9 @@ void Boiler::device_info(JsonArray & root) { // publish values via MQTT void Boiler::publish_values() { - const size_t capacity = JSON_OBJECT_SIZE(56); // must recalculate if more objects addded https://arduinojson.org/v6/assistant/ - DynamicJsonDocument doc(capacity); + // const size_t capacity = JSON_OBJECT_SIZE(56); // must recalculate if more objects addded https://arduinojson.org/v6/assistant/ + // DynamicJsonDocument doc(capacity); + StaticJsonDocument doc; char s[10]; // for formatting strings @@ -862,7 +863,7 @@ void Boiler::console_commands(Shell & shell, unsigned int context) { flash_string_vector{F_(typeid_mandatory)}, [=](Shell & shell __attribute__((unused)), const std::vector & arguments) { uint16_t type_id = Helpers::hextoint(arguments.front().c_str()); - EMSESP::send_read_request(type_id, device_id()); + EMSESP::send_read_request(type_id, get_device_id()); }); EMSESPShell::commands->add_command(ShellContext::BOILER, diff --git a/src/devices/heatpump.cpp b/src/devices/heatpump.cpp index 6895dd733..112a27963 100644 --- a/src/devices/heatpump.cpp +++ b/src/devices/heatpump.cpp @@ -29,8 +29,8 @@ Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, c LOG_DEBUG(F("Adding new Heat Pump module with device ID 0x%02X"), device_id); // telegram handlers - register_telegram_type(0x047B, F("HP1"), true, std::bind(&Heatpump::process_HPMonitor1, this, _1)); - register_telegram_type(0x042B, F("HP2"), true, std::bind(&Heatpump::process_HPMonitor2, this, _1)); + register_telegram_type(0x047B, F("HP1"), true, [&](std::shared_ptr t) { process_HPMonitor1(t); }); + register_telegram_type(0x042B, F("HP2"), true, [&](std::shared_ptr t) { process_HPMonitor2(t); }); } // context submenu diff --git a/src/devices/mixing.cpp b/src/devices/mixing.cpp index 995045676..81e3f3d53 100644 --- a/src/devices/mixing.cpp +++ b/src/devices/mixing.cpp @@ -31,21 +31,27 @@ Mixing::Mixing(uint8_t device_type, uint8_t device_id, uint8_t product_id, const if (flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { if (device_id <= 0x27) { // telegram handlers 0x20 - 0x27 for HC - register_telegram_type(device_id - 0x20 + 0x02D7, F("MMPLUSStatusMessage_HC"), true, std::bind(&Mixing::process_MMPLUSStatusMessage_HC, this, _1)); + register_telegram_type(device_id - 0x20 + 0x02D7, F("MMPLUSStatusMessage_HC"), true, [&](std::shared_ptr t) { + process_MMPLUSStatusMessage_HC(t); + }); } else { // telegram handlers for warm water/DHW 0x28, 0x29 - register_telegram_type(device_id - 0x28 + 0x0331, F("MMPLUSStatusMessage_WWC"), true, std::bind(&Mixing::process_MMPLUSStatusMessage_WWC, this, _1)); + register_telegram_type(device_id - 0x28 + 0x0331, F("MMPLUSStatusMessage_WWC"), true, [&](std::shared_ptr t) { + process_MMPLUSStatusMessage_WWC(t); + }); } } + // EMS 1.0 if (flags == EMSdevice::EMS_DEVICE_FLAG_MM10) { - register_telegram_type(0x00AA, F("MMConfigMessage"), false, std::bind(&Mixing::process_MMConfigMessage, this, _1)); - register_telegram_type(0x00AB, F("MMStatusMessage"), true, std::bind(&Mixing::process_MMStatusMessage, this, _1)); - register_telegram_type(0x00AC, F("MMSetMessage"), false, std::bind(&Mixing::process_MMSetMessage, this, _1)); + register_telegram_type(0x00AA, F("MMConfigMessage"), false, [&](std::shared_ptr t) { process_MMConfigMessage(t); }); + register_telegram_type(0x00AB, F("MMStatusMessage"), true, [&](std::shared_ptr t) { process_MMStatusMessage(t); }); + register_telegram_type(0x00AC, F("MMSetMessage"), false, [&](std::shared_ptr t) { process_MMSetMessage(t); }); } + // HT3 if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) { - register_telegram_type(0x010C, F("IPMSetMessage"), false, std::bind(&Mixing::process_IPMStatusMessage, this, _1)); + register_telegram_type(0x010C, F("IPMSetMessage"), false, [&](std::shared_ptr t) { process_IPMStatusMessage(t); }); } } @@ -64,6 +70,7 @@ void Mixing::device_info(JsonArray & root) { } else { render_value_json(root, "", F("Heating Circuit"), hc_, nullptr); } + render_value_json(root, "", F("Current flow temperature"), flowTemp_, F_(degrees), 10); render_value_json(root, "", F("Setpoint flow temperature"), flowSetTemp_, F_(degrees)); render_value_json(root, "", F("Current pump modulation"), pumpMod_, F_(percent)); @@ -92,6 +99,7 @@ void Mixing::show_values(uuid::console::Shell & shell) { } else { print_value(shell, 2, F("Heating Circuit"), hc_, nullptr); } + print_value(shell, 4, F("Current flow temperature"), flowTemp_, F_(degrees), 10); print_value(shell, 4, F("Setpoint flow temperature"), flowSetTemp_, F_(degrees)); print_value(shell, 4, F("Current pump modulation"), pumpMod_, F_(percent)); @@ -136,7 +144,7 @@ void Mixing::publish_values() { char topic[30]; char s[3]; // for formatting strings strlcpy(topic, "mixing_data", 30); - strlcat(topic, Helpers::itoa(s, device_id() - 0x20 + 1), 30); // append hc to topic + strlcat(topic, Helpers::itoa(s, get_device_id() - 0x20 + 1), 30); // append hc to topic Mqtt::publish(topic, doc); } @@ -168,7 +176,7 @@ void Mixing::process_MMPLUSStatusMessage_WWC(std::shared_ptr tel // A1 00 FF 00 00 0C 02 04 00 01 1D 00 82 void Mixing::process_IPMStatusMessage(std::shared_ptr telegram) { type_ = Type::HC; - hc_ = device_id() - 0x20 + 1; + hc_ = get_device_id() - 0x20 + 1; uint8_t ismixed = 0; telegram->read_value(ismixed, 0); // check if circuit is active, 0-off, 1-unmixed, 2-mixed if (ismixed == 0) { @@ -195,7 +203,7 @@ void Mixing::process_MMStatusMessage(std::shared_ptr telegram) { // the heating circuit is determine by which device_id it is, 0x20 - 0x23 // 0x21 is position 2. 0x20 is typically reserved for the WM10 switch module // see https://github.com/proddy/EMS-ESP/issues/270 and https://github.com/proddy/EMS-ESP/issues/386#issuecomment-629610918 - hc_ = device_id() - 0x20 + 1; + hc_ = get_device_id() - 0x20 + 1; telegram->read_value(flowTemp_, 1); // is * 10 telegram->read_value(pumpMod_, 3); telegram->read_value(flowSetTemp_, 0); @@ -207,7 +215,7 @@ void Mixing::process_MMStatusMessage(std::shared_ptr telegram) { // Mixing on a MM10 - 0xAA // e.g. Thermostat -> Mixing Module, type 0xAA, telegram: 10 21 AA 00 FF 0C 0A 11 0A 32 xx void Mixing::process_MMConfigMessage(std::shared_ptr telegram) { - hc_ = device_id() - 0x20 + 1; + hc_ = get_device_id() - 0x20 + 1; // pos 0: active FF = on // pos 1: valve runtime 0C = 120 sec in units of 10 sec } @@ -215,7 +223,7 @@ void Mixing::process_MMConfigMessage(std::shared_ptr telegram) { // Mixing on a MM10 - 0xAC // e.g. Thermostat -> Mixing Module, type 0xAC, telegram: 10 21 AC 00 1E 64 01 AB void Mixing::process_MMSetMessage(std::shared_ptr telegram) { - hc_ = device_id() - 0x20 + 1; + hc_ = get_device_id() - 0x20 + 1; // pos 0: flowtemp setpoint 1E = 30°C // pos 1: position in % } diff --git a/src/devices/solar.cpp b/src/devices/solar.cpp index 7e9f01909..87b0f3a68 100644 --- a/src/devices/solar.cpp +++ b/src/devices/solar.cpp @@ -30,20 +30,22 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s // telegram handlers if (flags == EMSdevice::EMS_DEVICE_FLAG_SM10) { - register_telegram_type(0x0097, F("SM10Monitor"), true, std::bind(&Solar::process_SM10Monitor, this, _1)); + register_telegram_type(0x0097, F("SM10Monitor"), true, [&](std::shared_ptr t) { process_SM10Monitor(t); }); } - if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) { - register_telegram_type(0x0362, F("SM100Monitor"), true, std::bind(&Solar::process_SM100Monitor, this, _1)); - register_telegram_type(0x0363, F("SM100Monitor2"), true, std::bind(&Solar::process_SM100Monitor2, this, _1)); - register_telegram_type(0x0366, F("SM100Config"), true, std::bind(&Solar::process_SM100Config, this, _1)); - register_telegram_type(0x0364, F("SM100Status"), false, std::bind(&Solar::process_SM100Status, this, _1)); - register_telegram_type(0x036A, F("SM100Status2"), false, std::bind(&Solar::process_SM100Status2, this, _1)); - register_telegram_type(0x038E, F("SM100Energy"), true, std::bind(&Solar::process_SM100Energy, this, _1)); + if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) { + register_telegram_type(0x0362, F("SM100Monitor"), true, [&](std::shared_ptr t) { process_SM100Monitor(t); }); + register_telegram_type(0x0363, F("SM100Monitor2"), true, [&](std::shared_ptr t) { process_SM100Monitor2(t); }); + register_telegram_type(0x0366, F("SM100Config"), true, [&](std::shared_ptr t) { process_SM100Config(t); }); + + register_telegram_type(0x0364, F("SM100Status"), false, [&](std::shared_ptr t) { process_SM100Status(t); }); + register_telegram_type(0x036A, F("SM100Status2"), false, [&](std::shared_ptr t) { process_SM100Status2(t); }); + register_telegram_type(0x038E, F("SM100Energy"), true, [&](std::shared_ptr t) { process_SM100Energy(t); }); } + if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) { - register_telegram_type(0x0103, F("ISM1StatusMessage"), true, std::bind(&Solar::process_ISM1StatusMessage, this, _1)); - register_telegram_type(0x0101, F("ISM1Set"), false, std::bind(&Solar::process_ISM1Set, this, _1)); + register_telegram_type(0x0103, F("ISM1StatusMessage"), true, [&](std::shared_ptr t) { process_ISM1StatusMessage(t); }); + register_telegram_type(0x0101, F("ISM1Set"), false, [&](std::shared_ptr t) { process_ISM1Set(t); }); } } @@ -106,7 +108,7 @@ void Solar::show_values(uuid::console::Shell & shell) { // publish values via MQTT void Solar::publish_values() { - DynamicJsonDocument doc(EMSESP_MAX_JSON_SIZE_MEDIUM); + StaticJsonDocument doc; char s[10]; // for formatting strings diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 163545897..8547530c9 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -24,6 +24,8 @@ namespace emsesp { uuid::log::Logger EMSdevice::logger_{F_(emsesp), uuid::log::Facility::CONSOLE}; +std::vector EMSdevice::telegram_functions_; + std::string EMSdevice::brand_to_string() const { switch (brand_) { case EMSdevice::Brand::BOSCH: @@ -198,7 +200,7 @@ void EMSdevice::show_values(uuid::console::Shell & shell) { // for each telegram that has the fetch value set (true) do a read request void EMSdevice::fetch_values() { - LOG_DEBUG(F("Fetching values for device ID 0x%02X"), device_id()); + LOG_DEBUG(F("Fetching values for device ID 0x%02X"), get_device_id()); for (const auto & tf : telegram_functions_) { if (tf.fetch_) { @@ -209,7 +211,7 @@ void EMSdevice::fetch_values() { // toggle on/off automatic fetch for a telegram id void EMSdevice::toggle_fetch(uint16_t telegram_id, bool toggle) { - LOG_DEBUG(F("Toggling fetch for device ID 0x%02X, telegram ID 0x%02X to %d"), device_id(), telegram_id, toggle); + LOG_DEBUG(F("Toggling fetch for device ID 0x%02X, telegram ID 0x%02X to %d"), get_device_id(), telegram_id, toggle); for (auto & tf : telegram_functions_) { if (tf.telegram_type_id_ == telegram_id) { @@ -243,22 +245,12 @@ void EMSdevice::register_mqtt_topic(const std::string & topic, mqtt_subfunction_ void EMSdevice::register_mqtt_cmd(const __FlashStringHelper * cmd, mqtt_cmdfunction_p f) { LOG_DEBUG(F("Registering MQTT cmd %s for device type %s"), uuid::read_flash_string(cmd).c_str(), this->device_type_name().c_str()); - Mqtt::add_command(this->device_type_, cmd, f); -} - -EMSdevice::TelegramFunction::TelegramFunction(uint16_t telegram_type_id, - const __FlashStringHelper * telegram_type_name, - bool fetch, - process_function_p process_function) - : telegram_type_id_(telegram_type_id) - , telegram_type_name_(telegram_type_name) - , fetch_(fetch) - , process_function_(process_function) { + Mqtt::add_command(this->device_type_, this->device_id_, cmd, f); } // register a call back function for a specific telegram type void EMSdevice::register_telegram_type(const uint16_t telegram_type_id, const __FlashStringHelper * telegram_type_name, bool fetch, process_function_p f) { - telegram_functions_.emplace_back(telegram_type_id, std::move(telegram_type_name), fetch, std::move(f)); + telegram_functions_.emplace_back(telegram_type_id, telegram_type_name, fetch, f); } // return the name of the telegram type @@ -302,24 +294,22 @@ bool EMSdevice::handle_telegram(std::shared_ptr telegram) { // send Tx write with a data block void EMSdevice::write_command(const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid) { - EMSESP::send_write_request(type_id, device_id(), offset, message_data, message_length, validate_typeid); + EMSESP::send_write_request(type_id, this->get_device_id(), offset, message_data, message_length, validate_typeid); } // send Tx write with a single value void EMSdevice::write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid) { - uint8_t message_data[1]; - message_data[0] = value; - EMSESP::send_write_request(type_id, device_id(), offset, message_data, 1, validate_typeid); + EMSESP::send_write_request(type_id, this->get_device_id(), offset, value, validate_typeid); } // send Tx write with a single value, with no post validation void EMSdevice::write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value) { - write_command(type_id, offset, value, 0); + EMSESP::send_write_request(type_id, this->get_device_id(), offset, value, 0); } // send Tx read command to the device void EMSdevice::read_command(const uint16_t type_id) { - EMSESP::send_read_request(type_id, device_id()); + EMSESP::send_read_request(type_id, get_device_id()); } // prints a string value to the console diff --git a/src/emsdevice.h b/src/emsdevice.h index 905b7bab8..4113b7c1d 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -30,10 +30,10 @@ namespace emsesp { -using namespace std::placeholders; // for `_1` - class EMSdevice { public: + static constexpr uint8_t EMS_DEVICES_MAX_TELEGRAMS = 20; + // device_type defines which derived class to use, e.g. BOILER, THERMOSTAT etc.. EMSdevice(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand) : device_type_(device_type) @@ -47,17 +47,7 @@ class EMSdevice { virtual ~EMSdevice() = default; // destructor of base class must always be virtual because it's a polymorphic class - /* - // https://github.com/proddy/EMS-ESP/issues/434#issuecomment-667840531 - inline uint8_t device_id(uint8_t hc = 0) const { - if (((device_id_ & 0x7F) >= 0x18) && ((device_id_ & 0x7F) <= 0x1B)) { - return ((device_id_ & 0x80) + 0x18 + hc); - } - return device_id_; - } - */ - - inline uint8_t device_id() const { + inline uint8_t get_device_id() const { return device_id_; } @@ -157,6 +147,10 @@ class EMSdevice { void fetch_values(); void toggle_fetch(uint16_t telegram_id, bool toggle); + static void reserve_mem(size_t n) { + telegram_functions_.reserve(n); + } + // prints a ems device value to the console, handling the correct rendering of the type // padding is # white space // name is the name of the parameter @@ -296,17 +290,21 @@ class EMSdevice { static uuid::log::Logger logger_; - class TelegramFunction { - public: - TelegramFunction(uint16_t telegram_type_id, const __FlashStringHelper * telegram_type_name, bool fetch, process_function_p process_function); - ~TelegramFunction() = default; - + struct TelegramFunction { uint16_t telegram_type_id_; // it's type_id const __FlashStringHelper * telegram_type_name_; // e.g. RC20Message bool fetch_; // if this type_id be queried automatically - process_function_p process_function_; + + process_function_p process_function_; + + TelegramFunction(uint16_t telegram_type_id, const __FlashStringHelper * telegram_type_name, bool fetch, process_function_p process_function) + : telegram_type_id_(telegram_type_id) + , telegram_type_name_(telegram_type_name) + , fetch_(fetch) + , process_function_(process_function) { + } }; - std::vector telegram_functions_; // each EMS device has its own set of registered telegram types + static std::vector telegram_functions_; // each EMS device has its own set of registered telegram types }; } // namespace emsesp diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 68fc242d9..4d8396970 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -20,9 +20,6 @@ namespace emsesp { -using DeviceFlags = emsesp::EMSdevice; -using DeviceType = emsesp::EMSdevice::DeviceType; - AsyncWebServer webServer(80); #if defined(ESP32) @@ -40,6 +37,8 @@ EMSESPSettingsService EMSESP::emsespSettingsService = EMSESPSettingsService(&web EMSESPStatusService EMSESP::emsespStatusService = EMSESPStatusService(&webServer, EMSESP::esp8266React.getSecurityManager()); EMSESPDevicesService EMSESP::emsespDevicesService = EMSESPDevicesService(&webServer, EMSESP::esp8266React.getSecurityManager()); +using DeviceFlags = emsesp::EMSdevice; +using DeviceType = emsesp::EMSdevice::DeviceType; std::vector> EMSESP::emsdevices; // array of all the detected EMS devices std::vector EMSESP::device_library_; // libary of all our known EMS devices so far @@ -77,6 +76,11 @@ void EMSESP::fetch_device_values(const uint8_t device_id) { } } +// clears list of recognized devices +void EMSESP::clear_all_devices() { + emsdevices.clear(); // or use empty to release memory too +} + // return number of devices of a known type uint8_t EMSESP::count_devices(const uint8_t device_type) { uint8_t count = 0; @@ -88,6 +92,33 @@ uint8_t EMSESP::count_devices(const uint8_t device_type) { return count; } +// scans for new devices +void EMSESP::scan_devices() { + EMSESP::clear_all_devices(); + EMSESP::send_read_request(EMSdevice::EMS_TYPE_UBADevices, EMSdevice::EMS_DEVICE_ID_BOILER); +} + +/** +* if thermostat master is 0x18 it handles only ww and hc1, hc2..hc4 handled by devices 0x19..0x1B +* we send to right device and match all reads to 0x18 +*/ +uint8_t EMSESP::check_master_device(const uint8_t device_id, const uint16_t type_id, const bool read) { + uint16_t mon_id[4] = {0x02A5, 0x02A6, 0x02A7, 0x02A8}; + uint16_t set_id[4] = {0x02B9, 0x02BA, 0x02BB, 0x02BC}; + if (actual_master_thermostat_ == 0x18) { + for (uint8_t i = 0; i < 4; i++) { + if (type_id == mon_id[i] || type_id == set_id[i]) { + if (read) { + return 0x18; + } else { + return 0x18 + i; + } + } + } + } + return device_id; +} + void EMSESP::actual_master_thermostat(const uint8_t device_id) { actual_master_thermostat_ = device_id; } @@ -215,11 +246,7 @@ void EMSESP::show_ems(uuid::console::Shell & shell) { } else if ((it.telegram_->operation) == Telegram::Operation::TX_WRITE) { op = read_flash_string(F("WRITE")); } - shell.printfln(F(" [%02d%c] %s %s"), - it.id_, - ((it.retry_) ? '*' : ' '), - op.c_str(), - pretty_telegram(it.telegram_).c_str()); + shell.printfln(F(" [%02d%c] %s %s"), it.id_, ((it.retry_) ? '*' : ' '), op.c_str(), pretty_telegram(it.telegram_).c_str()); } } @@ -541,7 +568,7 @@ void EMSESP::show_devices(uuid::console::Shell & shell) { for (const auto & emsdevice : emsdevices) { if ((emsdevice) && (emsdevice->device_type() == device_class.first)) { shell.printf(F("%s: %s"), emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str()); - if ((emsdevice->device_type() == EMSdevice::DeviceType::THERMOSTAT) && (emsdevice->device_id() == actual_master_thermostat())) { + if ((emsdevice->device_type() == EMSdevice::DeviceType::THERMOSTAT) && (emsdevice->get_device_id() == actual_master_thermostat())) { shell.printf(F(" ** master device **")); } shell.println(); @@ -561,6 +588,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, std:: return false; } + // first check to see if we already have it, if so update the record for (const auto & emsdevice : emsdevices) { if (emsdevice) { @@ -585,6 +613,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, std:: } } + // look up the rest of the details using the product_id and create the new device object Device_record * device_p = nullptr; for (auto & device : device_library_) { @@ -636,6 +665,17 @@ void EMSESP::send_write_request(const uint16_t type_id, txservice_.set_post_send_query(validate_typeid); // store which type_id to send Tx read after a write } +void EMSESP::send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t value) { + send_write_request(type_id, dest, offset, value, 0); +} + +// send Tx write with a single value +void EMSESP::send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid) { + uint8_t message_data[1]; + message_data[0] = value; + EMSESP::send_write_request(type_id, dest, offset, message_data, 1, validate_typeid); +} + // this is main entry point when data is received on the Rx line, via emsuart library // we check if its a complete telegram or just a single byte (which could be a poll or a return status) // the CRC check is not done here, only when it's added to the Rx queue with add() @@ -735,9 +775,11 @@ void EMSESP::send_raw_telegram(const char * data) { txservice_.send_raw(data); } -// kick off the party, start all the services +// start all the core services +// the services must be loaded in the correct order void EMSESP::start() { - // Load our library of known devices + // Load our library of known devices. Names are stored in Flash mem. + device_library_.reserve(100); device_library_ = { #include "device_library.h" }; @@ -758,6 +800,12 @@ void EMSESP::start() { txservice_.start(); // sets bus ID, sends out request for EMS devices sensors_.start(); // dallas external sensors webServer.begin(); // start web server + + // reserve some space for the telegram registries, to avoid memory fragmentation + EMSdevice::reserve_mem(EMSdevice::EMS_DEVICES_MAX_TELEGRAMS); // space for 20 telegram handlers + emsdevices.reserve(5); // reserve space for initially 5 devices + + LOG_INFO("EMS Device library loaded with %d records", device_library_.size()); } // main loop calling all services diff --git a/src/emsesp.h b/src/emsesp.h index e22633f88..96c04f335 100644 --- a/src/emsesp.h +++ b/src/emsesp.h @@ -78,6 +78,9 @@ class EMSESP { uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid); + static void send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t value); + static void send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid); + static void send_raw_telegram(const char * data); static bool device_exists(const uint8_t device_id); @@ -87,6 +90,7 @@ class EMSESP { static uint8_t actual_master_thermostat(); static void actual_master_thermostat(const uint8_t device_id); + static uint8_t check_master_device(const uint8_t device_id, const uint16_t type_id, const bool read); static void show_device_values(uuid::console::Shell & shell); static void show_sensor_values(uuid::console::Shell & shell); @@ -134,6 +138,8 @@ class EMSESP { static void fetch_device_values(const uint8_t device_id = 0); static bool add_device(const uint8_t device_id, const uint8_t product_id, std::string & version, const uint8_t brand); + static void scan_devices(); + static void clear_all_devices(); static std::vector> emsdevices; diff --git a/src/mqtt.cpp b/src/mqtt.cpp index bdbf1e436..3d49e156b 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -28,6 +28,7 @@ AsyncMqttClient * Mqtt::mqttClient_; std::string Mqtt::hostname_; uint8_t Mqtt::mqtt_qos_; uint16_t Mqtt::publish_time_; +uint8_t Mqtt::bus_id_; std::vector Mqtt::mqtt_subfunctions_; std::vector Mqtt::mqtt_cmdfunctions_; @@ -35,38 +36,11 @@ std::vector Mqtt::mqtt_cmdfunctions_; uint16_t Mqtt::mqtt_publish_fails_ = 0; size_t Mqtt::maximum_mqtt_messages_ = Mqtt::MAX_MQTT_MESSAGES; uint16_t Mqtt::mqtt_message_id_ = 0; -std::deque Mqtt::mqtt_messages_; +std::list Mqtt::mqtt_messages_; char will_topic_[Mqtt::MQTT_TOPIC_MAX_SIZE]; // because MQTT library keeps only char pointer uuid::log::Logger Mqtt::logger_{F_(mqtt), uuid::log::Facility::DAEMON}; -Mqtt::QueuedMqttMessage::QueuedMqttMessage(uint16_t id, std::shared_ptr && content) - : id_(id) - , content_(std::move(content)) { - retry_count_ = 0; - packet_id_ = 0; -} - -MqttMessage::MqttMessage(const uint8_t operation, const std::string & topic, const std::string && payload, bool retain) - : operation(operation) - , topic(topic) - , payload(std::move(payload)) - , retain(retain) { -} - -Mqtt::MQTTSubFunction::MQTTSubFunction(const uint8_t device_type, const std::string && topic, const std::string && full_topic, mqtt_subfunction_p mqtt_subfunction) - : device_type_(device_type) - , topic_(topic) - , full_topic_(full_topic) - , mqtt_subfunction_(mqtt_subfunction) { -} - -Mqtt::MQTTCmdFunction::MQTTCmdFunction(const uint8_t device_type, const __FlashStringHelper * cmd, mqtt_cmdfunction_p mqtt_cmdfunction) - : device_type_(device_type) - , cmd_(cmd) - , mqtt_cmdfunction_(mqtt_cmdfunction) { -} - // subscribe to an MQTT topic, and store the associated callback function // only if it already hasn't been added void Mqtt::subscribe(const uint8_t device_type, const std::string & topic, mqtt_subfunction_p cb) { @@ -88,10 +62,11 @@ void Mqtt::subscribe(const uint8_t device_type, const std::string & topic, mqtt_ } // adds a command and callback function for a specific device -void Mqtt::add_command(const uint8_t device_type, const __FlashStringHelper * cmd, mqtt_cmdfunction_p cb) { +void Mqtt::add_command(const uint8_t device_type, const uint8_t device_id, const __FlashStringHelper * cmd, mqtt_cmdfunction_p cb) { // subscribe to the command topic if it doesn't exist yet // create the cmd topic for a device like "_cmd" e.g. "boiler_cmd" // unless its a system MQTT command, then its system_cmd + std::string cmd_topic(40, '\0'); if (device_type == EMSdevice::DeviceType::SERVICEKEY) { cmd_topic = MQTT_SYSTEM_CMD; // hard-coded system @@ -111,8 +86,7 @@ void Mqtt::add_command(const uint8_t device_type, const __FlashStringHelper * cm Mqtt::subscribe(device_type, cmd_topic, nullptr); // use an empty function handler to signal this is a command function } - // add the function to our list - mqtt_cmdfunctions_.emplace_back(device_type, std::move(cmd), std::move(cb)); + mqtt_cmdfunctions_.emplace_back(device_type, device_id, cmd, cb); } // subscribe to an MQTT topic, and store the associated callback function. For generic functions not tied to a specific device @@ -366,6 +340,8 @@ void Mqtt::start() { mqtt_qos_ = mqttSettings.mqtt_qos; }); + EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) { bus_id_ = settings.ems_bus_id; }); + mqttClient_->onConnect([this](bool sessionPresent) { on_connect(); }); mqttClient_->onDisconnect([this](AsyncMqttClientDisconnectReason reason) { @@ -402,6 +378,10 @@ void Mqtt::start() { // publish on_publish(packetId); }); + + // create space for command buffer, to avoid heap memory fragmentation + mqtt_cmdfunctions_.reserve(40); // current count with boiler+thermostat is 37 + mqtt_subfunctions_.reserve(10); } void Mqtt::set_publish_time(uint16_t publish_time) { @@ -432,8 +412,8 @@ void Mqtt::on_connect() { // add the system MQTT subscriptions, only if its a fresh start with no previous subscriptions // these commands respond to the topic "system_cmd" and take a payload like {cmd:"", data:"", id:""} if (mqtt_subfunctions_.empty()) { - add_command(EMSdevice::DeviceType::SERVICEKEY, F("pin"), System::mqtt_command_pin); - add_command(EMSdevice::DeviceType::SERVICEKEY, F("send"), System::mqtt_command_send); + add_command(EMSdevice::DeviceType::SERVICEKEY, bus_id_, F("pin"), System::mqtt_command_pin); + add_command(EMSdevice::DeviceType::SERVICEKEY, bus_id_, F("send"), System::mqtt_command_send); } LOG_INFO(F("MQTT connected")); diff --git a/src/mqtt.h b/src/mqtt.h index e48c93a02..6c700137c 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -46,16 +46,20 @@ namespace emsesp { using mqtt_subfunction_p = std::function; using mqtt_cmdfunction_p = std::function; -using namespace std::placeholders; // for `_1` - struct MqttMessage { - MqttMessage(const uint8_t operation, const std::string & topic, const std::string && payload, bool retain); ~MqttMessage() = default; const uint8_t operation; const std::string topic; const std::string payload; const bool retain; + + MqttMessage(const uint8_t operation, const std::string & topic, const std::string && payload, bool retain) + : operation(operation) + , topic(topic) + , payload(std::move(payload)) + , retain(retain) { + } }; class Mqtt { @@ -74,7 +78,7 @@ class Mqtt { static void subscribe(const std::string & topic, mqtt_subfunction_p cb); static void resubscribe(); - static void add_command(const uint8_t device_type, const __FlashStringHelper * cmd, mqtt_cmdfunction_p cb); + static void add_command(const uint8_t device_type, const uint8_t device_id, const __FlashStringHelper * cmd, mqtt_cmdfunction_p cb); static void publish(const std::string & topic, const std::string & payload, bool retain = false); static void publish(const std::string & topic, const JsonDocument & payload, bool retain = false); @@ -106,16 +110,18 @@ class Mqtt { mqtt_publish_fails_ = 0; } - static std::string hostname_; - - class MQTTCmdFunction { - public: - MQTTCmdFunction(const uint8_t device_type, const __FlashStringHelper * cmd, mqtt_cmdfunction_p mqtt_cmdfunction); - ~MQTTCmdFunction() = default; - - const uint8_t device_type_; + struct MQTTCmdFunction { + uint8_t device_type_; + uint8_t device_id_; const __FlashStringHelper * cmd_; mqtt_cmdfunction_p mqtt_cmdfunction_; + + MQTTCmdFunction(uint8_t device_type, uint8_t device_id, const __FlashStringHelper * cmd, mqtt_cmdfunction_p mqtt_cmdfunction) + : device_type_(device_type) + , device_id_(device_id) + , cmd_(cmd) + , mqtt_cmdfunction_(mqtt_cmdfunction) { + } }; static std::vector commands() { @@ -127,15 +133,20 @@ class Mqtt { class QueuedMqttMessage { public: - QueuedMqttMessage(uint16_t id, std::shared_ptr && content); - ~QueuedMqttMessage() = default; - const uint16_t id_; const std::shared_ptr content_; uint8_t retry_count_; uint16_t packet_id_; + + ~QueuedMqttMessage() = default; + QueuedMqttMessage(uint16_t id, std::shared_ptr && content) + : id_(id) + , content_(std::move(content)) { + retry_count_ = 0; + packet_id_ = 0; + } }; - static std::deque mqtt_messages_; + static std::list mqtt_messages_; static AsyncMqttClient * mqttClient_; @@ -143,7 +154,7 @@ class Mqtt { static uint16_t mqtt_message_id_; static bool mqtt_retain_; - static constexpr size_t MAX_MQTT_MESSAGES = 30; // size of queue + static constexpr size_t MAX_MQTT_MESSAGES = 20; // size of queue static constexpr uint32_t MQTT_PUBLISH_WAIT = 200; // delay between sending publishes, to account for large payloads static constexpr uint8_t MQTT_PUBLISH_MAX_RETRY = 3; // max retries for giving up on publishing @@ -159,15 +170,18 @@ class Mqtt { static uint16_t mqtt_publish_fails_; // function handlers for MQTT subscriptions - class MQTTSubFunction { - public: - MQTTSubFunction(const uint8_t device_type, const std::string && topic, const std::string && full_topic, mqtt_subfunction_p mqtt_subfunction); - ~MQTTSubFunction() = default; - - const uint8_t device_type_; // which device type, from DeviceType:: + struct MQTTSubFunction { + uint8_t device_type_; // which device type, from DeviceType:: const std::string topic_; const std::string full_topic_; // the fully qualified topic name, usually with the hostname prefixed mqtt_subfunction_p mqtt_subfunction_; // can be empty + + MQTTSubFunction(uint8_t device_type, const std::string && topic, const std::string && full_topic, mqtt_subfunction_p mqtt_subfunction) + : device_type_(device_type) + , topic_(topic) + , full_topic_(full_topic) + , mqtt_subfunction_(mqtt_subfunction) { + } }; static std::vector mqtt_subfunctions_; // list of mqtt subscribe callbacks for all devices @@ -177,8 +191,10 @@ class Mqtt { uint32_t last_publish_ = 0; // settings, copied over - static uint8_t mqtt_qos_; - static uint16_t publish_time_; + static std::string hostname_; + static uint8_t mqtt_qos_; + static uint16_t publish_time_; + static uint8_t bus_id_; }; } // namespace emsesp diff --git a/src/telegram.cpp b/src/telegram.cpp index d65e3543a..4b8830661 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -127,11 +127,6 @@ std::string Telegram::to_string_message() const { return Helpers::data_to_hex(this->message_data, this->message_length); } -RxService::QueuedRxTelegram::QueuedRxTelegram(uint16_t id, std::shared_ptr && telegram) - : id_(id) - , telegram_(std::move(telegram)) { -} - // empty queue, don't process them void RxService::flush_rx_queue() { rx_telegrams_.clear(); @@ -143,12 +138,9 @@ void RxService::flush_rx_queue() { void RxService::loop() { while (!rx_telegrams_.empty()) { auto telegram = rx_telegrams_.front().telegram_; - (void)EMSESP::process_telegram(telegram); // further process the telegram - - increment_telegram_count(); // increase count - - rx_telegrams_.pop_front(); // remove it from the queue + increment_telegram_count(); // increase count + rx_telegrams_.pop_front(); // remove it from the queue } } @@ -221,11 +213,15 @@ void RxService::add(uint8_t * data, uint8_t length) { LOG_DEBUG(F("[DEBUG] New Rx [#%d] telegram, message length %d"), rx_telegram_id_, message_length); #endif - // if we don't have a type_id or empty data block, exit - if ((type_id == 0) || (message_length == 0)) { + // if we don't have a type_id exit, + // do not exit on empty message, it is checked for toggle fetch + if (type_id == 0) { return; } + // if we receive a hc2.. telegram from 0x19.. match it to master_thermostat if master is 0x18 + src = EMSESP::check_master_device(src, type_id, true); + // create the telegram auto telegram = std::make_shared(Telegram::Operation::RX, src, dest, type_id, offset, message_data, message_length); @@ -241,12 +237,6 @@ void RxService::add(uint8_t * data, uint8_t length) { // Tx CODE starts here... // -TxService::QueuedTxTelegram::QueuedTxTelegram(uint16_t id, std::shared_ptr && telegram, bool retry) - : id_(id) - , telegram_(std::move(telegram)) - , retry_(retry) { -} - // empty queue, don't process void TxService::flush_tx_queue() { tx_telegrams_.clear(); @@ -295,16 +285,12 @@ void TxService::send() { } // if we're in read-only mode (tx_mode 0) forget the Tx call - if (tx_mode() == 0) { - tx_telegrams_.pop_front(); - return; + if (tx_mode() != 0) { + send_telegram(tx_telegrams_.front()); } - // send next telegram in the queue (which is actually a list!) - send_telegram(tx_telegrams_.front()); - // remove the telegram from the queue - tx_telegrams_.pop_front(); + tx_telegrams_.pop_front(); // remove the telegram from the queue } // process a Tx telegram @@ -324,6 +310,10 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) { // dest - for READ the MSB must be set // fix the READ or WRITE depending on the operation uint8_t dest = telegram->dest; + + // check if we have to manipulate the id for thermostats > 0x18 + dest = EMSESP::check_master_device(dest, telegram->type_id, false); + if (telegram->operation == Telegram::Operation::TX_READ) { dest |= 0x80; // read has 8th bit set for the destination } @@ -570,7 +560,7 @@ void TxService::retry_tx(const uint8_t operation, const uint8_t * data, const ui return; } -#ifdef EMSESP_DENUG +#ifdef EMSESP_DEBUG LOG_DEBUG(F("[DEBUG] Last Tx %s operation failed. Retry #%d. sent message: %s, received: %s"), (operation == Telegram::Operation::TX_WRITE) ? F("Write") : F("Read"), retry_count_, diff --git a/src/telegram.h b/src/telegram.h index 8862c6b51..0432d82a8 100644 --- a/src/telegram.h +++ b/src/telegram.h @@ -20,9 +20,7 @@ #define EMSESP_TELEGRAM_H #include -#include -#include // for unique ptrs -#include +#include // UART drivers #if defined(ESP8266) @@ -197,7 +195,7 @@ class EMSbus { class RxService : public EMSbus { public: - static constexpr size_t MAX_RX_TELEGRAMS = 20; + static constexpr size_t MAX_RX_TELEGRAMS = 10; RxService() = default; ~RxService() = default; @@ -226,31 +224,32 @@ class RxService : public EMSbus { class QueuedRxTelegram { public: - QueuedRxTelegram(uint16_t id, std::shared_ptr && telegram); - ~QueuedRxTelegram() = default; - - uint16_t id_; // sequential identifier + const uint16_t id_; const std::shared_ptr telegram_; + + ~QueuedRxTelegram() = default; + QueuedRxTelegram(uint16_t id, std::shared_ptr && telegram) + : id_(id) + , telegram_(std::move(telegram)) { + } }; - const std::deque queue() const { + const std::list queue() const { return rx_telegrams_; } private: - uint32_t last_rx_check_ = 0; - - uint8_t rx_telegram_id_ = 0; // queue counter - + uint32_t last_rx_check_ = 0; + uint8_t rx_telegram_id_ = 0; // queue counter uint16_t telegram_count_ = 0; // # Rx received uint16_t telegram_error_count_ = 0; // # Rx CRC errors - std::deque rx_telegrams_; + std::list rx_telegrams_; }; class TxService : public EMSbus { public: - static constexpr size_t MAX_TX_TELEGRAMS = 30; // size of Tx queue + static constexpr size_t MAX_TX_TELEGRAMS = 20; // size of Tx queue static constexpr uint8_t TX_WRITE_FAIL = 4; static constexpr uint8_t TX_WRITE_SUCCESS = 1; @@ -336,26 +335,29 @@ class TxService : public EMSbus { class QueuedTxTelegram { public: - QueuedTxTelegram(uint16_t id, std::shared_ptr && telegram, bool retry); - ~QueuedTxTelegram() = default; - - uint16_t id_; // sequential identifier + const uint16_t id_; const std::shared_ptr telegram_; - bool retry_; // is a retry + const bool retry_; // is a retry + + ~QueuedTxTelegram() = default; + QueuedTxTelegram(uint16_t id, std::shared_ptr && telegram, bool retry) + : id_(id) + , telegram_(std::move(telegram)) + , retry_(retry) { + } }; - const std::deque queue() const { + const std::list queue() const { return tx_telegrams_; } static constexpr uint8_t MAXIMUM_TX_RETRIES = 3; private: - uint8_t tx_telegram_id_ = 0; // queue counter + uint8_t tx_telegram_id_ = 0; // queue counter + uint32_t last_tx_check_ = 0; - uint32_t last_tx_check_ = 0; - - std::deque tx_telegrams_; + std::list tx_telegrams_; uint16_t telegram_read_count_ = 0; // # Tx successful reads uint16_t telegram_write_count_ = 0; // # Tx successful writes diff --git a/src/version.h b/src/version.h index a6a05e171..f8948ed72 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "2.0.0b12-1" +#define EMSESP_APP_VERSION "2.0.0b12-2"