From 55ea5073f2b8ad1e7256b32ef8603b6be237327f Mon Sep 17 00:00:00 2001 From: Charles Date: Thu, 8 Apr 2021 20:02:19 +0200 Subject: [PATCH 1/4] first try of command management --- tasmota/xnrg_15_teleinfo.ino | 192 ++++++++++++++++++++++++++++------- 1 file changed, 155 insertions(+), 37 deletions(-) diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index c1e0fc9d9..604936a82 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -38,6 +38,28 @@ #define TINFO_READ_TIMEOUT 400 +#define D_NAME_TELEINFO "Teleinfo" + +// Json Command +const char S_JSON_TELEINFO_COMMAND_STRING[] PROGMEM = "{\"" D_NAME_TELEINFO "\":{\"%s\":%s}}"; +const char S_JSON_TELEINFO_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_TELEINFO "\":{\"%s\":%d}}"; +const char S_JSON_TELEINFO_COMMAND_SETTINGS[] PROGMEM = "{\"TIC_Settings\":{\"Mode\":%s,\"Raw\":%s,\"Skip\":%d,\"Limit\":%d}}"; + +#define MAX_TINFO_COMMAND_NAME 17 // Change this if one of the following kTInfo_Commands is higher then 16 char +const char kTInfo_Commands[] PROGMEM = "historique|standard|none|full|changed|skip|limit|config"; + +enum TInfoCommands { // commands for Console + CMND_TELEINFO_HISTORIQUE=0, // Set Legacy mode + CMND_TELEINFO_STANDARD, // Set Standard Mode + CMND_TELEINFO_RAW_DISABLE, // Disable Raw frame sending + CMND_TELEINFO_RAW_FULL, // Enable all RAW frame send + CMND_TELEINFO_RAW_CHANGE, // Enable only changed values RAW frame send + CMND_TELEINFO_SKIP, // Set number of frame to skip when raw mode is enabled + CMND_TELEINFO_LIMIT, // Limit RAW frame to values subject to fast change (Power, Current, ...), TBD + CMND_TELEINFO_CONFIG // Show Teleinfo current settings +}; + + // All contract type for legacy, standard mode has in clear text enum TInfoContrat{ CONTRAT_BAS = 1, // BASE => Option Base. @@ -126,6 +148,7 @@ bool tinfo_found = false; int contrat; int tarif; int isousc; +int raw_skip; /*********************************************************************************************/ @@ -366,10 +389,11 @@ void DataCallback(struct _ValueList * me, uint8_t flags) Function: responseDumpTInfo Purpose : add teleinfo values into JSON response Input : 1st separator space if begining of JSON, else comma + : select if append all data or just changed one Output : - Comments: - ====================================================================== */ -void ResponseAppendTInfo(char sep) +void ResponseAppendTInfo(char sep, bool all) { struct _ValueList * me = tinfo.getList(); @@ -383,32 +407,37 @@ void ResponseAppendTInfo(char sep) 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; + // Add values only if we want all data or if data has changed + if (all || ( Settings.teleinfo.raw_report_changed && (me->flags & (TINFO_FLAGS_UPDATED | TINFO_FLAGS_ADDED | TINFO_FLAGS_ALERT) ) ) ) { + + 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++; } - 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 JSON separator is needed + sep =','; } - - 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 JSON separator is needed - sep =','; } } } @@ -425,15 +454,28 @@ void NewFrameCallback(struct _ValueList * me) // Reset Energy Watchdog Energy.data_valid[0] = 0; - // send teleinfo full frame only if setup like that - // see setOption108 - if (Settings.flag4.teleinfo_rawdata) { - Response_P(PSTR("{")); - ResponseAppendTInfo(' '); - ResponseJsonEnd(); - // Publish adding ADCO serial number into the topic - // Need setOption4 to be enabled - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, serialNumber, false); + // Deprecated see setOption108 + // send teleinfo raw data only if setup like that + if (Settings.teleinfo.raw_send) { + // Do we need to skip this frame + if (raw_skip>0) { + raw_skip--; + } + + if (raw_skip == 0 ) { + Response_P(PSTR("{")); + // send teleinfo full frame or only changed data + ResponseAppendTInfo(' ', Settings.teleinfo.raw_report_changed ? false : true ); + ResponseJsonEnd(); + // Publish adding ADCO serial number into the topic + // Need setOption4 to be enabled + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, serialNumber, false); + + // Reset frame skip counter (if 0 it's disabled) + raw_skip = Settings.teleinfo.raw_skip; + } else { + AddLog(LOG_LEVEL_INFO, PSTR("TIC: not sending yet, will do in %d frame(s)"), raw_skip); + } } } @@ -463,9 +505,9 @@ void TInfoInit(void) int baudrate; int serial_buffer_size; - - // SetOption102 - Set Baud rate for Teleinfo serial communication (0 = 1200 or 1 = 9600) - if (Settings.flag4.teleinfo_baudrate) { + // Deprecated SetOption102 - Set Baud rate for Teleinfo serial communication (0 = 1200 or 1 = 9600) + // now set in bit field TeleinfoCfg + if (Settings.teleinfo.mode_standard) { baudrate = 9600; tinfo_mode = TINFO_MODE_STANDARD; serial_buffer_size = TELEINFO_SERIAL_BUFFER_STANDARD; @@ -475,6 +517,7 @@ void TInfoInit(void) serial_buffer_size = TELEINFO_SERIAL_BUFFER_HISTORIQUE; } + if (PinUsed(GPIO_TELEINFO_RX)) { int8_t rx_pin = Pin(GPIO_TELEINFO_RX); AddLog(LOG_LEVEL_INFO, PSTR("TIC: RX on GPIO%d, baudrate %d"), rx_pin, baudrate); @@ -533,11 +576,80 @@ void TInfoInit(void) tinfo.attachNewFrame(NewFrameCallback); tinfo_found = true; + if (Settings.teleinfo.raw_send) { + raw_skip = Settings.teleinfo.raw_skip; + AddLog(LOG_LEVEL_INFO, PSTR("TIC: Raw mode enabled")); + if (raw_skip) { + AddLog(LOG_LEVEL_INFO, PSTR("TIC: Sending only one frame over %d "), raw_skip+1); + } + } AddLog(LOG_LEVEL_INFO, PSTR("TIC: Ready")); } } } + +/* ====================================================================== +Function: TInfoCmd +Purpose : Tasmota core command engine for Teleinfo commands +Input : - +Output : - +Comments: - +====================================================================== */ +bool TInfoCmd(void) { + char command[CMDSZ]; + + uint8_t name_len = strlen(D_NAME_TELEINFO); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_NAME_TELEINFO), name_len)) { + + uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + name_len, kTInfo_Commands); + switch (command_code) { + case CMND_TELEINFO_STANDARD: + case CMND_TELEINFO_HISTORIQUE: { + char mode_name[MAX_TINFO_COMMAND_NAME]; + if (XdrvMailbox.data_len) { + Settings.teleinfo.mode_standard = command_code == CMND_TELEINFO_STANDARD ? 1 : 0; + // Get the mode and raw name + GetTextIndexed(mode_name, MAX_TINFO_COMMAND_NAME, command_code, kTInfo_Commands); + } + Response_P(S_JSON_TELEINFO_COMMAND_STRING, command, mode_name); + } + break; + + case CMND_TELEINFO_CONFIG: { + if (!XdrvMailbox.data_len) { + char mode_name[MAX_TINFO_COMMAND_NAME]; + char raw_name[MAX_TINFO_COMMAND_NAME]; + + int index_mode = Settings.teleinfo.mode_standard ? CMND_TELEINFO_STANDARD : CMND_TELEINFO_HISTORIQUE; + int index_raw = Settings.teleinfo.raw_send ? CMND_TELEINFO_RAW_FULL : CMND_TELEINFO_RAW_DISABLE; + + if (Settings.teleinfo.raw_send && Settings.teleinfo.raw_report_changed) { + index_raw = CMND_TELEINFO_RAW_CHANGE; + } + + // Get the mode and raw name + GetTextIndexed(mode_name, MAX_TINFO_COMMAND_NAME, index_mode, kTInfo_Commands); + GetTextIndexed(raw_name, MAX_TINFO_COMMAND_NAME, index_raw, kTInfo_Commands); + + Response_P(S_JSON_TELEINFO_COMMAND_SETTINGS, mode_name, raw_name, Settings.teleinfo.raw_skip, Settings.teleinfo.raw_limit ); + } + } + break; + + default: + return false; + } + + return true; + + } else { + return false; + } +} + + /* ====================================================================== Function: TInfoProcess Purpose : Tasmota callback executed often enough to read serial @@ -614,7 +726,7 @@ void TInfoShow(bool json) } // add teleinfo full frame - ResponseAppendTInfo(','); + ResponseAppendTInfo(',', true); #ifdef USE_WEBSERVER } @@ -696,11 +808,17 @@ void TInfoShow(bool json) \*********************************************************************************************/ bool Xnrg15(uint8_t function) { + bool result = false; switch (function) { case FUNC_EVERY_250_MSECOND: TInfoProcess(); break; + case FUNC_COMMAND: + AddLog(LOG_LEVEL_INFO, PSTR("TIC: FUNC_COMMAND")); + result = TInfoCmd(); + break; + case FUNC_JSON_APPEND: TInfoShow(1); break; @@ -716,7 +834,7 @@ bool Xnrg15(uint8_t function) TInfoDrvInit(); break; } - return false; + return result; } #endif // USE_TELEINFO From 19ddda132c998cba0bda82dfd78ddcdc65e378ca Mon Sep 17 00:00:00 2001 From: Charles Date: Fri, 9 Apr 2021 19:45:06 +0200 Subject: [PATCH 2/4] now settings are done with command Moved config to bit field added some config option --- tasmota/xnrg_15_teleinfo.ino | 189 +++++++++++++++++++++++++---------- 1 file changed, 138 insertions(+), 51 deletions(-) diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index 604936a82..394a57060 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -41,12 +41,12 @@ #define D_NAME_TELEINFO "Teleinfo" // Json Command -const char S_JSON_TELEINFO_COMMAND_STRING[] PROGMEM = "{\"" D_NAME_TELEINFO "\":{\"%s\":%s}}"; -const char S_JSON_TELEINFO_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_TELEINFO "\":{\"%s\":%d}}"; -const char S_JSON_TELEINFO_COMMAND_SETTINGS[] PROGMEM = "{\"TIC_Settings\":{\"Mode\":%s,\"Raw\":%s,\"Skip\":%d,\"Limit\":%d}}"; +//const char S_JSON_TELEINFO_COMMAND_STRING[] PROGMEM = "{\"" D_NAME_TELEINFO "\":{\"%s\":%s}}"; +//const char S_JSON_TELEINFO_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_TELEINFO "\":{\"%s\":%d}}"; +const char TELEINFO_COMMAND_SETTINGS[] PROGMEM = "TIC: Settings Mode:%s, Raw:%s, Skip:%d, Limit:%d"; -#define MAX_TINFO_COMMAND_NAME 17 // Change this if one of the following kTInfo_Commands is higher then 16 char -const char kTInfo_Commands[] PROGMEM = "historique|standard|none|full|changed|skip|limit|config"; +#define MAX_TINFO_COMMAND_NAME 16+1 // Change this if one of the following kTInfo_Commands is higher then 16 char +const char kTInfo_Commands[] PROGMEM = "historique|standard|noraw|full|changed|skip|limit"; enum TInfoCommands { // commands for Console CMND_TELEINFO_HISTORIQUE=0, // Set Legacy mode @@ -55,8 +55,7 @@ enum TInfoCommands { // commands for Console CMND_TELEINFO_RAW_FULL, // Enable all RAW frame send CMND_TELEINFO_RAW_CHANGE, // Enable only changed values RAW frame send CMND_TELEINFO_SKIP, // Set number of frame to skip when raw mode is enabled - CMND_TELEINFO_LIMIT, // Limit RAW frame to values subject to fast change (Power, Current, ...), TBD - CMND_TELEINFO_CONFIG // Show Teleinfo current settings + CMND_TELEINFO_LIMIT // Limit RAW frame to values subject to fast change (Power, Current, ...), TBD }; @@ -458,10 +457,6 @@ void NewFrameCallback(struct _ValueList * me) // send teleinfo raw data only if setup like that if (Settings.teleinfo.raw_send) { // Do we need to skip this frame - if (raw_skip>0) { - raw_skip--; - } - if (raw_skip == 0 ) { Response_P(PSTR("{")); // send teleinfo full frame or only changed data @@ -474,7 +469,8 @@ void NewFrameCallback(struct _ValueList * me) // Reset frame skip counter (if 0 it's disabled) raw_skip = Settings.teleinfo.raw_skip; } else { - AddLog(LOG_LEVEL_INFO, PSTR("TIC: not sending yet, will do in %d frame(s)"), raw_skip); + AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: not sending yet, will do in %d frame(s)"), raw_skip); + raw_skip--; } } } @@ -597,58 +593,150 @@ Output : - Comments: - ====================================================================== */ bool TInfoCmd(void) { + bool serviced = false; char command[CMDSZ]; - uint8_t name_len = strlen(D_NAME_TELEINFO); - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_NAME_TELEINFO), name_len)) { + // At least "EnergyConfig Teleinfo" + if (CMND_ENERGYCONFIG == Energy.command_code && XdrvMailbox.data_len >= name_len && !strncasecmp_P(XdrvMailbox.data, PSTR(D_NAME_TELEINFO), name_len) ) { + // Just "EnergyConfig Teleinfo" no more parameter + // Show Teleinfo configuration + if (XdrvMailbox.data_len == name_len) { - uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + name_len, kTInfo_Commands); - switch (command_code) { - case CMND_TELEINFO_STANDARD: - case CMND_TELEINFO_HISTORIQUE: { - char mode_name[MAX_TINFO_COMMAND_NAME]; - if (XdrvMailbox.data_len) { - Settings.teleinfo.mode_standard = command_code == CMND_TELEINFO_STANDARD ? 1 : 0; - // Get the mode and raw name - GetTextIndexed(mode_name, MAX_TINFO_COMMAND_NAME, command_code, kTInfo_Commands); + char mode_name[MAX_TINFO_COMMAND_NAME]; + char raw_name[MAX_TINFO_COMMAND_NAME]; + int index_mode = Settings.teleinfo.mode_standard ? CMND_TELEINFO_STANDARD : CMND_TELEINFO_HISTORIQUE; + int index_raw = Settings.teleinfo.raw_send ? CMND_TELEINFO_RAW_FULL : CMND_TELEINFO_RAW_DISABLE; + if (Settings.teleinfo.raw_send && Settings.teleinfo.raw_report_changed) { + index_raw = CMND_TELEINFO_RAW_CHANGE; + } + // Get the mode and raw name + GetTextIndexed(mode_name, MAX_TINFO_COMMAND_NAME, index_mode, kTInfo_Commands); + GetTextIndexed(raw_name, MAX_TINFO_COMMAND_NAME, index_raw, kTInfo_Commands); + + AddLog_P(LOG_LEVEL_INFO, TELEINFO_COMMAND_SETTINGS, mode_name, raw_name, Settings.teleinfo.raw_skip, Settings.teleinfo.raw_limit); + + serviced = true; + + // At least "EnergyConfig Teleinfo xyz" plus one space and one (or more) char + // so "EnergyConfig Teleinfo 0" or "EnergyConfig Teleinfo Standard" + } else if (XdrvMailbox.data_len > name_len + 1 && XdrvMailbox.data[name_len] == ' ' ) { + // Now point on parameter + char *pParam = XdrvMailbox.data + name_len + 1; + char *p = pParam; + char *pValue = nullptr; + // Check for sub parameter ie : EnergyConfig Teleinfo Skip value + while(*p) { + if (*p == ' ') { + if (*(p+1)) { + // Skip parameter by emptying th string so below getcommandcode works + *p++ = 0x00; + // Save parameter value for later + pValue = p; + } + break; } - Response_P(S_JSON_TELEINFO_COMMAND_STRING, command, mode_name); + p++; } - break; - case CMND_TELEINFO_CONFIG: { - if (!XdrvMailbox.data_len) { + int command_code = GetCommandCode(command, sizeof(command), pParam, kTInfo_Commands); + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TIC: EnergyConfig " D_NAME_TELEINFO " parameter '%s' => cmnd %d"), pParam, command_code); + + switch (command_code) { + case CMND_TELEINFO_STANDARD: + case CMND_TELEINFO_HISTORIQUE: { char mode_name[MAX_TINFO_COMMAND_NAME]; - char raw_name[MAX_TINFO_COMMAND_NAME]; - int index_mode = Settings.teleinfo.mode_standard ? CMND_TELEINFO_STANDARD : CMND_TELEINFO_HISTORIQUE; - int index_raw = Settings.teleinfo.raw_send ? CMND_TELEINFO_RAW_FULL : CMND_TELEINFO_RAW_DISABLE; + // Get the mode name + GetTextIndexed(mode_name, MAX_TINFO_COMMAND_NAME, command_code, kTInfo_Commands); - if (Settings.teleinfo.raw_send && Settings.teleinfo.raw_report_changed) { - index_raw = CMND_TELEINFO_RAW_CHANGE; - } + // Only if current settings is different than previous + if ( (tinfo_mode==TINFO_MODE_STANDARD && command_code==CMND_TELEINFO_HISTORIQUE) || + (tinfo_mode==TINFO_MODE_HISTORIQUE && command_code==CMND_TELEINFO_STANDARD) ) { - // Get the mode and raw name - GetTextIndexed(mode_name, MAX_TINFO_COMMAND_NAME, index_mode, kTInfo_Commands); - GetTextIndexed(raw_name, MAX_TINFO_COMMAND_NAME, index_raw, kTInfo_Commands); + // Cleanup Serial not sure it will works since + // there is no end() or close() on tasmotaserial class + if (TInfoSerial) { + TInfoSerial->flush(); + //TInfoSerial->end(); + free(TInfoSerial); + } - Response_P(S_JSON_TELEINFO_COMMAND_SETTINGS, mode_name, raw_name, Settings.teleinfo.raw_skip, Settings.teleinfo.raw_limit ); + // Change mode + Settings.teleinfo.mode_standard = command_code == CMND_TELEINFO_STANDARD ? 1 : 0; + + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Configured to '%s' mode"), mode_name); + + // Re init teleinfo (LibTeleinfo always free linked list on init) + TInfoInit(); + + serviced = true; + + } else { + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Already configured to '%s' mode"), mode_name); + } } - } - break; - - default: - return false; - } - - return true; - - } else { - return false; - } -} + break; + case CMND_TELEINFO_RAW_DISABLE: + case CMND_TELEINFO_RAW_FULL: + case CMND_TELEINFO_RAW_CHANGE: { + + // Enable all RAW frame send + char raw_name[MAX_TINFO_COMMAND_NAME]; + + // Get the raw name + GetTextIndexed(raw_name, MAX_TINFO_COMMAND_NAME, command_code, kTInfo_Commands); + + if (command_code == CMND_TELEINFO_RAW_DISABLE) { + // disable raw mode + Settings.teleinfo.raw_send = 0; + } else { + // enable raw mode + Settings.teleinfo.raw_send = 1; + Settings.teleinfo.raw_report_changed = command_code == CMND_TELEINFO_RAW_CHANGE ? 1 : 0; + } + + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw mode set to '%s'"), raw_name); + serviced = true; + } + break; + + case CMND_TELEINFO_SKIP: { + // Set Raw mode skip frame number + char skip_name[MAX_TINFO_COMMAND_NAME]; + // Get the raw name + GetTextIndexed(skip_name, MAX_TINFO_COMMAND_NAME, command_code, kTInfo_Commands); + int l = strlen(skip_name); + + // At least "EnergyConfig Teleinfo skip" plus one space and one (or more) digit + // so "EnergyConfig Teleinfo Skip 0" or "EnergyConfig Teleinfo Skip 123" + if ( pValue ) { + raw_skip = atoi(pValue); + Settings.teleinfo.raw_skip = raw_skip; + + if (raw_skip ==0) { + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw mode set with no skiping frame")); + } else { + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw mode sending one frame over %d"), raw_skip+1); + } + serviced = true; + } else { + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw mode no skip value")); + } + } + break; + + default: + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: incorrect command parameter '%s'"), pParam); + break; + + } + } + } + return serviced ; +} /* ====================================================================== Function: TInfoProcess @@ -815,7 +903,6 @@ bool Xnrg15(uint8_t function) TInfoProcess(); break; case FUNC_COMMAND: - AddLog(LOG_LEVEL_INFO, PSTR("TIC: FUNC_COMMAND")); result = TInfoCmd(); break; From b2d2742df177496e14546edbee8a1e4eb13611a1 Mon Sep 17 00:00:00 2001 From: Charles Date: Sat, 10 Apr 2021 00:49:38 +0200 Subject: [PATCH 3/4] removed unneeded teleinfo from command --- tasmota/xnrg_15_teleinfo.ino | 69 ++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index 394a57060..75ff81cef 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -389,15 +389,16 @@ Function: responseDumpTInfo Purpose : add teleinfo values into JSON response Input : 1st separator space if begining of JSON, else comma : select if append all data or just changed one -Output : - +Output : false if asked for changed value and none has changed else true Comments: - ====================================================================== */ -void ResponseAppendTInfo(char sep, bool all) +bool ResponseAppendTInfo(char sep, bool all) { struct _ValueList * me = tinfo.getList(); char * p ; - boolean isNumber ; + bool isNumber ; + bool hasValue = false; // Loop thru all the teleinfo frame but // always check we don't buffer overflow of MQTT data @@ -411,6 +412,7 @@ void ResponseAppendTInfo(char sep, bool all) if (all || ( Settings.teleinfo.raw_report_changed && (me->flags & (TINFO_FLAGS_UPDATED | TINFO_FLAGS_ADDED | TINFO_FLAGS_ALERT) ) ) ) { isNumber = true; + hasValue = true; p = me->value; // Specific treatment serial number don't convert to number later @@ -439,6 +441,7 @@ void ResponseAppendTInfo(char sep, bool all) } } } + return hasValue; } /* ====================================================================== @@ -460,11 +463,15 @@ void NewFrameCallback(struct _ValueList * me) if (raw_skip == 0 ) { Response_P(PSTR("{")); // send teleinfo full frame or only changed data - ResponseAppendTInfo(' ', Settings.teleinfo.raw_report_changed ? false : true ); + bool hasData = ResponseAppendTInfo(' ', Settings.teleinfo.raw_report_changed ? false : true ); ResponseJsonEnd(); + // Publish adding ADCO serial number into the topic // Need setOption4 to be enabled - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, serialNumber, false); + // No need to send empty payload + if (hasData) { + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, serialNumber, false); + } // Reset frame skip counter (if 0 it's disabled) raw_skip = Settings.teleinfo.raw_skip; @@ -595,13 +602,16 @@ Comments: - bool TInfoCmd(void) { bool serviced = false; char command[CMDSZ]; - uint8_t name_len = strlen(D_NAME_TELEINFO); + //uint8_t name_len = strlen(D_NAME_TELEINFO); - // At least "EnergyConfig Teleinfo" - if (CMND_ENERGYCONFIG == Energy.command_code && XdrvMailbox.data_len >= name_len && !strncasecmp_P(XdrvMailbox.data, PSTR(D_NAME_TELEINFO), name_len) ) { - // Just "EnergyConfig Teleinfo" no more parameter + // At least "EnergyConfig" + if (CMND_ENERGYCONFIG == Energy.command_code) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TIC: len %d, data '%s'"), XdrvMailbox.data_len, XdrvMailbox.data ? XdrvMailbox.data : "null" ); + + // Just "EnergyConfig" no more parameter // Show Teleinfo configuration - if (XdrvMailbox.data_len == name_len) { + if (XdrvMailbox.data_len == 0) { char mode_name[MAX_TINFO_COMMAND_NAME]; char raw_name[MAX_TINFO_COMMAND_NAME]; @@ -618,11 +628,11 @@ bool TInfoCmd(void) { serviced = true; - // At least "EnergyConfig Teleinfo xyz" plus one space and one (or more) char - // so "EnergyConfig Teleinfo 0" or "EnergyConfig Teleinfo Standard" - } else if (XdrvMailbox.data_len > name_len + 1 && XdrvMailbox.data[name_len] == ' ' ) { + // At least "EnergyConfig xyz" plus one space and one (or more) char + // so "EnergyConfig 0" or "EnergyConfig Teleinfo Standard" + } else if (XdrvMailbox.data_len) { // Now point on parameter - char *pParam = XdrvMailbox.data + name_len + 1; + char *pParam = XdrvMailbox.data; char *p = pParam; char *pValue = nullptr; // Check for sub parameter ie : EnergyConfig Teleinfo Skip value @@ -641,7 +651,7 @@ bool TInfoCmd(void) { int command_code = GetCommandCode(command, sizeof(command), pParam, kTInfo_Commands); - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TIC: EnergyConfig " D_NAME_TELEINFO " parameter '%s' => cmnd %d"), pParam, command_code); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TIC: param '%s' cmnd %d"), pParam, command_code); switch (command_code) { case CMND_TELEINFO_STANDARD: @@ -666,7 +676,7 @@ bool TInfoCmd(void) { // Change mode Settings.teleinfo.mode_standard = command_code == CMND_TELEINFO_STANDARD ? 1 : 0; - AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Configured to '%s' mode"), mode_name); + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: '%s' mode"), mode_name); // Re init teleinfo (LibTeleinfo always free linked list on init) TInfoInit(); @@ -674,7 +684,7 @@ bool TInfoCmd(void) { serviced = true; } else { - AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Already configured to '%s' mode"), mode_name); + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: No change to '%s' mode"), mode_name); } } break; @@ -698,7 +708,7 @@ bool TInfoCmd(void) { Settings.teleinfo.raw_report_changed = command_code == CMND_TELEINFO_RAW_CHANGE ? 1 : 0; } - AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw mode set to '%s'"), raw_name); + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw to '%s'"), raw_name); serviced = true; } break; @@ -711,25 +721,30 @@ bool TInfoCmd(void) { int l = strlen(skip_name); // At least "EnergyConfig Teleinfo skip" plus one space and one (or more) digit - // so "EnergyConfig Teleinfo Skip 0" or "EnergyConfig Teleinfo Skip 123" + // so "EnergyConfig Skip 0" or "EnergyConfig Skip 123" if ( pValue ) { - raw_skip = atoi(pValue); - Settings.teleinfo.raw_skip = raw_skip; + int value = atoi(pValue); + if (value >= 0 && value <= 255) { + raw_skip = value; + Settings.teleinfo.raw_skip = raw_skip; - if (raw_skip ==0) { - AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw mode set with no skiping frame")); + if (raw_skip ==0) { + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw no skip")); + } else { + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw each %d frame(s)"), raw_skip+1); + } + serviced = true; } else { - AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw mode sending one frame over %d"), raw_skip+1); + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: skip can be 0 to 255")); } - serviced = true; } else { - AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: Raw mode no skip value")); + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: no skip value")); } } break; default: - AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: incorrect command parameter '%s'"), pParam); + AddLog_P(LOG_LEVEL_INFO, PSTR("TIC: bad cmd param '%s'"), pParam); break; } From 3cab37ed80e32a71d4b3c23acec97ffaaa9ca72e Mon Sep 17 00:00:00 2001 From: Charles Date: Sat, 10 Apr 2021 00:58:42 +0200 Subject: [PATCH 4/4] obsolated SetOption102 and SetOption108 now teleinfo has it own bit field configuration --- tasmota/settings.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index b23d6dd0e..9e8b31d26 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -121,13 +121,13 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t zerocross_dimmer : 1; // bit 17 (v8.3.1.4) - SetOption99 - (PWM Dimmer) Enable zerocross dimmer (1) uint32_t remove_zbreceived : 1; // bit 18 (v8.3.1.7) - SetOption100 - (Zigbee) Remove ZbReceived form JSON message (1) uint32_t zb_index_ep : 1; // bit 19 (v8.3.1.7) - SetOption101 - (Zigbee) Add the source endpoint as suffix to attributes, ex `Power3` (1) instead of `Power` (0) if sent from endpoint 3 - uint32_t teleinfo_baudrate : 1; // bit 20 (v8.4.0.1) - SetOption102 - (Teleinfo) Set Baud rate for Teleinfo communication to 1200 (0) or 9600 (1) + uint32_t obsolete1 : 1; // bit 20 (v9.3.1.3) - SetOption102 - teleinfo_baudrate Obsolete Teleinfo config has now a dedicated bit field uint32_t mqtt_tls : 1; // bit 21 (v8.4.0.1) - SetOption103 - (MQTT TLS) Enable TLS mode (1) (requires TLS version) uint32_t mqtt_no_retain : 1; // bit 22 (v8.4.0.1) - SetOption104 - (MQTT) No Retain (1) - 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 - (Light) White Blend Mode (1) - 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 - (Light) Virtual CT (1) - Creates a virtual White ColorTemp for RGBW lights uint32_t virtual_ct_cw : 1; // bit 25 (v8.4.0.1) - SetOption107 - (Light) Virtual CT Channel (1) - signals whether the hardware white is cold CW (true) or warm WW (false) - uint32_t teleinfo_rawdata : 1; // bit 26 (v8.4.0.2) - SetOption108 - (Teleinfo) Enable Teleinfo + Tasmota Energy device (0) or Teleinfo raw data only (1) + uint32_t obsolete2 : 1; // bit 26 (v9.3.1.3) - SetOption108 - teleinfo_rawdata Obsolete Teleinfo config has now a dedicated bit field uint32_t alexa_gen_1 : 1; // bit 27 (v8.4.0.3) - SetOption109 - (Alexa) Gen1 mode (1) - if you only have Echo Dot 2nd gen devices uint32_t zb_disable_autobind : 1; // bit 28 (v8.5.0.1) - SetOption110 - (Zigbee) Disable auto-config (1) when pairing new devices uint32_t buzzer_freq_mode : 1; // bit 29 (v8.5.0.1) - SetOption111 - (Buzzer) Use frequency output (1) for buzzer pin instead of on/off signal (0)