From 1545f02fb30c3bfbbead20fee28525a48babd41e Mon Sep 17 00:00:00 2001 From: Charles Date: Sat, 25 Feb 2023 17:39:33 +0100 Subject: [PATCH] Teleinfo, add stats and more checksum controls (#18052) * added teleinfo config show_stats parameter * Added new command and more checksum test --- .../tasmota_xnrg_energy/xnrg_15_teleinfo.ino | 117 ++++++++++++------ 1 file changed, 77 insertions(+), 40 deletions(-) diff --git a/tasmota/tasmota_xnrg_energy/xnrg_15_teleinfo.ino b/tasmota/tasmota_xnrg_energy/xnrg_15_teleinfo.ino index c25025197..fb2502ebc 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_15_teleinfo.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_15_teleinfo.ino @@ -48,7 +48,7 @@ const char TELEINFO_COMMAND_SETTINGS[] PROGMEM = "TIC: Settings Mode:%s, RX:%s, EN:%s, Raw:%s, Skip:%d, Limit:%d"; #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"; +const char kTInfo_Commands[] PROGMEM = "historique|standard|noraw|full|changed|skip|limit|stats"; enum TInfoCommands { // commands for Console CMND_TELEINFO_HISTORIQUE=0, // Set Legacy mode @@ -57,7 +57,8 @@ 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_LIMIT, // Limit RAW frame to values subject to fast change (Power, Current, ...), TBD + CMND_TELEINFO_STATS // Show / clear / Enable TIC reception errors stats }; @@ -155,6 +156,7 @@ PROGMEM = "|PJOURF+1" "|MSG1" + "|PPOINTE" "|" ; @@ -527,53 +529,60 @@ bool ResponseAppendTInfo(char sep, bool all) if (me->name && me->value && *me->name && *me->value) { - // Does this label blacklisted ? - if (!isBlacklistedLabel(me->name)) { + // Check back checksum in case of any memory corruption + if (me->checksum==tinfo.calcChecksum(me->name, me->value))) { - // 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) ) ) ) { + // Does this label blacklisted ? + if (!isBlacklistedLabel(me->name)) { - isNumber = true; - hasValue = true; - p = me->value; + // 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) ) ) ) { - // 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++; - } - } + isNumber = true; + hasValue = true; + p = me->value; - // Avoid unneeded space - if (sep == ' ') { - ResponseAppend_P( PSTR("\"%s\":"), me->name ); - } else { - ResponseAppend_P( PSTR("%c\"%s\":"), sep, me->name ); - } - - if (!isNumber) { - // Some values contains space - if (strcmp(me->name, "NGTF")==0 || strcmp(me->name, "LTARF")==0 || strcmp(me->name, "MSG1")==0) { - char trimmed_value[strlen(me->value)+1]; - strcpy(trimmed_value, me->value); - ResponseAppend_P( PSTR("\"%s\""), Trim(trimmed_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 { - ResponseAppend_P( PSTR("\"%s\""), me->value ); + // check if value is number + while (*p && isNumber) { + if ( *p < '0' || *p > '9' ) { + isNumber = false; + } + p++; + } } - } else { - ResponseAppend_P( PSTR("%ld"), atol(me->value)); - } + // Avoid unneeded space + if (sep == ' ') { + ResponseAppend_P( PSTR("\"%s\":"), me->name ); + } else { + ResponseAppend_P( PSTR("%c\"%s\":"), sep, me->name ); + } - // Now JSON separator is needed - sep =','; + if (!isNumber) { + // Some values contains space + if (strcmp(me->name, "NGTF")==0 || strcmp(me->name, "LTARF")==0 || strcmp(me->name, "MSG1")==0) { + char trimmed_value[strlen(me->value)+1]; + strcpy(trimmed_value, me->value); + ResponseAppend_P( PSTR("\"%s\""), Trim(trimmed_value) ); + } else { + ResponseAppend_P( PSTR("\"%s\""), me->value ); + } + + } else { + ResponseAppend_P( PSTR("%ld"), atol(me->value)); + } + + // Now JSON separator is needed + sep =','; + } } + + } else { + AddLog(LOG_LEVEL_WARNING, PSTR("TIC: bad checksum for %s"), me->name); } } } @@ -897,6 +906,34 @@ bool TInfoCmd(void) { } break; + case CMND_TELEINFO_STATS: { + char stats_name[MAX_TINFO_COMMAND_NAME]; + // Get the raw name + GetTextIndexed(statsname, MAX_TINFO_COMMAND_NAME, command_code, kTInfo_Commands); + int l = strlen(stats_name); + // At least "EnergyConfig Stats" plus one space and one (or more) digit + // so "EnergyConfig Stats" or "EnergyConfig Stats 0" + if ( pValue ) { + int value = atoi(pValue); + if (value==0 || value==1) { + Settings->teleinfo.show_stats = value ; + AddLog(LOG_LEVEL_INFO, PSTR("TIC: Show stats=%d"), value); + } else if (value == 2) { + tinfo.clearstats(); + AddLog(LOG_LEVEL_INFO, PSTR("TIC: Stats cleared")); + } else { + AddLog(LOG_LEVEL_INFO, PSTR("TIC: bad Stats param '%d'"), value); + } + } + // Show stats + AddLog(LOG_LEVEL_INFO, PSTR("TIC: Frame error CheckSum:%d Size:%d Format:%d Interrupt:%d"), + tinfo.getChecksumErrorCount(), + tinfo.getFrameSizeErrorCount(), + tinfo.getFrameFormatErrorCount(), + tinfo.getFrameInterruptedCount() ); + } + break; + default: AddLog(LOG_LEVEL_INFO, PSTR("TIC: bad cmd param '%s'"), pParam); break;