first try of command management

This commit is contained in:
Charles 2021-04-08 20:02:19 +02:00
parent 1a2addfc16
commit 55ea5073f2
1 changed files with 155 additions and 37 deletions

View File

@ -38,6 +38,28 @@
#define TINFO_READ_TIMEOUT 400 #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 // All contract type for legacy, standard mode has in clear text
enum TInfoContrat{ enum TInfoContrat{
CONTRAT_BAS = 1, // BASE => Option Base. CONTRAT_BAS = 1, // BASE => Option Base.
@ -126,6 +148,7 @@ bool tinfo_found = false;
int contrat; int contrat;
int tarif; int tarif;
int isousc; int isousc;
int raw_skip;
/*********************************************************************************************/ /*********************************************************************************************/
@ -366,10 +389,11 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
Function: responseDumpTInfo Function: responseDumpTInfo
Purpose : add teleinfo values into JSON response Purpose : add teleinfo values into JSON response
Input : 1st separator space if begining of JSON, else comma Input : 1st separator space if begining of JSON, else comma
: select if append all data or just changed one
Output : - Output : -
Comments: - Comments: -
====================================================================== */ ====================================================================== */
void ResponseAppendTInfo(char sep) void ResponseAppendTInfo(char sep, bool all)
{ {
struct _ValueList * me = tinfo.getList(); struct _ValueList * me = tinfo.getList();
@ -383,32 +407,37 @@ void ResponseAppendTInfo(char sep)
me = me->next; me = me->next;
if (me->name && me->value && *me->name && *me->value) { if (me->name && me->value && *me->name && *me->value) {
isNumber = true;
p = me->value;
// Specific treatment serial number don't convert to number later // Add values only if we want all data or if data has changed
if (strcmp(me->name, "ADCO")==0 || strcmp(me->name, "ADSC")==0) { if (all || ( Settings.teleinfo.raw_report_changed && (me->flags & (TINFO_FLAGS_UPDATED | TINFO_FLAGS_ADDED | TINFO_FLAGS_ALERT) ) ) ) {
isNumber = false;
} else { isNumber = true;
// check if value is number p = me->value;
while (*p && isNumber) {
if ( *p < '0' || *p > '9' ) { // Specific treatment serial number don't convert to number later
isNumber = false; 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 // Reset Energy Watchdog
Energy.data_valid[0] = 0; Energy.data_valid[0] = 0;
// send teleinfo full frame only if setup like that // Deprecated see setOption108
// see setOption108 // send teleinfo raw data only if setup like that
if (Settings.flag4.teleinfo_rawdata) { if (Settings.teleinfo.raw_send) {
Response_P(PSTR("{")); // Do we need to skip this frame
ResponseAppendTInfo(' '); if (raw_skip>0) {
ResponseJsonEnd(); raw_skip--;
// Publish adding ADCO serial number into the topic }
// Need setOption4 to be enabled
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, serialNumber, false); 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 baudrate;
int serial_buffer_size; int serial_buffer_size;
// Deprecated SetOption102 - Set Baud rate for Teleinfo serial communication (0 = 1200 or 1 = 9600)
// SetOption102 - Set Baud rate for Teleinfo serial communication (0 = 1200 or 1 = 9600) // now set in bit field TeleinfoCfg
if (Settings.flag4.teleinfo_baudrate) { if (Settings.teleinfo.mode_standard) {
baudrate = 9600; baudrate = 9600;
tinfo_mode = TINFO_MODE_STANDARD; tinfo_mode = TINFO_MODE_STANDARD;
serial_buffer_size = TELEINFO_SERIAL_BUFFER_STANDARD; serial_buffer_size = TELEINFO_SERIAL_BUFFER_STANDARD;
@ -475,6 +517,7 @@ void TInfoInit(void)
serial_buffer_size = TELEINFO_SERIAL_BUFFER_HISTORIQUE; serial_buffer_size = TELEINFO_SERIAL_BUFFER_HISTORIQUE;
} }
if (PinUsed(GPIO_TELEINFO_RX)) { if (PinUsed(GPIO_TELEINFO_RX)) {
int8_t rx_pin = Pin(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); 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.attachNewFrame(NewFrameCallback);
tinfo_found = true; 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")); 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 Function: TInfoProcess
Purpose : Tasmota callback executed often enough to read serial Purpose : Tasmota callback executed often enough to read serial
@ -614,7 +726,7 @@ void TInfoShow(bool json)
} }
// add teleinfo full frame // add teleinfo full frame
ResponseAppendTInfo(','); ResponseAppendTInfo(',', true);
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
} }
@ -696,11 +808,17 @@ void TInfoShow(bool json)
\*********************************************************************************************/ \*********************************************************************************************/
bool Xnrg15(uint8_t function) bool Xnrg15(uint8_t function)
{ {
bool result = false;
switch (function) switch (function)
{ {
case FUNC_EVERY_250_MSECOND: case FUNC_EVERY_250_MSECOND:
TInfoProcess(); TInfoProcess();
break; break;
case FUNC_COMMAND:
AddLog(LOG_LEVEL_INFO, PSTR("TIC: FUNC_COMMAND"));
result = TInfoCmd();
break;
case FUNC_JSON_APPEND: case FUNC_JSON_APPEND:
TInfoShow(1); TInfoShow(1);
break; break;
@ -716,7 +834,7 @@ bool Xnrg15(uint8_t function)
TInfoDrvInit(); TInfoDrvInit();
break; break;
} }
return false; return result;
} }
#endif // USE_TELEINFO #endif // USE_TELEINFO