sml update

fix SML ESP32 uart handling
add replace cmd vars to SML section
add * option to SML WeBGUI
scripter add optional ws2812 array offset
scripter negative for next  loops
This commit is contained in:
gemu2015 2020-05-15 15:30:32 +02:00
parent bafe8a137f
commit 1bbc77e6a7
2 changed files with 173 additions and 36 deletions

View File

@ -641,13 +641,14 @@ char *script;
#ifdef USE_LIGHT #ifdef USE_LIGHT
#ifdef USE_WS2812 #ifdef USE_WS2812
void ws2812_set_array(float *array ,uint8_t len) { void ws2812_set_array(float *array ,uint32_t len, uint32_t offset) {
Ws2812ForceSuspend(); Ws2812ForceSuspend();
for (uint8_t cnt=0;cnt<len;cnt++) { for (uint32_t cnt=0;cnt<len;cnt++) {
if (cnt>Settings.light_pixels) break; uint32_t index=cnt+offset;
if (index>Settings.light_pixels) break;
uint32_t col=array[cnt]; uint32_t col=array[cnt];
Ws2812SetColor(cnt+1,col>>16,col>>8,col,0); Ws2812SetColor(index+1,col>>16,col>>8,col,0);
} }
Ws2812ForceUpdate(); Ws2812ForceUpdate();
} }
@ -2444,7 +2445,7 @@ char *ForceStringVar(char *lp,char *dstr) {
} }
// replace vars in cmd %var% // replace vars in cmd %var%
void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) { void Replace_Cmd_Vars(char *srcbuf,uint32_t srcsize, char *dstbuf,uint32_t dstsize) {
char *cp; char *cp;
uint16_t count; uint16_t count;
uint8_t vtype; uint8_t vtype;
@ -2455,6 +2456,7 @@ void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) {
char string[SCRIPT_MAXSSIZE]; char string[SCRIPT_MAXSSIZE];
dstsize-=2; dstsize-=2;
for (count=0;count<dstsize;count++) { for (count=0;count<dstsize;count++) {
if (srcsize && (*cp==SCRIPT_EOL)) break;
if (*cp=='%') { if (*cp=='%') {
cp++; cp++;
if (*cp=='%') { if (*cp=='%') {
@ -2869,7 +2871,11 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
lp=GetNumericResult(lp,OPER_EQU,&cv_inc,0); lp=GetNumericResult(lp,OPER_EQU,&cv_inc,0);
//SCRIPT_SKIP_EOL //SCRIPT_SKIP_EOL
cv_ptr=lp; cv_ptr=lp;
if (*cv_count<cv_max) {
floop=1; floop=1;
} else {
floop=2;
}
} else { } else {
// error // error
toLogEOL("for error",lp); toLogEOL("for error",lp);
@ -2877,12 +2883,21 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
} else if (!strncmp(lp,"next",4) && floop>0) { } else if (!strncmp(lp,"next",4) && floop>0) {
// for next loop // for next loop
*cv_count+=cv_inc; *cv_count+=cv_inc;
if (floop==1) {
if (*cv_count<=cv_max) { if (*cv_count<=cv_max) {
lp=cv_ptr; lp=cv_ptr;
} else { } else {
lp+=4; lp+=4;
floop=0; floop=0;
} }
} else {
if (*cv_count>=cv_max) {
lp=cv_ptr;
} else {
lp+=4;
floop=0;
}
}
} }
if (!strncmp(lp,"switch",6)) { if (!strncmp(lp,"switch",6)) {
@ -3010,6 +3025,12 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
lp+=7; lp+=7;
lp=isvar(lp,&vtype,&ind,0,0,0); lp=isvar(lp,&vtype,&ind,0,0,0);
if (vtype!=VAR_NV) { if (vtype!=VAR_NV) {
SCRIPT_SKIP_SPACES
if (*lp!=')') {
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
} else {
fvar=0;
}
// found variable as result // found variable as result
uint8_t index=glob_script_mem.type[ind.index].index; uint8_t index=glob_script_mem.type[ind.index].index;
if ((vtype&STYPE)==0) { if ((vtype&STYPE)==0) {
@ -3018,7 +3039,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
uint8_t len=0; uint8_t len=0;
float *fa=Get_MFAddr(index,&len); float *fa=Get_MFAddr(index,&len);
//Serial.printf(">> 2 %d\n",(uint32_t)*fa); //Serial.printf(">> 2 %d\n",(uint32_t)*fa);
if (fa && len) ws2812_set_array(fa,len); if (fa && len) ws2812_set_array(fa,len,fvar);
} }
} }
} }
@ -3069,7 +3090,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
//AddLog_P(LOG_LEVEL_INFO, tmp); //AddLog_P(LOG_LEVEL_INFO, tmp);
// replace vars in cmd // replace vars in cmd
char *tmp=cmdmem+SCRIPT_CMDMEM/2; char *tmp=cmdmem+SCRIPT_CMDMEM/2;
Replace_Cmd_Vars(cmd,tmp,SCRIPT_CMDMEM/2); Replace_Cmd_Vars(cmd,0,tmp,SCRIPT_CMDMEM/2);
//toSLog(tmp); //toSLog(tmp);
if (!strncmp(tmp,"print",5) || pflg) { if (!strncmp(tmp,"print",5) || pflg) {
@ -4198,7 +4219,7 @@ void Script_Check_Hue(String *response) {
} }
cp++; cp++;
} }
Replace_Cmd_Vars(line,tmp,sizeof(tmp)); Replace_Cmd_Vars(line,0,tmp,sizeof(tmp));
// check for hue defintions // check for hue defintions
// NAME, TYPE , vars // NAME, TYPE , vars
cp=tmp; cp=tmp;
@ -5043,7 +5064,7 @@ void ScriptWebShow(char mc) {
WSContentSend_PD(SCRIPT_MSG_NUMINP,label,minstr,maxstr,stepstr,vstr,vname); WSContentSend_PD(SCRIPT_MSG_NUMINP,label,minstr,maxstr,stepstr,vstr,vname);
} else { } else {
Replace_Cmd_Vars(lin,tmp,sizeof(tmp)); Replace_Cmd_Vars(lin,0,tmp,sizeof(tmp));
if (optflg) { if (optflg) {
WSContentSend_PD(PSTR("<div>%s</div>"),tmp); WSContentSend_PD(PSTR("<div>%s</div>"),tmp);
} else { } else {
@ -5052,7 +5073,7 @@ void ScriptWebShow(char mc) {
} }
} else { } else {
if (*lin==mc) { if (*lin==mc) {
Replace_Cmd_Vars(lin+1,tmp,sizeof(tmp)); Replace_Cmd_Vars(lin+1,0,tmp,sizeof(tmp));
WSContentSend_PD(PSTR("%s"),tmp); WSContentSend_PD(PSTR("%s"),tmp);
} }
} }
@ -5097,7 +5118,7 @@ uint8_t msect=Run_Scripter(">m",-2,0);
} }
cp++; cp++;
} }
Replace_Cmd_Vars(line,tmp,sizeof(tmp)); Replace_Cmd_Vars(line,0,tmp,sizeof(tmp));
//client->println(tmp); //client->println(tmp);
func(tmp); func(tmp);
} }
@ -5142,7 +5163,7 @@ void ScriptJsonAppend(void) {
} }
cp++; cp++;
} }
Replace_Cmd_Vars(line,tmp,sizeof(tmp)); Replace_Cmd_Vars(line,0,tmp,sizeof(tmp));
ResponseAppend_P(PSTR("%s"),tmp); ResponseAppend_P(PSTR("%s"),tmp);
} }
if (*lp==SCRIPT_EOL) { if (*lp==SCRIPT_EOL) {

View File

@ -45,7 +45,9 @@
#include <TasmotaSerial.h> #include <TasmotaSerial.h>
// use special no wait serial driver, should be always on // use special no wait serial driver, should be always on
#ifndef ESP32
#define SPECIAL_SS #define SPECIAL_SS
#endif
// addresses a bug in meter DWS74 // addresses a bug in meter DWS74
//#define DWS74_BUG //#define DWS74_BUG
@ -440,7 +442,9 @@ const uint8_t meter[]=
#endif #endif
// max number of meters , may be adjusted // max number of meters , may be adjusted
#ifndef MAX_METERS
#define MAX_METERS 5 #define MAX_METERS 5
#endif
double meter_vars[SML_MAX_VARS]; double meter_vars[SML_MAX_VARS];
// calulate deltas // calulate deltas
#define MAX_DVARS MAX_METERS*2 #define MAX_DVARS MAX_METERS*2
@ -453,7 +457,11 @@ const uint8_t *meter_p;
uint8_t meter_spos[MAX_METERS]; uint8_t meter_spos[MAX_METERS];
// software serial pointers // software serial pointers
#ifdef ESP32
HardwareSerial *meter_ss[MAX_METERS];
#else
TasmotaSerial *meter_ss[MAX_METERS]; TasmotaSerial *meter_ss[MAX_METERS];
#endif
// serial buffers, may be made larger depending on telegram lenght // serial buffers, may be made larger depending on telegram lenght
#define SML_BSIZ 48 #define SML_BSIZ 48
@ -774,18 +782,21 @@ uint8_t dump2log=0;
bool Serial_available() { bool Serial_available() {
uint8_t num=dump2log&7; uint8_t num=dump2log&7;
if (num<1 || num>meters_used) num=1; if (num<1 || num>meters_used) num=1;
if (!meter_ss[num-1]) return 0;
return meter_ss[num-1]->available(); return meter_ss[num-1]->available();
} }
uint8_t Serial_read() { uint8_t Serial_read() {
uint8_t num=dump2log&7; uint8_t num=dump2log&7;
if (num<1 || num>meters_used) num=1; if (num<1 || num>meters_used) num=1;
if (!meter_ss[num-1]) return 0;
return meter_ss[num-1]->read(); return meter_ss[num-1]->read();
} }
uint8_t Serial_peek() { uint8_t Serial_peek() {
uint8_t num=dump2log&7; uint8_t num=dump2log&7;
if (num<1 || num>meters_used) num=1; if (num<1 || num>meters_used) num=1;
if (!meter_ss[num-1]) return 0;
return meter_ss[num-1]->peek(); return meter_ss[num-1]->peek();
} }
@ -1186,7 +1197,8 @@ void sml_shift_in(uint32_t meters,uint32_t shard) {
} else if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M') { } else if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M') {
smltbuf[meters][meter_spos[meters]] = iob; smltbuf[meters][meter_spos[meters]] = iob;
meter_spos[meters]++; meter_spos[meters]++;
if (meter_spos[meters]>=9) { uint32_t mlen=smltbuf[meters][2]+5;
if (meter_spos[meters]>=mlen) {
SML_Decode(meters); SML_Decode(meters);
sml_empty_receiver(meters); sml_empty_receiver(meters);
meter_spos[meters]=0; meter_spos[meters]=0;
@ -1236,6 +1248,7 @@ uint32_t meters;
for (meters=0; meters<meters_used; meters++) { for (meters=0; meters<meters_used; meters++) {
if (meter_desc_p[meters].type!='c') { if (meter_desc_p[meters].type!='c') {
// poll for serial input // poll for serial input
if (!meter_ss[meters]) continue;
while (meter_ss[meters]->available()) { while (meter_ss[meters]->available()) {
sml_shift_in(meters,0); sml_shift_in(meters,0);
} }
@ -1530,9 +1543,10 @@ void SML_Decode(uint8_t index) {
if (mb_index!=meter_desc_p[mindex].index) { if (mb_index!=meter_desc_p[mindex].index) {
goto nextsect; goto nextsect;
} }
uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],7); uint16_t pos = smltbuf[mindex][2]+3;
if (lowByte(crc)!=smltbuf[mindex][7]) goto nextsect; uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],pos);
if (highByte(crc)!=smltbuf[mindex][8]) goto nextsect; if (lowByte(crc)!=smltbuf[mindex][pos]) goto nextsect;
if (highByte(crc)!=smltbuf[mindex][pos+1]) goto nextsect;
dval=mbus_dval; dval=mbus_dval;
//AddLog_P2(LOG_LEVEL_INFO, PSTR(">> %s"),mp); //AddLog_P2(LOG_LEVEL_INFO, PSTR(">> %s"),mp);
mp++; mp++;
@ -1728,7 +1742,7 @@ void SML_Show(boolean json) {
} else { } else {
// web ui export // web ui export
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s{s}%s %s: {m}%s %s{e}", b_mqtt_data,meter_desc[mindex].prefix,name,tpowstr,unit); //snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s{s}%s %s: {m}%s %s{e}", b_mqtt_data,meter_desc[mindex].prefix,name,tpowstr,unit);
WSContentSend_PD(PSTR("{s}%s %s: {m}%s %s{e}"),meter_desc_p[mindex].prefix,name,tpowstr,unit); if (strcmp(name,"*")) WSContentSend_PD(PSTR("{s}%s %s: {m}%s %s{e}"),meter_desc_p[mindex].prefix,name,tpowstr,unit);
} }
} }
} }
@ -1830,6 +1844,52 @@ uint8_t *script_meter;
#define METER_DEF_SIZE 3000 #define METER_DEF_SIZE 3000
#endif #endif
#ifdef SML_REPLACE_VARS
#define SML_SRCBSIZE 256
uint32_t SML_getlinelen(char *lp) {
uint32_t cnt;
for (cnt=0; cnt<SML_SRCBSIZE-1; cnt++) {
if (lp[cnt]==SCRIPT_EOL) {
break;
}
}
return cnt;
}
uint32_t SML_getscriptsize(char *lp) {
uint32_t mlen=0;
char dstbuf[SML_SRCBSIZE*2];
while (1) {
Replace_Cmd_Vars(lp,1,dstbuf,sizeof(dstbuf));
lp+=SML_getlinelen(lp)+1;
uint32_t slen=strlen(dstbuf);
//AddLog_P2(LOG_LEVEL_INFO, PSTR("%d - %s"),slen,dstbuf);
mlen+=slen+1;
if (*lp=='#') break;
if (*lp=='>') break;
if (*lp==0) break;
}
//AddLog_P2(LOG_LEVEL_INFO, PSTR("len=%d"),mlen);
return mlen+32;
}
#else
uint32_t SML_getscriptsize(char *lp) {
uint32_t mlen=0;
for (uint32_t cnt=0;cnt<METER_DEF_SIZE-1;cnt++) {
if (lp[cnt]=='\n' && lp[cnt+1]=='#') {
mlen=cnt+3;
break;
}
}
//AddLog_P2(LOG_LEVEL_INFO, PSTR("len=%d"),mlen);
return mlen;
}
#endif
bool Gpio_used(uint8_t gpiopin) { bool Gpio_used(uint8_t gpiopin) {
/* /*
for (uint16_t i=0;i<GPIO_SENSOR_END;i++) { for (uint16_t i=0;i<GPIO_SENSOR_END;i++) {
@ -1865,10 +1925,19 @@ void SML_Init(void) {
for (uint32_t cnt=0;cnt<MAX_METERS;cnt++) { for (uint32_t cnt=0;cnt<MAX_METERS;cnt++) {
if (script_meter_desc[cnt].txmem) { if (script_meter_desc[cnt].txmem) {
free(script_meter_desc[cnt].txmem); free(script_meter_desc[cnt].txmem);
}
script_meter_desc[cnt].txmem=0; script_meter_desc[cnt].txmem=0;
script_meter_desc[cnt].trxpin=-1;
if (meter_ss[cnt]) {
delete meter_ss[cnt];
meter_ss[cnt]=NULL;
} }
} }
if (bitRead(Settings.rule_enabled, 0)) {
uint8_t meter_script=Run_Scripter(">M",-2,0); uint8_t meter_script=Run_Scripter(">M",-2,0);
if (meter_script==99) { if (meter_script==99) {
// use script definition // use script definition
@ -1886,13 +1955,7 @@ void SML_Init(void) {
lp+=2; lp+=2;
meters_used=strtol(lp,0,10); meters_used=strtol(lp,0,10);
section=1; section=1;
uint32_t mlen=0; uint32_t mlen=SML_getscriptsize(lp);
for (uint32_t cnt=0;cnt<METER_DEF_SIZE-1;cnt++) {
if (lp[cnt]=='\n' && lp[cnt+1]=='#') {
mlen=cnt+3;
break;
}
}
if (mlen==0) return; // missing end # if (mlen==0) return; // missing end #
script_meter=(uint8_t*)calloc(mlen,1); script_meter=(uint8_t*)calloc(mlen,1);
if (!script_meter) { if (!script_meter) {
@ -1981,6 +2044,30 @@ dddef_exit:
goto next_line; goto next_line;
} }
#ifdef SML_REPLACE_VARS
char dstbuf[SML_SRCBSIZE*2];
Replace_Cmd_Vars(lp,1,dstbuf,sizeof(dstbuf));
lp+=SML_getlinelen(lp);
//AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),dstbuf);
char *lp1=dstbuf;
if (*lp1=='-' || isdigit(*lp1)) {
//toLogEOL(">>",lp);
// add meters line -1,1-0:1.8.0*255(@10000,H2OIN,cbm,COUNTER,4|
if (*lp1=='-') lp1++;
uint8_t mnum=strtol(lp1,0,10);
if (mnum<1 || mnum>meters_used) goto next_line;
while (1) {
if (*lp1==0) {
*tp++='|';
goto next_line;
}
*tp++=*lp1++;
index++;
if (index>=METER_DEF_SIZE) break;
}
}
#else
if (*lp=='-' || isdigit(*lp)) { if (*lp=='-' || isdigit(*lp)) {
//toLogEOL(">>",lp); //toLogEOL(">>",lp);
// add meters line -1,1-0:1.8.0*255(@10000,H2OIN,cbm,COUNTER,4| // add meters line -1,1-0:1.8.0*255(@10000,H2OIN,cbm,COUNTER,4|
@ -1997,6 +2084,7 @@ dddef_exit:
if (index>=METER_DEF_SIZE) break; if (index>=METER_DEF_SIZE) break;
} }
} }
#endif
} }
@ -2013,6 +2101,7 @@ next_line:
meter_desc_p=script_meter_desc; meter_desc_p=script_meter_desc;
meter_p=script_meter; meter_p=script_meter;
} }
}
#endif #endif
init10: init10:
@ -2024,6 +2113,7 @@ init10:
RtcSettings.pulse_counter[i]=Settings.pulse_counter[i]; RtcSettings.pulse_counter[i]=Settings.pulse_counter[i];
sml_counters[i].sml_cnt_last_ts=millis(); sml_counters[i].sml_cnt_last_ts=millis();
} }
uint32_t uart_index=2;
for (uint8_t meters=0; meters<meters_used; meters++) { for (uint8_t meters=0; meters<meters_used; meters++) {
if (meter_desc_p[meters].type=='c') { if (meter_desc_p[meters].type=='c') {
if (meter_desc_p[meters].flag&2) { if (meter_desc_p[meters].flag&2) {
@ -2058,9 +2148,23 @@ init10:
} else { } else {
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,1); meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,1);
} }
#else
#ifdef ESP32
meter_ss[meters] = new HardwareSerial(uart_index);
uart_index--;
if (uart_index<0) uart_index=0;
#else #else
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1); meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1);
#endif #endif
#endif
#ifdef ESP32
if (meter_desc_p[meters].type=='M') {
meter_ss[meters]->begin(meter_desc_p[meters].params, SERIAL_8E1,meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin);
} else {
meter_ss[meters]->begin(meter_desc_p[meters].params,SERIAL_8N1,meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin);
}
#else
if (meter_ss[meters]->begin(meter_desc_p[meters].params)) { if (meter_ss[meters]->begin(meter_desc_p[meters].params)) {
meter_ss[meters]->flush(); meter_ss[meters]->flush();
} }
@ -2069,8 +2173,9 @@ init10:
Serial.begin(meter_desc_p[meters].params, SERIAL_8E1); Serial.begin(meter_desc_p[meters].params, SERIAL_8E1);
} }
ClaimSerial(); ClaimSerial();
//Serial.setRxBufferSize(512);
} }
#endif
} }
} }
@ -2262,6 +2367,11 @@ void SML_Send_Seq(uint32_t meter,char *seq) {
uint8_t sbuff[32]; uint8_t sbuff[32];
uint8_t *ucp=sbuff,slen=0; uint8_t *ucp=sbuff,slen=0;
char *cp=seq; char *cp=seq;
uint8_t rflg = 0;
if (*cp=='r') {
rflg = 1;
cp++;
}
while (*cp) { while (*cp) {
if (!*cp || !*(cp+1)) break; if (!*cp || !*(cp+1)) break;
if (*cp==',') break; if (*cp==',') break;
@ -2272,8 +2382,10 @@ void SML_Send_Seq(uint32_t meter,char *seq) {
if (slen>=sizeof(sbuff)) break; if (slen>=sizeof(sbuff)) break;
} }
if (script_meter_desc[meter].type=='m' || script_meter_desc[meter].type=='M') { if (script_meter_desc[meter].type=='m' || script_meter_desc[meter].type=='M') {
if (!rflg) {
*ucp++=0; *ucp++=0;
*ucp++=2; *ucp++=2;
}
// append crc // append crc
uint16_t crc = MBUS_calculateCRC(sbuff,6); uint16_t crc = MBUS_calculateCRC(sbuff,6);
*ucp++=lowByte(crc); *ucp++=lowByte(crc);
@ -2412,14 +2524,18 @@ bool Xsns53(byte function) {
break; break;
case FUNC_LOOP: case FUNC_LOOP:
SML_Counter_Poll(); SML_Counter_Poll();
break;
case FUNC_EVERY_50_MSECOND:
if (dump2log) Dump2log(); if (dump2log) Dump2log();
else SML_Poll(); else SML_Poll();
break; break;
// case FUNC_EVERY_50_MSECOND:
// if (dump2log) Dump2log();
// else SML_Poll();
// break;
#ifdef USE_SCRIPT #ifdef USE_SCRIPT
case FUNC_EVERY_100_MSECOND: case FUNC_EVERY_100_MSECOND:
if (bitRead(Settings.rule_enabled, 0)) {
SML_Check_Send(); SML_Check_Send();
}
break; break;
#endif // USE_SCRIPT #endif // USE_SCRIPT
case FUNC_JSON_APPEND: case FUNC_JSON_APPEND: