scripter update

This commit is contained in:
gemu2015 2019-08-19 08:20:51 +02:00
parent 7965ada5c5
commit f6d22a6e4d
4 changed files with 103 additions and 17 deletions

View File

@ -94,7 +94,9 @@ special variables (read only):
**med(n x)** = calculates a 5 value median filter of x (2 filters possible n=0,1) **med(n x)** = calculates a 5 value median filter of x (2 filters possible n=0,1)
**int(x)** = gets the integer part of x (like floor) **int(x)** = gets the integer part of x (like floor)
**hn(x)** = converts x (0..255) to a hex nibble string **hn(x)** = converts x (0..255) to a hex nibble string
**st(svar c n)** = stringtoken gets the n th substring of svar separated by c **st(svar c n)** = stringtoken gets the n th substring of svar separated by c
**sl(svar)** = gets the length of a string
**sb(svar p n)** = gets a substring from svar at position p (if p<0 counts from end) and length n
**s(x)** = explicit conversion from number x to string **s(x)** = explicit conversion from number x to string
**mqtts** = state of mqtt disconnected=0, connected>0 **mqtts** = state of mqtt disconnected=0, connected>0
**wifis** = state of wifi disconnected=0, connected>0 **wifis** = state of wifi disconnected=0, connected>0
@ -139,7 +141,7 @@ a single percent sign must be given as **%%**
**special** cmds: **special** cmds:
>**=\> print** prints to info log for debugging >**print** or **=\>print** prints to info log for debugging
to save code space nearly no error messages are provided. However it is taken care of that at least it should not crash on syntax errors. to save code space nearly no error messages are provided. However it is taken care of that at least it should not crash on syntax errors.
if a variable does not exist a **???** is given on commands if a variable does not exist a **???** is given on commands
@ -188,7 +190,8 @@ and on the same line conditions may be bracketed e.g. if ((a==b) and ((c==d) or
>**#name** names a subroutine, subroutines are called with **=#name** >**#name** names a subroutine, subroutines are called with **=#name**
**#name(param)** names a subroutines with a parameter is called with **=#name(param)** **#name(param)** names a subroutines with a parameter is called with **=#name(param)**
subroutines end with the next '#' or '>' line or break, may be nested subroutines end with the next '#' or '>' line or break, may be nested
params can be numbers or strings and on mismatch are converted params can be numbers or strings and on mismatch are converted
**=(svar)** executes a script in a string variable (dynamic or self modifying code)
>**for var from to inc** >**for var from to inc**
**next** **next**

View File

@ -298,7 +298,7 @@
// Select none or only one of the below defines // Select none or only one of the below defines
#define USE_RULES // Add support for rules (+8k code) #define USE_RULES // Add support for rules (+8k code)
//#define USE_SCRIPT // Add support for script (+17k code) //#define USE_SCRIPT // Add support for script (+17k code)
#define USE_SCRIPT_FATFS 4 // Script: Add FAT FileSystem Support //#define USE_SCRIPT_FATFS 4 // Script: Add FAT FileSystem Support
// #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) // #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem)
// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) // #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code)

View File

@ -2399,7 +2399,7 @@ int WebSend(char *buffer)
int http_code = http.GET(); // Start connection and send HTTP header int http_code = http.GET(); // Start connection and send HTTP header
if (http_code > 0) { // http_code will be negative on error if (http_code > 0) { // http_code will be negative on error
if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) { if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) {
/* #ifdef USE_WEBSEND_RESPONSE
// Return received data to the user - Adds 900+ bytes to the code // Return received data to the user - Adds 900+ bytes to the code
String result = http.getString(); // File found at server - may need lot of ram or trigger out of memory! String result = http.getString(); // File found at server - may need lot of ram or trigger out of memory!
uint32_t j = 0; uint32_t j = 0;
@ -2412,7 +2412,13 @@ int WebSend(char *buffer)
} }
mqtt_data[j] = '\0'; mqtt_data[j] = '\0';
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WEBSEND)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WEBSEND));
*/ #ifdef USE_SCRIPT
extern uint8_t tasm_cmd_activ;
// recursive call must be possible in this case
tasm_cmd_activ=0;
XdrvRulesProcess();
#endif
#endif
} }
status = 0; // No error - Done status = 0; // No error - Done
} else { } else {

View File

@ -134,6 +134,7 @@ struct SCRIPT_MEM {
uint8_t *vnp_offset; uint8_t *vnp_offset;
char *glob_snp; // string vars pointer char *glob_snp; // string vars pointer
char *scriptptr; char *scriptptr;
char *scriptptr_bu;
char *script_ram; char *script_ram;
uint16_t script_size; uint16_t script_size;
uint8_t *script_pram; uint8_t *script_pram;
@ -161,6 +162,7 @@ uint8_t tasm_cmd_activ=0;
uint8_t fast_script=0; uint8_t fast_script=0;
uint32_t script_lastmillis; uint32_t script_lastmillis;
char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo); char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo);
char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo); char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo);
char *ForceStringVar(char *lp,char *dstr); char *ForceStringVar(char *lp,char *dstr);
@ -241,6 +243,7 @@ char *script;
glob_script_mem.max_ssize=SCRIPT_SVARSIZE; glob_script_mem.max_ssize=SCRIPT_SVARSIZE;
glob_script_mem.scriptptr=0; glob_script_mem.scriptptr=0;
if (!*script) return -999; if (!*script) return -999;
float fvalues[MAXVARS]; float fvalues[MAXVARS];
@ -539,6 +542,7 @@ char *script;
// store start of actual program here // store start of actual program here
glob_script_mem.scriptptr=lp-1; glob_script_mem.scriptptr=lp-1;
glob_script_mem.scriptptr_bu=glob_script_mem.scriptptr;
return 0; return 0;
} }
@ -943,9 +947,15 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso
} }
if (jo->success()) { if (jo->success()) {
char *subtype=strchr(vname,'#'); char *subtype=strchr(vname,'#');
char *subtype2;
if (subtype) { if (subtype) {
*subtype=0; *subtype=0;
subtype++; subtype++;
subtype2=strchr(subtype,'#');
if (subtype2) {
*subtype2=0;
*subtype2++;
}
} }
vn=vname; vn=vname;
str_value = (*jo)[vn]; str_value = (*jo)[vn];
@ -957,6 +967,23 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso
jo=&jobj1; jo=&jobj1;
str_value = (*jo)[vn]; str_value = (*jo)[vn];
if ((*jo)[vn].success()) { if ((*jo)[vn].success()) {
// 2. stage
if (subtype2) {
JsonObject &jobj2=(*jo)[vn];
if ((*jo)[vn].success()) {
vn=subtype2;
jo=&jobj2;
str_value = (*jo)[vn];
if ((*jo)[vn].success()) {
goto skip;
} else {
goto chknext;
}
} else {
goto chknext;
}
}
// end
goto skip; goto skip;
} }
} else { } else {
@ -1492,6 +1519,34 @@ chknext:
fvar=strlen(glob_script_mem.script_ram); fvar=strlen(glob_script_mem.script_ram);
goto exit; goto exit;
} }
if (!strncmp(vname,"sl(",3)) {
lp+=3;
char str[SCRIPT_MAXSSIZE];
lp=GetStringResult(lp,OPER_EQU,str,0);
lp++;
len=0;
fvar=strlen(str);
goto exit;
}
if (!strncmp(vname,"sb(",3)) {
lp+=3;
char str[SCRIPT_MAXSSIZE];
lp=GetStringResult(lp,OPER_EQU,str,0);
SCRIPT_SKIP_SPACES
float fvar1;
lp=GetNumericResult(lp,OPER_EQU,&fvar1,0);
SCRIPT_SKIP_SPACES
float fvar2;
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
lp++;
len=0;
if (fvar1<0) {
fvar1=strlen(str)+fvar1;
}
memcpy(sp,&str[(uint8_t)fvar1],(uint8_t)fvar2);
sp[(uint8_t)fvar2] = '\0';
goto strexit;
}
if (!strncmp(vname,"st(",3)) { if (!strncmp(vname,"st(",3)) {
lp+=3; lp+=3;
char str[SCRIPT_MAXSSIZE]; char str[SCRIPT_MAXSSIZE];
@ -2155,7 +2210,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
if (tasm_cmd_activ && tlen>0) return 0; if (tasm_cmd_activ && tlen>0) return 0;
uint8_t vtype=0,sindex,xflg,floop=0,globvindex; uint8_t vtype=0,sindex,xflg,floop=0,globvindex,fromscriptcmd=0;
int8_t globaindex; int8_t globaindex;
struct T_INDEX ind; struct T_INDEX ind;
uint8_t operand,lastop,numeric=1,if_state[IF_NEST],if_exe[IF_NEST],if_result[IF_NEST],and_or,ifstck=0; uint8_t operand,lastop,numeric=1,if_state[IF_NEST],if_exe[IF_NEST],if_result[IF_NEST],and_or,ifstck=0;
@ -2445,11 +2500,17 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
#endif #endif
#endif #endif
else if (!strncmp(lp,"=>",2) || !strncmp(lp,"->",2)) { else if (!strncmp(lp,"=>",2) || !strncmp(lp,"->",2) || !strncmp(lp,"print",5)) {
// execute cmd // execute cmd
uint8_t sflag=0,svmqtt,swll; uint8_t sflag=0,pflg=0,svmqtt,swll;
if (*lp=='-') sflag=1; if (*lp=='p') {
lp+=2; pflg=1;
lp+=5;
}
else {
if (*lp=='-') sflag=1;
lp+=2;
}
char *slp=lp; char *slp=lp;
SCRIPT_SKIP_SPACES SCRIPT_SKIP_SPACES
#define SCRIPT_CMDMEM 512 #define SCRIPT_CMDMEM 512
@ -2472,8 +2533,9 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
Replace_Cmd_Vars(cmd,tmp,SCRIPT_CMDMEM/2); Replace_Cmd_Vars(cmd,tmp,SCRIPT_CMDMEM/2);
//toSLog(tmp); //toSLog(tmp);
if (!strncmp(tmp,"print",5)) { if (!strncmp(tmp,"print",5) || pflg) {
toLog(&tmp[5]); if (pflg) toLog(tmp);
else toLog(&tmp[5]);
} else { } else {
if (!sflag) { if (!sflag) {
snprintf_P(log_data, sizeof(log_data), PSTR("Script: performs \"%s\""), tmp); snprintf_P(log_data, sizeof(log_data), PSTR("Script: performs \"%s\""), tmp);
@ -2508,9 +2570,23 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
lp++; lp++;
plen++; plen++;
} }
Run_Scripter(slp,plen,0); if (fromscriptcmd) {
char *sp=glob_script_mem.scriptptr;
glob_script_mem.scriptptr=glob_script_mem.scriptptr_bu;
Run_Scripter(slp,plen,0);
glob_script_mem.scriptptr=sp;
} else {
Run_Scripter(slp,plen,0);
}
lp=slp; lp=slp;
goto next_line; goto next_line;
} else if (!strncmp(lp,"=(",2)) {
lp+=2;
char str[128];
str[0]='>';
lp=GetStringResult(lp,OPER_EQU,&str[1],0);
lp++;
execute_script(str);
} }
// check for variable result // check for variable result
@ -2651,6 +2727,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
// called from cmdline // called from cmdline
lp++; lp++;
section=1; section=1;
fromscriptcmd=1;
goto startline; goto startline;
} }
if (!strncmp(lp,type,tlen)) { if (!strncmp(lp,type,tlen)) {
@ -3200,12 +3277,11 @@ void ScriptSaveSettings(void) {
#endif #endif
void execute_script(char *script) { void execute_script(char *script) {
char *svd_sp=glob_script_mem.scriptptr; char *svd_sp=glob_script_mem.scriptptr;
strcat(script,"\n#"); strcat(script,"\n#");
glob_script_mem.scriptptr=script; glob_script_mem.scriptptr=script;
Run_Scripter(">",1,0); Run_Scripter(">",1,0);
glob_script_mem.scriptptr=svd_sp; glob_script_mem.scriptptr=svd_sp;
Scripter_save_pvars();
} }
#define D_CMND_SCRIPT "Script" #define D_CMND_SCRIPT "Script"
#define D_CMND_SUBSCRIBE "Subscribe" #define D_CMND_SUBSCRIBE "Subscribe"
@ -3240,6 +3316,7 @@ bool ScriptCommand(void) {
if (XdrvMailbox.data[count]==';') XdrvMailbox.data[count]='\n'; if (XdrvMailbox.data[count]==';') XdrvMailbox.data[count]='\n';
} }
execute_script(XdrvMailbox.data); execute_script(XdrvMailbox.data);
Scripter_save_pvars();
} }
} }
return serviced; return serviced;
@ -3332,7 +3409,7 @@ bool ScriptMqttData(void)
value.trim(); value.trim();
//Create an new event. Cannot directly call RulesProcessEvent(). //Create an new event. Cannot directly call RulesProcessEvent().
//snprintf_P(Rules.event_data, sizeof(Rules.event_data), PSTR("%s=%s"), event_item.Event.c_str(), value.c_str()); //snprintf_P(event_data, sizeof(event_data), PSTR("%s=%s"), event_item.Event.c_str(), value.c_str());
char sbuffer[128]; char sbuffer[128];
snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str());
//toLog(sbuffer); //toLog(sbuffer);