diff --git a/src/console.cpp b/src/console.cpp
index df5b9b270..6b1882883 100644
--- a/src/console.cpp
+++ b/src/console.cpp
@@ -431,6 +431,10 @@ void Console::start() {
shell->maximum_log_messages(100); // default is 50
shell->start();
shell->log_level(uuid::log::Level::DEBUG); // order is: err, warning, notice, info, trace, debug, all
+
+#if defined(EMSESP_STANDALONE)
+ shell->add_flags(CommandFlags::ADMIN);
+#endif
}
// always start the telnet service, except on an ESP8266
diff --git a/src/device_library.h b/src/device_library.h
index 7f40fdae5..828a02ad2 100644
--- a/src/device_library.h
+++ b/src/device_library.h
@@ -39,50 +39,6 @@
{208, DeviceType::BOILER, F("Logamax plus/GB192/Condens GC9000"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{234, DeviceType::BOILER, F("Logamax Plus GB122"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
-// Solar Modules - 0x30
-{ 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10},
-{101, DeviceType::SOLAR, F("ISM1"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
-{162, DeviceType::SOLAR, F("SM50"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
-{163, DeviceType::SOLAR, F("SM100"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
-{164, DeviceType::SOLAR, F("SM200"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
-
-// Mixing Modules - 0x20-0x27 for HC, 0x28-0x29 for WWC
-{ 69, DeviceType::MIXING, F("MM10"), DeviceFlags::EMS_DEVICE_FLAG_MM10},
-{159, DeviceType::MIXING, F("MM50"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
-{160, DeviceType::MIXING, F("MM100"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
-{161, DeviceType::MIXING, F("MM200"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
-
-// Heat Pumps - 0x38
-{200, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
-{252, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
-
-// Switches - 0x11
-{ 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
-
-// Controllers - 0x09 / 0x10 / 0x50
-{ 68, DeviceType::CONTROLLER, F("BC10/RFM20"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-{ 89, DeviceType::CONTROLLER, F("BC10 GB142"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-{ 95, DeviceType::CONTROLLER, F("HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-{114, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-{125, DeviceType::CONTROLLER, F("BC25"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-{152, DeviceType::CONTROLLER, F("Controller"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-{169, DeviceType::CONTROLLER, F("BC40"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-{190, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-{207, DeviceType::CONTROLLER, F("Sense II/CS200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x10
-{209, DeviceType::CONTROLLER, F("ErP"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-{218, DeviceType::CONTROLLER, F("M200/RFM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x50
-{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-{241, DeviceType::CONTROLLER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
-
-// Connect devices - 0x02
-{171, DeviceType::CONNECT, F("OpenTherm Converter"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
-{205, DeviceType::CONNECT, F("Moduline Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
-{206, DeviceType::CONNECT, F("Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
-
-// Gateways - 0x48 / 0x18
-{ 94, DeviceType::GATEWAY, F("RFM20 Remote Base for RC20RF"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x18
-{189, DeviceType::GATEWAY, F("KM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x48
-
// Thermostat - not currently supporting write operations, like the Easy/100 types - 0x18
{202, DeviceType::THERMOSTAT, F("Logamatic TC100/Moduline Easy"), DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write
{203, DeviceType::THERMOSTAT, F("EasyControl CT200"), DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write
@@ -109,8 +65,53 @@
{107, DeviceType::THERMOSTAT, F("FR100"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_2}, // older model
{108, DeviceType::THERMOSTAT, F("FR110"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_2}, // older model
{111, DeviceType::THERMOSTAT, F("FR10"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
-{147, DeviceType::THERMOSTAT, F("FR50"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
+{147, DeviceType::THERMOSTAT, F("FR50"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
{191, DeviceType::THERMOSTAT, F("FR120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
-{192, DeviceType::THERMOSTAT, F("FW120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS}
+{192, DeviceType::THERMOSTAT, F("FW120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
+
+// Solar Modules - 0x30
+{ 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10},
+{101, DeviceType::SOLAR, F("ISM1"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
+{162, DeviceType::SOLAR, F("SM50"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
+{163, DeviceType::SOLAR, F("SM100"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
+{164, DeviceType::SOLAR, F("SM200"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
+
+// Mixing Modules - 0x20-0x27 for HC, 0x28-0x29 for WWC
+{ 69, DeviceType::MIXING, F("MM10"), DeviceFlags::EMS_DEVICE_FLAG_MM10},
+{159, DeviceType::MIXING, F("MM50"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
+{160, DeviceType::MIXING, F("MM100"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
+{161, DeviceType::MIXING, F("MM200"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
+
+// Heat Pumps - 0x38
+{200, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
+{252, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
+
+// Controllers - 0x09 / 0x10 / 0x50
+{ 68, DeviceType::CONTROLLER, F("BC10/RFM20"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+{ 89, DeviceType::CONTROLLER, F("BC10 GB142"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+{ 95, DeviceType::CONTROLLER, F("HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+{114, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+{125, DeviceType::CONTROLLER, F("BC25"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+{152, DeviceType::CONTROLLER, F("Controller"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+{169, DeviceType::CONTROLLER, F("BC40"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+{190, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+{207, DeviceType::CONTROLLER, F("Sense II/CS200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x10
+{209, DeviceType::CONTROLLER, F("ErP"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+{218, DeviceType::CONTROLLER, F("M200/RFM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x50
+{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+{241, DeviceType::CONTROLLER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
+
+// Connect devices - 0x02
+{171, DeviceType::CONNECT, F("OpenTherm Converter"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
+{205, DeviceType::CONNECT, F("Moduline Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
+{206, DeviceType::CONNECT, F("Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
+
+// Switches - 0x11
+{ 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
+
+// Gateways - 0x48 / 0x18
+{ 94, DeviceType::GATEWAY, F("RFM20 Remote Base for RC20RF"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x18
+{189, DeviceType::GATEWAY, F("KM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE} // 0x48
+
// clang-format on
diff --git a/src/devices/helpers.cpp b/src/devices/helpers.cpp
new file mode 100644
index 000000000..c0c176559
--- /dev/null
+++ b/src/devices/helpers.cpp
@@ -0,0 +1,307 @@
+/*
+ * EMS-ESP - https://github.com/proddy/EMS-ESP
+ * Copyright 2019 Paul Derbyshire
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "helpers.h"
+#include "telegram.h" // for EMS_VALUE_* settings
+
+namespace emsesp {
+
+// like itoa but for hex, and quicker
+char * Helpers::hextoa(char * result, const uint8_t value) {
+ char * p = result;
+ uint8_t nib1 = (value >> 4) & 0x0F;
+ uint8_t nib2 = (value >> 0) & 0x0F;
+ *p++ = nib1 < 0xA ? '0' + nib1 : 'A' + nib1 - 0xA;
+ *p++ = nib2 < 0xA ? '0' + nib2 : 'A' + nib2 - 0xA;
+ *p = '\0'; // null terminate just in case
+ return result;
+}
+
+/*
+ * itoa for 2 byte integers
+ * written by Lukás Chmela, Released under GPLv3. http://www.strudel.org.uk/itoa/ version 0.4
+ */
+char * Helpers::itoa(char * result, int16_t value, const uint8_t base) {
+ // check that the base if valid
+ if (base < 2 || base > 36) {
+ *result = '\0';
+ return result;
+ }
+
+ char * ptr = result, *ptr1 = result, tmp_char;
+ int16_t tmp_value;
+
+ do {
+ tmp_value = value;
+ value /= base;
+ *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];
+ } while (value);
+
+ // Apply negative sign
+ if (tmp_value < 0) {
+ *ptr++ = '-';
+ }
+ *ptr-- = '\0';
+ while (ptr1 < ptr) {
+ tmp_char = *ptr;
+ *ptr-- = *ptr1;
+ *ptr1++ = tmp_char;
+ }
+ return result;
+}
+
+// for decimals 0 to 99, printed as a 2 char string
+char * Helpers::smallitoa(char * result, const uint8_t value) {
+ result[0] = ((value / 10) == 0) ? '0' : (value / 10) + '0';
+ result[1] = (value % 10) + '0';
+ result[2] = '\0';
+ return result;
+}
+
+// for decimals 0 to 999, printed as a string
+char * Helpers::smallitoa(char * result, const uint16_t value) {
+ result[0] = ((value / 100) == 0) ? '0' : (value / 100) + '0';
+ result[1] = (((value % 100) / 10) == 0) ? '0' : ((value % 100) / 10) + '0';
+ result[2] = (value % 10) + '0';
+ result[3] = '\0';
+ return result;
+}
+
+// convert unsigned int (single byte) to text value and returns it
+// format: 2=divide by 2, 10=divide by 10, 255=handle as a Boolean
+char * Helpers::render_value(char * result, uint8_t value, uint8_t format) {
+ result[0] = '\0';
+
+ // check if its a boolean
+ if (format == EMS_VALUE_BOOL) {
+ if (value == EMS_VALUE_BOOL_OFF) {
+ strlcpy(result, "off", 5);
+ } else if (value == EMS_VALUE_BOOL_NOTSET) {
+ strlcpy(result, "?", 5);
+ } else {
+ strlcpy(result, "on", 5); // assume on. could have value 0x01 or 0xFF
+ }
+ return result;
+ }
+
+ if (value == EMS_VALUE_UINT_NOTSET) {
+ strlcpy(result, "?", 5);
+ return (result);
+ }
+
+ static char s2[5] = {0};
+
+ switch (format) {
+ case 2:
+ strlcpy(result, itoa(s2, value >> 1, 10), 5);
+ strlcat(result, ".", 5);
+ strlcat(result, ((value & 0x01) ? "5" : "0"), 5);
+ break;
+
+ case 10:
+ strlcpy(result, itoa(s2, value / 10, 10), 5);
+ strlcat(result, ".", 5);
+ strlcat(result, itoa(s2, value % 10, 10), 5);
+ break;
+
+ default:
+ itoa(result, value, 10);
+ break;
+ }
+
+ return result;
+}
+
+// convert float to char
+// format is the precision
+char * Helpers::render_value(char * result, const float value, const uint8_t format) {
+ long p[] = {0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
+
+ char * ret = result;
+ long whole = (long)value;
+ Helpers::itoa(result, whole, 10);
+ while (*result != '\0') {
+ result++;
+ }
+ *result++ = '.';
+ long decimal = abs((long)((value - whole) * p[format]));
+ itoa(result, decimal, 10);
+
+ return ret;
+}
+
+// convert short (two bytes) to text string and returns string
+// decimals: 0 = no division, 10=divide value by 10, 2=divide by 2, 100=divide value by 100
+// negative values are assumed stored as 1-compliment (https://medium.com/@LeeJulija/how-integers-are-stored-in-memory-using-twos-complement-5ba04d61a56c)
+char * Helpers::render_value(char * result, const int16_t value, const uint8_t format) {
+ result[0] = '\0';
+
+ // remove errors or invalid values, 0x7D00 and higher
+ if ((value == EMS_VALUE_SHORT_NOTSET) || (value == EMS_VALUE_SHORT_INVALID) || (value == EMS_VALUE_USHORT_NOTSET)) {
+ strlcpy(result, "?", 10);
+ return result;
+ }
+
+ // just print it if mo conversion required
+ if ((format == 0) || (format == 1)) {
+ itoa(result, value, 10);
+ return result;
+ }
+
+ int16_t new_value = value;
+
+ // check for negative values
+ if (new_value < 0) {
+ strlcpy(result, "-", 10);
+ new_value *= -1; // convert to positive
+ } else {
+ strlcpy(result, "", 10);
+ }
+
+ // do floating point
+ char s2[10] = {0};
+ if (format == 2) {
+ // divide by 2
+ strlcat(result, itoa(s2, new_value / 2, 10), 10);
+ strlcat(result, ".", 10);
+ strlcat(result, ((new_value & 0x01) ? "5" : "0"), 10);
+
+ } else {
+ strlcat(result, itoa(s2, new_value / format, 10), 10);
+ strlcat(result, ".", 10);
+ strlcat(result, itoa(s2, new_value % format, 10), 10);
+ }
+
+ return result;
+}
+
+// convert unsigned short (two bytes) to text string and prints it
+// format: 0 = no division, 10=divide value by 10, 2=divide by 2, 100=divide value by 100
+char * Helpers::render_value(char * result, const uint16_t value, const uint8_t format) {
+ result[0] = '\0';
+
+ if ((value == EMS_VALUE_USHORT_NOTSET) || (value == EMS_VALUE_USHORT_INVALID)) {
+ strlcpy(result, "?", 10);
+ return result;
+ }
+
+ return (render_value(result, (int16_t)value, format)); // use same code, force it to a signed int
+}
+
+// convert signed byte to text string and prints it
+// format: 0 = no division, 10=divide value by 10, 2=divide by 2, 100=divide value by 100
+char * Helpers::render_value(char * result, const int8_t value, const uint8_t format) {
+ result[0] = '\0';
+
+ if (value == EMS_VALUE_INT_NOTSET) {
+ strlcpy(result, "?", 10);
+ return result;
+ }
+
+ return (render_value(result, (int16_t)value, format)); // use same code, force it to a signed int
+}
+
+// render long (4 byte) unsigned values
+// format = 0 for normal, any other value for divide by format
+char * Helpers::render_value(char * result, const uint32_t value, const uint8_t format) {
+ result[0] = '\0';
+
+ if ((value == EMS_VALUE_ULONG_NOTSET) || (value == EMS_VALUE_ULONG_INVALID)) {
+ strlcpy(result, "?", 10);
+ return (result);
+ }
+
+ static char s[20] = {0};
+
+#ifndef EMSESP_STANDALONE
+ if (format <= 1) {
+ strlcat(result, ltoa(value, s, 10), 20);
+ } else {
+ strlcat(result, ltoa(value / format, s, 10), 20);
+ strlcat(result, ".", 2);
+ strlcat(result, ltoa(value % format, s, 10), 20);
+ }
+
+#else
+ strncat(result, itoa(s, value / format, 10), 20);
+#endif
+
+ return result;
+}
+
+// creates string of hex values from an arrray of bytes
+std::string Helpers::data_to_hex(const uint8_t * data, const uint8_t length) {
+ if (length == 0) {
+ return uuid::read_flash_string(F(""));
+ }
+
+ std::string str(160, '\0');
+ char buffer[4];
+ char * p = &str[0];
+ for (uint8_t i = 0; i < length; i++) {
+ Helpers::hextoa(buffer, data[i]);
+ *p++ = buffer[0];
+ *p++ = buffer[1];
+ *p++ = ' '; // space
+ }
+ *--p = '\0'; // null terminate just in case, loosing the trailing space
+
+ return str;
+}
+
+
+// takes a hex string and convert it to an unsigned 32bit number (max 8 hex digits)
+// works with only positive numbers
+uint32_t Helpers::hextoint(const char * hex) {
+ uint32_t val = 0;
+ while (*hex) {
+ // get current character then increment
+ char byte = *hex++;
+ // transform hex character to the 4bit equivalent number, using the ascii table indexes
+ if (byte >= '0' && byte <= '9')
+ byte = byte - '0';
+ else if (byte >= 'a' && byte <= 'f')
+ byte = byte - 'a' + 10;
+ else if (byte >= 'A' && byte <= 'F')
+ byte = byte - 'A' + 10;
+ else
+ return 0; // error
+ // shift 4 to make space for new digit, and add the 4 bits of the new digit
+ val = (val << 4) | (byte & 0xF);
+ }
+ return val;
+}
+
+// quick char to long
+uint16_t Helpers::atoint(const char * value) {
+ unsigned int x = 0;
+ while (*value != '\0') {
+ x = (x * 10) + (*value - '0');
+ ++value;
+ }
+ return x;
+}
+
+// rounds a number to 2 decimal places
+// example: round2(3.14159) -> 3.14
+double Helpers::round2(double value) {
+ return (int)(value * 100 + 0.5) / 100.0;
+}
+
+
+} // namespace emsesp
diff --git a/src/emsesp.cpp b/src/emsesp.cpp
index 2bb15bbdd..38d9b9fa5 100644
--- a/src/emsesp.cpp
+++ b/src/emsesp.cpp
@@ -63,7 +63,7 @@ bool EMSESP::ems_read_only_;
uint32_t EMSESP::last_fetch_ = 0;
#ifdef EMSESP_DEBUG
-#include "test/test_data.h" // used with the 'test' command, under su/admin
+#include "test_data.h" // used with the 'test' command, under su/admin
#endif
// for a specific EMS device go and request data values
@@ -172,7 +172,7 @@ void EMSESP::show_emsbus(uuid::console::Shell & shell) {
// and for each associated EMS device go and request data values
void EMSESP::show_values(uuid::console::Shell & shell) {
if (sensor_devices().empty() && emsdevices.empty()) {
- shell.printfln(F("No data available from devices to show"));
+ shell.printfln(F("No data collected from EMS devices. Try 'refresh'."));
return;
}
@@ -454,15 +454,16 @@ void EMSESP::add_context_menus() {
// for each associated EMS device go and get its system information
void EMSESP::show_devices(uuid::console::Shell & shell) {
- /*
+#ifdef EMSESP_DEBUG
// for debugging ony
// prints out DeviceType (UNKNOWN = 0, SERVICEKEY, BOILER, THERMOSTAT, MIXING, SOLAR, HEATPUMP, GATEWAY, SWITCH, CONTROLLER, CONNECT)
- shell.printf(F("Registered EMS device handlers:"));
+ // from emsdevice.h
+ shell.printf(F("(debug) Registered EMS device handlers:"));
for (const auto & pair : EMSFactory::device_handlers()) {
shell.printf(F(" %d"), pair.first);
}
shell.println();
- */
+#endif
if (emsdevices.empty()) {
shell.printfln(F("No EMS devices detected. Try scanning using the 'scan devices' command."));
@@ -514,7 +515,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
+ // look up the rest of the details using the product_id and create the new device object
// then send a request to the device to get the version and any other info we may have
bool found = false;
for (const auto & device : device_library_) {
@@ -531,9 +532,8 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, std::
LOG_NOTICE(F("Unrecognized EMS device with device ID 0x%02X with product ID %d. Please report on GitHub."), device_id, product_id);
return false; // not found
} else {
- LOG_DEBUG(F("Adding new device with device ID 0x%02X with product ID %d"), device_id, product_id);
- // go and fetch its data, including asking for the version
- send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id);
+ LOG_DEBUG(F("Adding new device with device ID 0x%02X with product ID %d and version %s"), device_id, product_id, version.c_str());
+ // go and fetch its data,
fetch_device_values(device_id);
}
@@ -542,7 +542,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, std::
// send a read request, passing it into to the Tx Service, with no offset
void EMSESP::send_read_request(const uint16_t type_id, const uint8_t dest) {
- txservice_.read_request(type_id, dest, 0); // no offset
+ txservice_.read_request(type_id, dest, 0); // 0 = no offset
}
// sends write request
diff --git a/src/emsesp.h b/src/emsesp.h
index 15c0e69ea..eef42c675 100644
--- a/src/emsesp.h
+++ b/src/emsesp.h
@@ -42,11 +42,12 @@
#include "system.h"
#include "sensors.h"
#include "console.h"
-#include "boiler.h"
#include "shower.h"
#include "roomcontrol.h"
-#define LOG_TRACE_WATCH_NONE 0 // no watch set
+#include "devices/boiler.h"
+
+#define LOG_TRACE_WATCH_NONE 0 // no watch id set
namespace emsesp {
@@ -62,6 +63,8 @@ class EMSESP {
#ifdef EMSESP_DEBUG
static void run_test(uuid::console::Shell & shell, const std::string & command); // only for testing
static void dummy_mqtt_commands(const char * message);
+ static void rx_telegram(const std::vector & data);
+ static void uart_telegram(const std::vector & rx_data);
#endif
static bool process_telegram(std::shared_ptr telegram);
diff --git a/src/emsfactory.h b/src/emsfactory.h
index 3f42310a7..ede08d8fe 100644
--- a/src/emsfactory.h
+++ b/src/emsfactory.h
@@ -32,10 +32,9 @@
auto registry_##derivedClass = ConcreteEMSFactory(device_type); \
}
-
namespace emsesp {
-class EMSdevice; // forward declaration
+class EMSdevice; // forward declaration, for gcc linking
class EMSFactory {
public:
diff --git a/src/test/test_data.h b/src/test_data.h
similarity index 66%
rename from src/test/test_data.h
rename to src/test_data.h
index ea8d96f91..f65e9a8db 100644
--- a/src/test/test_data.h
+++ b/src/test_data.h
@@ -7,18 +7,13 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
emsdevices.push_back(EMSFactory::add(EMSdevice::DeviceType::BOILER, EMSdevice::EMS_DEVICE_ID_BOILER, 0, "", "My Boiler", 0, 0));
// A fake response - UBADevices(0x07)
- uint8_t t[] = {0x08, 0x00, 0x07, 0x00, 0x0B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47};
- rxservice_.add(t, sizeof(t));
-
- return;
+ rx_telegram({0x08, 0x00, 0x07, 0x00, 0x0B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
}
if (command == "boiler2") {
// question: do we need to set the mask?
std::string version("1.2.3");
add_device(0x08, 123, version, EMSdevice::Brand::BUDERUS); // Nefit Trendline
-
- return;
}
if (command == "unknown") {
@@ -28,23 +23,33 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
rxservice_.loop();
// simulate getting version information back from an unknown device
- uint8_t t[] = {0x09, 0x0B, 0x02, 0x00, 0x59, 0x01, 0x02, 0x56};
- rxservice_.add(t, sizeof(t));
- rxservice_.loop();
-
- return;
+ rx_telegram({0x09, 0x0B, 0x02, 0x00, 0x59, 0x01, 0x02});
}
if (command == "unknown2") {
// simulate getting version information back from an unknown device
- uint8_t t[] = {0x09, 0x0B, 0x02, 0x00, 0x5A, 0x01, 0x02, 0x5A}; // product id is 90
- rxservice_.add(t, sizeof(t));
- rxservice_.loop();
-
- return;
+ rx_telegram({0x09, 0x0B, 0x02, 0x00, 0x5A, 0x01, 0x02}); // product id is 90 which doesn't exist
}
- if (command == "thermostats") {
+ if ((command == "gateway") || (command == "g")) {
+ // add 0x48 KM200, via a version command
+ rx_telegram({0x48, 0x0B, 0x02, 0x00, 0xBD, 0x04, 0x06, 00, 00, 00, 00, 00, 00, 00});
+
+ // Boiler(0x08) -> All(0x00), UBADevices(0x07), data: 09 01 00 00 00 00 00 00 01 00 00 00 00
+ // check: make sure 0x48 is not detected again !
+ rx_telegram({0x08, 0x00, 0x07, 0x00, 0x09, 01, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00});
+
+ // add thermostat - Thermostat: RC300/RC310/Moduline 3000/CW400/Sense II (DeviceID:0x10, ProductID:158, Version:03.03) ** master device **
+ std::string version("01.03");
+ add_device(0x10, 158, version, EMSdevice::Brand::BUDERUS);
+ rxservice_.loop();
+
+ // simulate incoming telegram
+ // Thermostat(0x10) -> 48(0x48), ?(0x26B), data: 6B 08 4F 00 00 00 02 00 00 00 02 00 03 00 03 00 03
+ rx_telegram({0x10, 0x48, 0xFF, 00, 01, 0x6B, 00, 0x6B, 0x08, 0x4F, 00, 00, 00, 02, 00, 00, 00, 02, 00, 03, 00, 03, 00, 03});
+ }
+
+ if (command == "thermostat") {
shell.printfln(F("Testing adding devices on the EMS bus..."));
// create some fake devices
@@ -56,8 +61,6 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
// add_device(0x17, 254, version, EMSdevice::Brand::BUDERUS); // test unknown product_id
add_device(0x18, 157, version, EMSdevice::Brand::BOSCH); // Bosch CR100 - https://github.com/proddy/EMS-ESP/issues/355
-
- return;
}
if (command == "solar") {
@@ -72,14 +75,8 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
// SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200
// B0 0B FF 00 02 62 00 44 02 7A 80 00 80 00 80 00 80 00 80 00 80 00 00 7C 80 00 80 00 80 00 80
- uint8_t t[] = {0xB0, 0x0B, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00,
- 0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x89};
- rxservice_.add(t, sizeof(t));
- rxservice_.loop();
-
- shell.loop_all();
-
- return;
+ rx_telegram({0xB0, 0x0B, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00,
+ 0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80});
}
if (command == "cr100") {
@@ -93,10 +90,8 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
// RCPLUSStatusMessage_HC1(0x01A5)
// 98 00 FF 00 01 A5 00 CF 21 2E 00 00 2E 24 03 25 03 03 01 03 25 00 C8 00 00 11 01 03
- uint8_t t[] = {0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24, 0x03,
- 0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03, 0x13};
- rxservice_.add(t, sizeof(t));
- rxservice_.loop();
+ uart_telegram({0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24,
+ 0x03, 0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03});
shell.loop_all();
rxservice_.loop();
@@ -115,9 +110,6 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
shell.loop_all();
txservice_.send(); // send it to UART
- shell.loop_all();
-
- return;
}
if (command == "rx") {
@@ -125,79 +117,59 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
// fake telegrams. length includes CRC
// Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25)
- uint8_t t1[] = {0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A,
- 0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00, 0xFB};
- rxservice_.add(t1, sizeof(t1));
+ uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A,
+ 0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00});
// Boiler -> Thermostat, UBAParameterWW(0x33), telegram: 08 97 33 00 23 24 (#data=2)
- uint8_t t2[] = {0x08, 0x97, 0x33, 0x00, 0x23, 0x24, 0x5B};
- rxservice_.add(t2, sizeof(t2));
+ uart_telegram({0x08, 0x97, 0x33, 0x00, 0x23, 0x24});
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
- uint8_t t21[] = {0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00, 0x5F};
- rxservice_.add(t21, sizeof(t21));
-
- // write return code 01, 04
- uint8_t t3[] = {0x04};
- rxservice_.add(t3, sizeof(t3));
+ uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
// Thermostat -> Me, RC20StatusMessage(0x91), telegram: 17 0B 91 05 44 45 46 47 (#data=4)
- uint8_t t4[] = {0x17, 0x0B, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47, 0x8E};
- rxservice_.add(t4, sizeof(t4));
+ uart_telegram({0x17, 0x0B, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47});
// bad CRC - corrupt telegram - CRC should be 0x8E
uint8_t t5[] = {0x17, 0x0B, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47, 0x99};
rxservice_.add(t5, sizeof(t5));
// simulating a Tx record
- uint8_t t7[] = {0x0B, 0x88, 0x07, 0x00, 0x20, 0xA8};
- rxservice_.add(t7, sizeof(t7));
+ uart_telegram({0x0B, 0x88, 0x07, 0x00, 0x20});
// Version Boiler
- uint8_t t8[] = {0x08, 0x0B, 0x02, 0x00, 0x7B, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x43};
- rxservice_.add(t8, sizeof(t8));
+ uart_telegram({0x08, 0x0B, 0x02, 0x00, 0x7B, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04});
// Version Thermostat, device_id 0x11
- uint8_t t9[] = {0x11, 0x0B, 0x02, 0x00, 0x4D, 0x03, 0x03, 0x55};
- rxservice_.add(t9, sizeof(t9));
+ uart_telegram({0x11, 0x0B, 0x02, 0x00, 0x4D, 0x03, 0x03});
// Thermostat -> all, telegram: 10 00 FF 00 01 A5 00 D7 21 00 00 00 00 30 01 84 01 01 03 01 84 01 F1 00 00 11 01 00 08 63 00
// 0x1A5 test ems+
- uint8_t t10a[] = {0x10, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xD7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x84,
- 0x01, 0x01, 0x03, 0x01, 0x84, 0x01, 0xF1, 0x00, 0x00, 0x11, 0x01, 0x00, 0x08, 0x63, 0x00, 0xCC};
- rxservice_.add(t10a, sizeof(t10a));
+ uart_telegram({0x10, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xD7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x84,
+ 0x01, 0x01, 0x03, 0x01, 0x84, 0x01, 0xF1, 0x00, 0x00, 0x11, 0x01, 0x00, 0x08, 0x63, 0x00});
// setting temp from 21.5 to 19.9C
- uint8_t t10b[] = {0x10, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xC7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x84,
- 0x01, 0x01, 0x03, 0x01, 0x84, 0x01, 0xF1, 0x00, 0x00, 0x11, 0x01, 0x00, 0x08, 0x63, 0x00, 0x46};
- rxservice_.add(t10b, sizeof(t10b));
+ uart_telegram({0x10, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xC7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x84,
+ 0x01, 0x01, 0x03, 0x01, 0x84, 0x01, 0xF1, 0x00, 0x00, 0x11, 0x01, 0x00, 0x08, 0x63, 0x00});
// Thermostat -> Boiler, UBAFlags(0x35), telegram: 17 08 35 00 11 00 (#data=2)
- uint8_t t13[] = {0x17, 0x08, 0x35, 0x00, 0x11, 0x00, 0xC1};
- rxservice_.add(t13, sizeof(t13));
+ uart_telegram({0x17, 0x08, 0x35, 0x00, 0x11, 0x00});
// Thermostat -> Boiler, UBASetPoints(0x1A), telegram: 17 08 1A 00 00 00 00 00 (#data=4)
- uint8_t t14[] = {0x17, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A};
- rxservice_.add(t14, sizeof(t14));
+ uart_telegram({0x17, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00});
// Thermostat -> Me, RC20Set(0xA8), telegram: 17 0B A8 00 01 00 FF F6 01 06 00 01 0D 01 00 FF FF 01 02 02 02 00 00 05 1F 05 1F 02 0E 00 FF (#data=27)
- uint8_t t15[] = {0x17, 0x0B, 0xA8, 0x00, 0x01, 0x00, 0xFF, 0xF6, 0x01, 0x06, 0x00, 0x01, 0x0D, 0x01, 0x00, 0xFF,
- 0xFF, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x05, 0x1F, 0x05, 0x1F, 0x02, 0x0E, 0x00, 0xFF, 0xDF};
- rxservice_.add(t15, sizeof(t15));
+ uart_telegram({0x17, 0x0B, 0xA8, 0x00, 0x01, 0x00, 0xFF, 0xF6, 0x01, 0x06, 0x00, 0x01, 0x0D, 0x01, 0x00, 0xFF,
+ 0xFF, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x05, 0x1F, 0x05, 0x1F, 0x02, 0x0E, 0x00, 0xFF});
// Boiler(0x08) -> All(0x00), UBAMonitorWW(0x34), data: 36 01 A5 80 00 21 00 00 01 00 01 3E 8D 03 77 91 00 80 00
- uint8_t t16[] = {0x08, 0x00, 0x34, 0x00, 0x36, 0x01, 0xA5, 0x80, 0x00, 0x21, 0x00, 0x00,
- 0x01, 0x00, 0x01, 0x3E, 0x8D, 0x03, 0x77, 0x91, 0x00, 0x80, 0x00, 0x3E};
- rxservice_.add(t16, sizeof(t16));
-
- return;
+ uart_telegram(
+ {0x08, 0x00, 0x34, 0x00, 0x36, 0x01, 0xA5, 0x80, 0x00, 0x21, 0x00, 0x00, 0x01, 0x00, 0x01, 0x3E, 0x8D, 0x03, 0x77, 0x91, 0x00, 0x80, 0x00});
}
if (command == "send") {
shell.printfln(F("Sending to Tx..."));
show_emsbus(shell);
txservice_.send(); // send it to UART
- return;
}
if (command == "tx") {
@@ -228,8 +200,6 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
txservice_.send(); // send it to UART
txservice_.flush_tx_queue();
-
- return;
}
if (command == "poll") {
@@ -249,9 +219,7 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
incoming_telegram(poll, 1);
// incoming Rx
- uint8_t t1[] = {0x17, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A};
- incoming_telegram(t1, sizeof(t1));
- rxservice_.loop();
+ uart_telegram({0x17, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A});
// Simulate adding a Poll - should send retry
incoming_telegram(poll, 1);
@@ -261,11 +229,7 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
send_write_request(0x91, 0x17, 0x00, t2, sizeof(t2), 0);
show_emsbus(shell);
- incoming_telegram(t1, sizeof(t1));
-
txservice_.flush_tx_queue();
-
- return;
}
if (command == "mqtt1") {
@@ -311,8 +275,6 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
// txservice_.show_tx_queue();
publish_all_values();
-
- return;
}
if (command == "poll2") {
@@ -327,24 +289,18 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
show_emsbus(shell);
txservice_.flush_tx_queue();
-
- return;
}
if (command == "rx2") {
// incoming Rx
- uint8_t t[] = {0x1B, 0x5B, 0xFD, 0x2D, 0x9E, 0x3A, 0xB6, 0xE5, 0x02, 0x20, 0x33, 0x30, 0x32, 0x3A, 0x20, 0x5B, 0x73,
- 0xFF, 0xFF, 0xCB, 0xDF, 0xB7, 0xA7, 0xB5, 0x67, 0x77, 0x77, 0xE4, 0xFF, 0xFD, 0x77, 0xFF, 0xD1};
- incoming_telegram(t, sizeof(t));
- return;
+ uart_telegram({0x1B, 0x5B, 0xFD, 0x2D, 0x9E, 0x3A, 0xB6, 0xE5, 0x02, 0x20, 0x33, 0x30, 0x32, 0x3A, 0x20, 0x5B,
+ 0x73, 0xFF, 0xFF, 0xCB, 0xDF, 0xB7, 0xA7, 0xB5, 0x67, 0x77, 0x77, 0xE4, 0xFF, 0xFD, 0x77, 0xFF});
}
// https://github.com/proddy/EMS-ESP/issues/380#issuecomment-633663007
if (command == "rx3") {
// incoming Rx
- uint8_t t[] = {0x21, 0x0B, 0xFF, 0x00, 0xDA};
- incoming_telegram(t, sizeof(t));
- return;
+ uart_telegram({0x21, 0x0B, 0xFF, 0x00});
}
if (command == "mqtt2") {
@@ -352,22 +308,18 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
for (uint8_t i = 0; i < 30; i++) {
Mqtt::subscribe("cmd", dummy_mqtt_commands);
}
- return;
}
-
// testing the UART tx command, without a queue
if (command == "tx2") {
uint8_t t[] = {0x0B, 0x88, 0x18, 0x00, 0x20, 0xD4}; // including CRC
EMSuart::transmit(t, sizeof(t));
- return;
}
// send read request with offset
if (command == "offset") {
// send_read_request(0x18, 0x08);
txservice_.read_request(0x18, 0x08, 27); // no offset
- return;
}
if (command == "mixing") {
@@ -382,21 +334,33 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
rxservice_.loop();
// WWC1 on 0x29
- uint8_t m1[] = {0xA9, 0x00, 0xFF, 0x00, 0x02, 0x32, 0x02, 0x6C, 0x00, 0x3C, 0x00, 0x3C, 0x3C, 0x46, 0x02, 0x03, 0x03, 0x00, 0x3C, 0x57};
- rxservice_.add(m1, sizeof(m1));
- rxservice_.loop();
+ rx_telegram({0xA9, 0x00, 0xFF, 0x00, 0x02, 0x32, 0x02, 0x6C, 0x00, 0x3C, 0x00, 0x3C, 0x3C, 0x46, 0x02, 0x03, 0x03, 0x00, 0x3C});
// WWC2 on 0x28
- uint8_t m2[] = {0xA8, 0x00, 0xFF, 0x00, 0x02, 0x31, 0x02, 0x35, 0x00, 0x3C, 0x00, 0x3C, 0x3C, 0x46, 0x02, 0x03, 0x03, 0x00, 0x3C, 0x71};
- rxservice_.add(m2, sizeof(m2));
- rxservice_.loop();
-
- shell.loop_all();
-
- return;
+ rx_telegram({0xA8, 0x00, 0xFF, 0x00, 0x02, 0x31, 0x02, 0x35, 0x00, 0x3C, 0x00, 0x3C, 0x3C, 0x46, 0x02, 0x03, 0x03, 0x00, 0x3C});
}
- shell.printfln(F("[Test] Unknown test command"));
+ // finally dump to console
+ shell.loop_all();
+}
+
+// simulates a telegram in the Rx queue, but without the CRC which is added automatically
+void EMSESP::rx_telegram(const std::vector & rx_data) {
+ uint8_t len = rx_data.size();
+ uint8_t data[50];
+ std::copy(rx_data.begin(), rx_data.end(), data);
+ data[len] = rxservice_.calculate_crc(rx_data.data(), len);
+ rxservice_.add(data, len + 1);
+ rxservice_.loop();
+}
+
+// simulates a telegram straight from UART, but without the CRC which is added automatically
+void EMSESP::uart_telegram(const std::vector & rx_data) {
+ uint8_t len = rx_data.size();
+ uint8_t data[50];
+ std::copy(rx_data.begin(), rx_data.end(), data);
+ data[len] = rxservice_.calculate_crc(rx_data.data(), len);
+ incoming_telegram(data, len + 1);
}
#pragma GCC diagnostic push
diff --git a/src/uart/emsuart_esp32.cpp b/src/uart/emsuart_esp32.cpp
index 7cef6668b..c2369217a 100644
--- a/src/uart/emsuart_esp32.cpp
+++ b/src/uart/emsuart_esp32.cpp
@@ -99,7 +99,7 @@ void EMSuart::start(uint8_t tx_mode) {
drop_next_rx = true;
buf_handle = xRingbufferCreate(128, RINGBUF_TYPE_NOSPLIT);
ESP_ERROR_CHECK(uart_isr_register(EMSUART_UART, emsuart_rx_intr_handler, NULL, ESP_INTR_FLAG_IRAM, &uart_handle));
- xTaskCreate(emsuart_recvTask, "emsuart_recvTask", 2048, NULL, configMAX_PRIORITIES -1, NULL);
+ xTaskCreate(emsuart_recvTask, "emsuart_recvTask", 2048, NULL, configMAX_PRIORITIES - 1, NULL);
EMS_UART.int_ena.brk_det = 1; // activate only break
}
diff --git a/src/uart/emsuart_esp8266.cpp b/src/uart/emsuart_esp8266.cpp
index ae317922d..dc029029f 100644
--- a/src/uart/emsuart_esp8266.cpp
+++ b/src/uart/emsuart_esp8266.cpp
@@ -250,7 +250,7 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
return EMS_TX_STATUS_OK; // nothing to send
}
#ifdef EMSESP_DEBUG
- LOG_INFO(F("UART Responsetime: %d ms"),uuid::get_uptime() - emsRxTime);
+ LOG_INFO(F("UART Responsetime: %d ms"), uuid::get_uptime() - emsRxTime);
#endif
// if ((uuid::get_uptime() - emsRxTime) > EMS_RX_TO_TX_TIMEOUT)) { // send allowed within 20 ms
// return EMS_TX_WTD_TIMEOUT;