From df69b70764ea9ca357bb5b2314b6ee56c617082f Mon Sep 17 00:00:00 2001 From: Charles Date: Fri, 14 Aug 2020 19:43:02 +0200 Subject: [PATCH 1/7] Added debug tasmota compliant --- lib/LibTeleinfo/src/LibTeleinfo.h | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/LibTeleinfo/src/LibTeleinfo.h b/lib/LibTeleinfo/src/LibTeleinfo.h index 45a467320..01c603c83 100755 --- a/lib/LibTeleinfo/src/LibTeleinfo.h +++ b/lib/LibTeleinfo/src/LibTeleinfo.h @@ -46,16 +46,24 @@ // debugging, this should not interfere with main sketch or other // libraries #ifdef TI_DEBUG - #ifdef ESP8266 - #define TI_Debug(x) Serial1.print(x) - #define TI_Debugln(x) Serial1.println(x) - #define TI_Debugf(...) Serial1.printf(__VA_ARGS__) - #define TI_Debugflush Serial1.flush + // Tasmota build + #ifdef CODE_IMAGE_STR + #define TI_Debug(x) AddLog_P2(LOG_LEVEL_DEBUG, x); + #define TI_Debugln(x) AddLog_P2(LOG_LEVEL_DEBUG, x); + #define TI_Debugf(...) AddLog_P2(LOG_LEVEL_DEBUG, __VA_ARGS__); + #define TI_Debugflush {} #else - #define TI_Debug(x) Serial.print(x) - #define TI_Debugln(x) Serial.println(x) - #define TI_Debugf(...) Serial.printf(__VA_ARGS__) - #define TI_Debugflush Serial.flush + #ifdef ESP8266 + #define TI_Debug(x) Serial1.print(x) + #define TI_Debugln(x) Serial1.println(x) + #define TI_Debugf(...) Serial1.printf(__VA_ARGS__) + #define TI_Debugflush Serial1.flush + #else + #define TI_Debug(x) Serial.print(x) + #define TI_Debugln(x) Serial.println(x) + #define TI_Debugf(...) Serial.printf(__VA_ARGS__) + #define TI_Debugflush Serial.flush + #endif #endif #else #define TI_Debug(x) {} From 86225d524363977758714f2d8faf9a4fe7a6f901 Mon Sep 17 00:00:00 2001 From: Charles Date: Fri, 14 Aug 2020 19:43:30 +0200 Subject: [PATCH 2/7] fix bug when checksum was space --- lib/LibTeleinfo/src/LibTeleinfo.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/LibTeleinfo/src/LibTeleinfo.cpp b/lib/LibTeleinfo/src/LibTeleinfo.cpp index 3d2f9f084..3d427676b 100644 --- a/lib/LibTeleinfo/src/LibTeleinfo.cpp +++ b/lib/LibTeleinfo/src/LibTeleinfo.cpp @@ -778,14 +778,13 @@ ValueList * TInfo::checkLine(char * pline) return NULL; p = &buff[0]; - i = len + 1 ; sep = 0; // Get our own working copy and in the // meantime, calculate separator count for // standard mode (to know if timestamped data) - while (i--) { - // count separator - if (*pline == _separator) { + for (i=0 ; i=3){ hasts = true; From f0bb4f10faf617deec70f37582529f42ad594fbf Mon Sep 17 00:00:00 2001 From: Charles Date: Fri, 14 Aug 2020 19:46:52 +0200 Subject: [PATCH 3/7] add setOption103 --- tasmota/CHANGELOG.md | 1 + tasmota/settings.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 29b1d3e43..28c9e0042 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -8,6 +8,7 @@ - Add Zigbee options to ``ZbSend`` ``Config`` and ``ReadCondig`` - Add command ``Restart 2`` to halt system. Needs hardware reset or power cycle to restart (#9046) - Add command ``SetOption102 0/1`` to switch between Teleinfo French Metering mode, legacy 1200 bps (0) or Linky standard 9600 bps (1) +- Add command ``SetOption103 0/1`` to enable Teleinfo telemetry into Tasmota Energy MQTT (0) or Teleinfo only (1) in this case MQTT will send RAW Teleinfo telemetry on each frame received and not into Tasmota energy calculation telemetry. ### 8.4.0 20200730 diff --git a/tasmota/settings.h b/tasmota/settings.h index 7241efc33..2b13128e4 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -122,7 +122,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t remove_zbreceived : 1; // bit 18 (v8.3.1.7) - SetOption100 - Remove ZbReceived form JSON message uint32_t zb_index_ep : 1; // bit 19 (v8.3.1.7) - SetOption101 - Add the source endpoint as suffix to attributes, ex `Power3` instead of `Power` if sent from endpoint 3 uint32_t teleinfo_baudrate : 1; // bit 20 (v8.4.0.1) - SetOption102 - Set Baud rate for Teleinfo communication (0 = 1200 or 1 = 9600) - uint32_t spare21 : 1; + uint32_t teleinfo_rawdata : 1; // bit 21 (v8.4.0.1) - SetOption103 - enable Teleinfo + Tasmota Energy device (0) or Teleinfo raw data only (1) uint32_t spare22 : 1; uint32_t spare23 : 1; uint32_t spare24 : 1; From 6410f9e8d0aaaa8a4c6b031aeb100dea40c0a71e Mon Sep 17 00:00:00 2001 From: Charles Date: Fri, 14 Aug 2020 19:47:13 +0200 Subject: [PATCH 4/7] add setOption103 stuff --- tasmota/xnrg_15_teleinfo.ino | 156 +++++++++++++++++++++++------------ 1 file changed, 105 insertions(+), 51 deletions(-) diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index 9da74ddd2..79dbcea7c 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -27,6 +27,7 @@ * {"NAME":"Denky (Teleinfo)","GPIO":[1,1,1,1,5664,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1376,1,1,0,0,0,0,1,5632,1,1,1,0,0,1],"FLAG":0,"BASE":1} * * Denky (aka WifInfo) ESP8266 Teleinfo Template + * {"NAME":"WifInfo v1.0a","GPIO":[17,255,255,255,6,5,255,255,7,210,255,255,255],"FLAG":15,"BASE":18} * {"NAME":"WifInfo","GPIO":[7,255,255,210,6,5,255,255,255,255,255,255,255],"FLAG":15,"BASE":18} * \*********************************************************************************************/ @@ -185,6 +186,8 @@ void DataCallback(struct _ValueList * me, uint8_t flags) } } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Label[%02d] %s=%s"), ilabel, labelName, me->value); + // Current tariff (legacy) if (ilabel == LABEL_PTEC) { @@ -217,34 +220,21 @@ void DataCallback(struct _ValueList * me, uint8_t flags) { Energy.voltage_available = true; Energy.voltage[0] = (float) atoi(me->value); - // Update current - if (Energy.voltage_available && Energy.voltage[0]) { - Energy.current[0] = Energy.active_power[0] / Energy.voltage[0] ; - } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Voltage %s, now %d"), me->value, (int) Energy.voltage[0]); } // Current I else if (ilabel == LABEL_IINST || ilabel == LABEL_IRMS1) { - if (!Energy.voltage_available) { - Energy.current[0] = (float) atoi(me->value); - } else if (Energy.voltage[0]) { - Energy.current[0] = Energy.active_power[0] / Energy.voltage[0] ; - } + Energy.current[0] = (float) atoi(me->value); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Current %s, now %d"), me->value, (int) Energy.current[0]); } // Power P else if (ilabel == LABEL_PAPP || ilabel == LABEL_SINSTS) { - int papp = atoi(me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Power %s, now %d"), me->value, papp); - Energy.active_power[0] = (float) atoi(me->value); - // Update current - if (Energy.voltage_available && Energy.voltage[0]) { - Energy.current[0] = Energy.active_power[0] / Energy.voltage[0] ; - } + Energy.active_power[0] = (float) atoi(me->value);; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Power %s, now %d"), me->value, (int) Energy.active_power[0]); } // Wh indexes (legacy) @@ -258,7 +248,10 @@ void DataCallback(struct _ValueList * me, uint8_t flags) if ( getValueFromLabelIndex(LABEL_HCHC, value) ) { hc = atoi(value);} if ( getValueFromLabelIndex(LABEL_HCHP, value) ) { hp = atoi(value);} total = hc + hp; - EnergyUpdateTotal(total/1000.0f, true); + + if (!Settings.flag4.teleinfo_rawdata) { + EnergyUpdateTotal(total/1000.0f, true); + } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u HP:%u Total:%u"), hc, hp, total); } @@ -266,7 +259,9 @@ void DataCallback(struct _ValueList * me, uint8_t flags) else if ( ilabel == LABEL_EAST) { uint32_t total = atoi(me->value); - EnergyUpdateTotal(total/1000.0f, true); + if (!Settings.flag4.teleinfo_rawdata) { + EnergyUpdateTotal(total/1000.0f, true); + } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Total:%uWh"), total); } @@ -324,6 +319,62 @@ void NewFrameCallback(struct _ValueList * me) { // Reset Energy Watchdog Energy.data_valid[0] = 0; + + // send teleinfo full frame only if setup like that + // see setOption103 + if (Settings.flag4.teleinfo_rawdata) { + struct _ValueList * me = tinfo.getList(); + + // Total size we can use, remove { } and \0 + int remaining_size; + char sep = ' '; + char * p ; + int len; + boolean isNumber ; + + strcpy_P(mqtt_data, PSTR("{")); + len = strlen(mqtt_data); + remaining_size = sizeof(mqtt_data) - len - 2; + + // Loop thru all the teleinfo frame but + // always check we don't buffer overflow of MQTT data + while (me->next) { + // go to next node + me = me->next; + + if (me->name && me->value && *me->name && *me->value) { + isNumber = true; + p = me->value; + + // check if value is number + while (*p && isNumber) { + if ( *p < '0' || *p > '9' ) { + isNumber = false; + } + p++; + } + + if (!isNumber) { + snprintf_P(mqtt_data+len, remaining_size, PSTR("%c\"%s\":\"%s\""), sep, me->name, me->value); + } else { + snprintf_P(mqtt_data+len, remaining_size, PSTR("%c\"%s\":%d"), sep, me->name, atoi(me->value)); + } + // Total size we can use now + // Still remove space for latest } and \0 and current size + len = strlen(mqtt_data); + remaining_size = sizeof(mqtt_data) - len - 2 ; + + // Now separator is comma + sep =','; + + } + } + + strcat_P(mqtt_data, PSTR("}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + } + + } /* ====================================================================== @@ -335,10 +386,8 @@ Comments: - ====================================================================== */ void TInfoDrvInit(void) { if (PinUsed(GPIO_TELEINFO_RX)) { - energy_flg = XNRG_15; - Energy.voltage_available = false; - //Energy.current_available = false; - Energy.type_dc = true; + energy_flg = XNRG_15; + Energy.voltage_available = false; } } @@ -433,14 +482,16 @@ Comments: - ====================================================================== */ void TInfoEvery250ms(void) { - char c; - if (!tinfo_found) + if (!tinfo_found) { return; + } if (TInfoSerial->available()) { - //AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: received %d chars"), TInfoSerial->available()); - // We received some data? - while (TInfoSerial->available()>8) { + unsigned long start = millis(); + char c; + + // We received some data, process but never more than 100ms ? + while (TInfoSerial->available()>8 && millis()-start < 100) { // get char c = TInfoSerial->read(); // data processing @@ -477,36 +528,39 @@ void TInfoShow(bool json) // Just add the raw label/values of the teleinfo frame if (json) { - struct _ValueList * me = tinfo.getList(); - // Calculated values if (isousc) { ResponseAppend_P(PSTR(",\"Load\":%d"),(int) ((Energy.current[0]*100.0f) / isousc)); } - // Loop thru all the teleinfo frame - while (me->next) { - // go to next node - me = me->next; + // add teleinfo full frame only if no teleinfo raw data setup + if (!Settings.flag4.teleinfo_rawdata) { + struct _ValueList * me = tinfo.getList(); - if (me->name && me->value && *me->name && *me->value) { - boolean isNumber = true; - char * p = me->value; + // Loop thru all the teleinfo frame + while (me->next) { + // go to next node + me = me->next; - // check if value is number - while (*p && isNumber) { - if ( *p < '0' || *p > '9' ) { - isNumber = false; + if (me->name && me->value && *me->name && *me->value) { + boolean isNumber = true; + char * p = me->value; + + // check if value is number + while (*p && isNumber) { + if ( *p < '0' || *p > '9' ) { + isNumber = false; + } + p++; + } + + // this will add "" on not number values + ResponseAppend_P(PSTR(",\"%s\":"), me->name); + if (!isNumber) { + ResponseAppend_P(PSTR("\"%s\""), me->value); + } else { + ResponseAppend_P(PSTR("%u"), atol(me->value)); } - p++; - } - - // this will add "" on not number values - ResponseAppend_P(PSTR(",\"%s\":"), me->name); - if (!isNumber) { - ResponseAppend_P(PSTR("\"%s\""), me->value); - } else { - ResponseAppend_P(PSTR("%u"), atol(me->value)); } } } @@ -531,7 +585,7 @@ void TInfoShow(bool json) WSContentSend_PD(HTTP_ENERGY_PMAX_TELEINFO, atoi(value)); } - if (tinfo_mode==TINFO_MODE_STANDARD ) { + if (tinfo_mode==TINFO_MODE_HISTORIQUE ) { if (tarif) { GetTextIndexed(name, sizeof(name), tarif-1, kTarifName); WSContentSend_PD(HTTP_ENERGY_TARIF_TELEINFO, name); @@ -542,7 +596,7 @@ void TInfoShow(bool json) WSContentSend_PD(HTTP_ENERGY_CONTRAT_TELEINFO, name, isousc); WSContentSend_PD(HTTP_ENERGY_LOAD_TELEINFO, percent); } - } else { + } else if (tinfo_mode==TINFO_MODE_STANDARD ) { if (getValueFromLabelIndex(LABEL_LTARF, name) ) { WSContentSend_PD(HTTP_ENERGY_TARIF_TELEINFO, name); } From 6e05a247b70ebe8a1489b66b302144a20ce3ae38 Mon Sep 17 00:00:00 2001 From: Charles Date: Fri, 14 Aug 2020 19:55:39 +0200 Subject: [PATCH 5/7] changed setOption103 to setOption108 taken during dev --- tasmota/CHANGELOG.md | 2 +- tasmota/settings.h | 12 ++++++------ tasmota/xnrg_15_teleinfo.ino | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 28c9e0042..815736610 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -8,7 +8,7 @@ - Add Zigbee options to ``ZbSend`` ``Config`` and ``ReadCondig`` - Add command ``Restart 2`` to halt system. Needs hardware reset or power cycle to restart (#9046) - Add command ``SetOption102 0/1`` to switch between Teleinfo French Metering mode, legacy 1200 bps (0) or Linky standard 9600 bps (1) -- Add command ``SetOption103 0/1`` to enable Teleinfo telemetry into Tasmota Energy MQTT (0) or Teleinfo only (1) in this case MQTT will send RAW Teleinfo telemetry on each frame received and not into Tasmota energy calculation telemetry. +- Add command ``SetOption108 0/1`` to enable Teleinfo telemetry into Tasmota Energy MQTT (0) or Teleinfo only (1) in this case MQTT will send RAW Teleinfo telemetry on each frame received and not into Tasmota energy calculation telemetry. ### 8.4.0 20200730 diff --git a/tasmota/settings.h b/tasmota/settings.h index 2b13128e4..d63c798e2 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -122,12 +122,12 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t remove_zbreceived : 1; // bit 18 (v8.3.1.7) - SetOption100 - Remove ZbReceived form JSON message uint32_t zb_index_ep : 1; // bit 19 (v8.3.1.7) - SetOption101 - Add the source endpoint as suffix to attributes, ex `Power3` instead of `Power` if sent from endpoint 3 uint32_t teleinfo_baudrate : 1; // bit 20 (v8.4.0.1) - SetOption102 - Set Baud rate for Teleinfo communication (0 = 1200 or 1 = 9600) - uint32_t teleinfo_rawdata : 1; // bit 21 (v8.4.0.1) - SetOption103 - enable Teleinfo + Tasmota Energy device (0) or Teleinfo raw data only (1) - uint32_t spare22 : 1; - uint32_t spare23 : 1; - uint32_t spare24 : 1; - uint32_t spare25 : 1; - uint32_t spare26 : 1; + uint32_t mqtt_tls : 1; // bit 21 (v8.4.0.1) - SetOption103 - Enable TLS mode (requires TLS version) + uint32_t mqtt_no_retain : 1; // bit 22 (v8.4.0.1) - SetOption104 - No Retain - disable all MQTT retained messages, some brokers don't support it: AWS IoT, Losant + uint32_t white_blend_mode : 1; // bit 23 (v8.4.0.1) - SetOption105 - White Blend Mode - used to be `RGBWWTable` last value `0`, now deprecated in favor of this option + uint32_t virtual_ct : 1; // bit 24 (v8.4.0.1) - SetOption106 - Virtual CT - Creates a virtual White ColorTemp for RGBW lights + uint32_t virtual_ct_cw : 1; // bit 25 (v8.4.0.1) - SetOption107 - Virtual CT Channel - signals whether the hardware white is cold CW (true) or warm WW (false) + uint32_t teleinfo_rawdata : 1; // bit 21 (v8.4.0.1) - SetOption108 - enable Teleinfo + Tasmota Energy device (0) or Teleinfo raw data only (1) uint32_t spare27 : 1; uint32_t spare28 : 1; uint32_t spare29 : 1; diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index 79dbcea7c..5eaa65e53 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -321,7 +321,7 @@ void NewFrameCallback(struct _ValueList * me) Energy.data_valid[0] = 0; // send teleinfo full frame only if setup like that - // see setOption103 + // see setOption108 if (Settings.flag4.teleinfo_rawdata) { struct _ValueList * me = tinfo.getList(); From 7c7545761a32ce8eb7d23d77b1ad8cbc05e4a7e2 Mon Sep 17 00:00:00 2001 From: Charles Date: Sun, 16 Aug 2020 11:54:16 +0200 Subject: [PATCH 6/7] Use ResponseAppend_P API --- tasmota/xnrg_15_teleinfo.ino | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index 5eaa65e53..6d8fb4b4d 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -325,16 +325,11 @@ void NewFrameCallback(struct _ValueList * me) if (Settings.flag4.teleinfo_rawdata) { struct _ValueList * me = tinfo.getList(); - // Total size we can use, remove { } and \0 - int remaining_size; - char sep = ' '; + char sep = ' '; // First JSON value separator char * p ; - int len; boolean isNumber ; - strcpy_P(mqtt_data, PSTR("{")); - len = strlen(mqtt_data); - remaining_size = sizeof(mqtt_data) - len - 2; + Response_P(PSTR("{")); // Loop thru all the teleinfo frame but // always check we don't buffer overflow of MQTT data @@ -354,23 +349,20 @@ void NewFrameCallback(struct _ValueList * me) p++; } + ResponseAppend_P( PSTR("%c\"%s\":"), sep, me->name ); + if (!isNumber) { - snprintf_P(mqtt_data+len, remaining_size, PSTR("%c\"%s\":\"%s\""), sep, me->name, me->value); + ResponseAppend_P( PSTR("\"%s\""), me->value ); } else { - snprintf_P(mqtt_data+len, remaining_size, PSTR("%c\"%s\":%d"), sep, me->name, atoi(me->value)); + ResponseAppend_P( PSTR("%d"), atoi(me->value)); } - // Total size we can use now - // Still remove space for latest } and \0 and current size - len = strlen(mqtt_data); - remaining_size = sizeof(mqtt_data) - len - 2 ; // Now separator is comma sep =','; - } } - strcat_P(mqtt_data, PSTR("}")); + ResponseJsonEnd(); MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); } From c9f8421187f60cc994f6d793f9e4d75ad2a913a9 Mon Sep 17 00:00:00 2001 From: Charles Date: Sun, 16 Aug 2020 20:53:28 +0200 Subject: [PATCH 7/7] Setoption108 add SerialNumber to topix prefix optimize code to sed json with response --- tasmota/xnrg_15_teleinfo.ino | 375 ++++++++++++++++++----------------- 1 file changed, 190 insertions(+), 185 deletions(-) diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index 6d8fb4b4d..6fb9d06ca 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -108,6 +108,7 @@ const char kLabel[] PROGMEM = TInfo tinfo; // Teleinfo object TasmotaSerial *TInfoSerial = nullptr; _Mode_e tinfo_mode = TINFO_MODE_HISTORIQUE; +char serialNumber[13] = ""; // Serial number is 12 char long bool tinfo_found = false; int contrat; int tarif; @@ -145,19 +146,17 @@ Comments: should have been initialised with a ====================================================================== */ void ADPSCallback(uint8_t phase) { - char adco[13]; - // n = phase number 1 to 3 if (phase == 0){ phase = 1; } - if (tinfo_mode == TINFO_MODE_HISTORIQUE) { - if (getValueFromLabelIndex(LABEL_ADCO, adco) ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"ADPS\":%i}}"), adco, phase ); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); - } - } + Response_P(PSTR("{")); + ResponseAppend_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"ADPS\":%i}}"), serialNumber, phase ); + ResponseJsonEnd(); + + // Publish adding ADCO serial number into the topic + MqttPublishPrefixTopic_P(RESULT_OR_TELE, serialNumber, false); AddLog_P2(LOG_LEVEL_INFO, PSTR("ADPS on phase %d"), phase); } @@ -186,126 +185,191 @@ void DataCallback(struct _ValueList * me, uint8_t flags) } } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Label[%02d] %s=%s"), ilabel, labelName, me->value); + if (flags & TINFO_FLAGS_ADDED) { c = '#'; } + if (flags & TINFO_FLAGS_UPDATED) { c = '*'; } + if (flags & TINFO_FLAGS_STRING) { c = '$'; } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: [%d]%c %s=%s"), ilabel, c , me->name, me->value); - // Current tariff (legacy) - if (ilabel == LABEL_PTEC) - { - char tarif_value[] = " "; // 4 spaces - // Find the tariff index - for (tarif = TARIF_TH ; tarif < TARIF_END ; tarif++) { - GetTextIndexed(tarif_value, sizeof(tarif_value), tarif-1, kTarifValue); - if (!strcmp(tarif_value, me->value)) { - break; + if (ilabelvalue)) { + break; + } } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif changed, now '%s' (%d)"), me->value, tarif); + } + + // Current tariff (standard is in clear text in value) + else if (ilabel == LABEL_LTARF) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif name changed, now '%s'"), me->value); + } + // Current tariff (standard index is is in clear text in value) + else if (ilabel == LABEL_NTARF) + { + tarif = atoi(me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif index changed, now '%d'"), tarif); + } + + + // Voltage V (not present on all Smart Meter) + else if ( ilabel == LABEL_TENSION || ilabel == LABEL_URMS1) + { + Energy.voltage_available = true; + Energy.voltage[0] = (float) atoi(me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Voltage %s, now %d"), me->value, (int) Energy.voltage[0]); } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif changed, now '%s' (%d)"), me->value, tarif); - } - // Current tariff (standard is in clear text in value) - else if (ilabel == LABEL_LTARF) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif name changed, now '%s'"), me->value); - } - // Current tariff (standard index is is in clear text in value) - else if (ilabel == LABEL_NTARF) - { - tarif = atoi(me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif index changed, now '%d'"), tarif); - } - - - // Voltage V (not present on all Smart Meter) - else if ( ilabel == LABEL_TENSION || ilabel == LABEL_URMS1) - { - Energy.voltage_available = true; - Energy.voltage[0] = (float) atoi(me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Voltage %s, now %d"), me->value, (int) Energy.voltage[0]); - } - - // Current I - else if (ilabel == LABEL_IINST || ilabel == LABEL_IRMS1) - { - Energy.current[0] = (float) atoi(me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Current %s, now %d"), me->value, (int) Energy.current[0]); - } - - // Power P - else if (ilabel == LABEL_PAPP || ilabel == LABEL_SINSTS) - { - Energy.active_power[0] = (float) atoi(me->value);; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Power %s, now %d"), me->value, (int) Energy.active_power[0]); - } - - // Wh indexes (legacy) - else if ( ilabel == LABEL_HCHC || ilabel == LABEL_HCHP) - { - char value[32]; - uint32_t hc = 0; - uint32_t hp = 0; - uint32_t total = 0; - - if ( getValueFromLabelIndex(LABEL_HCHC, value) ) { hc = atoi(value);} - if ( getValueFromLabelIndex(LABEL_HCHP, value) ) { hp = atoi(value);} - total = hc + hp; - - if (!Settings.flag4.teleinfo_rawdata) { - EnergyUpdateTotal(total/1000.0f, true); + // Current I + else if (ilabel == LABEL_IINST || ilabel == LABEL_IRMS1) + { + Energy.current[0] = (float) atoi(me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Current %s, now %d"), me->value, (int) Energy.current[0]); } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u HP:%u Total:%u"), hc, hp, total); - } - // Wh total index (standard) - else if ( ilabel == LABEL_EAST) - { - uint32_t total = atoi(me->value); - if (!Settings.flag4.teleinfo_rawdata) { - EnergyUpdateTotal(total/1000.0f, true); + // Power P + else if (ilabel == LABEL_PAPP || ilabel == LABEL_SINSTS) + { + Energy.active_power[0] = (float) atoi(me->value);; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Power %s, now %d"), me->value, (int) Energy.active_power[0]); } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Total:%uWh"), total); - } - // Wh indexes (standard) - else if ( ilabel == LABEL_EASF01) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u"), atoi(me->value)); - } - else if ( ilabel == LABEL_EASF02) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HP:%u"), atoi(me->value)); - } + // Wh indexes (legacy) + else if ( ilabel == LABEL_HCHC || ilabel == LABEL_HCHP) + { + char value[32]; + uint32_t hc = 0; + uint32_t hp = 0; + uint32_t total = 0; - // Contract subscribed (legacy) - else if (ilabel == LABEL_OPTARIF) - { - char contrat_value[] = " "; // 4 spaces - // Find the contract index - for (contrat = CONTRAT_BAS ; contrat < CONTRAT_END ; contrat++) { - GetTextIndexed(contrat_value, sizeof(contrat_value), contrat, kContratValue); - if (!strcmp(contrat_value, me->value)) { - break; + if ( getValueFromLabelIndex(LABEL_HCHC, value) ) { hc = atoi(value);} + if ( getValueFromLabelIndex(LABEL_HCHP, value) ) { hp = atoi(value);} + total = hc + hp; + + if (!Settings.flag4.teleinfo_rawdata) { + EnergyUpdateTotal(total/1000.0f, true); } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u HP:%u Total:%u"), hc, hp, total); } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s' (%d)"), me->value, contrat); - } - // Contract subscribed (standard is in clear text in value) - else if (ilabel == LABEL_NGTF) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s'"), me->value); - } - // Contract subscribed (Power) - else if (ilabel == LABEL_ISOUSC || ilabel == LABEL_PREF) - { - isousc = atoi( me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: ISousc set to %d"), isousc); - } + // Wh total index (standard) + else if ( ilabel == LABEL_EAST) + { + uint32_t total = atoi(me->value); + if (!Settings.flag4.teleinfo_rawdata) { + EnergyUpdateTotal(total/1000.0f, true); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Total:%uWh"), total); + } + // Wh indexes (standard) + else if ( ilabel == LABEL_EASF01) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u"), atoi(me->value)); + } + else if ( ilabel == LABEL_EASF02) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HP:%u"), atoi(me->value)); + } + + // Contract subscribed (legacy) + else if (ilabel == LABEL_OPTARIF) + { + char contrat_value[] = " "; // 4 spaces + // Find the contract index + for (contrat = CONTRAT_BAS ; contrat < CONTRAT_END ; contrat++) { + GetTextIndexed(contrat_value, sizeof(contrat_value), contrat, kContratValue); + if (!strcmp(contrat_value, me->value)) { + break; + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s' (%d)"), me->value, contrat); + } + // Contract subscribed (standard is in clear text in value) + else if (ilabel == LABEL_NGTF) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s'"), me->value); + } + + // Contract subscribed (Power) + else if (ilabel == LABEL_ISOUSC || ilabel == LABEL_PREF) + { + isousc = atoi( me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: ISousc set to %d"), isousc); + } + + // Serial Number of device + else if (ilabel == LABEL_ADCO || ilabel == LABEL_ADSC) + { + strcpy(serialNumber, me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: %s set to %s"), me->name, serialNumber); + } + + } } - if (flags & TINFO_FLAGS_ADDED) { c = '#'; } - if (flags & TINFO_FLAGS_UPDATED) { c = '*'; } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TIC: %c %s=%s"),c , me->name, me->value); + + + +} + +/* ====================================================================== +Function: responseDumpTInfo +Purpose : add teleinfo values into JSON response +Input : - +Output : - +Comments: - +====================================================================== */ +void ResponseAppendTInfo() +{ + struct _ValueList * me = tinfo.getList(); + + char sep = ' '; // First JSON value separator + char * p ; + boolean isNumber ; + + // Loop thru all the teleinfo frame but + // always check we don't buffer overflow of MQTT data + while (me->next) { + // go to next node + me = me->next; + + if (me->name && me->value && *me->name && *me->value) { + isNumber = true; + p = me->value; + + // Specific treatment serial number don't convert to number later + if (strcmp(me->name, "ADCO")==0 || strcmp(me->name, "ADSC")==0) { + isNumber = false; + } else { + // check if value is number + while (*p && isNumber) { + if ( *p < '0' || *p > '9' ) { + isNumber = false; + } + p++; + } + } + + ResponseAppend_P( PSTR("%c\"%s\":"), sep, me->name ); + + if (!isNumber || (me->flags & TINFO_FLAGS_STRING) ) { + ResponseAppend_P( PSTR("\"%s\""), me->value ); + } else { + ResponseAppend_P( PSTR("%d"), atoi(me->value)); + } + + // Now JSON separator is needed + sep =','; + } + } } /* ====================================================================== @@ -323,50 +387,13 @@ void NewFrameCallback(struct _ValueList * me) // send teleinfo full frame only if setup like that // see setOption108 if (Settings.flag4.teleinfo_rawdata) { - struct _ValueList * me = tinfo.getList(); - - char sep = ' '; // First JSON value separator - char * p ; - boolean isNumber ; - Response_P(PSTR("{")); - - // Loop thru all the teleinfo frame but - // always check we don't buffer overflow of MQTT data - while (me->next) { - // go to next node - me = me->next; - - if (me->name && me->value && *me->name && *me->value) { - isNumber = true; - p = me->value; - - // check if value is number - while (*p && isNumber) { - if ( *p < '0' || *p > '9' ) { - isNumber = false; - } - p++; - } - - ResponseAppend_P( PSTR("%c\"%s\":"), sep, me->name ); - - if (!isNumber) { - ResponseAppend_P( PSTR("\"%s\""), me->value ); - } else { - ResponseAppend_P( PSTR("%d"), atoi(me->value)); - } - - // Now separator is comma - sep =','; - } - } - + ResponseAppendTInfo(); ResponseJsonEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + // Publish adding ADCO serial number into the topic + // Need setOption4 to be enabled + MqttPublishPrefixTopic_P(RESULT_OR_TELE, serialNumber, false); } - - } /* ====================================================================== @@ -500,6 +527,7 @@ Output : - Comments: - ====================================================================== */ #ifdef USE_WEBSERVER +const char HTTP_ENERGY_ID_TELEINFO[] PROGMEM = "{s}ID{m}%s{e}" ; const char HTTP_ENERGY_INDEX_TELEINFO[] PROGMEM = "{s}%s{m}%s " D_UNIT_WATTHOUR "{e}" ; const char HTTP_ENERGY_PAPP_TELEINFO[] PROGMEM = "{s}" D_POWERUSAGE "{m}%d " D_UNIT_WATT "{e}" ; const char HTTP_ENERGY_IINST_TELEINFO[] PROGMEM = "{s}" D_CURRENT "{m}%d " D_UNIT_AMPERE "{e}" ; @@ -512,9 +540,6 @@ const char HTTP_ENERGY_PMAX_TELEINFO[] PROGMEM = "{s}" D_MAX_POWER "{m}%d" D_UN void TInfoShow(bool json) { - char name[32]; - char value[32]; - // Since it's an Energy device , current, voltage and power are // already present on the telemetry frame. No need to add here // Just add the raw label/values of the teleinfo frame @@ -527,34 +552,7 @@ void TInfoShow(bool json) // add teleinfo full frame only if no teleinfo raw data setup if (!Settings.flag4.teleinfo_rawdata) { - struct _ValueList * me = tinfo.getList(); - - // Loop thru all the teleinfo frame - while (me->next) { - // go to next node - me = me->next; - - if (me->name && me->value && *me->name && *me->value) { - boolean isNumber = true; - char * p = me->value; - - // check if value is number - while (*p && isNumber) { - if ( *p < '0' || *p > '9' ) { - isNumber = false; - } - p++; - } - - // this will add "" on not number values - ResponseAppend_P(PSTR(",\"%s\":"), me->name); - if (!isNumber) { - ResponseAppend_P(PSTR("\"%s\""), me->value); - } else { - ResponseAppend_P(PSTR("%u"), atol(me->value)); - } - } - } + ResponseAppendTInfo(); } @@ -562,6 +560,9 @@ void TInfoShow(bool json) } else { + char name[32]; + char value[32]; + if (getValueFromLabelIndex(LABEL_HCHC, value) ) { GetTextIndexed(name, sizeof(name), LABEL_HCHC, kLabel); WSContentSend_PD(HTTP_ENERGY_INDEX_TELEINFO, name, value); @@ -601,6 +602,10 @@ void TInfoShow(bool json) } } } + + // Serial number ADCO or ADSC + WSContentSend_PD(HTTP_ENERGY_ID_TELEINFO, serialNumber); + #endif // USE_WEBSERVER } }