Merge branch 'v2 a11' of https://github.com/proddy/EMS-ESP into v2

This commit is contained in:
MichaelDvP
2020-05-31 10:05:39 +02:00
20 changed files with 140 additions and 125 deletions

View File

@@ -112,6 +112,7 @@ MAKE_PSTR(deviceid_optional, "[device ID]")
MAKE_PSTR(invalid_log_level, "Invalid log level") MAKE_PSTR(invalid_log_level, "Invalid log level")
MAKE_PSTR(ip_address_optional, "[IP address]") MAKE_PSTR(ip_address_optional, "[IP address]")
MAKE_PSTR(ip_address_mandatory, "<IP address>") MAKE_PSTR(ip_address_mandatory, "<IP address>")
MAKE_PSTR(port_mandatory, "<port>")
MAKE_PSTR(log_level_fmt, "Log level = %s") MAKE_PSTR(log_level_fmt, "Log level = %s")
MAKE_PSTR(log_level_optional, "[level]") MAKE_PSTR(log_level_optional, "[level]")
MAKE_PSTR(name_mandatory, "<name>") MAKE_PSTR(name_mandatory, "<name>")

View File

@@ -24,36 +24,38 @@
*/ */
// Boilers - 0x08 // Boilers - 0x08
{115, DeviceType::BOILER, F("Topline/GB162"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{123, DeviceType::BOILER, F("GBx72/Trendline/Cerapur/Greenstar Si/27i"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{133, DeviceType::BOILER, F("GB125/Logamatic MC110"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{203, DeviceType::BOILER, F("Logamax U122/Cerapur"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{208, DeviceType::BOILER, F("Logamax plus/GB192/Condens GC9000"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{ 64, DeviceType::BOILER, F("BK13,BK15/Smartline/GB1x2"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, { 64, DeviceType::BOILER, F("BK13,BK15/Smartline/GB1x2"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{234, DeviceType::BOILER, F("Logamax Plus GB122"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, { 72, DeviceType::BOILER, F("GB125/MC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{ 84, DeviceType::BOILER, F("Logamax Plus GB022"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, { 84, DeviceType::BOILER, F("Logamax Plus GB022"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{ 95, DeviceType::BOILER, F("Condens 2500/Logamax/Logomatic/Cerapur Top/Greenstar/Generic HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, { 95, DeviceType::BOILER, F("Condens 2500/Logamax/Logomatic/Cerapur Top/Greenstar/Generic HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{115, DeviceType::BOILER, F("Topline/GB162"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{122, DeviceType::BOILER, F("Proline"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, {122, DeviceType::BOILER, F("Proline"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{123, DeviceType::BOILER, F("GBx72/Trendline/Cerapur/Greenstar Si/27i"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{133, DeviceType::BOILER, F("GB125/Logamatic MC110"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{170, DeviceType::BOILER, F("Logano GB212"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, {170, DeviceType::BOILER, F("Logano GB212"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{172, DeviceType::BOILER, F("Enviline/Compress 6000AW"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, {172, DeviceType::BOILER, F("Enviline/Compress 6000AW"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{ 72, DeviceType::BOILER, F("GB125/MC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, {195, DeviceType::BOILER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{203, DeviceType::BOILER, F("Logamax U122/Cerapur"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{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 // Solar Modules - 0x30
{ 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10}, { 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10},
{163, DeviceType::SOLAR, F("SM100"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
{164, DeviceType::SOLAR, F("SM200"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
{101, DeviceType::SOLAR, F("ISM1"), DeviceFlags::EMS_DEVICE_FLAG_SM100}, {101, DeviceType::SOLAR, F("ISM1"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
{162, DeviceType::SOLAR, F("SM50"), 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 // Mixing Modules - 0x20-0x27 for HC, 0x28-0x29 for WWC
{160, DeviceType::MIXING, F("MM100"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
{161, DeviceType::MIXING, F("MM200"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
{ 69, DeviceType::MIXING, F("MM10"), DeviceFlags::EMS_DEVICE_FLAG_MM10}, { 69, DeviceType::MIXING, F("MM10"), DeviceFlags::EMS_DEVICE_FLAG_MM10},
{159, DeviceType::MIXING, F("MM50"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS}, {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 // Heat Pumps - 0x38
{252, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{200, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, {200, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{252, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
// Switches - 0x11 // Switches - 0x11
{ 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x11 { 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x11
@@ -61,36 +63,38 @@
// Controllers - 0x09 / 0x10 / 0x50 // Controllers - 0x09 / 0x10 / 0x50
{ 68, DeviceType::CONTROLLER, F("BC10/RFM20"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 { 68, DeviceType::CONTROLLER, F("BC10/RFM20"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{ 89, DeviceType::CONTROLLER, F("BC10 GB142"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 { 89, DeviceType::CONTROLLER, F("BC10 GB142"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{218, DeviceType::CONTROLLER, F("M200/RFM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x50 { 95, DeviceType::CONTROLLER, F("HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{190, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{114, DeviceType::CONTROLLER, F("BC10"), 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 {125, DeviceType::CONTROLLER, F("BC25"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{169, DeviceType::CONTROLLER, F("BC40"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{152, DeviceType::CONTROLLER, F("Controller"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {152, DeviceType::CONTROLLER, F("Controller"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{ 95, DeviceType::CONTROLLER, F("HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {169, DeviceType::CONTROLLER, F("BC40"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{209, DeviceType::CONTROLLER, F("ErP"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {190, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{207, DeviceType::CONTROLLER, F("Sense II/CS200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x10 {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 // Connect devices - 0x02
{171, DeviceType::CONNECT, F("OpenTherm Converter"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x02
{205, DeviceType::CONNECT, F("Moduline Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x02 {205, DeviceType::CONNECT, F("Moduline Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x02
{206, DeviceType::CONNECT, F("Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x02 {206, DeviceType::CONNECT, F("Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x02
{171, DeviceType::CONNECT, F("OpenTherm Converter"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x02
// Gateways - 0x48 / 0x18 // Gateways - 0x48 / 0x18
{189, DeviceType::GATEWAY, F("KM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x48
{ 94, DeviceType::GATEWAY, F("RFM20 Remote Base for RC20RF"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 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 // 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 {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 {203, DeviceType::THERMOSTAT, F("EasyControl CT200"), DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write
// Thermostat - Common for Buderus/Nefit/Bosch specific - 0x17 / 0x10 / 0x18 // Thermostat - Common for Buderus/Nefit/Bosch specific - 0x17 / 0x10 / 0x18
{ 67, DeviceType::THERMOSTAT, F("RC30"), DeviceFlags::EMS_DEVICE_FLAG_RC30_1},// 0x10 - based on RC35
{ 77, DeviceType::THERMOSTAT, F("RC20/Moduline 300"), DeviceFlags::EMS_DEVICE_FLAG_RC20},// 0x17
{ 78, DeviceType::THERMOSTAT, F("Moduline 400"), DeviceFlags::EMS_DEVICE_FLAG_RC30}, // 0x10
{ 79, DeviceType::THERMOSTAT, F("RC10/Moduline 100"), DeviceFlags::EMS_DEVICE_FLAG_RC10},// 0x17 { 79, DeviceType::THERMOSTAT, F("RC10/Moduline 100"), DeviceFlags::EMS_DEVICE_FLAG_RC10},// 0x17
{ 80, DeviceType::THERMOSTAT, F("Moduline 200"), DeviceFlags::EMS_DEVICE_FLAG_RC10}, // 0x17 { 80, DeviceType::THERMOSTAT, F("Moduline 200"), DeviceFlags::EMS_DEVICE_FLAG_RC10}, // 0x17
{ 77, DeviceType::THERMOSTAT, F("RC20/Moduline 300"), DeviceFlags::EMS_DEVICE_FLAG_RC20},// 0x17
{ 67, DeviceType::THERMOSTAT, F("RC30"), DeviceFlags::EMS_DEVICE_FLAG_RC30_1},// 0x10 - based on RC35
{ 78, DeviceType::THERMOSTAT, F("Moduline 400"), DeviceFlags::EMS_DEVICE_FLAG_RC30}, // 0x10
{ 86, DeviceType::THERMOSTAT, F("RC35"), DeviceFlags::EMS_DEVICE_FLAG_RC35}, // 0x10 { 86, DeviceType::THERMOSTAT, F("RC35"), DeviceFlags::EMS_DEVICE_FLAG_RC35}, // 0x10
{ 93, DeviceType::THERMOSTAT, F("RC20RF"), DeviceFlags::EMS_DEVICE_FLAG_RC20}, // 0x19 { 93, DeviceType::THERMOSTAT, F("RC20RF"), DeviceFlags::EMS_DEVICE_FLAG_RC20}, // 0x19
{157, DeviceType::THERMOSTAT, F("RC200/CW100"), DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18 {157, DeviceType::THERMOSTAT, F("RC200/CW100"), DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18

View File

@@ -228,8 +228,7 @@ std::string EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> telegr
} }
for (const auto & tf : telegram_functions_) { for (const auto & tf : telegram_functions_) {
// if ((tf.telegram_type_id_ & 0x7F) == (telegram->type_id & 0x7F)) { if (tf.telegram_type_id_ == (telegram->type_id && ((telegram->type_id & 0xF0) != 0xF0))) {
if (tf.telegram_type_id_ == telegram->type_id && (telegram->type_id < 0xF0)) {
return uuid::read_flash_string(tf.telegram_type_name_); return uuid::read_flash_string(tf.telegram_type_name_);
} }
} }

View File

@@ -66,11 +66,6 @@ uint32_t EMSESP::last_fetch_ = 0;
#include "test/test_data.h" // used with the 'test' command, under su/admin #include "test/test_data.h" // used with the 'test' command, under su/admin
#endif #endif
// for each associated EMS device go and request its data values
void EMSESP::fetch_device_values() {
fetch_device_values(0); // 0 = fetch all
}
// for a specific EMS device go and request data values // for a specific EMS device go and request data values
// or if device_id is 0 it will fetch from all known devices // or if device_id is 0 it will fetch from all known devices
void EMSESP::fetch_device_values(const uint8_t device_id) { void EMSESP::fetch_device_values(const uint8_t device_id) {
@@ -423,7 +418,7 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
if (emsdevice) { if (emsdevice) {
if (emsdevice->is_device_id(telegram->src)) { if (emsdevice->is_device_id(telegram->src)) {
found = emsdevice->handle_telegram(telegram); found = emsdevice->handle_telegram(telegram);
// check to see if we need to force an MQTT publish // check to see if we need to follow up after the telegram has been processed
if (found) { if (found) {
if (emsdevice->updated_values()) { if (emsdevice->updated_values()) {
emsdevice->publish_values(); // publish to MQTT if we explicitly have too emsdevice->publish_values(); // publish to MQTT if we explicitly have too

View File

@@ -123,8 +123,7 @@ class EMSESP {
static void console_commands(Shell & shell, unsigned int context); static void console_commands(Shell & shell, unsigned int context);
static void fetch_device_values(const uint8_t device_id); static void fetch_device_values(const uint8_t device_id = 0);
static void fetch_device_values();
private: private:
EMSESP() = delete; EMSESP() = delete;

View File

@@ -43,8 +43,6 @@ Mixing::Mixing(uint8_t device_type, uint8_t device_id, uint8_t product_id, const
register_telegram_type(0x00AB, F("MMStatusMessage"), true, std::bind(&Mixing::process_MMStatusMessage, this, _1)); register_telegram_type(0x00AB, F("MMStatusMessage"), true, std::bind(&Mixing::process_MMStatusMessage, this, _1));
register_telegram_type(0x00AC, F("MMSetMessage"), false, nullptr); register_telegram_type(0x00AC, F("MMSetMessage"), false, nullptr);
} }
Settings settings;
mqtt_format_ = settings.mqtt_format(); // single, nested or ha
// MQTT callbacks // MQTT callbacks
// register_mqtt_topic("cmd", std::bind(&Mixing::cmd, this, _1)); // register_mqtt_topic("cmd", std::bind(&Mixing::cmd, this, _1));
@@ -88,63 +86,43 @@ void Mixing::show_values(uuid::console::Shell & shell) {
// ideally we should group up all the mixing units together into a nested JSON but for now we'll send them individually // ideally we should group up all the mixing units together into a nested JSON but for now we'll send them individually
void Mixing::publish_values() { void Mixing::publish_values() {
DynamicJsonDocument doc(EMSESP_MAX_JSON_SIZE_SMALL); DynamicJsonDocument doc(EMSESP_MAX_JSON_SIZE_SMALL);
JsonObject rootMixing = doc.to<JsonObject>();
JsonObject dataMixing;
if (mqtt_format_ == Settings::MQTT_format::SINGLE) { switch (type_) {
switch (type_) { case Type::HC:
case Type::HC: doc["type"] = "hc";
rootMixing["type"] = "hc"; break;
break; case Type::WWC:
case Type::WWC: doc["type"] = "wwc";
rootMixing["type"] = "wwc"; break;
break; case Type::NONE:
case Type::NONE: default:
default: return;
return;
}
dataMixing = rootMixing;
} else {
char hc_name[10]; // hc{1-4}
if(type_ == Type::HC) {
strlcpy(hc_name, "hc", 10);
} else {
strlcpy(hc_name, "wwc", 10);
}
char s[3]; // for formatting strings
strlcat(hc_name, Helpers::itoa(s, hc_), 10);
dataMixing = rootMixing.createNestedObject(hc_name);
} }
if (flowTemp_ != EMS_VALUE_USHORT_NOTSET) { if (flowTemp_ != EMS_VALUE_USHORT_NOTSET) {
dataMixing["flowTemp"] = (float)flowTemp_ / 10; doc["flowTemp"] = (float)flowTemp_ / 10;
} }
if (pumpMod_ != EMS_VALUE_UINT_NOTSET) { if (pumpMod_ != EMS_VALUE_UINT_NOTSET) {
dataMixing["pumpMod"] = pumpMod_; doc["pumpMod"] = pumpMod_;
} }
if (status_ != EMS_VALUE_UINT_NOTSET) { if (status_ != EMS_VALUE_UINT_NOTSET) {
dataMixing["status"] = status_; doc["status"] = status_;
} }
if (flowSetTemp_ != EMS_VALUE_UINT_NOTSET) { if (flowSetTemp_ != EMS_VALUE_UINT_NOTSET) {
dataMixing["flowSetTemp"] = flowSetTemp_; doc["flowSetTemp"] = flowSetTemp_;
} }
#ifdef EMSESP_DEBUG #ifdef EMSESP_DEBUG
LOG_DEBUG(F("[DEBUG] Performing a mixing module publish")); LOG_DEBUG(F("[DEBUG] Performing a mixing module publish"));
#endif #endif
// if format is single, send immediately and quit char topic[30];
if (mqtt_format_ == Settings::MQTT_format::SINGLE) { char s[3]; // for formatting strings
char topic[30]; strlcpy(topic, "mixing_data", 30);
char s[3]; // for formatting strings strlcat(topic, Helpers::itoa(s, device_id() - 0x20 + 1), 30); // append hc to topic
strlcpy(topic, "mixing_data", 30); Mqtt::publish(topic, doc);
strlcat(topic, Helpers::itoa(s, device_id() - 0x20 + 1), 30); // append hc to topic
Mqtt::publish(topic, doc);
return;
}
Mqtt::publish("mixing_data", doc);
} }
// heating circuits 0x02D7, 0x02D8 etc... // heating circuits 0x02D7, 0x02D8 etc...

View File

@@ -63,7 +63,6 @@ class Mixing : public EMSdevice {
uint8_t status_ = EMS_VALUE_UINT_NOTSET; uint8_t status_ = EMS_VALUE_UINT_NOTSET;
uint8_t flowSetTemp_ = EMS_VALUE_UINT_NOTSET; uint8_t flowSetTemp_ = EMS_VALUE_UINT_NOTSET;
Type type_ = Type::NONE; Type type_ = Type::NONE;
uint8_t mqtt_format_; // single, nested or ha
}; };

View File

@@ -24,10 +24,11 @@ MAKE_PSTR_WORD(qos)
MAKE_PSTR_WORD(base) MAKE_PSTR_WORD(base)
MAKE_PSTR_WORD(heartbeat) MAKE_PSTR_WORD(heartbeat)
MAKE_PSTR_WORD(ip) MAKE_PSTR_WORD(ip)
MAKE_PSTR_WORD(port)
MAKE_PSTR_WORD(nested) MAKE_PSTR_WORD(nested)
MAKE_PSTR_WORD(single) MAKE_PSTR_WORD(single)
MAKE_PSTR_WORD(ha) MAKE_PSTR_WORD(ha)
MAKE_PSTR_WORD(my) MAKE_PSTR_WORD(custom)
MAKE_PSTR_WORD(publish_time) MAKE_PSTR_WORD(publish_time)
MAKE_PSTR_WORD(publish) MAKE_PSTR_WORD(publish)
MAKE_PSTR_WORD(connected) MAKE_PSTR_WORD(connected)
@@ -647,8 +648,8 @@ void Mqtt::console_commands(Shell & shell, unsigned int context) {
value = Settings::MQTT_format::NESTED; value = Settings::MQTT_format::NESTED;
} else if (arguments[0] == read_flash_string(F_(ha))) { } else if (arguments[0] == read_flash_string(F_(ha))) {
value = Settings::MQTT_format::HA; value = Settings::MQTT_format::HA;
} else if (arguments[0] == read_flash_string(F_(my))) { } else if (arguments[0] == read_flash_string(F_(custom))) {
value = Settings::MQTT_format::MY; value = Settings::MQTT_format::CUSTOM;
} else { } else {
shell.println(F("Must be single, nested or ha")); shell.println(F("Must be single, nested or ha"));
return; return;
@@ -658,7 +659,7 @@ void Mqtt::console_commands(Shell & shell, unsigned int context) {
shell.println(F("Please restart EMS-ESP")); shell.println(F("Please restart EMS-ESP"));
}, },
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> { [](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
return std::vector<std::string>{read_flash_string(F_(single)), read_flash_string(F_(nested)), read_flash_string(F_(ha)), read_flash_string(F_(my))}; return std::vector<std::string>{read_flash_string(F_(single)), read_flash_string(F_(nested)), read_flash_string(F_(ha)), read_flash_string(F_(custom))};
}); });
EMSESPShell::commands->add_command(ShellContext::MQTT, EMSESPShell::commands->add_command(ShellContext::MQTT,
@@ -725,6 +726,19 @@ void Mqtt::console_commands(Shell & shell, unsigned int context) {
} }
reconnect(); reconnect();
}); });
EMSESPShell::commands->add_command(ShellContext::MQTT,
CommandFlags::ADMIN,
flash_string_vector{F_(set), F_(port)},
flash_string_vector{F_(port_mandatory)},
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
Settings settings;
if (!arguments.empty()) {
settings.mqtt_port(atoi(arguments.front().c_str()));
settings.commit();
}
reconnect();
});
EMSESPShell::commands->add_command(ShellContext::MQTT, EMSESPShell::commands->add_command(ShellContext::MQTT,
CommandFlags::ADMIN, CommandFlags::ADMIN,
@@ -823,8 +837,8 @@ void Mqtt::console_commands(Shell & shell, unsigned int context) {
shell.printfln(F_(mqtt_format_fmt), F_(nested)); shell.printfln(F_(mqtt_format_fmt), F_(nested));
} else if (settings.mqtt_format() == Settings::MQTT_format::HA) { } else if (settings.mqtt_format() == Settings::MQTT_format::HA) {
shell.printfln(F_(mqtt_format_fmt), F_(ha)); shell.printfln(F_(mqtt_format_fmt), F_(ha));
} else if (settings.mqtt_format() == Settings::MQTT_format::MY) { } else if (settings.mqtt_format() == Settings::MQTT_format::CUSTOM) {
shell.printfln(F_(mqtt_format_fmt), F_(my)); shell.printfln(F_(mqtt_format_fmt), F_(custom));
} }
shell.printfln(F_(mqtt_heartbeat_fmt), settings.mqtt_heartbeat() ? F_(enabled) : F_(disabled)); shell.printfln(F_(mqtt_heartbeat_fmt), settings.mqtt_heartbeat() ? F_(enabled) : F_(disabled));
shell.printfln(F_(mqtt_publish_time_fmt), settings.mqtt_publish_time()); shell.printfln(F_(mqtt_publish_time_fmt), settings.mqtt_publish_time());

View File

@@ -274,7 +274,7 @@ void Sensors::publish_values() {
uint8_t i = 1; uint8_t i = 1;
for (const auto & device : devices_) { for (const auto & device : devices_) {
if (mqtt_format_ == Settings::MQTT_format::MY) { if (mqtt_format_ == Settings::MQTT_format::CUSTOM) {
char s[5]; char s[5];
doc[device.to_string()] = Helpers::render_value(s, device.temperature_c_, 2); doc[device.to_string()] = Helpers::render_value(s, device.temperature_c_, 2);
} else { } else {

View File

@@ -48,8 +48,8 @@
#define EMSESP_DEFAULT_TX_MODE 1 #define EMSESP_DEFAULT_TX_MODE 1
#define EMSESP_DEFAULT_MQTT_ENABLED true #define EMSESP_DEFAULT_MQTT_ENABLED true
#define EMSESP_DEFAULT_MQTT_BASE "home" #define EMSESP_DEFAULT_MQTT_BASE "home"
#define EMSESP_DEFAULT_MQTT_PORT 1884 #define EMSESP_DEFAULT_MQTT_PORT 1883
#define EMSESP_DEFAULT_MQTT_QOS 0 #define EMSESP_DEFAULT_MQTT_QOS 1
#define EMSESP_DEFAULT_MQTT_RETAIN false #define EMSESP_DEFAULT_MQTT_RETAIN false
#define EMSESP_DEFAULT_MQTT_FORMAT 2 // 2=nested #define EMSESP_DEFAULT_MQTT_FORMAT 2 // 2=nested
#define EMSESP_DEFAULT_MQTT_HEARTBEAT true #define EMSESP_DEFAULT_MQTT_HEARTBEAT true
@@ -148,7 +148,7 @@ class Settings {
uint8_t master_thermostat() const; uint8_t master_thermostat() const;
void master_thermostat(const uint8_t & master_thermostat); void master_thermostat(const uint8_t & master_thermostat);
enum MQTT_format : uint8_t { SINGLE = 1, NESTED, HA, MY }; enum MQTT_format : uint8_t { SINGLE = 1, NESTED, HA, CUSTOM };
uint8_t mqtt_format() const; uint8_t mqtt_format() const;
void mqtt_format(const uint8_t & mqtt_format); void mqtt_format(const uint8_t & mqtt_format);

View File

@@ -172,9 +172,9 @@ void Solar::process_SM100Status2(std::shared_ptr<const Telegram> telegram) {
* e.g. 30 00 FF 00 02 8E 00 00 00 00 00 00 06 C5 00 00 76 35 * e.g. 30 00 FF 00 02 8E 00 00 00 00 00 00 06 C5 00 00 76 35
*/ */
void Solar::process_SM100Energy(std::shared_ptr<const Telegram> telegram) { void Solar::process_SM100Energy(std::shared_ptr<const Telegram> telegram) {
telegram->read_value(energyLastHour_, 0); // last hour / 10 in Wh telegram->read_value32(energyLastHour_, 0); // last hour / 10 in Wh
telegram->read_value(energyToday_, 4); // todays in Wh telegram->read_value32(energyToday_, 4); // todays in Wh
telegram->read_value(energyTotal_, 8); // total / 10 in kWh telegram->read_value32(energyTotal_, 8); // total / 10 in kWh
} }
/* /*

View File

@@ -104,13 +104,13 @@ std::string Telegram::to_string(const uint8_t * telegram, uint8_t length) const
// if offset is 0, it takes the whole telegram. if it's for example 1 it'll show the 2nd data item and // if offset is 0, it takes the whole telegram. if it's for example 1 it'll show the 2nd data item and
// everything after it // everything after it
// returns -1 if out of bounds // returns -1 if out of bounds
int8_t Telegram::_getDataPosition(const uint8_t index) const { int8_t Telegram::_getDataPosition(const uint8_t index, const uint8_t size) const {
return ((index - offset) >= message_length) ? -1 : (index - offset); return ((index - offset + size - 1) >= message_length) ? -1 : (index - offset);
} }
// unsigned byte // unsigned byte
void Telegram::read_value(uint8_t & param, const uint8_t index) const { void Telegram::read_value(uint8_t & param, const uint8_t index) const {
int8_t pos = _getDataPosition(index); int8_t pos = _getDataPosition(index, sizeof(param));
if (pos < 0) { if (pos < 0) {
return; return;
} }
@@ -119,7 +119,7 @@ void Telegram::read_value(uint8_t & param, const uint8_t index) const {
// signed byte // signed byte
void Telegram::read_value(int8_t & param, const uint8_t index) const { void Telegram::read_value(int8_t & param, const uint8_t index) const {
int8_t pos = _getDataPosition(index); int8_t pos = _getDataPosition(index, sizeof(param));
if (pos < 0) { if (pos < 0) {
return; return;
} }
@@ -128,7 +128,7 @@ void Telegram::read_value(int8_t & param, const uint8_t index) const {
// unsigned short // unsigned short
void Telegram::read_value(uint16_t & param, const uint8_t index) const { void Telegram::read_value(uint16_t & param, const uint8_t index) const {
int8_t pos = _getDataPosition(index); int8_t pos = _getDataPosition(index, sizeof(param));
if (pos < 0) { if (pos < 0) {
return; return;
} }
@@ -145,7 +145,7 @@ void Telegram::read_value(uint16_t & param, const uint8_t index) const {
// signed short // signed short
void Telegram::read_value(int16_t & param, const uint8_t index) const { void Telegram::read_value(int16_t & param, const uint8_t index) const {
int8_t pos = _getDataPosition(index); int8_t pos = _getDataPosition(index, sizeof(param));
if (pos < 0) { if (pos < 0) {
return; return;
} }
@@ -160,9 +160,9 @@ void Telegram::read_value(int16_t & param, const uint8_t index) const {
param = value; param = value;
} }
// Long // Long 24 bit
void Telegram::read_value(uint32_t & param, const uint8_t index) const { void Telegram::read_value(uint32_t & param, const uint8_t index) const {
int8_t pos = _getDataPosition(index); int8_t pos = _getDataPosition(index, 3);
if (pos < 0) { if (pos < 0) {
return; return;
} }
@@ -170,9 +170,19 @@ void Telegram::read_value(uint32_t & param, const uint8_t index) const {
param = (uint32_t)((message_data[pos] << 16) + (message_data[pos + 1] << 8) + (message_data[pos + 2])); param = (uint32_t)((message_data[pos] << 16) + (message_data[pos + 1] << 8) + (message_data[pos + 2]));
} }
// Long 32 bit
void Telegram::read_value32(uint32_t & param, const uint8_t index) const {
int8_t pos = _getDataPosition(index, sizeof(param));
if (pos < 0) {
return;
}
param = (uint32_t)((message_data[pos] << 24) + (message_data[pos] << 16) + (message_data[pos + 1] << 8) + (message_data[pos + 2]));
}
// bit from an unsigned byte // bit from an unsigned byte
void Telegram::read_value(uint8_t & param, const uint8_t index, const uint8_t bit) const { void Telegram::read_value(uint8_t & param, const uint8_t index, const uint8_t bit) const {
int8_t pos = _getDataPosition(index); int8_t pos = _getDataPosition(index, sizeof(param));
if (pos < 0) { if (pos < 0) {
return; return;
} }
@@ -182,7 +192,7 @@ void Telegram::read_value(uint8_t & param, const uint8_t index, const uint8_t bi
// convert signed short to single 8 byte, for setpoint thermostat temperatures that don't store their temps in 2 bytes // convert signed short to single 8 byte, for setpoint thermostat temperatures that don't store their temps in 2 bytes
void Telegram::read_value8(int16_t & param, const uint8_t index) const { void Telegram::read_value8(int16_t & param, const uint8_t index) const {
int8_t pos = _getDataPosition(index); int8_t pos = _getDataPosition(index, 1);
if (pos < 0) { if (pos < 0) {
return; return;
} }
@@ -365,7 +375,7 @@ void TxService::loop() {
// sends a 1 byte poll which is our own device ID // sends a 1 byte poll which is our own device ID
void TxService::send_poll() { void TxService::send_poll() {
//OG_TRACE(F("Ack %02X"),ems_bus_id() ^ ems_mask()); //LOG_TRACE(F("Ack %02X"),ems_bus_id() ^ ems_mask());
EMSuart::send_poll(ems_bus_id() ^ ems_mask()); EMSuart::send_poll(ems_bus_id() ^ ems_mask());
} }

View File

@@ -76,6 +76,7 @@ class Telegram {
void read_value(uint16_t & param, const uint8_t index) const; void read_value(uint16_t & param, const uint8_t index) const;
void read_value(uint32_t & param, const uint8_t index) const; void read_value(uint32_t & param, const uint8_t index) const;
void read_value32(uint32_t & param, const uint8_t index) const;
void read_value(uint8_t & param, const uint8_t index, const uint8_t bit) const; void read_value(uint8_t & param, const uint8_t index, const uint8_t bit) const;
void read_value(uint8_t & param, const uint8_t index) const; void read_value(uint8_t & param, const uint8_t index) const;
void read_value(int16_t & param, const uint8_t index) const; void read_value(int16_t & param, const uint8_t index) const;
@@ -83,7 +84,7 @@ class Telegram {
void read_value(int8_t & param, const uint8_t index) const; void read_value(int8_t & param, const uint8_t index) const;
private: private:
int8_t _getDataPosition(const uint8_t index) const; int8_t _getDataPosition(const uint8_t index, const uint8_t size) const;
}; };
class EMSbus { class EMSbus {

View File

@@ -135,6 +135,16 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
} else { } else {
LOG_DEBUG(F("Registering new thermostat with device ID 0x%02X"), device_id); LOG_DEBUG(F("Registering new thermostat with device ID 0x%02X"), device_id);
} }
// for the thermostat, go a query all the heating circuits. This is only done once. The automatic fetch will from now on
// only update the active heating circuits
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
EMSESP::send_read_request(set_typeids[i], device_id);
}
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
EMSESP::send_read_request(monitor_typeids[i], device_id);
}
} }
// for the master thermostat initialize the MQTT subscribes // for the master thermostat initialize the MQTT subscribes
@@ -221,6 +231,7 @@ void Thermostat::thermostat_cmd(const char * message) {
LOG_DEBUG(F("MQTT error: payload %s, error %s"), message, error.c_str()); LOG_DEBUG(F("MQTT error: payload %s, error %s"), message, error.c_str());
return; return;
} }
for (const auto & hc : heating_circuits_) { for (const auto & hc : heating_circuits_) {
char hc_name[6], s[3]; // hc{1-4} char hc_name[6], s[3]; // hc{1-4}
strlcpy(hc_name, "hc", 6); strlcpy(hc_name, "hc", 6);
@@ -230,7 +241,7 @@ void Thermostat::thermostat_cmd(const char * message) {
std::string mode = doc[hc_name]["mode"]; // first check mode std::string mode = doc[hc_name]["mode"]; // first check mode
set_mode(mode, hc_num); set_mode(mode, hc_num);
} }
if (float f = doc[hc_name]["temp"]) { if (float f = doc[hc_name]["temp"]) {
set_temperature(f, HeatingCircuit::Mode::AUTO, hc_num); set_temperature(f, HeatingCircuit::Mode::AUTO, hc_num);
} }
if (float f = doc[hc_name]["nighttemp"]) { if (float f = doc[hc_name]["nighttemp"]) {
@@ -255,10 +266,10 @@ void Thermostat::thermostat_cmd(const char * message) {
set_temperature(f, HeatingCircuit::Mode::HOLIDAY, hc_num); set_temperature(f, HeatingCircuit::Mode::HOLIDAY, hc_num);
} }
if (float f = doc[hc_name]["remotetemp"]) { if (float f = doc[hc_name]["remotetemp"]) {
if(f > 100 || f < 0) { if (f > 100 || f < 0) {
hc->remotetemp = EMS_VALUE_SHORT_NOTSET; hc->remotetemp = EMS_VALUE_SHORT_NOTSET;
} else { } else {
hc->remotetemp = (uint16_t) (f * 10); hc->remotetemp = (uint16_t)(f * 10);
} }
} }
} }
@@ -376,7 +387,7 @@ void Thermostat::thermostat_cmd_mode(const char * message) {
set_mode(s, DEFAULT_HEATING_CIRCUIT); set_mode(s, DEFAULT_HEATING_CIRCUIT);
} }
// this function is called post and telegram process call // this function is called post the telegram handler function has been executed
// we check if any of the thermostat values have changed and then republish if necessary // we check if any of the thermostat values have changed and then republish if necessary
bool Thermostat::updated_values() { bool Thermostat::updated_values() {
// only publish on the master thermostat // only publish on the master thermostat
@@ -420,8 +431,9 @@ void Thermostat::publish_values() {
JsonObject rootThermostat = doc.to<JsonObject>(); JsonObject rootThermostat = doc.to<JsonObject>();
JsonObject dataThermostat; JsonObject dataThermostat;
// optional, add external temp. I don't think anyone (except MichaelDvP) actually is interested in this // add external temp
if ((flags == EMS_DEVICE_FLAG_RC35 || flags == EMS_DEVICE_FLAG_RC30_1) && (mqtt_format_ == Settings::MQTT_format::SINGLE || mqtt_format_ == Settings::MQTT_format::MY)) { if ((flags == EMS_DEVICE_FLAG_RC35 || flags == EMS_DEVICE_FLAG_RC30_1)
&& (mqtt_format_ == Settings::MQTT_format::SINGLE || mqtt_format_ == Settings::MQTT_format::CUSTOM)) {
if (datetime_.size()) { if (datetime_.size()) {
rootThermostat["time"] = datetime_.c_str(); rootThermostat["time"] = datetime_.c_str();
} }
@@ -434,15 +446,12 @@ void Thermostat::publish_values() {
if (tempsensor2 != EMS_VALUE_USHORT_NOTSET) { if (tempsensor2 != EMS_VALUE_USHORT_NOTSET) {
rootThermostat["inttemp2"] = (float)tempsensor2 / 10; rootThermostat["inttemp2"] = (float)tempsensor2 / 10;
} }
if (ibaCalIntTemperature != EMS_VALUE_INT_NOTSET) { if (ibaCalIntTemperature != EMS_VALUE_INT_NOTSET) {
rootThermostat["intoffset"] = (float)ibaCalIntTemperature / 2; rootThermostat["intoffset"] = (float)ibaCalIntTemperature / 2;
} }
if (ibaMinExtTemperature != EMS_VALUE_INT_NOTSET) { if (ibaMinExtTemperature != EMS_VALUE_INT_NOTSET) {
rootThermostat["minexttemp"] = (float)ibaMinExtTemperature; // min ext temp for heating curve, in deg. rootThermostat["minexttemp"] = (float)ibaMinExtTemperature; // min ext temp for heating curve, in deg.
} }
if (ibaBuildingType != EMS_VALUE_UINT_NOTSET) { if (ibaBuildingType != EMS_VALUE_UINT_NOTSET) {
if (ibaBuildingType == 0) { if (ibaBuildingType == 0) {
rootThermostat["building"] = "light"; rootThermostat["building"] = "light";
@@ -495,6 +504,7 @@ void Thermostat::publish_values() {
if (hc->setpoint_roomTemp != EMS_VALUE_SHORT_NOTSET) { if (hc->setpoint_roomTemp != EMS_VALUE_SHORT_NOTSET) {
dataThermostat["seltemp"] = Helpers::round2((float)hc->setpoint_roomTemp / setpoint_temp_divider); dataThermostat["seltemp"] = Helpers::round2((float)hc->setpoint_roomTemp / setpoint_temp_divider);
} }
if (hc->curr_roomTemp != EMS_VALUE_SHORT_NOTSET && hc->curr_roomTemp != EMS_VALUE_USHORT_NOTSET) { if (hc->curr_roomTemp != EMS_VALUE_SHORT_NOTSET && hc->curr_roomTemp != EMS_VALUE_USHORT_NOTSET) {
dataThermostat["currtemp"] = Helpers::round2((float)hc->curr_roomTemp / curr_temp_divider); dataThermostat["currtemp"] = Helpers::round2((float)hc->curr_roomTemp / curr_temp_divider);
} }
@@ -525,7 +535,8 @@ void Thermostat::publish_values() {
dataThermostat["designtemp"] = hc->designtemp; dataThermostat["designtemp"] = hc->designtemp;
} }
if (hc->mode != EMS_VALUE_UINT_NOTSET) { // when using HA always send the mode otherwise it'll break the component/widget and report an error
if ((hc->mode != EMS_VALUE_UINT_NOTSET) || (mqtt_format_ == Settings::MQTT_format::HA)) {
uint8_t hc_mode = hc->get_mode(flags); uint8_t hc_mode = hc->get_mode(flags);
// if we're sending to HA the only valid mode types are heat, auto and off // if we're sending to HA the only valid mode types are heat, auto and off
if (mqtt_format_ == Settings::MQTT_format::HA) { if (mqtt_format_ == Settings::MQTT_format::HA) {
@@ -574,7 +585,7 @@ void Thermostat::publish_values() {
Mqtt::publish("thermostat_data", doc); Mqtt::publish("thermostat_data", doc);
} else if (mqtt_format_ == Settings::MQTT_format::HA) { } else if (mqtt_format_ == Settings::MQTT_format::HA) {
Mqtt::publish("homeassistant/climate/ems-esp/state", doc); Mqtt::publish("homeassistant/climate/ems-esp/state", doc);
} else if (mqtt_format_ == Settings::MQTT_format::MY) { } else if (mqtt_format_ == Settings::MQTT_format::CUSTOM) {
Mqtt::publish("thermostat_data", doc); Mqtt::publish("thermostat_data", doc);
} }
} }
@@ -1239,7 +1250,6 @@ void Thermostat::set_mode(const uint8_t mode, const uint8_t hc_num) {
write_command(set_typeids[hc->hc_num() - 1], offset, set_mode_value, validate_typeid); write_command(set_typeids[hc->hc_num() - 1], offset, set_mode_value, validate_typeid);
} }
// Set the temperature of the thermostat // Set the temperature of the thermostat
void Thermostat::set_temperature(const float temperature, const uint8_t mode, const uint8_t hc_num) { void Thermostat::set_temperature(const float temperature, const uint8_t mode, const uint8_t hc_num) {
if (can_write()) { if (can_write()) {

View File

@@ -246,4 +246,4 @@ class Thermostat : public EMSdevice {
} // namespace emsesp } // namespace emsesp
#endif #endif

View File

@@ -81,7 +81,7 @@ void EMSuart::start(uint8_t tx_mode) {
restart(); restart();
return; return;
} }
tx_mode_ = tx_mode; tx_mode_ = tx_mode;
uart_config_t uart_config = { uart_config_t uart_config = {
.baud_rate = EMSUART_BAUD, .baud_rate = EMSUART_BAUD,
.data_bits = UART_DATA_8_BITS, .data_bits = UART_DATA_8_BITS,
@@ -89,18 +89,18 @@ void EMSuart::start(uint8_t tx_mode) {
.stop_bits = UART_STOP_BITS_1, .stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
}; };
ESP_ERROR_CHECK(uart_param_config(EMSUART_UART, &uart_config)); ESP_ERROR_CHECK(uart_param_config(EMSUART_UART, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(EMSUART_UART, EMSUART_TXPIN, EMSUART_RXPIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); ESP_ERROR_CHECK(uart_set_pin(EMSUART_UART, EMSUART_TXPIN, EMSUART_RXPIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
EMS_UART.int_ena.val = 0; // disable all intr. EMS_UART.int_ena.val = 0; // disable all intr.
EMS_UART.int_clr.val = 0xFFFFFFFF; // clear all intr. flags EMS_UART.int_clr.val = 0xFFFFFFFF; // clear all intr. flags
EMS_UART.idle_conf.tx_brk_num = 11; // breaklength 11 bit EMS_UART.idle_conf.tx_brk_num = 11; // breaklength 11 bit
EMS_UART.idle_conf.rx_idle_thrhd = 256; EMS_UART.idle_conf.rx_idle_thrhd = 256;
drop_next_rx = true; drop_next_rx = true;
buf_handle = xRingbufferCreate(128, RINGBUF_TYPE_NOSPLIT); 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)); 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, 12, NULL); xTaskCreate(emsuart_recvTask, "emsuart_recvTask", 2048, NULL, 12, NULL);
EMS_UART.int_ena.brk_det = 1; // activate only break EMS_UART.int_ena.brk_det = 1; // activate only break
} }
/* /*
@@ -114,9 +114,9 @@ void EMSuart::stop() {
* Restart Interrupt * Restart Interrupt
*/ */
void EMSuart::restart() { void EMSuart::restart() {
if (EMS_UART.int_raw.brk_det) { if (EMS_UART.int_raw.brk_det) {
EMS_UART.int_clr.brk_det = 1; // clear flag EMS_UART.int_clr.brk_det = 1; // clear flag
drop_next_rx = true; // and drop first frame drop_next_rx = true; // and drop first frame
} }
EMS_UART.int_ena.brk_det = 1; // activate only break EMS_UART.int_ena.brk_det = 1; // activate only break
}; };

View File

@@ -16,6 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/*
* ESP32 UART port by @ArwedL and improved by @MichaelDvP. See https://github.com/proddy/EMS-ESP/issues/380
*/
#ifndef EMSESP_EMSUART_H #ifndef EMSESP_EMSUART_H
#define EMSESP_EMSUART_H #define EMSESP_EMSUART_H
@@ -31,7 +36,7 @@
#define EMSUART_UART UART_NUM_2 // on the ESP32 we're using UART2 #define EMSUART_UART UART_NUM_2 // on the ESP32 we're using UART2
#define EMS_UART UART2 // for intr setting #define EMS_UART UART2 // for intr setting
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit #define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
// customize the GPIO pins for RX and TX here // customize the GPIO pins for RX and TX here
#define EMSUART_RXPIN 23 // 17 is UART2 RX. Use 23 for D7 on a Wemos D1-32 mini for backwards compatabilty #define EMSUART_RXPIN 23 // 17 is UART2 RX. Use 23 for D7 on a Wemos D1-32 mini for backwards compatabilty

View File

@@ -38,8 +38,8 @@ bool drop_next_rx = true;
// Important: must not use ICACHE_FLASH_ATTR // Important: must not use ICACHE_FLASH_ATTR
// //
void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) { void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
static uint8_t length = 0;
// static bool rx_idle_ = true; // static bool rx_idle_ = true;
static uint8_t length = 0;
static uint8_t uart_buffer[EMS_MAXBUFFERSIZE + 2]; static uint8_t uart_buffer[EMS_MAXBUFFERSIZE + 2];
/* /*
@@ -62,7 +62,7 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
*/ */
// BREAK detection = End of EMS data block // BREAK detection = End of EMS data block
if (USIS(EMSUART_UART) & ((1 << UIBD))) { if (USIS(EMSUART_UART) & ((1 << UIBD))) {
length = 0; length = 0;
while ((USS(EMSUART_UART) >> USRXC) & 0xFF) { while ((USS(EMSUART_UART) >> USRXC) & 0xFF) {
uint8_t rx = USF(EMSUART_UART); uint8_t rx = USF(EMSUART_UART);
if (length < EMS_MAXBUFFERSIZE) { if (length < EMS_MAXBUFFERSIZE) {
@@ -77,7 +77,7 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
if (!drop_next_rx) { if (!drop_next_rx) {
pEMSRxBuf->length = length; pEMSRxBuf->length = length;
os_memcpy((void *)pEMSRxBuf->buffer, (void *)&uart_buffer, pEMSRxBuf->length); // copy data into transfer buffer, including the BRK 0x00 at the end os_memcpy((void *)pEMSRxBuf->buffer, (void *)&uart_buffer, pEMSRxBuf->length); // copy data into transfer buffer, including the BRK 0x00 at the end
// rx_idle_ = true; // check set the status flag stating BRK has been received and we can start a new package // rx_idle_ = true; // check set the status flag stating BRK has been received and we can start a new package
} }
drop_next_rx = false; drop_next_rx = false;
ETS_UART_INTR_ENABLE(); // re-enable UART interrupts ETS_UART_INTR_ENABLE(); // re-enable UART interrupts

View File

@@ -36,7 +36,7 @@
#define EMS_TXMODE_DEFAULT 1 #define EMS_TXMODE_DEFAULT 1
#define EMS_TXMODE_EMSPLUS 2 #define EMS_TXMODE_EMSPLUS 2
#define EMS_TXMODE_HT3 3 #define EMS_TXMODE_HT3 3
#define EMS_TXMODE_NEW 4 // for michael #define EMS_TXMODE_NEW 4 // for michael's testing
// LEGACY // LEGACY
#define EMSUART_BIT_TIME 104 // bit time @9600 baud #define EMSUART_BIT_TIME 104 // bit time @9600 baud

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "2.0.0a10" #define EMSESP_APP_VERSION "2.0.0a11"