Merge pull request #6048 from gemu2015/scripter_update

Scripter update
This commit is contained in:
Theo Arends 2019-07-09 10:48:19 +02:00 committed by GitHub
commit a19d491b54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 48 deletions

View File

@ -76,6 +76,7 @@ special variables (read only):
**gtopic** = mqtt group topic **gtopic** = mqtt group topic
**prefixn** = prefix n = 1-3 **prefixn** = prefix n = 1-3
**pwr[x]** = tasmota power state (x = 1-N) **pwr[x]** = tasmota power state (x = 1-N)
**tbut[x]** = touch screen button state (x = 1-N)
**sw[x]** = tasmota switch state (x = 1-N) **sw[x]** = tasmota switch state (x = 1-N)
>**pin[x]** = gpio pin level (x = 0-16) >**pin[x]** = gpio pin level (x = 0-16)
**pn[x]** = pin number for sensor code x, 99 if none **pn[x]** = pin number for sensor code x, 99 if none
@ -366,7 +367,7 @@ endif
=\>WebSend %url% dimmer %dimmer% =\>WebSend %url% dimmer %dimmer%
; show on display ; show on display
dprec0 dp0
=\>displaytext [c1l1f1s2p20] dimmer=%dimmer% =\>displaytext [c1l1f1s2p20] dimmer=%dimmer%
=\>print %upsecs% %uptime% %time% %sunrise% %sunset% %tstamp% =\>print %upsecs% %uptime% %time% %sunrise% %sunset% %tstamp%
@ -613,7 +614,7 @@ punit=PressureUnit
// update display every teleperiod time // update display every teleperiod time
if upsecs%tper==0 if upsecs%tper==0
then then
dprec2 dp2
=>%DT% [f1p7x0y5]%temp% %tunit% =>%DT% [f1p7x0y5]%temp% %tunit%
=>%DT% [p5x70y5]%hum% %%[x250y5t] =>%DT% [p5x70y5]%hum% %%[x250y5t]
=>%DT% [p11x140y5]%press% %punit% =>%DT% [p11x140y5]%press% %punit%
@ -621,7 +622,7 @@ dprec2
=>%DT% [p10x160y25]eCO2: %eco2% ppm =>%DT% [p10x160y25]eCO2: %eco2% ppm
=>%DT% [p10c26l5]ahum: %ahum% g^m3 =>%DT% [p10c26l5]ahum: %ahum% g^m3
dprec0 dp0
=>%DT% [p25c1l5]WR 1 (Dach) : %wr1% W =>%DT% [p25c1l5]WR 1 (Dach) : %wr1% W
=>%DT% [p25c1l6]WR 2 (Garage): %-wr3% W =>%DT% [p25c1l6]WR 2 (Garage): %-wr3% W
=>%DT% [p25c1l7]WR 3 (Garten): %-wr2% W =>%DT% [p25c1l7]WR 3 (Garten): %-wr2% W
@ -697,14 +698,14 @@ endif
; update graph every teleperiod ; update graph every teleperiod
if upsecs%tper==0 if upsecs%tper==0
then then
dprec2 dp2
=>%DT% [f1Ci3x40y260w30Ci1] =>%DT% [f1Ci3x40y260w30Ci1]
=>%DT% [Ci7x120y220t] =>%DT% [Ci7x120y220t]
=>%DT% [Ci7x180y220T] =>%DT% [Ci7x180y220T]
=>%DT% [Ci7p8x120y240]%temp% %tunit% =>%DT% [Ci7p8x120y240]%temp% %tunit%
=>%DT% [Ci7x120y260]%press% %punit% =>%DT% [Ci7x120y260]%press% %punit%
=>%DT% [Ci7x120y280]%dist% mm =>%DT% [Ci7x120y280]%dist% mm
dprec0 dp0
=>%DT% [g0:%zwz%g1:%wr1%g2:%-wr2%g3:%-wr3%] =>%DT% [g0:%zwz%g1:%wr1%g2:%-wr2%g3:%-wr3%]
if zwz>0 if zwz>0
then then

View File

@ -297,7 +297,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 (only for cores 2.3.0, 2.4.2 and 2.5.0) #define USE_SCRIPT_FATFS 4 // Script: Add FAT FileSystem Support (only for cores 2.3.0, 2.4.2 and 2.5.0)
// #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

@ -35,9 +35,6 @@ no math hierarchy (costs ram and execution time, better group with brackets, an
(will probably make math hierarchy an ifdefed option) (will probably make math hierarchy an ifdefed option)
keywords if then else endif, or, and are better readable for beginners (others may use {}) keywords if then else endif, or, and are better readable for beginners (others may use {})
changelog after merging to Tasmota
1. draw color picture from sd card
2. upload files to sc card
\*********************************************************************************************/ \*********************************************************************************************/
@ -65,6 +62,17 @@ enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD};
#include <SD.h> #include <SD.h>
#define FAT_SCRIPT_SIZE 4096 #define FAT_SCRIPT_SIZE 4096
#define FAT_SCRIPT_NAME "script.txt" #define FAT_SCRIPT_NAME "script.txt"
#if USE_LONG_FILE_NAMES==1
#warning ("FATFS long filenames not supported");
#endif
#if USE_STANDARD_SPI_LIBRARY==0
#warning ("FATFS standard spi should be used");
#endif
#endif
#ifdef USE_TOUCH_BUTTONS
#include <renderer.h>
extern Adafruit_GFX_Button *buttons[MAXBUTTONS];
#endif #endif
typedef union { typedef union {
@ -146,7 +154,6 @@ uint8_t tasm_cmd_activ=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);
@ -182,7 +189,7 @@ void ScriptEverySecond(void) {
} }
void RulesTeleperiod(void) { void RulesTeleperiod(void) {
if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">T",2, mqtt_data); if (bitRead(Settings.rule_enabled, 0) && mqtt_data[0]) Run_Scripter(">T",2, mqtt_data);
} }
//#define USE_24C256 //#define USE_24C256
@ -1403,6 +1410,22 @@ chknext:
if (sp) strlcpy(sp,Settings.mqtt_topic,glob_script_mem.max_ssize); if (sp) strlcpy(sp,Settings.mqtt_topic,glob_script_mem.max_ssize);
goto strexit; goto strexit;
} }
#ifdef USE_TOUCH_BUTTONS
if (!strncmp(vname,"tbut[",5)) {
GetNumericResult(vname+5,OPER_EQU,&fvar,0);
uint8_t index=fvar;
if (index<1 || index>MAXBUTTONS) index=1;
index--;
if (buttons[index]) {
fvar=buttons[index]->vpower&0x80;
} else {
fvar=-1;
}
len+=1;
goto exit;
}
#endif
break; break;
case 'u': case 'u':
if (!strncmp(vname,"uptime",6)) { if (!strncmp(vname,"uptime",6)) {
@ -1433,6 +1456,7 @@ chknext:
goto notfound; goto notfound;
} }
break; break;
case 'w': case 'w':
if (!strncmp(vname,"wday",4)) { if (!strncmp(vname,"wday",4)) {
fvar=RtcTime.day_of_week; fvar=RtcTime.day_of_week;
@ -1717,6 +1741,7 @@ struct T_INDEX ind;
break; break;
default: default:
break; break;
} }
slp=lp; slp=lp;
lp=getop(lp,&operand); lp=getop(lp,&operand);
@ -2106,7 +2131,7 @@ int16_t Run_Scripter(const char *type, uint8_t tlen, char *js) {
char *cmdmem=(char*)malloc(SCRIPT_CMDMEM); char *cmdmem=(char*)malloc(SCRIPT_CMDMEM);
if (cmdmem) { if (cmdmem) {
char *cmd=cmdmem; char *cmd=cmdmem;
short count; uint16_t count;
for (count=0; count<SCRIPT_CMDMEM/2-1; count++) { for (count=0; count<SCRIPT_CMDMEM/2-1; count++) {
//if (*lp=='\r' || *lp=='\n' || *lp=='}') { //if (*lp=='\r' || *lp=='\n' || *lp=='}') {
if (!*lp || *lp=='\r' || *lp=='\n') { if (!*lp || *lp=='\r' || *lp=='\n') {
@ -2526,6 +2551,10 @@ const char HTTP_FORM_SCRIPT1b[] PROGMEM =
"});" "});"
"</script>"; "</script>";
const char HTTP_SCRIPT_FORM_END[] PROGMEM =
"<br/>"
"<button name='save' type='submit' formmethod='post' formenctype='multipart/form-data' formaction='/ta' class='button bgrn'>" D_SAVE "</button>"
"</form></fieldset>";
#ifdef USE_SCRIPT_FATFS #ifdef USE_SCRIPT_FATFS
const char HTTP_FORM_SCRIPT1c[] PROGMEM = const char HTTP_FORM_SCRIPT1c[] PROGMEM =
@ -2573,12 +2602,28 @@ const char HTTP_FORM_SDC_HREF[] PROGMEM =
#ifdef USE_SCRIPT_FATFS #ifdef USE_SCRIPT_FATFS
#if USE_LONG_FILE_NAMES>0
#define REJCMPL 6
#else
#define REJCMPL 8
#endif
uint8_t reject(char *name) { uint8_t reject(char *name) {
if (*name=='_') return 1; if (*name=='_') return 1;
if (!strncmp(name,"SPOTLI~1",8)) return 1; if (*name=='.') return 1;
if (!strncmp(name,"TRASHE~1",8)) return 1;
if (!strncmp(name,"FSEVEN~1",8)) return 1; #ifndef ARDUINO_ESP8266_RELEASE_2_3_0
if (!strncmp(name,"SYSTEM~1",8)) return 1; if (!strncasecmp(name,"SPOTLI~1",REJCMPL)) return 1;
if (!strncasecmp(name,"TRASHE~1",REJCMPL)) return 1;
if (!strncasecmp(name,"FSEVEN~1",REJCMPL)) return 1;
if (!strncasecmp(name,"SYSTEM~1",REJCMPL)) return 1;
#else
if (!strcasecmp(name,"SPOTLI~1")) return 1;
if (!strcasecmp(name,"TRASHE~1")) return 1;
if (!strcasecmp(name,"FSEVEN~1")) return 1;
if (!strcasecmp(name,"SYSTEM~1")) return 1;
#endif
return 0; return 0;
} }
@ -2687,6 +2732,8 @@ void ScriptFileUploadSuccess(void) {
WSContentStop(); WSContentStop();
} }
void script_upload(void) { void script_upload(void) {
//AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: file upload")); //AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: file upload"));
@ -2773,18 +2820,22 @@ uint8_t DownloadFile(char *file) {
#endif #endif
void HandleScriptConfiguration(void)
{ void HandleScriptTextareaConfiguration(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
if (WebServer->hasArg("save")) {
ScriptSaveSettings();
HandleConfiguration();
return;
}
}
void HandleScriptConfiguration(void) {
if (!HttpCheckPriviledgedAccess()) { return; } if (!HttpCheckPriviledgedAccess()) { return; }
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_SCRIPT); AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_SCRIPT);
if (WebServer->hasArg("save")) {
ScriptSaveSettings();
HandleConfiguration();
return;
}
#ifdef USE_SCRIPT_FATFS #ifdef USE_SCRIPT_FATFS
if (WebServer->hasArg("d1")) { if (WebServer->hasArg("d1")) {
DownloadFile(glob_script_mem.flink[0]); DownloadFile(glob_script_mem.flink[0]);
@ -2816,22 +2867,12 @@ void HandleScriptConfiguration(void)
} }
#endif #endif
WSContentSend_P(HTTP_FORM_END); WSContentSend_P(HTTP_SCRIPT_FORM_END);
WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentSpaceButton(BUTTON_CONFIGURATION);
WSContentStop(); WSContentStop();
} }
void strrepl_inplace(char *str, const char *a, const char *b) {
for (char *cursor=str; (cursor=strstr(cursor,a)) != NULL;) {
memmove(cursor+strlen(b),cursor+strlen(a),strlen(cursor)-strlen(a)+1);
for (uint32_t i=0; b[i]!='\0'; i++) {
cursor[i] = b[i];
}
cursor += strlen(b);
}
}
void ScriptSaveSettings(void) { void ScriptSaveSettings(void) {
if (WebServer->hasArg("c1")) { if (WebServer->hasArg("c1")) {
@ -2840,16 +2881,14 @@ void ScriptSaveSettings(void) {
bitWrite(Settings.rule_enabled,0,0); bitWrite(Settings.rule_enabled,0,0);
} }
String str = WebServer->arg("t1"); String str = WebServer->arg("t1");
if (*str.c_str()) { if (*str.c_str()) {
#if 1
strrepl_inplace((char*)str.c_str(),"\r\n","\n");
strrepl_inplace((char*)str.c_str(),"\r","\n");
#else
str.replace("\r\n","\n"); str.replace("\r\n","\n");
str.replace("\r","\n"); str.replace("\r","\n");
#endif
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);
#ifdef USE_24C256 #ifdef USE_24C256
@ -2921,15 +2960,15 @@ bool ScriptCommand(void) {
} else { } else {
if ('>' == XdrvMailbox.data[0]) { if ('>' == XdrvMailbox.data[0]) {
// execute script // execute script
for (uint8_t count=0; count<XdrvMailbox.data_len; count++) { snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),command,XdrvMailbox.data);
if (XdrvMailbox.data[count]==';') XdrvMailbox.data[count]='\n'; if (bitRead(Settings.rule_enabled, 0)) {
for (uint8_t count=0; count<XdrvMailbox.data_len; count++) {
if (XdrvMailbox.data[count]==';') XdrvMailbox.data[count]='\n';
}
execute_script(XdrvMailbox.data);
} }
if (bitRead(Settings.rule_enabled, 0)) execute_script(XdrvMailbox.data);
/*
for (uint8_t count=0; count<XdrvMailbox.data_len; count++) {
if (XdrvMailbox.data[count]=='\n') XdrvMailbox.data[count]=';';
}*/
} }
return serviced;
} }
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"Free\":%d}"),command, GetStateText(bitRead(Settings.rule_enabled,0)),glob_script_mem.script_size-strlen(glob_script_mem.script_ram)); snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"Free\":%d}"),command, GetStateText(bitRead(Settings.rule_enabled,0)),glob_script_mem.script_size-strlen(glob_script_mem.script_ram));
} else serviced = false; } else serviced = false;
@ -2939,6 +2978,7 @@ bool ScriptCommand(void) {
#ifdef USE_SCRIPT_FATFS #ifdef USE_SCRIPT_FATFS
#ifdef FAT_DATE
void dateTime(uint16_t* date, uint16_t* time) { void dateTime(uint16_t* date, uint16_t* time) {
// return date using FAT_DATE macro to format fields // return date using FAT_DATE macro to format fields
*date = FAT_DATE(RtcTime.year,RtcTime.month, RtcTime.day_of_month); *date = FAT_DATE(RtcTime.year,RtcTime.month, RtcTime.day_of_month);
@ -2946,6 +2986,7 @@ void dateTime(uint16_t* date, uint16_t* time) {
*time = FAT_TIME(RtcTime.hour,RtcTime.minute,RtcTime.second); *time = FAT_TIME(RtcTime.hour,RtcTime.minute,RtcTime.second);
} }
#endif #endif
#endif
/*********************************************************************************************\ /*********************************************************************************************\
* Interface * Interface
@ -3006,7 +3047,11 @@ bool Xdrv10(uint8_t function)
glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE; glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE;
glob_script_mem.flags=1; glob_script_mem.flags=1;
#ifdef FAT_DATE
// for unkonwn reasons is not defined in 2.52
SdFile::dateTimeCallback(dateTime); SdFile::dateTimeCallback(dateTime);
#endif
} else { } else {
glob_script_mem.script_sd_found=0; glob_script_mem.script_sd_found=0;
@ -3036,7 +3081,7 @@ bool Xdrv10(uint8_t function)
break; break;
case FUNC_SET_POWER: case FUNC_SET_POWER:
case FUNC_RULES_PROCESS: case FUNC_RULES_PROCESS:
if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,mqtt_data); if (bitRead(Settings.rule_enabled, 0) && mqtt_data[0]) Run_Scripter(">E",2,mqtt_data);
break; break;
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
case FUNC_WEB_ADD_BUTTON: case FUNC_WEB_ADD_BUTTON:
@ -3044,6 +3089,7 @@ bool Xdrv10(uint8_t function)
break; break;
case FUNC_WEB_ADD_HANDLER: case FUNC_WEB_ADD_HANDLER:
WebServer->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); WebServer->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration);
WebServer->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration);
#ifdef USE_SCRIPT_FATFS #ifdef USE_SCRIPT_FATFS
WebServer->on("/u3", HTTP_POST,[]() { WebServer->sendHeader("Location","/u3");WebServer->send(303);},script_upload); WebServer->on("/u3", HTTP_POST,[]() { WebServer->sendHeader("Location","/u3");WebServer->send(303);},script_upload);
WebServer->on("/u3", HTTP_GET,ScriptFileUploadSuccess); WebServer->on("/u3", HTTP_GET,ScriptFileUploadSuccess);