From 0ebcbc76dc7642af17a2fac98e2872dbb813ffdd Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 5 Jun 2020 18:24:31 +0200 Subject: [PATCH 1/6] Fix wrong sign of attributes --- tasmota/xdrv_23_zigbee_5_converters.ino | 2 +- tasmota/xdrv_23_zigbee_9_impl.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index bf508d9c2..70cbfe128 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -1397,7 +1397,7 @@ int32_t Z_ApplyConverter(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObje if (multiplier > 0) { json[new_name] = ((float)value) * multiplier; } else { - json[new_name] = ((float)value) / multiplier; + json[new_name] = ((float)value) / (-multiplier); } } diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 0ea39c194..4da0a48f6 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -483,7 +483,7 @@ void ZbSendReportWrite(const JsonObject &val_pubwrite, uint16_t device, uint16_t if (multiplier > 0) { // inverse of decoding val_f = val_f / multiplier; } else { - val_f = val_f * multiplier; + val_f = val_f * (-multiplier); } use_val = false; } From 9987b3f2d5b98a17e5aeb33ed86c89086f281494 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Fri, 5 Jun 2020 20:15:16 +0200 Subject: [PATCH 2/6] scripter update, eeprom support --- esp32_partition_app1984k_spiffs60k.csv | 7 + tasmota/my_user_config.h | 1 + tasmota/support_eeprom.ino | 89 ++++++++++ tasmota/xdrv_10_scripter.ino | 235 +++++++++++++++++-------- 4 files changed, 254 insertions(+), 78 deletions(-) create mode 100644 esp32_partition_app1984k_spiffs60k.csv create mode 100644 tasmota/support_eeprom.ino diff --git a/esp32_partition_app1984k_spiffs60k.csv b/esp32_partition_app1984k_spiffs60k.csv new file mode 100644 index 000000000..e8bcd9d49 --- /dev/null +++ b/esp32_partition_app1984k_spiffs60k.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x1F0000, +app1, app, ota_1, 0x200000, 0x1F0000, +spiffs, data, spiffs, 0x3F0000,0xf000, +eeprom, data, nvs, 0x3FF000,0x1000, diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 050c2e390..b6008abcf 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -399,6 +399,7 @@ #define USE_RULES // Add support for rules (+8k code) #define USE_RULES_COMPRESSION // Compresses rules in Flash at about ~50% (+3.3k code) //#define USE_SCRIPT // Add support for script (+17k code) + #define USE_SCRIPT_COMPRESSION //#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) diff --git a/tasmota/support_eeprom.ino b/tasmota/support_eeprom.ino new file mode 100644 index 000000000..b990aa242 --- /dev/null +++ b/tasmota/support_eeprom.ino @@ -0,0 +1,89 @@ +/* + support_eeprom.ino - eeprom support for Sonoff-Tasmota + + Copyright (C) 2020 Theo Arends & Gerhard Mutz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + supports hardware i2c eeprom 24c256 and flash eeprom simulation on ESP8266 and ESP32 + all ESP8266 linker files contain 4k eeprom partition + ESP32 requires esp32_partition_app1984k_spiffs60k.csv for 4k eeprom +*/ + + +#ifdef USE_EEPROM + +#ifdef USE_24C256 + // i2c eeprom +#include +#define EEPROM_ADDRESS 0x50 +static Eeprom24C128_256 m_eeprom(EEPROM_ADDRESS); + +void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + m_eeprom.writeBytes(addr,len,(uint8_t*)buff); +} +void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + m_eeprom.readBytes(addr,len,(uint8_t*)buff); +} + +uint32_t eeprom_init(uint32_t size) { + if (i2c_flg) { + if (I2cActive(EEPROM_ADDRESS) || I2cSetDevice(EEPROM_ADDRESS)) { + // eeprom is present + I2cSetActiveFound(EEPROM_ADDRESS, "24C256"); + return 1; + } + } + return 0; +} + +#else // USE_24C256 + +#ifdef ESP32 + +// esp32 uses eeprom section +uint32_t eeprom_init(uint32_t size) { + return EEPROM.begin(size); +} +void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + EEPROM.writeBytes(addr, buff, len); + EEPROM.commit(); +} +void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + EEPROM.readBytes(addr, buff, len); +} + +#else +// esp8266 uses eeprom section +uint32_t eeprom_init(uint32_t size) { + EEPROM.begin(size); + return 1; +} +void eeprom_writeBytes(uint32_t adr, uint32_t len, uint8_t *buf) { + for (uint32_t cnt=0; cnt -//Unishox compressor; // singleton #define SCRIPT_COMPRESS compressor.unishox_compress #define SCRIPT_DECOMPRESS compressor.unishox_decompress #ifndef UNISHOXRSIZE @@ -78,17 +119,19 @@ uint32_t DecodeLightId(uint32_t hue_id); #endif #endif // USE_SCRIPT_COMPRESSION -#if (defined(LITTLEFS_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS)) || (USE_SCRIPT_FATFS==-1) +#if defined(LITTLEFS_SCRIPT_SIZE) || (USE_SCRIPT_FATFS==-1) #ifdef ESP32 #include "FS.h" #include "SPIFFS.h" #else #include #endif - FS *fsp; +#endif // LITTLEFS_SCRIPT_SIZE + +#ifdef LITTLEFS_SCRIPT_SIZE void SaveFile(const char *name,const uint8_t *buf,uint32_t len) { File file = fsp->open(name, "w"); if (!file) return; @@ -116,7 +159,7 @@ void LoadFile(const char *name,uint8_t *buf,uint32_t len) { file.read(buf, len); file.close(); } -#endif +#endif // LITTLEFS_SCRIPT_SIZE // offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution #define EPOCH_OFFSET 1546300800 @@ -317,23 +360,10 @@ void RulesTeleperiod(void) { } // EEPROM MACROS -#ifdef USE_24C256 -#ifndef USE_SCRIPT_FATFS // i2c eeprom -#include -#define EEPROM_ADDRESS 0x50 -// strange bug, crashes with powers of 2 ??? 4096 crashes -#ifndef EEP_SCRIPT_SIZE -#define EEP_SCRIPT_SIZE 4095 -#endif +#define EEP_WRITE(A,B,C) eeprom_writeBytes(A,B,(uint8_t*)C); +#define EEP_READ(A,B,C) eeprom_readBytes(A,B,(uint8_t*)C); -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 -#endif #define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++; #define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++; @@ -651,13 +681,7 @@ char *script; #if USE_SCRIPT_FATFS>=0 fsp=&SD; - -#ifdef USE_MMC - if (fsp->begin()) { -#else if (SD.begin(USE_SCRIPT_FATFS)) { -#endif - #else if (fsp->begin()) { #endif @@ -738,13 +762,14 @@ float median_array(float *array,uint8_t len) { } -float *Get_MFAddr(uint8_t index,uint8_t *len) { +float *Get_MFAddr(uint8_t index,uint8_t *len,uint8_t *ipos) { *len=0; uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; for (uint8_t count=0; countnumvals&0x7f; + if (ipos) *ipos=mflp->index; return mflp->rbuff; } mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); @@ -936,6 +961,56 @@ if (hsv.S == 0) { #endif //#endif +#ifdef USE_ANGLE_FUNC +uint32_t pulse_time_hl; +uint32_t pulse_time_lh; +uint32_t pulse_ltime_hl; +uint32_t pulse_ltime_lh; +uint8_t pt_pin; + +void MP_Timer(void) ICACHE_RAM_ATTR; + +#define MPT_DEBOUNCE 10 + +void MP_Timer(void) { + uint32_t level = digitalRead(pt_pin&0x3f); + uint32_t ms = millis(); + uint32_t time; + if (level) { + // rising edge + pulse_ltime_lh = ms; + time = ms - pulse_ltime_hl; + if (time>MPT_DEBOUNCE) pulse_time_hl = time; + } else { + // falling edge + pulse_ltime_hl = ms; + time = ms - pulse_ltime_lh; + if (time>MPT_DEBOUNCE) pulse_time_lh = time; + } +} + +uint32_t MeasurePulseTime(int32_t in) { + if (in >= 0) { + // define pin; + pt_pin = in; + pinMode(pt_pin&0x3f,INPUT_PULLUP); + attachInterrupt(pt_pin&0x3f, MP_Timer, CHANGE); + pulse_ltime_lh = millis(); + pulse_ltime_hl = millis(); + return 0; + } + uint32_t ptime; + if (in==-1) { + ptime = pulse_time_lh; + pulse_time_lh = 0; + } else { + ptime = pulse_time_hl; + pulse_time_hl = 0; + } + return ptime; +} +#endif // USE_ANGLE_FUNC + // vtype => 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) { @@ -1720,6 +1795,15 @@ chknext: len=0; goto exit; } +#ifdef USE_ANGLE_FUNC + if (!strncmp(vname,"mpt(",4)) { + lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); + fvar=MeasurePulseTime(fvar); + lp++; + len=0; + goto exit; + } +#endif if (!strncmp(vname,"micros",6)) { fvar=micros(); goto exit; @@ -3159,7 +3243,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { // numeric result if (glob_script_mem.type[ind.index].bits.is_filter) { uint8_t len=0; - float *fa=Get_MFAddr(index,&len); + float *fa=Get_MFAddr(index,&len,0); //Serial.printf(">> 2 %d\n",(uint32_t)*fa); if (fa && len) ws2812_set_array(fa,len,fvar); } @@ -4065,26 +4149,26 @@ void ScriptSaveSettings(void) { } -#if defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) +#ifdef EEP_SCRIPT_SIZE if (glob_script_mem.flags&1) { EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); } -#endif +#endif // EEP_SCRIPT_SIZE -#if !defined(USE_24C256) && defined(USE_SCRIPT_FATFS) +#ifdef USE_SCRIPT_FATFS if (glob_script_mem.flags&1) { fsp->remove(FAT_SCRIPT_NAME); File file=fsp->open(FAT_SCRIPT_NAME,FILE_WRITE); file.write((const uint8_t*)glob_script_mem.script_ram,FAT_SCRIPT_SIZE); file.close(); } -#endif +#endif // USE_SCRIPT_FATFS -#if defined(LITTLEFS_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) +#ifdef LITTLEFS_SCRIPT_SIZE if (glob_script_mem.flags&1) { SaveFile("/script.txt",(uint8_t*)glob_script_mem.script_ram,LITTLEFS_SCRIPT_SIZE); } -#endif +#endif // LITTLEFS_SCRIPT_SIZE } if (glob_script_mem.script_mem) { @@ -4095,10 +4179,6 @@ void ScriptSaveSettings(void) { } #ifdef USE_SCRIPT_COMPRESSION -#ifndef USE_24C256 -#ifndef USE_SCRIPT_FATFS -#ifndef LITTLEFS_SCRIPT_SIZE - //AddLog_P2(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram)); uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), Settings.rules[0], MAX_SCRIPT_SIZE-1); if (len_compressed > 0) { @@ -4107,10 +4187,6 @@ void ScriptSaveSettings(void) { } else { AddLog_P2(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); } - -#endif -#endif -#endif #endif // USE_SCRIPT_COMPRESSION if (bitRead(Settings.rule_enabled, 0)) { @@ -5068,10 +5144,11 @@ const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'"; #define MAX_GARRAY 4 -char *gc_get_arrays(char *lp, float **arrays, uint8_t *ranum, uint8_t *rentries) { +char *gc_get_arrays(char *lp, float **arrays, uint8_t *ranum, uint8_t *rentries, uint8_t *ipos) { struct T_INDEX ind; uint8_t vtype; uint8 entries=0; +uint8_t cipos=0; uint8_t anum=0; while (anum> 2 %d\n",(uint32_t)*fa); if (fa && len>=entries) { - if (!entries) {entries = len;} + if (!entries) { + entries = len; + } // add array to list arrays[anum]=fa; anum++; @@ -5111,6 +5190,7 @@ uint8 entries=0; //Serial.printf(">> %d - %d - %d\n",anum,entries,(uint32_t)*arrays[0]); *ranum=anum; *rentries=entries; + *ipos=cipos; return lp; } @@ -5409,7 +5489,8 @@ void ScriptWebShow(char mc) { float *arrays[MAX_GARRAY]; uint8_t anum=0; uint8 entries=0; - lp=gc_get_arrays(lp, &arrays[0], &anum, &entries); + uint8 ipos=0; + lp=gc_get_arrays(lp, &arrays[0], &anum, &entries, &ipos); if (anum>nanum) { goto nextwebline; @@ -5456,28 +5537,38 @@ void ScriptWebShow(char mc) { int8_t todflg=-1; if (!strncmp(label,"cnt",3)) { todflg=atoi(&label[3]); + if (todflg>=entries) todflg=entries-1; } + uint32_t aind=ipos; + if (aind>=entries) aind=entries-1; for (uint32_t cnt=0; cnt=0) { sprintf(lbl,"%d",todflg); todflg++; + if (todflg>=entries) { + todflg=0; + } } else { - GetTextIndexed(lbl, sizeof(lbl), cnt, label); + GetTextIndexed(lbl, sizeof(lbl), aind, label); } WSContentSend_PD(lbl); WSContentSend_PD("',"); for (uint32_t ind=0; ind=entries) { + aind=0; + } } // get header @@ -5722,7 +5813,7 @@ uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core) { /*********************************************************************************************\ * Interface \*********************************************************************************************/ - +//const esp_partition_t *esp32_part; bool Xdrv10(uint8_t function) { @@ -5740,9 +5831,6 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_pram_size=PMEM_SIZE; #ifdef USE_SCRIPT_COMPRESSION -#ifndef USE_24C256 -#ifndef USE_SCRIPT_FATFS -#ifndef LITTLEFS_SCRIPT_SIZE int32_t len_decompressed; sprt=(char*)calloc(UNISHOXRSIZE+8,1); if (!sprt) { break; } @@ -5751,9 +5839,6 @@ bool Xdrv10(uint8_t function) len_decompressed = SCRIPT_DECOMPRESS(Settings.rules[0], strlen(Settings.rules[0]), glob_script_mem.script_ram, glob_script_mem.script_size); if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed]=0; //AddLog_P2(LOG_LEVEL_INFO, PSTR("decompressed script len %d"),len_decompressed); -#endif -#endif -#endif #endif // USE_SCRIPT_COMPRESSION #ifdef USE_BUTTON_EVENT @@ -5762,10 +5847,8 @@ bool Xdrv10(uint8_t function) } #endif -#ifdef USE_24C256 -#ifndef USE_SCRIPT_FATFS - if (I2cEnabled(XI2C_37)) { - if (I2cSetDevice(EEPROM_ADDRESS)) { +#ifdef EEP_SCRIPT_SIZE + if (eeprom_init(EEP_SCRIPT_SIZE)) { // found 32kb eeprom char *script; script=(char*)calloc(EEP_SCRIPT_SIZE+4,1); @@ -5782,34 +5865,26 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE; glob_script_mem.flags=1; - I2cSetActiveFound(EEPROM_ADDRESS, "EEPROM"); - } } -#endif -#endif +#endif // EEP_SCRIPT_SIZE #ifdef USE_SCRIPT_FATFS #if USE_SCRIPT_FATFS>=0 - fsp = &SD; - -#ifdef USE_MMC - if (fsp->begin()) { -#else - + // fs on SD card #ifdef ESP32 if (PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO) && PinUsed(GPIO_SPI_CLK)) { - SPI.begin(Pin(GPIO_SPI_CLK),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_MOSI), -1); + SPI.begin(Pin(GPIO_SPI_CLK),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_MOSI), -1); } -#endif +#endif // ESP32 + fsp = &SD; if (SD.begin(USE_SCRIPT_FATFS)) { -#endif - #else - fsp = &LittleFS; - if (fsp->begin()) { -#endif + // fs on flash + fsp = &LittleFS; + if (fsp->begin()) { +#endif // USE_SCRIPT_FATFS>=0 //fsp->dateTimeCallback(dateTime); @@ -5834,14 +5909,18 @@ bool Xdrv10(uint8_t function) } else { glob_script_mem.script_sd_found=0; } -#endif +#endif // USE_SCRIPT_FATFS -#if defined(LITTLEFS_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) +#ifdef LITTLEFS_SCRIPT_SIZE #ifdef ESP32 + // spiffs on esp32 fsp = &SPIFFS; + //esp32_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,ESP_PARTITION_SUBTYPE_DATA_SPIFFS,NULL); + //Serial.printf("address %d - %d - %s\n",esp32_part->address,esp32_part->size, esp32_part->label); #else + // lfs on esp8266 fsp = &LittleFS; #endif char *script; @@ -5856,7 +5935,7 @@ bool Xdrv10(uint8_t function) 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 +#endif // LITTLEFS_SCRIPT_SIZE // a valid script MUST start with >D if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') { From 0bfb79e6942f5eb50146c946df7c7c89b72bc53e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 5 Jun 2020 22:27:47 +0200 Subject: [PATCH 3/6] Fix Zigbee Time and add TimeEpoch --- tasmota/xdrv_23_zigbee_5_converters.ino | 3 ++- tasmota/xdrv_23_zigbee_8_parsers.ino | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index bf508d9c2..02a0f4d6d 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -136,7 +136,7 @@ ZF(MainsVoltage) ZF(MainsFrequency) ZF(BatteryVoltage) ZF(BatteryPercentage) ZF(CurrentTemperature) ZF(MinTempExperienced) ZF(MaxTempExperienced) ZF(OverTempTotalDwell) ZF(SceneCount) ZF(CurrentScene) ZF(CurrentGroup) ZF(SceneValid) ZF(AlarmCount) ZF(Time) ZF(TimeStatus) ZF(TimeZone) ZF(DstStart) ZF(DstEnd) -ZF(DstShift) ZF(StandardTime) ZF(LocalTime) ZF(LastSetTime) ZF(ValidUntilTime) +ZF(DstShift) ZF(StandardTime) ZF(LocalTime) ZF(LastSetTime) ZF(ValidUntilTime) ZF(TimeEpoch) ZF(LocationType) ZF(LocationMethod) ZF(LocationAge) ZF(QualityMeasure) ZF(NumberOfDevices) @@ -283,6 +283,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zuint32, Cx000A, 0x0007, Z(LocalTime), 1, Z_Nop }, { ZUTC, Cx000A, 0x0008, Z(LastSetTime), 1, Z_Nop }, { ZUTC, Cx000A, 0x0009, Z(ValidUntilTime), 1, Z_Nop }, + { ZUTC, Cx000A, 0xFF00, Z(TimeEpoch), 1, Z_Nop }, // Tasmota specific, epoch // RSSI Location cluster { Zdata8, Cx000B, 0x0000, Z(LocationType), 1, Z_Nop }, diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 996103fe5..aad2732ca 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -866,7 +866,8 @@ void Z_AutoResponder(uint16_t srcaddr, uint16_t cluster, uint8_t endpoint, const break; #endif case 0x000A: // Time - if (HasKeyCaseInsensitive(json, PSTR("Time"))) { json_out[F("Time")] = Rtc.utc_time; } + if (HasKeyCaseInsensitive(json, PSTR("Time"))) { json_out[F("Time")] = (Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? Rtc.utc_time - 946684800 : Rtc.utc_time; } + if (HasKeyCaseInsensitive(json, PSTR("TimeEpoch"))) { json_out[F("TimeEpoch")] = Rtc.utc_time; } if (HasKeyCaseInsensitive(json, PSTR("TimeStatus"))) { json_out[F("TimeStatus")] = (Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? 0x02 : 0x00; } // if time is beyond 2010 then we are synchronized if (HasKeyCaseInsensitive(json, PSTR("TimeZone"))) { json_out[F("TimeZone")] = Settings.toffset[0] * 60; } // seconds break; From a7b70f04e085e55115600e004edfe9032bf522c9 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sat, 6 Jun 2020 06:38:12 +0200 Subject: [PATCH 4/6] Update esp32_partition_app1984k_spiffs60k.csv converted and verified with gen_esp32part.py tool --- esp32_partition_app1984k_spiffs60k.csv | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/esp32_partition_app1984k_spiffs60k.csv b/esp32_partition_app1984k_spiffs60k.csv index e8bcd9d49..9c5f895a0 100644 --- a/esp32_partition_app1984k_spiffs60k.csv +++ b/esp32_partition_app1984k_spiffs60k.csv @@ -1,7 +1,8 @@ -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x5000, -otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x1F0000, -app1, app, ota_1, 0x200000, 0x1F0000, -spiffs, data, spiffs, 0x3F0000,0xf000, -eeprom, data, nvs, 0x3FF000,0x1000, +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs,data,nvs,0x9000,20K, +otadata,data,ota,0xe000,8K, +app0,app,ota_0,0x10000,1984K, +app1,app,ota_1,0x200000,1984K, +spiffs,data,spiffs,0x3f0000,60K, +eeprom,data,nvs,0x3ff000,4K, From 8a67477cab1ea54c4dadf4b0f38942d8e87cdc2f Mon Sep 17 00:00:00 2001 From: Matteo Albinola Date: Sat, 6 Jun 2020 09:25:00 +0200 Subject: [PATCH 5/6] Make ISR variables volatile --- tasmota/xsns_68_windmeter.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xsns_68_windmeter.ino b/tasmota/xsns_68_windmeter.ino index 3faa7ecb7..5487c898c 100644 --- a/tasmota/xsns_68_windmeter.ino +++ b/tasmota/xsns_68_windmeter.ino @@ -58,8 +58,8 @@ float const windmeter_pi = 3.1415926535897932384626433; // Pi float const windmeter_2pi = windmeter_pi * 2; struct WINDMETER { - uint32_t counter_time; - unsigned long counter = 0; + volatile uint32_t counter_time; + volatile unsigned long counter = 0; //uint32_t speed_time; float speed = 0; float last_tele_speed = 0; From 7077a80541a5ac79c0fe37fbaa8c9d0cc7ac53a5 Mon Sep 17 00:00:00 2001 From: Staars Date: Sat, 6 Jun 2020 20:04:10 +0200 Subject: [PATCH 6/6] unify USE_*_COMPRESSION to USE_UNISHOX_COMPRESSION --- tasmota/my_user_config.h | 6 ++++-- tasmota/support.ino | 4 ++-- tasmota/xdrv_10_rules.ino | 32 ++++++++++++++++---------------- tasmota/xdrv_10_scripter.ino | 22 +++++++++++----------- tasmota/xdrv_21_wemo.ino | 10 +++++----- 5 files changed, 38 insertions(+), 36 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index b6008abcf..466a8991e 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -394,12 +394,14 @@ // -- Ping ---------------------------------------- // #define USE_PING // Enable Ping command (+2k code) +#define USE_UNISHOX_COMPRESSION // add support for string compression for RULES or SCRIPT + // -- Rules or Script ---------------------------- // Select none or only one of the below defines USE_RULES or USE_SCRIPT #define USE_RULES // Add support for rules (+8k code) - #define USE_RULES_COMPRESSION // Compresses rules in Flash at about ~50% (+3.3k code) + // with USE_UNISHOX_COMPRESSION // Compresses rules in Flash at about ~50% (+3.3k code) //#define USE_SCRIPT // Add support for script (+17k code) - #define USE_SCRIPT_COMPRESSION + // supports USE_UNISHOX_COMPRESSION //#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) diff --git a/tasmota/support.ino b/tasmota/support.ino index 839e126f6..8d915cf05 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1882,7 +1882,7 @@ void AddLogBufferSize(uint32_t loglevel, uint8_t *buffer, uint32_t count, uint32 * Uncompress static PROGMEM strings \*********************************************************************************************/ -#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) +#ifdef USE_UNISHOX_COMPRESSION #include @@ -1908,4 +1908,4 @@ String Decompress(const char * compressed, size_t uncompressed_size) { return content; } -#endif // defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) \ No newline at end of file +#endif // USE_UNISHOX_COMPRESSION \ No newline at end of file diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 8dd185a29..10c4c22e8 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -210,15 +210,15 @@ char rules_vars[MAX_RULE_VARS][33] = {{ 0 }}; */ /*******************************************************************************************/ -#ifdef USE_RULES_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION // Statically allocate one String per rule String k_rules[MAX_RULE_SETS] = { String(), String(), String() }; // Strings are created empty // Unishox compressor; // singleton -#endif // USE_RULES_COMPRESSION +#endif // USE_UNISHOX_COMPRESSION // Returns whether the rule is uncompressed, which means the first byte is not NULL inline bool IsRuleUncompressed(uint32_t idx) { -#ifdef USE_RULES_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION return Settings.rules[idx][0] ? true : false; // first byte not NULL, the rule is not empty and not compressed #else return true; @@ -227,7 +227,7 @@ inline bool IsRuleUncompressed(uint32_t idx) { // Returns whether the rule is empty, which requires two consecutive NULL inline bool IsRuleEmpty(uint32_t idx) { -#ifdef USE_RULES_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION return (Settings.rules[idx][0] == 0) && (Settings.rules[idx][1] == 0) ? true : false; #else return (Settings.rules[idx][0] == 0) ? true : false; @@ -236,7 +236,7 @@ inline bool IsRuleEmpty(uint32_t idx) { // Returns the approximate (+3-0) length of the rule, not counting the trailing NULL size_t GetRuleLen(uint32_t idx) { - // no need to use #ifdef USE_RULES_COMPRESSION, the compiler will optimize since first test is always true + // no need to use #ifdef USE_UNISHOX_COMPRESSION, the compiler will optimize since first test is always true if (IsRuleUncompressed(idx)) { return strlen(Settings.rules[idx]); } else { // either empty or compressed @@ -246,7 +246,7 @@ size_t GetRuleLen(uint32_t idx) { // Returns the actual Flash storage for the Rule, including trailing NULL size_t GetRuleLenStorage(uint32_t idx) { -#ifdef USE_RULES_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION if (Settings.rules[idx][0] || !Settings.rules[idx][1]) { // if first byte is non-NULL it is uncompressed, if second byte is NULL, then it's either uncompressed or empty return 1 + strlen(Settings.rules[idx]); // uncompressed or empty } else { @@ -257,7 +257,7 @@ size_t GetRuleLenStorage(uint32_t idx) { #endif } -#ifdef USE_RULES_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION // internal function, do the actual decompression void GetRule_decompress(String &rule, const char *rule_head) { size_t buf_len = 1 + *rule_head * 8; // the first byte contains size of buffer for uncompressed rule / 8, buf_len may overshoot by 7 @@ -265,7 +265,7 @@ void GetRule_decompress(String &rule, const char *rule_head) { rule = Decompress(rule_head, buf_len); } -#endif // USE_RULES_COMPRESSION +#endif // USE_UNISHOX_COMPRESSION // // Read rule in memory, uncompress if needed @@ -275,7 +275,7 @@ String GetRule(uint32_t idx) { if (IsRuleUncompressed(idx)) { return String(Settings.rules[idx]); } else { -#ifdef USE_RULES_COMPRESSION // we still do #ifdef to make sure we don't link unnecessary code +#ifdef USE_UNISHOX_COMPRESSION // we still do #ifdef to make sure we don't link unnecessary code String rule(""); if (Settings.rules[idx][1] == 0) { return rule; } // the rule is empty @@ -295,7 +295,7 @@ String GetRule(uint32_t idx) { } } -#ifdef USE_RULES_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION // internal function, comrpess rule and store a cached version uncompressed (except if SetOption94 1) // If out == nullptr, we are in dry-run mode, so don't keep rule in cache int32_t SetRule_compress(uint32_t idx, const char *in, size_t in_len, char *out, size_t out_len) { @@ -312,7 +312,7 @@ int32_t SetRule_compress(uint32_t idx, const char *in, size_t in_len, char *out, } return len_compressed; } -#endif // USE_RULES_COMPRESSION +#endif // USE_UNISHOX_COMPRESSION // Returns: // >= 0 : the actual stored size @@ -343,7 +343,7 @@ int32_t SetRule(uint32_t idx, const char *content, bool append = false) { Settings.rules[idx][1] = 0; } -#ifdef USE_RULES_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION if (0 != len_in + offset) { // do a dry-run compression to display how much it would be compressed int32_t len_compressed, len_uncompressed; @@ -353,11 +353,11 @@ int32_t SetRule(uint32_t idx, const char *content, bool append = false) { AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: Stored uncompressed, would compress from %d to %d (-%d%%)"), len_uncompressed, len_compressed, 100 - changeUIntScale(len_compressed, 0, len_uncompressed, 0, 100)); } -#endif // USE_RULES_COMPRESSION +#endif // USE_UNISHOX_COMPRESSION return len_in + offset; } else { -#ifdef USE_RULES_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION int32_t len_compressed; // allocate temp buffer so we don't nuke the rule if it's too big to fit char *buf_out = (char*) malloc(MAX_RULE_SIZE + 8); // take some margin @@ -390,9 +390,9 @@ int32_t SetRule(uint32_t idx, const char *content, bool append = false) { free(buf_out); return len_compressed; -#else // USE_RULES_COMPRESSION +#else // USE_UNISHOX_COMPRESSION return -1; // the rule does not fit and we can't compress -#endif // USE_RULES_COMPRESSION +#endif // USE_UNISHOX_COMPRESSION } } diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 80164f992..888fa3cb8 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -73,7 +73,7 @@ uint32_t DecodeLightId(uint32_t hue_id); #ifdef USE_SCRIPT_FATFS #undef LITTLEFS_SCRIPT_SIZE #undef EEP_SCRIPT_SIZE -#undef USE_SCRIPT_COMPRESSION +#undef USE_UNISHOX_COMPRESSION #if USE_SCRIPT_FATFS==-1 #ifdef ESP32 #error "script fat file option -1 currently not supported for ESP32" @@ -88,13 +88,13 @@ uint32_t DecodeLightId(uint32_t hue_id); // lfs on esp8266 spiffs on esp32 #ifdef LITTLEFS_SCRIPT_SIZE #undef EEP_SCRIPT_SIZE -#undef USE_SCRIPT_COMPRESSION +#undef USE_UNISHOX_COMPRESSION #pragma message "script little file system option used" #endif // LITTLEFS_SCRIPT_SIZE // eeprom script #ifdef EEP_SCRIPT_SIZE -#undef USE_SCRIPT_COMPRESSION +#undef USE_UNISHOX_COMPRESSION #ifdef USE_24C256 #pragma message "script 24c256 file option used" #else @@ -104,12 +104,12 @@ uint32_t DecodeLightId(uint32_t hue_id); #endif // EEP_SCRIPT_SIZE // compression last option before default -#ifdef USE_SCRIPT_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION #pragma message "script compression option used" -#endif // USE_SCRIPT_COMPRESSION +#endif // USE_UNISHOX_COMPRESSION -#ifdef USE_SCRIPT_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION #include #define SCRIPT_COMPRESS compressor.unishox_compress @@ -117,7 +117,7 @@ uint32_t DecodeLightId(uint32_t hue_id); #ifndef UNISHOXRSIZE #define UNISHOXRSIZE 2560 #endif -#endif // USE_SCRIPT_COMPRESSION +#endif // USE_UNISHOX_COMPRESSION #if defined(LITTLEFS_SCRIPT_SIZE) || (USE_SCRIPT_FATFS==-1) @@ -4178,7 +4178,7 @@ void ScriptSaveSettings(void) { glob_script_mem.script_mem_size=0; } -#ifdef USE_SCRIPT_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION //AddLog_P2(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram)); uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), Settings.rules[0], MAX_SCRIPT_SIZE-1); if (len_compressed > 0) { @@ -4187,7 +4187,7 @@ void ScriptSaveSettings(void) { } else { AddLog_P2(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); } -#endif // USE_SCRIPT_COMPRESSION +#endif // USE_UNISHOX_COMPRESSION if (bitRead(Settings.rule_enabled, 0)) { int16_t res=Init_Scripter(); @@ -5830,7 +5830,7 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_pram=(uint8_t*)Settings.script_pram[0]; glob_script_mem.script_pram_size=PMEM_SIZE; -#ifdef USE_SCRIPT_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION int32_t len_decompressed; sprt=(char*)calloc(UNISHOXRSIZE+8,1); if (!sprt) { break; } @@ -5839,7 +5839,7 @@ bool Xdrv10(uint8_t function) len_decompressed = SCRIPT_DECOMPRESS(Settings.rules[0], strlen(Settings.rules[0]), glob_script_mem.script_ram, glob_script_mem.script_size); if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed]=0; //AddLog_P2(LOG_LEVEL_INFO, PSTR("decompressed script len %d"),len_decompressed); -#endif // USE_SCRIPT_COMPRESSION +#endif // USE_UNISHOX_COMPRESSION #ifdef USE_BUTTON_EVENT for (uint32_t cnt=0;cntSetBinaryStateBinaryStateBinaryStateinGetBinaryStateBinaryStateBinaryStateoutBinaryStatebool0levelstring0\r\n\r\n //Successfully compressed from 779 to 249 bytes (-68%) @@ -293,7 +293,7 @@ void HandleUpnpEvent(void) } } -#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) +#ifdef USE_UNISHOX_COMPRESSION snprintf_P(event, sizeof(event), Decompress(WEMO_RESPONSE_STATE_SOAP, WEMO_RESPONSE_STATE_SOAP_SIZE).c_str(), state, bitRead(power, devices_present -1), state); #else snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(power, devices_present -1), state); @@ -305,7 +305,7 @@ void HandleUpnpService(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_EVENT_SERVICE)); -#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) +#ifdef USE_UNISHOX_COMPRESSION WSSend(200, CT_PLAIN, Decompress(WEMO_EVENTSERVICE_XML, WEMO_EVENTSERVICE_XML_SIZE)); #else WSSend(200, CT_PLAIN, FPSTR(WEMO_EVENTSERVICE_XML)); @@ -316,7 +316,7 @@ void HandleUpnpMetaService(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_META_SERVICE)); -#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) +#ifdef USE_UNISHOX_COMPRESSION WSSend(200, CT_PLAIN, Decompress(WEMO_METASERVICE_XML, WEMO_METASERVICE_XML_SIZE)); #else WSSend(200, CT_PLAIN, FPSTR(WEMO_METASERVICE_XML)); @@ -327,7 +327,7 @@ void HandleUpnpSetupWemo(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP)); -#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) +#ifdef USE_UNISHOX_COMPRESSION String setup_xml = Decompress(WEMO_SETUP_XML, WEMO_SETUP_XML_SIZE); #else String setup_xml = FPSTR(WEMO_SETUP_XML);