From b5ae84704819b6f1237eb6be2d2ff61e17f45206 Mon Sep 17 00:00:00 2001 From: proddy Date: Fri, 22 Mar 2019 17:21:17 +0100 Subject: [PATCH] SM10 MQTT support --- src/ems-esp.ino | 33 ++++++++++++++ src/ems.cpp | 117 ++++++++++++++++++++++++------------------------ src/ems.h | 3 +- src/my_config.h | 8 ++++ 4 files changed, 102 insertions(+), 59 deletions(-) diff --git a/src/ems-esp.ino b/src/ems-esp.ino index 5a3323e07..aacaf533b 100644 --- a/src/ems-esp.ino +++ b/src/ems-esp.ino @@ -396,6 +396,7 @@ void showInfo() { _renderFloatValue(" Collector temperature", "C", EMS_Other.SM10collectorTemp); _renderFloatValue(" Bottom temperature", "C", EMS_Other.SM10bottomTemp); _renderIntValue(" Pump modulation", "%", EMS_Other.SM10pumpModulation); + _renderBoolValue(" Pump active", EMS_Other.SM10pump); } myDebug(""); // newline @@ -486,6 +487,7 @@ void publishValues(bool force) { static uint8_t last_boilerActive = 0xFF; // for remembering last setting of the tap water or heating on/off static uint32_t previousBoilerPublishCRC = 0; // CRC check for boiler values static uint32_t previousThermostatPublishCRC = 0; // CRC check for thermostat values + static uint32_t previousOtherPublishCRC = 0; // CRC check for other values (e.g. SM10) JsonObject rootBoiler = doc.to(); @@ -595,6 +597,36 @@ void publishValues(bool force) { myESP.mqttPublish(TOPIC_THERMOSTAT_DATA, data); } } + + // handle the other values separately + // For SM10 Solar Module + if (EMS_Other.SM10) { + // build new json object + doc.clear(); + JsonObject rootSM10 = doc.to(); + + rootSM10[SM10_COLLECTORTEMP] = _float_to_char(s, EMS_Other.SM10collectorTemp); + rootSM10[SM10_BOTTOMTEMP] = _float_to_char(s, EMS_Other.SM10bottomTemp); + rootSM10[SM10_PUMPMODULATION] = _int_to_char(s, EMS_Other.SM10pumpModulation); + rootSM10[SM10_PUMP] = _bool_to_char(s, EMS_Other.SM10pump); + + data[0] = '\0'; // reset data for next package + serializeJson(doc, data, sizeof(data)); + + // calculate new CRC + crc.reset(); + for (size_t i = 0; i < measureJson(doc) - 1; i++) { + crc.update(data[i]); + } + fchecksum = crc.finalize(); + if ((previousOtherPublishCRC != fchecksum) || force) { + previousOtherPublishCRC = fchecksum; + myDebugLog("Publishing SM10 data via MQTT"); + + // send values via MQTT + myESP.mqttPublish(TOPIC_SM10_DATA, data); + } + } } // sets the shower timer on/off @@ -1387,6 +1419,7 @@ void loop() { myESP.loop(); // check Dallas sensors, every 2 seconds + // these values are published to MQTT seperately via the timer publishSensorValuesTimer if (EMSESP_Status.dallas_sensors != 0) { ds18.loop(); } diff --git a/src/ems.cpp b/src/ems.cpp index f71be507d..4a2bbc025 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -238,6 +238,7 @@ void ems_init() { EMS_Other.SM10collectorTemp = EMS_VALUE_FLOAT_NOTSET; // collector temp from SM10 EMS_Other.SM10bottomTemp = EMS_VALUE_FLOAT_NOTSET; // bottom temp from SM10 EMS_Other.SM10pumpModulation = EMS_VALUE_INT_NOTSET; // modulation solar pump SM10 + EMS_Other.SM10pump = EMS_VALUE_INT_NOTSET; // pump active // calculated values EMS_Boiler.tapwaterActive = EMS_VALUE_INT_NOTSET; // Hot tap water is on/off @@ -1143,6 +1144,51 @@ void _process_RCOutdoorTempMessage(uint8_t src, uint8_t * data, uint8_t length) // add support here if you're reading external sensors } +/* + * SM10Monitor - type 0x97 + */ +void _process_SM10Monitor(uint8_t src, uint8_t * data, uint8_t length) { + EMS_Other.SM10collectorTemp = _toFloat(2, data); // collector temp from SM10 + EMS_Other.SM10bottomTemp = _toFloat(5, data); // bottom temp from SM10 + EMS_Other.SM10pumpModulation = data[4]; // modulation solar pump + EMS_Other.SM10pump = bitRead(data[6], 1); // active if bit 1 is set (to 1) + + EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT +} + +/** + * UBASetPoint 0x1A + */ +void _process_SetPoints(uint8_t src, uint8_t * data, uint8_t length) { + /* + if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) { + if (length != 0) { + uint8_t setpoint = data[0]; + uint8_t hk_power = data[1]; + uint8_t ww_power = data[2]; + myDebug(" SetPoint=%d, hk_power=%d, ww_power=%d", setpoint, hk_power, ww_power); + } + } + */ +} + +/** + * process_RCTime - type 0x06 - date and time from a thermostat - 14 bytes long + * common for all thermostats + */ +void _process_RCTime(uint8_t src, uint8_t * data, uint8_t length) { + if ((EMS_Thermostat.model_id == EMS_MODEL_EASY) || (EMS_Thermostat.model_id == EMS_MODEL_BOSCHEASY)) { + return; // not supported + } + + EMS_Thermostat.hour = data[2]; + EMS_Thermostat.minute = data[4]; + EMS_Thermostat.second = data[5]; + EMS_Thermostat.day = data[3]; + EMS_Thermostat.month = data[1]; + EMS_Thermostat.year = data[0]; +} + /** * type 0x02 - get the firmware version and type of an EMS device * look up known devices via the product id and setup if not already set @@ -1272,48 +1318,6 @@ void _process_Version(uint8_t src, uint8_t * data, uint8_t length) { } } -/* - * SM10Monitor - type 0x97 - */ -void _process_SM10Monitor(uint8_t src, uint8_t * data, uint8_t length) { - EMS_Other.SM10collectorTemp = _toFloat(2, data); // collector temp from SM10 - EMS_Other.SM10bottomTemp = _toFloat(5, data); // bottom temp from SM10 - EMS_Other.SM10pumpModulation = data[4]; // modulation solar pump -} - -/** - * UBASetPoint 0x1A - */ -void _process_SetPoints(uint8_t src, uint8_t * data, uint8_t length) { - /* - if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) { - if (length != 0) { - uint8_t setpoint = data[0]; - uint8_t hk_power = data[1]; - uint8_t ww_power = data[2]; - myDebug(" SetPoint=%d, hk_power=%d, ww_power=%d", setpoint, hk_power, ww_power); - } - } - */ -} - -/** - * process_RCTime - type 0x06 - date and time from a thermostat - 14 bytes long - * common for all thermostats - */ -void _process_RCTime(uint8_t src, uint8_t * data, uint8_t length) { - if ((EMS_Thermostat.model_id == EMS_MODEL_EASY) || (EMS_Thermostat.model_id == EMS_MODEL_BOSCHEASY)) { - return; // not supported - } - - EMS_Thermostat.hour = data[2]; - EMS_Thermostat.minute = data[4]; - EMS_Thermostat.second = data[5]; - EMS_Thermostat.day = data[3]; - EMS_Thermostat.month = data[1]; - EMS_Thermostat.year = data[0]; -} - /* * Figure out the boiler and thermostat types */ @@ -1486,9 +1490,9 @@ char * ems_getThermostatDescription(char * buffer) { if (!ems_getThermostatEnabled()) { strlcpy(buffer, "", size); } else { - // find the boiler details - int i = 0; - bool found = false; + int i = 0; + bool found = false; + char tmp[6] = {0}; // scan through known ID types while (i < _Thermostat_Types_max) { @@ -1498,16 +1502,15 @@ char * ems_getThermostatDescription(char * buffer) { } i++; } + if (found) { strlcpy(buffer, Thermostat_Types[i].model_string, size); } else { - strlcpy(buffer, "Generic Type", size); + strlcpy(buffer, "TypeID: 0x", size); + strlcat(buffer, _hextoa(EMS_Thermostat.type_id, tmp), size); } - char tmp[6] = {0}; - strlcat(buffer, " [Type ID: 0x", size); - strlcat(buffer, _hextoa(EMS_Thermostat.type_id, tmp), size); - strlcat(buffer, "] Product ID:", size); + strlcat(buffer, " Product ID:", size); strlcat(buffer, itoa(EMS_Thermostat.product_id, tmp, 10), size); strlcat(buffer, " Version:", size); strlcat(buffer, EMS_Thermostat.version, size); @@ -1524,9 +1527,9 @@ char * ems_getBoilerDescription(char * buffer) { if (!ems_getBoilerEnabled()) { strlcpy(buffer, "", size); } else { - // find the boiler details - int i = 0; - bool found = false; + int i = 0; + bool found = false; + char tmp[6] = {0}; // scan through known ID types while (i < _Boiler_Types_max) { @@ -1539,13 +1542,11 @@ char * ems_getBoilerDescription(char * buffer) { if (found) { strlcpy(buffer, Boiler_Types[i].model_string, size); } else { - strlcpy(buffer, "Generic Type", size); + strlcpy(buffer, "TypeID: 0x", size); + strlcat(buffer, _hextoa(EMS_Boiler.type_id, tmp), size); } - char tmp[6] = {0}; - strlcat(buffer, " [Type ID: 0x", size); - strlcat(buffer, _hextoa(EMS_Boiler.type_id, tmp), size); - strlcat(buffer, "] Product ID:", size); + strlcat(buffer, " Product ID:", size); strlcat(buffer, itoa(EMS_Boiler.product_id, tmp, 10), size); strlcat(buffer, " Version:", size); strlcat(buffer, EMS_Boiler.version, size); diff --git a/src/ems.h b/src/ems.h index 4a27395ff..ddee54043 100644 --- a/src/ems.h +++ b/src/ems.h @@ -232,6 +232,7 @@ typedef struct { float SM10collectorTemp; // collector temp from SM10 float SM10bottomTemp; // bottom temp from SM10 uint8_t SM10pumpModulation; // modulation solar pump + uint8_t SM10pump; // pump active } _EMS_Other; // Thermostat data @@ -308,7 +309,7 @@ void ems_startupTelegrams(); // private functions uint8_t _crcCalculator(uint8_t * data, uint8_t len); -void _processType(_EMS_RxTelegram *EMS_RxTelegram); +void _processType(_EMS_RxTelegram * EMS_RxTelegram); void _debugPrintPackage(const char * prefix, _EMS_RxTelegram * EMS_RxTelegram, const char * color); void _ems_clearTxData(); int _ems_findBoilerModel(uint8_t model_id); diff --git a/src/my_config.h b/src/my_config.h index 9ff43a405..8f55c891f 100644 --- a/src/my_config.h +++ b/src/my_config.h @@ -39,6 +39,13 @@ #define TOPIC_BOILER_CMD_WWTEMP "boiler_cmd_wwtemp" // for received boiler wwtemp changes via MQTT #define TOPIC_BOILER_CMD_COMFORT "boiler_cmd_comfort" // for received boiler ww comfort setting via MQTT +// MQTT for SM10 Solar Module +#define TOPIC_SM10_DATA "sm10_data" // topic name +#define SM10_COLLECTORTEMP "temp" // collector temp +#define SM10_BOTTOMTEMP "bottomtemp" // bottom temp +#define SM10_PUMPMODULATION "pumpmodulation" // pump modulation +#define SM10_PUMP "pump" // pump active + // shower time #define TOPIC_SHOWERTIME "showertime" // for sending shower time results #define TOPIC_SHOWER_TIMER "shower_timer" // toggle switch for enabling the shower logic @@ -49,6 +56,7 @@ #define TOPIC_EXTERNAL_SENSORS "sensors" // for sending sensor values to MQTT #define PAYLOAD_EXTERNAL_SENSORS "temp_%d" // for formatting the payload for each external dallas sensor + //////////////////////////////////////////////////////////////////////////////////////////////////// // THESE DEFAULT VALUES CAN ALSO BE SET AND STORED WITHTIN THE APPLICATION (see 'set' command) // ////////////////////////////////////////////////////////////////////////////////////////////////////