mirror of https://github.com/arendst/Tasmota.git
scripter update
This commit is contained in:
parent
7965ada5c5
commit
f6d22a6e4d
|
@ -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**
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue