diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 6c968efad..176d45e78 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -15,7 +15,7 @@ For more details go to [emsesp.org](https://emsesp.org/). - signed value for solarInfuence [#3077](https://github.com/emsesp/EMS-ESP32/issues/3077) - TLS support with 4MB boards without PSRAM - Prevent system crash during WiFi network discovery on ESP32-S3 hardware [#3128](https://github.com/emsesp/EMS-ESP32/pull/3128) - +- check arithmetric operations on strings [#3127](https://github.com/emsesp/EMS-ESP32/discussions/3127) ## Changed @@ -23,3 +23,4 @@ For more details go to [emsesp.org](https://emsesp.org/). - Scheduler name is now mandatory - network fallback to AP only after start [#3090](https://github.com/emsesp/EMS-ESP32/issues/3090) - replaced Web async-validator with custom validator and toast with native snackbar to reduce bundle size +- Dewtemperature for Easycontrol calculated by ems-esp [3135](https://github.com/emsesp/EMS-ESP32/issues/3135) diff --git a/src/ESP32React/WiFiScanner.cpp b/src/ESP32React/WiFiScanner.cpp index f64a7a5e2..aab103dc8 100644 --- a/src/ESP32React/WiFiScanner.cpp +++ b/src/ESP32React/WiFiScanner.cpp @@ -1,7 +1,5 @@ #include "WiFiScanner.h" -#include "../core/psram_async_json_response.h" - WiFiScanner::WiFiScanner(AsyncWebServer * server, SecurityManager * securityManager) { securityManager->addEndpoint(server, SCAN_NETWORKS_SERVICE_PATH, AuthenticationPredicates::IS_ADMIN, [this](AsyncWebServerRequest * request) { scanNetworks(request); @@ -17,13 +15,14 @@ void WiFiScanner::scanNetworks(AsyncWebServerRequest * request) { if (WiFi.scanComplete() != -1) { WiFi.scanDelete(); - WiFi.scanNetworks(true, false, true, 250); } + WiFi.scanNetworks(true, false, true, 250); + } } void WiFiScanner::listNetworks(AsyncWebServerRequest * request) { const int numNetworks = WiFi.scanComplete(); if (numNetworks > -1) { - auto * response = new emsesp::PsramAsyncJsonResponse(false); + auto * response = new AsyncJsonResponse(false); JsonObject root = response->getRoot(); JsonArray networks = root["networks"].to(); for (uint8_t i = 0; i < numNetworks; i++) { @@ -39,9 +38,10 @@ void WiFiScanner::listNetworks(AsyncWebServerRequest * request) { } else if (numNetworks == -1) { request->send(202); // special code to indicate scan in progress } else { - auto * response = new AsyncJsonResponse(false); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false); + JsonObject root = response->getRoot(); root["networks"].to(); response->setLength(); - request->send(response); } -} + request->send(response); + } +} \ No newline at end of file diff --git a/src/core/roomcontrol.cpp b/src/core/roomcontrol.cpp index 2eb59fbbd..cd0b8d93b 100644 --- a/src/core/roomcontrol.cpp +++ b/src/core/roomcontrol.cpp @@ -16,441 +16,441 @@ * along with this program. If not, see . */ - #include "roomcontrol.h" +#include "roomcontrol.h" - namespace emsesp { - - // init statics - bool Roomctrl::switch_off_[HCS] = {false, false, false, false}; - uint32_t Roomctrl::send_time_[HCS] = {0, 0, 0, 0}; - uint32_t Roomctrl::receive_time_[HCS] = {0, 0, 0, 0}; - int16_t Roomctrl::remotetemp_[HCS] = {EMS_VALUE_INT16_NOTSET, EMS_VALUE_INT16_NOTSET, EMS_VALUE_INT16_NOTSET, EMS_VALUE_INT16_NOTSET}; - uint8_t Roomctrl::remotehum_[HCS] = {EMS_VALUE_UINT8_NOTSET, EMS_VALUE_UINT8_NOTSET, EMS_VALUE_UINT8_NOTSET, EMS_VALUE_UINT8_NOTSET}; - uint8_t Roomctrl::sendtype_[HCS] = {SendType::TEMP, SendType::TEMP, SendType::TEMP, SendType::TEMP}; - uint8_t Roomctrl::type_[HCS] = {RemoteType::NONE, RemoteType::NONE, RemoteType::NONE, RemoteType::NONE}; - uint32_t Roomctrl::timeout_ = 0; - - /** +namespace emsesp { + +// init statics +bool Roomctrl::switch_off_[HCS] = {false, false, false, false}; +uint32_t Roomctrl::send_time_[HCS] = {0, 0, 0, 0}; +uint32_t Roomctrl::receive_time_[HCS] = {0, 0, 0, 0}; +int16_t Roomctrl::remotetemp_[HCS] = {EMS_VALUE_INT16_NOTSET, EMS_VALUE_INT16_NOTSET, EMS_VALUE_INT16_NOTSET, EMS_VALUE_INT16_NOTSET}; +uint8_t Roomctrl::remotehum_[HCS] = {EMS_VALUE_UINT8_NOTSET, EMS_VALUE_UINT8_NOTSET, EMS_VALUE_UINT8_NOTSET, EMS_VALUE_UINT8_NOTSET}; +uint8_t Roomctrl::sendtype_[HCS] = {SendType::TEMP, SendType::TEMP, SendType::TEMP, SendType::TEMP}; +uint8_t Roomctrl::type_[HCS] = {RemoteType::NONE, RemoteType::NONE, RemoteType::NONE, RemoteType::NONE}; +uint32_t Roomctrl::timeout_ = 0; + +/** * set the temperature, */ - void Roomctrl::set_timeout(uint8_t t) { - timeout_ = t * 3600000; // ms - } - void Roomctrl::set_remotetemp(const uint8_t type, const uint8_t hc, const int16_t temp) { - if (!type_[hc] && !type) { - return; - } - if (remotetemp_[hc] != EMS_VALUE_INT16_NOTSET && temp == EMS_VALUE_INT16_NOTSET) { // switch remote off - remotetemp_[hc] = EMS_VALUE_INT16_NOTSET; - switch_off_[hc] = true; - send_time_[hc] = uuid::get_uptime() - SEND_INTERVAL; // send now - sendtype_[hc] = SendType::TEMP; - return; - } - if (hc >= HCS || !type) { - return; - } - if (remotetemp_[hc] != temp) { - send_time_[hc] = uuid::get_uptime() - SEND_INTERVAL; // send now - sendtype_[hc] = SendType::TEMP; - } - type_[hc] = type; - remotetemp_[hc] = temp; - receive_time_[hc] = uuid::get_uptime(); - } - - // set humidity for RC100H emulation - void Roomctrl::set_remotehum(const uint8_t type, const uint8_t hc, const int8_t hum) { - if (hc >= HCS || type != type_[hc]) { - return; - } - if (remotehum_[hc] != hum) { - send_time_[hc] = uuid::get_uptime() - SEND_INTERVAL; // send now - sendtype_[hc] = SendType::HUMI; - } - remotehum_[hc] = hum; - } - - uint8_t Roomctrl::get_hc(uint8_t addr) { - addr &= 0x7F; - if (addr >= 0x40 && addr <= 0x44 && type_[addr - 0x40] == SENSOR) { - return addr - 0x40; // SENSOR - } else if (addr >= 0x38 && addr <= 0x3B - && (type_[addr - 0x38] == RC100H || type_[addr - 0x38] == RC200 || type_[addr - 0x38] == RC100 || type_[addr - 0x38] == RT800 - || type_[addr - 0x38] == RC120RF)) { - return addr - 0x38; // RC100H, RC200 - } else if (addr >= 0x18 && addr <= 0x1B && (type_[addr - 0x18] == RC20 || type_[addr - 0x18] == FB10)) { - return addr - 0x18; // RC20, FB10 - } - return 0xFF; // invalid - } - - /** +void Roomctrl::set_timeout(uint8_t t) { + timeout_ = t * 3600000; // ms +} +void Roomctrl::set_remotetemp(const uint8_t type, const uint8_t hc, const int16_t temp) { + if (!type_[hc] && !type) { + return; + } + if (remotetemp_[hc] != EMS_VALUE_INT16_NOTSET && temp == EMS_VALUE_INT16_NOTSET) { // switch remote off + remotetemp_[hc] = EMS_VALUE_INT16_NOTSET; + switch_off_[hc] = true; + send_time_[hc] = uuid::get_uptime() - SEND_INTERVAL; // send now + sendtype_[hc] = SendType::TEMP; + return; + } + if (hc >= HCS || !type) { + return; + } + if (remotetemp_[hc] != temp) { + send_time_[hc] = uuid::get_uptime() - SEND_INTERVAL; // send now + sendtype_[hc] = SendType::TEMP; + } + type_[hc] = type; + remotetemp_[hc] = temp; + receive_time_[hc] = uuid::get_uptime(); +} + +// set humidity for RC100H emulation +void Roomctrl::set_remotehum(const uint8_t type, const uint8_t hc, const int8_t hum) { + if (hc >= HCS || type != type_[hc]) { + return; + } + if (remotehum_[hc] != hum) { + send_time_[hc] = uuid::get_uptime() - SEND_INTERVAL; // send now + sendtype_[hc] = SendType::HUMI; + } + remotehum_[hc] = hum; +} + +uint8_t Roomctrl::get_hc(uint8_t addr) { + addr &= 0x7F; + if (addr >= 0x40 && addr <= 0x44 && type_[addr - 0x40] == SENSOR) { + return addr - 0x40; // SENSOR + } else if (addr >= 0x38 && addr <= 0x3B + && (type_[addr - 0x38] == RC100H || type_[addr - 0x38] == RC200 || type_[addr - 0x38] == RC100 || type_[addr - 0x38] == RT800 + || type_[addr - 0x38] == RC120RF)) { + return addr - 0x38; // RC100H, RC200 + } else if (addr >= 0x18 && addr <= 0x1B && (type_[addr - 0x18] == RC20 || type_[addr - 0x18] == FB10)) { + return addr - 0x18; // RC20, FB10 + } + return 0xFF; // invalid +} + +/** * if remote control is active send the temperature every 15 seconds */ - void Roomctrl::send(uint8_t addr) { - if ((addr & 0x80) || EMSESP::system_.readonly_mode()) { - return; - } - uint8_t hc = get_hc(addr); - // check address, reply only on addresses 0x18..0x1B or 0x40..0x43 - if (hc >= HCS) { - return; - } - // no reply if the temperature is not set - if (!switch_off_[hc] && remotetemp_[hc] == EMS_VALUE_INT16_NOTSET && remotehum_[hc] == EMS_VALUE_UINT8_NOTSET) { - return; - } - - if (!switch_off_[hc] && timeout_ && (uuid::get_uptime() - receive_time_[hc]) > timeout_) { - remotetemp_[hc] = EMS_VALUE_INT16_NOTSET; - switch_off_[hc] = true; - sendtype_[hc] = SendType::TEMP; - EMSESP::logger().warning("remotetemp timeout hc%d, stop sending roomtemperature to thermostat", hc); - } - if (switch_off_[hc] || (uuid::get_uptime() - send_time_[hc]) > SEND_INTERVAL) { // check interval - if (type_[hc] == RC100H || type_[hc] == RT800 || type_[hc] == RC120RF) { - if (sendtype_[hc] == SendType::HUMI) { // send humidity - if (switch_off_[hc]) { - remotehum_[hc] = EMS_VALUE_UINT8_NOTSET; - } - send_time_[hc] = uuid::get_uptime(); - humidity(addr, 0x10, hc); - sendtype_[hc] = SendType::TEMP; - } else { // temperature telegram - if (remotehum_[hc] != EMS_VALUE_UINT8_NOTSET) { - sendtype_[hc] = SendType::HUMI; - } else { - send_time_[hc] = uuid::get_uptime(); - } - temperature(addr, 0x10, hc); // send to master-thermostat - } - } else if (type_[hc] == RC200 || type_[hc] == RC100 || type_[hc] == FB10) { - send_time_[hc] = uuid::get_uptime(); - temperature(addr, 0x10, hc); // send to master-thermostat (https://github.com/emsesp/EMS-ESP32/issues/336) - } else { // type==RC20 or SENSOR - send_time_[hc] = uuid::get_uptime(); - temperature(addr, 0x00, hc); // send to all - } - if (remotehum_[hc] == EMS_VALUE_UINT8_NOTSET && switch_off_[hc]) { - switch_off_[hc] = false; - type_[hc] = RemoteType::NONE; - } - } else { - // acknowledge every poll - EMSuart::send_poll(addr | EMSbus::ems_mask()); - } - } - - /** +void Roomctrl::send(uint8_t addr) { + if ((addr & 0x80) || EMSESP::system_.readonly_mode()) { + return; + } + uint8_t hc = get_hc(addr); + // check address, reply only on addresses 0x18..0x1B or 0x40..0x43 + if (hc >= HCS) { + return; + } + // no reply if the temperature is not set + if (!switch_off_[hc] && remotetemp_[hc] == EMS_VALUE_INT16_NOTSET && remotehum_[hc] == EMS_VALUE_UINT8_NOTSET) { + return; + } + + if (!switch_off_[hc] && timeout_ && (uuid::get_uptime() - receive_time_[hc]) > timeout_) { + remotetemp_[hc] = EMS_VALUE_INT16_NOTSET; + switch_off_[hc] = true; + sendtype_[hc] = SendType::TEMP; + EMSESP::logger().warning("remotetemp timeout hc%d, stop sending roomtemperature to thermostat", hc); + } + if (switch_off_[hc] || (uuid::get_uptime() - send_time_[hc]) > SEND_INTERVAL) { // check interval + if (type_[hc] == RC100H || type_[hc] == RT800 || type_[hc] == RC120RF) { + if (sendtype_[hc] == SendType::HUMI) { // send humidity + if (switch_off_[hc]) { + remotehum_[hc] = EMS_VALUE_UINT8_NOTSET; + } + send_time_[hc] = uuid::get_uptime(); + humidity(addr, 0x10, hc); + sendtype_[hc] = SendType::TEMP; + } else { // temperature telegram + if (remotehum_[hc] != EMS_VALUE_UINT8_NOTSET) { + sendtype_[hc] = SendType::HUMI; + } else { + send_time_[hc] = uuid::get_uptime(); + } + temperature(addr, 0x10, hc); // send to master-thermostat + } + } else if (type_[hc] == RC200 || type_[hc] == RC100 || type_[hc] == FB10) { + send_time_[hc] = uuid::get_uptime(); + temperature(addr, 0x10, hc); // send to master-thermostat (https://github.com/emsesp/EMS-ESP32/issues/336) + } else { // type==RC20 or SENSOR + send_time_[hc] = uuid::get_uptime(); + temperature(addr, 0x00, hc); // send to all + } + if (remotehum_[hc] == EMS_VALUE_UINT8_NOTSET && switch_off_[hc]) { + switch_off_[hc] = false; + type_[hc] = RemoteType::NONE; + } + } else { + // acknowledge every poll + EMSuart::send_poll(addr | EMSbus::ems_mask()); + } +} + +/** * check if there is a message for the remote room controller */ - void Roomctrl::check(uint8_t addr, const uint8_t * data, const uint8_t length) { - if (EMSESP::system_.readonly_mode()) { - return; - } - uint8_t hc = get_hc(addr); - if (hc >= HCS || length < 5) { - return; - } - if (type_[hc] == SENSOR) { - return; - } - // no reply if the temperature is not set - if (remotetemp_[hc] == EMS_VALUE_INT16_NOTSET) { - return; - } - // reply to writes with write nack byte - if ((addr & 0x80) == 0) { // it's a write to us - ack_write(); // accept writes, don't care. - return; - } - addr &= 0x7F; - // reads: for now we only reply to version and remote temperature - // empty message back if temperature not set or unknown message type - if (data[2] == EMSdevice::EMS_TYPE_VERSION) { - version(addr, data[0], hc); - } else if (data[2] == 0xAF && data[3] == 0) { - temperature(addr, data[0], hc); - } else if (length == 6) { // all other ems queries - unknown(addr, data[0], data[2], data[3]); - } else if (length == 8 && data[2] == 0xFF && data[3] == 0 && data[5] == 0 && data[6] == 0x23) { // Junkers - temperature(addr, data[0], hc); - } else if (length == 8 && data[2] == 0xFF && data[3] == 0 && data[5] == 3 && data[6] == 0x2B + hc) { // EMS+ temperature - temperature(addr, data[0], hc); - } else if (length == 8 && data[2] == 0xFF && data[3] == 0 && data[5] == 3 && data[6] == 0x7B + hc && remotehum_[hc] != EMS_VALUE_UINT8_NOTSET) { // EMS+ humidity - humidity(addr, data[0], hc); - } else if (length == 8 && data[2] == 0xFF) { // ems+ query - unknown(addr, data[0], data[3], data[5], data[6]); - } else if (data[2] == 0xF7) { // ems+ query with 3 bytes type src dst 7F offset len=FF FF HIGH LOW - replyF7(addr, data[0], data[3], data[5], data[6], data[7], hc); - } else if (length == 8) { - unknown(addr, data[0], data[3], data[5], data[6]); - } - } - - /** +void Roomctrl::check(uint8_t addr, const uint8_t * data, const uint8_t length) { + if (EMSESP::system_.readonly_mode()) { + return; + } + uint8_t hc = get_hc(addr); + if (hc >= HCS || length < 5) { + return; + } + if (type_[hc] == SENSOR) { + return; + } + // no reply if the temperature is not set + if (remotetemp_[hc] == EMS_VALUE_INT16_NOTSET) { + return; + } + // reply to writes with write nack byte + if ((addr & 0x80) == 0) { // it's a write to us + ack_write(); // accept writes, don't care. + return; + } + addr &= 0x7F; + // reads: for now we only reply to version and remote temperature + // empty message back if temperature not set or unknown message type + if (data[2] == EMSdevice::EMS_TYPE_VERSION) { + version(addr, data[0], hc); + } else if (data[2] == 0xAF && data[3] == 0) { + temperature(addr, data[0], hc); + } else if (length == 6) { // all other ems queries + unknown(addr, data[0], data[2], data[3]); + } else if (length == 8 && data[2] == 0xFF && data[3] == 0 && data[5] == 0 && data[6] == 0x23) { // Junkers + temperature(addr, data[0], hc); + } else if (length == 8 && data[2] == 0xFF && data[3] == 0 && data[5] == 3 && data[6] == 0x2B + hc) { // EMS+ temperature + temperature(addr, data[0], hc); + } else if (length == 8 && data[2] == 0xFF && data[3] == 0 && data[5] == 3 && data[6] == 0x7B + hc && remotehum_[hc] != EMS_VALUE_UINT8_NOTSET) { // EMS+ humidity + humidity(addr, data[0], hc); + } else if (length == 8 && data[2] == 0xFF) { // ems+ query + unknown(addr, data[0], data[3], data[5], data[6]); + } else if (data[2] == 0xF7) { // ems+ query with 3 bytes type src dst 7F offset len=FF FF HIGH LOW + replyF7(addr, data[0], data[3], data[5], data[6], data[7], hc); + } else if (length == 8) { + unknown(addr, data[0], data[3], data[5], data[6]); + } +} + +/** * send version info */ - void Roomctrl::version(uint8_t addr, uint8_t dst, uint8_t hc) { - uint8_t data[20]; - data[0] = addr | EMSbus::ems_mask(); - data[1] = dst & 0x7F; - data[2] = 0x02; - data[3] = 0; - data[4] = type_[hc]; // set RC20 id 113, Ver 02.01 or Junkers FB10 id 109, Ver 16.05, RC100H id 200 ver 40.04 - if (type_[hc] == RC20) { - data[5] = 2; // version 2.01 - data[6] = 1; - data[7] = EMSbus::calculate_crc(data, 7); // append CRC - EMSuart::transmit(data, 8); - return; - } else if (type_[hc] == FB10) { - data[5] = 16; // version 16.05 - data[6] = 5; - data[7] = 0; - data[8] = 0; - data[9] = 0; - data[10] = 0; - data[11] = 0; - data[12] = 0; - data[13] = 0; - data[14] = EMSbus::calculate_crc(data, 14); // append CRC - EMSuart::transmit(data, 15); - return; - } else if (type_[hc] == RC200) { - data[5] = 32; // version 32.02 see #1611 - data[6] = 2; - data[7] = 0; - data[8] = 0xFF; - data[9] = 0; - data[10] = 0; - data[11] = 0; - data[12] = 0; - data[13] = 0; - data[14] = EMSbus::calculate_crc(data, 14); // append CRC - EMSuart::transmit(data, 15); - return; - } else if (type_[hc] == RC100H) { - data[5] = 40; // version 40.04 - data[6] = 4; - data[7] = 0; - data[8] = 0xFF; - data[9] = EMSbus::calculate_crc(data, 9); // append CRC - EMSuart::transmit(data, 10); - return; - } else if (type_[hc] == RC100) { - data[5] = 40; // version 40.03 - data[6] = 3; - data[7] = 0; - data[8] = 0xFF; - data[9] = EMSbus::calculate_crc(data, 9); // append CRC - EMSuart::transmit(data, 10); - return; - } else if (type_[hc] == RT800) { - data[5] = 21; // version 21.03 - data[6] = 3; - data[7] = EMSbus::calculate_crc(data, 7); // append CRC - EMSuart::transmit(data, 8); - return; - } else if (type_[hc] == RC120RF) { - data[5] = 16; // version 16.02 - data[6] = 2; - data[7] = 0; - data[8] = 0xFF; - data[9] = EMSbus::calculate_crc(data, 9); // append CRC - EMSuart::transmit(data, 10); - return; - } - } - - /** +void Roomctrl::version(uint8_t addr, uint8_t dst, uint8_t hc) { + uint8_t data[20]; + data[0] = addr | EMSbus::ems_mask(); + data[1] = dst & 0x7F; + data[2] = 0x02; + data[3] = 0; + data[4] = type_[hc]; // set RC20 id 113, Ver 02.01 or Junkers FB10 id 109, Ver 16.05, RC100H id 200 ver 40.04 + if (type_[hc] == RC20) { + data[5] = 2; // version 2.01 + data[6] = 1; + data[7] = EMSbus::calculate_crc(data, 7); // append CRC + EMSuart::transmit(data, 8); + return; + } else if (type_[hc] == FB10) { + data[5] = 16; // version 16.05 + data[6] = 5; + data[7] = 0; + data[8] = 0; + data[9] = 0; + data[10] = 0; + data[11] = 0; + data[12] = 0; + data[13] = 0; + data[14] = EMSbus::calculate_crc(data, 14); // append CRC + EMSuart::transmit(data, 15); + return; + } else if (type_[hc] == RC200) { + data[5] = 32; // version 32.02 see #1611 + data[6] = 2; + data[7] = 0; + data[8] = 0xFF; + data[9] = 0; + data[10] = 0; + data[11] = 0; + data[12] = 0; + data[13] = 0; + data[14] = EMSbus::calculate_crc(data, 14); // append CRC + EMSuart::transmit(data, 15); + return; + } else if (type_[hc] == RC100H) { + data[5] = 40; // version 40.04 + data[6] = 4; + data[7] = 0; + data[8] = 0xFF; + data[9] = EMSbus::calculate_crc(data, 9); // append CRC + EMSuart::transmit(data, 10); + return; + } else if (type_[hc] == RC100) { + data[5] = 40; // version 40.03 + data[6] = 3; + data[7] = 0; + data[8] = 0xFF; + data[9] = EMSbus::calculate_crc(data, 9); // append CRC + EMSuart::transmit(data, 10); + return; + } else if (type_[hc] == RT800) { + data[5] = 21; // version 21.03 + data[6] = 3; + data[7] = EMSbus::calculate_crc(data, 7); // append CRC + EMSuart::transmit(data, 8); + return; + } else if (type_[hc] == RC120RF) { + data[5] = 16; // version 16.02 + data[6] = 2; + data[7] = 0; + data[8] = 0xFF; + data[9] = EMSbus::calculate_crc(data, 9); // append CRC + EMSuart::transmit(data, 10); + return; + } +} + +/** * unknown message id, we reply with empty message */ - void Roomctrl::unknown(uint8_t addr, uint8_t dst, uint8_t type, uint8_t offset) { - uint8_t data[10]; - data[0] = addr | EMSbus::ems_mask(); - data[1] = dst & 0x7F; - data[2] = type; - data[3] = offset; - data[4] = EMSbus::calculate_crc(data, 4); // append CRC - EMSuart::transmit(data, 5); - } - - void Roomctrl::unknown(uint8_t addr, uint8_t dst, uint8_t offset, uint8_t typeh, uint8_t typel) { - uint8_t data[10]; - data[0] = addr | EMSbus::ems_mask(); - data[1] = dst & 0x7F; - data[2] = 0xFF; - data[3] = offset; - data[4] = typeh; - data[5] = typel; - data[6] = EMSbus::calculate_crc(data, 6); // append CRC - EMSuart::transmit(data, 7); - } - - /** +void Roomctrl::unknown(uint8_t addr, uint8_t dst, uint8_t type, uint8_t offset) { + uint8_t data[10]; + data[0] = addr | EMSbus::ems_mask(); + data[1] = dst & 0x7F; + data[2] = type; + data[3] = offset; + data[4] = EMSbus::calculate_crc(data, 4); // append CRC + EMSuart::transmit(data, 5); +} + +void Roomctrl::unknown(uint8_t addr, uint8_t dst, uint8_t offset, uint8_t typeh, uint8_t typel) { + uint8_t data[10]; + data[0] = addr | EMSbus::ems_mask(); + data[1] = dst & 0x7F; + data[2] = 0xFF; + data[3] = offset; + data[4] = typeh; + data[5] = typel; + data[6] = EMSbus::calculate_crc(data, 6); // append CRC + EMSuart::transmit(data, 7); +} + +/** * send the room temperature in message 0xAF */ - void Roomctrl::temperature(uint8_t addr, uint8_t dst, uint8_t hc) { - uint8_t data[14]; - data[0] = addr | EMSbus::ems_mask(); - data[1] = dst & 0x7F; - if (type_[hc] == RC20) { // RC20, telegram 0xAF - data[2] = 0xAF; - data[3] = 0; - data[4] = (uint8_t)(remotetemp_[hc] >> 8); - data[5] = (uint8_t)(remotetemp_[hc] & 0xFF); - data[6] = 0; - data[7] = EMSbus::calculate_crc(data, 7); // append CRC - EMSuart::transmit(data, 8); - } else if (type_[hc] == FB10) { // Junkers FB10, telegram 0x0123 - data[2] = 0xFF; - data[3] = 0; - data[4] = 0; - data[5] = 0x23; // fixed for all hc - data[6] = (uint8_t)(remotetemp_[hc] >> 8); - data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); - data[8] = EMSbus::calculate_crc(data, 8); // append CRC - EMSuart::transmit(data, 9); - } else if (type_[hc] == RC200) { // RC200, telegram 42B, ff - data[2] = 0xFF; - data[3] = 0; - data[4] = 3; - data[5] = 0x2B + hc; - data[6] = (uint8_t)(remotetemp_[hc] >> 8); - data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); - uint16_t t1 = remotetemp_[hc] * 10; - data[8] = (uint8_t)(t1 >> 8); - data[9] = (uint8_t)(t1 & 0xFF); - data[10] = 1; // not sure what this is and if we need it, maybe mode? - data[11] = EMSbus::calculate_crc(data, 11); // append CRC - EMSuart::transmit(data, 12); - } else if (type_[hc] == RC100H || type_[hc] == RC100) { // RC100H, telegram 42B, ff - data[2] = 0xFF; - data[3] = 0; - data[4] = 3; - data[5] = 0x2B + hc; - data[6] = (uint8_t)(remotetemp_[hc] >> 8); - data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); - data[8] = EMSbus::calculate_crc(data, 8); // append CRC - EMSuart::transmit(data, 9); - } else if (type_[hc] == SENSOR) { // wireless sensor, broadcast id 435 - data[2] = 0xFF; - data[3] = 0; - data[4] = 3; - data[5] = 0x35 + hc; - data[6] = (uint8_t)(remotetemp_[hc] >> 8); - data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); - data[8] = EMSbus::calculate_crc(data, 8); // append CRC - EMSuart::transmit(data, 9); - } else if (type_[hc] == RT800) { // RC200, telegram 42B, ff - data[2] = 0xFF; - data[3] = 0; - data[4] = 3; - data[5] = 0x2B + hc; - data[6] = (uint8_t)(remotetemp_[hc] >> 8); - data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); - uint16_t t1 = remotetemp_[hc] * 10; - data[8] = (uint8_t)(t1 >> 8); - data[9] = (uint8_t)(t1 & 0xFF); - data[10] = 1; // not sure what this is and if we need it, maybe mode? - data[11] = 9; // not sure what this is and if we need it, maybe mode? - data[12] = EMSbus::calculate_crc(data, 12); // append CRC - EMSuart::transmit(data, 13); - } else if (type_[hc] == RC120RF) { - data[2] = 0xFF; - data[3] = 0; - data[4] = 3; - data[5] = 0x2B + hc; - data[6] = (uint8_t)(remotetemp_[hc] >> 8); - data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); - uint16_t t1 = remotetemp_[hc] * 10; - data[8] = (uint8_t)(t1 >> 8); - data[9] = (uint8_t)(t1 & 0xFF); - data[10] = 0; // not sure what this is and if we need it - data[11] = 0; // not sure what this is and if we need it - data[12] = EMSbus::calculate_crc(data, 12); // append CRC - EMSuart::transmit(data, 13); - } - } - - // send telegram 0x047B only for RC100H - void Roomctrl::humidity(uint8_t addr, uint8_t dst, uint8_t hc) { - int16_t dew = calc_dew(remotetemp_[hc], remotehum_[hc]); - int8_t dew8 = EMS_VALUE_INT8_NOTSET; - if (dew != EMS_VALUE_INT16_NOTSET) { - dew8 = static_cast((dew >= 0 ? dew + 5 : dew - 5) / 10); - } - uint8_t data[11]; - data[0] = addr | EMSbus::ems_mask(); - data[1] = dst & 0x7F; - data[2] = 0xFF; - data[3] = 0; - data[4] = 3; - data[5] = 0x7B + hc; - data[6] = static_cast(dew8); - data[7] = remotehum_[hc]; - data[8] = static_cast(static_cast(dew) >> 8); - data[9] = static_cast(static_cast(dew) & 0xFF); - data[10] = EMSbus::calculate_crc(data, 10); // append CRC - EMSuart::transmit(data, 11); - } - - /** +void Roomctrl::temperature(uint8_t addr, uint8_t dst, uint8_t hc) { + uint8_t data[14]; + data[0] = addr | EMSbus::ems_mask(); + data[1] = dst & 0x7F; + if (type_[hc] == RC20) { // RC20, telegram 0xAF + data[2] = 0xAF; + data[3] = 0; + data[4] = (uint8_t)(remotetemp_[hc] >> 8); + data[5] = (uint8_t)(remotetemp_[hc] & 0xFF); + data[6] = 0; + data[7] = EMSbus::calculate_crc(data, 7); // append CRC + EMSuart::transmit(data, 8); + } else if (type_[hc] == FB10) { // Junkers FB10, telegram 0x0123 + data[2] = 0xFF; + data[3] = 0; + data[4] = 0; + data[5] = 0x23; // fixed for all hc + data[6] = (uint8_t)(remotetemp_[hc] >> 8); + data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); + data[8] = EMSbus::calculate_crc(data, 8); // append CRC + EMSuart::transmit(data, 9); + } else if (type_[hc] == RC200) { // RC200, telegram 42B, ff + data[2] = 0xFF; + data[3] = 0; + data[4] = 3; + data[5] = 0x2B + hc; + data[6] = (uint8_t)(remotetemp_[hc] >> 8); + data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); + uint16_t t1 = remotetemp_[hc] * 10; + data[8] = (uint8_t)(t1 >> 8); + data[9] = (uint8_t)(t1 & 0xFF); + data[10] = 1; // not sure what this is and if we need it, maybe mode? + data[11] = EMSbus::calculate_crc(data, 11); // append CRC + EMSuart::transmit(data, 12); + } else if (type_[hc] == RC100H || type_[hc] == RC100) { // RC100H, telegram 42B, ff + data[2] = 0xFF; + data[3] = 0; + data[4] = 3; + data[5] = 0x2B + hc; + data[6] = (uint8_t)(remotetemp_[hc] >> 8); + data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); + data[8] = EMSbus::calculate_crc(data, 8); // append CRC + EMSuart::transmit(data, 9); + } else if (type_[hc] == SENSOR) { // wireless sensor, broadcast id 435 + data[2] = 0xFF; + data[3] = 0; + data[4] = 3; + data[5] = 0x35 + hc; + data[6] = (uint8_t)(remotetemp_[hc] >> 8); + data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); + data[8] = EMSbus::calculate_crc(data, 8); // append CRC + EMSuart::transmit(data, 9); + } else if (type_[hc] == RT800) { // RC200, telegram 42B, ff + data[2] = 0xFF; + data[3] = 0; + data[4] = 3; + data[5] = 0x2B + hc; + data[6] = (uint8_t)(remotetemp_[hc] >> 8); + data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); + uint16_t t1 = remotetemp_[hc] * 10; + data[8] = (uint8_t)(t1 >> 8); + data[9] = (uint8_t)(t1 & 0xFF); + data[10] = 1; // not sure what this is and if we need it, maybe mode? + data[11] = 9; // not sure what this is and if we need it, maybe mode? + data[12] = EMSbus::calculate_crc(data, 12); // append CRC + EMSuart::transmit(data, 13); + } else if (type_[hc] == RC120RF) { + data[2] = 0xFF; + data[3] = 0; + data[4] = 3; + data[5] = 0x2B + hc; + data[6] = (uint8_t)(remotetemp_[hc] >> 8); + data[7] = (uint8_t)(remotetemp_[hc] & 0xFF); + uint16_t t1 = remotetemp_[hc] * 10; + data[8] = (uint8_t)(t1 >> 8); + data[9] = (uint8_t)(t1 & 0xFF); + data[10] = 0; // not sure what this is and if we need it + data[11] = 0; // not sure what this is and if we need it + data[12] = EMSbus::calculate_crc(data, 12); // append CRC + EMSuart::transmit(data, 13); + } +} + +// send telegram 0x047B only for RC100H +void Roomctrl::humidity(uint8_t addr, uint8_t dst, uint8_t hc) { + int16_t dew = calc_dew(remotetemp_[hc], remotehum_[hc]); + int8_t dew8 = EMS_VALUE_INT8_NOTSET; + if (dew != EMS_VALUE_INT16_NOTSET) { + dew8 = static_cast((dew >= 0 ? dew + 5 : dew - 5) / 10); + } + uint8_t data[11]; + data[0] = addr | EMSbus::ems_mask(); + data[1] = dst & 0x7F; + data[2] = 0xFF; + data[3] = 0; + data[4] = 3; + data[5] = 0x7B + hc; + data[6] = static_cast(dew8); + data[7] = remotehum_[hc]; + data[8] = static_cast(static_cast(dew) >> 8); + data[9] = static_cast(static_cast(dew) & 0xFF); + data[10] = EMSbus::calculate_crc(data, 10); // append CRC + EMSuart::transmit(data, 11); +} + +/** * send a nack if someone want to write to us. */ - void Roomctrl::nack_write() { - uint8_t data[1]; - data[0] = TxService::TX_WRITE_FAIL; - EMSuart::transmit(data, 1); - } - - /** +void Roomctrl::nack_write() { + uint8_t data[1]; + data[0] = TxService::TX_WRITE_FAIL; + EMSuart::transmit(data, 1); +} + +/** * send a ack if someone want to write to us. */ - void Roomctrl::ack_write() { - uint8_t data[1]; - data[0] = TxService::TX_WRITE_SUCCESS; - EMSuart::transmit(data, 1); - } - - void Roomctrl::replyF7(uint8_t addr, uint8_t dst, uint8_t offset, uint8_t typehh, uint8_t typeh, uint8_t typel, uint8_t hc) { - uint8_t data[12]; - data[0] = addr | EMSbus::ems_mask(); - data[1] = dst & 0x7F; - data[2] = 0xF7; - data[3] = offset; - data[4] = typehh; - data[5] = typeh; - data[6] = typel; - if (typehh == 0x02) { - if (type_[hc] == RC200 || type_[hc] == FB10) { - data[7] = 0xFF; - data[8] = 0x01; - } else { - data[7] = 0x0F; - data[8] = 0x00; - } - } else { - data[7] = 0; - data[8] = 0; - } - data[9] = EMSbus::calculate_crc(data, 9); // append CRC - EMSuart::transmit(data, 10); - } - - int16_t Roomctrl::calc_dew(int16_t temp, uint8_t humi) { - if (humi == EMS_VALUE_UINT8_NOTSET || temp == EMS_VALUE_INT16_NOTSET) { - return EMS_VALUE_INT16_NOTSET; - } - const float k2 = 17.62; - const float k3 = 243.12; - const float t = (float)temp / 10; - const float h = (float)humi / 100; - int16_t dt = (10 * k3 * (((k2 * t) / (k3 + t)) + log(h)) / (((k2 * k3) / (k3 + t)) - log(h))); - return dt; - } - - - } // namespace emsesp \ No newline at end of file +void Roomctrl::ack_write() { + uint8_t data[1]; + data[0] = TxService::TX_WRITE_SUCCESS; + EMSuart::transmit(data, 1); +} + +void Roomctrl::replyF7(uint8_t addr, uint8_t dst, uint8_t offset, uint8_t typehh, uint8_t typeh, uint8_t typel, uint8_t hc) { + uint8_t data[12]; + data[0] = addr | EMSbus::ems_mask(); + data[1] = dst & 0x7F; + data[2] = 0xF7; + data[3] = offset; + data[4] = typehh; + data[5] = typeh; + data[6] = typel; + if (typehh == 0x02) { + if (type_[hc] == RC200 || type_[hc] == FB10) { + data[7] = 0xFF; + data[8] = 0x01; + } else { + data[7] = 0x0F; + data[8] = 0x00; + } + } else { + data[7] = 0; + data[8] = 0; + } + data[9] = EMSbus::calculate_crc(data, 9); // append CRC + EMSuart::transmit(data, 10); +} + +int16_t Roomctrl::calc_dew(int16_t temp, uint8_t humi) { + if (humi == EMS_VALUE_UINT8_NOTSET || temp == EMS_VALUE_INT16_NOTSET) { + return EMS_VALUE_INT16_NOTSET; + } + const float k2 = 17.62; + const float k3 = 243.12; + const float t = (float)temp / 10; + const float h = (float)humi / 100; + int16_t dt = (10 * k3 * (((k2 * t) / (k3 + t)) + log(h)) / (((k2 * k3) / (k3 + t)) - log(h))); + return dt; +} + + +} // namespace emsesp \ No newline at end of file diff --git a/src/core/roomcontrol.h b/src/core/roomcontrol.h index 5b361cfe3..69e79499a 100644 --- a/src/core/roomcontrol.h +++ b/src/core/roomcontrol.h @@ -34,7 +34,8 @@ class Roomctrl { static bool is_remote(const uint8_t hc) { return (hc < 4 && remotetemp_[hc] != EMS_VALUE_INT16_NOTSET); } - static void set_timeout(uint8_t t); + static void set_timeout(uint8_t t); + static int16_t calc_dew(int16_t temp, uint8_t hum); private: static constexpr uint32_t SEND_INTERVAL = 15000; // 15 sec @@ -50,7 +51,6 @@ class Roomctrl { static void nack_write(); static void ack_write(); static void replyF7(uint8_t addr, uint8_t dst, uint8_t offset, uint8_t typehh, uint8_t typeh, uint8_t typel, uint8_t hc); - static int16_t calc_dew(int16_t temp, uint8_t hum); static bool switch_off_[HCS]; static uint32_t send_time_[HCS]; @@ -64,4 +64,4 @@ class Roomctrl { } // namespace emsesp -#endif +#endif \ No newline at end of file diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 94b420e33..5a2de88fa 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -816,16 +816,16 @@ void Thermostat::process_RemoteTemp(const std::shared_ptr & tele // e.g. "38 10 FF 00 03 7B 08 24 00 4B" void Thermostat::process_RemoteHumidity(const std::shared_ptr & telegram) { // has_update(telegram, dewtemperature_, 0); // this is int8 - has_update(telegram, humidity_, 1); - has_update(telegram, dewtemperature_, 2); // this is int16 + // some thermostats use short telegram with int8 dewpoint, https://github.com/emsesp/EMS-ESP32/issues/1491 - if (telegram->offset == 0 && telegram->message_length < 4) { - int8_t dew = dewtemperature_ / 10; - telegram->read_value(dew, 0); - if (dew != EMS_VALUE_INT8_NOTSET && dewtemperature_ != dew * 10) { - dewtemperature_ = dew * 10; - has_update(dewtemperature_); - } + // but it's not a dewpoint in offset 0, removed, see https://github.com/emsesp/EMS-ESP32/issues/3135 + has_update(telegram, humidity_, 1); + // has_update(telegram, dewtemperature_, 2); // this is int16 + int16_t dew = EMS_VALUE_INT16_NOTSET; + if (telegram->read_value(dew, 2)) { + has_update(dewtemperature_, dew); + } else if (telegram->offset == 0 && telegram->message_length < 4) { + has_update(dewtemperature_, Roomctrl::calc_dew(tempsensor1_, humidity_)); } } diff --git a/src/emsesp_version.h b/src/emsesp_version.h index dd02903f5..a731a45b3 100644 --- a/src/emsesp_version.h +++ b/src/emsesp_version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.9.0-dev.14" +#define EMSESP_APP_VERSION "3.9.0-dev.15"