mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
in standalone mode, always go as SU/admin
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -111,6 +67,51 @@
|
||||
{111, DeviceType::THERMOSTAT, F("FR10"), 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
|
||||
|
||||
307
src/devices/helpers.cpp
Normal file
307
src/devices/helpers.cpp
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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("<empty>"));
|
||||
}
|
||||
|
||||
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
|
||||
@@ -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
|
||||
|
||||
@@ -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<uint8_t> & data);
|
||||
static void uart_telegram(const std::vector<uint8_t> & rx_data);
|
||||
#endif
|
||||
|
||||
static bool process_telegram(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
@@ -32,10 +32,9 @@
|
||||
auto registry_##derivedClass = ConcreteEMSFactory<derivedClass>(device_type); \
|
||||
}
|
||||
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
class EMSdevice; // forward declaration
|
||||
class EMSdevice; // forward declaration, for gcc linking
|
||||
|
||||
class EMSFactory {
|
||||
public:
|
||||
|
||||
@@ -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<uint8_t> & 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<uint8_t> & 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
|
||||
Reference in New Issue
Block a user