diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index d4b4d1134..48fe3e891 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -205,11 +205,17 @@ void alt_eeprom_readBytes(uint32_t adr, uint32_t len, uint8_t *buf) { #endif // LITTLEFS_SCRIPT_SIZE +#include #ifdef TESLA_POWERWALL #include "powerwall.h" #endif +#ifdef USE_DISPLAY_DUMP +#include +extern Renderer *renderer; +#endif + // offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution #ifndef EPOCH_OFFSET #define EPOCH_OFFSET 1546300800 @@ -231,7 +237,7 @@ extern FS *ufsp; #endif // USE_UFILESYS -extern "C" void homekit_main(char *, uint32_t); +extern "C" int32_t homekit_main(char *, uint32_t); #ifdef SUPPORT_MQTT_EVENT #include // Import LinkedList library @@ -434,6 +440,9 @@ struct SCRIPT_MEM { bool homekit_running = false; #endif // USE_HOMEKIT uint32_t epoch_offset = EPOCH_OFFSET; +#ifdef USE_SCRIPT_SERIAL + TasmotaSerial *sp; +#endif } glob_script_mem; @@ -3176,6 +3185,143 @@ chknext: goto exit; } #endif //USE_SML_M + +#ifdef USE_SCRIPT_SERIAL + if (!strncmp(vname, "so(", 3)) { + float rxpin, txpin, br; + lp = GetNumericArgument(lp + 3, OPER_EQU, &rxpin, gv); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &txpin, gv); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &br, gv); + SCRIPT_SKIP_SPACES + uint32_t sconfig = TS_SERIAL_8N1; + if (*lp!=')') { + // serial options, must be 3 chars 8N1, 7E2 etc + uint8_t bits = *lp++ & 0xf; + uint8_t parity = 0; + if (*lp == 'E') parity = 1; + if (*lp == 'O') parity = 2; + lp++; + uint8_t stopb = (*lp++ & 0x3) - 1; + sconfig = (bits - 5) + (parity * 8) + stopb * 4; + } + fvar= -1; + if (glob_script_mem.sp) { + fvar == -1; + } else { + if (Is_gpio_used(rxpin) || Is_gpio_used(txpin)) { + AddLog(LOG_LEVEL_INFO, PSTR("warning: pins already used")); + } + + glob_script_mem.sp = new TasmotaSerial(rxpin, txpin, 1); + if (glob_script_mem.sp) { + uint32_t config; +#ifdef ESP8266 + config = pgm_read_byte(kTasmotaSerialConfig + sconfig); +#endif // ESP8266 + +#ifdef ESP32 + config = pgm_read_dword(kTasmotaSerialConfig + sconfig); +#endif // ESP32 + fvar = glob_script_mem.sp->begin(br, config); + uint32_t savc = Settings->serial_config; + Settings->serial_config = sconfig; + AddLog(LOG_LEVEL_INFO, PSTR("Serial port set to %s %d bit/s at rx=%d tx=%d"), GetSerialConfig().c_str(), (uint32_t)br, (uint32_t)rxpin, (uint32_t)txpin); + Settings->serial_config = savc; + if (rxpin == 3 and txpin == 1) ClaimSerial(); + + } else { + fvar = -2; + } + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sw(", 3)) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + fvar = -1; + if (glob_script_mem.sp) { + glob_script_mem.sp->write(str, strlen(str)); + fvar = 0; + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "swb(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = -1; + if (glob_script_mem.sp) { + glob_script_mem.sp->write((uint8_t)fvar); + fvar = 0; + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sa(", 3)) { + fvar = -1; + if (glob_script_mem.sp) { + fvar = glob_script_mem.sp->available(); + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "srb(", 3)) { + fvar = -1; + if (glob_script_mem.sp) { + fvar = glob_script_mem.sp->available(); + if (fvar > 0) { + fvar = glob_script_mem.sp->read(); + } + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sp(", 3)) { + fvar = -1; + if (glob_script_mem.sp) { + fvar = glob_script_mem.sp->available(); + if (fvar > 0) { + fvar = glob_script_mem.sp->peek(); + } + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sr(", 4)) { + char str[SCRIPT_MAXSSIZE]; + memset(str, 0, sizeof(str)); + fvar = -1; + if (glob_script_mem.sp) { + for (uint8_t index = 0; index < sizeof(str) - 1; index++) { + if (!glob_script_mem.sp->available()) { + break; + } + str[index] = glob_script_mem.sp->read(); + } + } + lp++; + len = 0; + if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); + goto strexit;; + } + if (!strncmp(vname, "sc(", 3)) { + fvar = -1; + if (Script_Close_Serial()) { + fvar = 0; + } + lp+=4; + len = 0; + goto exit; + } +#endif //USE_SCRIPT_SERIAL break; case 't': if (!strncmp(vname, "time", 4)) { @@ -3280,6 +3426,21 @@ chknext: goto exit; } #endif + +#ifdef USE_TIMERS + if (!strncmp(vname, "ttget(", 6)) { + lp = GetNumericArgument(lp + 6, OPER_EQU, &fvar, gv); + SCRIPT_SKIP_SPACES + uint8_t index = fvar; + if (index < 1 || index > MAX_TIMERS) index = 1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv); + SCRIPT_SKIP_SPACES + fvar = get_tpars(index - 1, fvar); + lp++; + len = 0; + goto exit; + } +#endif break; case 'u': if (!strncmp(vname, "uptime", 6)) { @@ -3382,7 +3543,7 @@ chknext: goto exit; } #endif // USE_TTGO_WATCH -#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) +#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_M5EPD47) if (!strncmp(vname, "wtch(", 5)) { lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv); fvar = Touch_Status(fvar); @@ -4498,6 +4659,9 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { // set pin mode lp = GetNumericArgument(lp + 6, OPER_EQU, &fvar, 0); int8_t pinnr = fvar; + if (Is_gpio_used(pinnr)) { + AddLog(LOG_LEVEL_INFO, PSTR("warning: pins already used")); + } SCRIPT_SKIP_SPACES uint8_t mode = 0; if ((*lp=='I') || (*lp=='O') || (*lp=='P')) { @@ -5000,6 +5164,25 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { return -1; } +#ifdef USE_SCRIPT_SERIAL +bool Script_Close_Serial() { + if (glob_script_mem.sp) { + glob_script_mem.sp->flush(); + delay(100); + delete(glob_script_mem.sp); + glob_script_mem.sp = 0; + return true; + } + return false; +} +#endif //USE_SCRIPT_SERIAL + +bool Is_gpio_used(uint8_t gpiopin) { + if ((gpiopin < nitems(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) { + return true; + } + return false; +} void ScripterEvery100ms(void) { static uint8_t xsns_index = 0; @@ -5440,6 +5623,8 @@ void ScriptSaveSettings(void) { SaveScript(); + } else { + AddLog(LOG_LEVEL_INFO, PSTR("script memory error")); } SaveScriptEnd(); @@ -5481,6 +5666,10 @@ void SaveScriptEnd(void) { return; } +#ifdef USE_SCRIPT_SERIAL + Script_Close_Serial(); +#endif + Run_Scripter(">B\n", 3, 0); Run_Scripter(">BS", 3, 0); @@ -6529,9 +6718,8 @@ char buff[512]; if (sflg) { #ifdef USE_DISPLAY_DUMP - -#include -extern Renderer *renderer; +//#include +//extern Renderer *renderer; // screen copy #define fileHeaderSize 14 @@ -6541,7 +6729,9 @@ extern Renderer *renderer; uint8_t *bp = renderer->framebuffer; uint8_t *lbuf = (uint8_t*)special_malloc(Settings->display_width * 3 + 2); if (!lbuf) return; - int8_t bpp = renderer->disp_bpp; + uint8_t dmflg = 0; + if (renderer->disp_bpp & 0x40) dmflg = 1; + int8_t bpp = renderer->disp_bpp & 0xbf;; uint8_t *lbp; uint8_t fileHeader[fileHeaderSize]; createBitmapFileHeader(Settings->display_height , Settings->display_width , fileHeader); @@ -6549,8 +6739,7 @@ extern Renderer *renderer; uint8_t infoHeader[infoHeaderSize]; createBitmapInfoHeader(Settings->display_height, Settings->display_width, infoHeader ); Webserver->client().write((uint8_t *)infoHeader, infoHeaderSize); - - if (bpp == -1) { + if (bpp < 0) { for (uint32_t lins = Settings->display_height - 1; lins >= 0 ; lins--) { lbp = lbuf; for (uint32_t cols = 0; cols < Settings->display_width; cols ++) { @@ -6570,16 +6759,30 @@ extern Renderer *renderer; if (bpp == 4) { for (uint32_t cols = 0; cols < Settings->display_width; cols += 2) { uint8_t pixel; - for (uint32_t cnt = 0; cnt <= 1; cnt++) { - if (cnt & 1) { - pixel = *bp >> 4; - } else { - pixel = *bp & 0xf; + if (!dmflg) { + for (uint32_t cnt = 0; cnt <= 1; cnt++) { + if (cnt & 1) { + pixel = *bp >> 4; + } else { + pixel = *bp & 0xf; + } } pixel *= 15; *--lbp = pixel; *--lbp = pixel; *--lbp = pixel; + } else { + for (uint32_t cnt = 0; cnt <= 1; cnt++) { + if (!(cnt & 1)) { + pixel = *bp >> 4; + } else { + pixel = *bp & 0xf; + } + pixel *= 15; + *--lbp = pixel; + *--lbp = pixel; + *--lbp = pixel; + } } bp++; } @@ -6601,8 +6804,8 @@ extern Renderer *renderer; bp++; } } + Webserver->client().write((const char*)lbuf, Settings->display_width * 3); } - Webserver->client().write((const char*)lbuf, Settings->display_width * 3); } if (lbuf) free(lbuf); Webserver->client().stop(); @@ -6796,6 +6999,13 @@ const char SCRIPT_MSG_SLIDER[] PROGMEM = const char SCRIPT_MSG_CHKBOX[] PROGMEM = "
"; +const char SCRIPT_MSG_PULLDOWNa[] PROGMEM = + "
"; + const char SCRIPT_MSG_TEXTINP[] PROGMEM = "
"; @@ -7098,7 +7308,43 @@ void ScriptWebShow(char mc) { uval = 1; } WSContentSend_PD(SCRIPT_MSG_CHKBOX, label, (char*)cp, uval, vname); + } else if (!strncmp(lin, "pd(", 3)) { + // pull down + char *lp = lin + 3; + char *slp = lp; + float val; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + SCRIPT_SKIP_SPACES + char pulabel[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, pulabel, 0); + + WSContentSend_PD(SCRIPT_MSG_PULLDOWNa, vname, pulabel, 1, vname, vname); + + // get pu labels + uint8_t index = 1; + while (*lp) { + SCRIPT_SKIP_SPACES + lp = GetStringArgument(lp, OPER_EQU, pulabel, 0); + char *cp; + if (val == index) { + cp = (char*)"selected"; + } else { + cp = (char*)""; + } + WSContentSend_PD(SCRIPT_MSG_PULLDOWNb, cp, index, pulabel); + SCRIPT_SKIP_SPACES + if (*lp == ')') { + lp++; + break; + } + index++; + } + WSContentSend_PD(SCRIPT_MSG_PULLDOWNc); } else if (!strncmp(lin, "bu(", 3)) { char *lp = lin + 3; uint8_t bcnt = 0; @@ -8295,6 +8541,42 @@ void lvgl_setup(void) { #endif // USE_LVGL + +#ifdef USE_TIMERS +int32_t get_tpars(uint32_t index, uint32_t sel) { +int32_t retval = 0; + switch (sel) { + case 0: + retval = Settings->timer[index].time; + break; + case 1: + //retval = Settings->timer[index].window; + retval = timer_window[index]; + break; + case 2: + retval = Settings->timer[index].repeat; + break; + case 3: + retval = Settings->timer[index].days; + break; + case 4: + retval = Settings->timer[index].device; + break; + case 5: + retval = Settings->timer[index].power; + break; + case 6: + retval = Settings->timer[index].mode; + break; + case 7: + retval = Settings->timer[index].arm; + break; + } + return retval; +} + +#endif + /*********************************************************************************************\ * Interface \*********************************************************************************************/