From ce72a8347a9e3e1db0d28719d192080101ca1582 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 30 May 2019 13:22:50 +0200 Subject: [PATCH 1/6] empty --- scripter.md | 0 sonoff/xdrv_10_scripter.ino | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripter.md mode change 100644 => 100755 sonoff/xdrv_10_scripter.ino diff --git a/scripter.md b/scripter.md old mode 100644 new mode 100755 diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino old mode 100644 new mode 100755 From fb4ada320a02e5eb0e1e98404c8eed1ab1783296 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 30 May 2019 13:23:54 +0200 Subject: [PATCH 2/6] scripter update --- scripter.md | 88 ++++++- sonoff/xdrv_10_scripter.ino | 472 +++++++++++++++++++++++++++++++++--- 2 files changed, 511 insertions(+), 49 deletions(-) mode change 100755 => 100644 scripter.md mode change 100755 => 100644 sonoff/xdrv_10_scripter.ino diff --git a/scripter.md b/scripter.md old mode 100755 new mode 100644 index dc4123192..40ad3451e --- a/scripter.md +++ b/scripter.md @@ -1,6 +1,6 @@ **Script Language for Tasmota** -As an alternative to rules. (about 14,2k flash size, variable ram size) +As an alternative to rules. (about 17k flash size, variable ram size) In submenu Configuration =\> edit script 1535 bytes max script size (uses rules buffer) @@ -88,6 +88,7 @@ special variables (read only): **int(x)** = gets the integer part of x (like floor) **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 +**s(x)** = explicit conversion from number x to string **mqtts** = state of mqtt disconnected=0, connected>0 **wifis** = state of wifi disconnected=0, connected>0 @@ -187,6 +188,24 @@ specifies a for next loop, (loop count must not be less then 1) **ends** specifies a switch case selector +**sd card support** +enable by CARD_CS = gpio pin of card chip select +\#define USE_SCRIPT_FATFS CARD_CS +sd card uses standard hardware spi gpios: mosi,miso,sclk +max 4 files open at a time +allows for e.g. logging sensors to a tab delimited file and then download (see example below) +script itself is also stored on sdcard with a default size of 4096 chars +requires additional 10k flash + +>**fr=fo("fname" m)** open file fname, mode 0=read, 1=write (returns file reference (0-3) or -1 for error) +**res=fw("text" fr)** writes text to (the end of) file fr, returns number of bytes written +**res=fr(svar fr)** reads a string into svar, returns bytes read (string is read until delimiter \t \n \r or eof) +**fc(fr)** close file +**fd("fname")** delete file fname +**flx(fname)** create download link for file (x=1 or 2) fname = file name of file to download +**fsm** return 1 if filesystem is mounted, (valid sd card found) + + **konsole script cmds** >**script 1 or 0** switch script on or off **script >cmdline** executes the script cmdline @@ -228,8 +247,8 @@ tcnt=0 hour=0 state=1 m:med5=0 -M:movav=0 -; define array with 10 entries +M:movav=0 +; define array with 10 entries m:array=0 10 **\>B** @@ -290,10 +309,10 @@ endif ; every second but not completely reliable time here ; use upsecs and uptime or best t: for reliable timers -; arrays -array[1]=4 -array[2]=5 -tmp=array[1]+array[2] +; arrays +array[1]=4 +array[2]=5 +tmp=array[1]+array[2] ; call subrountines with parameters =#sub1("hallo") @@ -473,11 +492,54 @@ col=hn(255)+hn(0)+hn(0) **\>R** =\>print restarting now +**a log sensor example** +; define all vars here +; reserve large strings +**\>D** 48 +hum=0 +temp=0 +fr=0 +res=0 +; moving average for 60 seconds +M:mhum=0 60 +M:mtemp=0 60 +str="" + +**\>B** +; open file for write +fr=fo("slog.txt" 1) +; set sensor file download link +fl1("slog.txt") + +**\>T** +; get sensor values +temp=BME280#Temperature +hum=BME280#Humidity + +**\>S** +; average sensor values every second +mhum=hum +mtemp=temp + +; write average to sensor log every minute +if upsecs%60==0 +then +; compose string for tab delimited file entry +str=s(upsecs)+"\t"+s(mhum)+"\t"+s(mtemp)+"\n" +; write string to log file +res=fw(str fr) +endif + +**\>R** +; close file +fc(fr) + + **a real example** epaper 29 with sgp30 and bme280 some vars are set from iobroker DisplayText substituted to save script space -\>D +**\>D** hum=0 temp=0 press=0 @@ -496,13 +558,13 @@ DT="DisplayText" punit="hPa" tunit="C" -\>B +**\>B** ;reset auto draw =>%DT% [zD0] ;clr display and draw a frame =>%DT% [x0y20h296x0y40h296] -\>T +**\>T** ; get tele vars temp=BME280#Temperature hum=BME280#Humidity @@ -513,7 +575,7 @@ ahum=SGP30#aHumidity tunit=TempUnit punit=PressureUnit -\>S +**\>S** // update display every teleperiod time if upsecs%tper==0 then @@ -536,9 +598,9 @@ dprec0 endif -\>E +**\>E** -\>R +**\>R** **another real example** ILI 9488 color LCD Display shows various energy graphs diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino old mode 100755 new mode 100644 index 83c29a42c..d5a3176da --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -21,8 +21,7 @@ #ifndef USE_RULES /*********************************************************************************************\ for documentation see up to date docs in file SCRIPTER.md -uses about 14,2 k of flash -more stack could be needed for sendmail => -D CONT_STACKSIZE=4800 = +0.8k stack -0.8k heap +uses about 17 k of flash to do optimize code for space @@ -36,7 +35,13 @@ no math hierarchy (costs ram and execution time, better group with brackets, an (will probably make math hierarchy an ifdefed option) keywords if then else endif, or, and are better readable for beginners (others may use {}) - +changelog after merging to Tasmota +1 show remaining chars in webui, +2 now can expand script space to 2048 chars by setting MAX_RULE_SETS to 4 +3 at24256 eeprom support #ifdef defaults to 4095 bytes script size (reduces heap by this amount) +4 some housekeeping +5 sd card support #ifdef allows eg for sensor logging +6 download link for sdcard files \*********************************************************************************************/ @@ -53,11 +58,18 @@ keywords if then else endif, or, and are better readable for beginners (others m #define SCRIPT_EOL '\n' #define SCRIPT_FLOAT_PRECISION 2 #define SCRIPT_MAXPERM (MAX_RULE_MEMS*10)-4/sizeof(float) - +#define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS enum {OPER_EQU=1,OPER_PLS,OPER_MIN,OPER_MUL,OPER_DIV,OPER_PLSEQU,OPER_MINEQU,OPER_MULEQU,OPER_DIVEQU,OPER_EQUEQU,OPER_NOTEQU,OPER_GRTEQU,OPER_LOWEQU,OPER_GRT,OPER_LOW,OPER_PERC,OPER_XOR,OPER_AND,OPER_OR,OPER_ANDEQU,OPER_OREQU,OPER_XOREQU,OPER_PERCEQU}; enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD}; +#ifdef USE_SCRIPT_FATFS +#include +#include +#define FAT_SCRIPT_SIZE 4096 +#define FAT_SCRIPT_NAME "script.txt" +#endif + typedef union { uint8_t data; struct { @@ -84,6 +96,7 @@ struct M_FILT { float rbuff[1]; }; +#define SFS_MAX 4 // global memory struct SCRIPT_MEM { float *fvars; // number var pointer @@ -94,6 +107,10 @@ struct SCRIPT_MEM { uint8_t *vnp_offset; char *glob_snp; // string vars pointer char *scriptptr; + char *script_ram; + uint16_t script_size; + uint8_t *script_pram; + uint16_t script_pram_size; uint8_t numvars; void *script_mem; uint16_t script_mem_size; @@ -102,6 +119,13 @@ struct SCRIPT_MEM { uint8_t glob_error; uint8_t max_ssize; uint8_t script_loglevel; + uint8_t flags; +#ifdef USE_SCRIPT_FATFS + File files[SFS_MAX]; + uint8_t file_flags[SFS_MAX]; + uint8_t script_sd_found; + char flink[2][14]; +#endif } glob_script_mem; @@ -110,8 +134,11 @@ uint8_t tasm_cmd_activ=0; uint32_t script_lastmillis; + char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo); char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo); +char *ForceStringVar(char *lp,char *dstr); +void send_download(void); void ScriptEverySecond(void) { @@ -145,11 +172,31 @@ void RulesTeleperiod(void) { if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">T",2, mqtt_data); } +//#define USE_24C256 + +// EEPROM MACROS +#ifdef USE_24C256 +// i2c eeprom +#include +#define EEPROM_ADDRESS 0x50 +// strange bug, crashes with powers of 2 ??? 4096 crashes +#define EEP_SCRIPT_SIZE 4095 +static Eeprom24C128_256 eeprom(EEPROM_ADDRESS); +// eeprom.writeBytes(address, length, buffer); +#define EEP_WRITE(A,B,C) eeprom.writeBytes(A,B,(uint8_t*)C); +// eeprom.readBytes(address, length, buffer); +#define EEP_READ(A,B,C) eeprom.readBytes(A,B,(uint8_t*)C); +#endif + #define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++; #define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++; -// allocates all variable and presets them -int16_t Init_Scripter(char *script) { +// allocates all variables and presets them +int16_t Init_Scripter(void) { +char *script; + + script=glob_script_mem.script_ram; + // scan lines for >DEF uint16_t lines=0,nvars=0,svars=0,vars=0; char *lp=script; @@ -415,10 +462,7 @@ int16_t Init_Scripter(char *script) { #endif // now preset permanent vars - uint32_t lptr=(uint32_t)Settings.mems[0]; - lptr&=0xfffffffc; - float *fp=(float*)lptr; - fp++; + float *fp=(float*)glob_script_mem.script_pram; struct T_INDEX *vtp=glob_script_mem.type; for (uint8_t count=0; count0 ClaimSerial(); SetSerialBaudrate(9600); @@ -513,8 +570,13 @@ void Set_MFVal(uint8_t index,uint8_t bind,float val) { struct M_FILT *mflp=(struct M_FILT*)mp; if (count==index) { uint8_t maxind=mflp->numvals&0x7f; - if (bind<1 || bind>maxind) bind=maxind; - mflp->rbuff[bind-1]=val; + if (!bind) { + mflp->index=val; + } else { + if (bind<1 || bind>maxind) bind=maxind; + mflp->rbuff[bind-1]=val; + } + return; } mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); } @@ -610,7 +672,24 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso lp++; while (*lp!='"') { if (*lp==0 || *lp==SCRIPT_EOL) break; - if (sp) *sp++=*lp; + uint8_t iob=*lp; + if (iob=='\\') { + lp++; + if (*lp=='t') { + iob='\t'; + } else if (*lp=='n') { + iob='\n'; + } else if (*lp=='r') { + iob='\r'; + } else if (*lp=='\\') { + iob='\\'; + } else { + lp--; + } + if (sp) *sp++=iob; + } else { + if (sp) *sp++=iob; + } lp++; } if (sp) *sp=0; @@ -797,6 +876,141 @@ chknext: goto exit; } break; +#ifdef USE_SCRIPT_FATFS + case 'f': + if (!strncmp(vname,"fo(",3)) { + lp+=3; + char str[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,str,0); + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + uint8_t mode=fvar; + fvar=-1; + for (uint8_t cnt=0;cnt=SFS_MAX) ind=SFS_MAX-1; + glob_script_mem.files[ind].close(); + glob_script_mem.file_flags[ind]=0; + fvar=0; + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"fw(",3)) { + lp+=3; + char str[SCRIPT_MAXSSIZE]; + lp=ForceStringVar(lp,str); + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + uint8_t ind=fvar; + if (ind>=SFS_MAX) ind=SFS_MAX-1; + if (glob_script_mem.file_flags[ind]&1) { + fvar=glob_script_mem.files[ind].print(str); + } else { + fvar=0; + } + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"fr(",3)) { + lp+=3; + struct T_INDEX ind; + uint8_t vtype; + uint8_t sindex=0; + lp=isvar(lp,&vtype,&ind,0,0,0); + if (vtype!=VAR_NV) { + // found variable as result + if ((vtype&STYPE)==0) { + // error + fvar=0; + goto exit; + } else { + // string result + sindex=glob_script_mem.type[ind.index].index; + } + } else { + // error + fvar=0; + goto exit; + } + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + uint8_t find=fvar; + if (find>=SFS_MAX) find=SFS_MAX-1; + uint8_t index=0; + char str[glob_script_mem.max_ssize+1]; + char *cp=str; + if (glob_script_mem.file_flags[find]&1) { + while (glob_script_mem.files[find].available()) { + char buf[1]; + glob_script_mem.files[find].read(buf,1); + if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { + break; + } else { + *cp++=buf[0]; + index++; + if (index>=glob_script_mem.max_ssize-1) break; + } + } + *cp=0; + } else { + strcpy(str,"file error"); + } + lp++; + strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); + fvar=index; + len=0; + goto exit; + } + if (!strncmp(vname,"fd(",3)) { + lp+=3; + char str[glob_script_mem.max_ssize+1]; + lp=GetStringResult(lp,OPER_EQU,str,0); + SD.remove(str); + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"fl1(",4) || !strncmp(vname,"fl2(",4) ) { + uint8_t lknum=*(lp+2)&3; + lp+=4; + char str[glob_script_mem.max_ssize+1]; + lp=GetStringResult(lp,OPER_EQU,str,0); + if (lknum<1 || lknum>2) lknum=1; + strlcpy(glob_script_mem.flink[lknum-1],str,14); + lp++; + fvar=0; + len=0; + goto exit; + } + if (!strncmp(vname,"fsm",3)) { + fvar=glob_script_mem.script_sd_found; + //card_init(); + goto exit; + } + break; + +#endif //USE_SCRIPT_FATFS case 'g': if (!strncmp(vname,"gtmp",4)) { fvar=global_temperature; @@ -974,7 +1188,7 @@ chknext: break; case 'r': if (!strncmp(vname,"ram",3)) { - fvar=glob_script_mem.script_mem_size+(MAX_RULE_SETS*MAX_RULE_SIZE)+(MAX_RULE_MEMS*10); + fvar=glob_script_mem.script_mem_size+(glob_script_mem.script_size)+(MAX_RULE_MEMS*10); goto exit; } break; @@ -996,7 +1210,7 @@ chknext: goto exit; } if (!strncmp(vname,"slen",4)) { - fvar=strlen(Settings.rules[0]); + fvar=strlen(glob_script_mem.script_ram); goto exit; } if (!strncmp(vname,"st(",3)) { @@ -1033,6 +1247,16 @@ chknext: } goto strexit; } + if (!strncmp(vname,"s(",2)) { + lp+=2; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + char str[glob_script_mem.max_ssize+1]; + dtostrfd(fvar,glob_script_mem.script_dprec,str); + if (sp) strlcpy(sp,str,glob_script_mem.max_ssize); + lp++; + len=0; + goto strexit; + } #if defined(USE_TIMERS) && defined(USE_SUNRISE) if (!strncmp(vname,"sunrise",7)) { fvar=SunMinutes(0); @@ -1416,6 +1640,20 @@ struct T_INDEX ind; } +char *ForceStringVar(char *lp,char *dstr) { + float fvar; + char *slp=lp; + glob_script_mem.var_not_found=0; + lp=GetStringResult(lp,OPER_EQU,dstr,0); + if (glob_script_mem.var_not_found) { + // mismatch + lp=GetNumericResult(slp,OPER_EQU,&fvar,0); + dtostrfd(fvar,6,dstr); + glob_script_mem.var_not_found=0; + } + return lp; +} + // replace vars in cmd %var% void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) { char *cp; @@ -1774,7 +2012,7 @@ int16_t Run_Scripter(const char *type, uint8_t tlen, char *js) { toLog(&tmp[5]); } else { snprintf_P(log_data, sizeof(log_data), PSTR("Script: performs \"%s\""), tmp); - AddLog(glob_script_mem.script_loglevel); + AddLog(glob_script_mem.script_loglevel&0x7f); tasm_cmd_activ=1; ExecuteCommand((char*)tmp, SRC_RULE); tasm_cmd_activ=0; @@ -2078,8 +2316,8 @@ int16_t Run_Scripter(const char *type, uint8_t tlen, char *js) { uint8_t script_xsns_index = 0; -void ScripterEvery100ms(void) -{ +void ScripterEvery100ms(void) { + if (Settings.rule_enabled && (uptime > 4)) { mqtt_data[0] = '\0'; uint16_t script_tele_period_save = tele_period; @@ -2098,11 +2336,8 @@ void ScripterEvery100ms(void) // can hold 11 floats or floats + strings // should report overflow later void Scripter_save_pvars(void) { - uint32_t lptr=(uint32_t)Settings.mems[0]; int16_t mlen=0; - lptr&=0xfffffffc; - float *fp=(float*)lptr; - fp++; + float *fp=(float*)glob_script_mem.script_pram; mlen+=sizeof(float); struct T_INDEX *vtp=glob_script_mem.type; for (uint8_t count=0; count " D_RULEVARS " " + "
 " D_SCRIPT " " "
"; const char HTTP_FORM_SCRIPT1[] PROGMEM = - "
script enable
" - "
"; + "" + ""; + +#ifdef USE_SCRIPT_FATFS +const char HTTP_FORM_SCRIPT1c[] PROGMEM = +""; +#endif + +#ifdef USE_SCRIPT_FATFS + +void script_download(uint8_t num) { + File download_file; + WiFiClient download_Client; + + if (!HttpCheckPriviledgedAccess()) { return; } + + if (!SD.exists(glob_script_mem.flink[num-1])) { + toLog("file not found"); + return; + } + + download_file=SD.open(glob_script_mem.flink[num-1],FILE_READ); + if (!download_file) { + toLog("could not open file"); + } + uint32_t flen=download_file.size(); + + download_Client = WebServer->client(); + WebServer->setContentLength(flen); + + char attachment[100]; + snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),glob_script_mem.flink[num-1]); + WebServer->sendHeader(F("Content-Disposition"), attachment); + WSSend(200, CT_STREAM, ""); + + uint8_t buff[512]; + uint16_t bread; + + // transfer is about 150kb/s + uint8_t cnt=0; + while (download_file.available()) { + bread=download_file.read(buff,sizeof(buff)); + uint16_t bw=download_Client.write((const char*)buff,bread); + if (!bw) break; + cnt++; + if (cnt>7) { + cnt=0; + if (glob_script_mem.script_loglevel&0x80) { + // this indeed multitasks, but is slower 50 kB/s + loop(); + } + } + } + download_file.close(); + download_Client.stop(); +} +#endif void HandleScriptConfiguration(void) { @@ -2169,16 +2475,31 @@ void HandleScriptConfiguration(void) return; } +#ifdef USE_SCRIPT_FATFS + if (WebServer->hasArg("d1")) { + script_download(1); + } + if (WebServer->hasArg("d2")) { + script_download(2); + } +#endif + WSContentStart_P(S_CONFIGURE_SCRIPT); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_SCRIPT); - WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",1,1,MAX_RULE_SIZE*3); + WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); // script is to larg for WSContentSend_P - if (Settings.rules[0][0]) { - _WSContentSend(Settings.rules[0]); + if (glob_script_mem.script_ram[0]) { + _WSContentSend(glob_script_mem.script_ram); } WSContentSend_P(HTTP_FORM_SCRIPT1b); + +#ifdef USE_SCRIPT_FATFS + if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,1,glob_script_mem.flink[0]); + if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,2,glob_script_mem.flink[1]); +#endif + WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentStop(); @@ -2195,7 +2516,7 @@ void strrepl_inplace(char *str, const char *a, const char *b) { } } -#define MAX_SCRIPT_SIZE MAX_RULE_SIZE*3 + void ScriptSaveSettings(void) { @@ -2215,7 +2536,23 @@ void ScriptSaveSettings(void) { str.replace("\r\n","\n"); str.replace("\r","\n"); #endif - strlcpy(Settings.rules[0],str.c_str(), MAX_RULE_SIZE*3); + strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); + +#ifdef USE_24C256 + if (glob_script_mem.flags&1) { + EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); + } +#endif + +#ifdef USE_SCRIPT_FATFS + if (glob_script_mem.flags&1) { + SD.remove(FAT_SCRIPT_NAME); + File file=SD.open(FAT_SCRIPT_NAME,FILE_WRITE); + file.write(glob_script_mem.script_ram,FAT_SCRIPT_SIZE); + file.close(); + } +#endif + } if (glob_script_mem.script_mem) { @@ -2226,7 +2563,7 @@ void ScriptSaveSettings(void) { } if (bitRead(Settings.rule_enabled, 0)) { - int16_t res=Init_Scripter(Settings.rules[0]); + int16_t res=Init_Scripter(); if (res) { snprintf_P(log_data, sizeof(log_data), PSTR("script init error: %d"),res); AddLog(LOG_LEVEL_INFO); @@ -2280,7 +2617,7 @@ bool ScriptCommand(void) { }*/ } } - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"Free\":%d}"),command, GetStateText(bitRead(Settings.rule_enabled,0)),MAX_RULE_SIZE*3-strlen(Settings.rules[0])); + 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; return serviced; @@ -2290,13 +2627,76 @@ bool ScriptCommand(void) { * Interface \*********************************************************************************************/ -bool Xdrv10(byte function) +bool Xdrv10(uint8_t function) { bool result = false; switch (function) { case FUNC_PRE_INIT: - if (bitRead(Settings.rule_enabled, 0)) Init_Scripter(Settings.rules[0]); + // set defaults to rules memory + glob_script_mem.script_ram=Settings.rules[0]; + glob_script_mem.script_size=MAX_SCRIPT_SIZE; + glob_script_mem.flags=0; + glob_script_mem.script_pram=(uint8_t*)Settings.mems[0]; + glob_script_mem.script_pram_size=MAX_RULE_MEMS*10; + +#ifdef USE_24C256 + if (i2c_flg) { + if (I2cDevice(EEPROM_ADDRESS)) { + // found 32kb eeprom + char *script; + script=(char*)calloc(EEP_SCRIPT_SIZE+4,1); + if (!script) break; + glob_script_mem.script_ram=script; + glob_script_mem.script_size=EEP_SCRIPT_SIZE; + EEP_READ(0,EEP_SCRIPT_SIZE,script); + if (*script==0xff) { + memset(script,EEP_SCRIPT_SIZE,0); + } + script[EEP_SCRIPT_SIZE-1]=0; + // use rules storage for permanent vars + glob_script_mem.script_pram=(uint8_t*)Settings.rules[0]; + glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE; + + glob_script_mem.flags=1; + } + } +#endif + + + +#ifdef USE_SCRIPT_FATFS + if (SD.begin(USE_SCRIPT_FATFS)) { + glob_script_mem.script_sd_found=1; + char *script; + script=(char*)calloc(FAT_SCRIPT_SIZE+4,1); + if (!script) break; + glob_script_mem.script_ram=script; + glob_script_mem.script_size=FAT_SCRIPT_SIZE; + if (SD.exists(FAT_SCRIPT_NAME)) { + File file=SD.open(FAT_SCRIPT_NAME,FILE_READ); + file.read(script,FAT_SCRIPT_SIZE); + file.close(); + } + script[FAT_SCRIPT_SIZE-1]=0; + // use rules storage for permanent vars + glob_script_mem.script_pram=(uint8_t*)Settings.rules[0]; + glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE; + + glob_script_mem.flags=1; + } else { + glob_script_mem.script_sd_found=0; + } +#endif + + // assure permanent memory is 4 byte aligned + { uint32_t ptr=(uint32_t)glob_script_mem.script_pram; + ptr&=0xfffffffc; + glob_script_mem.script_pram=(uint8_t*)ptr; + glob_script_mem.script_pram_size-=4; + } + + if (bitRead(Settings.rule_enabled, 0)) Init_Scripter(); break; case FUNC_INIT: if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">B",2,0); From 7505f7dd64dbd881aea7b3f33930f6492c014817 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 30 May 2019 13:34:48 +0200 Subject: [PATCH 3/6] Update my_user_config.h --- sonoff/my_user_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 4c3b3ae30..624eecf43 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -291,8 +291,8 @@ // -- Rules or Script ---------------------------- // Select none or only one of the below defines -#define USE_RULES // Add support for rules (+8k code) -//#define USE_SCRIPT // Add support for script (+15k code) +//#define USE_RULES // Add support for rules (+8k code) +#define USE_SCRIPT // Add support for script (+15k code) // #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) From 66dfbb59827aece9013fb846ac5ce3cd46265f77 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 30 May 2019 13:56:21 +0200 Subject: [PATCH 4/6] Update my_user_config.h --- sonoff/my_user_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 624eecf43..f3bd851f6 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -293,6 +293,7 @@ // Select none or only one of the below defines //#define USE_RULES // Add support for rules (+8k code) #define USE_SCRIPT // Add support for script (+15k code) +#define USE_SCRIPT_FATFS 4 // #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) From 19a7e2af901f51f985a4aa6b53f9d26f19f60c98 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 30 May 2019 14:11:03 +0200 Subject: [PATCH 5/6] Update xdrv_10_scripter.ino --- sonoff/xdrv_10_scripter.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index d5a3176da..3b21603de 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -962,7 +962,7 @@ chknext: char *cp=str; if (glob_script_mem.file_flags[find]&1) { while (glob_script_mem.files[find].available()) { - char buf[1]; + uint8_t buf[1]; glob_script_mem.files[find].read(buf,1); if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { break; @@ -2675,7 +2675,7 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_size=FAT_SCRIPT_SIZE; if (SD.exists(FAT_SCRIPT_NAME)) { File file=SD.open(FAT_SCRIPT_NAME,FILE_READ); - file.read(script,FAT_SCRIPT_SIZE); + file.read((uint8_t*)script,FAT_SCRIPT_SIZE); file.close(); } script[FAT_SCRIPT_SIZE-1]=0; From 86a606dd90ef43acdf5449d5cc8fc9560df2fad3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 30 May 2019 14:18:22 +0200 Subject: [PATCH 6/6] Update my_user_config.h Keep rules the default --- sonoff/my_user_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index f3bd851f6..2dce8ed84 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -291,9 +291,9 @@ // -- Rules or Script ---------------------------- // Select none or only one of the below defines -//#define USE_RULES // Add support for rules (+8k code) -#define USE_SCRIPT // Add support for script (+15k code) -#define USE_SCRIPT_FATFS 4 +#define USE_RULES // Add support for rules (+8k code) +//#define USE_SCRIPT // Add support for script (+17k code) + #define USE_SCRIPT_FATFS 4 // #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)