scripter update

add direct access to some energy registers and sml registers
make google charts optional #define USE_GOOGLE_CHARTS
This commit is contained in:
gemu2015 2020-05-23 10:24:08 +02:00
parent 8db2489f59
commit 584b3c2ef8
2 changed files with 335 additions and 132 deletions

View File

@ -1228,6 +1228,52 @@ chknext:
fvar=UtcTime()-(uint32_t)EPOCH_OFFSET; fvar=UtcTime()-(uint32_t)EPOCH_OFFSET;
goto exit; goto exit;
} }
#ifdef USE_ENERGY_SENSOR
if (!strncmp(vname,"enrg[",5)) {
lp+=5;
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
while (*lp==' ') lp++;
switch ((uint32_t)fvar) {
case 0:
fvar=Energy.total;
break;
case 1:
fvar=Energy.voltage[0];
break;
case 2:
fvar=Energy.voltage[1];
break;
case 3:
fvar=Energy.voltage[2];
break;
case 4:
fvar=Energy.current[0];
break;
case 5:
fvar=Energy.current[1];
break;
case 6:
fvar=Energy.current[2];
break;
case 7:
fvar=Energy.active_power[0];
break;
case 8:
fvar=Energy.active_power[1];
break;
case 9:
fvar=Energy.active_power[2];
break;
default:
fvar=99999;
break;
}
len=0;
lp++;
goto exit;
}
#endif //USE_ENERGY_SENSOR
break; break;
case 'f': case 'f':
#ifdef USE_SCRIPT_FATFS #ifdef USE_SCRIPT_FATFS
@ -1948,6 +1994,15 @@ chknext:
} }
#endif #endif
#if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD) #if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD)
if (!strncmp(vname,"sml[",4)) {
lp+=4;
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
SCRIPT_SKIP_SPACES
fvar=SML_GetVal[fvar];
lp++;
len=0;
goto exit;
}
if (!strncmp(vname,"sml(",4)) { if (!strncmp(vname,"sml(",4)) {
lp+=4; lp+=4;
float fvar1; float fvar1;
@ -3948,6 +4003,12 @@ void ScriptSaveSettings(void) {
strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size);
if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') {
AddLog_P2(LOG_LEVEL_INFO, PSTR("script error: must start with >D"));
bitWrite(Settings.rule_enabled, 0, 0);
}
#if defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) #if defined(USE_24C256) && !defined(USE_SCRIPT_FATFS)
if (glob_script_mem.flags&1) { if (glob_script_mem.flags&1) {
EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram);
@ -3983,9 +4044,9 @@ void ScriptSaveSettings(void) {
#ifndef ESP32_SCRIPT_SIZE #ifndef ESP32_SCRIPT_SIZE
//AddLog_P2(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram)); //AddLog_P2(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram));
uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram)+1, Settings.rules[0], MAX_SCRIPT_SIZE-1); uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), Settings.rules[0], MAX_SCRIPT_SIZE-1);
Settings.rules[0][len_compressed] = 0;
if (len_compressed > 0) { if (len_compressed > 0) {
Settings.rules[0][len_compressed] = 0;
AddLog_P2(LOG_LEVEL_INFO,PSTR("script compressed to %d %%"),len_compressed * 100 / strlen(glob_script_mem.script_ram)); AddLog_P2(LOG_LEVEL_INFO,PSTR("script compressed to %d %%"),len_compressed * 100 / strlen(glob_script_mem.script_ram));
} else { } else {
AddLog_P2(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); AddLog_P2(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed);
@ -4899,12 +4960,20 @@ const char SCRIPT_MSG_TEXTINP[] PROGMEM =
const char SCRIPT_MSG_NUMINP[] PROGMEM = const char SCRIPT_MSG_NUMINP[] PROGMEM =
"<div><center><label><b>%s</b><input min='%s' max='%s' step='%s' value='%s' type='number' style='width:200px' onfocusin='pr(0)' onfocusout='pr(1)' onchange='siva(value,\"%s\")'></label></div>"; "<div><center><label><b>%s</b><input min='%s' max='%s' step='%s' value='%s' type='number' style='width:200px' onfocusin='pr(0)' onfocusout='pr(1)' onchange='siva(value,\"%s\")'></label></div>";
#ifdef USE_GOOGLE_CHARTS
const char SCRIPT_MSG_GTABLE[] PROGMEM = const char SCRIPT_MSG_GTABLE[] PROGMEM =
"<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>" "<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>"
"<script type='text/javascript'>google.charts.load('current',{packages:['corechart']});</script>" "<script type='text/javascript'>google.charts.load('current',{packages:['corechart']});</script>"
"<script type='text/javascript'>google.charts.load('current',{packages:['table']});</script>" "<style>.hRow{font-weight:bold;color:black;background-color:lightblue;}.hCol{font-weight:bold;color:black;background-color:lightblue;}.tCell{color:black}</style>"
"<script type='text/javascript'>google.charts.load('current',{packages:['gauge']});</script>" "<style>#chart1{display: inline-block;margin: 0 auto;#timeline text{fill:magenta;}}</style>";
"<style>.hRow{font-weight:bold;color:black;background-color:lightblue;}.hCol{font-weight:bold;color:black;background-color:lightblue;}.tCell{color:black}</style>";
const char SCRIPT_MSG_TABLE[] PROGMEM =
"<script type='text/javascript'>google.charts.load('current',{packages:['table']});</script>";
const char SCRIPT_MSG_GAUGE[] PROGMEM =
"<script type='text/javascript'>google.charts.load('current',{packages:['gauge']});</script>";
const char SCRIPT_MSG_TIMELINE[] PROGMEM =
"<script type='text/javascript'>google.charts.load('current',{packages:['timeline']});</script>";
const char SCRIPT_MSG_GTABLEa[] PROGMEM = const char SCRIPT_MSG_GTABLEa[] PROGMEM =
@ -4913,9 +4982,15 @@ const char SCRIPT_MSG_GTABLEa[] PROGMEM =
"var data=google.visualization.arrayToDataTable(["; "var data=google.visualization.arrayToDataTable([";
const char SCRIPT_MSG_GTABLEd[] PROGMEM =
"['Timeline','start','end'],";
//#define CHART_EXTRA_OPTIONS ",width:'640px',height:'480px'"
#define CHART_EXTRA_OPTIONS
const char SCRIPT_MSG_GTABLEb[] PROGMEM = const char SCRIPT_MSG_GTABLEb[] PROGMEM =
"]);" "]);"
"var options={%s};" "var options={%s" CHART_EXTRA_OPTIONS "};"
"var chart=new google.visualization.%s(document.getElementById('chart%1d'));" "var chart=new google.visualization.%s(document.getElementById('chart%1d'));"
"chart.draw(data,options);}" "chart.draw(data,options);}"
"google.charts.setOnLoadCallback(drawChart);</script>"; "google.charts.setOnLoadCallback(drawChart);</script>";
@ -4923,15 +4998,83 @@ const char SCRIPT_MSG_GTABLEb[] PROGMEM =
const char SCRIPT_MSG_GOPT1[] PROGMEM = const char SCRIPT_MSG_GOPT1[] PROGMEM =
"title:'%s',isStacked:false"; "title:'%s',isStacked:false";
const char SCRIPT_MSG_GOPT3[] PROGMEM =
"title:'%s',vAxes:{0:{maxValue:%d},1:{maxValue:%d}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}";
const char SCRIPT_MSG_GOPT2[] PROGMEM = const char SCRIPT_MSG_GOPT2[] PROGMEM =
"showRowNumber:true,sort:'disable',allowHtml:true,width:'100%%',height:'100%%',cssClassNames:cssc"; "showRowNumber:true,sort:'disable',allowHtml:true,width:'100%%',height:'100%%',cssClassNames:cssc";
const char SCRIPT_MSG_GOPT3[] PROGMEM =
"title:'%s',isStacked:false,vAxes:{0:{maxValue:%d},1:{maxValue:%d}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}%s";
const char SCRIPT_MSG_GOPT4[] PROGMEM =
//"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'}";
"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'},theme: 'maximized'";
const char SCRIPT_MSG_GOPT5[] PROGMEM =
"new Date(0,1,1,%d,%d)";
const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'"; const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'";
#define GLIBS_MAIN 1<<0
#define GLIBS_TABLE 1<<1
#define GLIBS_GAUGE 1<<2
#define GLIBS_TIMELINE 1<<3
#define MAX_GARRAY 4
char *gc_get_arrays(char *lp, float **arrays, uint8_t *ranum, uint8_t *rentries) {
struct T_INDEX ind;
uint8_t vtype;
uint8 entries=0;
uint8_t anum=0;
while (anum<MAX_GARRAY) {
if (*lp==')' || *lp==0) break;
char *lp1=lp;
lp=isvar(lp,&vtype,&ind,0,0,0);
if (vtype!=VAR_NV) {
SCRIPT_SKIP_SPACES
uint8_t index=glob_script_mem.type[ind.index].index;
if ((vtype&STYPE)==0) {
// numeric result
//Serial.printf("numeric %d - %d \n",ind.index,index);
if (glob_script_mem.type[ind.index].bits.is_filter) {
//Serial.printf("numeric array\n");
uint8_t len=0;
float *fa=Get_MFAddr(index,&len);
//Serial.printf(">> 2 %d\n",(uint32_t)*fa);
if (fa && len>=entries) {
if (!entries) {entries = len;}
// add array to list
arrays[anum]=fa;
anum++;
}
}
} else {
lp=lp1;
break;
}
}
}
*ranum=anum;
*rentries=entries;
return lp;
}
char *gc_send_labels(char *lp,uint32_t anum) {
WSContentSend_PD("[");
for (uint32_t cnt=0; cnt<anum+1; cnt++) {
char label[SCRIPT_MAXSSIZE];
lp=GetStringResult(lp,OPER_EQU,label,0);
SCRIPT_SKIP_SPACES
WSContentSend_PD(SCRIPT_MSG_GTE1,label);
//Serial.printf("labels %s\n",label);
if (cnt<anum) { WSContentSend_PD(","); }
}
WSContentSend_PD("],");
return lp;
}
#endif // USE_GOOGLE_CHARTS
void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) { void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) {
uint32_t cnt; uint32_t cnt;
for (cnt=0;cnt<blen-1;cnt++) { for (cnt=0;cnt<blen-1;cnt++) {
@ -5141,66 +5284,130 @@ void ScriptWebShow(char mc) {
} }
} else { } else {
if (*lin==mc) { if (*lin==mc) {
#ifdef USE_GOOGLE_CHARTS
lin++; lin++;
if (!strncmp(lin,"tb(",3)) { if (!strncmp(lin,"gc(",3)) {
// get google table // get google table
struct T_INDEX ind; lp=lin+3;
uint8_t vtype;
char *lp=lin+3;
uint8 entries=0;
#define MAX_GARRAY 4
float *arrays[MAX_GARRAY];
uint8_t anum=0;
while (anum<MAX_GARRAY) {
if (*lp==')' || *lp==0) break;
char *lp1=lp;
lp=isvar(lp,&vtype,&ind,0,0,0);
if (vtype!=VAR_NV) {
SCRIPT_SKIP_SPACES SCRIPT_SKIP_SPACES
uint8_t index=glob_script_mem.type[ind.index].index; const char *type;
if ((vtype&STYPE)==0) { const char *func;
// numeric result char options[256];
//Serial.printf("numeric %d - %d \n",ind.index,index); uint8_t nanum=MAX_GARRAY;
if (glob_script_mem.type[ind.index].bits.is_filter) { uint8_t y2f=0;
//Serial.printf("numeric array\n"); char ctype;
uint8_t len=0; ctype=*lp;
float *fa=Get_MFAddr(index,&len); lp++;
//Serial.printf(">> 2 %d\n",(uint32_t)*fa); if (!(google_libs&GLIBS_MAIN)) {
if (fa && len>=entries) { google_libs|=GLIBS_MAIN;
if (!entries) {entries = len;} WSContentSend_PD(SCRIPT_MSG_GTABLE);
// add array to list
arrays[anum]=fa;
anum++;
} }
switch (ctype) {
case 'l':
type=PSTR("LineChart");
break;
case 'b':
type=PSTR("BarChart");
break;
case 'p':
type=PSTR("PieChart");
break;
case 'g':
type=PSTR("Gauge");
if (!(google_libs&GLIBS_GAUGE)) {
google_libs|=GLIBS_GAUGE;
WSContentSend_PD(SCRIPT_MSG_GAUGE);
} }
} else { break;
lp=lp1; case 't':
type=PSTR("Table");
if (!(google_libs&GLIBS_TABLE)) {
google_libs|=GLIBS_TABLE;
WSContentSend_PD(SCRIPT_MSG_TABLE);
}
break;
case 'T':
type=PSTR("Timeline");
if (!(google_libs&GLIBS_TIMELINE)) {
google_libs|=GLIBS_TIMELINE;
WSContentSend_PD(SCRIPT_MSG_TIMELINE);
}
break;
case 'h':
type=PSTR("Histogram");
break;
case 'c':
type=PSTR("ColumnChart");
break;
default:
// error
goto nextwebline;
break; break;
} }
if (ctype=='l' && *lp=='f') {
lp++;
func=PSTR(",curveType:'function'");
} else {
func="";
} }
if (*lp=='2') {
lp++;
nanum=2;
y2f=1;
} }
SCRIPT_SKIP_SPACES
//Serial.printf("type %d\n",ctype);
float *arrays[MAX_GARRAY];
uint8_t anum=0;
uint8 entries=0;
lp=gc_get_arrays(lp, &arrays[0], &anum, &entries);
if (anum>nanum) {
goto nextwebline;
}
// we know how many arrays and the number of entries
//Serial.printf("arrays %d\n",anum); //Serial.printf("arrays %d\n",anum);
//Serial.printf("entries %d\n",entries); //Serial.printf("entries %d\n",entries);
if (ctype=='T') {
if (!google_libs) { if (anum && !(entries&1)) {
WSContentSend_PD(SCRIPT_MSG_GTABLE);
google_libs=1;
}
WSContentSend_PD(SCRIPT_MSG_GTABLEa); WSContentSend_PD(SCRIPT_MSG_GTABLEa);
WSContentSend_PD(SCRIPT_MSG_GTABLEd);
// we know how many arrays and the number of entries
// we need to fetch the labels now
WSContentSend_PD("[");
for (uint32_t cnt=0; cnt<anum+1; cnt++) {
char label[SCRIPT_MAXSSIZE]; char label[SCRIPT_MAXSSIZE];
lp=GetStringResult(lp,OPER_EQU,label,0); lp=GetStringResult(lp,OPER_EQU,label,0);
SCRIPT_SKIP_SPACES SCRIPT_SKIP_SPACES
WSContentSend_PD(SCRIPT_MSG_GTE1,label); char *lblp=label;
//Serial.printf("labels %s\n",label); for (uint32_t ind=0; ind<anum; ind++) {
if (cnt<anum) { WSContentSend_PD(","); } char lbl[16];
strncpy(lbl,lblp,sizeof(lbl));
for (uint32_t i=0; i<strlen(lblp); i++) {
if (lblp[i]=='|') {
lbl[i]=0;
lblp+=i+1;
break;
} }
WSContentSend_PD("],"); lbl[i]=lblp[i];
}
for (uint32_t cnt=0; cnt<entries; cnt+=2) {
WSContentSend_PD("['%s',",lbl);
float *fp=arrays[ind];
uint32_t time=fp[cnt];
WSContentSend_PD(SCRIPT_MSG_GOPT5,time/60,time%60);
WSContentSend_PD(",");
time=fp[cnt+1];
WSContentSend_PD(SCRIPT_MSG_GOPT5,time/60,time%60);
WSContentSend_PD("]");
if (cnt<entries-2) { WSContentSend_PD(","); }
}
if (ind<anum-1) { WSContentSend_PD(","); }
}
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT4);
}
} else {
// we need to fetch the labels now
WSContentSend_PD(SCRIPT_MSG_GTABLEa);
lp=gc_send_labels(lp,anum);
// now we have to export the values // now we have to export the values
// fetch label part only once in combo string // fetch label part only once in combo string
@ -5234,22 +5441,22 @@ void ScriptWebShow(char mc) {
if (cnt<entries-1) { WSContentSend_PD(","); } if (cnt<entries-1) { WSContentSend_PD(","); }
} }
// get header
char header[SCRIPT_MAXSSIZE]; char header[SCRIPT_MAXSSIZE];
lp=GetStringResult(lp,OPER_EQU,header,0); lp=GetStringResult(lp,OPER_EQU,header,0);
SCRIPT_SKIP_SPACES SCRIPT_SKIP_SPACES
char options[256]; switch (ctype) {
case 't':
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT2);
break;
default:
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT1,header); snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT1,header);
//uint32_t slen=sizeof(SCRIPT_MSG_GOPT1)+strlen(header); break;
}
const char *type; // check for 2 axis option
if (*lp!=')') { if (y2f) {
switch (*lp) {
case 'l':
type=PSTR("LineChart");
if (*(lp+1)=='2') {
// 2 y axes variant // 2 y axes variant
lp+=2;
SCRIPT_SKIP_SPACES SCRIPT_SKIP_SPACES
float max1; float max1;
lp=GetNumericResult(lp,OPER_EQU,&max1,0); lp=GetNumericResult(lp,OPER_EQU,&max1,0);
@ -5257,43 +5464,24 @@ void ScriptWebShow(char mc) {
float max2; float max2;
lp=GetNumericResult(lp,OPER_EQU,&max2,0); lp=GetNumericResult(lp,OPER_EQU,&max2,0);
SCRIPT_SKIP_SPACES SCRIPT_SKIP_SPACES
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT3,header,(uint32_t)max1,(uint32_t)max2); snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT3,header,(uint32_t)max1,(uint32_t)max2,func);
} }
break;
case 'b':
type=PSTR("BarChart");
break;
case 'p':
type=PSTR("PieChart");
break;
case 'g':
type=PSTR("Gauge");
break;
case 't':
type=PSTR("Table");
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT2);
break;
case 'h':
type=PSTR("Histogram");
break;
default:
type=PSTR("ColumnChart");
break;
} }
} else {
type=PSTR("ColumnChart");
}
lp++;
WSContentSend_PD(SCRIPT_MSG_GTABLEb,options,type,chartindex); WSContentSend_PD(SCRIPT_MSG_GTABLEb,options,type,chartindex);
chartindex++; chartindex++;
} else { } else {
Replace_Cmd_Vars(lin,0,tmp,sizeof(tmp)); Replace_Cmd_Vars(lin,0,tmp,sizeof(tmp));
WSContentSend_PD(PSTR("%s"),tmp); WSContentSend_PD(PSTR("%s"),tmp);
} }
#else
} else {
Replace_Cmd_Vars(lin,0,tmp,sizeof(tmp));
WSContentSend_PD(PSTR("%s"),tmp);
#endif //USE_GOOGLE_CHARTS
} }
} }
} }
nextwebline:
if (*lp==SCRIPT_EOL) { if (*lp==SCRIPT_EOL) {
lp++; lp++;
} else { } else {
@ -5474,7 +5662,7 @@ bool Xdrv10(uint8_t function)
glob_script_mem.script_ram=sprt; glob_script_mem.script_ram=sprt;
glob_script_mem.script_size=UNISHOXRSIZE; glob_script_mem.script_size=UNISHOXRSIZE;
len_decompressed = SCRIPT_DECOMPRESS(Settings.rules[0], strlen(Settings.rules[0]), glob_script_mem.script_ram, glob_script_mem.script_size); len_decompressed = SCRIPT_DECOMPRESS(Settings.rules[0], strlen(Settings.rules[0]), glob_script_mem.script_ram, glob_script_mem.script_size);
glob_script_mem.script_ram[len_decompressed]=0; if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed]=0;
//AddLog_P2(LOG_LEVEL_INFO, PSTR("decompressed script len %d"),len_decompressed); //AddLog_P2(LOG_LEVEL_INFO, PSTR("decompressed script len %d"),len_decompressed);
#endif #endif
#endif #endif
@ -5568,6 +5756,14 @@ bool Xdrv10(uint8_t function)
glob_script_mem.flags=1; glob_script_mem.flags=1;
#endif #endif
// a valid script MUST start with >D
if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') {
// clr all
memset(glob_script_mem.script_ram,0,glob_script_mem.script_size);
strcpy_P(glob_script_mem.script_ram, PSTR(">D\nscript error must start with >D"));
bitWrite(Settings.rule_enabled, 0, 0);
}
// assure permanent memory is 4 byte aligned // assure permanent memory is 4 byte aligned
{ uint32_t ptr=(uint32_t)glob_script_mem.script_pram; { uint32_t ptr=(uint32_t)glob_script_mem.script_pram;
ptr&=0xfffffffc; ptr&=0xfffffffc;

View File

@ -2151,6 +2151,7 @@ init10:
#else #else
#ifdef ESP32 #ifdef ESP32
meter_ss[meters] = new HardwareSerial(uart_index); meter_ss[meters] = new HardwareSerial(uart_index);
if (uart_index==0) { ClaimSerial(); }
uart_index--; uart_index--;
if (uart_index<0) uart_index=0; if (uart_index<0) uart_index=0;
#else #else
@ -2216,7 +2217,13 @@ uint32_t SML_Write(uint32_t meter,char *hstr) {
SML_Send_Seq(meter,hstr); SML_Send_Seq(meter,hstr);
return 1; return 1;
} }
#endif
float SML_GetVal(uint32_t index) {
if (index<1 && index>SML_MAX_VARS) { index = 1;}
return meter_vars[index-1];
}
#endif // USE_SML_SCRIPT_CMD
void SetDBGLed(uint8_t srcpin, uint8_t ledpin) { void SetDBGLed(uint8_t srcpin, uint8_t ledpin) {