From de52580a18f5034fcaae69f045ce6509c108e003 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 20 Jul 2022 14:25:40 +0200 Subject: [PATCH] sml special options descriptor --- tasmota/tasmota_xsns_sensor/xsns_53_sml.ino | 177 ++++++++++++++++++-- 1 file changed, 163 insertions(+), 14 deletions(-) diff --git a/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino b/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino index 319c2b4b6..c3a9a9743 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino @@ -78,6 +78,7 @@ #define DJ_VAVG "Volt_avg" #define DJ_COUNTER "Count" + struct METER_DESC { int8_t srcpin; uint8_t type; @@ -91,8 +92,28 @@ struct METER_DESC { uint8_t max_index; char *script_str; uint8_t sopt; +#ifdef USE_SML_SPECOPT + uint32_t so_obis1; + uint32_t so_obis2; + uint8_t so_fcode1; + uint8_t so_bpos1; + uint8_t so_fcode2; + uint8_t so_bpos2; +#endif }; +// max number of meters , may be adjusted +#ifndef MAX_METERS +#define MAX_METERS 5 +#endif + +#ifdef USE_SCRIPT +struct METER_DESC script_meter_desc[MAX_METERS]; +uint8_t *script_meter; +#endif + + + // this descriptor method is no longer supported // but still functional for simple meters // use scripting method instead @@ -480,10 +501,7 @@ const uint8_t meter[]= #define SML_MAX_VARS 20 #endif -// max number of meters , may be adjusted -#ifndef MAX_METERS -#define MAX_METERS 5 -#endif + double meter_vars[SML_MAX_VARS]; // calulate deltas #define MAX_DVARS MAX_METERS*2 @@ -1236,7 +1254,7 @@ void Hexdump(uint8_t *sbuff, uint32_t slen) { AddLogData(LOG_LEVEL_INFO, cbuff); } -#if defined(ED300L) || defined(AS2020) +#if defined(ED300L) || defined(AS2020) || defined(DTZ541) || defined(USE_SML_SPECOPT) uint8_t sml_status[MAX_METERS]; uint8_t g_mindex; #endif @@ -1293,6 +1311,46 @@ double dval; sml_status[g_mindex]=*(cp+1); } #endif +#ifdef DTZ541 + unsigned char *cpx=cp-5; + // decode OBIS 0180 amd extract direction info + if (*cp==0x65 && *cpx==0 && *(cpx+1)==0x01 && *(cpx+2)==0x08 && *(cpx+3)==0) { + sml_status[g_mindex]=*(cp+3); + } +#endif + +#ifdef USE_SML_SPECOPT + unsigned char *cpx = cp - 5; + uint32_t ocode = (*(cpx+0)<<24) | (*(cpx+1)<<16) | (*(cpx+2)<<8) | (*(cpx+3)<<0); + + if (ocode == script_meter_desc[g_mindex].so_obis1) { + sml_status[g_mindex]&=0xfe; + uint32_t flag = 0; + uint16_t bytes = 0; + if (*cp == script_meter_desc[g_mindex].so_fcode1) { + cpx = cp + 1; + bytes = (script_meter_desc[g_mindex].so_fcode1 & 0xf) - 1; + for (uint16_t cnt = 0; cnt < bytes; cnt++) { + flag <<= 8; + flag |= *cpx++; + } + if (flag & (1 << script_meter_desc[g_mindex].so_bpos1)) { + sml_status[g_mindex]|=1; + } + } + if (*cp == script_meter_desc[g_mindex].so_fcode2) { + cpx = cp + 1; + bytes = (script_meter_desc[g_mindex].so_fcode2 & 0xf) - 1; + for (uint16_t cnt = 0; cnt < bytes; cnt++) { + flag <<= 8; + flag |= *cpx++; + } + if (flag & (1 << script_meter_desc[g_mindex].so_bpos1)) { + sml_status[g_mindex]|=1; + } + } + } +#endif cp=skip_sml(cp,&result); // check time @@ -1418,6 +1476,25 @@ double dval; } } #endif + #ifdef DTZ541 + // decode current power OBIS 00 10 07 00 + if (*cpx==0x00 && *(cpx+1)==0x10 && *(cpx+2)==0x07 && *(cpx+3)==0) { + if (sml_status[g_mindex]&0x08) { + // and invert sign on solar feed + dval*=-1; + } + } + #endif + #ifdef USE_SML_SPECOPT + ocode = (*(cpx+0)<<24) | (*(cpx+1)<<16) | (*(cpx+2)<<8) | (*(cpx+3)<<0); + if (ocode == script_meter_desc[g_mindex].so_obis2) { + if (sml_status[g_mindex] & 1) { + // and invert sign on solar feed + dval*=-1; + } + } + #endif + return dval; } @@ -1723,6 +1800,12 @@ void SML_Decode(uint8_t index) { continue; } + if (*mp == '=' && *(mp+1) == 's') { + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } + // =d must handle dindex if (*mp == '=' && *(mp + 1) == 'd') { if (index != mindex) { @@ -1851,6 +1934,11 @@ void SML_Decode(uint8_t index) { mp = strchr(mp, '|'); if (mp) mp++; continue; + } else if (*mp == 's') { + // skip spec option tag line + mp = strchr(mp, '|'); + if (mp) mp++; + continue; } } else { // compare value @@ -2118,8 +2206,8 @@ void SML_Decode(uint8_t index) { // matches, get value dvalid[vindex] = 1; mp++; -#if defined(ED300L) || defined(AS2020) - g_mindex=mindex; +#if defined(ED300L) || defined(AS2020) || defined(DTZ541) || defined(USE_SML_SPECOPT) + g_mindex = mindex; #endif if (*mp == '#') { // get string value @@ -2333,6 +2421,11 @@ void SML_Show(boolean json) { if (mp) mp++; continue; } + if (*mp=='=' && *(mp+1)=='s') { + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } // skip compare section cp=strchr(mp,'@'); if (cp) { @@ -2519,11 +2612,6 @@ uint32_t debounce_time; } -#ifdef USE_SCRIPT -struct METER_DESC script_meter_desc[MAX_METERS]; -uint8_t *script_meter; -#endif - #ifndef METER_DEF_SIZE #define METER_DEF_SIZE 3000 #endif @@ -2583,6 +2671,40 @@ bool Gpio_used(uint8_t gpiopin) { return false; } +#ifdef USE_SML_SPECOPT +void SML_GetSpecOpt(char *cp, uint32_t mnum) { +// special option 1 +// we need 2 obis codes +// 2 flag codes + bit positions +// 1,=so1,00010800,63,7,64,11,00100700 + + if (*cp == ',') { + cp++; + script_meter_desc[mnum].so_obis1 = strtol(cp, &cp, 16); + } + if (*cp == ',') { + cp++; + script_meter_desc[mnum].so_fcode1 = strtol(cp, &cp, 16); + } + if (*cp == ',') { + cp++; + script_meter_desc[mnum].so_bpos1 = strtol(cp, &cp, 10); + } + if (*cp == ',') { + cp++; + script_meter_desc[mnum].so_fcode2 = strtol(cp, &cp, 16); + } + if (*cp == ',') { + cp++; + script_meter_desc[mnum].so_bpos2 = strtol(cp, &cp, 10); + } + if (*cp == ',') { + cp++; + script_meter_desc[mnum].so_obis2 = strtol(cp, &cp, 16); + } +} +#endif + void SML_Init(void) { meters_used=METERS_USED; meter_desc_p=meter_desc; @@ -2599,6 +2721,13 @@ void SML_Init(void) { meter_spos[cnt]=0; } +#ifdef USE_SML_SPECOPT + for (uint32_t cnt = 0; cnt < MAX_METERS; cnt++) { + script_meter_desc[cnt].so_obis1 = 0; + script_meter_desc[cnt].so_obis2 = 0; + } +#endif + #ifdef USE_SCRIPT for (uint32_t cnt=0;cntmeters_used) return 0; meter--; -#if defined(ED300L) || defined(AS2020) +#if defined(ED300L) || defined(AS2020) || defined(DTZ541) || defined(USE_SML_SPECOPT) return sml_status[meter]; #else return 0; @@ -3055,6 +3203,7 @@ uint32_t SML_Status(uint32_t meter) { } + uint32_t SML_Write(uint32_t meter,char *hstr) { if (meter<1 || meter>meters_used) return 0; meter--;