Added basic support for new Standard mode of Linky

This commit is contained in:
Charles 2020-08-11 19:58:24 +02:00
parent 48a346c443
commit ca02de910d
1 changed files with 112 additions and 46 deletions

View File

@ -30,7 +30,6 @@
* {"NAME":"WifInfo","GPIO":[7,255,255,210,6,5,255,255,255,255,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}
* *
\*********************************************************************************************/ \*********************************************************************************************/
#define XNRG_15 15 #define XNRG_15 15
#include "LibTeleinfo.h" #include "LibTeleinfo.h"
@ -38,7 +37,7 @@
#define TINFO_READ_TIMEOUT 400 #define TINFO_READ_TIMEOUT 400
// All contract type // 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.
CONTRAT_HC, // HC.. => Option Heures Creuses. CONTRAT_HC, // HC.. => Option Heures Creuses.
@ -47,17 +46,17 @@ enum TInfoContrat{
CONTRAT_END CONTRAT_END
}; };
// contract displayed name // contract displayed name for legacy, standard mode has in clear text
const char kContratName[] PROGMEM = const char kContratName[] PROGMEM =
"|Base|Heures Creuses|EJP|Bleu Blanc Rouge" "|Base|Heures Creuses|EJP|Bleu Blanc Rouge"
; ;
// Received current contract value // Received current contract value for legacy, standard mode has in clear text
const char kContratValue[] PROGMEM = const char kContratValue[] PROGMEM =
"|BASE|HC..|EJP.|BBR" "|BASE|HC..|EJP.|BBR"
; ;
// all tariff type // all tariff type for legacy, standard mode has in clear text
enum TInfoTarif{ enum TInfoTarif{
TARIF_TH = 1, TARIF_TH = 1,
TARIF_HC, TARIF_HP, TARIF_HC, TARIF_HP,
@ -67,7 +66,8 @@ enum TInfoTarif{
TARIF_END TARIF_END
}; };
// Received current tariff values // Received current tariff values
// for legacy, standard mode has in clear text
const char kTarifValue[] PROGMEM = const char kTarifValue[] PROGMEM =
"|TH..|HC..|HP.." "|TH..|HC..|HP.."
"|HN..|PM.." "|HN..|PM.."
@ -75,7 +75,7 @@ const char kTarifValue[] PROGMEM =
"|HPJB|HPJW|HPJR" "|HPJB|HPJW|HPJR"
; ;
// tariff displayed name // tariff displayed name (for legacy, standard mode has in clear text)
const char kTarifName[] PROGMEM = const char kTarifName[] PROGMEM =
"|Toutes|Creuses|Pleines" "|Toutes|Creuses|Pleines"
"|Normales|Pointe Mobile" "|Normales|Pointe Mobile"
@ -83,27 +83,30 @@ const char kTarifName[] PROGMEM =
"|Pleines Bleu|Pleines Blanc|Pleines Rouges" "|Pleines Bleu|Pleines Blanc|Pleines Rouges"
; ;
// Label used to do some post processing and/or calculation
enum TInfoLabel{ enum TInfoLabel{
LABEL_BASE = 1, LABEL_BASE = 1,
LABEL_ADCO, LABEL_ADCO, LABEL_ADSC,
LABEL_HCHC, LABEL_HCHP, LABEL_HCHC, LABEL_HCHP, LABEL_EAST, LABEL_EASF01, LABEL_EASF02,
LABEL_OPTARIF, LABEL_ISOUSC, LABEL_PTEC, LABEL_OPTARIF, LABEL_NGTF, LABEL_ISOUSC, LABEL_PREF, LABEL_PTEC, LABEL_LTARF, LABEL_NTARF,
LABEL_PAPP, LABEL_IINST, LABEL_TENSION, LABEL_PAPP, LABEL_SINSTS, LABEL_IINST, LABEL_IRMS1, LABEL_TENSION, LABEL_URMS1,
LABEL_IMAX, LABEL_PMAX, LABEL_IMAX, LABEL_PMAX, LABEL_SMAXSN,
LABEL_DEMAIN, LABEL_DEMAIN,
LABEL_END LABEL_END
}; };
const char kLabel[] PROGMEM = const char kLabel[] PROGMEM =
"|BASE|ADCO|HCHC|HCHP" "|BASE|ADCO|ADSC"
"|OPTARIF|ISOUSC|PTEC" "|HCHC|HCHP|EAST|EASF01|EASF02"
"|PAPP|IINST|TENSION" "|OPTARIF|NGTF|ISOUSC|PREF|PTEC|LTARF|NTARF"
"|IMAX|PMAX" "|PAPP|SINSTS|IINST|IRMS1|TENSION|URMS1"
"|IMAX|PMAX|SMAXSN"
"|DEMAIN" "|DEMAIN"
; ;
TInfo tinfo; // Teleinfo object TInfo tinfo; // Teleinfo object
TasmotaSerial *TInfoSerial = nullptr; TasmotaSerial *TInfoSerial = nullptr;
_Mode_e tinfo_mode = TINFO_MODE_HISTORIQUE;
bool tinfo_found = false; bool tinfo_found = false;
int contrat; int contrat;
int tarif; int tarif;
@ -147,10 +150,12 @@ void ADPSCallback(uint8_t phase)
if (phase == 0){ if (phase == 0){
phase = 1; phase = 1;
} }
if (getValueFromLabelIndex(LABEL_ADCO, adco)) { if (tinfo_mode == TINFO_MODE_HISTORIQUE) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"ADPS\":%i}}"), adco, phase ); if (getValueFromLabelIndex(LABEL_ADCO, adco) ) {
MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"ADPS\":%i}}"), adco, phase );
MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data);
}
} }
AddLog_P2(LOG_LEVEL_INFO, PSTR("ADPS on phase %d"), phase); AddLog_P2(LOG_LEVEL_INFO, PSTR("ADPS on phase %d"), phase);
@ -180,7 +185,7 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
} }
} }
// Current tariff // Current tariff (legacy)
if (ilabel == LABEL_PTEC) if (ilabel == LABEL_PTEC)
{ {
char tarif_value[] = " "; // 4 spaces char tarif_value[] = " "; // 4 spaces
@ -194,8 +199,21 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif changed, now '%s' (%d)"), me->value, tarif); 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) // Voltage V (not present on all Smart Meter)
else if ( ilabel == LABEL_TENSION) else if ( ilabel == LABEL_TENSION || ilabel == LABEL_URMS1)
{ {
Energy.voltage_available = true; Energy.voltage_available = true;
Energy.voltage[0] = (float) atoi(me->value); Energy.voltage[0] = (float) atoi(me->value);
@ -207,7 +225,7 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
} }
// Current I // Current I
else if (ilabel == LABEL_IINST) else if (ilabel == LABEL_IINST || ilabel == LABEL_IRMS1)
{ {
if (!Energy.voltage_available) { if (!Energy.voltage_available) {
Energy.current[0] = (float) atoi(me->value); Energy.current[0] = (float) atoi(me->value);
@ -218,7 +236,7 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
} }
// Power P // Power P
else if (ilabel == LABEL_PAPP) else if (ilabel == LABEL_PAPP || ilabel == LABEL_SINSTS)
{ {
int papp = atoi(me->value); int papp = atoi(me->value);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Power %s, now %d"), me->value, papp); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Power %s, now %d"), me->value, papp);
@ -229,7 +247,7 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
} }
} }
// Wh indexes // Wh indexes (legacy)
else if ( ilabel == LABEL_HCHC || ilabel == LABEL_HCHP) else if ( ilabel == LABEL_HCHC || ilabel == LABEL_HCHP)
{ {
char value[32]; char value[32];
@ -244,7 +262,25 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u HP:%u Total:%u"), hc, hp, total); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u HP:%u Total:%u"), hc, hp, total);
} }
// Contract subscribed // Wh total index (standard)
else if ( ilabel == LABEL_EAST)
{
uint32_t total = atoi(me->value);
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) else if (ilabel == LABEL_OPTARIF)
{ {
char contrat_value[] = " "; // 4 spaces char contrat_value[] = " "; // 4 spaces
@ -257,9 +293,14 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
} }
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s' (%d)"), me->value, contrat); 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) // Contract subscribed (Power)
else if (ilabel == LABEL_ISOUSC) else if (ilabel == LABEL_ISOUSC || ilabel == LABEL_PREF)
{ {
isousc = atoi( me->value); isousc = atoi( me->value);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: ISousc set to %d"), isousc); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: ISousc set to %d"), isousc);
@ -285,7 +326,6 @@ void NewFrameCallback(struct _ValueList * me)
Energy.data_valid[0] = 0; Energy.data_valid[0] = 0;
} }
/* ====================================================================== /* ======================================================================
Function: TInfoDrvInit Function: TInfoDrvInit
Purpose : Tasmota core driver init Purpose : Tasmota core driver init
@ -311,13 +351,20 @@ Comments: -
====================================================================== */ ====================================================================== */
void TInfoInit(void) void TInfoInit(void)
{ {
#ifdef USE_TELEINFO_STANDARD int baudrate;
#define TINFO_SPEED 9600
#else
#define TINFO_SPEED 1200
#endif
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: inferface speed %d bps"),TINFO_SPEED); AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: inferface saved settings %d bps"), Settings.flag4.teleinfo_baudrate );
// SetOption102 - Set Baud rate for Teleinfo serial communication (0 = 1200 or 1 = 9600)
if (Settings.flag4.teleinfo_baudrate) {
baudrate = 9600;
tinfo_mode = TINFO_MODE_STANDARD;
} else {
baudrate = 1200;
tinfo_mode = TINFO_MODE_HISTORIQUE;
}
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: inferface speed %d bps"),baudrate);
if (PinUsed(GPIO_TELEINFO_RX)) { if (PinUsed(GPIO_TELEINFO_RX)) {
uint8_t rx_pin = Pin(GPIO_TELEINFO_RX); uint8_t rx_pin = Pin(GPIO_TELEINFO_RX);
@ -333,12 +380,17 @@ void TInfoInit(void)
AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: always enabled")); AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: always enabled"));
} }
TInfoSerial = new TasmotaSerial(rx_pin, -1, 1); #if defined (ESP8266)
// Allow GPIO3 AND GPIO13 with hardware fallback to 2
TInfoSerial = new TasmotaSerial(rx_pin, -1, 2);
//pinMode(rx_pin, INPUT_PULLUP); //pinMode(rx_pin, INPUT_PULLUP);
#else
TInfoSerial = new TasmotaSerial(rx_pin, -1, 1);
#endif
// Trick here even using SERIAL_7E1 or TS_SERIAL_7E1 // Trick here even using SERIAL_7E1 or TS_SERIAL_7E1
// this is not working, need to call SetSerialConfig after // this is not working, need to call SetSerialConfig after
if (TInfoSerial->begin(TINFO_SPEED)) { if (TInfoSerial->begin(baudrate)) {
#if defined (ESP8266) #if defined (ESP8266)
@ -360,7 +412,7 @@ void TInfoInit(void)
AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: using ESP32 hardware serial")); AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: using ESP32 hardware serial"));
#endif #endif
// Init teleinfo // Init teleinfo
tinfo.init(); tinfo.init(tinfo_mode);
// Attach needed callbacks // Attach needed callbacks
tinfo.attachADPS(ADPSCallback); tinfo.attachADPS(ADPSCallback);
tinfo.attachData(DataCallback); tinfo.attachData(DataCallback);
@ -479,15 +531,29 @@ void TInfoShow(bool json)
WSContentSend_PD(HTTP_ENERGY_PMAX_TELEINFO, atoi(value)); WSContentSend_PD(HTTP_ENERGY_PMAX_TELEINFO, atoi(value));
} }
if (tarif) { if (tinfo_mode==TINFO_MODE_STANDARD ) {
GetTextIndexed(name, sizeof(name), tarif-1, kTarifName); if (tarif) {
WSContentSend_PD(HTTP_ENERGY_TARIF_TELEINFO, name); GetTextIndexed(name, sizeof(name), tarif-1, kTarifName);
} WSContentSend_PD(HTTP_ENERGY_TARIF_TELEINFO, name);
if (contrat && isousc) { }
int percent = (int) ((Energy.current[0]*100.0f) / isousc) ; if (contrat && isousc) {
GetTextIndexed(name, sizeof(name), contrat, kContratName); int percent = (int) ((Energy.current[0]*100.0f) / isousc) ;
WSContentSend_PD(HTTP_ENERGY_CONTRAT_TELEINFO, name, isousc); GetTextIndexed(name, sizeof(name), contrat, kContratName);
WSContentSend_PD(HTTP_ENERGY_LOAD_TELEINFO, percent); WSContentSend_PD(HTTP_ENERGY_CONTRAT_TELEINFO, name, isousc);
WSContentSend_PD(HTTP_ENERGY_LOAD_TELEINFO, percent);
}
} else {
if (getValueFromLabelIndex(LABEL_LTARF, name) ) {
WSContentSend_PD(HTTP_ENERGY_TARIF_TELEINFO, name);
}
if (getValueFromLabelIndex(LABEL_NGTF, name) ) {
if (isousc) {
int percent = (int) ((Energy.current[0]*100.0f) / isousc) ;
WSContentSend_PD(HTTP_ENERGY_CONTRAT_TELEINFO, name, isousc);
WSContentSend_PD(HTTP_ENERGY_LOAD_TELEINFO, percent);
}
}
} }
#endif // USE_WEBSERVER #endif // USE_WEBSERVER
} }