mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
Merge branch 'v2 a11' of https://github.com/proddy/EMS-ESP into v2
This commit is contained in:
@@ -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>")
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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...
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
26
src/mqtt.cpp
26
src/mqtt.cpp
@@ -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());
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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()) {
|
||||||
|
|||||||
@@ -246,4 +246,4 @@ class Thermostat : public EMSdevice {
|
|||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "2.0.0a10"
|
#define EMSESP_APP_VERSION "2.0.0a11"
|
||||||
|
|||||||
Reference in New Issue
Block a user