diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 4d0bc1588..35427e67a 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -26,7 +26,6 @@ uses about 17 k of flash to do optimize code for space -g:var gloabal vars (via udp broadcast) remarks @@ -237,7 +236,11 @@ extern VButton *buttons[MAXBUTTONS]; #endif typedef union { +#ifdef USE_SCRIPT_GLOBVARS + uint16_t data; +#else uint8_t data; +#endif struct { uint8_t is_string : 1; // string or number uint8_t is_permanent : 1; @@ -247,6 +250,9 @@ typedef union { uint8_t settable : 1; uint8_t is_filter : 1; uint8_t constant : 1; +#ifdef USE_SCRIPT_GLOBVARS + uint8_t global : 1; +#endif }; } SCRIPT_TYPE; @@ -276,6 +282,32 @@ typedef union { }; } FILE_FLAGS; +typedef union { + uint8_t data; + struct { + uint8_t nutu8 : 1; + uint8_t nutu7 : 1; + uint8_t nutu6 : 1; + uint8_t nutu5 : 1; + uint8_t nutu4 : 1; + uint8_t nutu3 : 1; + uint8_t udp_connected : 1; + uint8_t udp_used : 1; + }; +} UDP_FLAGS; + + +#define NUM_RES 0xfe +#define STR_RES 0xfd +#define VAR_NV 0xff + +#define NTYPE 0 +#define STYPE 0x80 + +#ifndef FLT_MAX +#define FLT_MAX 99999999 +#endif + #define SFS_MAX 4 // global memory struct SCRIPT_MEM { @@ -308,12 +340,19 @@ struct SCRIPT_MEM { uint8_t script_sd_found; char flink[2][14]; #endif +#ifdef USE_SCRIPT_GLOBVARS + UDP_FLAGS udp_flags; +#endif } glob_script_mem; +#ifdef USE_SCRIPT_GLOBVARS +IPAddress last_udp_ip; +#endif int16_t last_findex; uint8_t tasm_cmd_activ=0; uint8_t fast_script=0; +uint8_t glob_script=0; uint32_t script_lastmillis; @@ -436,6 +475,16 @@ char *script; } else { vtypes[vars].bits.is_autoinc=0; } + +#ifdef USE_SCRIPT_GLOBVARS + if (*lp=='g' && *(lp+1)==':') { + lp+=2; + vtypes[vars].bits.global=1; + glob_script_mem.udp_flags.udp_used = 1; + } else { + vtypes[vars].bits.global=0; + } +#endif if ((*lp=='m' || *lp=='M') && *(lp+1)==':') { uint8_t flg=*lp; lp+=2; @@ -703,10 +752,112 @@ char *script; // store start of actual program here glob_script_mem.scriptptr=lp-1; glob_script_mem.scriptptr_bu=glob_script_mem.scriptptr; + +#ifdef USE_SCRIPT_GLOBVARS + if (glob_script_mem.udp_flags.udp_used) { + Script_Init_UDP(); + glob_script=Run_Scripter(">G",-2,0); + } +#endif + return 0; } +#ifdef USE_SCRIPT_GLOBVARS +#define SCRIPT_UDP_BUFFER_SIZE 128 +#define SCRIPT_UDP_PORT 1999 +IPAddress script_udp_remote_ip; + +void Script_Init_UDP() { + if (global_state.wifi_down) return; + if (glob_script_mem.udp_flags.udp_connected) return; + + if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), SCRIPT_UDP_PORT)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP "SCRIPT UDP started")); + glob_script_mem.udp_flags.udp_connected = 1; + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP "SCRIPT UDP failed")); + glob_script_mem.udp_flags.udp_connected = 0; + } +} +void Script_PollUdp(void) { + if (!glob_script_mem.udp_flags.udp_used) return; + if (glob_script_mem.udp_flags.udp_connected ) { + while (PortUdp.parsePacket()) { + char packet_buffer[SCRIPT_UDP_BUFFER_SIZE]; + int32_t len = PortUdp.read(packet_buffer, SCRIPT_UDP_BUFFER_SIZE -1); + packet_buffer[len] = 0; + script_udp_remote_ip = PortUdp.remoteIP(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("UDP: Packet %s - %d - %s"), packet_buffer, len, script_udp_remote_ip.toString().c_str()); + char *lp=packet_buffer; + if (!strncmp(lp,"=>",2)) { + lp+=2; + char *cp=strchr(lp,'='); + if (cp) { + char vnam[32]; + for (uint32_t count=0; countG",2,0); + } + } + } + } + optimistic_yield(100); + } + } else { + Script_Init_UDP(); + } +} + +void script_udp_sendvar(char *vname,float *fp,char *sp) { + if (!glob_script_mem.udp_flags.udp_used) return; + if (!glob_script_mem.udp_flags.udp_connected) return; + + char sbuf[SCRIPT_MAXSSIZE+4]; + strcpy(sbuf,"=>"); + strcat(sbuf,vname); + strcat(sbuf,"="); + if (fp) { + char flstr[16]; + dtostrfd(*fp,8,flstr); + strcat(sbuf,flstr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("num var updated - %s"),sbuf); + } else { + strcat(sbuf,sp); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("string var updated - %s"),sbuf); + } + PortUdp.beginPacket(IPAddress(239,255,255,250), SCRIPT_UDP_PORT); + // Udp.print(String("RET UC: ") + String(recv_Packet)); + PortUdp.write((const uint8_t*)sbuf,strlen(sbuf)); + PortUdp.endPacket(); +} + +#endif + #ifdef USE_LIGHT #ifdef USE_WS2812 void ws2812_set_array(float *array ,uint32_t len, uint32_t offset) { @@ -723,16 +874,7 @@ void ws2812_set_array(float *array ,uint32_t len, uint32_t offset) { #endif #endif -#define NUM_RES 0xfe -#define STR_RES 0xfd -#define VAR_NV 0xff -#define NTYPE 0 -#define STYPE 0x80 - -#ifndef FLT_MAX -#define FLT_MAX 99999999 -#endif float median_array(float *array,uint8_t len) { uint8_t ind[len]; @@ -1011,6 +1153,37 @@ uint32_t MeasurePulseTime(int32_t in) { } #endif // USE_ANGLE_FUNC +#ifdef USE_SCRIPT_GLOBVARS +uint32_t match_vars(char *dvnam, float **fp, char **sp, uint32_t *ind) { + uint16_t olen=strlen(dvnam); + struct T_INDEX *vtp=glob_script_mem.type; + for (uint32_t count=0; count ff=nothing found, fe=constant number,fd = constant string else bit 7 => 80 = string, 0 = number // no flash strings here for performance reasons!!! char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,JsonObject *jo) { @@ -1765,12 +1938,40 @@ chknext: len=0; goto exit; } + if (!strncmp(vname,"is(",3)) { + lp=GetNumericResult(lp+3,OPER_EQU,&fvar,0); + SCRIPT_SKIP_SPACES + if (*lp!='"') { + break; + } + lp++; + char *sstr=lp; + for (uint32_t cnt=0; cnt<256; cnt++) { + if (lp[cnt]='\n' || lp[cnt]=='"') { + lp+=cnt+1; + break; + } + } + char str[SCRIPT_MAXSSIZE]; + GetTextIndexed(str, sizeof(str), fvar, sstr); + lp++; + if (sp) strlcpy(sp,str,glob_script_mem.max_ssize); + fvar=0; + len=0; + goto exit; + } break; case 'l': if (!strncmp(vname,"lip",3)) { if (sp) strlcpy(sp,(const char*)WiFi.localIP().toString().c_str(),glob_script_mem.max_ssize); goto strexit; } +#ifdef USE_SCRIPT_GLOBVARS + if (!strncmp(vname,"luip",4)) { + if (sp) strlcpy(sp,IPAddressToString(last_udp_ip),glob_script_mem.max_ssize); + goto strexit; + } +#endif if (!strncmp(vname,"loglvl",6)) { fvar=glob_script_mem.script_loglevel; tind->index=SCRIPT_LOGLEVEL; @@ -3167,7 +3368,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { if (!if_exe[ifstck] && if_state[ifstck]!=1) goto next_line; #ifdef IFTHEN_DEBUG - sprintf(tbuff,"stack=%d,exe=%d,state=%d,cmpres=%d execute line: ",ifstck,if_exe[ifstck],if_state[ifstck],if_result[ifstck]); + sdtoff(tbuff,"stack=%d,exe=%d,state=%d,cmpres=%d execute line: ",ifstck,if_exe[ifstck],if_state[ifstck],if_result[ifstck]); toLogEOL(tbuff,lp); #endif @@ -3382,8 +3583,16 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { } goto next_line; } else { + char *vnp=lp; lp=isvar(lp,&vtype,&ind,&sysvar,0,0); if (vtype!=VAR_NV) { +#ifdef USE_SCRIPT_GLOBVARS + char varname[16]; + uint32_t vnl=(uint32_t)lp-(uint32)vnp; + strncpy(varname,vnp,vnl); + varname[vnl]=0; +#endif + // found variable as result globvindex=ind.index; // save destination var index here globaindex=last_findex; @@ -3451,6 +3660,11 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { } // var was changed glob_script_mem.type[globvindex].bits.changed=1; +#ifdef USE_SCRIPT_GLOBVARS + if (glob_script_mem.type[globvindex].bits.global) { + script_udp_sendvar(varname,dfvar,0); + } +#endif if (glob_script_mem.type[globvindex].bits.is_filter) { if (globaindex>=0) { Set_MFVal(glob_script_mem.type[globvindex].index,globaindex,*dfvar); @@ -3492,6 +3706,11 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { if (!glob_script_mem.var_not_found) { // var was changed glob_script_mem.type[globvindex].bits.changed=1; +#ifdef USE_SCRIPT_GLOBVARS + if (glob_script_mem.type[globvindex].bits.global) { + script_udp_sendvar(varname,0,str); + } +#endif if (lastop==OPER_EQU) { strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); } else if (lastop==OPER_PLSEQU) { @@ -6136,6 +6355,12 @@ bool Xdrv10(uint8_t function) break; #endif +#ifdef USE_SCRIPT_GLOBVARS + case FUNC_LOOP: + Script_PollUdp(); + break; +#endif + } return result; }