From dc2d7cc6816011af29acbb6ce5a6cab2f2b686d3 Mon Sep 17 00:00:00 2001 From: saper-2 Date: Sun, 5 Jan 2020 01:06:30 +0100 Subject: [PATCH 001/160] Added F&F LE-01MR support --- tasmota/language/en-GB.h | 2 + tasmota/my_user_config.h | 4 +- tasmota/support_features.ino | 5 +- tasmota/tasmota_post.h | 5 + tasmota/tasmota_template.h | 9 +- tasmota/xnrg_13_fif_le01mr.ino | 290 +++++++++++++++++++++++++++++++++ 6 files changed, 311 insertions(+), 4 deletions(-) create mode 100644 tasmota/xnrg_13_fif_le01mr.ino diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index 5121a7471..7c68553a4 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 06e444658..18e48992f 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -498,7 +498,9 @@ //#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k1 code) #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) #define SOLAXX1_PV2 // Solax X1 using second PV - +//#define USE_LE01MR // Add support for F&F LE-01MR modbus energy meter + //#define LE01MR_SPEED 2400 // LE-01MR modbus baudrate (2400 default) + //#define LE01MR_ADDR 0x01 // LE-01MR modbus address (0x01 default) // -- Low level interface devices ----------------- #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code) diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index d86bf11bb..8d37d3a71 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -501,8 +501,9 @@ void GetFeatures(void) #ifdef USE_HOTPLUG feature5 |= 0x00800000; #endif - -// feature5 |= 0x01000000; +#ifdef USE_LE01MR + feature5 |= 0x01000000; +#endif // feature5 |= 0x02000000; // feature5 |= 0x04000000; // feature5 |= 0x08000000; diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index af2fe00f7..8a16ffead 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -194,6 +194,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) //#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k1 code) +//#define USE_LE01MR // Add support for F&F LE-01MR modbus energy meter #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI @@ -281,6 +282,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) + #undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #define USE_DISPLAY // Add I2C Display Support (+2k code) @@ -362,6 +364,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) + #undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter //#undef USE_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) @@ -481,6 +484,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) +#undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -592,6 +596,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) +#undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 1793902eb..0d0eab2f5 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -216,6 +216,8 @@ enum UserSelectablePins { GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface GPIO_GPS_RX, // GPS serial interface GPIO_GPS_TX, // GPS serial interface + GPIO_LE01MR_RX, // F&F LE-01MR energy meter + GPIO_LE01MR_TX, // F&F LE-01MR energy meter GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -296,7 +298,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" D_SENSOR_SLAVE_RESET "i|" D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|" - D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX + D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX "|" + D_SENSOR_LE01MR_RX "|" D_SENSOR_LE01MR_TX ; const char kSensorNamesFixed[] PROGMEM = @@ -676,6 +679,10 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SOLAXX1_TX, // Solax Inverter tx pin GPIO_SOLAXX1_RX, // Solax Inverter rx pin #endif // USE_SOLAX_X1 +#ifdef USE_LE01MR + GPIO_LE01MR_RX, // F7F LE-01MR energy meter rx pin + GPIO_LE01MR_TX, // F7F LE-01MR energy meter tx pin +#endif // IFDEF:USE_LE01MR #endif // USE_ENERGY_SENSOR // Serial diff --git a/tasmota/xnrg_13_fif_le01mr.ino b/tasmota/xnrg_13_fif_le01mr.ino new file mode 100644 index 000000000..35e975358 --- /dev/null +++ b/tasmota/xnrg_13_fif_le01mr.ino @@ -0,0 +1,290 @@ +/* + xnrg_13_fif_le01mr.ino - F&F LE-01MR energy meter with Modbus interface - support for Tasmota + + Copyright (C) 2020 Przemyslaw Wistuba + + 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 . +*/ +#ifdef USE_ENERGY_SENSOR +#ifdef USE_LE01MR +/*********************************************************************************************\ + * F&F LE-01MR - This is a single phase energy meter with rs485 modbus interface + * (and bidirectional energy counting - enabled by RS485). + * It measure: Active energy imported AE+ [kWh] , Reactive energy imported RE+ [kvarh], + * Voltage V [V], Current I [A], Frequency F [Hz], power factor (aka "cos-phi"), + * Active power P [kW], Reactive power Q [kvar], Apparent power S [kVA], + * *Active energy exported AE- [kWh] (when meter is switched to bi-directional counting then + * reactive energy imported register contains value of Active energy exported). + * + * Meter descriptions at manufacturer page (english version have some description errors): + * EN: https://www.fif.com.pl/en/usage-electric-power-meters/517-electricity-consumption-meter-le-01mr.html + * PL: https://www.fif.com.pl/pl/liczniki-zuzycia-energii-elektrycznej/517-licznik-zuzycia-energii-le-01mr.html + * + * Register descriptions (not all, only those that are being read): + * + * /----------------------------------- Register address + * | /-------------------------- Registers count + * | | /---------------------- Datatype and size + * | | | /----------------- Resolution (or multiplier) + * | | | | /---------- Unit + * | | | | | /---- Description + * 0x0130 1 U16 0.01 Hz Frequency + * 0x0131 1 U16 0.01 V Voltage + * 0x0139 2 U32 0.001 A Current + * 0x0140 2 U32 0.001 kW Active power + * 0x0148 2 U32 0.001 kvar Reactive power + * 0x0150 2 U32 0.001 kVA Apparent power + * 0x0158 1 S16 0.001 - Power factor + * 0xA000 2 U32 0.01 kWh Active energy imported + * 0xA01E 2 U32 0.01 kvarh Reactive energy imported + * + * Datatype: S = signed int, U = unsigend int, + * U32 - the first (lower) register contains high word, + * second register contains lower word of 32bit dword: + * value_32bit = (register+0)<<16 | (register+1); + * /or/ val32bit = (reg+0)*65536 + (reg+1); +\*********************************************************************************************/ + +#define XNRG_13 13 + +// can be user defined in my_user_config.h +#ifndef LE01MR_SPEED + #define LE01MR_SPEED 2400 // default LE01MR Modbus speed +#endif +// can be user defined in my_user_config.h +#ifndef LE01MR_ADDR + #define LE01MR_ADDR 1 // default LE01MR Modbus address +#endif + +#include +TasmotaModbus *FifLEModbus; + +const uint8_t le01mr_table_sz = 9; + +const uint16_t le01mr_register_addresses[] { + // IDX (reg count/datatype) [unit] + 0x0130, // 00 . LE01MR_FREQUENCY (1/U16) [Hz] + 0x0131, // 01 . LE01MR_VOLTAGE (1/U16) [V] + 0x0158, // 02 . LE01MR_POWER_FACTOR (1/S16) + 0x0139, // 03 . LE01MR_CURRENT (2/U32) [A] + 0x0140, // 04 . LE01MR_ACTIVE_POWER (2/U32) [kW] + 0x0148, // 05 . LE01MR_REACTIVE_POWER (2/U32) [kvar] + 0x0150, // 06 . LE01MR_APPARENT_POWER (2/U32) [kVA] + 0xA000, // 07 . LE01MR_TOTAL_ACTIVE_ENERGY (2/U32) [kWh] + 0xA01E // 08 . LE01MR_TOTAL_REACTIVE_ENERGY (2/U32) [kvarh] +}; + +struct LE01MR { + float total_active = 0; + float total_reactive = 0; + uint8_t read_state = 0; + uint8_t send_retry = 0; + uint8_t start_address_count = le01mr_table_sz; +} Le01mr; + +/*********************************************************************************************/ + +void FifLEEvery250ms(void) +{ + bool data_ready = FifLEModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; // At least 9 + uint8_t reg_count = 2; + if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) { + reg_count=1; + } + + uint32_t error = FifLEModbus->ReceiveBuffer(buffer, reg_count); + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, FifLEModbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus error %d"), error); + } else { + Energy.data_valid[0] = 0; + + // SA=Slave Address, FC=Function Code, BC=Byte Count, B3..B0=Data byte, Ch Cl = crc16 checksum + // U32 registers: + // 00 01 02 03 04 05 06 07 08 + // SA FC BC B3 B2 B1 B0 Cl Ch + // 01 03 04 00 00 00 72 7A 16 = REG[B3..B2=0x0139,B1..B0=0x013A] 114 = 0.114 A + // 01 03 04 00 00 00 B0 FB 87 = REG[B3..B2=0xA01E,B1..B0=0xA01F] 176 = 1.76 kvarh + // U16/S16 registers: + // 00 01 02 03 04 05 06 + // SA FC BC B1 B0 Cl Ch + // 01 03 02 5B 02 02 B5 = REG[B1..B0=0x0131] 23298 = 232.98 V + // 01 03 02 03 E8 B8 FA = REG[B1..B0=0x0158] 1000 = 1.000 (power factor) + // there are 3 data types used: + // U16 - uint16_t + // U32 - uint32_t + // S16 - int16_t + // everything drop into uint32 value, but depending on register ther will be 2 or 4 bytes + uint32_t value_buff = 0; + // for register table items 0..2 use 2 bytes (U16) + if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) { // + value_buff = ((uint32_t)buffer[3])<<8 | buffer[4]; + //((uint8_t*)&value_buff)[1] = buffer[3]; + //((uint8_t*)&value_buff)[0] = buffer[4]; + } else { + value_buff = ((uint32_t)buffer[3])<<24 | ((uint32_t)buffer[4])<<16 | ((uint32_t)buffer[5])<<8 | buffer[6]; + } + + switch(Le01mr.read_state) { + case 0: + Energy.frequency[0] = value_buff * 0.01f; // 5000 => 50.00 + break; + + case 1: + Energy.voltage[0] = value_buff * 0.01f; // 23298 => 232.98 V + break; + + case 2: + Energy.power_factor[0] = ((int16_t)value_buff) * 0.001f; // 1000 => 1.000 + break; + + case 3: + Energy.current[0] = value_buff * 0.001f; // 114 => 0.114 A + break; + + case 4: + Energy.active_power[0] = value_buff * 0.001f; + break; + + case 5: + Energy.reactive_power[0] = value_buff * 0.001f; + break; + + case 6: + Energy.apparent_power[0] = value_buff * 0.001f; + break; + + case 7: + Le01mr.total_active = value_buff * 0.01f; + break; + + case 8: + Le01mr.total_reactive = value_buff * 0.01f; // 176 => 1.76 + break; + } + + Le01mr.read_state++; + if (Le01mr.read_state == Le01mr.start_address_count) { + Le01mr.read_state = 0; + + EnergyUpdateTotal(Le01mr.total_active, true); + } + } + } // end data ready + + if (0 == Le01mr.send_retry || data_ready) { + uint8_t reg_count = 2; + + Le01mr.send_retry = 5; + // some registers are 1reg in size + if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) reg_count=1; + // send request + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus req reg %X, count %d"), le01mr_register_addresses[Le01mr.read_state], reg_count); + FifLEModbus->Send(LE01MR_ADDR, 0x03, le01mr_register_addresses[Le01mr.read_state], reg_count); + } else { + Le01mr.send_retry--; + } +} + +void FifLESnsInit(void) +{ + FifLEModbus = new TasmotaModbus(pin[GPIO_LE01MR_RX], pin[GPIO_LE01MR_RX]); + uint8_t result = FifLEModbus->Begin(LE01MR_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void FifLEDrvInit(void) +{ + if ((pin[GPIO_LE01MR_RX] < 99) && (pin[GPIO_LE01MR_RX] < 99)) { + energy_flg = XNRG_13; + } +} + +void FifLEReset(void) +{ + Le01mr.total_active = 0; +} + +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_LE01MR[] PROGMEM = + "{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}"; +#endif // USE_WEBSERVER + +void FifLEShow(bool json) +{ + char total_reactive_chr[FLOATSZ]; + dtostrfd(Le01mr.total_reactive, Settings.flag2.energy_resolution, total_reactive_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_REACTIVE "\":%s"), + total_reactive_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_ENERGY_LE01MR, total_reactive_chr); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define SLOW_DOWN_X250MS 6 +uint8_t slowdown = SLOW_DOWN_X250MS; + +bool Xnrg13(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { + if (--slowdown == 0) { + FifLEEvery250ms(); + slowdown=SLOW_DOWN_X250MS; + } + } + break; + case FUNC_JSON_APPEND: + FifLEShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + FifLEShow(0); + break; +#endif // USE_WEBSERVER + case FUNC_ENERGY_RESET: + FifLEReset(); + break; + case FUNC_INIT: + FifLESnsInit(); + break; + case FUNC_PRE_INIT: + FifLEDrvInit(); + break; + } + return result; +} + +#endif // USE_LE01MR +#endif // USE_ENERGY_SENSOR From 179a1c549d0f555e7c1c0bf8f39a3fd4b58eb191 Mon Sep 17 00:00:00 2001 From: saper-2 Date: Sun, 5 Jan 2020 14:32:35 +0100 Subject: [PATCH 002/160] Fixed few bugs (multiplers, 0's, etc) --- tasmota/xnrg_13_fif_le01mr.ino | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tasmota/xnrg_13_fif_le01mr.ino b/tasmota/xnrg_13_fif_le01mr.ino index 35e975358..f5998d95f 100644 --- a/tasmota/xnrg_13_fif_le01mr.ino +++ b/tasmota/xnrg_13_fif_le01mr.ino @@ -102,7 +102,7 @@ void FifLEEvery250ms(void) if (data_ready) { uint8_t buffer[14]; // At least 9 uint8_t reg_count = 2; - if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) { + if (Le01mr.read_state < 3) { reg_count=1; } @@ -141,6 +141,9 @@ void FifLEEvery250ms(void) value_buff = ((uint32_t)buffer[3])<<24 | ((uint32_t)buffer[4])<<16 | ((uint32_t)buffer[5])<<8 | buffer[6]; } + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR buff[3..6]: %2x %2x %2x %2x"), buffer[3], buffer[4], buffer[5], buffer[6]); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR reg_count/value_buff: %d / %d"), reg_count,value_buff); + switch(Le01mr.read_state) { case 0: Energy.frequency[0] = value_buff * 0.01f; // 5000 => 50.00 @@ -159,23 +162,23 @@ void FifLEEvery250ms(void) break; case 4: - Energy.active_power[0] = value_buff * 0.001f; + Energy.active_power[0] = value_buff * 1.0f; // P [W] break; case 5: - Energy.reactive_power[0] = value_buff * 0.001f; + Energy.reactive_power[0] = value_buff * 1.0f; // Q [var] break; case 6: - Energy.apparent_power[0] = value_buff * 0.001f; + Energy.apparent_power[0] = value_buff * 1.0f; // S [VA] break; case 7: - Le01mr.total_active = value_buff * 0.01f; + Le01mr.total_active = value_buff * 0.01f; // [kWh] break; case 8: - Le01mr.total_reactive = value_buff * 0.01f; // 176 => 1.76 + Le01mr.total_reactive = value_buff * 0.01f; // [kvarh] 176 => 1.76 break; } @@ -193,7 +196,7 @@ void FifLEEvery250ms(void) Le01mr.send_retry = 5; // some registers are 1reg in size - if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) reg_count=1; + if (Le01mr.read_state < 3) reg_count=1; // send request AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus req reg %X, count %d"), le01mr_register_addresses[Le01mr.read_state], reg_count); FifLEModbus->Send(LE01MR_ADDR, 0x03, le01mr_register_addresses[Le01mr.read_state], reg_count); @@ -204,7 +207,7 @@ void FifLEEvery250ms(void) void FifLESnsInit(void) { - FifLEModbus = new TasmotaModbus(pin[GPIO_LE01MR_RX], pin[GPIO_LE01MR_RX]); + FifLEModbus = new TasmotaModbus(pin[GPIO_LE01MR_RX], pin[GPIO_LE01MR_TX]); uint8_t result = FifLEModbus->Begin(LE01MR_SPEED); if (result) { if (2 == result) { ClaimSerial(); } @@ -249,7 +252,8 @@ void FifLEShow(bool json) * Interface \*********************************************************************************************/ -#define SLOW_DOWN_X250MS 6 +// just to slow down tramitter (for deug purpouses) +#define SLOW_DOWN_X250MS 1 uint8_t slowdown = SLOW_DOWN_X250MS; bool Xnrg13(uint8_t function) From f2ca1f3e47b9434ff84143cecb215b8a71ce0cf1 Mon Sep 17 00:00:00 2001 From: saper-2 Date: Sun, 5 Jan 2020 19:51:12 +0100 Subject: [PATCH 003/160] Added totalActive from le01, more code tunning --- tasmota/i18n.h | 1 + tasmota/language/en-GB.h | 3 ++- tasmota/my_user_config.h | 6 +++--- tasmota/xnrg_13_fif_le01mr.ino | 31 ++++++++++++++++++++----------- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index fb54edd4a..67a262b75 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -183,6 +183,7 @@ #define D_JSON_SOLAR_POWER "SolarPower" #define D_JSON_USAGE "Usage" #define D_JSON_EXPORT "Export" +#define D_JSON_TOTAL_ACTIVE "TotalActive" #define D_RSLT_ENERGY "ENERGY" #define D_RSLT_HASS_STATE "HASS_STATE" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index 7c68553a4..163a46b87 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -671,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Phase Angle" #define D_IMPORT_ACTIVE "Import Active" #define D_EXPORT_ACTIVE "Export Active" @@ -680,6 +680,7 @@ #define D_TOTAL_REACTIVE "Total Reactive" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 18e48992f..85d6737e9 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -498,9 +498,9 @@ //#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k1 code) #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) #define SOLAXX1_PV2 // Solax X1 using second PV -//#define USE_LE01MR // Add support for F&F LE-01MR modbus energy meter - //#define LE01MR_SPEED 2400 // LE-01MR modbus baudrate (2400 default) - //#define LE01MR_ADDR 0x01 // LE-01MR modbus address (0x01 default) +//#define USE_LE01MR // Add support for F&F LE-01MR modbus energy meter + #define LE01MR_SPEED 2400 // LE-01MR modbus baudrate (2400 default) + #define LE01MR_ADDR 1 // LE-01MR modbus address (0x01 default) // -- Low level interface devices ----------------- #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code) diff --git a/tasmota/xnrg_13_fif_le01mr.ino b/tasmota/xnrg_13_fif_le01mr.ino index f5998d95f..3ca424d66 100644 --- a/tasmota/xnrg_13_fif_le01mr.ino +++ b/tasmota/xnrg_13_fif_le01mr.ino @@ -198,7 +198,7 @@ void FifLEEvery250ms(void) // some registers are 1reg in size if (Le01mr.read_state < 3) reg_count=1; // send request - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus req reg %X, count %d"), le01mr_register_addresses[Le01mr.read_state], reg_count); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus req reg %X, count %d"), le01mr_register_addresses[Le01mr.read_state], reg_count); FifLEModbus->Send(LE01MR_ADDR, 0x03, le01mr_register_addresses[Le01mr.read_state], reg_count); } else { Le01mr.send_retry--; @@ -226,24 +226,30 @@ void FifLEDrvInit(void) void FifLEReset(void) { Le01mr.total_active = 0; + Le01mr.total_reactive = 0; } #ifdef USE_WEBSERVER const char HTTP_ENERGY_LE01MR[] PROGMEM = - "{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}"; + "{s}" D_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + ; #endif // USE_WEBSERVER void FifLEShow(bool json) { char total_reactive_chr[FLOATSZ]; dtostrfd(Le01mr.total_reactive, Settings.flag2.energy_resolution, total_reactive_chr); + char total_active_chr[FLOATSZ]; + dtostrfd(Le01mr.total_active, Settings.flag2.energy_resolution, total_active_chr); + if (json) { - ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_REACTIVE "\":%s"), - total_reactive_chr); + ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_ACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s"), + total_active_chr, total_reactive_chr); #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_ENERGY_LE01MR, total_reactive_chr); + WSContentSend_PD(HTTP_ENERGY_LE01MR, total_active_chr, total_reactive_chr); #endif // USE_WEBSERVER } } @@ -253,20 +259,23 @@ void FifLEShow(bool json) \*********************************************************************************************/ // just to slow down tramitter (for deug purpouses) -#define SLOW_DOWN_X250MS 1 -uint8_t slowdown = SLOW_DOWN_X250MS; +//#define SLOW_DOWN_X250MS 1 +//uint8_t slowdown = SLOW_DOWN_X250MS; bool Xnrg13(uint8_t function) { bool result = false; switch (function) { + // TODO: Verify if there is corrleaction with 250ms scan time, + // and MQTT breaking connection and causing exception in ESP8266 after few minutes + // test with "FUNC_EVERY_SECOND" case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { - if (--slowdown == 0) { + if (uptime > 4) { + //if (--slowdown == 0) { FifLEEvery250ms(); - slowdown=SLOW_DOWN_X250MS; - } + // slowdown=SLOW_DOWN_X250MS; + //} } break; case FUNC_JSON_APPEND: From f145d22e90df65b3750ba643fa26dfe68ee57635 Mon Sep 17 00:00:00 2001 From: saper-2 Date: Sun, 5 Jan 2020 22:09:00 +0100 Subject: [PATCH 004/160] A bit more of code cleanup --- tasmota/xnrg_13_fif_le01mr.ino | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/tasmota/xnrg_13_fif_le01mr.ino b/tasmota/xnrg_13_fif_le01mr.ino index 3ca424d66..342e8cf17 100644 --- a/tasmota/xnrg_13_fif_le01mr.ino +++ b/tasmota/xnrg_13_fif_le01mr.ino @@ -113,6 +113,7 @@ void FifLEEvery250ms(void) if (error) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus error %d"), error); } else { + //if (Le01mr.read_state == 0) Energy.data_valid[0] = 0; // SA=Slave Address, FC=Function Code, BC=Byte Count, B3..B0=Data byte, Ch Cl = crc16 checksum @@ -135,8 +136,6 @@ void FifLEEvery250ms(void) // for register table items 0..2 use 2 bytes (U16) if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) { // value_buff = ((uint32_t)buffer[3])<<8 | buffer[4]; - //((uint8_t*)&value_buff)[1] = buffer[3]; - //((uint8_t*)&value_buff)[0] = buffer[4]; } else { value_buff = ((uint32_t)buffer[3])<<24 | ((uint32_t)buffer[4])<<16 | ((uint32_t)buffer[5])<<8 | buffer[6]; } @@ -154,7 +153,7 @@ void FifLEEvery250ms(void) break; case 2: - Energy.power_factor[0] = ((int16_t)value_buff) * 0.001f; // 1000 => 1.000 + Energy.power_factor[0] = ((int16_t)value_buff) * 0.001f; // 1000 => 1.000 //note: I never saw this negative... break; case 3: @@ -218,7 +217,7 @@ void FifLESnsInit(void) void FifLEDrvInit(void) { - if ((pin[GPIO_LE01MR_RX] < 99) && (pin[GPIO_LE01MR_RX] < 99)) { + if ((pin[GPIO_LE01MR_RX] < 99) && (pin[GPIO_LE01MR_TX] < 99)) { energy_flg = XNRG_13; } } @@ -258,24 +257,14 @@ void FifLEShow(bool json) * Interface \*********************************************************************************************/ -// just to slow down tramitter (for deug purpouses) -//#define SLOW_DOWN_X250MS 1 -//uint8_t slowdown = SLOW_DOWN_X250MS; - bool Xnrg13(uint8_t function) { bool result = false; switch (function) { - // TODO: Verify if there is corrleaction with 250ms scan time, - // and MQTT breaking connection and causing exception in ESP8266 after few minutes - // test with "FUNC_EVERY_SECOND" case FUNC_EVERY_250_MSECOND: if (uptime > 4) { - //if (--slowdown == 0) { FifLEEvery250ms(); - // slowdown=SLOW_DOWN_X250MS; - //} } break; case FUNC_JSON_APPEND: From 1c0db7e689f7394f71dc005ae845193dc2d0d7e0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 7 Jan 2020 17:01:48 +0100 Subject: [PATCH 005/160] Refactor version compatibility --- tasmota/settings.ino | 34 +++++++++++++++++----------------- tasmota/support_tasmota.ino | 3 +-- tasmota/xdrv_01_webserver.ino | 3 +-- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 21f3e0ab4..0e32bc7bd 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -343,10 +343,10 @@ void SetFlashModeDout(void) delete[] _buffer; } -uint32_t OtaVersion(void) +bool VersionCompatible(void) { if (Settings.flag3.compatibility_check) { - return 0xFFFFFFFF; + return true; } eboot_command ebcmd; @@ -362,15 +362,15 @@ uint32_t OtaVersion(void) if ((address == start_address) && (0x1F == (buffer[0] & 0xFF))) { version[1] = 0xFFFFFFFF; // Ota file is gzipped and can not be checked for compatibility found = true; - break; - } - for (uint32_t i = 0; i < (FLASH_SECTOR_SIZE / 4); i++) { - version[0] = version[1]; - version[1] = version[2]; - version[2] = buffer[i]; - if ((version[0] == MARKER_START) && (version[2] == MARKER_END)) { - found = true; - break; + } else { + for (uint32_t i = 0; i < (FLASH_SECTOR_SIZE / 4); i++) { + version[0] = version[1]; + version[1] = version[2]; + version[2] = buffer[i]; + if ((MARKER_START == version[0]) && (MARKER_END == version[2])) { + found = true; + break; + } } } if (found) { break; } @@ -381,13 +381,13 @@ uint32_t OtaVersion(void) AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: Version 0x%08X, Compatible 0x%08X"), version[1], VERSION_COMPATIBLE); - return version[1]; -} + if (version[1] < VERSION_COMPATIBLE) { + uint32_t eboot_magic = 0; // Abandon OTA result + ESP.rtcUserMemoryWrite(0, (uint32_t*)&eboot_magic, sizeof(eboot_magic)); + return false; + } -void AbandonOta(void) -{ - uint32_t eboot_magic = 0; - ESP.rtcUserMemoryWrite(0, (uint32_t*)&eboot_magic, sizeof(eboot_magic)); + return true; } void SettingsBufferFree(void) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index b20e5ef26..4b0aa48bd 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -869,8 +869,7 @@ void Every250mSeconds(void) Response_P(PSTR("{\"" D_CMND_UPGRADE "\":\"")); if (ota_result) { // SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 - if (OtaVersion() < VERSION_COMPATIBLE) { - AbandonOta(); + if (!VersionCompatible()) { ResponseAppend_P(PSTR(D_JSON_FAILED " " D_UPLOAD_ERR_14)); } else { ResponseAppend_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 682663905..b6a45340a 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2398,8 +2398,7 @@ void HandleUploadLoop(void) Web.upload_error = 6; // Upload failed. Enable logging 3 return; } - if (OtaVersion() < VERSION_COMPATIBLE) { - AbandonOta(); + if (!VersionCompatible()) { Web.upload_error = 14; // Not compatible return; } From ca7776573ab0c18f04ad6aa8891de05683688aa7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 7 Jan 2020 17:10:07 +0100 Subject: [PATCH 006/160] Remove debug info --- tasmota/xsns_56_hpma.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/tasmota/xsns_56_hpma.ino b/tasmota/xsns_56_hpma.ino index c9d50f28f..c66b3c7fd 100644 --- a/tasmota/xsns_56_hpma.ino +++ b/tasmota/xsns_56_hpma.ino @@ -64,7 +64,6 @@ void HpmaSecond(void) // Every second void HpmaInit(void) { hpma_type = 0; - Serial.println("SDS init"); if (pin[GPIO_HPMA_RX] < 99 && pin[GPIO_HPMA_TX] < 99) { HpmaSerial = new TasmotaSerial(pin[GPIO_HPMA_RX], pin[GPIO_HPMA_TX], 1); hpma115S0 = new HPMA115S0(*HpmaSerial); From 8db49a0fe36b8a88bf0f63811c84084dc499d52e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 7 Jan 2020 17:28:06 +0100 Subject: [PATCH 007/160] Add support for tasmota-minimal.bin.gz --- tasmota/support_tasmota.ino | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 4b0aa48bd..a4ce37d36 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -833,13 +833,15 @@ void Every250mSeconds(void) strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); #ifndef FIRMWARE_MINIMAL if (RtcSettings.ota_loader) { - char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it + char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it char *pch = strrchr((bch != nullptr) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin - char *ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin +// char *ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin + char *ech = strchr((bch != nullptr) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin or filename.bin.gz into filename-minimal.bin.gz if (!pch) { pch = ech; } if (pch) { mqtt_data[pch - mqtt_data] = '\0'; - char *ech = strrchr(SettingsText(SET_OTAURL), '.'); // Change from filename.bin into filename-minimal.bin +// char *ech = strrchr(SettingsText(SET_OTAURL), '.'); // Change from filename.bin into filename-minimal.bin + char *ech = strchr(SettingsText(SET_OTAURL), '.'); // Change from filename.bin into filename-minimal.bin snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ech); // Minimal filename must be filename-minimal } } From d2f14c6b83676dbf6c850e53f3d0afb842fa7d4a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 7 Jan 2020 20:59:35 +0100 Subject: [PATCH 008/160] add tasmota*.bin.gz to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e9c55b5b9..ef1e0a508 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ build firmware.map firmware.asm tasmota*.bin +tasmota*.bin.gz tasmota*.map platformio_override.ini From 63b6cee1a19a53f9817fe1351672a81d6aa4f152 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Tue, 7 Jan 2020 22:32:48 +0100 Subject: [PATCH 009/160] Make gzip Python2.7 compatible --- pio/gzip-firmware.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/pio/gzip-firmware.py b/pio/gzip-firmware.py index 1061f1010..e8fae2c92 100644 --- a/pio/gzip-firmware.py +++ b/pio/gzip-firmware.py @@ -13,17 +13,11 @@ def bin_gzip(source, target, env): gzip_file = "{}firmware{}{}.bin.gz".format(OUTPUT_DIR, os.path.sep, variant) # check if new target files exist and remove if necessary - for f in [gzip_file]: - if os.path.isfile(f): - os.remove(f) + if os.path.isfile(gzip_file): os.remove(gzip_file) # write gzip firmware file - fp = open(bin_file,"rb") - data = fp.read() - bindata = bytearray(data) - with gzip.open(gzip_file, "wb") as f: - f.write(bindata) - fp.close() - f.close() + with open(bin_file,"rb") as fp: + with gzip.open(gzip_file, "wb") as f: + shutil.copyfileobj(fp, f) env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [bin_gzip]) From 7c43fca8e33a4a2bcfa1b8173a00941d62b898ee Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 8 Jan 2020 11:08:30 +0100 Subject: [PATCH 010/160] Use Python 3.7.6 with Gitpod --- .gitpod.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitpod.yml b/.gitpod.yml index ee7750c54..8ac16a8ad 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,3 +1,3 @@ tasks: - - before: pip install -U platformio + - before: pip3 install -U platformio command: platformio run -e tasmota From 2c23364d486698600a3cc20d7176203501e77198 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 8 Jan 2020 11:43:39 +0100 Subject: [PATCH 011/160] Fix DDS238-2 total energy Fix DDS238-2 total energy (#7457) --- tasmota/xnrg_09_dds2382.ino | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tasmota/xnrg_09_dds2382.ino b/tasmota/xnrg_09_dds2382.ino index b211fa698..aea1f03ea 100644 --- a/tasmota/xnrg_09_dds2382.ino +++ b/tasmota/xnrg_09_dds2382.ino @@ -56,9 +56,14 @@ void Dds2382EverySecond(void) // 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 = ModBus register // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 = Buffer index + // 01 03 24 00 00 1C 7B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 F3 00 00 17 88 09 77 01 A6 03 F8 00 70 03 E1 13 8A 63 ED + // 01 03 24 00 00 1C AD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 F3 00 00 17 BA 09 77 01 F1 04 AF 00 6C 03 E3 13 86 41 A2 // SA FC BC EnergyTotal ExportActiv ImportActiv Volta Curre APowe RPowe PFact Frequ Crc-- = DDS238-2 ZN/S version 1 (#6384) // SA FC BC EnergyTotal ExportActiv ImportActiv Volta Curre APowe RPowe PFact Frequ Crc-- = DDS238-2 ZN/S version 2 (#6531) + // {"TotalStartTime":"2020-01-08T09:43:05","Total":0.060,"Yesterday":0.001,"Today":0.001,"ExportActive":12.670,"Period":0,"Power":1016,"ApparentPower":1020,"ReactivePower":112,"Factor":0.99,"Frequency":50,"Voltage":242,"Current":4.210}} + // {"TotalStartTime":"2020-01-08T00:00:00","Total":0.061,"Yesterday":0.001,"Today":0.001,"ExportActive":12.670,"Period":0.020,"Power":1199.000,"ApparentPower":1204.231,"ReactivePower":108.000,"Factor":1.00,"Frequency":49.98,"Voltage":242.3,"Current":4.970}} + Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0; Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0; Energy.active_power[0] = (float)((buffer[31] << 8) + buffer[32]); @@ -69,10 +74,10 @@ void Dds2382EverySecond(void) if (Settings.flag3.dds2382_model) { // SetOption71 - Select different Modbus registers for Active Energy (#6531) offset = 19; } - Energy.export_active = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; // 429496729.0 W - float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; // 429496729.0 W + Energy.export_active = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; // 429496.729 kW + float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; // 429496.729 kW - EnergyUpdateTotal(import_active, false); // 484.708 kWh + EnergyUpdateTotal(import_active, true); // 484.708 kWh } } // end data ready From edf15844310f77d0d1311f94cfb6ef44b9f39de3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 8 Jan 2020 16:45:43 +0100 Subject: [PATCH 012/160] Improve random color cycle for scheme 4 Improve random color cycle for scheme 4 (#7273) --- tasmota/xdrv_04_light.ino | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 3eacfbcaa..df65b1591 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1612,13 +1612,19 @@ void LightCycleColor(int8_t direction) if (0 == direction) { if (Light.random == Light.wheel) { Light.random = random(255); + + uint8_t my_dir = ((Light.random < Light.wheel -128) || (Light.random > Light.wheel +128)) ? 1 : 0; + Light.random |= my_dir; + +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: random %d"), Light.random); } - direction = (Light.random < Light.wheel) ? -1 : 1; +// direction = (Light.random < Light.wheel) ? -1 : 1; + direction = (Light.random &1) ? -1 : 1; } Light.wheel += direction; uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); // Scale to hue to keep amount of steps low (max 255 instead of 359) -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: random %d, wheel %d, hue %d"), Light.random, Light.wheel, hue); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: random %d, wheel %d, hue %d"), Light.random, Light.wheel, hue); uint8_t sat; light_state.getHSB(nullptr, &sat, nullptr); // Allow user control over Saturation @@ -1964,9 +1970,9 @@ void LightSetOutputs(const uint16_t *cur_col_10) { } } } - char msg[24]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Channels %s"), - ToHex_P((const unsigned char *)cur_col_10, 10, msg, sizeof(msg))); + +// char msg[24]; +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Channels %s"), ToHex_P((const unsigned char *)cur_col_10, 10, msg, sizeof(msg))); uint8_t cur_col[LST_MAX]; for (uint32_t i = 0; i < LST_MAX; i++) { From 7c68d7a754a06f56c7178e41cb4b4fae9756bbc1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 8 Jan 2020 17:45:48 +0100 Subject: [PATCH 013/160] Improve random color cycle for scheme 4 Improve random color cycle for scheme 4 (#7273) --- tasmota/xdrv_04_light.ino | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index df65b1591..5cbcecdfa 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1613,13 +1613,15 @@ void LightCycleColor(int8_t direction) if (Light.random == Light.wheel) { Light.random = random(255); - uint8_t my_dir = ((Light.random < Light.wheel -128) || (Light.random > Light.wheel +128)) ? 1 : 0; - Light.random |= my_dir; + uint8_t my_dir = (Light.random < Light.wheel -128) ? 1 : + (Light.random < Light.wheel ) ? 0 : + (Light.random > Light.wheel +128) ? 0 : 1; // Increment or Decrement and roll-over + Light.random = (Light.random & 0xFE) | my_dir; // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: random %d"), Light.random); } // direction = (Light.random < Light.wheel) ? -1 : 1; - direction = (Light.random &1) ? -1 : 1; + direction = (Light.random &0x01) ? 1 : -1; } Light.wheel += direction; uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); // Scale to hue to keep amount of steps low (max 255 instead of 359) From 2c6659fca4e57f96fdc3a266e853c78ff9ca5032 Mon Sep 17 00:00:00 2001 From: to-scho Date: Thu, 9 Jan 2020 09:17:39 +0100 Subject: [PATCH 014/160] Fix labeling of web buttons for shutters Instead of switching power of the shutter relais web buttons will issue shutter commands to work right when in shuttermode 1. Up down labels arrow up/down fixed for more than one shutter. --- tasmota/i18n.h | 2 ++ tasmota/xdrv_01_webserver.ino | 49 ++++++++++++++++++++++++----------- tasmota/xdrv_27_shutter.ino | 6 ++--- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index fb54edd4a..e8432bc48 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -502,6 +502,8 @@ #define D_CMND_SHUTTER_CLOSE "Close" #define D_CMND_SHUTTER_UP "Up" #define D_CMND_SHUTTER_DOWN "Down" +#define D_CMND_SHUTTER_TOGGLEUP "ToggleUp" +#define D_CMND_SHUTTER_TOGGLEDOWN "ToggleDown" #define D_CMND_SHUTTER_STOP "Stop" #define D_CMND_SHUTTER_POSITION "Position" #define D_CMND_SHUTTER_OPENTIME "OpenDuration" diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index b6a45340a..00adbd73e 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1120,20 +1120,12 @@ void HandleRoot(void) for (uint32_t idx = 1; idx <= devices_present; idx++) { bool set_button = ((idx <= MAX_BUTTON_TEXT) && strlen(SettingsText(SET_BUTTON1 + idx -1))); #ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support - bool shutter_used = false; - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - if (Settings.shutter_startrelay[i] == (((idx -1) & 0xFFFFFFFE) +1)) { - shutter_used = true; - break; - } - } - if (shutter_used) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (idx % 2) ? "▲" : "▼", - ""); - continue; - } + int32_t ShutterWebButton; + if (ShutterWebButton = IsShutterWebButton(idx)) { + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (ShutterWebButton>0) ? "▲" : "▼", + ""); + continue; } #endif // USE_SHUTTER snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); @@ -1216,7 +1208,18 @@ bool HandleRootStatusRefresh(void) } } else { #endif // USE_SONOFF_IFAN - ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); +#ifdef USE_SHUTTER + int32_t ShutterWebButton; + if (ShutterWebButton = IsShutterWebButton(device)) { + snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), abs(ShutterWebButton), (ShutterWebButton>0) ? PSTR(D_CMND_SHUTTER_TOGGLEUP) : PSTR(D_CMND_SHUTTER_TOGGLEDOWN)); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: WebButton %d, %s"), ShutterWebButton, svalue); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } else { +#endif // USE_SHUTTER + ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); +#ifdef USE_SHUTTER + } +#endif // USE_SHUTTER #ifdef USE_SONOFF_IFAN } #endif // USE_SONOFF_IFAN @@ -1301,6 +1304,22 @@ bool HandleRootStatusRefresh(void) return true; } +#ifdef USE_SHUTTER +int32_t IsShutterWebButton(uint32_t idx) { + /* 0: Not a shutter, 1..4: shutter up idx, -1..-4: shutter down idx */ + int32_t ShutterWebButton = 0; + if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + if (Settings.shutter_startrelay[i] && ((Settings.shutter_startrelay[i] == idx) || (Settings.shutter_startrelay[i] == (idx-1)))) { + ShutterWebButton = (Settings.shutter_startrelay[i] == idx) ? (i+1): (-1-i); + break; + } + } + } + return ShutterWebButton; +} +#endif // USE_SHUTTER + /*-------------------------------------------------------------------------------------------*/ #ifndef FIRMWARE_MINIMAL diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index ec272487b..b849df526 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -667,15 +667,15 @@ void CmndShutterPosition(void) // value 0 with data_len > 0 can mean Open if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { //UpperCase(XdrvMailbox.data, XdrvMailbox.data); - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN)) { + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP))) { CmndShutterOpen(); return; } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE)) { + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN))) { CmndShutterClose(); return; } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP)) { + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter.direction[index]) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN)))) { XdrvMailbox.payload = -99; CmndShutterStop(); return; From 3675388148ad5bbf68dac9d46db2c7895c075611 Mon Sep 17 00:00:00 2001 From: to-scho Date: Thu, 9 Jan 2020 10:35:27 +0100 Subject: [PATCH 015/160] Add MQTT field to short shutterButton command syntax Align code to latest command doc suggestion --- tasmota/xdrv_27_shutter.ino | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index ec272487b..87bcd3dd1 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -809,7 +809,7 @@ void CmndShutterButton(void) // (setting>> 0)&(0x03) : shutter_index if (XdrvMailbox.data_len > 0) { uint32_t i = 0, button_index = 0; - bool done = false; + bool done = false, isShortCommand = false; char *str_ptr; char* version_dup = strdup(XdrvMailbox.data); // Duplicate the version_str as strtok_r will modify it. // Loop through the version string, splitting on ' ' seperators. @@ -830,19 +830,26 @@ void CmndShutterButton(void) break; case 1: if (!strcmp_P(str, PSTR("up"))) { - setting |= (((100>>1)+1)<<2) | (((50>>1)+1)<<8) | (((75>>1)+1)<<14) | (((100>>1)+1)<<20) | (0x18<<26); - done = true; + setting |= (((100>>1)+1)<<2) | (((50>>1)+1)<<8) | (((75>>1)+1)<<14) | (((100>>1)+1)<<20); + isShortCommand = true; break; } else if (!strcmp_P(str, PSTR("down"))) { - setting |= (((0>>1)+1)<<2) | (((50>>1)+1)<<8) | (((25>>1)+1)<<14) | (((0>>1)+1)<<20) | (0x18<<26); - done = true; + setting |= (((0>>1)+1)<<2) | (((50>>1)+1)<<8) | (((25>>1)+1)<<14) | (((0>>1)+1)<<20); + isShortCommand = true; break; } else if (!strcmp_P(str, PSTR("updown"))) { setting |= (((100>>1)+1)<<2) | (((0>>1)+1)<<8) | (((50>>1)+1)<<14); - done = true; + isShortCommand = true; break; } case 2: + if (isShortCommand) { + if ((field==1) && (setting & (0x3F<<(2+6*3)))) + // if short command up or down then also enable MQTT broadcast + setting |= (0x3<<29); + done = true; + break; + } case 3: case 4: if ((field >= -1) && (field<=100)) From a6dcf467717eef659667f4a4ac15e208a68fcfd1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 9 Jan 2020 11:35:01 +0100 Subject: [PATCH 016/160] Move heap to stack --- tasmota/my_user_config.h | 2 +- tasmota/support.ino | 8 ++--- tasmota/xdrv_27_shutter.ino | 66 ++++++++++++++++++++----------------- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 06e444658..e9e8f390c 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -345,7 +345,7 @@ #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) #define USE_BUZZER // Add support for a buzzer (+0k6 code) #define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) -//#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+6k code) +//#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+11k code) #define USE_DEEPSLEEP // Add support for deepsleep (+1k code) //#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) // #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) diff --git a/tasmota/support.ino b/tasmota/support.ino index 9e23c1423..6ae6898e4 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -499,17 +499,14 @@ bool NewerVersion(char* version_str) uint32_t version = 0; uint32_t i = 0; char *str_ptr; - char* version_dup = strdup(version_str); // Duplicate the version_str as strtok_r will modify it. - if (!version_dup) { - return false; // Bail if we can't duplicate. Assume bad. - } + char version_dup[strlen(version_str) +1]; + strncpy(version_dup, version_str, sizeof(version_dup)); // Duplicate the version_str as strtok_r will modify it. // Loop through the version string, splitting on '.' seperators. for (char *str = strtok_r(version_dup, ".", &str_ptr); str && i < sizeof(VERSION); str = strtok_r(nullptr, ".", &str_ptr), i++) { int field = atoi(str); // The fields in a version string can only range from 0-255. if ((field < 0) || (field > 255)) { - free(version_dup); return false; } // Shuffle the accumulated bytes across, and add the new byte. @@ -521,7 +518,6 @@ bool NewerVersion(char* version_str) i++; } } - free(version_dup); // We no longer need this. // A version string should have 2-4 fields. e.g. 1.2, 1.2.3, or 1.2.3a (= 1.2.3.1). // If not, then don't consider it a valid version string. if ((i < 2) || (i > sizeof(VERSION))) { diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index e4fdc1479..057e159fb 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -808,18 +808,22 @@ void CmndShutterButton(void) // (setting>> 2)&(0x3f) : shutter_position single press 0 disabled, 1..101 == 0..100% // (setting>> 0)&(0x03) : shutter_index if (XdrvMailbox.data_len > 0) { - uint32_t i = 0, button_index = 0; - bool done = false, isShortCommand = false; + uint32_t i = 0; + uint32_t button_index = 0; + bool done = false; + bool isShortCommand = false; char *str_ptr; - char* version_dup = strdup(XdrvMailbox.data); // Duplicate the version_str as strtok_r will modify it. - // Loop through the version string, splitting on ' ' seperators. - for (char *str = strtok_r(version_dup, " ", &str_ptr); str && i < (1+4+4+1); str = strtok_r(nullptr, " ", &str_ptr), i++) { - int field; - if (str[0] == '-') - field = -1; - else - field = atoi(str); + char data_copy[strlen(XdrvMailbox.data) +1]; + strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); // Duplicate data as strtok_r will modify it. + // Loop through the data string, splitting on ' ' seperators. + for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < (1+4+4+1); str = strtok_r(nullptr, " ", &str_ptr), i++) { + int field; + if (str[0] == '-') { + field = -1; + } else { + field = atoi(str); + } switch (i) { case 0: if ((field >= -1) && (field<=4)) { @@ -866,7 +870,6 @@ void CmndShutterButton(void) } if (done) break; } - free(version_dup); if (button_index) { if (button_index==-1) { @@ -957,30 +960,31 @@ void CmndShutterInvert(void) } } -void CmndShutterCalibration(void) // ???? +void CmndShutterCalibration(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if (XdrvMailbox.data_len > 0) { - uint32_t i = 0; - char *str_ptr; - char* version_dup = strdup(XdrvMailbox.data); // Duplicate the version_str as strtok_r will modify it. - // Loop through the version string, splitting on '.' seperators. - for (char *str = strtok_r(version_dup, " ", &str_ptr); str && i < 5; str = strtok_r(nullptr, " ", &str_ptr), i++) { - int field = atoi(str); - // The fields in a version string can only range from 1-30000. - // and following value must be higher than previous one - if ((field <= 0) || (field > 30000) || ( (i>0) && (field <= messwerte[i-1]) ) ) { - break; - } - messwerte[i] = field; + uint32_t i = 0; + char *str_ptr; + + char data_copy[strlen(XdrvMailbox.data) +1]; + strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); // Duplicate data as strtok_r will modify it. + // Loop through the data string, splitting on ' ' seperators. + for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < 5; str = strtok_r(nullptr, " ", &str_ptr), i++) { + int field = atoi(str); + // The fields in a data string can only range from 1-30000. + // and following value must be higher than previous one + if ((field <= 0) || (field > 30000) || ( (i>0) && (field <= messwerte[i-1]) ) ) { + break; } - free(version_dup); - for (i=0 ; i < 5 ; i++) { - Settings.shuttercoeff[i][XdrvMailbox.index -1] = (uint32_t)messwerte[i] * 1000 / messwerte[4]; - AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); - } - ShutterInit(); - ResponseCmndIdxChar(XdrvMailbox.data); + messwerte[i] = field; + } + for (i = 0; i < 5; i++) { + Settings.shuttercoeff[i][XdrvMailbox.index -1] = (uint32_t)messwerte[i] * 1000 / messwerte[4]; + AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); + } + ShutterInit(); + ResponseCmndIdxChar(XdrvMailbox.data); } else { char setting_chr[30] = "0"; snprintf_P(setting_chr, sizeof(setting_chr), PSTR("%d %d %d %d %d"), Settings.shuttercoeff[0][XdrvMailbox.index -1], Settings.shuttercoeff[1][XdrvMailbox.index -1], Settings.shuttercoeff[2][XdrvMailbox.index -1], Settings.shuttercoeff[3][XdrvMailbox.index -1], Settings.shuttercoeff[4][XdrvMailbox.index -1]); From d0774995ded142f1400a8e26a2959082ec5aee30 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 9 Jan 2020 14:19:19 +0100 Subject: [PATCH 017/160] Allow duplicate names but different channel in wifi scan Allow duplicate names but different channel in wifi scan --- tasmota/xdrv_01_webserver.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 00adbd73e..73127a06f 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1675,8 +1675,9 @@ void HandleWifiConfiguration(void) for (uint32_t i = 0; i < n; i++) { if (-1 == indices[i]) { continue; } cssid = WiFi.SSID(indices[i]); + uint32_t cschn = WiFi.channel(indices[i]); for (uint32_t j = i + 1; j < n; j++) { - if (cssid == WiFi.SSID(indices[j])) { + if ((cssid == WiFi.SSID(indices[j])) && (cschn == WiFi.channel(indices[j]))) { DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); indices[j] = -1; // set dup aps to index -1 } From 250e3f3dc4ea90aa3bb803817194609a762916df Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 9 Jan 2020 14:35:03 +0100 Subject: [PATCH 018/160] Fix display of wifi scan signal strength Fix display of wifi scan signal strength --- tasmota/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 73127a06f..eff136c7d 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1696,7 +1696,7 @@ void HandleWifiConfiguration(void) HtmlEscape(WiFi.SSID(indices[i])).c_str(), WiFi.channel(indices[i]), GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), - quality, WiFi.RSSI() + quality, WiFi.RSSI(indices[i]) ); delay(0); From a1ccd0131d58240963a19ad8726afd53f9054d1e Mon Sep 17 00:00:00 2001 From: to-scho Date: Thu, 9 Jan 2020 14:48:23 +0100 Subject: [PATCH 019/160] Enable WIFI setup, restart and reset via ShutterButtons When no button restriction is given and ALL shutter buttons are pressed simultaneously more than 5 times or hold simultaneously follow Tasmota's basic button behavior. --- tasmota/xdrv_27_shutter.ino | 61 ++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index e4fdc1479..133e5e5ca 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -34,7 +34,7 @@ uint16_t messwerte[5] = {30,50,70,90,100}; uint16_t last_execute_step; enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE, SHT_OFF_ON__OPEN_CLOSE_STEPPER,}; -enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE,}; +enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" @@ -497,6 +497,16 @@ void ShutterRelayChanged(void) } } +bool ShutterButtonIsSimultaneousHold(uint32_t button_index) { + // check for simultaneous shutter button hold + uint32 min_shutterbutton_hold_timer = -1; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if ((Settings.shutter_button[i] & (1<<31)) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) + min_shutterbutton_hold_timer = Button.hold_timer[i]; + } + return (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1)); +} + void ShutterButtonHandler(void) { uint8_t buttonState = SHT_NOT_PRESSED; @@ -534,11 +544,31 @@ void ShutterButtonHandler(void) Button.press_counter[button_index] = 0; // Discard button press to disable functionality } } - if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold + if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10)) { // press still valid && SetOption32 (40) - Button hold + if (!Settings.flag.button_restrict) { // no SetOption1 (0) + // check for simultaneous shutter button hold + if (ShutterButtonIsSimultaneousHold(button_index)) { + // simultaneous shutter button hold detected + for (uint32_t i = 0; i < MAX_KEYS; i++) + if (Settings.shutter_button[i] & (1<<31)) + Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings + } + } if (Button.press_counter[button_index]<99) buttonState = SHT_PRESSED_HOLD; Button.press_counter[button_index] = 0; } + if ((!Settings.flag.button_restrict) && (Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { // no SetOption1 (0) && SetOption32 (40) - Button held for factor times longer + // check for simultaneous shutter button extend hold + if (ShutterButtonIsSimultaneousHold(button_index)) { + // simultaneous shutter button extend hold detected + char scmnd[20]; + buttonState = SHT_PRESSED_EXT_HOLD_SIMULTANEOUS; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } } } @@ -548,15 +578,38 @@ void ShutterButtonHandler(void) } else { if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0)) { if (Button.press_counter[button_index]<99) { + if ((!Settings.flag.button_restrict) && (Button.press_counter[button_index]>=5)) { // no SetOption1 (0) && 5x or more presses + // check for simultaneous shutter button press >3 + uint32 min_shutterbutton_press_counter = -1; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if ((Settings.shutter_button[i] & (1<<31)) && (Button.press_counter[i] < min_shutterbutton_press_counter)) + min_shutterbutton_press_counter = Button.press_counter[i]; + } + if (min_shutterbutton_press_counter >= Button.press_counter[button_index]-2) { + char scmnd[20]; + // simultaneous shutter button press >3 detected + press_index = Button.press_counter[button_index]; + for (uint32_t i = 0; i < MAX_KEYS; i++) + if (Settings.shutter_button[i] & (1<<31)) + Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings + buttonState = SHT_SHT_PRESSED_MULTI_SIMULTANEOUS; + GetTextIndexed(scmnd, sizeof(scmnd), press_index -3, kCommands); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } press_index = Button.press_counter[button_index]; - buttonState = SHT_PRESSED_MULTI; + if ((buttonState == SHT_NOT_PRESSED) && (Button.press_counter[button_index]<99)) { + // no simultaneous shutter button press >3 detected + buttonState = SHT_PRESSED_MULTI; + } } Button.press_counter[button_index] = 0; } } } - if (buttonState != SHT_NOT_PRESSED) { + if ((buttonState != SHT_NOT_PRESSED) && (buttonState != SHT_SHT_PRESSED_MULTI_SIMULTANEOUS) && (buttonState != SHT_PRESSED_EXT_HOLD_SIMULTANEOUS)) { if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { if (press_index>3) press_index=3; press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); From be85d3a0602ac15967a7775e899cf8636cdf9029 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Fri, 10 Jan 2020 20:54:13 +0100 Subject: [PATCH 020/160] Fix ``WakeUp `` ignores provided value (#7473) --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_04_light.ino | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index db1e951e9..e260285e8 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Add support for gzipped binaries - Update IRremoteESP8266 lib updated to v2.7.2 +- Fix ``WakeUp `` ignores provided value (#7473) ### 8.1.0.2 20191230 diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 5cbcecdfa..9526f8c82 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2325,7 +2325,7 @@ void CmndScheme(void) void CmndWakeup(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Settings.light_dimmer = XdrvMailbox.payload; + light_controller.changeDimmer(XdrvMailbox.payload); } Light.wakeup_active = 3; Settings.light_scheme = LS_WAKEUP; From 20c58f5f203cf113d16ab1752ccb9406ffe7c86e Mon Sep 17 00:00:00 2001 From: Roman Lomonosov Date: Sat, 11 Jan 2020 10:15:30 +0300 Subject: [PATCH 021/160] Fix typo in gauge metric type (#7216) --- tasmota/xsns_91_prometheus.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xsns_91_prometheus.ino b/tasmota/xsns_91_prometheus.ino index ff18f4e70..ea4c0047a 100644 --- a/tasmota/xsns_91_prometheus.ino +++ b/tasmota/xsns_91_prometheus.ino @@ -56,7 +56,7 @@ void HandleMetrics(void) dtostrfd(Energy.current[0], Settings.flag2.current_resolution, parameter); WSContentSend_P(PSTR("# TYPE current gauge\ncurrent %s\n"), parameter); dtostrfd(Energy.active_power[0], Settings.flag2.wattage_resolution, parameter); - WSContentSend_P(PSTR("# TYPE active_power guage\nactive_power %s\n"), parameter); + WSContentSend_P(PSTR("# TYPE active_power gauge\nactive_power %s\n"), parameter); dtostrfd(Energy.daily, Settings.flag2.energy_resolution, parameter); WSContentSend_P(PSTR("# TYPE energy_daily gauge\nenergy_daily %s\n"), parameter); dtostrfd(Energy.total, Settings.flag2.energy_resolution, parameter); From e7b061ce5a688d48aba3d1736d48973d4dadd5e8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 11 Jan 2020 15:39:56 +0100 Subject: [PATCH 022/160] Fix Tuya PowerOn state Fix Tuya PowerOn state (#7412) --- tasmota/support_tasmota.ino | 54 +++++++++++++++++++++++++++++++++++++ tasmota/tasmota.ino | 49 +-------------------------------- tasmota/xdrv_16_tuyamcu.ino | 2 +- 3 files changed, 56 insertions(+), 49 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index a4ce37d36..d502e64c3 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -276,6 +276,60 @@ void SetAllPower(uint32_t state, uint32_t source) } } +void SetPowerOnState(void) +{ + if (MOTOR == my_module_type) { + Settings.poweronstate = POWER_ALL_ON; // Needs always on else in limbo! + } + if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { + SetDevicePower(1, SRC_RESTART); + } else { + if ((ResetReason() == REASON_DEFAULT_RST) || (ResetReason() == REASON_EXT_SYS_RST)) { + switch (Settings.poweronstate) { + case POWER_ALL_OFF: + case POWER_ALL_OFF_PULSETIME_ON: + power = 0; + SetDevicePower(power, SRC_RESTART); + break; + case POWER_ALL_ON: // All on + power = (1 << devices_present) -1; + SetDevicePower(power, SRC_RESTART); + break; + case POWER_ALL_SAVED_TOGGLE: + power = (Settings.power & ((1 << devices_present) -1)) ^ POWER_MASK; + if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart + SetDevicePower(power, SRC_RESTART); + } + break; + case POWER_ALL_SAVED: + power = Settings.power & ((1 << devices_present) -1); + if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart + SetDevicePower(power, SRC_RESTART); + } + break; + } + } else { + power = Settings.power & ((1 << devices_present) -1); + if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart + SetDevicePower(power, SRC_RESTART); + } + } + } + + // Issue #526 and #909 + for (uint32_t i = 0; i < devices_present; i++) { + if (!Settings.flag3.no_power_feedback) { // SetOption63 - Don't scan relay power state at restart - #5594 and #5663 + if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { + bitWrite(power, i, digitalRead(pin[GPIO_REL1 +i]) ^ bitRead(rel_inverted, i)); + } + } + if ((i < MAX_PULSETIMERS) && (bitRead(power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate))) { + SetPulseTimer(i, Settings.pulse_timer[i]); + } + } + blink_powersave = power; +} + void SetLedPowerIdx(uint32_t led, uint32_t state) { if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index fe90b1a33..97f2ff797 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -276,54 +276,7 @@ void setup(void) WifiConnect(); - if (MOTOR == my_module_type) { Settings.poweronstate = POWER_ALL_ON; } // Needs always on else in limbo! - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - SetDevicePower(1, SRC_RESTART); - } else { - if ((ResetReason() == REASON_DEFAULT_RST) || (ResetReason() == REASON_EXT_SYS_RST)) { - switch (Settings.poweronstate) { - case POWER_ALL_OFF: - case POWER_ALL_OFF_PULSETIME_ON: - power = 0; - SetDevicePower(power, SRC_RESTART); - break; - case POWER_ALL_ON: // All on - power = (1 << devices_present) -1; - SetDevicePower(power, SRC_RESTART); - break; - case POWER_ALL_SAVED_TOGGLE: - power = (Settings.power & ((1 << devices_present) -1)) ^ POWER_MASK; - if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart - SetDevicePower(power, SRC_RESTART); - } - break; - case POWER_ALL_SAVED: - power = Settings.power & ((1 << devices_present) -1); - if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart - SetDevicePower(power, SRC_RESTART); - } - break; - } - } else { - power = Settings.power & ((1 << devices_present) -1); - if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart - SetDevicePower(power, SRC_RESTART); - } - } - } - - // Issue #526 and #909 - for (uint32_t i = 0; i < devices_present; i++) { - if (!Settings.flag3.no_power_feedback) { // SetOption63 - Don't scan relay power state at restart - #5594 and #5663 - if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { - bitWrite(power, i, digitalRead(pin[GPIO_REL1 +i]) ^ bitRead(rel_inverted, i)); - } - } - if ((i < MAX_PULSETIMERS) && (bitRead(power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate))) { - SetPulseTimer(i, Settings.pulse_timer[i]); - } - } - blink_powersave = power; + SetPowerOnState(); AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, SettingsText(SET_FRIENDLYNAME1), my_version, my_image); #ifdef FIRMWARE_MINIMAL diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index a5f1df326..18a899589 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -794,7 +794,7 @@ bool Xdrv16(uint8_t function) case FUNC_MODULE_INIT: result = TuyaModuleSelected(); break; - case FUNC_INIT: + case FUNC_PRE_INIT: TuyaInit(); break; case FUNC_SET_DEVICE_POWER: From 0e0d8190fa4750c846d794aaad25f2f91b8d8259 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 12 Jan 2020 13:10:21 +0100 Subject: [PATCH 023/160] Change some commands displaying all items Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items --- RELEASENOTES.md | 2 + tasmota/CHANGELOG.md | 1 + tasmota/settings.ino | 2 +- tasmota/support_command.ino | 69 +++++++++++++++++++++++------------ tasmota/support_tasmota.ino | 4 +- tasmota/support_wifi.ino | 2 +- tasmota/tasmota.h | 4 ++ tasmota/xdrv_01_webserver.ino | 6 +-- tasmota/xdrv_02_mqtt.ino | 35 +++++++++++------- tasmota/xdrv_10_rules.ino | 6 +-- 10 files changed, 79 insertions(+), 52 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 007b99fe2..af4aeeb73 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -55,12 +55,14 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ### Version 8.1.0.3 - Change Lights: simplified gamma correction and 10 bits internal computation +- Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Fix ``White`` added to light status (#7142) - Fix Improved fade linearity with gamma correction - Fix LCD line and column positioning (#7387) - Fix Display handling of hexadecimal escape characters (#7387) +- Fix ``WakeUp `` ignores provided value (#7473) - Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) - Add command ``SetOption82 0/1`` to limit the CT range for Alexa to 200..380 - Add command ``ShutterButton `` to control shutter(s) by to-scho (#7403) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index e260285e8..f9089b818 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,6 +2,7 @@ ### 8.1.0.3 20200106 +- Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items - Add support for gzipped binaries - Update IRremoteESP8266 lib updated to v2.7.2 - Fix ``WakeUp `` ignores provided value (#7473) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 0e32bc7bd..a059b71e6 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1043,7 +1043,7 @@ void SettingsDefaultSet2(void) SettingsUpdateText(SET_NTPSERVER1, NTP_SERVER1); SettingsUpdateText(SET_NTPSERVER2, NTP_SERVER2); SettingsUpdateText(SET_NTPSERVER3, NTP_SERVER3); - for (uint32_t i = 0; i < 3; i++) { + for (uint32_t i = 0; i < MAX_NTP_SERVERS; i++) { SettingsUpdateText(SET_NTPSERVER1 +i, ReplaceCommaWithDot(SettingsText(SET_NTPSERVER1 +i))); } Settings.latitude = (int)((double)LATITUDE * 1000000); diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index d754e95cc..6812085c6 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -89,6 +89,15 @@ void ResponseCmndIdxChar(const char* value) Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, XdrvMailbox.index, value); } +void ResponseCmndAll(uint32_t text_index, uint32_t count) +{ + mqtt_data[0] = '\0'; + for (uint32_t i = 0; i < count; i++) { + ResponseAppend_P(PSTR("%c\"%s%d\":\"%s\""), (i) ? ',' : '{', XdrvMailbox.command, i +1, SettingsText(text_index +i)); + } + ResponseJsonEnd(); +} + /********************************************************************************************/ void ExecuteCommand(const char *cmnd, uint32_t source) @@ -1220,16 +1229,20 @@ void CmndIpAddress(void) void CmndNtpServer(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { - uint32_t ntp_server = SET_NTPSERVER1 + XdrvMailbox.index -1; - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(ntp_server, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? NTP_SERVER1 : (2 == XdrvMailbox.index) ? NTP_SERVER2 : NTP_SERVER3 : XdrvMailbox.data); - SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server))); -// restart_flag = 2; // Issue #3890 - ntp_force_sync = true; + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_NTP_SERVERS)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_NTPSERVER1, MAX_NTP_SERVERS); + } else { + uint32_t ntp_server = SET_NTPSERVER1 + XdrvMailbox.index -1; + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(ntp_server, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? NTP_SERVER1 : (2 == XdrvMailbox.index) ? NTP_SERVER2 : NTP_SERVER3 : XdrvMailbox.data); + SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server))); + // restart_flag = 2; // Issue #3890 + ntp_force_sync = true; + } + ResponseCmndIdxChar(SettingsText(ntp_server)); } - ResponseCmndIdxChar(SettingsText(ntp_server)); } } @@ -1251,14 +1264,18 @@ void CmndAp(void) void CmndSsid(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_STASSID1 + XdrvMailbox.index -1, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data); - Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SSIDS)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_STASSID1, MAX_SSIDS); + } else { + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_STASSID1 + XdrvMailbox.index -1, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data); + Settings.sta_active = XdrvMailbox.index -1; + restart_flag = 2; + } + ResponseCmndIdxChar(SettingsText(SET_STASSID1 + XdrvMailbox.index -1)); } - ResponseCmndIdxChar(SettingsText(SET_STASSID1 + XdrvMailbox.index -1)); } } @@ -1308,16 +1325,20 @@ void CmndWifiConfig(void) void CmndFriendlyname(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_FRIENDLYNAMES)) { - if (XdrvMailbox.data_len > 0) { - char stemp1[TOPSZ]; - if (1 == XdrvMailbox.index) { - snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME)); - } else { - snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), XdrvMailbox.index); + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_FRIENDLYNAME1, MAX_FRIENDLYNAMES); + } else { + if (XdrvMailbox.data_len > 0) { + char stemp1[TOPSZ]; + if (1 == XdrvMailbox.index) { + snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME)); + } else { + snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), XdrvMailbox.index); + } + SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data); } - SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data); + ResponseCmndIdxChar(SettingsText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1)); } - ResponseCmndIdxChar(SettingsText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1)); } } diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index d502e64c3..187c116a1 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -107,7 +107,7 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi fulltopic += F("/"); fulltopic += FPSTR(MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops } - for (uint32_t i = 0; i < 3; i++) { + for (uint32_t i = 0; i < MAX_MQTT_PREFIXES; i++) { if (!strlen(SettingsText(SET_MQTTPREFIX1 + i))) { char temp[TOPSZ]; SettingsUpdateText(SET_MQTTPREFIX1 + i, GetTextIndexed(temp, sizeof(temp), i, kPrefixes)); @@ -144,7 +144,7 @@ char* GetFallbackTopic_P(char *stopic, const char* subtopic) char* GetStateText(uint32_t state) { - if (state > 3) { + if (state >= MAX_STATE_TEXT) { state = 1; } return SettingsText(SET_STATE_TXT1 + state); diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 3989f8c66..954e2fb3c 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -279,7 +279,7 @@ void WifiBeginAfterScan(void) bool known = false; uint32_t j; - for (j = 0; j < 2; j++) { + for (j = 0; j < MAX_SSIDS; j++) { if (ssid_scan == SettingsText(SET_STASSID1 + j)) { // SSID match known = true; if (rssi_scan > best_network_db) { // Best network diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 32a85c80a..f0e747c27 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -73,6 +73,10 @@ const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 5 const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules // Changes to the following MAX_ defines need to be in line with enum SettingsTextIndex +const uint8_t MAX_MQTT_PREFIXES = 3; // Max number of MQTT prefixes (cmnd, stat, tele) +const uint8_t MAX_SSIDS = 2; // Max number of SSIDs +const uint8_t MAX_STATE_TEXT = 4; // Max number of State names (OFF, ON, TOGGLE, HOLD) +const uint8_t MAX_NTP_SERVERS = 3; // Max number of NTP servers const uint8_t MAX_RULE_MEMS = 16; // Max number of saved vars const uint8_t MAX_FRIENDLYNAMES = 8; // Max number of Friendly names const uint8_t MAX_BUTTON_TEXT = 16; // Max number of GUI button labels diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index eff136c7d..db0fce2a5 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2906,11 +2906,7 @@ void CmndWebButton(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_BUTTON_TEXT)) { if (!XdrvMailbox.usridx) { - mqtt_data[0] = '\0'; - for (uint32_t i = 0; i < MAX_BUTTON_TEXT; i++) { - ResponseAppend_P(PSTR("%c\"WebButton%d\":\"%s\""), (i) ? ',' : '{', i +1, SettingsText(SET_BUTTON1 +i)); - } - ResponseJsonEnd(); + ResponseCmndAll(SET_BUTTON1, MAX_BUTTON_TEXT); } else { if (XdrvMailbox.data_len > 0) { SettingsUpdateText(SET_BUTTON1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 5beac68f0..6096103c4 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -789,14 +789,18 @@ void CmndMqttRetry(void) void CmndStateText(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - if (XdrvMailbox.data_len > 0) { - for (uint32_t i = 0; i <= XdrvMailbox.data_len; i++) { - if (XdrvMailbox.data[i] == ' ') XdrvMailbox.data[i] = '_'; + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_STATE_TEXT)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_STATE_TXT1, MAX_STATE_TEXT); + } else { + if (XdrvMailbox.data_len > 0) { + for (uint32_t i = 0; i <= XdrvMailbox.data_len; i++) { + if (XdrvMailbox.data[i] == ' ') XdrvMailbox.data[i] = '_'; + } + SettingsUpdateText(SET_STATE_TXT1 + XdrvMailbox.index -1, XdrvMailbox.data); } - SettingsUpdateText(SET_STATE_TXT1 + XdrvMailbox.index -1, XdrvMailbox.data); + ResponseCmndIdxChar(GetStateText(XdrvMailbox.index -1)); } - ResponseCmndIdxChar(GetStateText(XdrvMailbox.index -1)); } } @@ -828,15 +832,18 @@ void CmndFullTopic(void) void CmndPrefix(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { - - if (XdrvMailbox.data_len > 0) { - MakeValidMqtt(0, XdrvMailbox.data); - SettingsUpdateText(SET_MQTTPREFIX1 + XdrvMailbox.index -1, - (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index) ? SUB_PREFIX : (2==XdrvMailbox.index) ? PUB_PREFIX : PUB_PREFIX2 : XdrvMailbox.data); - restart_flag = 2; + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_MQTT_PREFIXES)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_MQTTPREFIX1, MAX_MQTT_PREFIXES); + } else { + if (XdrvMailbox.data_len > 0) { + MakeValidMqtt(0, XdrvMailbox.data); + SettingsUpdateText(SET_MQTTPREFIX1 + XdrvMailbox.index -1, + (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index) ? SUB_PREFIX : (2==XdrvMailbox.index) ? PUB_PREFIX : PUB_PREFIX2 : XdrvMailbox.data); + restart_flag = 2; + } + ResponseCmndIdxChar(SettingsText(SET_MQTTPREFIX1 + XdrvMailbox.index -1)); } - ResponseCmndIdxChar(SettingsText(SET_MQTTPREFIX1 + XdrvMailbox.index -1)); } } diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 78cb73e10..dd557a0fd 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -1812,11 +1812,7 @@ void CmndMemory(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_MEMS)) { if (!XdrvMailbox.usridx) { - mqtt_data[0] = '\0'; - for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - ResponseAppend_P(PSTR("%c\"Mem%d\":\"%s\""), (i) ? ',' : '{', i +1, SettingsText(SET_MEM1 +i)); - } - ResponseJsonEnd(); + ResponseCmndAll(SET_MEM1, MAX_RULE_MEMS); } else { if (XdrvMailbox.data_len > 0) { #ifdef USE_EXPRESSION From 8cf411a1c3a94e842c98081bed6e343295b8723a Mon Sep 17 00:00:00 2001 From: to-scho Date: Sun, 12 Jan 2020 14:18:15 +0100 Subject: [PATCH 024/160] New command ShutterLock Command shutterlock 1 locks shutter movement. Any ongoing movement is still finished when called. Subsequent calls of shutter commands about movement, web buttons and shutter buttons are blocked when shutter is locked. shutterlock 0 unlocks shutter . --- tasmota/i18n.h | 1 + tasmota/settings.h | 2 +- tasmota/xdrv_01_webserver.ino | 1 - tasmota/xdrv_20_hue.ino | 4 +- tasmota/xdrv_27_shutter.ino | 199 +++++++++++++++++++--------------- 5 files changed, 115 insertions(+), 92 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index e8432bc48..8ec8020da 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -516,6 +516,7 @@ #define D_CMND_SHUTTER_MOTORDELAY "MotorDelay" #define D_CMND_SHUTTER_FREQUENCY "Frequency" #define D_CMND_SHUTTER_BUTTON "Button" +#define D_CMND_SHUTTER_LOCK "Lock" // Commands xdrv_32_hotplug.ino #define D_CMND_HOTPLUG "HotPlug" diff --git a/tasmota/settings.h b/tasmota/settings.h index b46c0dd48..684ab18af 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -432,7 +432,7 @@ struct SYSCFG { uint16_t shutter_opentime[MAX_SHUTTERS]; // E40 uint16_t shutter_closetime[MAX_SHUTTERS]; // E48 int16_t shuttercoeff[5][MAX_SHUTTERS]; // E50 - uint8_t shutter_invert[MAX_SHUTTERS]; // E78 + uint8_t shutter_options[MAX_SHUTTERS]; // E78 uint8_t shutter_set50percent[MAX_SHUTTERS]; // E7C uint8_t shutter_position[MAX_SHUTTERS]; // E80 uint8_t shutter_startrelay[MAX_SHUTTERS]; // E84 diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index db0fce2a5..927ad564d 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1212,7 +1212,6 @@ bool HandleRootStatusRefresh(void) int32_t ShutterWebButton; if (ShutterWebButton = IsShutterWebButton(device)) { snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), abs(ShutterWebButton), (ShutterWebButton>0) ? PSTR(D_CMND_SHUTTER_TOGGLEUP) : PSTR(D_CMND_SHUTTER_TOGGLEDOWN)); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: WebButton %d, %s"), ShutterWebButton, svalue); ExecuteWebCommand(svalue, SRC_WEBGUI); } else { #endif // USE_SHUTTER diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 37de3a902..87e3b3d71 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -279,7 +279,7 @@ void HueLightStatus1(uint8_t device, String *response) #ifdef USE_SHUTTER if (ShutterState(device)) { - bri = (float)(Settings.shutter_invert[device-1] ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; + bri = (float)((Settings.shutter_options[device-1] & 1) ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; } #endif @@ -681,7 +681,7 @@ void HueLights(String *path) if (change) { #ifdef USE_SHUTTER if (ShutterState(device)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_invert[device-1]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_options[device-1] & 1); ShutterSetPosition(device, bri * 100.0f ); } else #endif diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 8184cca1a..beacc6ea2 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -40,13 +40,13 @@ const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" - D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON; + D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK; void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition, &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, - &CmndShutterFrequency, &CmndShutterButton}; + &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock}; const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; @@ -233,10 +233,10 @@ void ShutterInit(void) dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); char shutter_close_chr[10]; dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d,motordelay %d"), + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100, Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, is locked %d, shuttermode %d, motordelay %d"), i+1, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], - Shutter.mask, Settings.shutter_invert[i], Shutter.mode, Shutter.motordelay[i]); + Shutter.mask, (Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, Shutter.mode, Shutter.motordelay[i]); } else { // terminate loop at first INVALID shutter. @@ -259,7 +259,7 @@ void ShutterReportPosition(bool always) ShutterLogPos(i); } if (i) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(JSON_SHUTTER_POS, i+1, Settings.shutter_invert[i] ? 100-position : position, Shutter.direction[i]); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i]); } ResponseJsonEnd(); if (always || (1 == shutter_moving)) { @@ -371,7 +371,7 @@ void ShutterUpdatePosition(void) // sending MQTT result to broker snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P("%d", Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); + Response_P("%d", (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); MqttPublish(stopic, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN Shutter.direction[i] = 0; @@ -690,22 +690,27 @@ void CmndShutterClose(void) void CmndShutterStop(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { - XdrvMailbox.index = XdrvMailbox.payload; - } - uint32_t i = XdrvMailbox.index -1; - if (Shutter.direction[i] != 0) { + if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { + if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { + XdrvMailbox.index = XdrvMailbox.payload; + } + uint32_t i = XdrvMailbox.index -1; + if (Shutter.direction[i] != 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[i]); - // set stop position 10 steps ahead (0.5sec to allow normal stop) - int32_t temp_realpos = Shutter.start_position[i] + ( (Shutter.time[i]+10) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); - XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); - //XdrvMailbox.payload = Settings.shuttercoeff[2][i] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][i] : (temp_realpos-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; - last_source = SRC_WEBGUI; - CmndShutterPosition(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[i]); + // set stop position 10 steps ahead (0.5sec to allow normal stop) + int32_t temp_realpos = Shutter.start_position[i] + ( (Shutter.time[i]+10) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); + XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); + //XdrvMailbox.payload = Settings.shuttercoeff[2][i] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][i] : (temp_realpos-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; + last_source = SRC_WEBGUI; + CmndShutterPosition(); + } else { + if (XdrvMailbox.command) + ResponseCmndDone(); + } } else { if (XdrvMailbox.command) - ResponseCmndDone(); + ResponseCmndIdxChar("Locked"); } } } @@ -713,78 +718,83 @@ void CmndShutterStop(void) void CmndShutterPosition(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - uint32_t index = XdrvMailbox.index-1; - //limit the payload - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); + if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { + uint32_t index = XdrvMailbox.index-1; + //limit the payload + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); - // value 0 with data_len > 0 can mean Open - if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { - //UpperCase(XdrvMailbox.data, XdrvMailbox.data); - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP))) { - CmndShutterOpen(); - return; + // value 0 with data_len > 0 can mean Open + if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { + //UpperCase(XdrvMailbox.data, XdrvMailbox.data); + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP))) { + CmndShutterOpen(); + return; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN))) { + CmndShutterClose(); + return; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter.direction[index]) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN)))) { + XdrvMailbox.payload = -99; + CmndShutterStop(); + return; + } } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN))) { - CmndShutterClose(); - return; - } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter.direction[index]) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN)))) { - XdrvMailbox.payload = -99; - CmndShutterStop(); - return; - } - } - int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? 0 : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); - // webgui still send also on inverted shutter the native position. - target_pos_percent = (Settings.shutter_invert[index] && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; - if (XdrvMailbox.payload != -99) { - //target_pos_percent = Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent; - Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); - Shutter.accelerator[index] = Shutter.max_pwm_frequency / ((Shutter.motordelay[index] > 0) ? Shutter.motordelay[index] : 1); - //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); - } - if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) { - int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1; - if (Shutter.direction[index] == -new_shutterdirection) { - // direction need to be changed. on momentary switches first stop the Shutter - if (SHT_PULSE_OPEN__PULSE_CLOSE == Shutter.mode) { - // code for momentary shutters only small switch on to stop Shutter - ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 0 : 1), 1, SRC_SHUTTER); - delay(100); - } else { - if (SHT_OFF_OPEN__OFF_CLOSE == Shutter.mode) { - ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 1 : 0), 0, SRC_SHUTTER); - ShutterWaitForMotorStop(index); + int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? 0 : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); + // webgui still send also on inverted shutter the native position. + target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; + if (XdrvMailbox.payload != -99) { + //target_pos_percent = (Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent; + Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); + Shutter.accelerator[index] = Shutter.max_pwm_frequency / ((Shutter.motordelay[index] > 0) ? Shutter.motordelay[index] : 1); + //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); + } + if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) { + int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1; + if (Shutter.direction[index] == -new_shutterdirection) { + // direction need to be changed. on momentary switches first stop the Shutter + if (SHT_PULSE_OPEN__PULSE_CLOSE == Shutter.mode) { + // code for momentary shutters only small switch on to stop Shutter + ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 0 : 1), 1, SRC_SHUTTER); + delay(100); + } else { + if (SHT_OFF_OPEN__OFF_CLOSE == Shutter.mode) { + ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 1 : 0), 0, SRC_SHUTTER); + ShutterWaitForMotorStop(index); + } } } - } - if (Shutter.direction[index] != new_shutterdirection) { - if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); - ShutterWaitForMotorStop(index); - ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); - ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); - // Code for shutters with circuit safe configuration, switch the direction Relay - ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); - // power on - ExecuteCommandPower(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); - } else { - // now start the motor for the right direction, work for momentary and normal shutters. - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start in dir %d"), Shutter.direction[index]); - ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); - ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay6 5s, xdrv %d"), XdrvMailbox.payload); + if (Shutter.direction[index] != new_shutterdirection) { + if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); + ShutterWaitForMotorStop(index); + ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); + ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); + // Code for shutters with circuit safe configuration, switch the direction Relay + ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); + // power on + ExecuteCommandPower(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); + } else { + // now start the motor for the right direction, work for momentary and normal shutters. + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start in dir %d"), Shutter.direction[index]); + ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); + ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay6 5s, xdrv %d"), XdrvMailbox.payload); + } + Shutter.switched_relay = 0; } - Shutter.switched_relay = 0; + } else { + target_pos_percent = ShutterRealToPercentPosition(Shutter.real_position[index], index); } + XdrvMailbox.index = index +1; // Fix random index for ShutterClose + if (XdrvMailbox.command) + ResponseCmndIdxNumber((Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent); } else { - target_pos_percent = ShutterRealToPercentPosition(Shutter.real_position[index], index); + if (XdrvMailbox.command) + ResponseCmndIdxChar("Locked"); } - XdrvMailbox.index = index +1; // Fix random index for ShutterClose - if (XdrvMailbox.command) - ResponseCmndIdxNumber(Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent); } } @@ -972,10 +982,10 @@ void CmndShutterSetHalfway(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Settings.shutter_set50percent[XdrvMailbox.index -1] = Settings.shutter_invert[XdrvMailbox.index -1] ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; + Settings.shutter_set50percent[XdrvMailbox.index -1] = (Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; ShutterInit(); } - ResponseCmndIdxNumber(Settings.shutter_invert[XdrvMailbox.index -1] ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]); + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]); } } @@ -1006,10 +1016,12 @@ void CmndShutterSetClose(void) void CmndShutterInvert(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.shutter_invert[XdrvMailbox.index -1] = XdrvMailbox.payload; + if (XdrvMailbox.payload == 0) { + Settings.shutter_options[XdrvMailbox.index -1] &= ~(1); + } else if (XdrvMailbox.payload == 1) { + Settings.shutter_options[XdrvMailbox.index -1] |= (1); } - ResponseCmndIdxNumber(Settings.shutter_invert[XdrvMailbox.index -1]); + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 1 : 0); } } @@ -1046,6 +1058,17 @@ void CmndShutterCalibration(void) } } +void CmndShutterLock(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.payload == 0) { + Settings.shutter_options[XdrvMailbox.index -1] &= ~(2); + } else if (XdrvMailbox.payload == 1) { + Settings.shutter_options[XdrvMailbox.index -1] |= (2); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 2) ? 1 : 0); + } +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -1072,7 +1095,7 @@ bool Xdrv27(uint8_t function) break; case FUNC_JSON_APPEND: for (uint8_t i = 0; i < shutters_present; i++) { - uint8_t position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; + uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; ResponseAppend_P(","); ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); #ifdef USE_DOMOTICZ From 80773f74c7c20a6efb21a1777064ce87c61e9d31 Mon Sep 17 00:00:00 2001 From: to-scho Date: Sun, 12 Jan 2020 15:40:31 +0100 Subject: [PATCH 025/160] initialize shutters when interlock is changed --- tasmota/support_command.ino | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 6812085c6..2149bd083 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1394,6 +1394,11 @@ void CmndInterlock(void) SetDevicePower(power, SRC_IGNORE); // Remove multiple relays if set } } +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support + ShutterInit(); // to update shutter mode + } +#endif // USE_SHUTTER } Response_P(PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); uint32_t anygroup = 0; From 5840f71af9bc095e6f912296eaf01379e13ca160 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 12 Jan 2020 23:31:57 +0100 Subject: [PATCH 026/160] Fix char[] allocation --- tasmota/xdrv_05_irremote.ino | 2 +- tasmota/xdrv_05_irremote_full.ino | 4 ++-- tasmota/xdrv_09_timers.ino | 2 +- tasmota/xdrv_17_rcswitch.ino | 2 +- tasmota/xdrv_23_zigbee_9_impl.ino | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tasmota/xdrv_05_irremote.ino b/tasmota/xdrv_05_irremote.ino index 3c9479937..6c6e16fdb 100644 --- a/tasmota/xdrv_05_irremote.ino +++ b/tasmota/xdrv_05_irremote.ino @@ -181,7 +181,7 @@ uint32_t IrRemoteCmndIrSendJson(void) // IRsend { "protocol": "RC5", "bits": 12, "data":"0xC86" } // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } - char dataBufUc[XdrvMailbox.data_len]; + char dataBufUc[XdrvMailbox.data_len + 1]; UpperCase(dataBufUc, XdrvMailbox.data); RemoveSpace(dataBufUc); if (strlen(dataBufUc) < 8) { diff --git a/tasmota/xdrv_05_irremote_full.ino b/tasmota/xdrv_05_irremote_full.ino index 77fc3f7cc..14de34cbc 100644 --- a/tasmota/xdrv_05_irremote_full.ino +++ b/tasmota/xdrv_05_irremote_full.ino @@ -280,7 +280,7 @@ uint32_t IrRemoteCmndIrHvacJson(void) char parm_uc[12]; //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Received %s"), XdrvMailbox.data); - char dataBufUc[XdrvMailbox.data_len]; + char dataBufUc[XdrvMailbox.data_len + 1]; UpperCase(dataBufUc, XdrvMailbox.data); RemoveSpace(dataBufUc); if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } @@ -393,7 +393,7 @@ uint32_t IrRemoteCmndIrSendJson(void) // ArduinoJSON entry used to calculate jsonBuf: JSON_OBJECT_SIZE(3) + 40 = 96 // IRsend { "protocol": "RC5", "bits": 12, "data":"0xC86" } // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } - char dataBufUc[XdrvMailbox.data_len]; + char dataBufUc[XdrvMailbox.data_len + 1]; UpperCase(dataBufUc, XdrvMailbox.data); RemoveSpace(dataBufUc); if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index b31a6a5ef..0804ce286 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -364,7 +364,7 @@ void CmndTimer(void) #if defined(USE_RULES)==0 && defined(USE_SCRIPT)==0 if (devices_present) { #endif - char dataBufUc[XdrvMailbox.data_len]; + char dataBufUc[XdrvMailbox.data_len + 1]; UpperCase(dataBufUc, XdrvMailbox.data); StaticJsonBuffer<256> jsonBuffer; JsonObject& root = jsonBuffer.parseObject(dataBufUc); diff --git a/tasmota/xdrv_17_rcswitch.ino b/tasmota/xdrv_17_rcswitch.ino index 4462a5e21..9cd2d14d8 100644 --- a/tasmota/xdrv_17_rcswitch.ino +++ b/tasmota/xdrv_17_rcswitch.ino @@ -105,7 +105,7 @@ void CmndRfSend(void) int repeat = 10; int pulse = 350; - char dataBufUc[XdrvMailbox.data_len]; + char dataBufUc[XdrvMailbox.data_len + 1]; UpperCase(dataBufUc, XdrvMailbox.data); StaticJsonBuffer<150> jsonBuf; // ArduinoJSON entry used to calculate jsonBuf: JSON_OBJECT_SIZE(5) + 40 = 134 JsonObject &root = jsonBuf.parseObject(dataBufUc); diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 70c5659ca..408410f9b 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -548,7 +548,7 @@ void CmndZigbeeSend(void) { // Probe a specific device to get its endpoints and supported clusters void CmndZigbeeProbe(void) { if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - char dataBufUc[XdrvMailbox.data_len]; + char dataBufUc[XdrvMailbox.data_len + 1]; UpperCase(dataBufUc, XdrvMailbox.data); RemoveSpace(dataBufUc); if (strlen(dataBufUc) < 3) { ResponseCmndChar("Invalid destination"); return; } From d00bea84ece1324e2b550f6740628b1dad584d18 Mon Sep 17 00:00:00 2001 From: to-scho Date: Mon, 13 Jan 2020 09:48:29 +0100 Subject: [PATCH 027/160] Fix target shutter position inaccuracy Introduced numerical rounding when calculating between "%" and "time" position values --- tasmota/xdrv_27_shutter.ino | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index beacc6ea2..79a015eed 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -97,6 +97,8 @@ void ShutterRtc50mS(void) } } +#define SHT_DIV_ROUND(__A, __B) (((__A) + (__B)/2) / (__B)) + int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) { if (Settings.shutter_set50percent[index] != 50) { @@ -108,21 +110,21 @@ int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) if (0 == Settings.shuttercoeff[j][index]) { AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0")); for (uint32_t k = 0; k < 5; k++) { - Settings.shuttercoeff[k][index] = messwerte[k] * 1000 / messwerte[4]; + Settings.shuttercoeff[k][index] = SHT_DIV_ROUND(calibrate_pos[k+1] * 1000, calibrate_pos[5]); } } } for (uint32_t i = 0; i < 5; i++) { if ((percent * 10) > Settings.shuttercoeff[i][index]) { - realpos = Shutter.open_max[index] * calibrate_pos[i+1] / 100; + realpos = SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i+1], 100); //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[i][index]); } else { if (0 == i) { - realpos = percent * Shutter.open_max[index] * calibrate_pos[i+1] / Settings.shuttercoeff[i][index] / 10; + realpos = SHT_DIV_ROUND(SHT_DIV_ROUND(percent * Shutter.open_max[index] * calibrate_pos[i+1], Settings.shuttercoeff[i][index]), 10); } else { //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP2: %d, %% %d, coeff %d"), addon, (calibrate_pos[i+1] - calibrate_pos[i]), (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index])); - realpos += ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter.open_max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; + realpos += SHT_DIV_ROUND(SHT_DIV_ROUND((percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter.open_max[index] * (calibrate_pos[i+1] - calibrate_pos[i]), Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]), 100); } break; } @@ -134,22 +136,22 @@ int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) { if (Settings.shutter_set50percent[index] != 50) { - return (Settings.shuttercoeff[2][index] * 5 > realpos) ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index]; + return (Settings.shuttercoeff[2][index] * 5 > realpos) ? SHT_DIV_ROUND(realpos, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos-Settings.shuttercoeff[0][index], Settings.shuttercoeff[1][index]); } else { uint16_t realpercent; for (uint32_t i = 0; i < 5; i++) { if (realpos >= Shutter.open_max[index] * calibrate_pos[i+1] / 100) { - realpercent = Settings.shuttercoeff[i][index] /10; + realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[i][index], 10); //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP1: %d, %% %d, coeff %d"), realpercent, realpos, Shutter_Open_Max[index] * calibrate_pos[i+1] / 100); } else { if (0 == i) { - realpercent = ( realpos - (Shutter.open_max[index] * calibrate_pos[i] / 100) ) * 10 * Settings.shuttercoeff[i][index] / calibrate_pos[i+1] / Shutter.open_max[index]; + realpercent = SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i], 100)) * 10 * Settings.shuttercoeff[i][index], calibrate_pos[i+1]), Shutter.open_max[index]); } else { //uint16_t addon = ( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i])/ Shutter_Open_Max[index]; //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP2: %d, delta %d, %% %d, coeff %d"), addon,( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) , (calibrate_pos[i+1] - calibrate_pos[i])* Shutter_Open_Max[index]/100, (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index])); - realpercent += ( realpos - (Shutter.open_max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i]) / Shutter.open_max[index] ; + realpercent += SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i], 100)) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]), (calibrate_pos[i+1] - calibrate_pos[i])), Shutter.open_max[index]) ; } break; } @@ -1045,7 +1047,7 @@ void CmndShutterCalibration(void) messwerte[i] = field; } for (i = 0; i < 5; i++) { - Settings.shuttercoeff[i][XdrvMailbox.index -1] = (uint32_t)messwerte[i] * 1000 / messwerte[4]; + Settings.shuttercoeff[i][XdrvMailbox.index -1] = SHT_DIV_ROUND((uint32_t)messwerte[i] * 1000, messwerte[4]); AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); } ShutterInit(); From 0327d7f4b4541b68b3c0b87632693d71b27009b8 Mon Sep 17 00:00:00 2001 From: to-scho Date: Mon, 13 Jan 2020 12:00:34 +0100 Subject: [PATCH 028/160] New command ShutterEnableEndStopTime --- tasmota/i18n.h | 1 + tasmota/xdrv_27_shutter.ino | 38 +++++++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 8ec8020da..0dece041a 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -517,6 +517,7 @@ #define D_CMND_SHUTTER_FREQUENCY "Frequency" #define D_CMND_SHUTTER_BUTTON "Button" #define D_CMND_SHUTTER_LOCK "Lock" +#define D_CMND_SHUTTER_ENABLEENDSTOPTIME "EnableEndStopTime" // Commands xdrv_32_hotplug.ino #define D_CMND_HOTPLUG "HotPlug" diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 79a015eed..f79f2de9d 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -40,13 +40,13 @@ const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" - D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK; + D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME; void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition, &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, - &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock}; + &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime}; const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; @@ -115,7 +115,7 @@ int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) } } for (uint32_t i = 0; i < 5; i++) { - if ((percent * 10) > Settings.shuttercoeff[i][index]) { + if ((percent * 10) >= Settings.shuttercoeff[i][index]) { realpos = SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i+1], 100); //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[i][index]); } else { @@ -235,10 +235,10 @@ void ShutterInit(void) dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); char shutter_close_chr[10]; dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100, Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, is locked %d, shuttermode %d, motordelay %d"), + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100, Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, is locked %d, end stop time enabled %d, shuttermode %d, motordelay %d"), i+1, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], - Shutter.mask, (Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, Shutter.mode, Shutter.motordelay[i]); + Shutter.mask, (Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, (Settings.shutter_options[i]&4) ? 1 : 0, Shutter.mode, Shutter.motordelay[i]); } else { // terminate loop at first INVALID shutter. @@ -276,6 +276,13 @@ void ShutterReportPosition(bool always) //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); } +void ShutterLimitRealAndTargetPositions(uint32_t i) { + if (Shutter.real_position[i]<0) Shutter.real_position[i] = 0; + if (Shutter.real_position[i]>Shutter.open_max[i]) Shutter.real_position[i] = Shutter.open_max[i]; + if (Shutter.target_position[i]<0) Shutter.target_position[i] = 0; + if (Shutter.target_position[i]>Shutter.open_max[i]) Shutter.target_position[i] = Shutter.open_max[i]; +} + void ShutterUpdatePosition(void) { @@ -364,6 +371,7 @@ void ShutterUpdatePosition(void) } break; } + ShutterLimitRealAndTargetPositions(i); Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); ShutterLogPos(i); @@ -464,6 +472,7 @@ void ShutterRelayChanged(void) //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i+1, GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); if (manual_relays_changed) { //Shutter.skip_relay_change = true; + ShutterLimitRealAndTargetPositions(i); if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { ShutterWaitForMotorStop(i); switch (powerstate_local) { @@ -748,7 +757,13 @@ void CmndShutterPosition(void) target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; if (XdrvMailbox.payload != -99) { //target_pos_percent = (Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent; - Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); + if (0 == target_pos_percent) { + Shutter.target_position[index] = (Settings.shutter_options[index] & 4) ? (-1 * 2000) : 0; + } else if (100 == target_pos_percent) { + Shutter.target_position[index] = (Settings.shutter_options[index] & 4) ? (Shutter.open_max[index] + 1 * 2000) : Shutter.open_max[index]; + } else { + Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); + } Shutter.accelerator[index] = Shutter.max_pwm_frequency / ((Shutter.motordelay[index] > 0) ? Shutter.motordelay[index] : 1); //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); @@ -1071,6 +1086,17 @@ void CmndShutterLock(void) { } } +void CmndShutterEnableEndStopTime(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.payload == 0) { + Settings.shutter_options[XdrvMailbox.index -1] &= ~(4); + } else if (XdrvMailbox.payload == 1) { + Settings.shutter_options[XdrvMailbox.index -1] |= (4); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 4) ? 1 : 0); + } +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ From bc83aad8bd926f70d69d875fad7f6126c454bbf1 Mon Sep 17 00:00:00 2001 From: to-scho Date: Tue, 14 Jan 2020 11:00:22 +0100 Subject: [PATCH 029/160] Show webbutton label '-' when shutter is locked --- tasmota/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 927ad564d..f07ce00d8 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1123,7 +1123,7 @@ void HandleRoot(void) int32_t ShutterWebButton; if (ShutterWebButton = IsShutterWebButton(idx)) { WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (ShutterWebButton>0) ? "▲" : "▼", + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) /* is locked */ ? "-" : ((ShutterWebButton>0) ? "▲" : "▼")), ""); continue; } From 0db458c77424cb959613268ecccb7ac32b999705 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 14 Jan 2020 12:47:48 +0100 Subject: [PATCH 030/160] Fix exception 9 restart on log message Fix exception 9 restart on log message in Ticker interrupt service routines NTP, Wemos and Hue emulation (#7496) --- RELEASENOTES.md | 2 ++ tasmota/CHANGELOG.md | 5 +++-- tasmota/support.ino | 10 ++++++++++ tasmota/support_rtc.ino | 6 +++--- tasmota/support_tasmota.ino | 12 +++++------- tasmota/tasmota.ino | 2 +- tasmota/xdrv_20_hue.ino | 3 ++- tasmota/xdrv_21_wemo.ino | 3 ++- 8 files changed, 28 insertions(+), 15 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index af4aeeb73..bd00d25fb 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -56,6 +56,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change Lights: simplified gamma correction and 10 bits internal computation - Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items +- Change IRremoteESP8266 library updated to v2.7.2 - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Fix ``White`` added to light status (#7142) @@ -63,6 +64,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix LCD line and column positioning (#7387) - Fix Display handling of hexadecimal escape characters (#7387) - Fix ``WakeUp `` ignores provided value (#7473) +- Fix exception 9 restart on log message in Ticker interrupt service routines NTP, Wemos and Hue emulation (#7496) - Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) - Add command ``SetOption82 0/1`` to limit the CT range for Alexa to 200..380 - Add command ``ShutterButton `` to control shutter(s) by to-scho (#7403) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index f9089b818..3df11015b 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,9 +3,10 @@ ### 8.1.0.3 20200106 - Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items -- Add support for gzipped binaries -- Update IRremoteESP8266 lib updated to v2.7.2 +- Change IRremoteESP8266 library updated to v2.7.2 - Fix ``WakeUp `` ignores provided value (#7473) +- Fix exception 9 restart on log message in Ticker interrupt service routines NTP, Wemos and Hue emulation (#7496) +- Add support for gzipped binaries ### 8.1.0.2 20191230 diff --git a/tasmota/support.ino b/tasmota/support.ino index 6ae6898e4..011fa8ca4 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1678,6 +1678,16 @@ void AddLog_P(uint32_t loglevel, const char *formatP, const char *formatP2) AddLog(loglevel); } +void PrepLog_P2(uint32_t loglevel, PGM_P formatP, ...) +{ + va_list arg; + va_start(arg, formatP); + vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + va_end(arg); + + prepped_loglevel = loglevel; +} + void AddLog_P2(uint32_t loglevel, PGM_P formatP, ...) { va_list arg; diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index 03ebca18d..fe8f12454 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -396,9 +396,9 @@ void RtcSecond(void) Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); - // Do not use AddLog here if syslog is enabled. UDP will force exception 9 - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "(" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - ntp_synced_message = true; + // Do not use AddLog_P2 here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9 + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + DriftTime(), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01 rules_flag.time_init = 1; diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 187c116a1..fd5bf28fa 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -698,13 +698,6 @@ void PerformEverySecond(void) { uptime++; - if (ntp_synced_message) { - // Moved here to fix syslog UDP exception 9 during RtcSecond - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - DriftTime(), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - ntp_synced_message = false; - } - if (POWER_CYCLE_TIME == uptime) { UpdateQuickPowerCycle(false); } @@ -782,6 +775,11 @@ void Every100mSeconds(void) // As the max amount of sleep = 250 mSec this loop will shift in time... power_t power_now; + if (prepped_loglevel) { + AddLog(prepped_loglevel); + prepped_loglevel = 0; + } + if (latching_relay_pulse) { latching_relay_pulse--; if (!latching_relay_pulse) SetLatchingRelay(0, 0); diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 97f2ff797..721c2f4ac 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -139,6 +139,7 @@ uint8_t my_module_type; // Current copy of Settings.module o uint8_t my_adc0; // Active copy of Module ADC0 uint8_t last_source = 0; // Last command source uint8_t shutters_present = 0; // Number of actual define shutters +uint8_t prepped_loglevel = 0; // Delayed log level message //uint8_t mdns_delayed_start = 0; // mDNS delayed start bool serial_local = false; // Handle serial locally; bool fallback_topic_flag = false; // Use Topic or FallbackTopic @@ -152,7 +153,6 @@ bool i2c_flg = false; // I2C configured bool spi_flg = false; // SPI configured bool soft_spi_flg = false; // Software SPI configured bool ntp_force_sync = false; // Force NTP sync -bool ntp_synced_message = false; // NTP synced message flag bool is_8285 = false; // Hardware device ESP8266EX (0) or ESP8285 (1) myio my_module; // Active copy of Module GPIOs (17 x 8 bits) gpio_flag my_module_flag; // Active copy of Template GPIO flags diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 87e3b3d71..9bd88193c 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -100,7 +100,8 @@ void HueRespondToMSearch(void) } else { snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), + // Do not use AddLog_P2 here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9 + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), message, udp_remote_ip.toString().c_str(), udp_remote_port); udp_response_mutex = false; diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino index 6aef27311..85d462876 100644 --- a/tasmota/xdrv_21_wemo.ino +++ b/tasmota/xdrv_21_wemo.ino @@ -74,7 +74,8 @@ void WemoRespondToMSearch(int echo_type) } else { snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), + // Do not use AddLog_P2 here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9 + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port); udp_response_mutex = false; From 64d3d0c075222f0fb5083ff8f5962c1245f2c344 Mon Sep 17 00:00:00 2001 From: to-scho Date: Tue, 14 Jan 2020 13:32:51 +0100 Subject: [PATCH 031/160] Change MQTT reporting of instantaneous shutter position from tele to stat --- tasmota/xdrv_27_shutter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index f79f2de9d..f7a574714 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -265,7 +265,7 @@ void ShutterReportPosition(bool always) } ResponseJsonEnd(); if (always || (1 == shutter_moving)) { - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_PRFX_SHUTTER)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); } if (rules_flag.shutter_moving > shutter_moving) { rules_flag.shutter_moved = 1; From 423b6f251b0c71b0573a326b934fd5eda63517c6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 14 Jan 2020 14:33:27 +0100 Subject: [PATCH 032/160] Add user control over vertical console size Add user control over vertical console size (#7507) --- tasmota/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index f07ce00d8..ea744f149 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -341,7 +341,7 @@ const char HTTP_HEAD_STYLE1[] PROGMEM = "input[type=checkbox],input[type=radio]{width:1em;margin-right:6px;vertical-align:-1px;}" "input[type=range]{width:99%%;}" "select{width:100%%;background:#%06x;color:#%06x;}" // COLOR_INPUT, COLOR_INPUT_TEXT - "textarea{resize:none;width:98%%;height:318px;padding:5px;overflow:auto;background:#%06x;color:#%06x;}" // COLOR_CONSOLE, COLOR_CONSOLE_TEXT + "textarea{resize:vertical;width:98%%;height:318px;padding:5px;overflow:auto;background:#%06x;color:#%06x;}" // COLOR_CONSOLE, COLOR_CONSOLE_TEXT "body{text-align:center;font-family:verdana,sans-serif;background:#%06x;}" // COLOR_BACKGROUND "td{padding:0px;}"; const char HTTP_HEAD_STYLE2[] PROGMEM = From 81d58d69b63abc5f39a1923eb417e5287736ed44 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 14 Jan 2020 14:42:30 +0100 Subject: [PATCH 033/160] Revert "Add user control over vertical console size" This reverts commit 423b6f251b0c71b0573a326b934fd5eda63517c6. --- tasmota/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index ea744f149..f07ce00d8 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -341,7 +341,7 @@ const char HTTP_HEAD_STYLE1[] PROGMEM = "input[type=checkbox],input[type=radio]{width:1em;margin-right:6px;vertical-align:-1px;}" "input[type=range]{width:99%%;}" "select{width:100%%;background:#%06x;color:#%06x;}" // COLOR_INPUT, COLOR_INPUT_TEXT - "textarea{resize:vertical;width:98%%;height:318px;padding:5px;overflow:auto;background:#%06x;color:#%06x;}" // COLOR_CONSOLE, COLOR_CONSOLE_TEXT + "textarea{resize:none;width:98%%;height:318px;padding:5px;overflow:auto;background:#%06x;color:#%06x;}" // COLOR_CONSOLE, COLOR_CONSOLE_TEXT "body{text-align:center;font-family:verdana,sans-serif;background:#%06x;}" // COLOR_BACKGROUND "td{padding:0px;}"; const char HTTP_HEAD_STYLE2[] PROGMEM = From fe17be62ccc3a170f8ba6cacb709b361fea9d7ef Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 14 Jan 2020 15:38:16 +0100 Subject: [PATCH 034/160] Add user control over vertical console size Add user control over vertical console size (#7507) --- tasmota/xdrv_01_webserver.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index f07ce00d8..40628fbb1 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -187,7 +187,8 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "c=eb('c1');" "o='&c1='+encodeURIComponent(c.value);" "c.value='';" - "t.scrollTop=sn;" + "t.scrollTop=99999;" + "sn=t.scrollTop;" "}" "if(t.scrollTop>=sn){" // User scrolled back so no updates "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) @@ -341,7 +342,7 @@ const char HTTP_HEAD_STYLE1[] PROGMEM = "input[type=checkbox],input[type=radio]{width:1em;margin-right:6px;vertical-align:-1px;}" "input[type=range]{width:99%%;}" "select{width:100%%;background:#%06x;color:#%06x;}" // COLOR_INPUT, COLOR_INPUT_TEXT - "textarea{resize:none;width:98%%;height:318px;padding:5px;overflow:auto;background:#%06x;color:#%06x;}" // COLOR_CONSOLE, COLOR_CONSOLE_TEXT + "textarea{resize:vertical;width:98%%;height:318px;padding:5px;overflow:auto;background:#%06x;color:#%06x;}" // COLOR_CONSOLE, COLOR_CONSOLE_TEXT "body{text-align:center;font-family:verdana,sans-serif;background:#%06x;}" // COLOR_BACKGROUND "td{padding:0px;}"; const char HTTP_HEAD_STYLE2[] PROGMEM = From ceef5634148a8adb920be8a54b83864f865ceee2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 14 Jan 2020 15:58:56 +0100 Subject: [PATCH 035/160] Add simple check for serialreceived JSON Add simple check for serialreceived JSON (#7506) --- tasmota/support_tasmota.ino | 7 +++++-- tasmota/xdrv_08_serial_bridge.ino | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index fd5bf28fa..ee3678ee2 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1209,8 +1209,11 @@ void SerialInput(void) if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { // CMND_SERIALSEND and CMND_SERIALLOG serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed char hex_char[(serial_in_byte_counter * 2) + 2]; - Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), - (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer); + bool assume_json = (!Settings.flag.mqtt_serial_raw && (serial_in_buffer[0] == '{')); + Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":%s%s%s}"), + (assume_json) ? "" : """", + (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer, + (assume_json) ? "" : """"); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); XdrvRulesProcess(); serial_in_byte_counter = 0; diff --git a/tasmota/xdrv_08_serial_bridge.ino b/tasmota/xdrv_08_serial_bridge.ino index 3be49f6b2..c4f530a21 100644 --- a/tasmota/xdrv_08_serial_bridge.ino +++ b/tasmota/xdrv_08_serial_bridge.ino @@ -71,8 +71,11 @@ void SerialBridgeInput(void) if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // Serial data completed char hex_char[(serial_bridge_in_byte_counter * 2) + 2]; - Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), - (serial_bridge_raw) ? ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char)) : serial_bridge_buffer); + bool assume_json = (!serial_bridge_raw && (serial_bridge_buffer[0] == '{')); + Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":%s%s%s}"), + (assume_json) ? "" : """", + (serial_bridge_raw) ? ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char)) : serial_bridge_buffer, + (assume_json) ? "" : """"); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); XdrvRulesProcess(); serial_bridge_in_byte_counter = 0; From 77191f2fe97a7910386aa87405bf22747a8c394d Mon Sep 17 00:00:00 2001 From: Hadinger Date: Tue, 14 Jan 2020 16:41:47 +0100 Subject: [PATCH 036/160] Simplified TimeDifference (saves 16 bytes) --- tasmota/support.ino | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index 011fa8ca4..a9a631fd1 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1244,45 +1244,18 @@ void TemplateJson(void) * Sleep aware time scheduler functions borrowed from ESPEasy \*********************************************************************************************/ -long TimeDifference(unsigned long prev, unsigned long next) -{ - // Return the time difference as a signed value, taking into account the timers may overflow. - // Returned timediff is between -24.9 days and +24.9 days. - // Returned value is positive when "next" is after "prev" - long signed_diff = 0; - // To cast a value to a signed long, the difference may not exceed half 0xffffffffUL (= 4294967294) - const unsigned long half_max_unsigned_long = 2147483647u; // = 2^31 -1 - if (next >= prev) { - const unsigned long diff = next - prev; - if (diff <= half_max_unsigned_long) { // Normal situation, just return the difference. - signed_diff = static_cast(diff); // Difference is a positive value. - } else { - // prev has overflow, return a negative difference value - signed_diff = static_cast((0xffffffffUL - next) + prev + 1u); - signed_diff = -1 * signed_diff; - } - } else { - // next < prev - const unsigned long diff = prev - next; - if (diff <= half_max_unsigned_long) { // Normal situation, return a negative difference value - signed_diff = static_cast(diff); - signed_diff = -1 * signed_diff; - } else { - // next has overflow, return a positive difference value - signed_diff = static_cast((0xffffffffUL - prev) + next + 1u); - } - } - return signed_diff; +inline int32_t TimeDifference(uint32_t prev, uint32_t next) { + return ((int32_t) (next - prev)); } -long TimePassedSince(unsigned long timestamp) +int32_t TimePassedSince(uint32_t timestamp) { // Compute the number of milliSeconds passed since timestamp given. // Note: value can be negative if the timestamp has not yet been reached. return TimeDifference(timestamp, millis()); } -bool TimeReached(unsigned long timer) +bool TimeReached(uint32_t timer) { // Check if a certain timeout has been reached. const long passed = TimePassedSince(timer); From 338499d8e2b7d23a7964a5c667e3155724a030e4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 14 Jan 2020 16:57:55 +0100 Subject: [PATCH 037/160] Fix unknown command topic --- tasmota/support_command.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 2149bd083..a1c38cf43 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -237,9 +237,9 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) if (type == nullptr) { blinks = 201; - snprintf_P(topicBuf, sizeof(topicBuf), PSTR(D_JSON_COMMAND)); + snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_COMMAND)); Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); - type = (char*)topicBuf; + type = (char*)stemp1; } if (mqtt_data[0] != '\0') { From a2c8ea9d653b1c86f3acf46800cd0141028dc903 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Wed, 15 Jan 2020 22:14:47 +1100 Subject: [PATCH 038/160] Make the B or brightness part of the HSBColor command optional This makes it easier (possible?) to use the HSBColor with hs_command_topic in Home-Assistant, which in turn allows completely independent control of the color part of an RGBW or RGBWW bulb. --- tasmota/xdrv_04_light.ino | 42 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 9526f8c82..0fa8838f8 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2249,31 +2249,31 @@ void CmndHsbColor(void) bool validHSB = (XdrvMailbox.data_len > 0); if (validHSB) { uint16_t HSB[3]; - if (strstr(XdrvMailbox.data, ",") != nullptr) { // Command with 3 comma separated parameters, Hue (0 Date: Wed, 15 Jan 2020 13:05:00 +0100 Subject: [PATCH 039/160] New switchmodes TOGGLEMULTI, FOLLOWMULTI and FOLLOWMULTI_INV --- tasmota/my_user_config.h | 2 +- tasmota/support_switch.ino | 48 ++++++++++++++++++++++++++------------ tasmota/tasmota.h | 2 +- tasmota/xdrv_10_rules.ino | 2 +- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index e9e8f390c..801c57acc 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -225,7 +225,7 @@ #define KEY_DEBOUNCE_TIME 50 // [ButtonDebounce] Number of mSeconds button press debounce time #define KEY_HOLD_TIME 40 // [SetOption32] Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message #define SWITCH_DEBOUNCE_TIME 50 // [SwitchDebounce] Number of mSeconds switch press debounce time -#define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE (the wall switch state) +#define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEHOLD, FOLLOWHOLD, FOLLOWHOLD_INV (the wall switch state) #define WS2812_LEDS 30 // [Pixels] Number of WS2812 LEDs to start with (max is 512) #define TEMP_CONVERSION 0 // [SetOption8] Return temperature in (0 = Celsius or 1 = Fahrenheit) diff --git a/tasmota/support_switch.ino b/tasmota/support_switch.ino index b8ce8c646..9cc3c336f 100644 --- a/tasmota/support_switch.ino +++ b/tasmota/support_switch.ino @@ -137,22 +137,36 @@ void SwitchHandler(uint8_t mode) for (uint32_t i = 0; i < MAX_SWITCHES; i++) { if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { + uint8_t button = Switch.virtual_state[i]; + uint8_t switchflag = POWER_TOGGLE +1; if (Switch.hold_timer[i]) { Switch.hold_timer[i]--; if (0 == Switch.hold_timer[i]) { - SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + + switch (Settings.switchmode[i]) { + case TOGGLEMULTI: + switchflag = POWER_TOGGLE; // Toggle after hold + break; + case FOLLOWMULTI: + switchflag = button &1; // Follow wall switch state after hold + break; + case FOLLOWMULTI_INV: + switchflag = ~button &1; // Follow inverted wall switch state after hold + break; + default: + SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + break; + } } } - uint8_t button = Switch.virtual_state[i]; - -// enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION}; +// enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEMULTI, FOLLOWMULTI, FOLLOWMULTI_INV, MAX_SWITCH_OPTION}; if (button != Switch.last_state[i]) { - uint8_t switchflag = POWER_TOGGLE +1; switch (Settings.switchmode[i]) { case TOGGLE: + case PUSHBUTTON_TOGGLE: switchflag = POWER_TOGGLE; // Toggle break; case FOLLOW: @@ -171,11 +185,6 @@ void SwitchHandler(uint8_t mode) switchflag = POWER_TOGGLE; // Toggle with releasing pushbutton from Gnd } break; - case PUSHBUTTON_TOGGLE: - if (button != Switch.last_state[i]) { - switchflag = POWER_TOGGLE; // Toggle with any pushbutton change - } - break; case PUSHBUTTONHOLD: if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; @@ -194,16 +203,25 @@ void SwitchHandler(uint8_t mode) switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd } break; - } - - if (switchflag <= POWER_TOGGLE) { - if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT - ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < devices_present) + case TOGGLEMULTI: + case FOLLOWMULTI: + case FOLLOWMULTI_INV: + if (Switch.hold_timer[i]) { + Switch.hold_timer[i] = 0; + SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + } else { + Switch.hold_timer[i] = loops_per_second / 2; // 0.5 second multi press window } + break; } Switch.last_state[i] = button; } + if (switchflag <= POWER_TOGGLE) { + if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT + ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < devices_present) + } + } } } } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index f0e747c27..b4b944d80 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -231,7 +231,7 @@ enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_D enum WifiConfigOptions {WIFI_RESTART, EX_WIFI_SMARTCONFIG, WIFI_MANAGER, EX_WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY, MAX_WIFI_OPTION}; -enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION}; +enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEMULTI, FOLLOWMULTI, FOLLOWMULTI_INV, MAX_SWITCH_OPTION}; enum LedStateOptions {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION}; diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index dd557a0fd..13287d009 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -563,7 +563,7 @@ void RulesEvery50ms(void) #else if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 - bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); + bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i]) || (FOLLOWMULTI_INV == Settings.switchmode[i])); snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (swm ^ SwitchLastState(i))); RulesProcessEvent(json_event); } From 6ab5c7432ec44aa8831cb2b688ad8c1b3f63eb32 Mon Sep 17 00:00:00 2001 From: to-scho Date: Wed, 15 Jan 2020 16:12:55 +0100 Subject: [PATCH 040/160] patch-1 typos --- tasmota/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 801c57acc..f22023f6a 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -225,7 +225,7 @@ #define KEY_DEBOUNCE_TIME 50 // [ButtonDebounce] Number of mSeconds button press debounce time #define KEY_HOLD_TIME 40 // [SetOption32] Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message #define SWITCH_DEBOUNCE_TIME 50 // [SwitchDebounce] Number of mSeconds switch press debounce time -#define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEHOLD, FOLLOWHOLD, FOLLOWHOLD_INV (the wall switch state) +#define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEMULTI, FOLLOWMULTI, FOLLOWMULTI_INV (the wall switch state) #define WS2812_LEDS 30 // [Pixels] Number of WS2812 LEDs to start with (max is 512) #define TEMP_CONVERSION 0 // [SetOption8] Return temperature in (0 = Celsius or 1 = Fahrenheit) From 5b797a8f4e2900952affa2667fe091ada7392ea7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 16 Jan 2020 10:39:59 +0100 Subject: [PATCH 041/160] Add new SwitchMode options Add ``SwitchMode 8`` ToggleMulti, ``SwitchMode 9`` FollowMulti and ``SwitchMode 10`` FollowMultiInverted (#7522) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/support_tasmota.ino | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index bd00d25fb..ea8b0a046 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -68,6 +68,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) - Add command ``SetOption82 0/1`` to limit the CT range for Alexa to 200..380 - Add command ``ShutterButton `` to control shutter(s) by to-scho (#7403) +- Add ``SwitchMode 8`` ToggleMulti, ``SwitchMode 9`` FollowMulti and ``SwitchMode 10`` FollowMultiInverted (#7522) - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` - Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 3df11015b..e0f9b7289 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -7,6 +7,7 @@ - Fix ``WakeUp `` ignores provided value (#7473) - Fix exception 9 restart on log message in Ticker interrupt service routines NTP, Wemos and Hue emulation (#7496) - Add support for gzipped binaries +- Add ``SwitchMode 8`` ToggleMulti, ``SwitchMode 9`` FollowMulti and ``SwitchMode 10`` FollowMultiInverted (#7522) ### 8.1.0.2 20191230 diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index ee3678ee2..1bbae6f1b 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -664,7 +664,7 @@ bool MqttShowSensor(void) #else if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 - bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); + bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i]) || (FOLLOWMULTI_INV == Settings.switchmode[i])); ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(swm ^ SwitchLastState(i))); } } From 0755ad488ebeaf77dd7009d6081d7170442f1de8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 16 Jan 2020 11:35:48 +0100 Subject: [PATCH 042/160] Bump version to 8.1.0.4 --- RELEASENOTES.md | 2 +- tasmota/CHANGELOG.md | 4 ++++ tasmota/tasmota_version.h | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ea8b0a046..277c65ddd 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,7 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.1.0.3 +### Version 8.1.0.4 - Change Lights: simplified gamma correction and 10 bits internal computation - Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index e0f9b7289..a7a88c2f8 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 8.1.0.4 20200116 + +- Bump version + ### 8.1.0.3 20200106 - Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index fab871449..1539def62 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08010003; +const uint32_t VERSION = 0x08010004; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; From a6e95211cc0b521aaa6cbdd5da1261f6b7f0980c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 16 Jan 2020 14:22:39 +0100 Subject: [PATCH 043/160] Add more web page sliders Add web page sliders when ``SetOption37 128`` is active allowing control of white(s) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 2 +- tasmota/support_command.ino | 4 ++-- tasmota/xdrv_01_webserver.ino | 43 +++++++++++++++++++++++++++-------- tasmota/xdrv_04_light.ino | 6 ++++- 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 277c65ddd..97d4a34d6 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -78,3 +78,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add experimental support for NRF24L01 as BLE-bridge for Mijia Bluetooth sensors by Christian Baars (#7394) - Add support to BMP driver to enter reset state (sleep enable) when deep sleep is used in Tasmota - Add support for gzipped binaries +- Add web page sliders when ``SetOption37 128`` is active allowing control of white(s) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index a7a88c2f8..44b9cedb0 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,7 +2,7 @@ ### 8.1.0.4 20200116 -- Bump version +- Add web page sliders when ``SetOption37 128`` is active allowing control of white(s) ### 8.1.0.3 20200106 diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index a1c38cf43..6f70e7359 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -141,8 +141,8 @@ void ExecuteCommand(const char *cmnd, uint32_t source) /********************************************************************************************/ // topicBuf: /power1 dataBuf: toggle = Console command -// topicBuf: cmnd/tasmota/power1 dataBuf: toggle = Mqtt command using topic -// topicBuf: cmnd/tasmotas/power1 dataBuf: toggle = Mqtt command using a group topic +// topicBuf: cmnd/tasmota/power1 dataBuf: toggle = Mqtt command using topic +// topicBuf: cmnd/tasmotas/power1 dataBuf: toggle = Mqtt command using a group topic // topicBuf: cmnd/DVES_83BB10_fb/power1 dataBuf: toggle = Mqtt command using fallback topic void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 40628fbb1..0873cebc5 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -984,6 +984,17 @@ void HandleWifiLogin(void) WSContentStop(); } +void WebSliderColdWarm(void) +{ + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Cold Warm + "a", // a - Unique HTML id + "#fff", "#ff0", // White to Yellow + 1, // sl1 + 153, 500, // Range color temperature + LightGetColorTemp(), + 't', 0); // t0 - Value id releated to lc("t0", value) and WebGetArg("t0", tmp, sizeof(tmp)); +} + void HandleRoot(void) { if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the page. @@ -1033,17 +1044,13 @@ void HandleRoot(void) if (light_type) { uint8_t light_subtype = light_type &7; if (!Settings.flag3.pwm_multi_channels) { // SetOption68 0 - Enable multi-channels PWM instead of Color PWM - if ((LST_COLDWARM == light_subtype) || (LST_RGBCW == light_subtype)) { + bool split_white = ((LST_RGBW <= light_subtype) && (devices_present > 1)); // Only on RGBW or RGBCW and SetOption37 128 - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Cold Warm - "a", // a - Unique HTML id - "#fff", "#ff0", // White to Yellow - 1, // sl1 - 153, 500, // Range color temperature - LightGetColorTemp(), - 't', 0); // t0 - Value id releated to lc("t0", value) and WebGetArg("t0", tmp, sizeof(tmp)); + if ((LST_COLDWARM == light_subtype) || ((LST_RGBCW == light_subtype) && !split_white)) { + WebSliderColdWarm(); } - if (light_subtype > 2) { + + if (light_subtype > 2) { // No W or CW uint16_t hue; uint8_t sat; LightGetHSB(&hue, &sat, nullptr); @@ -1079,6 +1086,19 @@ void HandleRoot(void) Settings.flag3.slider_dimmer_stay_on, 100, // Range 0/1 to 100% Settings.light_dimmer, 'd', 0); // d0 - Value id is related to lc("d0", value) and WebGetArg("d0", tmp, sizeof(tmp)); + + if (split_white) { // SetOption37 128 + if (LST_RGBCW == light_subtype) { + WebSliderColdWarm(); + } + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // White brightness - Black to White + "f", // f - Unique HTML id + "#000", "#fff", // Black to White + 5, // sl5 - Unique range HTML id - Not used + Settings.flag3.slider_dimmer_stay_on, 100, // Range 0/1 to 100% + LightGetDimmer(2), + 'w', 0); // w0 - Value id is related to lc("w0", value) and WebGetArg("w0", tmp, sizeof(tmp)); + } } else { // Settings.flag3.pwm_multi_channels - SetOption68 1 - Enable multi-channels PWM instead of Color PWM uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype; stemp[0] = 'e'; stemp[1] = '0'; stemp[2] = '\0'; // d0 @@ -1229,6 +1249,11 @@ bool HandleRootStatusRefresh(void) snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } + WebGetArg("w0", tmp, sizeof(tmp)); // 0 - 100 White value + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_WHITE " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); for (uint32_t j = 1; j <= pwm_channels; j++) { snprintf_P(webindex, sizeof(webindex), PSTR("e%d"), j); diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 0fa8838f8..019fced67 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1336,11 +1336,15 @@ void LightUpdateColorMapping(void) //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%d colors: %d %d %d %d %d") ,Settings.param[P_RGB_REMAP], Light.color_remap[0],Light.color_remap[1],Light.color_remap[2],Light.color_remap[3],Light.color_remap[4]); } +uint8_t LightGetDimmer(uint8_t dimmer) { + return light_state.getDimmer(dimmer); +} + void LightSetDimmer(uint8_t dimmer) { light_controller.changeDimmer(dimmer); } -uint32_t LightGetHSB(uint16_t *hue,uint8_t *sat, uint8_t *bri) { +void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { light_state.getHSB(hue, sat, bri); } From adb2dbbcbdcb71acab5357888914e260b4b88911 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 16 Jan 2020 14:37:10 +0100 Subject: [PATCH 044/160] Fix ColorTemp brightness --- tasmota/xdrv_04_light.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 019fced67..d217b75c7 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2351,7 +2351,7 @@ void CmndColorTemperature(void) } } if ((XdrvMailbox.payload >= CT_MIN) && (XdrvMailbox.payload <= CT_MAX)) { // https://developers.meethue.com/documentation/core-concepts - light_controller.changeCTB(XdrvMailbox.payload, light_state.getBri()); + light_controller.changeCTB(XdrvMailbox.payload, light_state.getBriCT()); LightPreparePower(2); } else { ResponseCmndNumber(ct); From 920501fef99d38c3886b26acc6db1bcb6a5fabcf Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Thu, 16 Jan 2020 15:19:57 +0000 Subject: [PATCH 045/160] Implement new Tuya multi dpid protocol. Fixes #7489 --- tasmota/xdrv_16_tuyamcu.ino | 128 ++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 57 deletions(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 18a899589..da189c568 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -413,70 +413,77 @@ void TuyaResetWifi(void) void TuyaProcessStatePacket(void) { char scmnd[20]; - uint8_t fnId = TuyaGetFuncId(Tuya.buffer[6]); + uint8_t dpidStart = 6; + uint8_t fnId; + uint16_t dpDataLen; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d is set for dpId=%d"), fnId, Tuya.buffer[6]); - // if (TuyaFuncIdValid(fnId)) { - if (Tuya.buffer[5] == 5) { // on/off packet + while (dpidStart + 4 < Tuya.byte_counter) { + dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; + fnId = TuyaGetFuncId(Tuya.buffer[dpidStart]); - if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); - if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { - ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction - } - } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); - if (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { - ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10] ^ 1, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction - } - } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[10], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d is set for dpId=%d"), fnId, Tuya.buffer[dpidStart]); + // if (TuyaFuncIdValid(fnId)) { + if (Tuya.buffer[dpidStart + 1] == 1) { // Data Type 1 - if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[10]) { - SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[10]); - SwitchHandler(1); + if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); + if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction + } + } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); + if (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4] ^ 1, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction + } + } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[dpidStart + 4], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); + + if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[dpidStart + 4]) { + SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[dpidStart + 4]); + SwitchHandler(1); + } } + } + else if (Tuya.buffer[dpidStart + 1] == 2) { // Data Type 2 + bool tuya_energy_enabled = (XNRG_16 == energy_flg); + uint16_t packetValue = Tuya.buffer[dpidStart + 6] << 8 | Tuya.buffer[dpidStart + 7]; + if (fnId == TUYA_MCU_FUNC_DIMMER) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), packetValue); + Tuya.new_dim = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100); + if ((power || Settings.flag3.tuya_apply_o20) && // SetOption54 - Apply SetOption20 settings to Tuya device + (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { + Tuya.ignore_dim = true; - } - else if (Tuya.buffer[5] == 8) { // Long value packet - bool tuya_energy_enabled = (XNRG_16 == energy_flg); - uint16_t packetValue = Tuya.buffer[12] << 8 | Tuya.buffer[13]; - if (fnId == TUYA_MCU_FUNC_DIMMER) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), packetValue); - Tuya.new_dim = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100); - if ((power || Settings.flag3.tuya_apply_o20) && // SetOption54 - Apply SetOption20 settings to Tuya device - (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { - Tuya.ignore_dim = true; - - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); - ExecuteCommand(scmnd, SRC_SWITCH); + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); + ExecuteCommand(scmnd, SRC_SWITCH); + } } - } -#ifdef USE_ENERGY_SENSOR - else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { - Energy.voltage[0] = (float)packetValue / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[6], packetValue); - } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { - Energy.current[0] = (float)packetValue / 1000; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[6], packetValue); - } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { - Energy.active_power[0] = (float)packetValue / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[6], packetValue); + #ifdef USE_ENERGY_SENSOR + else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { + Energy.voltage[0] = (float)packetValue / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[dpidStart], packetValue); + } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { + Energy.current[0] = (float)packetValue / 1000; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[dpidStart], packetValue); + } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { + Energy.active_power[0] = (float)packetValue / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[dpidStart], packetValue); - if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) { - Energy.kWhtoday += (float)Energy.active_power[0] * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; - EnergyUpdateToday(); + if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) { + Energy.kWhtoday += (float)Energy.active_power[0] * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; + EnergyUpdateToday(); + } + Tuya.lastPowerCheckTime = Rtc.utc_time; } - Tuya.lastPowerCheckTime = Rtc.utc_time; - } -#endif // USE_ENERGY_SENSOR + #endif // USE_ENERGY_SENSOR - } - // } else { - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Unknown FnId=%s for dpId=%s"), fnId, Tuya.buffer[6]); - // } + } + // } else { + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Unknown FnId=%s for dpId=%s"), fnId, Tuya.buffer[6]); + dpidStart += dpDataLen + 4; + } } void TuyaLowPowerModePacketProcess(void) { @@ -671,10 +678,17 @@ void TuyaSerialInput(void) if (len > 0) { ResponseAppend_P(PSTR(",\"CmndData\":\"%s\""), ToHex_P((unsigned char*)&Tuya.buffer[6], len, hex_char, sizeof(hex_char))); if (TUYA_CMD_STATE == Tuya.buffer[3]) { - uint16_t dpDataLen = Tuya.buffer[8] << 8 | Tuya.buffer[9]; - ResponseAppend_P(PSTR(",\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), Tuya.buffer[6], Tuya.buffer[7], ToHex_P((unsigned char*)&Tuya.buffer[10], dpDataLen, hex_char, sizeof(hex_char))); - if (TUYA_TYPE_STRING == Tuya.buffer[7]) { - ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, (char *)&Tuya.buffer[10]); + //55 AA 03 07 00 0D 01 04 00 01 02 02 02 00 04 00 00 00 1A 40 + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + uint8_t dpidStart = 6; + while (dpidStart + 4 < Tuya.byte_counter) { + uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; + ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), Tuya.buffer[dpidStart], Tuya.buffer[dpidStart], Tuya.buffer[dpidStart + 1], ToHex_P((unsigned char*)&Tuya.buffer[dpidStart + 4], dpDataLen, hex_char, sizeof(hex_char))); + if (TUYA_TYPE_STRING == Tuya.buffer[dpidStart + 1]) { + ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, (char *)&Tuya.buffer[dpidStart + 4]); + } + ResponseAppend_P(PSTR("}")); + dpidStart += dpDataLen + 4; } } } From 65d1f3aacedb9dfe9b9cb32fde40de762beda4f5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 17 Jan 2020 10:12:57 +0100 Subject: [PATCH 046/160] Fix PowerDelta calculation Fix PowerDelta calculation not detecting zero power (#7515) --- tasmota/xdrv_03_energy.ino | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index 900bb2767..166fd7aa8 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -289,14 +289,19 @@ void EnergyMarginCheck(void) if (Settings.energy_power_delta) { uint16_t delta = abs(Energy.power_history[0] - energy_power_u); - uint16_t min_power = (Energy.power_history[0] > energy_power_u) ? energy_power_u : Energy.power_history[0]; - - DEBUG_DRIVER_LOG(PSTR("NRG: Delta %d, Power %d"), delta, min_power); - - if ((delta > 0) && (min_power > 0)) { // Fix divide by 0 exception (#6741) - if (((Settings.energy_power_delta < 101) && (((delta * 100) / min_power) > Settings.energy_power_delta)) || // 1..100 = Percentage - ((Settings.energy_power_delta > 100) && (delta > (Settings.energy_power_delta -100)))) { // 101..32000 = Absolute - Energy.power_delta = true; + if (delta > 0) { + if (Settings.energy_power_delta < 101) { // 1..100 = Percentage + uint16_t min_power = (Energy.power_history[0] > energy_power_u) ? energy_power_u : Energy.power_history[0]; + if (0 == min_power) { min_power++; } // Fix divide by 0 exception (#6741) + if (((delta * 100) / min_power) > Settings.energy_power_delta) { + Energy.power_delta = true; + } + } else { // 101..32000 = Absolute + if (delta > (Settings.energy_power_delta -100)) { + Energy.power_delta = true; + } + } + if (Energy.power_delta) { Energy.power_history[1] = Energy.active_power[0]; // We only want one report so reset history Energy.power_history[2] = Energy.active_power[0]; } From e8ce1eb64111d7ff061fad7835da2b30f6772d69 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 17 Jan 2020 15:38:03 +0100 Subject: [PATCH 047/160] Fix OTA minimal gzipped detection Fix OTA minimal gzipped detection regression from 8.1.0.3 --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 2 ++ tasmota/support_tasmota.ino | 17 +++++++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 97d4a34d6..ce6c4963f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -65,6 +65,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix Display handling of hexadecimal escape characters (#7387) - Fix ``WakeUp `` ignores provided value (#7473) - Fix exception 9 restart on log message in Ticker interrupt service routines NTP, Wemos and Hue emulation (#7496) +- Fix ``PowerDelta`` zero power detection (#7515) - Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) - Add command ``SetOption82 0/1`` to limit the CT range for Alexa to 200..380 - Add command ``ShutterButton `` to control shutter(s) by to-scho (#7403) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 44b9cedb0..e1d562772 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,6 +2,8 @@ ### 8.1.0.4 20200116 +- Fix ``PowerDelta`` zero power detection (#7515) +- Fix OTA minimal gzipped detection regression from 8.1.0.3 - Add web page sliders when ``SetOption37 128`` is active allowing control of white(s) ### 8.1.0.3 20200106 diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 1bbae6f1b..2fc83f53d 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -887,14 +887,19 @@ void Every250mSeconds(void) if (RtcSettings.ota_loader) { char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it char *pch = strrchr((bch != nullptr) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin -// char *ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin - char *ech = strchr((bch != nullptr) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin or filename.bin.gz into filename-minimal.bin.gz - if (!pch) { pch = ech; } + char *ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Find file type (none, .bin or .bin.gz) + if ((ech != nullptr) && (0 == strncasecmp_P(ech, PSTR(".GZ"), 3))) { + char *fch = ech; + *fch = '\0'; + ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Find file type .bin.gz + *fch = '.'; + } + char ota_url_type[strlen(ech) +1]; + strncpy(ota_url_type, ech, sizeof(ota_url_type)); // Either nothing, .bin or .bin.gz + if (pch == nullptr) { pch = ech; } if (pch) { mqtt_data[pch - mqtt_data] = '\0'; -// char *ech = strrchr(SettingsText(SET_OTAURL), '.'); // Change from filename.bin into filename-minimal.bin - char *ech = strchr(SettingsText(SET_OTAURL), '.'); // Change from filename.bin into filename-minimal.bin - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ech); // Minimal filename must be filename-minimal + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ota_url_type); // Minimal filename must be filename-minimal } } #endif // FIRMWARE_MINIMAL From 400d4a0604f254d88f8e5257f075e1e86020251e Mon Sep 17 00:00:00 2001 From: Staars Date: Fri, 17 Jan 2020 16:44:43 +0100 Subject: [PATCH 048/160] add virtual serial port via TCP --- tasmota/xsns_60_GPS.ino | 79 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/tasmota/xsns_60_GPS.ino b/tasmota/xsns_60_GPS.ino index 13cfebdbd..42ef9949b 100644 --- a/tasmota/xsns_60_GPS.ino +++ b/tasmota/xsns_60_GPS.ino @@ -23,6 +23,8 @@ Version Date Action Description -------------------------------------------------------------------------------------------- + 0.9.2.0 20200110 integrate - Added UART-over-TCP/IP-bridge (virtual serial port). Minor tweaks. + --- 0.9.1.0 20191216 integrate - Added pin specifications from Tasmota WEB UI. Minor tweaks. --- 0.9.0.0 20190817 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota @@ -38,11 +40,11 @@ Driver is tested on a NEO-6m and a Beitian-220. Series 7 should work too. This a - can log postion data with timestamp to flash with a small memory footprint of only 12 Bytes per record - constructs a GPX-file for download of this data - Web-UI -- simplified NTP-server +- simplified NTP-server and UART-over-TCP/IP-bridge (virtual serial port) - command interface ## Usage: -The serial pins are GPX_RX and GPS_TX, no further installation steps needed. To get more debug information compile it with option "DEBUG_TASMOTA_SENSOR". +The serial pins are GPS_RX and GPS_TX, no further installation steps needed. To get more debug information compile it with option "DEBUG_TASMOTA_SENSOR". ## Commands: @@ -89,7 +91,11 @@ The serial pins are GPX_RX and GPS_TX, no further installation steps needed. To + sensor60 13 set latitude and longitude in settings ++ sensor60 14 + open virtual serial port over TCP, usable for u-center ++ sensor60 15 + pause virtual serial port over TCP ## Rules examples for SSD1306 32x128 @@ -119,6 +125,9 @@ const char kUBXTypes[] PROGMEM = "UBX"; #define UBX_LAT_LON_THRESHOLD 1000 // filter out some noise of local drift +#define UBX_SERIAL_BUFFER_SIZE 256 +#define UBX_TCP_PORT 1234 + /********************************************************************************************\ | *globals \*********************************************************************************************/ @@ -252,6 +261,7 @@ struct UBX_t { uint32_t send_UI_only:1; uint32_t runningNTP:1; uint32_t forceUTCupdate:1; + uint32_t runningVPort:1; // TODO: more to come } mode; @@ -280,6 +290,9 @@ TasmotaSerial *UBXSerial; NtpServer timeServer(PortUdp); +WiFiServer vPortServer(UBX_TCP_PORT); +WiFiClient vPortClient; + /*********************************************************************************************\ * helper function \*********************************************************************************************/ @@ -324,7 +337,7 @@ void UBXDetect(void) { UBX.mode.init = 0; if ((pin[GPIO_GPS_RX] < 99) && (pin[GPIO_GPS_TX] < 99)) { - UBXSerial = new TasmotaSerial(pin[GPIO_GPS_RX], pin[GPIO_GPS_TX], 1, 0, 96); // 64 byte buffer is NOT enough + UBXSerial = new TasmotaSerial(pin[GPIO_GPS_RX], pin[GPIO_GPS_TX], 1, 0, UBX_SERIAL_BUFFER_SIZE); // 64 byte buffer is NOT enough if (UBXSerial->begin(9600)) { DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); if (UBXSerial->hardwareSerial()) { @@ -575,6 +588,14 @@ void UBXSelectMode(uint16_t mode) Settings.latitude = UBX.state.last_lat; Settings.longitude = UBX.state.last_lon; break; + case 14: + vPortServer.begin(); + UBX.mode.runningVPort = 1; + break; + case 15: + // vPortServer.stop(); // seems not to work reliably + UBX.mode.runningVPort = 0; + break; default: if (mode>1000 && mode <1066) { // UBXSetRate(mode-1000); // min. 1001 = 0.001 Hz, but will be converted to 1/65535 anyway ~0.015 Hz, max. 2000 = 1.000 Hz @@ -629,7 +650,7 @@ void UBXHandleSTATUS() void UBXHandleTIME() { DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time: %u-%u-%u %u:%u:%u"), UBX.Message.navTime.year, UBX.Message.navTime.month ,UBX.Message.navTime.day,UBX.Message.navTime.hour,UBX.Message.navTime.min,UBX.Message.navTime.sec); - if (UBX.Message.navTime.valid.UTC) { + if (UBX.Message.navTime.valid.UTC == 1) { DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time is valid")); if (Rtc.user_time_entry == false || UBX.mode.forceUTCupdate) { AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time")); @@ -649,6 +670,7 @@ void UBXHandleTIME() void UBXHandleOther(void) { if (UBX.state.non_empty_loops>6) { // we expect only 4-5 non-empty loops in a row, could change with other sensor speed (Hz) + if(UBX.mode.runningVPort) return; UBXinitCFG(); // this should only happen with lots of NMEA-messages, but it is only a guess!! AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); UBXSerial->flush(); @@ -658,8 +680,49 @@ void UBXHandleOther(void) /********************************************************************************************/ +void UBXhandleVPort(){ + static uint32_t idx = 0; + static uint8_t buf[UBX_SERIAL_BUFFER_SIZE]; + // static uint32_t tBufMax = 0; + // static uint32_t sBufMax = 0; + + if(!vPortClient.connected()) { + vPortClient = vPortServer.available(); + } + + while(vPortClient.available()) { + buf[idx] = (uint8_t)vPortClient.read(); + if(idxwrite(buf, idx); + // if(idx>tBufMax) { + // tBufMax = idx; + // AddLog_P2(LOG_LEVEL_INFO, PSTR("VPORT: new max. tcp buffer size: %u"),tBufMax); + // } + } + idx = 0; + + while(UBXSerial->available()) { + buf[idx] = (char)UBXSerial->read(); + if(idxsBufMax) { + // sBufMax = idx; + // AddLog_P2(LOG_LEVEL_INFO, PSTR("VPORT: new max. serial buffer size: %u"),sBufMax); + // } + } + idx = 0; +} + void UBXTimeServer() { + if(UBX.mode.runningVPort){ + UBXhandleVPort(); + return; + } if(UBX.mode.runningNTP){ timeServer.processOneRequest(Rtc.utc_time, UBX.state.last_iTOW%1000); } @@ -670,6 +733,10 @@ void UBXLoop(void) static uint16_t counter; //count up every 100 msec static bool new_position; + if(UBX.mode.runningVPort) { + return; + } + uint32_t msgType = UBXprocessGPS(); switch(msgType){ @@ -832,7 +899,7 @@ bool Xsns60(uint8_t function) } break; case FUNC_EVERY_50_MSECOND: - UBXTimeServer(); + UBXTimeServer(); // handles virtual serial port too break; case FUNC_EVERY_100_MSECOND: #ifdef USE_FLOG @@ -865,4 +932,4 @@ bool Xsns60(uint8_t function) return result; } -#endif // USE_GPS +#endif // USE_GPS \ No newline at end of file From 330d41a4f10e28b60710ddd1e1c6889aa96a1d5f Mon Sep 17 00:00:00 2001 From: Hadinger Date: Fri, 17 Jan 2020 17:09:51 +0100 Subject: [PATCH 049/160] Sync with latest BearSSL --- lib/bearssl-esp8266/src/t_bearssl_ec.h | 2 +- lib/bearssl-esp8266/src/t_bearssl_ssl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/bearssl-esp8266/src/t_bearssl_ec.h b/lib/bearssl-esp8266/src/t_bearssl_ec.h index 660bd5186..fbe69cc02 100644 --- a/lib/bearssl-esp8266/src/t_bearssl_ec.h +++ b/lib/bearssl-esp8266/src/t_bearssl_ec.h @@ -108,7 +108,7 @@ extern "C" { * * - The multipliers (integers) MUST be lower than the subgroup order. * If this property is not met, then the result is indeterminate, - * but an error value is not ncessearily returned. + * but an error value is not necessarily returned. * * * ## ECDSA diff --git a/lib/bearssl-esp8266/src/t_bearssl_ssl.h b/lib/bearssl-esp8266/src/t_bearssl_ssl.h index 8cd42d9f4..df0d44f08 100644 --- a/lib/bearssl-esp8266/src/t_bearssl_ssl.h +++ b/lib/bearssl-esp8266/src/t_bearssl_ssl.h @@ -2114,7 +2114,7 @@ void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len); /** * \brief Get buffer for received application data. * - * If the engine has received application data from the peer, hen this + * If the engine has received application data from the peer, then this * call returns a pointer to the buffer from where such data shall be * read, and its length is written in `*len`. Otherwise, `*len` is set * to 0 and `NULL` is returned. From be5c7a43671a2ddad8316bdb7ded1553ba882358 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 17 Jan 2020 17:14:53 +0100 Subject: [PATCH 050/160] Document and add errorchecks to OTA Document and add errorchecks to OTA --- tasmota/support_tasmota.ino | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 2fc83f53d..1cb3aae8b 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -885,22 +885,36 @@ void Every250mSeconds(void) strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); #ifndef FIRMWARE_MINIMAL if (RtcSettings.ota_loader) { - char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it - char *pch = strrchr((bch != nullptr) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin - char *ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Find file type (none, .bin or .bin.gz) + // OTA File too large so try OTA minimal version + // Replace tasmota with tasmota-minimal + // Replace tasmota-DE with tasmota-minimal + // Replace tasmota.bin with tasmota-minimal.bin + // Replace tasmota.xyz with tasmota-minimal.xyz + // Replace tasmota.bin.gz with tasmota-minimal.bin.gz + // Replace tasmota.xyz.gz with tasmota-minimal.xyz.gz + // Replace http://domus1:80/api/arduino/tasmota.bin with http://domus1:80/api/arduino/tasmota-minimal.bin + // Replace http://domus1:80/api/arduino/tasmota.bin.gz with http://domus1:80/api/arduino/tasmota-minimal.bin.gz + // Replace http://domus1:80/api/arduino/tasmota-DE.bin.gz with http://domus1:80/api/arduino/tasmota-minimal.bin.gz + // Replace http://domus1:80/api/ard-uino/tasmota-DE.bin.gz with http://domus1:80/api/ard-uino/tasmota-minimal.bin.gz + + char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it + if (bch == nullptr) { bch = mqtt_data; } // No path found so use filename only + + char *ech = strrchr(bch, '.'); // Find file type in filename (none, .bin or .gz) if ((ech != nullptr) && (0 == strncasecmp_P(ech, PSTR(".GZ"), 3))) { char *fch = ech; *fch = '\0'; - ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Find file type .bin.gz + ech = strrchr(bch, '.'); // Find file type .bin.gz *fch = '.'; } + if (ech == nullptr) { ech = mqtt_data + strlen(mqtt_data); } char ota_url_type[strlen(ech) +1]; - strncpy(ota_url_type, ech, sizeof(ota_url_type)); // Either nothing, .bin or .bin.gz - if (pch == nullptr) { pch = ech; } - if (pch) { - mqtt_data[pch - mqtt_data] = '\0'; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ota_url_type); // Minimal filename must be filename-minimal - } + strncpy(ota_url_type, ech, sizeof(ota_url_type)); // Either empty, .bin or .bin.gz + + char *pch = strrchr(bch, '-'); // Find last dash (-) and ignore remainder - handles tasmota-DE + if (pch == nullptr) { pch = ech; } // No dash so ignore filetype + *pch = '\0'; // mqtt_data = http://domus1:80/api/arduino/tasmota + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ota_url_type); // Minimal filename must be filename-minimal } #endif // FIRMWARE_MINIMAL AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); From 50a25aeb7c52c9154e4f0f9735d57fe14a38eeb6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 17 Jan 2020 17:51:27 +0100 Subject: [PATCH 051/160] Experimental DS18x20 for Shelly Experimental DS18x20 for Shelly (#7469) --- tasmota/xsns_05_ds18x20_shelly.ino | 463 +++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 tasmota/xsns_05_ds18x20_shelly.ino diff --git a/tasmota/xsns_05_ds18x20_shelly.ino b/tasmota/xsns_05_ds18x20_shelly.ino new file mode 100644 index 000000000..f8ddcc58d --- /dev/null +++ b/tasmota/xsns_05_ds18x20_shelly.ino @@ -0,0 +1,463 @@ +/* + xsns_05_ds18x20.ino - DS18x20 temperature sensor support for Tasmota + + Copyright (C) 2020 Theo Arends + + 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 . +*/ + +#ifdef USE_DS18x20SHELLY +/*********************************************************************************************\ + * DS18B20 - Temperature - Multiple sensors +\*********************************************************************************************/ + +#define XSNS_05 5 + +//#define USE_DS18x20_RECONFIGURE // When sensor is lost keep retrying or re-configure + +#define DS18S20_CHIPID 0x10 // +/-0.5C 9-bit +#define DS1822_CHIPID 0x22 // +/-2C 12-bit +#define DS18B20_CHIPID 0x28 // +/-0.5C 12-bit +#define MAX31850_CHIPID 0x3B // +/-0.25C 14-bit + +#define W1_SKIP_ROM 0xCC +#define W1_CONVERT_TEMP 0x44 +#define W1_WRITE_EEPROM 0x48 +#define W1_WRITE_SCRATCHPAD 0x4E +#define W1_READ_SCRATCHPAD 0xBE + +#define DS18X20_MAX_SENSORS 8 + +const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850"; + +uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID, MAX31850_CHIPID }; + +struct DS18X20STRUCT { + uint8_t address[8]; + uint8_t index; + uint8_t valid; + float temperature; +} ds18x20_sensor[DS18X20_MAX_SENSORS]; +uint8_t ds18x20_sensors = 0; +uint8_t ds18x20_pin_in = 3; // Shelly GPIO03 +uint8_t ds18x20_pin_out = 0; // Shelly GPIO02 +char ds18x20_types[12]; + +/*********************************************************************************************\ + * Embedded tuned OneWire library +\*********************************************************************************************/ + +#define W1_MATCH_ROM 0x55 +#define W1_SEARCH_ROM 0xF0 + +uint8_t onewire_last_discrepancy = 0; +uint8_t onewire_last_family_discrepancy = 0; +bool onewire_last_device_flag = false; +unsigned char onewire_rom_id[8] = { 0 }; + +uint8_t OneWireReset(void) +{ + uint8_t retries = 125; + + //noInterrupts(); + pinMode(ds18x20_pin_in, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); // SetOption74 - Enable internal pullup for single DS18x20 sensor + do { + if (--retries == 0) { + return 0; + } + delayMicroseconds(2); + } while (!digitalRead(ds18x20_pin_in)); + pinMode(ds18x20_pin_out, OUTPUT); + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(480); + pinMode(ds18x20_pin_in, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); // SetOption74 - Enable internal pullup for single DS18x20 sensor + delayMicroseconds(70); + uint8_t r = !digitalRead(ds18x20_pin_in); + //interrupts(); + delayMicroseconds(410); + return r; +} + +void OneWireWriteBit(uint8_t v) +{ + static const uint8_t delay_low[2] = { 65, 10 }; + static const uint8_t delay_high[2] = { 5, 55 }; + + v &= 1; + //noInterrupts(); + digitalWrite(ds18x20_pin_out, LOW); + pinMode(ds18x20_pin_out, OUTPUT); + delayMicroseconds(delay_low[v]); + digitalWrite(ds18x20_pin_out, HIGH); + //interrupts(); + delayMicroseconds(delay_high[v]); +} + +uint8_t OneWireReadBit(void) +{ + //noInterrupts(); + pinMode(ds18x20_pin_out, OUTPUT); + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(3); + pinMode(ds18x20_pin_in, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); // SetOption74 - Enable internal pullup for single DS18x20 sensor + delayMicroseconds(10); + uint8_t r = digitalRead(ds18x20_pin_in); + //interrupts(); + delayMicroseconds(53); + return r; +} + +void OneWireWrite(uint8_t v) +{ + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + OneWireWriteBit((bit_mask & v) ? 1 : 0); + } +} + +uint8_t OneWireRead(void) +{ + uint8_t r = 0; + + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + if (OneWireReadBit()) { + r |= bit_mask; + } + } + return r; +} + +void OneWireSelect(const uint8_t rom[8]) +{ + OneWireWrite(W1_MATCH_ROM); + for (uint32_t i = 0; i < 8; i++) { + OneWireWrite(rom[i]); + } +} + +void OneWireResetSearch(void) +{ + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + for (uint32_t i = 0; i < 8; i++) { + onewire_rom_id[i] = 0; + } +} + +uint8_t OneWireSearch(uint8_t *newAddr) +{ + uint8_t id_bit_number = 1; + uint8_t last_zero = 0; + uint8_t rom_byte_number = 0; + uint8_t search_result = 0; + uint8_t id_bit; + uint8_t cmp_id_bit; + unsigned char rom_byte_mask = 1; + unsigned char search_direction; + + if (!onewire_last_device_flag) { + if (!OneWireReset()) { + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + return false; + } + OneWireWrite(W1_SEARCH_ROM); + do { + id_bit = OneWireReadBit(); + cmp_id_bit = OneWireReadBit(); + + if ((id_bit == 1) && (cmp_id_bit == 1)) { + break; + } else { + if (id_bit != cmp_id_bit) { + search_direction = id_bit; + } else { + if (id_bit_number < onewire_last_discrepancy) { + search_direction = ((onewire_rom_id[rom_byte_number] & rom_byte_mask) > 0); + } else { + search_direction = (id_bit_number == onewire_last_discrepancy); + } + if (search_direction == 0) { + last_zero = id_bit_number; + if (last_zero < 9) { + onewire_last_family_discrepancy = last_zero; + } + } + } + if (search_direction == 1) { + onewire_rom_id[rom_byte_number] |= rom_byte_mask; + } else { + onewire_rom_id[rom_byte_number] &= ~rom_byte_mask; + } + OneWireWriteBit(search_direction); + id_bit_number++; + rom_byte_mask <<= 1; + if (rom_byte_mask == 0) { + rom_byte_number++; + rom_byte_mask = 1; + } + } + } while (rom_byte_number < 8); + if (!(id_bit_number < 65)) { + onewire_last_discrepancy = last_zero; + if (onewire_last_discrepancy == 0) { + onewire_last_device_flag = true; + } + search_result = true; + } + } + if (!search_result || !onewire_rom_id[0]) { + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + search_result = false; + } + for (uint32_t i = 0; i < 8; i++) { + newAddr[i] = onewire_rom_id[i]; + } + return search_result; +} + +bool OneWireCrc8(uint8_t *addr) +{ + uint8_t crc = 0; + uint8_t len = 8; + + while (len--) { + uint8_t inbyte = *addr++; // from 0 to 7 + for (uint32_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x01; + crc >>= 1; + if (mix) { + crc ^= 0x8C; + } + inbyte >>= 1; + } + } + return (crc == *addr); // addr 8 +} + +/********************************************************************************************/ + +void Ds18x20Init(void) +{ + uint64_t ids[DS18X20_MAX_SENSORS]; + +// ds18x20_pin = pin[GPIO_DSB]; + + OneWireResetSearch(); + + ds18x20_sensors = 0; + while (ds18x20_sensors < DS18X20_MAX_SENSORS) { + if (!OneWireSearch(ds18x20_sensor[ds18x20_sensors].address)) { + break; + } + if (OneWireCrc8(ds18x20_sensor[ds18x20_sensors].address) && + ((ds18x20_sensor[ds18x20_sensors].address[0] == DS18S20_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == DS1822_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == DS18B20_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == MAX31850_CHIPID))) { + ds18x20_sensor[ds18x20_sensors].index = ds18x20_sensors; + ids[ds18x20_sensors] = ds18x20_sensor[ds18x20_sensors].address[0]; // Chip id + for (uint32_t j = 6; j > 0; j--) { + ids[ds18x20_sensors] = ids[ds18x20_sensors] << 8 | ds18x20_sensor[ds18x20_sensors].address[j]; + } + ds18x20_sensors++; + } + } + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + for (uint32_t j = i + 1; j < ds18x20_sensors; j++) { + if (ids[ds18x20_sensor[i].index] > ids[ds18x20_sensor[j].index]) { // Sort ascending + std::swap(ds18x20_sensor[i].index, ds18x20_sensor[j].index); + } + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); +} + +void Ds18x20Convert(void) +{ + OneWireReset(); + OneWireWrite(W1_SKIP_ROM); // Address all Sensors on Bus + OneWireWrite(W1_CONVERT_TEMP); // start conversion, no parasite power on at the end +// delay(750); // 750ms should be enough for 12bit conv +} + +bool Ds18x20Read(uint8_t sensor) +{ + uint8_t data[9]; + int8_t sign = 1; + + uint8_t index = ds18x20_sensor[sensor].index; + if (ds18x20_sensor[index].valid) { ds18x20_sensor[index].valid--; } + for (uint32_t retry = 0; retry < 3; retry++) { + OneWireReset(); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_READ_SCRATCHPAD); + for (uint32_t i = 0; i < 9; i++) { + data[i] = OneWireRead(); + } + if (OneWireCrc8(data)) { + switch(ds18x20_sensor[index].address[0]) { + case DS18S20_CHIPID: { + if (data[1] > 0x80) { + data[0] = (~data[0]) +1; + sign = -1; // App-Note fix possible sign error + } + float temp9 = (float)(data[0] >> 1) * sign; + ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + case DS1822_CHIPID: + case DS18B20_CHIPID: { + if (data[4] != 0x7F) { + data[4] = 0x7F; // Set resolution to 12-bit + OneWireReset(); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_WRITE_SCRATCHPAD); + OneWireWrite(data[2]); // Th Register + OneWireWrite(data[3]); // Tl Register + OneWireWrite(data[4]); // Configuration Register + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_WRITE_EEPROM); // Save scratchpad to EEPROM + } + uint16_t temp12 = (data[1] << 8) + data[0]; + if (temp12 > 2047) { + temp12 = (~temp12) +1; + sign = -1; + } + ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); // Divide by 16 + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + case MAX31850_CHIPID: { + int16_t temp14 = (data[1] << 8) + (data[0] & 0xFC); + ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); // Divide by 16 + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + } + } + } + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); + return false; +} + +void Ds18x20Name(uint8_t sensor) +{ + uint8_t index = sizeof(ds18x20_chipids); + while (index) { + if (ds18x20_sensor[ds18x20_sensor[sensor].index].address[0] == ds18x20_chipids[index]) { + break; + } + index--; + } + GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types); + if (ds18x20_sensors > 1) { + snprintf_P(ds18x20_types, sizeof(ds18x20_types), PSTR("%s%c%d"), ds18x20_types, IndexSeparator(), sensor +1); + } +} + +/********************************************************************************************/ + +void Ds18x20EverySecond(void) +{ + if (uptime & 1) { + // 2mS + Ds18x20Convert(); // Start conversion, takes up to one second + } else { + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + // 12mS per device + if (!Ds18x20Read(i)) { // Read temperature + Ds18x20Name(i); + AddLogMissed(ds18x20_types, ds18x20_sensor[ds18x20_sensor[i].index].valid); +#ifdef USE_DS18x20_RECONFIGURE + if (!ds18x20_sensor[ds18x20_sensor[i].index].valid) { + memset(&ds18x20_sensor, 0, sizeof(ds18x20_sensor)); + Ds18x20Init(); // Re-configure + } +#endif // USE_DS18x20_RECONFIGURE + } + } + } +} + +void Ds18x20Show(bool json) +{ + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + uint8_t index = ds18x20_sensor[i].index; + + if (ds18x20_sensor[index].valid) { // Check for valid temperature + char temperature[33]; + dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature); + + Ds18x20Name(i); + + if (json) { + char address[17]; + for (uint32_t j = 0; j < 6; j++) { + sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); // Skip sensor type and crc + } + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif // USE_DOMOTICZ +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, ds18x20_sensor[index].temperature); + } +#endif // USE_KNX +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, ds18x20_types, temperature, TempUnit()); +#endif // USE_WEBSERVER + } + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns05(uint8_t function) +{ + bool result = false; + +// if (pin[GPIO_DSB] < 99) { + switch (function) { + case FUNC_INIT: + Ds18x20Init(); + break; + case FUNC_EVERY_SECOND: + Ds18x20EverySecond(); + break; + case FUNC_JSON_APPEND: + Ds18x20Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ds18x20Show(0); + break; +#endif // USE_WEBSERVER + } +// } + return result; +} + +#endif // USE_DS18x20SHELLY From 18ce64f8137226af843997c6a788ffddf75e83d1 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 18 Jan 2020 00:02:01 +0100 Subject: [PATCH 052/160] Add Zigbee persistence and friendly names --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 3 + tasmota/settings.h | 4 +- tasmota/support_static_buffer.ino | 29 +- tasmota/xdrv_02_mqtt.ino | 6 +- tasmota/xdrv_23_zigbee_3_devices.ino | 265 ++++++++++++++--- tasmota/xdrv_23_zigbee_4_persistence.ino | 332 ++++++++++++++++++++++ tasmota/xdrv_23_zigbee_5_converters.ino | 8 +- tasmota/xdrv_23_zigbee_7_statemachine.ino | 3 +- tasmota/xdrv_23_zigbee_8_parsers.ino | 24 +- tasmota/xdrv_23_zigbee_9_impl.ino | 92 ++++-- 11 files changed, 704 insertions(+), 63 deletions(-) create mode 100644 tasmota/xdrv_23_zigbee_4_persistence.ino diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index e1d562772..ccffecfdc 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,6 +5,7 @@ - Fix ``PowerDelta`` zero power detection (#7515) - Fix OTA minimal gzipped detection regression from 8.1.0.3 - Add web page sliders when ``SetOption37 128`` is active allowing control of white(s) +- Add Zigbee persistence and friendly names ### 8.1.0.3 20200106 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 0dece041a..20207bcb4 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -480,7 +480,10 @@ #define D_JSON_ZIGBEEZCL_RAW_RECEIVED "ZigbeeZCLRawReceived" #define D_JSON_ZIGBEE_DEVICE "Device" #define D_JSON_ZIGBEE_NAME "Name" +#define D_CMND_ZIGBEE_NAME "ZigbeeName" #define D_CMND_ZIGBEE_PROBE "ZigbeeProbe" +#define D_CMND_ZIGBEE_FORGET "ZigbeeForget" +#define D_CMND_ZIGBEE_SAVE "ZigbeeSave" #define D_CMND_ZIGBEE_RECEIVED "ZigbeeReceived" #define D_CMND_ZIGBEE_LINKQUALITY "LinkQuality" #define D_CMND_ZIGBEE_READ "ZigbeeRead" diff --git a/tasmota/settings.h b/tasmota/settings.h index 684ab18af..74023ff60 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -101,8 +101,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... uint32_t data; // Allow bit manipulation using SetOption struct { // SetOption82 .. SetOption113 - uint32_t alexa_ct_range : 1; // bit 0 (v8.1.0.2) - SetOption82 - Reduced CT range for Alexa - uint32_t spare01 : 1; + uint32_t alexa_ct_range : 1; // bit 0 (v8.1.0.2) - SetOption82 - Reduced CT range for Alexa + uint32_t zigbee_use_names : 1; // bit 1 (V8.1.0.4) - SetOption83 - Use FriendlyNames instead of ShortAddresses when possible uint32_t spare02 : 1; uint32_t spare03 : 1; uint32_t spare04 : 1; diff --git a/tasmota/support_static_buffer.ino b/tasmota/support_static_buffer.ino index 512ec0db1..bec831cc9 100644 --- a/tasmota/support_static_buffer.ino +++ b/tasmota/support_static_buffer.ino @@ -80,7 +80,7 @@ public: return _buf->len; } size_t add32(const uint32_t data) { // append 32 bits value - if (_buf->len < _buf->size - 3) { // do we have room for 2 bytes + if (_buf->len < _buf->size - 3) { // do we have room for 4 bytes _buf->buf[_buf->len++] = data; _buf->buf[_buf->len++] = data >> 8; _buf->buf[_buf->len++] = data >> 16; @@ -88,6 +88,19 @@ public: } return _buf->len; } + size_t add64(const uint64_t data) { // append 64 bits value + if (_buf->len < _buf->size - 7) { // do we have room for 8 bytes + _buf->buf[_buf->len++] = data; + _buf->buf[_buf->len++] = data >> 8; + _buf->buf[_buf->len++] = data >> 16; + _buf->buf[_buf->len++] = data >> 24; + _buf->buf[_buf->len++] = data >> 32; + _buf->buf[_buf->len++] = data >> 40; + _buf->buf[_buf->len++] = data >> 48; + _buf->buf[_buf->len++] = data >> 56; + } + return _buf->len; + } size_t addBuffer(const SBuffer &buf2) { if (len() + buf2.len() <= size()) { @@ -152,6 +165,20 @@ public: return 0; } + // if no NULL is found, returns length until the end of the buffer + inline size_t strlen(const size_t offset) const { + return strnlen((const char*) &_buf->buf[offset], len() - offset); + } + + size_t strlen_s(const size_t offset) const { + size_t slen = this->strlen(offset); + if (slen == len() - offset) { + return 0; // we didn't find a NULL char + } else { + return slen; + } + } + SBuffer subBuffer(const size_t start, size_t len) const { if (start >= _buf->len) { len = 0; diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 6096103c4..799829fe6 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -986,8 +986,10 @@ void CmndSensorRetain(void) \*********************************************************************************************/ #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) -const static uint16_t tls_spi_start_sector = SPIFFS_END + 4; // 0xXXFF -const static uint8_t* tls_spi_start = (uint8_t*) ((tls_spi_start_sector * SPI_FLASH_SEC_SIZE) + 0x40200000); // 0x40XFF000 +// const static uint16_t tls_spi_start_sector = SPIFFS_END + 4; // 0xXXFF +// const static uint8_t* tls_spi_start = (uint8_t*) ((tls_spi_start_sector * SPI_FLASH_SEC_SIZE) + 0x40200000); // 0x40XFF000 +const static uint16_t tls_spi_start_sector = 0xFF; // Force last bank of first MB +const static uint8_t* tls_spi_start = (uint8_t*) 0x402FF000; // 0x402FF000 const static size_t tls_spi_len = 0x1000; // 4kb blocs const static size_t tls_block_offset = 0x0400; const static size_t tls_block_len = 0x0400; // 1kb diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index 1d793f730..97c995aaf 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -22,6 +22,10 @@ #include #include +#ifndef ZIGBEE_SAVE_DELAY_SECONDS +#define ZIGBEE_SAVE_DELAY_SECONDS 10; // wait for 10s before saving Zigbee info +#endif +const uint16_t kZigbeeSaveDelaySeconds = ZIGBEE_SAVE_DELAY_SECONDS; // wait for x seconds typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); @@ -57,6 +61,16 @@ class Z_Devices { public: Z_Devices() {}; + // Probe the existence of device keys + // Results: + // - 0x0000 = not found + // - 0xFFFF = bad parameter + // - 0x = the device's short address + uint16_t isKnownShortAddr(uint16_t shortaddr) const; + uint16_t isKnownLongAddr(uint64_t longaddr) const; + uint16_t isKnownIndex(uint32_t index) const; + uint16_t isKnownFriendlyName(const char * name) const; + // Add new device, provide ShortAddr and optional longAddr // If it is already registered, update information, otherwise create the entry void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); @@ -74,13 +88,14 @@ public: void setManufId(uint16_t shortaddr, const char * str); void setModelId(uint16_t shortaddr, const char * str); - void setFriendlyNameId(uint16_t shortaddr, const char * str); + void setFriendlyName(uint16_t shortaddr, const char * str); + const String * getFriendlyName(uint16_t) const; // device just seen on the network, update the lastSeen field void updateLastSeen(uint16_t shortaddr); // Dump json - String dump(uint32_t dump_mode, int32_t device_num = 0) const; + String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; // Timers void resetTimer(uint32_t shortaddr); @@ -89,13 +104,32 @@ public: // Append or clear attributes Json structure void jsonClear(uint16_t shortaddr); - void jsonAppend(uint16_t shortaddr, JsonObject &values); + void jsonAppend(uint16_t shortaddr, const JsonObject &values); const JsonObject *jsonGet(uint16_t shortaddr); - const void jsonPublish(uint16_t shortaddr); // publish the json message and clear buffer + void jsonPublishFlush(uint16_t shortaddr); // publish the json message and clear buffer bool jsonIsConflict(uint16_t shortaddr, const JsonObject &values); + void jsonPublishNow(uint16_t shortaddr, JsonObject &values); + + // Iterator + size_t devicesSize(void) const { + return _devices.size(); + } + const Z_Device &devicesAt(size_t i) const { + return _devices.at(i); + } + + // Remove device from list + bool removeDevice(uint16_t shortaddr); + + // Mark data as 'dirty' and requiring to save in Flash + void dirty(void); + + // Find device by name, can be short_addr, long_addr, number_in_array or name + uint16_t parseDeviceParam(const char * param, bool short_must_be_known = false) const; private: std::vector _devices = {}; + uint32_t _saveTimer = 0; template < typename T> static bool findInVector(const std::vector & vecOfElements, const T & element); @@ -109,8 +143,9 @@ private: Z_Device & getShortAddr(uint16_t shortaddr); // find Device from shortAddr, creates it if does not exist Z_Device & getLongAddr(uint64_t longaddr); // find Device from shortAddr, creates it if does not exist - int32_t findShortAddr(uint16_t shortaddr); - int32_t findLongAddr(uint64_t longaddr); + int32_t findShortAddr(uint16_t shortaddr) const; + int32_t findLongAddr(uint64_t longaddr) const; + int32_t findFriendlyName(const char * name) const; void _updateLastSeen(Z_Device &device) { if (&device != nullptr) { @@ -187,6 +222,7 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { nullptr, nullptr }; device.json_buffer = new DynamicJsonBuffer(); _devices.push_back(device); + dirty(); return _devices.back(); } @@ -198,7 +234,7 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { // Out: // index in _devices of entry, -1 if not found // -int32_t Z_Devices::findShortAddr(uint16_t shortaddr) { +int32_t Z_Devices::findShortAddr(uint16_t shortaddr) const { if (!shortaddr) { return -1; } // does not make sense to look for 0x0000 shortaddr (localhost) int32_t found = 0; if (shortaddr) { @@ -217,7 +253,7 @@ int32_t Z_Devices::findShortAddr(uint16_t shortaddr) { // Out: // index in _devices of entry, -1 if not found // -int32_t Z_Devices::findLongAddr(uint64_t longaddr) { +int32_t Z_Devices::findLongAddr(uint64_t longaddr) const { if (!longaddr) { return -1; } int32_t found = 0; if (longaddr) { @@ -228,6 +264,66 @@ int32_t Z_Devices::findLongAddr(uint64_t longaddr) { } return -1; } +// +// Scan all devices to find a corresponding friendlyNme +// Looks info device.friendlyName entry +// In: +// friendlyName (null terminated, should not be empty) +// Out: +// index in _devices of entry, -1 if not found +// +int32_t Z_Devices::findFriendlyName(const char * name) const { + if (!name) { return -1; } // if pointer is null + size_t name_len = strlen(name); + int32_t found = 0; + if (name_len) { + for (auto &elem : _devices) { + if (elem.friendlyName == name) { return found; } + found++; + } + } + return -1; +} + +// Probe if device is already known but don't create any entry +uint16_t Z_Devices::isKnownShortAddr(uint16_t shortaddr) const { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + return shortaddr; + } else { + return 0; // unknown + } +} + +uint16_t Z_Devices::isKnownLongAddr(uint64_t longaddr) const { + int32_t found = findLongAddr(longaddr); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + return device.shortaddr; // can be zero, if not yet registered + } else { + return 0; + } +} + +uint16_t Z_Devices::isKnownIndex(uint32_t index) const { + if (index < devicesSize()) { + const Z_Device & device = devicesAt(index); + return device.shortaddr; + } else { + return 0; + } +} + +uint16_t Z_Devices::isKnownFriendlyName(const char * name) const { + if ((!name) || (0 == strlen(name))) { return 0xFFFF; } // Error + int32_t found = findFriendlyName(name); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + return device.shortaddr; // can be zero, if not yet registered + } else { + return 0; + } +} // // We have a seen a shortaddr on the network, get the corresponding @@ -252,6 +348,17 @@ Z_Device & Z_Devices::getLongAddr(uint64_t longaddr) { return createDeviceEntry(0, longaddr); } +// Remove device from list, return true if it was known, false if it was not recorded +bool Z_Devices::removeDevice(uint16_t shortaddr) { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + _devices.erase(_devices.begin() + found); + dirty(); + return true; + } + return false; +} + // // We have just seen a device on the network, update the info based on short/long addr // In: @@ -270,15 +377,18 @@ void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { // erase the previous shortaddr _devices.erase(_devices.begin() + s_found); updateLastSeen(shortaddr); + dirty(); } } else if (s_found >= 0) { // shortaddr already exists but longaddr not // add the longaddr to the entry _devices[s_found].longaddr = longaddr; updateLastSeen(shortaddr); + dirty(); } else if (l_found >= 0) { // longaddr entry exists, update shortaddr _devices[l_found].shortaddr = shortaddr; + dirty(); } else { // neither short/lonf addr are found. if (shortaddr || longaddr) { @@ -298,6 +408,7 @@ void Z_Devices::addEndoint(uint16_t shortaddr, uint8_t endpoint) { _updateLastSeen(device); if (findEndpointInVector(device.endpoints, ep_profile) < 0) { device.endpoints.push_back(ep_profile); + dirty(); } } @@ -310,8 +421,12 @@ void Z_Devices::addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t int32_t found = findEndpointInVector(device.endpoints, ep_profile); if (found < 0) { device.endpoints.push_back(ep_profile); + dirty(); } else { - device.endpoints[found] = ep_profile; + if (device.endpoints[found] != ep_profile) { + device.endpoints[found] = ep_profile; + dirty(); + } } } @@ -324,10 +439,12 @@ void Z_Devices::addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluste if (!out) { if (!findInVector(device.clusters_in, ep_cluster)) { device.clusters_in.push_back(ep_cluster); + dirty(); } } else { // out if (!findInVector(device.clusters_out, ep_cluster)) { device.clusters_out.push_back(ep_cluster); + dirty(); } } } @@ -353,18 +470,32 @@ void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { if (&device == nullptr) { return; } // don't crash if not found _updateLastSeen(device); device.manufacturerId = str; + dirty(); } void Z_Devices::setModelId(uint16_t shortaddr, const char * str) { Z_Device & device = getShortAddr(shortaddr); if (&device == nullptr) { return; } // don't crash if not found _updateLastSeen(device); device.modelId = str; + dirty(); } -void Z_Devices::setFriendlyNameId(uint16_t shortaddr, const char * str) { +void Z_Devices::setFriendlyName(uint16_t shortaddr, const char * str) { Z_Device & device = getShortAddr(shortaddr); if (&device == nullptr) { return; } // don't crash if not found _updateLastSeen(device); device.friendlyName = str; + dirty(); +} + +const String * Z_Devices::getFriendlyName(uint16_t shortaddr) const { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + if (device.friendlyName.length() > 0) { + return &device.friendlyName; + } + } + return nullptr; } // device just seen on the network, update the lastSeen field @@ -398,19 +529,22 @@ void Z_Devices::setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, // Run timer at each tick void Z_Devices::runTimer(void) { - uint32_t now = millis(); - for (std::vector::iterator it = _devices.begin(); it != _devices.end(); ++it) { Z_Device &device = *it; uint16_t shortaddr = device.shortaddr; uint32_t timer = device.timer; - if ((timer) && (timer <= now)) { + if ((timer) && TimeReached(timer)) { device.timer = 0; // cancel the timer before calling, so the callback can set another timer // trigger the timer (*device.func)(device.shortaddr, device.cluster, device.endpoint, device.value); } } + // save timer + if ((_saveTimer) && TimeReached(_saveTimer)) { + saveZigbeeDevices(); + _saveTimer = 0; + } } void Z_Devices::jsonClear(uint16_t shortaddr) { @@ -482,7 +616,7 @@ bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const JsonObject &values) { return false; } -void Z_Devices::jsonAppend(uint16_t shortaddr, JsonObject &values) { +void Z_Devices::jsonAppend(uint16_t shortaddr, const JsonObject &values) { Z_Device & device = getShortAddr(shortaddr); if (&device == nullptr) { return; } // don't crash if not found if (&values == nullptr) { return; } @@ -500,40 +634,103 @@ const JsonObject *Z_Devices::jsonGet(uint16_t shortaddr) { return device.json; } -const void Z_Devices::jsonPublish(uint16_t shortaddr) { - const JsonObject *json = zigbee_devices.jsonGet(shortaddr); - if (json == nullptr) { return; } // don't crash if not found +void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } // don't crash if not found + JsonObject * json = device.json; + if (json == nullptr) { return; } // abort if nothing in buffer + + const String * fname = zigbee_devices.getFriendlyName(shortaddr); + bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); // should we replace shortaddr with friendlyname? + + if (use_fname) { + // we need to add the Device short_addr inside the JSON + char sa[8]; + snprintf_P(sa, sizeof(sa), PSTR("0x%04X"), shortaddr); + json->set(F(D_JSON_ZIGBEE_DEVICE), sa); + } else if (fname) { + json->set(F(D_JSON_NAME), (char*) fname); + } String msg = ""; json->printTo(msg); zigbee_devices.jsonClear(shortaddr); - Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + + if (use_fname) { + Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); + } else { + Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + } MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); } +void Z_Devices::jsonPublishNow(uint16_t shortaddr, JsonObject & values) { + jsonPublishFlush(shortaddr); // flush any previous buffer + jsonAppend(shortaddr, values); + jsonPublishFlush(shortaddr); // publish now +} + +void Z_Devices::dirty(void) { + _saveTimer = kZigbeeSaveDelaySeconds * 1000 + millis(); +} + +// Parse the command parameters for either: +// - a short address starting with "0x", example: 0x1234 +// - a long address starting with "0x", example: 0x7CB03EBB0A0292DD +// - a number 0..99, the index number in ZigbeeStatus +// - a friendly name, between quotes, example: "Room_Temp" +uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_known) const { + if (nullptr == param) { return 0; } + size_t param_len = strlen(param); + char dataBuf[param_len + 1]; + strcpy(dataBuf, param); + RemoveSpace(dataBuf); + uint16_t shortaddr = 0; + + if (strlen(dataBuf) < 4) { + // simple number 0..99 + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 99)) { + shortaddr = zigbee_devices.isKnownIndex(XdrvMailbox.payload - 1); + } + } else if ((dataBuf[0] == '0') && (dataBuf[1] == 'x')) { + // starts with 0x + if (strlen(dataBuf) < 18) { + // expect a short address + shortaddr = strtoull(dataBuf, nullptr, 0); + if (short_must_be_known) { + shortaddr = zigbee_devices.isKnownShortAddr(shortaddr); + } + // else we don't check if it's already registered to force unregistered devices + } else { + // expect a long address + uint64_t longaddr = strtoull(dataBuf, nullptr, 0); + shortaddr = zigbee_devices.isKnownLongAddr(longaddr); + } + } else { + // expect a Friendly Name + shortaddr = zigbee_devices.isKnownFriendlyName(dataBuf); + } + + return shortaddr; +} // Dump the internal memory of Zigbee devices -// Mode = 1: simple dump of devices addresses and names -// Mode = 2: Mode 1 + also dump the endpoints, profiles and clusters -String Z_Devices::dump(uint32_t dump_mode, int32_t device_num) const { +// Mode = 1: simple dump of devices addresses +// Mode = 2: simple dump of devices addresses and names +// Mode = 3: Mode 2 + also dump the endpoints, profiles and clusters +String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { DynamicJsonBuffer jsonBuffer; JsonArray& json = jsonBuffer.createArray(); JsonArray& devices = json; - //JsonArray& devices = json.createNestedArray(F("ZigbeeDevices")); - - // if device_num == 0, then we show all devices. - // When no payload, the default is -99. In this case change it to 0. - if (device_num < 0) { device_num = 0; } - - uint32_t device_current = 1; - for (std::vector::const_iterator it = _devices.begin(); it != _devices.end(); ++it, ++device_current) { - // ignore non-current device, if specified device is non-zero - if ((device_num > 0) && (device_num != device_current)) { continue; } + for (std::vector::const_iterator it = _devices.begin(); it != _devices.end(); ++it) { const Z_Device& device = *it; uint16_t shortaddr = device.shortaddr; - char hex[20]; + char hex[22]; + + // ignore non-current device, if specified device is non-zero + if ((status_shortaddr) && (status_shortaddr != shortaddr)) { continue; } JsonObject& dev = devices.createNestedObject(); @@ -545,7 +742,9 @@ String Z_Devices::dump(uint32_t dump_mode, int32_t device_num) const { } if (2 <= dump_mode) { - Uint64toHex(device.longaddr, hex, 64); + hex[0] = '0'; // prefix with '0x' + hex[1] = 'x'; + Uint64toHex(device.longaddr, &hex[2], 64); dev[F("IEEEAddr")] = hex; if (device.modelId.length() > 0) { dev[F(D_JSON_MODEL D_JSON_ID)] = device.modelId; diff --git a/tasmota/xdrv_23_zigbee_4_persistence.ino b/tasmota/xdrv_23_zigbee_4_persistence.ino new file mode 100644 index 000000000..e4fae384d --- /dev/null +++ b/tasmota/xdrv_23_zigbee_4_persistence.ino @@ -0,0 +1,332 @@ +/* + xdrv_23_zigbee.ino - zigbee support for Tasmota + + Copyright (C) 2020 Theo Arends and Stephan Hadinger + + 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 . +*/ + +#ifdef USE_ZIGBEE + +// Ensure persistence of devices into Flash +// +// Structure: +// (from file info): +// uint16 - start address in Flash (offset) +// uint16 - length in bytes (makes sure parsing stops) +// +// File structure: +// uint8 - number of devices, 0=none, 0xFF=invalid entry (probably Flash was erased) +// +// [Array of devices] +// [Offset = 2] +// uint8 - length of revice record +// uint16 - short address +// uint64 - long IEEE address +// uint8 - number of endpoints +// [Array of endpoints] +// uint8 - endpoint number +// uint16 - profileID of the endpoint +// Array of uint8 - clusters In codes, 0xFF end marker +// Array of uint8 - clusters Out codes, 0xFF end marker +// +// str - ModelID (null terminated C string, 32 chars max) +// str - Manuf (null terminated C string, 32 chars max) +// reserved for extensions + +// Memory footprint +const static uint16_t z_spi_start_sector = 0xFF; // Force last bank of first MB +const static uint8_t* z_spi_start = (uint8_t*) 0x402FF000; // 0x402FF000 +const static uint8_t* z_dev_start = z_spi_start + 0x0800; // 0x402FF800 - 2KB +const static size_t z_spi_len = 0x1000; // 4kb blocs +const static size_t z_block_offset = 0x0800; +const static size_t z_block_len = 0x0800; // 2kb + +class z_flashdata_t { +public: + uint32_t name; // simple 4 letters name. Currently 'skey', 'crt ', 'crt1', 'crt2' + uint16_t len; // len of object + uint16_t reserved; // align on 4 bytes boundary +}; + +const static uint32_t ZIGB_NAME = 0x3167697A; // 'zig1' little endian +const static size_t Z_MAX_FLASH = z_block_len - sizeof(z_flashdata_t); // 2040 + +// encoding for the most commonly 32 clusters, used for binary encoding +const uint16_t Z_ClusterNumber[] PROGMEM = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0100, 0x0101, 0x0102, + 0x0201, 0x0202, 0x0203, 0x0204, + 0x0300, 0x0301, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, + 0x0500, 0x0501, 0x0502, + 0x0700, 0x0701, 0x0702, + 0x0B00, 0x0B01, 0x0B02, 0x0B03, 0x0B04, 0x0B05, + 0x1000, + 0xFC0F, +}; + +// convert a 1 byte cluster code to the actual cluster number +uint16_t fromClusterCode(uint8_t c) { + if (c >= sizeof(Z_ClusterNumber)/sizeof(Z_ClusterNumber[0])) { + return 0xFFFF; // invalid + } + return pgm_read_word(&Z_ClusterNumber[c]); +} + +// convert a cluster number to 1 byte, or 0xFF if not in table +uint8_t toClusterCode(uint16_t c) { + for (uint32_t i = 0; i < sizeof(Z_ClusterNumber)/sizeof(Z_ClusterNumber[0]); i++) { + if (c == pgm_read_word(&Z_ClusterNumber[i])) { + return i; + } + } + return 0xFF; // not found +} + +class SBuffer hibernateDevice(const struct Z_Device &device) { + SBuffer buf(128); + + buf.add8(0x00); // overall length, will be updated later + buf.add16(device.shortaddr); + buf.add64(device.longaddr); + uint32_t endpoints = device.endpoints.size(); + if (endpoints > 254) { endpoints = 254; } + buf.add8(endpoints); + // iterate on endpoints + for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { + uint32_t ep_profile = *ite; + uint8_t endpoint = (ep_profile >> 16) & 0xFF; + uint16_t profileId = ep_profile & 0xFFFF; + + buf.add8(endpoint); + buf.add16(profileId); + for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t c_endpoint = (*itc >> 16) & 0xFF; + + if (endpoint == c_endpoint) { + uint8_t clusterCode = toClusterCode(cluster); + if (0xFF != clusterCode) { buf.add8(clusterCode); } + } + } + buf.add8(0xFF); // end of endpoint marker + + for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t c_endpoint = (*itc >> 16) & 0xFF; + + if (endpoint == c_endpoint) { + uint8_t clusterCode = toClusterCode(cluster); + if (0xFF != clusterCode) { buf.add8(clusterCode); } + } + } + buf.add8(0xFF); // end of endpoint marker + } + + // ModelID + size_t model_len = device.modelId.length(); + if (model_len > 32) { model_len = 32; } // max 32 chars + buf.addBuffer(device.modelId.c_str(), model_len); + buf.add8(0x00); // end of string marker + + // ManufID + size_t manuf_len = device.manufacturerId.length(); + if (manuf_len > 32) {manuf_len = 32; } // max 32 chars + buf.addBuffer(device.manufacturerId.c_str(), manuf_len); + buf.add8(0x00); // end of string marker + + // FriendlyName + size_t frname_len = device.friendlyName.length(); + if (frname_len > 32) {frname_len = 32; } // max 32 chars + buf.addBuffer(device.friendlyName.c_str(), frname_len); + buf.add8(0x00); // end of string marker + + // update overall length + buf.set8(0, buf.len()); + + return buf; +} + +class SBuffer hibernateDevices(void) { + SBuffer buf(2048); + + size_t devices_size = zigbee_devices.devicesSize(); + if (devices_size > 32) { devices_size = 32; } // arbitrarily limit to 32 devices, for now + buf.add8(devices_size); // number of devices + + for (uint32_t i = 0; i < devices_size; i++) { + const Z_Device & device = zigbee_devices.devicesAt(i); + const SBuffer buf_device = hibernateDevice(device); + buf.addBuffer(buf_device); + } + + size_t buf_len = buf.len(); + if (buf_len > 2040) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Devices list too big to fit in Flash (%d)"), buf_len); + } + + // Log + char *hex_char = (char*) malloc((buf_len * 2) + 2); + if (hex_char) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZigbeeFlashStore %s"), + ToHex_P(buf.getBuffer(), buf_len, hex_char, (buf_len * 2) + 2)); + free(hex_char); + } + + return buf; +} + +void hidrateDevices(const SBuffer &buf) { + uint32_t buf_len = buf.len(); + if (buf_len <= 10) { return; } + + uint32_t k = 0; + uint32_t num_devices = buf.get8(k++); + + for (uint32_t i = 0; (i < num_devices) && (k < buf_len); i++) { + uint32_t dev_record_len = buf.get8(k); + + SBuffer buf_d = buf.subBuffer(k, dev_record_len); + + uint32_t d = 1; // index in device buffer + uint16_t shortaddr = buf_d.get16(d); d += 2; + uint64_t longaddr = buf_d.get64(d); d += 8; + zigbee_devices.updateDevice(shortaddr, longaddr); // update device's addresses + + uint32_t endpoints = buf_d.get8(d++); + for (uint32_t j = 0; j < endpoints; j++) { + uint8_t ep = buf_d.get8(d++); + uint16_t ep_profile = buf_d.get16(d); d += 2; + zigbee_devices.addEndointProfile(shortaddr, ep, ep_profile); + + // in clusters + while (d < dev_record_len) { // safe guard against overflow + uint8_t ep_cluster = buf_d.get8(d++); + if (0xFF == ep_cluster) { break; } // end of block + zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), false); + } + // out clusters + while (d < dev_record_len) { // safe guard against overflow + uint8_t ep_cluster = buf_d.get8(d++); + if (0xFF == ep_cluster) { break; } // end of block + zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), true); + } + } + + // parse 3 strings + char empty[] = ""; + + // ManufID + uint32_t s_len = buf_d.strlen_s(d); + char *ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setModelId(shortaddr, ptr); + d += s_len + 1; + + // ManufID + s_len = buf_d.strlen_s(d); + ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setManufId(shortaddr, ptr); + d += s_len + 1; + + // FriendlyName + s_len = buf_d.strlen_s(d); + ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setFriendlyName(shortaddr, ptr); + d += s_len + 1; + + // next iteration + k += dev_record_len; + } +} + +void loadZigbeeDevices(void) { + z_flashdata_t flashdata; + memcpy_P(&flashdata, z_dev_start, sizeof(z_flashdata_t)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Zigbee signature in Flash: %08X - %d"), flashdata.name, flashdata.len); + + // Check the signature + if ((flashdata.name == ZIGB_NAME) && (flashdata.len > 0)) { + uint16_t buf_len = flashdata.len; + // parse what seems to be a valid entry + SBuffer buf(buf_len); + buf.addBuffer(z_dev_start + sizeof(z_flashdata_t), buf_len); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee devices data in Flash (%d bytes)"), buf_len); + hidrateDevices(buf); + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "No zigbee devices data in Flash")); + } +} + +void saveZigbeeDevices(void) { + SBuffer buf = hibernateDevices(); + size_t buf_len = buf.len(); + if (buf_len > Z_MAX_FLASH) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Buffer too big to fit in Flash (%d bytes)"), buf_len); + return; + } + + // first copy SPI buffer into ram + uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); + if (!spi_buffer) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); + return; + } + // copy the flash into RAM to make local change, and write back the whole buffer + ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + + z_flashdata_t *flashdata = (z_flashdata_t*)(spi_buffer + z_block_offset); + flashdata->name = ZIGB_NAME; + flashdata->len = buf_len; + flashdata->reserved = 0; + + memcpy(spi_buffer + z_block_offset + sizeof(z_flashdata_t), buf.getBuffer(), buf_len); + + // buffer is now ready, write it back + if (ESP.flashEraseSector(z_spi_start_sector)) { + ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + } + + free(spi_buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data store in Flash (0x%08X - %d bytes)"), z_dev_start, buf_len); +} + +// Erase the flash area containing the ZigbeeData +void eraseZigbeeDevices(void) { + // first copy SPI buffer into ram + uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); + if (!spi_buffer) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); + return; + } + // copy the flash into RAM to make local change, and write back the whole buffer + ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + + // Fill the Zigbee area with 0xFF + memset(spi_buffer + z_block_offset, 0xFF, z_block_len); + + // buffer is now ready, write it back + if (ESP.flashEraseSector(z_spi_start_sector)) { + ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + } + + free(spi_buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased (0x%08X - %d bytes)"), z_dev_start, z_block_len); +} + +#endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 58b055d2b..af691876e 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -830,10 +830,10 @@ int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& // Publish a message for `"Occupancy":0` when the timer expired int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { - // send Occupancy:false message - Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"0x%04X\":{\"" OCCUPANCY "\":0}}}"), shortaddr); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + json[F(OCCUPANCY)] = 0; + zigbee_devices.jsonPublishNow(shortaddr, json); } // Aqara Cube diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index 520dbd232..c32634f6b 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -354,7 +354,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = { //ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "starting zigbee coordinator") ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) // wait for sync ack of command - ZI_WAIT_UNTIL(5000, AREQ_STARTUPFROMAPP) // wait for async message that coordinator started + ZI_WAIT_UNTIL(10000, AREQ_STARTUPFROMAPP) // wait for async message that coordinator started ZI_SEND(ZBS_GETDEVICEINFO) // GetDeviceInfo ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo) //ZI_WAIT_RECV(2000, ZBR_GETDEVICEINFO) // memorize info @@ -386,6 +386,7 @@ ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator ZI_MQTT_STATE(ZIGBEE_STATUS_OK, "Started") ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "Zigbee started") ZI_CALL(&Z_State_Ready, 1) // Now accept incoming messages + ZI_CALL(&Z_Load_Devices, 0) ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) ZI_WAIT_FOREVER() ZI_GOTO(ZIGBEE_LABEL_READY) diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index d396b3fc4..90d272a00 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -403,7 +403,7 @@ int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t cluster, uint16_t endpo // Post-provess for Aqara Presence Senson Z_AqaraOccupancy(shortaddr, cluster, endpoint, json); - zigbee_devices.jsonPublish(shortaddr); + zigbee_devices.jsonPublishFlush(shortaddr); return 1; } @@ -433,8 +433,15 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { DynamicJsonBuffer jsonBuffer; JsonObject& json_root = jsonBuffer.createObject(); + JsonObject& json1 = json_root.createNestedObject(F(D_CMND_ZIGBEE_RECEIVED)); - JsonObject& json = json1.createNestedObject(shortaddr); + + const String * fname = zigbee_devices.getFriendlyName(srcaddr); + bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); // should we replace shortaddr with friendlyname? + JsonObject& json = json1.createNestedObject(use_fname ? fname->c_str() : shortaddr); + if (use_fname) { + json[F(D_JSON_ZIGBEE_DEVICE)] = shortaddr; + } if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { zcl_received.parseRawAttributes(json); @@ -449,6 +456,11 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { json_root.printTo(msg); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeZCLRawReceived: %s"), msg.c_str()); + // Add friendly name + if ((!use_fname) && (fname)) { + json[F(D_JSON_ZIGBEE_NAME)] = (char*)fname->c_str(); // (char*) will force a copy of the string + } + zcl_received.postProcessAttributes(srcaddr, json); // Add linkquality json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; @@ -457,7 +469,7 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { // Prepare for publish if (zigbee_devices.jsonIsConflict(srcaddr, json)) { // there is conflicting values, force a publish of the previous message now and don't coalesce - zigbee_devices.jsonPublish(srcaddr); + zigbee_devices.jsonPublishFlush(srcaddr); } else { zigbee_devices.jsonAppend(srcaddr, json); zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); @@ -511,6 +523,12 @@ int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { } } +int32_t Z_Load_Devices(uint8_t value) { + // try to hidrate from known devices + loadZigbeeDevices(); + return 0; // continue +} + int32_t Z_State_Ready(uint8_t value) { zigbee.init_phase = false; // initialization phase complete return 0; // continue diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 408410f9b..4464ab525 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -31,13 +31,15 @@ TasmotaSerial *ZigbeeSerial = nullptr; const char kZigbeeCommands[] PROGMEM = "|" D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" - D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE + D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME ; void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZigbeeZNPSend, &CmndZigbeePermitJoin, &CmndZigbeeStatus, &CmndZigbeeReset, &CmndZigbeeSend, - &CmndZigbeeProbe, &CmndZigbeeRead, &CmndZigbeeZNPReceive + &CmndZigbeeProbe, &CmndZigbeeRead, &CmndZigbeeZNPReceive, + &CmndZigbeeForget, &CmndZigbeeSave, &CmndZigbeeName }; int32_t ZigbeeProcessInput(class SBuffer &buf) { @@ -254,6 +256,7 @@ void CmndZigbeeReset(void) { switch (XdrvMailbox.payload) { case 1: ZigbeeZNPSend(ZIGBEE_FACTORY_RESET, sizeof(ZIGBEE_FACTORY_RESET)); + eraseZigbeeDevices(); restart_flag = 2; ResponseCmndChar(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING); break; @@ -263,13 +266,6 @@ void CmndZigbeeReset(void) { } } -void CmndZigbeeStatus(void) { - if (ZigbeeSerial) { - String dump = zigbee_devices.dump(XdrvMailbox.index, XdrvMailbox.payload); - Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str()); - } -} - void CmndZigbeeZNPSendOrReceive(bool send) { if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { @@ -548,20 +544,68 @@ void CmndZigbeeSend(void) { // Probe a specific device to get its endpoints and supported clusters void CmndZigbeeProbe(void) { if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - char dataBufUc[XdrvMailbox.data_len + 1]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 3) { ResponseCmndChar("Invalid destination"); return; } - - // TODO, for now ignore friendly names - uint16_t shortaddr = strtoull(dataBufUc, nullptr, 0); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CmndZigbeeScan: short addr 0x%04X"), shortaddr); + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } // everything is good, we can send the command Z_SendActiveEpReq(shortaddr); ResponseCmndDone(); } +// Specify, read or erase a Friendly Name +void CmndZigbeeName(void) { + // Syntax is: + // ZigbeeName , - assign a friendly name + // ZigbeeName - display the current friendly name + // ZigbeeName , - remove friendly name + // + // Where can be: short_addr, long_addr, device_index, friendly_name + + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + + // check if parameters contain a comma ',' + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + + // parse first part, + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + + if (p == nullptr) { + const String * friendlyName = zigbee_devices.getFriendlyName(shortaddr); + Response_P(PSTR("{\"0x%04X\":{\"name\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName->c_str() : ""); + } else { + zigbee_devices.setFriendlyName(shortaddr, p); + Response_P(PSTR("{\"0x%04X\":{\"name\":\"%s\"}}"), shortaddr, p); + } +} + +// Remove an old Zigbee device from the list of known devices, use ZigbeeStatus to know all registered devices +void CmndZigbeeForget(void) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + + // everything is good, we can send the command + if (zigbee_devices.removeDevice(shortaddr)) { + ResponseCmndDone(); + } else { + ResponseCmndChar("Unknown device"); + } +} + +// Save Zigbee information to flash +void CmndZigbeeSave(void) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + + saveZigbeeDevices(); + + ResponseCmndDone(); +} + // Send an attribute read command to a device, specifying cluster and list of attributes void CmndZigbeeRead(void) { // ZigbeeRead {"Device":"0xF289","Cluster":0,"Endpoint":3,"Attr":5} @@ -633,6 +677,20 @@ void CmndZigbeePermitJoin(void) ResponseCmndDone(); } +void CmndZigbeeStatus(void) { + if (ZigbeeSerial) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + if (XdrvMailbox.payload > 0) { + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + } + + String dump = zigbee_devices.dump(XdrvMailbox.index, shortaddr); + Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str()); + } +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ From 5716d08de9edbb839ba7651beef2c1a47ccbf29c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 18 Jan 2020 15:34:01 +0100 Subject: [PATCH 053/160] Refactor MQTT Logging and publish --- tasmota/support.ino | 8 +++- tasmota/support_tasmota.ino | 6 +-- tasmota/xdrv_02_mqtt.ino | 78 +++++++++++++++---------------------- 3 files changed, 41 insertions(+), 51 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index a9a631fd1..9b8f5dc9d 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1631,8 +1631,12 @@ void AddLog(uint32_t loglevel) if (!web_log_index) web_log_index++; // Index 0 is not allowed as it is the end of char string } #endif // USE_WEBSERVER - if (!global_state.mqtt_down && (loglevel <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); } - if (!global_state.wifi_down && (loglevel <= syslog_level)) { Syslog(); } + if (Settings.flag.mqtt_enabled && // SetOption3 - Enable MQTT + !global_state.mqtt_down && + (loglevel <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); } + + if (!global_state.wifi_down && + (loglevel <= syslog_level)) { Syslog(); } } void AddLog_P(uint32_t loglevel, const char *formatP) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 1cb3aae8b..551f5b2c6 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -438,9 +438,9 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) #ifdef USE_DOMOTICZ if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { #endif // USE_DOMOTICZ - MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain // CMND_SWITCHRETAIN - : Settings.flag.mqtt_button_retain) && // CMND_BUTTONRETAIN - (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); // SetOption62 - Don't use retain flag on HOLD messages + MqttPublish(stopic, ((key) ? Settings.flag.mqtt_switch_retain // CMND_SWITCHRETAIN + : Settings.flag.mqtt_button_retain) && // CMND_BUTTONRETAIN + (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); // SetOption62 - Don't use retain flag on HOLD messages #ifdef USE_DOMOTICZ } #endif // USE_DOMOTICZ diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 799829fe6..d489606d4 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -221,6 +221,17 @@ void MqttUnsubscribeLib(const char *topic) bool MqttPublishLib(const char* topic, bool retained) { + // If Prefix1 equals Prefix2 disable next MQTT subscription to prevent loop + if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { + char *str = strstr(topic, SettingsText(SET_MQTTPREFIX1)); + if (str == topic) { + if (0 == mqtt_cmnd_publish) { + mqtt_cmnd_publish += 3; + } + mqtt_cmnd_publish += 3; + } + } + bool result = MqttClient.publish(topic, mqtt_data, retained); yield(); // #3313 return result; @@ -291,43 +302,37 @@ void MqttUnsubscribe(const char *topic) void MqttPublishLogging(const char *mxtime) { - if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT - if (MqttIsConnected()) { + if (MqttIsConnected()) { + char saved_mqtt_data[MESSZ]; + memcpy(saved_mqtt_data, mqtt_data, sizeof(saved_mqtt_data)); - char saved_mqtt_data[MESSZ]; - memcpy(saved_mqtt_data, mqtt_data, sizeof(saved_mqtt_data)); -// ResponseTime_P(PSTR(",\"Log\":{\"%s\"}}"), log_data); // Will fail as some messages contain JSON - Response_P(PSTR("%s%s"), mxtime, log_data); // No JSON and ugly!! +// ResponseTime_P(PSTR(",\"Log\":{\"%s\"}}"), log_data); // Will fail as some messages contain JSON + Response_P(PSTR("%s%s"), mxtime, log_data); // No JSON and ugly!! - char romram[33]; - char stopic[TOPSZ]; - snprintf_P(romram, sizeof(romram), PSTR("LOGGING")); - GetTopic_P(stopic, STAT, mqtt_topic, romram); + char stopic[TOPSZ]; + GetTopic_P(stopic, STAT, mqtt_topic, PSTR("LOGGING")); + MqttPublishLib(stopic, false); - char *me; - if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { - me = strstr(stopic, SettingsText(SET_MQTTPREFIX1)); - if (me == stopic) { - mqtt_cmnd_publish += 3; - } - } - MqttPublishLib(stopic, false); - - memcpy(mqtt_data, saved_mqtt_data, sizeof(saved_mqtt_data)); - } + memcpy(mqtt_data, saved_mqtt_data, sizeof(saved_mqtt_data)); } } -void MqttPublishDirect(const char* topic, bool retained) +void MqttPublish(const char* topic, bool retained) { - char sretained[CMDSZ]; - char slog_type[20]; - #ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("MqttPublishDirect")); + ShowFreeMem(PSTR("MqttPublish")); #endif +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + if (retained) { +// AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR("Retained are not supported by AWS IoT, using retained = false.")); + retained = false; // AWS IoT does not support retained, it will disconnect if received + } +#endif + + char sretained[CMDSZ]; sretained[0] = '\0'; + char slog_type[20]; snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_RESULT)); if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT @@ -354,25 +359,6 @@ void MqttPublishDirect(const char* topic, bool retained) } } -void MqttPublish(const char* topic, bool retained) -{ - char *me; -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if (retained) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR("Retained are not supported by AWS IoT, using retained = false.")); - } - retained = false; // AWS IoT does not support retained, it will disconnect if received -#endif - - if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { - me = strstr(topic, SettingsText(SET_MQTTPREFIX1)); - if (me == topic) { - mqtt_cmnd_publish += 3; - } - } - MqttPublishDirect(topic, retained); -} - void MqttPublish(const char* topic) { MqttPublish(topic, false); @@ -860,7 +846,7 @@ void CmndPublish(void) } else { mqtt_data[0] = '\0'; } - MqttPublishDirect(stemp1, (XdrvMailbox.index == 2)); + MqttPublish(stemp1, (XdrvMailbox.index == 2)); // ResponseCmndDone(); mqtt_data[0] = '\0'; } From 45ed0257b68e485e6f5f9f90f61191a48b78dade Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 18 Jan 2020 16:57:48 +0100 Subject: [PATCH 054/160] Better support for Prefix1 equals Prefix2 --- tasmota/support_command.ino | 3 ++- tasmota/support_tasmota.ino | 19 +++++++++++++------ tasmota/tasmota.ino | 3 ++- tasmota/xdrv_02_mqtt.ino | 14 ++++---------- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 6f70e7359..24ef2051c 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -338,7 +338,8 @@ void CmndStatus(void) char stemp2[TOPSZ]; // Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX - if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2)) && (!payload)) { option++; } // TELE + // Commented on 20200118 as it seems to be no longer needed +// if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2)) && (!payload)) { option++; } // TELE if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } // SetOption3 - Enable MQTT if (!energy_flg && (9 == payload)) { payload = 99; } diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 551f5b2c6..9095a09bf 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -692,7 +692,12 @@ void MqttPublishSensor(void) } } -/********************************************************************************************/ +/*********************************************************************************************\ + * State loops +\*********************************************************************************************/ +/*-------------------------------------------------------------------------------------------*\ + * Every second +\*-------------------------------------------------------------------------------------------*/ void PerformEverySecond(void) { @@ -715,6 +720,13 @@ void PerformEverySecond(void) #endif } + if (mqtt_cmnd_blocked_reset) { + mqtt_cmnd_blocked_reset--; + if (!mqtt_cmnd_blocked_reset) { + mqtt_cmnd_blocked = 0; // Clean up MQTT cmnd loop block + } + } + if (seriallog_timer) { seriallog_timer--; if (!seriallog_timer) { @@ -763,9 +775,6 @@ void PerformEverySecond(void) } } -/*********************************************************************************************\ - * State loops -\*********************************************************************************************/ /*-------------------------------------------------------------------------------------------*\ * Every 0.1 second \*-------------------------------------------------------------------------------------------*/ @@ -822,8 +831,6 @@ void Every250mSeconds(void) state_250mS++; state_250mS &= 0x3; - if (mqtt_cmnd_publish) mqtt_cmnd_publish--; // Clean up - if (!Settings.flag.global_state) { // Problem blinkyblinky enabled - SetOption31 - Control link led blinking if (global_state.data) { // Any problem if (global_state.mqtt_down) { blinkinterval = 7; } // MQTT problem so blink every 2 seconds (slowest) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 721c2f4ac..15375e338 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -110,12 +110,13 @@ float global_temperature = 9999; // Provide a global temperature to b float global_humidity = 0; // Provide a global humidity to be used by some sensors float global_pressure = 0; // Provide a global pressure to be used by some sensors uint16_t tele_period = 9999; // Tele period timer -uint16_t mqtt_cmnd_publish = 0; // ignore flag for publish command uint16_t blink_counter = 0; // Number of blink cycles uint16_t seriallog_timer = 0; // Timer to disable Seriallog uint16_t syslog_timer = 0; // Timer to re-enable syslog_level int16_t save_data_counter; // Counter and flag for config save to Flash RulesBitfield rules_flag; // Rule state flags (16 bits) +uint8_t mqtt_cmnd_blocked = 0; // Ignore flag for publish command +uint8_t mqtt_cmnd_blocked_reset = 0; // Count down to reset if needed uint8_t state_250mS = 0; // State 250msecond per second flag uint8_t latching_relay_pulse = 0; // Latching relay pulse timer uint8_t sleep; // Current copy of Settings.sleep diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index d489606d4..a5d90f49a 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -225,10 +225,8 @@ bool MqttPublishLib(const char* topic, bool retained) if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { char *str = strstr(topic, SettingsText(SET_MQTTPREFIX1)); if (str == topic) { - if (0 == mqtt_cmnd_publish) { - mqtt_cmnd_publish += 3; - } - mqtt_cmnd_publish += 3; + mqtt_cmnd_blocked_reset = 4; // Allow up to four seconds before resetting residual cmnd blocks + mqtt_cmnd_blocked++; } } @@ -249,12 +247,8 @@ void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len // Do not execute multiple times if Prefix1 equals Prefix2 if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { char *str = strstr(mqtt_topic, SettingsText(SET_MQTTPREFIX1)); - if ((str == mqtt_topic) && mqtt_cmnd_publish) { - if (mqtt_cmnd_publish > 3) { - mqtt_cmnd_publish -= 3; - } else { - mqtt_cmnd_publish = 0; - } + if ((str == mqtt_topic) && mqtt_cmnd_blocked) { + mqtt_cmnd_blocked--; return; } } From 6c837872102a400c84c017eb4ef30f0305c9f1cb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 19 Jan 2020 12:22:40 +0100 Subject: [PATCH 055/160] Lower mqttlog stack usage --- tasmota/xdrv_02_mqtt.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index a5d90f49a..49d1bf259 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -297,12 +297,11 @@ void MqttUnsubscribe(const char *topic) void MqttPublishLogging(const char *mxtime) { if (MqttIsConnected()) { - char saved_mqtt_data[MESSZ]; + char saved_mqtt_data[strlen(mqtt_data) +1]; memcpy(saved_mqtt_data, mqtt_data, sizeof(saved_mqtt_data)); // ResponseTime_P(PSTR(",\"Log\":{\"%s\"}}"), log_data); // Will fail as some messages contain JSON Response_P(PSTR("%s%s"), mxtime, log_data); // No JSON and ugly!! - char stopic[TOPSZ]; GetTopic_P(stopic, STAT, mqtt_topic, PSTR("LOGGING")); MqttPublishLib(stopic, false); From 6d5b0ed62237fc32aad8b95e85dd31d574a8d184 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 19 Jan 2020 14:12:25 +0100 Subject: [PATCH 056/160] Remove redundant code --- tasmota/xdrv_02_mqtt.ino | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 49d1bf259..38bae9a01 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -296,18 +296,16 @@ void MqttUnsubscribe(const char *topic) void MqttPublishLogging(const char *mxtime) { - if (MqttIsConnected()) { - char saved_mqtt_data[strlen(mqtt_data) +1]; - memcpy(saved_mqtt_data, mqtt_data, sizeof(saved_mqtt_data)); + char saved_mqtt_data[strlen(mqtt_data) +1]; + memcpy(saved_mqtt_data, mqtt_data, sizeof(saved_mqtt_data)); // ResponseTime_P(PSTR(",\"Log\":{\"%s\"}}"), log_data); // Will fail as some messages contain JSON - Response_P(PSTR("%s%s"), mxtime, log_data); // No JSON and ugly!! - char stopic[TOPSZ]; - GetTopic_P(stopic, STAT, mqtt_topic, PSTR("LOGGING")); - MqttPublishLib(stopic, false); + Response_P(PSTR("%s%s"), mxtime, log_data); // No JSON and ugly!! + char stopic[TOPSZ]; + GetTopic_P(stopic, STAT, mqtt_topic, PSTR("LOGGING")); + MqttPublishLib(stopic, false); - memcpy(mqtt_data, saved_mqtt_data, sizeof(saved_mqtt_data)); - } + memcpy(mqtt_data, saved_mqtt_data, sizeof(saved_mqtt_data)); } void MqttPublish(const char* topic, bool retained) @@ -317,10 +315,10 @@ void MqttPublish(const char* topic, bool retained) #endif #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if (retained) { +// if (retained) { // AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR("Retained are not supported by AWS IoT, using retained = false.")); - retained = false; // AWS IoT does not support retained, it will disconnect if received - } +// } + retained = false; // AWS IoT does not support retained, it will disconnect if received #endif char sretained[CMDSZ]; @@ -329,12 +327,10 @@ void MqttPublish(const char* topic, bool retained) snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_RESULT)); if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT - if (MqttIsConnected()) { - if (MqttPublishLib(topic, retained)) { - snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_MQTT)); - if (retained) { - snprintf_P(sretained, sizeof(sretained), PSTR(" (" D_RETAINED ")")); - } + if (MqttPublishLib(topic, retained)) { + snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_MQTT)); + if (retained) { + snprintf_P(sretained, sizeof(sretained), PSTR(" (" D_RETAINED ")")); } } } From e03a14ce21a75db208cf7c4741699b41ba349c56 Mon Sep 17 00:00:00 2001 From: Leonid Muravjev Date: Sun, 19 Jan 2020 16:15:18 +0300 Subject: [PATCH 057/160] i2c: I2cSetDevice wrong behavior Most drivers do not expect address blocking after calling i2cSetDevice. I2cSetActive removed from I2cSetDevice. All drivers waiting for this call are fixed. refs #7556 --- tasmota/support.ino | 6 +----- tasmota/xdrv_10_scripter.ino | 1 + tasmota/xdsp_08_ILI9488.ino | 1 + tasmota/xdsp_10_RA8876.ino | 1 + 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index 9b8f5dc9d..94def5a6f 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1521,11 +1521,7 @@ bool I2cSetDevice(uint32_t addr) return false; // If already active report as not present; } Wire.beginTransmission((uint8_t)addr); - bool result = (0 == Wire.endTransmission()); - if (result) { - I2cSetActive(addr, 1); - } - return result; + return (0 == Wire.endTransmission()); } #endif // USE_I2C diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 17ef36177..09406e810 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -4775,6 +4775,7 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE; glob_script_mem.flags=1; + I2cSetActiveFound(EEPROM_ADDRESS, "EEPROM"); } } #endif diff --git a/tasmota/xdsp_08_ILI9488.ino b/tasmota/xdsp_08_ILI9488.ino index 8b7438c5a..84a493fc6 100644 --- a/tasmota/xdsp_08_ILI9488.ino +++ b/tasmota/xdsp_08_ILI9488.ino @@ -116,6 +116,7 @@ void ILI9488_InitDriver() if (I2cEnabled(XI2C_38) && I2cSetDevice(FT6236_address)) { FT6236begin(FT6236_address); FT6236_found=1; + I2cSetActiveFound(FT6236_address, "FT6236"); } else { FT6236_found=0; } diff --git a/tasmota/xdsp_10_RA8876.ino b/tasmota/xdsp_10_RA8876.ino index 139a654ed..88f3ebad2 100644 --- a/tasmota/xdsp_10_RA8876.ino +++ b/tasmota/xdsp_10_RA8876.ino @@ -101,6 +101,7 @@ void RA8876_InitDriver() if (I2cEnabled(XI2C_39) && I2cSetDevice(FT5316_address)) { FT6236begin(FT5316_address); FT5316_found=1; + I2cSetActiveFound(FT5316_address, "FT5316"); } else { FT5316_found=0; } From 79fdc265b7b6500e30b9905c479b28a5af0b4496 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 19 Jan 2020 22:59:02 +0100 Subject: [PATCH 058/160] Minor fixes to Zigbee friendly names --- tasmota/xdrv_23_zigbee_3_devices.ino | 29 ++++++++++++++++++----- tasmota/xdrv_23_zigbee_7_statemachine.ino | 1 - tasmota/xdrv_23_zigbee_8_parsers.ino | 26 ++++---------------- tasmota/xdrv_23_zigbee_9_impl.ino | 4 ++-- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index 97c995aaf..e034868e6 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -624,6 +624,16 @@ void Z_Devices::jsonAppend(uint16_t shortaddr, const JsonObject &values) { if (nullptr == device.json) { device.json = &(device.json_buffer->createObject()); } + // Prepend Device, will be removed later if redundant + char sa[8]; + snprintf_P(sa, sizeof(sa), PSTR("0x%04X"), shortaddr); + device.json->set(F(D_JSON_ZIGBEE_DEVICE), sa); + // Prepend Friendly Name if it has one + const String * fname = zigbee_devices.getFriendlyName(shortaddr); + if (fname) { + device.json->set(F(D_JSON_ZIGBEE_NAME), (char*)fname->c_str()); // (char*) forces ArduinoJson to make a copy of the cstring + } + // copy all values from 'values' to 'json' CopyJsonObject(*device.json, values); } @@ -643,13 +653,20 @@ void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { const String * fname = zigbee_devices.getFriendlyName(shortaddr); bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); // should we replace shortaddr with friendlyname? + // if (use_fname) { + // // we need to add the Device short_addr inside the JSON + // char sa[8]; + // snprintf_P(sa, sizeof(sa), PSTR("0x%04X"), shortaddr); + // json->set(F(D_JSON_ZIGBEE_DEVICE), sa); + // } else if (fname) { + // json->set(F(D_JSON_NAME), (char*) fname); + // } + + // Remove redundant "Name" or "Device" if (use_fname) { - // we need to add the Device short_addr inside the JSON - char sa[8]; - snprintf_P(sa, sizeof(sa), PSTR("0x%04X"), shortaddr); - json->set(F(D_JSON_ZIGBEE_DEVICE), sa); - } else if (fname) { - json->set(F(D_JSON_NAME), (char*) fname); + json->remove(F(D_JSON_ZIGBEE_NAME)); + } else { + json->remove(F(D_JSON_ZIGBEE_DEVICE)); } String msg = ""; diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index c32634f6b..1e683d059 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -32,7 +32,6 @@ const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; // Device announces its const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; // Node descriptor const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; // Endpoints descriptor const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; // Simple Descriptor (clusters) -const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; // Device announces its address const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 90d272a00..26185fd6c 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -432,16 +432,7 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); DynamicJsonBuffer jsonBuffer; - JsonObject& json_root = jsonBuffer.createObject(); - - JsonObject& json1 = json_root.createNestedObject(F(D_CMND_ZIGBEE_RECEIVED)); - - const String * fname = zigbee_devices.getFriendlyName(srcaddr); - bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); // should we replace shortaddr with friendlyname? - JsonObject& json = json1.createNestedObject(use_fname ? fname->c_str() : shortaddr); - if (use_fname) { - json[F(D_JSON_ZIGBEE_DEVICE)] = shortaddr; - } + JsonObject& json = jsonBuffer.createObject(); if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { zcl_received.parseRawAttributes(json); @@ -453,13 +444,8 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { } String msg(""); msg.reserve(100); - json_root.printTo(msg); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeZCLRawReceived: %s"), msg.c_str()); - - // Add friendly name - if ((!use_fname) && (fname)) { - json[F(D_JSON_ZIGBEE_NAME)] = (char*)fname->c_str(); // (char*) will force a copy of the string - } + json.printTo(msg); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZigbeeZCLRawReceived: {\"0x%04X\":%s}"), srcaddr, msg.c_str()); zcl_received.postProcessAttributes(srcaddr, json); // Add linkquality @@ -476,11 +462,7 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { } } else { // Publish immediately - msg = ""; - json_root.printTo(msg); - Response_P(PSTR("%s"), msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); + zigbee_devices.jsonPublishNow(srcaddr, json); } return -1; } diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 4464ab525..da73f9db7 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -575,10 +575,10 @@ void CmndZigbeeName(void) { if (p == nullptr) { const String * friendlyName = zigbee_devices.getFriendlyName(shortaddr); - Response_P(PSTR("{\"0x%04X\":{\"name\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName->c_str() : ""); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName->c_str() : ""); } else { zigbee_devices.setFriendlyName(shortaddr, p); - Response_P(PSTR("{\"0x%04X\":{\"name\":\"%s\"}}"), shortaddr, p); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, p); } } From 58a50cec8cec731db838cfda81b41410c3cfc6a0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 20 Jan 2020 10:05:12 +0100 Subject: [PATCH 059/160] Fix Zigbee compile error --- tasmota/xdrv_23_zigbee_7_statemachine.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index 1e683d059..683375bf1 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -32,6 +32,7 @@ const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; // Device announces its const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; // Node descriptor const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; // Endpoints descriptor const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; // Simple Descriptor (clusters) +const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; // Device announces its address const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version From e01c1b8c458671378867b90571d1269ab6a9dd7c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 20 Jan 2020 18:49:57 +0100 Subject: [PATCH 060/160] Add compile time control over SetOptions --- tasmota/my_user_config.h | 79 ++++++++++++++++++++++++++++++++++------ tasmota/settings.ino | 66 +++++++++++++++++++++++++-------- 2 files changed, 118 insertions(+), 27 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index f22023f6a..692320333 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -53,7 +53,7 @@ //#define MODULE SONOFF_BASIC // [Module] Select default model from tasmota_template.h #define SAVE_DATA 1 // [SaveData] Save changed parameters to Flash (0 = disable, 1 - 3600 seconds) -#define SAVE_STATE 1 // [SetOption0] Save changed power state to Flash (0 = disable, 1 = enable) +#define SAVE_STATE true // [SetOption0] Save changed power state to Flash (false = disable, true = enable) #define BOOT_LOOP_OFFSET 1 // [SetOption36] Number of boot loops before starting restoring defaults (0 = disable, 1..200 = boot loops offset) // -- Wifi ---------------------------------------- @@ -69,6 +69,8 @@ #define WIFI_CONFIG_TOOL WIFI_RETRY // [WifiConfig] Default tool if wifi fails to connect (default option: 4 - WIFI_RETRY) // (WIFI_RESTART, WIFI_MANAGER, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY) // The configuration can be changed after first setup using WifiConfig 0, 2, 4, 5, 6 and 7. +#define WIFI_SCAN_AT_RESTART false // [SetOption56] Scan wifi network at restart for configured AP's +#define WIFI_SCAN_REGULARLY false // [SetOption57] Scan wifi network every 44 minutes for configured AP's // -- Syslog -------------------------------------- #define SYS_LOG_HOST "" // [LogHost] (Linux) syslog host @@ -80,9 +82,10 @@ // -- Ota ----------------------------------------- #define OTA_URL "http://thehackbox.org/tasmota/release/tasmota.bin" // [OtaUrl] +#define OTA_COMPATIBILITY false // [SetOption78] Disable OTA compatibility check // -- MQTT ---------------------------------------- -#define MQTT_USE 1 // [SetOption3] Select default MQTT use (0 = Off, 1 = On) +#define MQTT_USE true // [SetOption3] Select default MQTT use (false = Off, true = On) #define MQTT_HOST "" // [MqttHost] #define MQTT_FINGERPRINT1 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" // [MqttFingerprint1] @@ -91,10 +94,10 @@ #define MQTT_USER "DVES_USER" // [MqttUser] MQTT user #define MQTT_PASS "DVES_PASS" // [MqttPassword] MQTT password -#define MQTT_BUTTON_RETAIN 0 // [ButtonRetain] Button may send retain flag (0 = off, 1 = on) -#define MQTT_POWER_RETAIN 0 // [PowerRetain] Power status message may send retain flag (0 = off, 1 = on) -#define MQTT_SWITCH_RETAIN 0 // [SwitchRetain] Switch may send retain flag (0 = off, 1 = on) -#define MQTT_BUTTON_SWITCH_FORCE_LOCAL 0 // [SetOption61] Force local operation when button/switch topic is set (0 = off, 1 = on) +#define MQTT_BUTTON_RETAIN false // [ButtonRetain] Button may send retain flag (false = off, true = on) +#define MQTT_POWER_RETAIN false // [PowerRetain] Power status message may send retain flag (false = off, true = on) +#define MQTT_SWITCH_RETAIN false // [SwitchRetain] Switch may send retain flag (false = off, true = on) +#define MQTT_BUTTON_SWITCH_FORCE_LOCAL false // [SetOption61] Force local operation when button/switch topic is set (false = off, true = on) #define MQTT_STATUS_OFF "OFF" // [StateText1] Command or Status result when turned off (needs to be a string like "0" or "Off") #define MQTT_STATUS_ON "ON" // [StateText2] Command or Status result when turned on (needs to be a string like "1" or "On") @@ -113,19 +116,30 @@ // %topic% token options (also ButtonTopic and SwitchTopic) #define MQTT_TOPIC PROJECT // [Topic] (unique) MQTT device topic, set to 'PROJECT "_%06X"' for unique topic including device MAC address #define MQTT_GRPTOPIC "tasmotas" // [GroupTopic] MQTT Group topic +#define MQTT_GROUPTOPIC_FORMAT false // [SetOption75] GroupTopic replaces %topic% (false) or fixed topic cmnd/grouptopic (true) #define MQTT_BUTTON_TOPIC "0" // [ButtonTopic] MQTT button topic, "0" = same as MQTT_TOPIC, set to 'PROJECT "_BTN_%06X"' for unique topic including device MAC address #define MQTT_SWITCH_TOPIC "0" // [SwitchTopic] MQTT button topic, "0" = same as MQTT_TOPIC, set to 'PROJECT "_SW_%06X"' for unique topic including device MAC address #define MQTT_CLIENT_ID "DVES_%06X" // [MqttClient] Also fall back topic using Chip Id = last 6 characters of MAC address // -- MQTT - Telemetry ---------------------------- #define TELE_PERIOD 300 // [TelePeriod] Telemetry (0 = disable, 10 - 3600 seconds) -#define TELE_ON_POWER 0 // [SetOption59] send tele/STATE together with stat/RESULT (0 = Disable, 1 = Enable) +#define TELE_ON_POWER false // [SetOption59] send tele/STATE together with stat/RESULT (false = Disable, true = Enable) // -- MQTT - Domoticz ----------------------------- #define DOMOTICZ_UPDATE_TIMER 0 // [DomoticzUpdateTimer] Send relay status (0 = disable, 1 - 3600 seconds) // -- MQTT - Home Assistant Discovery ------------- -#define HOME_ASSISTANT_DISCOVERY_ENABLE 0 // [SetOption19] Home Assistant Discovery (0 = Disable, 1 = Enable) +#define HOME_ASSISTANT_DISCOVERY_ENABLE false // [SetOption19] Home Assistant Discovery (false = Disable, true = Enable) +#define HASS_AS_LIGHT false // [SetOption30] Enforce HAss autodiscovery as light + +// -- MQTT - Options ------------------------------ +#define MQTT_RESULT_COMMAND false // [SetOption4] Switch between MQTT RESULT or COMMAND +#define MQTT_LWT_MESSAGE false // [SetOption10] Switch between MQTT LWT OFFLINE or empty message +#define MQTT_POWER_FORMAT false // [SetOption26] Switch between POWER or POWER1 for single power devices +#define MQTT_APPEND_TIMEZONE false // [SetOption52] Append timezone to JSON time +#define MQTT_NO_HOLD_RETAIN false // [SetOption62] Disable retain flag on HOLD messages +#define MQTT_INDEX_SEPARATOR false // [SetOption64] Enable "_" instead of "-" as sensor index separator +#define MQTT_TUYA_RECEIVED false // [SetOption66] Enable TuyaMcuReceived messages over Mqtt // -- HTTP ---------------------------------------- #define WEB_SERVER 2 // [WebServer] Web server (0 = Off, 1 = Start as User, 2 = Start as Admin) @@ -134,6 +148,9 @@ #define EMULATION EMUL_NONE // [Emulation] Select Belkin WeMo (single relay/light) or Hue Bridge emulation (multi relay/light) (EMUL_NONE, EMUL_WEMO or EMUL_HUE) #define CORS_DOMAIN "" // [Cors] CORS Domain for preflight requests +// -- HTTP Options -------------------------------- +#define GUI_SHOW_HOSTNAME false // [SetOption53] Show hostname and IP address in GUI main menu + // -- HTTP GUI Colors ----------------------------- // HTML hex color codes. Only 3 and 6 digit hex string values are supported!! See https://www.w3schools.com/colors/colors_hex.asp // Light theme - pre v7 @@ -182,7 +199,7 @@ #define COLOR_TITLE_TEXT "#eaeaea" // [WebColor19] Title text color - Very light gray // -- mDNS ---------------------------------------- -#define MDNS_ENABLED 0 // [SetOption55] Use mDNS (0 = Disable, 1 = Enable) +#define MDNS_ENABLED false // [SetOption55] Use mDNS (false = Disable, true = Enable) // -- Time - Up to three NTP servers in your region #define NTP_SERVER1 "pool.ntp.org" // [NtpServer1] Select first NTP server by name or IP address (129.250.35.250) @@ -214,28 +231,68 @@ #define APP_LEDSTATE LED_POWER // [LedState] Function of led // (LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT) #define APP_LEDMASK 0xFFFF // [LedMask] Assign Relay to Power led (0xFFFF is default) +#define APP_ENABLE_LEDLINK false // [SetOption31] Enable link led blinking + #define APP_PULSETIME 0 // [PulseTime] Time in 0.1 Sec to turn off power for relay 1 (0 = disabled) #define APP_POWERON_STATE POWER_ALL_SAVED // [PowerOnState] Power On Relay state // (POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON) #define APP_BLINKTIME 10 // [BlinkTime] Time in 0.1 Sec to blink/toggle power for relay 1 #define APP_BLINKCOUNT 10 // [BlinkCount] Number of blinks (0 = 32000) + +#define APP_NORMAL_SLEEP false // [SetOption60] Enable normal sleep instead of dynamic sleep #define APP_SLEEP 0 // [Sleep] Sleep time to lower energy consumption (0 = Off, 1 - 250 mSec), #define PWM_MAX_SLEEP 10 // Sleep will be lowered to this value when light is on, to avoid flickering #define KEY_DEBOUNCE_TIME 50 // [ButtonDebounce] Number of mSeconds button press debounce time #define KEY_HOLD_TIME 40 // [SetOption32] Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message +#define KEY_DISABLE_MULTIPRESS false // [SetOption1] Disable button multipress +#define KEY_SWAP_DOUBLE_PRESS false // [SetOption11] Swap button single and double press functionality +#define KEY_ONLY_SINGLE_PRESS false // [SetOption13] Enable only single press to speed up button press recognition + #define SWITCH_DEBOUNCE_TIME 50 // [SwitchDebounce] Number of mSeconds switch press debounce time #define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEMULTI, FOLLOWMULTI, FOLLOWMULTI_INV (the wall switch state) #define WS2812_LEDS 30 // [Pixels] Number of WS2812 LEDs to start with (max is 512) -#define TEMP_CONVERSION 0 // [SetOption8] Return temperature in (0 = Celsius or 1 = Fahrenheit) -#define PRESSURE_CONVERSION 0 // [SetOption24] Return pressure in (0 = hPa or 1 = mmHg) +#define TEMP_CONVERSION false // [SetOption8] Return temperature in (false = Celsius or true = Fahrenheit) +#define PRESSURE_CONVERSION false // [SetOption24] Return pressure in (false = hPa or true = mmHg) #define TEMP_RESOLUTION 1 // [TempRes] Maximum number of decimals (0 - 3) showing sensor Temperature #define HUMIDITY_RESOLUTION 1 // [HumRes] Maximum number of decimals (0 - 3) showing sensor Humidity #define PRESSURE_RESOLUTION 1 // [PressRes] Maximum number of decimals (0 - 3) showing sensor Pressure #define ENERGY_RESOLUTION 3 // [EnergyRes] Maximum number of decimals (0 - 5) showing energy usage in kWh #define CALC_RESOLUTION 3 // [CalcRes] Maximum number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE +#define APP_FLASH_CYCLE false // [SetOption12] Switch between dynamic or fixed slot flash save location +#define APP_NO_RELAY_SCAN false // [SetOption63] Don't scan relay power state at restart +#define APP_DISABLE_POWERCYCLE false // [SetOption65] Disable fast power cycle detection for device reset +#define DEEPSLEEP_BOOTCOUNT false // [SetOption76] Enable incrementing bootcount when deepsleep is enabled + +// -- Lights -------------------------------------- +#define LIGHT_MODE true // [SetOption15] Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL +#define LIGHT_CLOCK_DIRECTION false // [SetOption16] Switch WS2812 clock between clockwise or counter-clockwise +#define LIGHT_COLOR_RADIX false // [SetOption17] Switch between decimal or hexadecimal color output (false = hexadecimal, true = decimal) +#define LIGHT_PAIRS_CO2 false // [SetOption18] Enable Pair light signal with CO2 sensor +#define LIGHT_POWER_CONTROL false // [SetOption20] Enable power control in relation to Dimmer/Color/Ct changes +#define LIGHT_CHANNEL_MODE false // [SetOption68] Enable multi-channels PWM instead of Color PWM +#define LIGHT_SLIDER_POWER false // [SetOption77] Do not power off if slider moved to far left +#define LIGHT_ALEXA_CT_RANGE false // [SetOption82] Reduced CT range for Alexa + +// -- Energy -------------------------------------- +#define ENERGY_VOLTAGE_ALWAYS false // [SetOption21] Enable show voltage even if powered off +#define ENERGY_DDS2382_MODE false // [SetOption71] Enable DDS2382 different Modbus registers for Active Energy (#6531) +#define ENERGY_HARDWARE_TOTALS false // [SetOption72] Enable hardware energy total counter as reference (#6561) + +// -- Other Options ------------------------------- +#define RF_DATA_RADIX false // [SetOption28] RF receive data format (false = hexadecimal, true = decimal) +#define IR_DATA_RADIX false // [SetOption29] IR receive data format (false = hexadecimal, true = decimal) +#define TUYA_SETOPTION_20 false // [SetOption54] Apply SetOption20 settings to Tuya device +#define IR_ADD_RAW_DATA false // [SetOption58] Add IR Raw data to JSON message +#define BUZZER_ENABLE false // [SetOption67] Enable buzzer when available +#define DS18X20_PULL_UP false // [SetOption74] Enable internal pullup for single DS18x20 sensor +#define COUNTER_RESET false // [SetOption79] Enable resetting of counters after telemetry was sent +#define SHUTTER_SUPPORT false // [SetOption80] Enable shutter support +#define PCF8574_INVERT_PORTS false // [SetOption81] Invert all ports on PCF8574 devices +#define ZIGBEE_FRIENDLY_NAMES false // [SetOption83] Enable Zigbee FriendlyNames instead of ShortAddresses when possible + /*********************************************************************************************\ * END OF SECTION 1 * diff --git a/tasmota/settings.ino b/tasmota/settings.ino index a059b71e6..93c323e32 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -782,8 +782,13 @@ void SettingsDefaultSet2(void) { memset((char*)&Settings +16, 0x00, sizeof(SYSCFG) -16); -// Settings.flag.value_units = 0; -// Settings.flag.stop_flash_rotate = 0; + Settings.flag.stop_flash_rotate = APP_FLASH_CYCLE; + Settings.flag.global_state = APP_ENABLE_LEDLINK; + Settings.flag3.sleep_normal = APP_NORMAL_SLEEP; + Settings.flag3.no_power_feedback = APP_NO_RELAY_SCAN; + Settings.flag3.fast_power_cycle_disable = APP_DISABLE_POWERCYCLE; + Settings.flag3.bootcount_update = DEEPSLEEP_BOOTCOUNT; + Settings.flag3.compatibility_check = OTA_COMPATIBILITY; Settings.save_data = SAVE_DATA; Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; // SetOption36 @@ -824,6 +829,8 @@ void SettingsDefaultSet2(void) Settings.seriallog_level = SERIAL_LOG_LEVEL; // Wifi + Settings.flag3.use_wifi_scan = WIFI_SCAN_AT_RESTART; + Settings.flag3.use_wifi_rescan = WIFI_SCAN_REGULARLY; Settings.wifi_output_power = 170; ParseIp(&Settings.ip_address[0], WIFI_IP_ADDRESS); ParseIp(&Settings.ip_address[1], WIFI_GATEWAY); @@ -844,16 +851,17 @@ void SettingsDefaultSet2(void) // Webserver Settings.flag2.emulation = EMULATION; + Settings.flag3.gui_hostname_ip = GUI_SHOW_HOSTNAME; + Settings.flag3.mdns_enabled = MDNS_ENABLED; Settings.webserver = WEB_SERVER; Settings.weblog_level = WEB_LOG_LEVEL; SettingsUpdateText(SET_WEBPWD, WEB_PASSWORD); - Settings.flag3.mdns_enabled = MDNS_ENABLED; SettingsUpdateText(SET_CORS, CORS_DOMAIN); // Button -// Settings.flag.button_restrict = 0; -// Settings.flag.button_swap = 0; -// Settings.flag.button_single = 0; + Settings.flag.button_restrict = KEY_DISABLE_MULTIPRESS; + Settings.flag.button_swap = KEY_SWAP_DOUBLE_PRESS; + Settings.flag.button_single = KEY_ONLY_SINGLE_PRESS; Settings.param[P_HOLD_TIME] = KEY_HOLD_TIME; // Default 4 seconds hold time // Switch @@ -861,16 +869,19 @@ void SettingsDefaultSet2(void) // MQTT Settings.flag.mqtt_enabled = MQTT_USE; -// Settings.flag.mqtt_response = 0; + Settings.flag.mqtt_response = MQTT_RESULT_COMMAND; + Settings.flag.mqtt_offline = MQTT_LWT_MESSAGE; Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN; Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; - Settings.flag3.button_switch_force_local = MQTT_BUTTON_SWITCH_FORCE_LOCAL; - Settings.flag3.hass_tele_on_power = TELE_ON_POWER; // Settings.flag.mqtt_sensor_retain = 0; -// Settings.flag.mqtt_offline = 0; // Settings.flag.mqtt_serial = 0; -// Settings.flag.device_index_enable = 0; + Settings.flag.device_index_enable = MQTT_POWER_FORMAT; + Settings.flag3.time_append_timezone = MQTT_APPEND_TIMEZONE; + Settings.flag3.button_switch_force_local = MQTT_BUTTON_SWITCH_FORCE_LOCAL; + Settings.flag3.no_hold_retain = MQTT_NO_HOLD_RETAIN; + Settings.flag3.use_underscore = MQTT_INDEX_SEPARATOR; + Settings.flag3.grouptopic_mode = MQTT_GROUPTOPIC_FORMAT; SettingsUpdateText(SET_MQTT_HOST, MQTT_HOST); Settings.mqtt_port = MQTT_PORT; SettingsUpdateText(SET_MQTT_CLIENT, MQTT_CLIENT_ID); @@ -904,10 +915,13 @@ void SettingsDefaultSet2(void) Settings.mqttlog_level = MQTT_LOG_LEVEL; // Energy + Settings.flag.no_power_on_check = ENERGY_VOLTAGE_ALWAYS; Settings.flag2.current_resolution = 3; // Settings.flag2.voltage_resolution = 0; // Settings.flag2.wattage_resolution = 0; Settings.flag2.energy_resolution = ENERGY_RESOLUTION; + Settings.flag3.dds2382_model = ENERGY_DDS2382_MODE; + Settings.flag3.hardware_energy_total = ENERGY_HARDWARE_TOTALS; Settings.param[P_MAX_POWER_RETRY] = MAX_POWER_RETRY; // Settings.energy_power_delta = 0; Settings.energy_power_calibration = HLW_PREF_PULSE; @@ -937,9 +951,12 @@ void SettingsDefaultSet2(void) Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; // IRRemote + Settings.flag.ir_receive_decimal = IR_DATA_RADIX; + Settings.flag3.receive_raw = IR_ADD_RAW_DATA; Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; // RF Bridge + Settings.flag.rf_receive_decimal = RF_DATA_RADIX; // for (uint32_t i = 0; i < 17; i++) { Settings.rf_code[i][0] = 0; } memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); @@ -960,6 +977,8 @@ void SettingsDefaultSet2(void) Settings.flag2.pressure_resolution = PRESSURE_RESOLUTION; Settings.flag2.humidity_resolution = HUMIDITY_RESOLUTION; Settings.flag2.temperature_resolution = TEMP_RESOLUTION; + Settings.flag3.ds18x20_internal_pullup = DS18X20_PULL_UP; + Settings.flag3.counter_reset_on_tele = COUNTER_RESET; // Settings.altitude = 0; // Rules @@ -969,18 +988,24 @@ void SettingsDefaultSet2(void) Settings.flag2.calc_resolution = CALC_RESOLUTION; // Home Assistant + Settings.flag.hass_light = HASS_AS_LIGHT; Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE; + Settings.flag3.hass_tele_on_power = TELE_ON_POWER; // Knx // Settings.flag.knx_enabled = 0; // Settings.flag.knx_enable_enhancement = 0; // Light - Settings.flag.pwm_control = 1; - //Settings.flag.ws_clock_reverse = 0; - //Settings.flag.light_signal = 0; - //Settings.flag.not_power_linked = 0; - //Settings.flag.decimal_text = 0; + Settings.flag.pwm_control = LIGHT_MODE; + Settings.flag.ws_clock_reverse = LIGHT_CLOCK_DIRECTION; + Settings.flag.light_signal = LIGHT_PAIRS_CO2; + Settings.flag.not_power_linked = LIGHT_POWER_CONTROL; + Settings.flag.decimal_text = LIGHT_COLOR_RADIX; + Settings.flag3.pwm_multi_channels = LIGHT_CHANNEL_MODE; + Settings.flag3.slider_dimmer_stay_on = LIGHT_SLIDER_POWER; + Settings.flag4.alexa_ct_range = LIGHT_ALEXA_CT_RANGE; + Settings.pwm_frequency = PWM_FREQ; Settings.pwm_range = PWM_RANGE; for (uint32_t i = 0; i < MAX_PWMS; i++) { @@ -1064,6 +1089,15 @@ void SettingsDefaultSet2(void) memset(&Settings.monitors, 0xFF, 20); // Enable all possible monitors, displays and sensors SettingsEnableAllI2cDrivers(); + + // Tuya + Settings.flag3.tuya_apply_o20 = TUYA_SETOPTION_20; + Settings.flag3.tuya_serial_mqtt_publish = MQTT_TUYA_RECEIVED; + + Settings.flag3.buzzer_enable = BUZZER_ENABLE; + Settings.flag3.shutter_mode = SHUTTER_SUPPORT; + Settings.flag3.pcf8574_ports_inverted = PCF8574_INVERT_PORTS; + Settings.flag4.zigbee_use_names = ZIGBEE_FRIENDLY_NAMES; } /********************************************************************************************/ From 6d36f366595d9f451cf6962bc506001a47004a34 Mon Sep 17 00:00:00 2001 From: Staars Date: Mon, 20 Jan 2020 19:44:55 +0100 Subject: [PATCH 061/160] add support for LYWSD02 --- tasmota/xsns_61_MI_BLE.ino | 103 +++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/tasmota/xsns_61_MI_BLE.ino b/tasmota/xsns_61_MI_BLE.ino index 88983e533..c07323684 100644 --- a/tasmota/xsns_61_MI_BLE.ino +++ b/tasmota/xsns_61_MI_BLE.ino @@ -21,6 +21,8 @@ Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- + + 0.9.1.0 20200117 integrate - Added support for the LYWSD02 --- 0.9.0.0 20191127 started - further development by Christian Baars base - code base from cbm80amiga, floe, Dmitry.GR @@ -52,7 +54,7 @@ const char MIBLESlaveFlora[] PROGMEM = "Flora"; const char MIBLESlaveMJ_HT_V1[] PROGMEM = "MJ_HT_V1"; - +const char MIBLESlaveLYWSD02[] PROGMEM = "LYWSD02"; #pragma pack(1) // important!! struct MJ_HT_V1Header_t {// related to the payload @@ -148,6 +150,19 @@ union MJ_HT_V1Packet_t { // related to the whole 32-byte-packet/buffer // We do NOT need the isolated T and H packet }; +union LYWSD02Packet_t { // related to the whole 32-byte-packet/buffer + struct { + uint16_t idWord; + uint8_t padding; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint16_t data; + } TH; // mode 04 or 06 +}; + struct bleAdvPacket_t { // for nRF24L01 max 32 bytes = 2+6+24 uint8_t pduType; uint8_t payloadSize; @@ -205,6 +220,7 @@ union FIFO_t{ bleAdvPacket_t bleAdv; floraPacket_t floraPacket; MJ_HT_V1Packet_t MJ_HT_V1Packet; + LYWSD02Packet_t LYWSD02Packet; uint8_t raw[32]; }; @@ -227,7 +243,7 @@ struct { } MIBLE; struct mi_sensor_t{ - uint8_t type; //flora = 1; MI-HT_V1=2 + uint8_t type; //flora = 1; MI-HT_V1=2; LYWSD02=3 uint8_t serial[6]; uint8_t showedUp; union { @@ -242,6 +258,10 @@ struct mi_sensor_t{ float hum; uint8_t bat; } MJ_HT_V1; + struct { + float temp; + float hum; + } LYWSD02; }; }; @@ -312,6 +332,9 @@ bool MIBLEreceivePacket(void) case 2: MIBLEwhiten((uint8_t *)&MIBLE.buffer, sizeof(MIBLE.buffer), 0x72); // "MJ_HT_V1" mode 0x72 break; + case 3: + MIBLEwhiten((uint8_t *)&MIBLE.buffer, sizeof(MIBLE.buffer), 0x17); // "LYWSD02" mode 0x17 + break; } // DEBUG_SENSOR_LOG(PSTR("MIBLE: LSFR:%x"),_lsfr); // if (_lsfr>254) _lsfr=0; @@ -403,6 +426,9 @@ void MIBLEchangePacketModeTo(uint8_t _mode) { case 2: // special MJ_HT_V1 packet NRF24radio.openReadingPipe(0,0xdbcc0cd3); // 95 fe 50 20 -> MJ_HT_V1, needs lsfr 0x72 break; + case 3: // special LYWSD02 packet + NRF24radio.openReadingPipe(0,0xef3b0730); // 95 fe 70 20 -> LYWSD02, needs lfsr 0x17 + break; } DEBUG_SENSOR_LOG(PSTR("MIBLE: Change Mode to %u"),_mode); MIBLE.timer = 0; @@ -447,6 +473,10 @@ uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ _newSensor.MJ_HT_V1.hum=-1.0f; _newSensor.MJ_HT_V1.bat=0xff; break; + case 3: + _newSensor.LYWSD02.temp=-1000.0f; + _newSensor.LYWSD02.hum=-1.0f; + break; default: break; } @@ -544,7 +574,34 @@ void MIBLEhandleMJ_HT_V1Packet(void){ DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1 mode:0x0a: U8: %x %%"), MIBLE.buffer.MJ_HT_V1Packet.B.battery); break; } +} +void MIBLEhandleLYWSD02Packet(void){ + if(MIBLE.buffer.LYWSD02Packet.TH.valueTen!=0x10){ + DEBUG_SENSOR_LOG(PSTR("MIBLE: unexpected LYWSD02-packet")); + MIBLE_LOG_BUFFER(MIBLE.buffer.raw); + return; + } + uint32_t _slot = MIBLEgetSensorSlot(MIBLE.buffer.LYWSD02Packet.TH.serial, 3); // H would be possible too + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + + static float _tempFloat; + switch(MIBLE.buffer.LYWSD02Packet.TH.mode) { // we can use any struct with a mode, they are all same at this point + case 4: + _tempFloat=(float)(MIBLE.buffer.LYWSD02Packet.TH.data)/10.0f; + if(_tempFloat<60){ + MIBLEsensors.at(_slot).LYWSD02.temp=_tempFloat; + } + DEBUG_SENSOR_LOG(PSTR("LYWSD02: Mode 4: U16: %x Temp"), MIBLE.buffer.LYWSD02Packet.TH.data ); + break; + case 6: + _tempFloat=(float)(MIBLE.buffer.LYWSD02Packet.TH.data)/10.0f; + if(_tempFloat<101){ + MIBLEsensors.at(_slot).LYWSD02.hum=_tempFloat; + } + DEBUG_SENSOR_LOG(PSTR("LYWSD02: Mode 6: U16: %x Hum"), MIBLE.buffer.LYWSD02Packet.TH.data ); + break; + } } void MIBLE_EVERY_100_MSECOND() { // Every 100mseconds, with many sensors 50ms could make sense @@ -555,7 +612,7 @@ void MIBLE_EVERY_100_MSECOND() { // Every 100mseconds, with many sensors 50ms co MIBLEpurgeFakeSensors(); } DEBUG_SENSOR_LOG(PSTR("MIBLE: Change packet mode after 60 seconds, MIBLE.timer: %u"),MIBLE.timer); - if (MIBLE.packetMode == 2){ + if (MIBLE.packetMode == 3){ MIBLEinitBLE(1); // no real ble packets in release mode, otherwise for developing use 0 } else { @@ -592,7 +649,10 @@ void MIBLE_EVERY_100_MSECOND() { // Every 100mseconds, with many sensors 50ms co } if (MIBLE.packetMode == 2){ // "MJ_HT_V1" mode MIBLEhandleMJ_HT_V1Packet(); - } + } + if (MIBLE.packetMode == 3){ // "LYWSD02" mode + MIBLEhandleLYWSD02Packet(); + } MIBLEhopChannel(); NRF24radio.startListening(); @@ -666,6 +726,23 @@ void MIBLEShow(bool json) } ResponseAppend_P(PSTR("}")); break; + case 3: + if(MIBLEsensors.at(i).showedUp < 3){ + DEBUG_SENSOR_LOG(PSTR("MIBLE: sensor not fully registered yet")); + break; + } + sprintf_P(slave,"%s-%02x%02x%02x",MIBLESlaveLYWSD02,MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[0]); + dtostrfd(MIBLEsensors.at(i).LYWSD02.temp, Settings.flag2.temperature_resolution, temperature); + dtostrfd(MIBLEsensors.at(i).LYWSD02.hum, 1, humidity); + ResponseAppend_P(PSTR(",\"%s\":{"),slave); + if(MIBLEsensors.at(i).LYWSD02.temp!=-1000.0f){ // this is the error code -> no temperature + ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); + } + if(MIBLEsensors.at(i).LYWSD02.hum!=-1000.0f){ // this is the error code -> no temperature + ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); + } + ResponseAppend_P(PSTR("}")); + break; } } #ifdef USE_WEBSERVER @@ -721,11 +798,27 @@ void MIBLEShow(bool json) } if(MIBLEsensors.at(i).MJ_HT_V1.bat!=0xff){ WSContentSend_PD(HTTP_BATTERY, MIBLESlaveMJ_HT_V1, MIBLEsensors.at(i).MJ_HT_V1.bat); + } + break; + case 3: + if(MIBLEsensors.at(i).showedUp < 3){ + DEBUG_SENSOR_LOG(PSTR("MIBLE: sensor not fully registered yet")); + break; + } + dtostrfd(MIBLEsensors.at(i).LYWSD02.temp, Settings.flag2.temperature_resolution, temperature); + dtostrfd(MIBLEsensors.at(i).LYWSD02.hum, 1, humidity); + + WSContentSend_PD(HTTP_MIBLE_SERIAL, MIBLESlaveLYWSD02, MIBLEsensors.at(i).serial[5], MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[0]); + if(MIBLEsensors.at(i).LYWSD02.temp!=-1000.0f){ + WSContentSend_PD(HTTP_SNS_TEMP, MIBLESlaveLYWSD02, temperature, TempUnit()); + } + if(MIBLEsensors.at(i).LYWSD02.hum!=-1.0f){ + WSContentSend_PD(HTTP_SNS_HUM, MIBLESlaveLYWSD02, humidity); + } break; } } } - } #endif // USE_WEBSERVER } From 760f4e49ac88c0d26f69a4d694a40138105ae8b3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 21 Jan 2020 12:36:44 +0100 Subject: [PATCH 062/160] Add compile time control over settings --- tasmota/my_user_config.h | 12 +++++++++--- tasmota/settings.ino | 9 ++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 692320333..ec40b4c8d 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -97,6 +97,7 @@ #define MQTT_BUTTON_RETAIN false // [ButtonRetain] Button may send retain flag (false = off, true = on) #define MQTT_POWER_RETAIN false // [PowerRetain] Power status message may send retain flag (false = off, true = on) #define MQTT_SWITCH_RETAIN false // [SwitchRetain] Switch may send retain flag (false = off, true = on) +#define MQTT_SENSOR_RETAIN false // [SensorRetain] Sensor may send retain flag (false = off, true = on) #define MQTT_BUTTON_SWITCH_FORCE_LOCAL false // [SetOption61] Force local operation when button/switch topic is set (false = off, true = on) #define MQTT_STATUS_OFF "OFF" // [StateText1] Command or Status result when turned off (needs to be a string like "0" or "Off") @@ -198,6 +199,10 @@ #define COLOR_TIMER_TAB_BACKGROUND "#999" // [WebColor18] Config timer tab background color - Dark gray #define COLOR_TITLE_TEXT "#eaeaea" // [WebColor19] Title text color - Very light gray +// -- KNX ----------------------------------------- +#define KNX_ENABLED false // [Knx_Enabled] Enable KNX protocol +#define KNX_ENHANCED false // [Knx_Enhanced] Enable KNX Enhanced Mode + // -- mDNS ---------------------------------------- #define MDNS_ENABLED false // [SetOption55] Use mDNS (false = Disable, true = Enable) @@ -251,7 +256,6 @@ #define SWITCH_DEBOUNCE_TIME 50 // [SwitchDebounce] Number of mSeconds switch press debounce time #define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEMULTI, FOLLOWMULTI, FOLLOWMULTI_INV (the wall switch state) -#define WS2812_LEDS 30 // [Pixels] Number of WS2812 LEDs to start with (max is 512) #define TEMP_CONVERSION false // [SetOption8] Return temperature in (false = Celsius or true = Fahrenheit) #define PRESSURE_CONVERSION false // [SetOption24] Return pressure in (false = hPa or true = mmHg) @@ -264,9 +268,10 @@ #define APP_FLASH_CYCLE false // [SetOption12] Switch between dynamic or fixed slot flash save location #define APP_NO_RELAY_SCAN false // [SetOption63] Don't scan relay power state at restart #define APP_DISABLE_POWERCYCLE false // [SetOption65] Disable fast power cycle detection for device reset -#define DEEPSLEEP_BOOTCOUNT false // [SetOption76] Enable incrementing bootcount when deepsleep is enabled +#define DEEPSLEEP_BOOTCOUNT false // [SetOption76] Enable incrementing bootcount when deepsleep is enabled // -- Lights -------------------------------------- +#define WS2812_LEDS 30 // [Pixels] Number of WS2812 LEDs to start with (max is 512) #define LIGHT_MODE true // [SetOption15] Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL #define LIGHT_CLOCK_DIRECTION false // [SetOption16] Switch WS2812 clock between clockwise or counter-clockwise #define LIGHT_COLOR_RADIX false // [SetOption17] Switch between decimal or hexadecimal color output (false = hexadecimal, true = decimal) @@ -279,9 +284,10 @@ // -- Energy -------------------------------------- #define ENERGY_VOLTAGE_ALWAYS false // [SetOption21] Enable show voltage even if powered off #define ENERGY_DDS2382_MODE false // [SetOption71] Enable DDS2382 different Modbus registers for Active Energy (#6531) -#define ENERGY_HARDWARE_TOTALS false // [SetOption72] Enable hardware energy total counter as reference (#6561) +#define ENERGY_HARDWARE_TOTALS false // [SetOption72] Enable hardware energy total counter as reference (#6561) // -- Other Options ------------------------------- +#define TIMERS_ENABLED false // [Timers] Enable Timers #define RF_DATA_RADIX false // [SetOption28] RF receive data format (false = hexadecimal, true = decimal) #define IR_DATA_RADIX false // [SetOption29] IR receive data format (false = hexadecimal, true = decimal) #define TUYA_SETOPTION_20 false // [SetOption54] Apply SetOption20 settings to Tuya device diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 93c323e32..363ebbd9f 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -874,7 +874,7 @@ void SettingsDefaultSet2(void) Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN; Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; -// Settings.flag.mqtt_sensor_retain = 0; + Settings.flag.mqtt_sensor_retain = MQTT_SENSOR_RETAIN; // Settings.flag.mqtt_serial = 0; Settings.flag.device_index_enable = MQTT_POWER_FORMAT; Settings.flag3.time_append_timezone = MQTT_APPEND_TIMEZONE; @@ -987,14 +987,17 @@ void SettingsDefaultSet2(void) // for (uint32_t i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; } Settings.flag2.calc_resolution = CALC_RESOLUTION; + // Timer + Settings.flag3.timers_enable = TIMERS_ENABLED; + // Home Assistant Settings.flag.hass_light = HASS_AS_LIGHT; Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE; Settings.flag3.hass_tele_on_power = TELE_ON_POWER; // Knx -// Settings.flag.knx_enabled = 0; -// Settings.flag.knx_enable_enhancement = 0; + Settings.flag.knx_enabled = KNX_ENABLED; + Settings.flag.knx_enable_enhancement = KNX_ENHANCED; // Light Settings.flag.pwm_control = LIGHT_MODE; From a61c028b6608a02ec54524bcbb0b8c1ccb6b39f1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 21 Jan 2020 16:38:55 +0100 Subject: [PATCH 063/160] Add SoftwareSerial to CSE7766 driver Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) --- RELEASENOTES.md | 2 + tasmota/CHANGELOG.md | 2 + tasmota/xnrg_02_cse7766.ino | 116 +++++++++++++++++++++++------------- 3 files changed, 77 insertions(+), 43 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ce6c4963f..993c285d4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -80,3 +80,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support to BMP driver to enter reset state (sleep enable) when deep sleep is used in Tasmota - Add support for gzipped binaries - Add web page sliders when ``SetOption37 128`` is active allowing control of white(s) +- Add most SetOptions as defines to my_user_config.h +- Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index ccffecfdc..98f48c7a8 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -6,6 +6,8 @@ - Fix OTA minimal gzipped detection regression from 8.1.0.3 - Add web page sliders when ``SetOption37 128`` is active allowing control of white(s) - Add Zigbee persistence and friendly names +- Add most SetOptions as defines to my_user_config.h +- Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) ### 8.1.0.3 20200106 diff --git a/tasmota/xnrg_02_cse7766.ino b/tasmota/xnrg_02_cse7766.ino index 45001b55e..a95505c3b 100644 --- a/tasmota/xnrg_02_cse7766.ino +++ b/tasmota/xnrg_02_cse7766.ino @@ -20,7 +20,7 @@ #ifdef USE_ENERGY_SENSOR #ifdef USE_CSE7766 /*********************************************************************************************\ - * CSE7766 - Energy (Sonoff S31 and Sonoff Pow R2) + * CSE7759 and CSE7766 - Energy (Sonoff S31 and Sonoff Pow R2) * HLW8032 - Energy (Blitzwolf SHP5) * * Based on datasheet from http://www.chipsea.com/UploadFiles/2017/08/11144342F01B5662.pdf @@ -37,6 +37,12 @@ #define CSE_PREF 1000 #define CSE_UREF 100 +#define CSE_BUFFER_SIZE 25 + +#include + +TasmotaSerial *CseSerial = nullptr; + struct CSE { long voltage_cycle = 0; long current_cycle = 0; @@ -45,6 +51,8 @@ struct CSE { long cf_pulses = 0; long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + int byte_counter = 0; + uint8_t *rx_buffer = nullptr; uint8_t power_invalid = 0; bool received = false; } Cse; @@ -57,7 +65,7 @@ void CseReceived(void) // 55 5A 02 F7 60 00 03 AB 00 40 10 02 60 5D 51 A6 58 03 E9 EF 71 0B 7A 36 - 55 = Ok, 71 = Ok // Hd Id VCal---- Voltage- ICal---- Current- PCal---- Power--- Ad CF--- Ck - uint8_t header = serial_in_buffer[0]; + uint8_t header = Cse.rx_buffer[0]; if ((header & 0xFC) == 0xFC) { AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Abnormal hardware")); return; @@ -67,30 +75,30 @@ void CseReceived(void) if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { long voltage_coefficient = 191200; // uSec if (CSE_NOT_CALIBRATED != header) { - voltage_coefficient = serial_in_buffer[2] << 16 | serial_in_buffer[3] << 8 | serial_in_buffer[4]; + voltage_coefficient = Cse.rx_buffer[2] << 16 | Cse.rx_buffer[3] << 8 | Cse.rx_buffer[4]; } Settings.energy_voltage_calibration = voltage_coefficient / CSE_UREF; } if (HLW_IREF_PULSE == Settings.energy_current_calibration) { long current_coefficient = 16140; // uSec if (CSE_NOT_CALIBRATED != header) { - current_coefficient = serial_in_buffer[8] << 16 | serial_in_buffer[9] << 8 | serial_in_buffer[10]; + current_coefficient = Cse.rx_buffer[8] << 16 | Cse.rx_buffer[9] << 8 | Cse.rx_buffer[10]; } Settings.energy_current_calibration = current_coefficient; } if (HLW_PREF_PULSE == Settings.energy_power_calibration) { long power_coefficient = 5364000; // uSec if (CSE_NOT_CALIBRATED != header) { - power_coefficient = serial_in_buffer[14] << 16 | serial_in_buffer[15] << 8 | serial_in_buffer[16]; + power_coefficient = Cse.rx_buffer[14] << 16 | Cse.rx_buffer[15] << 8 | Cse.rx_buffer[16]; } Settings.energy_power_calibration = power_coefficient / CSE_PREF; } - uint8_t adjustement = serial_in_buffer[20]; - Cse.voltage_cycle = serial_in_buffer[5] << 16 | serial_in_buffer[6] << 8 | serial_in_buffer[7]; - Cse.current_cycle = serial_in_buffer[11] << 16 | serial_in_buffer[12] << 8 | serial_in_buffer[13]; - Cse.power_cycle = serial_in_buffer[17] << 16 | serial_in_buffer[18] << 8 | serial_in_buffer[19]; - Cse.cf_pulses = serial_in_buffer[21] << 8 | serial_in_buffer[22]; + uint8_t adjustement = Cse.rx_buffer[20]; + Cse.voltage_cycle = Cse.rx_buffer[5] << 16 | Cse.rx_buffer[6] << 8 | Cse.rx_buffer[7]; + Cse.current_cycle = Cse.rx_buffer[11] << 16 | Cse.rx_buffer[12] << 8 | Cse.rx_buffer[13]; + Cse.power_cycle = Cse.rx_buffer[17] << 16 | Cse.rx_buffer[18] << 8 | Cse.rx_buffer[19]; + Cse.cf_pulses = Cse.rx_buffer[21] << 8 | Cse.rx_buffer[22]; if (Energy.power_on) { // Powered on if (adjustement & 0x40) { // Voltage valid @@ -134,41 +142,44 @@ void CseReceived(void) bool CseSerialInput(void) { - if (Cse.received) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (24 == serial_in_byte_counter) { + while (CseSerial->available()) { + yield(); + uint8_t serial_in_byte = CseSerial->read(); - AddLogSerial(LOG_LEVEL_DEBUG_MORE); + if (Cse.received) { + Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; + if (24 == Cse.byte_counter) { - uint8_t checksum = 0; - for (uint32_t i = 2; i < 23; i++) { checksum += serial_in_buffer[i]; } - if (checksum == serial_in_buffer[23]) { - Energy.data_valid[0] = 0; - CseReceived(); - Cse.received = false; - return true; - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); - do { // Sync buffer with data (issue #1907 and #3425) - memmove(serial_in_buffer, serial_in_buffer +1, 24); - serial_in_byte_counter--; - } while ((serial_in_byte_counter > 2) && (0x5A != serial_in_buffer[1])); - if (0x5A != serial_in_buffer[1]) { + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, Cse.rx_buffer, 24); + + uint8_t checksum = 0; + for (uint32_t i = 2; i < 23; i++) { checksum += Cse.rx_buffer[i]; } + if (checksum == Cse.rx_buffer[23]) { + Energy.data_valid[0] = 0; + CseReceived(); Cse.received = false; - serial_in_byte_counter = 0; + return true; + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); + do { // Sync buffer with data (issue #1907 and #3425) + memmove(Cse.rx_buffer, Cse.rx_buffer +1, 24); + Cse.byte_counter--; + } while ((Cse.byte_counter > 2) && (0x5A != Cse.rx_buffer[1])); + if (0x5A != Cse.rx_buffer[1]) { + Cse.received = false; + Cse.byte_counter = 0; + } } } - } - } else { - if ((0x5A == serial_in_byte) && (1 == serial_in_byte_counter)) { // 0x5A - Packet header 2 - Cse.received = true; } else { - serial_in_byte_counter = 0; + if ((0x5A == serial_in_byte) && (1 == Cse.byte_counter)) { // 0x5A - Packet header 2 + Cse.received = true; + } else { + Cse.byte_counter = 0; + } + Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; } - serial_in_byte = 0; // Discard - return false; } /********************************************************************************************/ @@ -209,15 +220,31 @@ void CseEverySecond(void) } } -void CseDrvInit(void) +void CseSnsInit(void) { - if ((3 == pin[GPIO_CSE7766_RX]) && (1 == pin[GPIO_CSE7766_TX])) { // As it uses 8E1 currently only hardware serial is supported - SetSerial(4800, TS_SERIAL_8E1); + // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions + CseSerial = new TasmotaSerial(pin[GPIO_CSE7766_RX], pin[GPIO_CSE7766_TX], 1); + if (CseSerial->begin(4800, 2)) { // Fake Software Serial 8E1 by using two stop bits + if (CseSerial->hardwareSerial()) { + SetSerial(4800, TS_SERIAL_8E1); + ClaimSerial(); + } if (0 == Settings.param[P_CSE7766_INVALID_POWER]) { Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; // SetOption39 1..255 } Cse.power_invalid = Settings.param[P_CSE7766_INVALID_POWER]; - energy_flg = XNRG_02; + } else { + energy_flg = ENERGY_NONE; + } +} + +void CseDrvInit(void) +{ + Cse.rx_buffer = (uint8_t*)(malloc(CSE_BUFFER_SIZE)); + if (Cse.rx_buffer != nullptr) { + if ((pin[GPIO_CSE7766_RX] < 99) && (pin[GPIO_CSE7766_TX] < 99)) { + energy_flg = XNRG_02; + } } } @@ -254,8 +281,8 @@ bool Xnrg02(uint8_t function) bool result = false; switch (function) { - case FUNC_SERIAL: - result = CseSerialInput(); + case FUNC_LOOP: + if (CseSerial) { CseSerialInput(); } break; case FUNC_ENERGY_EVERY_SECOND: CseEverySecond(); @@ -263,6 +290,9 @@ bool Xnrg02(uint8_t function) case FUNC_COMMAND: result = CseCommand(); break; + case FUNC_INIT: + CseSnsInit(); + break; case FUNC_PRE_INIT: CseDrvInit(); break; From 38b344fcea438e793391fea1ceb8130ea0956c2c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 21 Jan 2020 17:10:08 +0100 Subject: [PATCH 064/160] Remove the need for GPIO_CSE7766_TX --- tasmota/xnrg_02_cse7766.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/xnrg_02_cse7766.ino b/tasmota/xnrg_02_cse7766.ino index a95505c3b..d7bb93665 100644 --- a/tasmota/xnrg_02_cse7766.ino +++ b/tasmota/xnrg_02_cse7766.ino @@ -223,7 +223,8 @@ void CseEverySecond(void) void CseSnsInit(void) { // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions - CseSerial = new TasmotaSerial(pin[GPIO_CSE7766_RX], pin[GPIO_CSE7766_TX], 1); +// CseSerial = new TasmotaSerial(pin[GPIO_CSE7766_RX], pin[GPIO_CSE7766_TX], 1); + CseSerial = new TasmotaSerial(pin[GPIO_CSE7766_RX], -1, 1); if (CseSerial->begin(4800, 2)) { // Fake Software Serial 8E1 by using two stop bits if (CseSerial->hardwareSerial()) { SetSerial(4800, TS_SERIAL_8E1); @@ -242,7 +243,8 @@ void CseDrvInit(void) { Cse.rx_buffer = (uint8_t*)(malloc(CSE_BUFFER_SIZE)); if (Cse.rx_buffer != nullptr) { - if ((pin[GPIO_CSE7766_RX] < 99) && (pin[GPIO_CSE7766_TX] < 99)) { +// if ((pin[GPIO_CSE7766_RX] < 99) && (pin[GPIO_CSE7766_TX] < 99)) { + if (pin[GPIO_CSE7766_RX] < 99) { energy_flg = XNRG_02; } } From fb485dabd3c3c436b327d4b101b508fcd87a8ab7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 Jan 2020 11:55:48 +0100 Subject: [PATCH 065/160] Add optional parameter to command ``Scheme`` Add optional parameter to command ``Scheme , `` to control initial start color --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/support.ino | 11 +++++++++++ tasmota/tasmota_template.h | 2 +- tasmota/xdrv_03_energy.ino | 23 ++++++++--------------- tasmota/xdrv_04_light.ino | 14 ++++++-------- tasmota/xdrv_24_buzzer.ino | 7 +------ 7 files changed, 29 insertions(+), 30 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 993c285d4..5eef31626 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -82,3 +82,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add web page sliders when ``SetOption37 128`` is active allowing control of white(s) - Add most SetOptions as defines to my_user_config.h - Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) +- Add optional parameter to command ``Scheme , `` to control initial start color diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 98f48c7a8..9285bdda1 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -8,6 +8,7 @@ - Add Zigbee persistence and friendly names - Add most SetOptions as defines to my_user_config.h - Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) +- Add optional parameter to command ``Scheme , `` to control initial start color ### 8.1.0.3 20200106 diff --git a/tasmota/support.ino b/tasmota/support.ino index 94def5a6f..0a281bc68 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -493,6 +493,17 @@ bool ParseIp(uint32_t* addr, const char* str) return (3 == i); } +uint32_t ParseParameters(uint32_t count, uint32_t *params) +{ + char *p; + uint32_t i = 0; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p)) { + params[i] = strtoul(str, nullptr, 0); + i++; + } + return i; +} + // Function to parse & check if version_str is newer than our currently installed version. bool NewerVersion(char* version_str) { diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 1793902eb..9bb98ce6e 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -169,7 +169,7 @@ enum UserSelectablePins { GPIO_SM16716_SEL, // SM16716 SELECT GPIO_DI, // my92x1 PWM input GPIO_DCKI, // my92x1 CLK input - GPIO_CSE7766_TX, // CSE7766 Serial interface (S31 and Pow R2) + GPIO_CSE7766_TX, // CSE7766 Serial interface (S31 and Pow R2) - Not used anymore 20200121 GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2) GPIO_ARIRFRCV, // AriLux RF Receive input GPIO_TXD, // Serial interface diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index 166fd7aa8..4573d2406 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -522,26 +522,19 @@ void CmndEnergyReset(void) } } else if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - int32_t position = -1; - uint32_t values[2]; - - while ((str != nullptr) && (position < 1)) { - uint32_t value = strtoul(str, nullptr, 10); - position++; - values[position] = value *100; - str = strtok_r(nullptr, ", ", &p); - } + uint32_t values[2] = { 0 }; + uint32_t position = ParseParameters(2, values); + values[0] *= 100; + values[1] *= 100; switch (XdrvMailbox.index) { case 4: // Reset energy_usage.usage totals - if (position > -1) { + if (position > 0) { RtcSettings.energy_usage.usage1_kWhtotal = values[0]; } - if (position > 0) { + if (position > 1) { RtcSettings.energy_usage.usage2_kWhtotal = values[1]; } Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal; @@ -549,10 +542,10 @@ void CmndEnergyReset(void) break; case 5: // Reset energy_usage.return totals - if (position > -1) { + if (position > 0) { RtcSettings.energy_usage.return1_kWhtotal = values[0]; } - if (position > 0) { + if (position > 1) { RtcSettings.energy_usage.return2_kWhtotal = values[1]; } Settings.energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal; diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index d217b75c7..48cc2d283 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2311,6 +2311,10 @@ void CmndScheme(void) } } if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= max_scheme)) { + uint32_t parm[2]; + if (ParseParameters(2, parm) > 1) { + Light.wheel = parm[1]; + } Settings.light_scheme = XdrvMailbox.payload; if (LS_WAKEUP == Settings.light_scheme) { Light.wakeup_active = 3; @@ -2403,16 +2407,10 @@ void CmndDimmer(void) void CmndDimmerRange(void) { if (XdrvMailbox.data_len > 0) { - char *p; - uint8_t i = 0; - uint16_t parm[2]; + uint32_t parm[2]; parm[0] = Settings.dimmer_hw_min; parm[1] = Settings.dimmer_hw_max; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { - parm[i] = strtoul(str, nullptr, 0); - i++; - } - + ParseParameters(2, parm); if (parm[0] < parm[1]) { Settings.dimmer_hw_min = parm[0]; Settings.dimmer_hw_max = parm[1]; diff --git a/tasmota/xdrv_24_buzzer.ino b/tasmota/xdrv_24_buzzer.ino index 9cfa7e111..78246f0f6 100644 --- a/tasmota/xdrv_24_buzzer.ino +++ b/tasmota/xdrv_24_buzzer.ino @@ -155,13 +155,8 @@ void CmndBuzzer(void) if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.payload > 0) { - char *p; - uint32_t i = 0; uint32_t parm[4] = { 0 }; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 4; str = strtok_r(nullptr, ", ", &p)) { - parm[i] = strtoul(str, nullptr, 0); - i++; - } + ParseParameters(4, parm); for (uint32_t i = 0; i < 3; i++) { if (parm[i] < 1) { parm[i] = 1; } // Default Count, On time, Off time } From 6e812627098c77b533ceb40a891d29a01ead29d4 Mon Sep 17 00:00:00 2001 From: to-scho Date: Wed, 22 Jan 2020 13:23:59 +0100 Subject: [PATCH 066/160] Shutterbutton to MQTT and rules --- tasmota/xdrv_27_shutter.ino | 161 ++++++++++++++++++++---------------- 1 file changed, 89 insertions(+), 72 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index f7a574714..e112416b1 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -34,7 +34,7 @@ uint16_t messwerte[5] = {30,50,70,90,100}; uint16_t last_execute_step; enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE, SHT_OFF_ON__OPEN_CLOSE_STEPPER,}; -enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; +enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" @@ -48,7 +48,8 @@ void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime}; -const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; + const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; + const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; #include @@ -244,7 +245,7 @@ void ShutterInit(void) // terminate loop at first INVALID shutter. break; } - + ShutterLimitRealAndTargetPositions(i); Settings.shutter_accuracy = 1; } } @@ -556,28 +557,27 @@ void ShutterButtonHandler(void) } } if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10)) { // press still valid && SetOption32 (40) - Button hold - if (!Settings.flag.button_restrict) { // no SetOption1 (0) - // check for simultaneous shutter button hold - if (ShutterButtonIsSimultaneousHold(button_index)) { - // simultaneous shutter button hold detected - for (uint32_t i = 0; i < MAX_KEYS; i++) - if (Settings.shutter_button[i] & (1<<31)) - Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings - } + // check for simultaneous shutter button hold + if (ShutterButtonIsSimultaneousHold(button_index)) { + // simultaneous shutter button hold detected + for (uint32_t i = 0; i < MAX_KEYS; i++) + if (Settings.shutter_button[i] & (1<<31)) + Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings + press_index = 0; + buttonState = SHT_PRESSED_HOLD_SIMULTANEOUS; } - if (Button.press_counter[button_index]<99) + if (Button.press_counter[button_index]<99) { + press_index = 0; buttonState = SHT_PRESSED_HOLD; + } Button.press_counter[button_index] = 0; } - if ((!Settings.flag.button_restrict) && (Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { // no SetOption1 (0) && SetOption32 (40) - Button held for factor times longer + if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer // check for simultaneous shutter button extend hold if (ShutterButtonIsSimultaneousHold(button_index)) { // simultaneous shutter button extend hold detected - char scmnd[20]; + press_index = 0; buttonState = SHT_PRESSED_EXT_HOLD_SIMULTANEOUS; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - ExecuteCommand(scmnd, SRC_BUTTON); - return; } } } @@ -589,29 +589,23 @@ void ShutterButtonHandler(void) } else { if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0)) { if (Button.press_counter[button_index]<99) { - if ((!Settings.flag.button_restrict) && (Button.press_counter[button_index]>=5)) { // no SetOption1 (0) && 5x or more presses - // check for simultaneous shutter button press >3 - uint32 min_shutterbutton_press_counter = -1; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((Settings.shutter_button[i] & (1<<31)) && (Button.press_counter[i] < min_shutterbutton_press_counter)) - min_shutterbutton_press_counter = Button.press_counter[i]; - } - if (min_shutterbutton_press_counter >= Button.press_counter[button_index]-2) { - char scmnd[20]; - // simultaneous shutter button press >3 detected - press_index = Button.press_counter[button_index]; - for (uint32_t i = 0; i < MAX_KEYS; i++) - if (Settings.shutter_button[i] & (1<<31)) - Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings - buttonState = SHT_SHT_PRESSED_MULTI_SIMULTANEOUS; - GetTextIndexed(scmnd, sizeof(scmnd), press_index -3, kCommands); - ExecuteCommand(scmnd, SRC_BUTTON); - return; - } + // check for simultaneous shutter button press + uint32 min_shutterbutton_press_counter = -1; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if ((Settings.shutter_button[i] & (1<<31)) && (Button.press_counter[i] < min_shutterbutton_press_counter)) + min_shutterbutton_press_counter = Button.press_counter[i]; } - press_index = Button.press_counter[button_index]; - if ((buttonState == SHT_NOT_PRESSED) && (Button.press_counter[button_index]<99)) { + if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { + // simultaneous shutter button press detected + press_index = Button.press_counter[button_index]; + for (uint32_t i = 0; i < MAX_KEYS; i++) + if (Settings.shutter_button[i] & (1<<31)) + Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings + buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS; + } + if ((buttonState != SHT_PRESSED_MULTI_SIMULTANEOUS) && (Button.press_counter[button_index]<99)) { // no simultaneous shutter button press >3 detected + press_index = Button.press_counter[button_index]; buttonState = SHT_PRESSED_MULTI; } } @@ -620,40 +614,58 @@ void ShutterButtonHandler(void) } } - if ((buttonState != SHT_NOT_PRESSED) && (buttonState != SHT_SHT_PRESSED_MULTI_SIMULTANEOUS) && (buttonState != SHT_PRESSED_EXT_HOLD_SIMULTANEOUS)) { - if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { - if (press_index>3) press_index=3; - press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: shutter %d, button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, press_index+1); - XdrvMailbox.index = shutter_index +1; - last_source = SRC_BUTTON; - XdrvMailbox.data_len = 0; - char databuf[1] = ""; - XdrvMailbox.data = databuf; - XdrvMailbox.command = NULL; - if (buttonState == SHT_PRESSED_IMMEDIATE) { - XdrvMailbox.payload = XdrvMailbox.index; - CmndShutterStop(); - } - else { - uint8_t position = (Settings.shutter_button[button_index]>>(6*press_index + 2)) & 0x03f; - if (position) { - if (Shutter.direction[shutter_index]) { - XdrvMailbox.payload = XdrvMailbox.index; - CmndShutterStop(); - } else { - XdrvMailbox.payload = position = (position-1)<<1; - CmndShutterPosition(); - if (Settings.shutter_button[button_index] & ((0x01<<26)<=5) && (press_index<=7) && (!Settings.flag.button_restrict)) { // 5x..7x && no SetOption1 (0) + // simultaneous shutter button press 5x, 6x, 7x detected + char scmnd[20]; + GetTextIndexed(scmnd, sizeof(scmnd), press_index -3, kCommands); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } else if (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) { + // simultaneous shutter button extend hold detected + if (!Settings.flag.button_restrict) { // no SetOption1 (0) + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } else if (buttonState <= SHT_PRESSED_IMMEDIATE) { + if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { + uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); + if (pos_press_index>3) pos_press_index=3; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: shutter %d, button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, pos_press_index+1); + XdrvMailbox.index = shutter_index +1; + last_source = SRC_BUTTON; + XdrvMailbox.data_len = 0; + char databuf[1] = ""; + XdrvMailbox.data = databuf; + XdrvMailbox.command = NULL; + if (buttonState == SHT_PRESSED_IMMEDIATE) { + XdrvMailbox.payload = XdrvMailbox.index; + CmndShutterStop(); + } + else { + uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f; + if (position) { + if (Shutter.direction[shutter_index]) { + XdrvMailbox.payload = XdrvMailbox.index; + CmndShutterStop(); + } else { + XdrvMailbox.payload = position = (position-1)<<1; + CmndShutterPosition(); + if (Settings.shutter_button[button_index] & ((0x01<<26)< Date: Wed, 22 Jan 2020 16:14:03 +0100 Subject: [PATCH 067/160] Document Light commands --- tasmota/xdrv_04_light.ino | 123 +++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 48 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 48cc2d283..3df7b43a0 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2185,6 +2185,13 @@ void CmndSupportColor(void) void CmndColor(void) { + // Color - Show current RGBWW color state + // Color1 - Change color to RGBWW + // Color2 - Change color to RGBWW but retain brightness (=dimmer) + // Color3 - Change color to RGB of WS2812 Clock Second + // Color4 - Change color to RGB of WS2812 Clock Minute + // Color5 - Change color to RGB of WS2812 Clock Hour + // Color6 - Change color to RGB of WS2812 Clock Marker if ((Light.subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { CmndSupportColor(); } @@ -2192,6 +2199,8 @@ void CmndColor(void) void CmndWhite(void) { + // White - Show current White (=Dimmer2) state + // White 0..100 - Set White colors dimmer state if (Light.pwm_multi_channels) { return; } if ( ((Light.subtype >= LST_RGBW) || (LST_COLDWARM == Light.subtype)) && (XdrvMailbox.index == 1)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { @@ -2205,6 +2214,10 @@ void CmndWhite(void) void CmndChannel(void) { + // Channel - Show current Channel state + // Channel 0..100 - Set Channel dimmer state + // Channel + - Incerement Channel in steps of 10 + // Channel - - Decrement Channel in steps of 10 if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { uint32_t light_index = XdrvMailbox.index - Light.device; power_t coldim = 0; // bit flag to update @@ -2249,48 +2262,35 @@ void CmndChannel(void) void CmndHsbColor(void) { + // HsbColor - Show current HSB + // HsbColor 360,100,100 - Set Hue, Saturation and Brighthness + // HsbColor 360,100 - Set Hue and Saturation + // HsbColor 360 - Set Hue + // HsbColor1 360 - Set Hue + // HsbColor2 100 - Set Saturation + // HsbColor3 100 - Set Brightness if (Light.subtype >= LST_RGB) { - bool validHSB = (XdrvMailbox.data_len > 0); - if (validHSB) { - uint16_t HSB[3]; + if (XdrvMailbox.data_len > 0) { uint16_t c_hue; uint8_t c_sat; - light_state.getHSB(&c_hue, &c_sat, nullptr); + uint32_t HSB[3]; HSB[0] = c_hue; HSB[1] = c_sat; HSB[2] = light_state.getBriRGB(); - - char *substr = strstr(XdrvMailbox.data, ","); - if (substr != nullptr) { // Command with comma separated parameters, Hue (0 100) { XdrvMailbox.payload = 100; } + HSB[XdrvMailbox.index-1] = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 255); + } else { + uint32_t paramcount = ParseParameters(3, HSB); + if (HSB[0] > 360) { HSB[0] = 360; } + for (uint32_t i = 1; i < paramcount; i++) { + if (HSB[i] > 100) { HSB[i] == 100; } HSB[i] = changeUIntScale(HSB[i], 0, 100, 0, 255); // change sat and bri to 0..255 - substr = strstr(substr, ","); - if (substr == nullptr) { - break; - } - } - if (substr != nullptr) { - validHSB = false; - } - } else { // Command with only 1 parameter, Hue (0 1) && (XdrvMailbox.index < 4)) { - HSB[XdrvMailbox.index-1] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); - } else { - validHSB = false; } } - if (validHSB) { - light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); - LightPreparePower(1); - } + light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); + LightPreparePower(1); } else { LightState(0); } @@ -2299,6 +2299,11 @@ void CmndHsbColor(void) void CmndScheme(void) { + // Scheme 0..12 - Select one of schemes 0 to 12 + // Scheme 2 - Select scheme 2 + // Scheme 2,0 - Select scheme 2 with color wheel set to 0 (HSB Red) + // Scheme + - Select next scheme + // Scheme - - Select previous scheme if (Light.subtype >= LST_RGB) { uint32_t max_scheme = Light.max_scheme; @@ -2332,6 +2337,8 @@ void CmndScheme(void) void CmndWakeup(void) { + // Wakeup - Start wakeup light + // Wakeup 0..100 - Start wakeup light to dimmer value 0..100 if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { light_controller.changeDimmer(XdrvMailbox.payload); } @@ -2343,6 +2350,10 @@ void CmndWakeup(void) void CmndColorTemperature(void) { + // CT - Show current color temperature + // CT 153..500 - Set color temperature + // CT + - Incerement color temperature in steps of 34 + // CT - - Decrement color temperature in steps of 34 if (Light.pwm_multi_channels) { return; } if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { // ColorTemp uint32_t ct = light_state.getCT(); @@ -2365,6 +2376,12 @@ void CmndColorTemperature(void) void CmndDimmer(void) { + // Dimmer - Show current Dimmer state + // Dimmer0 0..100 - Change both RGB and W(W) Dimmers + // Dimmer1 0..100 - Change RGB Dimmer + // Dimmer2 0..100 - Change W(W) Dimmer + // Dimmer + - Incerement Dimmer in steps of 10 + // Dimmer - - Decrement Dimmer in steps of 10 uint32_t dimmer; if (XdrvMailbox.index > 2) { XdrvMailbox.index = 1; } @@ -2406,6 +2423,8 @@ void CmndDimmer(void) void CmndDimmerRange(void) { + // DimmerRange - Show current dimmer range as used by Tuya and PS16DZ Dimmers + // DimmerRange 0,100 - Set dimmer hardware range from 0 to 100 and restart if (XdrvMailbox.data_len > 0) { uint32_t parm[2]; parm[0] = Settings.dimmer_hw_min; @@ -2425,6 +2444,10 @@ void CmndDimmerRange(void) void CmndLedTable(void) { + // LedTable - Show current LedTable state + // LedTable 0 - Turn LedTable Off + // LedTable On - Turn LedTable On + // LedTable Toggle - Toggle LedTable state if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { switch (XdrvMailbox.payload) { case 0: // Off @@ -2442,20 +2465,13 @@ void CmndLedTable(void) void CmndRgbwwTable(void) { + // RgbWwTable - Show current RGBWW State + // RgbWwTable 255,255,255,255,255 - Set RGBWW state to maximum if ((XdrvMailbox.data_len > 0)) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { // Command with up to 5 comma separated parameters - for (uint32_t i = 0; i < LST_RGBCW; i++) { - char *substr; - - if (0 == i) { - substr = strtok(XdrvMailbox.data, ","); - } else { - substr = strtok(nullptr, ","); - } - if (substr != nullptr) { - Settings.rgbwwTable[i] = atoi(substr); - } - } + uint32_t parm[LST_RGBCW -1]; + uint32_t parmcount = ParseParameters(LST_RGBCW, parm); + for (uint32_t i = 0; i < parmcount; i++) { + Settings.rgbwwTable[i] = parm[i]; } Light.update = true; } @@ -2464,11 +2480,15 @@ void CmndRgbwwTable(void) for (uint32_t i = 0; i < LST_RGBCW; i++) { snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); } - ResponseCmndIdxChar(scolor); + ResponseCmndChar(scolor); } void CmndFade(void) { + // Fade - Show current Fade state + // Fade 0 - Turn Fade Off + // Fade On - Turn Fade On + // Fade Toggle - Toggle Fade state switch (XdrvMailbox.payload) { case 0: // Off case 1: // On @@ -2483,7 +2503,11 @@ void CmndFade(void) } void CmndSpeed(void) -{ // 1 - fast, 40 - very slow +{ + // Speed 1 - Fast + // Speed 40 - Very slow + // Speed + - Increment Speed + // Speed - - Decrement Speed if (1 == XdrvMailbox.data_len) { if (('+' == XdrvMailbox.data[0]) && (Settings.light_speed > 1)) { XdrvMailbox.payload = Settings.light_speed - 1; @@ -2500,6 +2524,8 @@ void CmndSpeed(void) void CmndWakeupDuration(void) { + // WakeUpDuration - Show current Wake Up duration in seconds + // WakeUpDuration 60 - Set Wake Up duration to 60 seconds if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3001)) { Settings.light_wakeup = XdrvMailbox.payload; Light.wakeup_active = 0; @@ -2508,7 +2534,8 @@ void CmndWakeupDuration(void) } void CmndUndocA(void) -{ // Theos legacy status +{ + // Theos legacy status char scolor[LIGHT_COLOR_SIZE]; LightGetColor(scolor, true); // force hex whatever Option 17 scolor[6] = '\0'; // RGB only From 514f3e7357b8bcbd481c1c1512ce8c1488f1f933 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Wed, 22 Jan 2020 21:37:23 +0100 Subject: [PATCH 068/160] Fix ``RGBWWTable`` ignored (#7572) --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_04_light.ino | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 9285bdda1..b35d22064 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -9,6 +9,7 @@ - Add most SetOptions as defines to my_user_config.h - Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) - Add optional parameter to command ``Scheme , `` to control initial start color +- Fix ``RGBWWTable`` ignored (#7572) ### 8.1.0.3 20200106 diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 3df7b43a0..2de7432a0 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1799,6 +1799,14 @@ void LightAnimate(void) } } + // Apply RGBWWTable only if Settings.rgbwwTable[4] != 0 + if (0 != Settings.rgbwwTable[4]) { + for (uint32_t i = 0; i Date: Wed, 22 Jan 2020 22:40:28 +0100 Subject: [PATCH 069/160] Minor Zigbee improvements --- tasmota/xdrv_23_zigbee_3_devices.ino | 16 +++++++++++++--- tasmota/xdrv_23_zigbee_4_persistence.ino | 2 ++ tasmota/xdrv_23_zigbee_6_commands.ino | 10 +++++----- tasmota/xdrv_23_zigbee_9_impl.ino | 2 +- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index e034868e6..339737b57 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -123,6 +123,7 @@ public: // Mark data as 'dirty' and requiring to save in Flash void dirty(void); + void clean(void); // avoid writing to flash the last changes // Find device by name, can be short_addr, long_addr, number_in_array or name uint16_t parseDeviceParam(const char * param, bool short_must_be_known = false) const; @@ -469,22 +470,28 @@ void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { Z_Device & device = getShortAddr(shortaddr); if (&device == nullptr) { return; } // don't crash if not found _updateLastSeen(device); + if (!device.manufacturerId.equals(str)) { + dirty(); + } device.manufacturerId = str; - dirty(); } void Z_Devices::setModelId(uint16_t shortaddr, const char * str) { Z_Device & device = getShortAddr(shortaddr); if (&device == nullptr) { return; } // don't crash if not found _updateLastSeen(device); + if (!device.modelId.equals(str)) { + dirty(); + } device.modelId = str; - dirty(); } void Z_Devices::setFriendlyName(uint16_t shortaddr, const char * str) { Z_Device & device = getShortAddr(shortaddr); if (&device == nullptr) { return; } // don't crash if not found _updateLastSeen(device); + if (!device.friendlyName.equals(str)) { + dirty(); + } device.friendlyName = str; - dirty(); } const String * Z_Devices::getFriendlyName(uint16_t shortaddr) const { @@ -691,6 +698,9 @@ void Z_Devices::jsonPublishNow(uint16_t shortaddr, JsonObject & values) { void Z_Devices::dirty(void) { _saveTimer = kZigbeeSaveDelaySeconds * 1000 + millis(); } +void Z_Devices::clean(void) { + _saveTimer = 0; +} // Parse the command parameters for either: // - a short address starting with "0x", example: 0x1234 diff --git a/tasmota/xdrv_23_zigbee_4_persistence.ino b/tasmota/xdrv_23_zigbee_4_persistence.ino index e4fae384d..c3003854f 100644 --- a/tasmota/xdrv_23_zigbee_4_persistence.ino +++ b/tasmota/xdrv_23_zigbee_4_persistence.ino @@ -268,6 +268,7 @@ void loadZigbeeDevices(void) { buf.addBuffer(z_dev_start + sizeof(z_flashdata_t), buf_len); AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee devices data in Flash (%d bytes)"), buf_len); hidrateDevices(buf); + zigbee_devices.clean(); // don't write back to Flash what we just loaded } else { AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "No zigbee devices data in Flash")); } @@ -308,6 +309,7 @@ void saveZigbeeDevices(void) { // Erase the flash area containing the ZigbeeData void eraseZigbeeDevices(void) { + zigbee_devices.clean(); // avoid writing data to flash after erase // first copy SPI buffer into ram uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); if (!spi_buffer) { diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 4c9b0672f..073ab8e4c 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -40,11 +40,11 @@ const Z_CommandConverter Z_Commands[] = { { "Color", "0300!07/xxxxyyyy0A00" }, // x, y (uint16) { "CT", "0300!0A/xxxx0A00" }, // Color Temperature Mireds (uint16) { "Shutter", "0102!xx" }, - { "ShutterOpen", "0102!00"}, - { "ShutterClose", "0102!01"}, - { "ShutterStop", "0102!02"}, - { "ShutterLift", "0102!05xx"}, // Lift percentage, 0%=open, 100%=closed - { "ShutterTilt", "0102!08xx"}, // Tilt percentage + { "ShutterOpen", "0102!00" }, + { "ShutterClose", "0102!01" }, + { "ShutterStop", "0102!02" }, + { "ShutterLift", "0102!05xx" }, // Lift percentage, 0%=open, 100%=closed + { "ShutterTilt", "0102!08xx" }, // Tilt percentage }; #define ZLE(x) ((x) & 0xFF), ((x) >> 8) // Little Endian diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index da73f9db7..9b44ce35e 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -463,7 +463,7 @@ void CmndZigbeeSend(void) { if (nullptr != &val_device) { device = strToUInt(val_device); } const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("endpoint")); if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } - const JsonVariant val_cmd = getCaseInsensitive(json, PSTR("Send")); + const JsonVariant &val_cmd = getCaseInsensitive(json, PSTR("Send")); if (nullptr != &val_cmd) { // probe the type of the argument // If JSON object, it's high level commands From 2e89370f1ecd9b4620a4843d2f6fc256158c1e71 Mon Sep 17 00:00:00 2001 From: Patrick Domack Date: Wed, 22 Jan 2020 16:49:28 -0500 Subject: [PATCH 070/160] Add ability to define more subversions in user overrides and remove ram/flash usage to store all versions. --- tasmota/tasmota.h | 1 + tasmota/tasmota.ino | 5 +---- tasmota/tasmota_post.h | 12 ++++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index b4b944d80..4cb435a55 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -31,6 +31,7 @@ \*********************************************************************************************/ #define CODE_IMAGE 0 +#define CODE_IMAGE_STR "tasmota" #define USE_LIGHT // Enable light control #define USE_ENERGY_SENSOR // Use energy sensors (+14k code) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 15375e338..5c20da3ad 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -68,7 +68,7 @@ // Structs #include "settings.h" -const char kCodeImage[] PROGMEM = "tasmota|minimal|sensors|knx|lite|display|ir"; +const char my_image[] PROGMEM = "(" CODE_IMAGE_STR ")"; /*********************************************************************************************\ * Global variables @@ -159,7 +159,6 @@ myio my_module; // Active copy of Module GPIOs (17 x gpio_flag my_module_flag; // Active copy of Template GPIO flags StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) char my_version[33]; // Composed version string -char my_image[33]; // Code image and/or commit char my_hostname[33]; // Composed Wifi hostname char mqtt_client[TOPSZ]; // Composed MQTT Clientname char mqtt_topic[TOPSZ]; // Composed MQTT topic @@ -200,8 +199,6 @@ void setup(void) if (VERSION & 0xff) { // Development or patched version 6.3.0.10 snprintf_P(my_version, sizeof(my_version), PSTR("%s.%d"), my_version, VERSION & 0xff); } - char code_image[20]; - snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), GetTextIndexed(code_image, sizeof(code_image), CODE_IMAGE, kCodeImage)); SettingsLoad(); SettingsDelta(); diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index af2fe00f7..bef9c567d 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -79,6 +79,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef CODE_IMAGE #define CODE_IMAGE 2 +#undef CODE_IMAGE_STR +#define CODE_IMAGE_STR "sensors" #undef USE_DISCOVERY // Disable mDNS (+8k code or +23.5k code with core 2_5_x, +0.3k mem) @@ -228,6 +230,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef CODE_IMAGE #define CODE_IMAGE 3 +#undef CODE_IMAGE_STR +#define CODE_IMAGE_STR "knx" #ifndef USE_KNX #define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem) @@ -248,6 +252,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef CODE_IMAGE #define CODE_IMAGE 5 +#undef CODE_IMAGE_STR +#define CODE_IMAGE_STR "display" #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) #undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common) @@ -313,6 +319,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef CODE_IMAGE #define CODE_IMAGE 6 +#undef CODE_IMAGE_STR +#define CODE_IMAGE_STR "ir" #undef USE_EMULATION #undef USE_EMULATION_HUE // Disable Hue emulation - only for lights and relays @@ -406,6 +414,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef CODE_IMAGE #define CODE_IMAGE 4 +#undef CODE_IMAGE_STR +#define CODE_IMAGE_STR "lite" #undef APP_SLEEP #define APP_SLEEP 1 // Default to sleep = 1 for FIRMWARE_LITE @@ -511,6 +521,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef CODE_IMAGE #define CODE_IMAGE 1 +#undef CODE_IMAGE_STR +#define CODE_IMAGE_STR "minimal" #undef FIRMWARE_LITE // Disable tasmota-lite with no sensors #undef FIRMWARE_SENSORS // Disable tasmota-sensors with useful sensors enabled From 405da3ee3f147d056abbac43045c71d8bb9c0085 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 23 Jan 2020 10:33:08 +0100 Subject: [PATCH 071/160] Update tasmota.ino Keep hackbox commit insert possibility --- tasmota/tasmota.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 5c20da3ad..5b47ca581 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -68,8 +68,6 @@ // Structs #include "settings.h" -const char my_image[] PROGMEM = "(" CODE_IMAGE_STR ")"; - /*********************************************************************************************\ * Global variables \*********************************************************************************************/ @@ -159,6 +157,7 @@ myio my_module; // Active copy of Module GPIOs (17 x gpio_flag my_module_flag; // Active copy of Template GPIO flags StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) char my_version[33]; // Composed version string +char my_image[33]; // Code image and/or commit char my_hostname[33]; // Composed Wifi hostname char mqtt_client[TOPSZ]; // Composed MQTT Clientname char mqtt_topic[TOPSZ]; // Composed MQTT topic @@ -199,7 +198,8 @@ void setup(void) if (VERSION & 0xff) { // Development or patched version 6.3.0.10 snprintf_P(my_version, sizeof(my_version), PSTR("%s.%d"), my_version, VERSION & 0xff); } - + snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), CODE_IMAGE_STR); + SettingsLoad(); SettingsDelta(); From ac486f21864d438499f9269f3a936c5ddfd7eab5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 23 Jan 2020 10:57:29 +0100 Subject: [PATCH 072/160] Document my_image --- tasmota/tasmota.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 5b47ca581..92ee55fdf 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -198,8 +198,9 @@ void setup(void) if (VERSION & 0xff) { // Development or patched version 6.3.0.10 snprintf_P(my_version, sizeof(my_version), PSTR("%s.%d"), my_version, VERSION & 0xff); } - snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), CODE_IMAGE_STR); - + // Thehackbox inserts "release" or "commit number" before compiling using sed -i -e 's/PSTR("(%s)")/PSTR("(85cff52-%s)")/g' tasmota.ino + snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), CODE_IMAGE_STR); // Results in (85cff52-tasmota) or (release-tasmota) + SettingsLoad(); SettingsDelta(); From 9afbf854cfa06c17c6e4d4801c634018f8cd1117 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 23 Jan 2020 13:03:05 +0100 Subject: [PATCH 073/160] Add rule trigger on one level deeper Add rule trigger on one level deeper using syntax with two ``#`` like ``on zigbeereceived#vibration_sensor#aqaracubeside=0 do ...`` --- RELEASENOTES.md | 2 ++ tasmota/CHANGELOG.md | 3 ++- tasmota/xdrv_10_rules.ino | 12 +++++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5eef31626..ef8df5f8d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -66,6 +66,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix ``WakeUp `` ignores provided value (#7473) - Fix exception 9 restart on log message in Ticker interrupt service routines NTP, Wemos and Hue emulation (#7496) - Fix ``PowerDelta`` zero power detection (#7515) +- Fix ``RGBWWTable`` ignored (#7572) - Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) - Add command ``SetOption82 0/1`` to limit the CT range for Alexa to 200..380 - Add command ``ShutterButton `` to control shutter(s) by to-scho (#7403) @@ -83,3 +84,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add most SetOptions as defines to my_user_config.h - Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) - Add optional parameter to command ``Scheme , `` to control initial start color +- Add rule trigger on one level deeper using syntax with two ``#`` like ``on zigbeereceived#vibration_sensor#aqaracubeside=0 do ...`` diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index b35d22064..5c7073c6e 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,12 +4,13 @@ - Fix ``PowerDelta`` zero power detection (#7515) - Fix OTA minimal gzipped detection regression from 8.1.0.3 +- Fix ``RGBWWTable`` ignored (#7572) - Add web page sliders when ``SetOption37 128`` is active allowing control of white(s) - Add Zigbee persistence and friendly names - Add most SetOptions as defines to my_user_config.h - Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) - Add optional parameter to command ``Scheme , `` to control initial start color -- Fix ``RGBWWTable`` ignored (#7572) +- Add rule trigger on one level deeper using syntax with two ``#`` like ``on zigbeereceived#vibration_sensor#aqaracubeside=0 do ...`` ### 8.1.0.3 20200106 diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 13287d009..b750ebcbe 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -259,6 +259,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) JsonObject &root = jsonBuf.parseObject(event); if (!root.success()) { return false; } // No valid JSON data + String rule_subfield = ""; const char* str_value; if ((pos = rule_name.indexOf("[")) > 0) { // "CURRENT[1]" int rule_name_idx = rule_name.substring(pos +1).toInt(); @@ -267,6 +268,11 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) } rule_name = rule_name.substring(0, pos); // "CURRENT" str_value = root[rule_task][rule_name][rule_name_idx -1]; // "ENERGY" and "CURRENT" and 0 + } + else if ((pos = rule_name.indexOf("#")) > 0) { // "VIBRATION_SENSOR#AQARACUBESIDE" + rule_subfield = rule_name.substring(pos +1); // "AQARACUBESIDE" + rule_name = rule_name.substring(0, pos); // "VIBRATION_SENSOR" + str_value = root[rule_task][rule_name][rule_subfield]; // "ZIGBEERECEIVED", "VIBRATION_SENSOR" and "AQARACUBESIDE" } else { str_value = root[rule_task][rule_name]; // "INA219" and "CURRENT" } @@ -274,7 +280,11 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"), // rule_task.c_str(), rule_name.c_str(), rule_svalue, Rules.trigger_count[rule_set], bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none"); - if (!root[rule_task][rule_name].success()) { return false; } + if (rule_subfield.length()) { + if (!root[rule_task][rule_name][rule_subfield].success()) { return false; } + } else { + if (!root[rule_task][rule_name].success()) { return false; } + } // No value but rule_name is ok Rules.event_value = str_value; // Prepare %value% From ad083d1675003e20ed5cf9ec16e1cf7e78d0e74c Mon Sep 17 00:00:00 2001 From: saper-2 Date: Thu, 23 Jan 2020 16:13:25 +0100 Subject: [PATCH 074/160] Some code cleanup and add comments & info --- tasmota/my_user_config.h | 2 +- tasmota/xnrg_13_fif_le01mr.ino | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 85d6737e9..8a709c2dd 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -499,7 +499,7 @@ #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) #define SOLAXX1_PV2 // Solax X1 using second PV //#define USE_LE01MR // Add support for F&F LE-01MR modbus energy meter - #define LE01MR_SPEED 2400 // LE-01MR modbus baudrate (2400 default) + #define LE01MR_SPEED 2400 // LE-01MR modbus baudrate (9600 default) (+2k code, +36 RAM) #define LE01MR_ADDR 1 // LE-01MR modbus address (0x01 default) // -- Low level interface devices ----------------- #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code) diff --git a/tasmota/xnrg_13_fif_le01mr.ino b/tasmota/xnrg_13_fif_le01mr.ino index 342e8cf17..e99041c9c 100644 --- a/tasmota/xnrg_13_fif_le01mr.ino +++ b/tasmota/xnrg_13_fif_le01mr.ino @@ -23,7 +23,7 @@ * (and bidirectional energy counting - enabled by RS485). * It measure: Active energy imported AE+ [kWh] , Reactive energy imported RE+ [kvarh], * Voltage V [V], Current I [A], Frequency F [Hz], power factor (aka "cos-phi"), - * Active power P [kW], Reactive power Q [kvar], Apparent power S [kVA], + * Active power P [kW], Reactive power Q [kVAr], Apparent power S [kVA], * *Active energy exported AE- [kWh] (when meter is switched to bi-directional counting then * reactive energy imported register contains value of Active energy exported). * @@ -31,6 +31,12 @@ * EN: https://www.fif.com.pl/en/usage-electric-power-meters/517-electricity-consumption-meter-le-01mr.html * PL: https://www.fif.com.pl/pl/liczniki-zuzycia-energii-elektrycznej/517-licznik-zuzycia-energii-le-01mr.html * + * Note about communication settings: The meter must be reconfigured to use baudrate 2400 (or 9600) *without* + * parity bit - by default the meter is configured to 9600 8E1 + * (Frame format: "EVEN 1") . To make those changes, use LE-Config + * software (can be found in download tab in product page - link above) + * and USB-RS485 dongle (those cheap ~2$ from ali works fine) + * * Register descriptions (not all, only those that are being read): * * /----------------------------------- Register address @@ -54,6 +60,11 @@ * second register contains lower word of 32bit dword: * value_32bit = (register+0)<<16 | (register+1); * /or/ val32bit = (reg+0)*65536 + (reg+1); + * + * Note about MQTT/JSON: In fields "ENERGY.TotalActive" and "ENERGY.TotalReactive" there are + * counters values directly from the meter (without Tasmota calculation, + * energy used calculated by Tasmota is in Total/Today fields ). + * Filed "ENERGY.Period" is always zero. \*********************************************************************************************/ #define XNRG_13 13 @@ -113,7 +124,6 @@ void FifLEEvery250ms(void) if (error) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus error %d"), error); } else { - //if (Le01mr.read_state == 0) Energy.data_valid[0] = 0; // SA=Slave Address, FC=Function Code, BC=Byte Count, B3..B0=Data byte, Ch Cl = crc16 checksum @@ -140,9 +150,6 @@ void FifLEEvery250ms(void) value_buff = ((uint32_t)buffer[3])<<24 | ((uint32_t)buffer[4])<<16 | ((uint32_t)buffer[5])<<8 | buffer[6]; } - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR buff[3..6]: %2x %2x %2x %2x"), buffer[3], buffer[4], buffer[5], buffer[6]); - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR reg_count/value_buff: %d / %d"), reg_count,value_buff); - switch(Le01mr.read_state) { case 0: Energy.frequency[0] = value_buff * 0.01f; // 5000 => 50.00 @@ -197,7 +204,6 @@ void FifLEEvery250ms(void) // some registers are 1reg in size if (Le01mr.read_state < 3) reg_count=1; // send request - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus req reg %X, count %d"), le01mr_register_addresses[Le01mr.read_state], reg_count); FifLEModbus->Send(LE01MR_ADDR, 0x03, le01mr_register_addresses[Le01mr.read_state], reg_count); } else { Le01mr.send_retry--; From e26999f3006673933313c669f4dfb8b41cc558c0 Mon Sep 17 00:00:00 2001 From: saper-2 Date: Thu, 23 Jan 2020 17:18:44 +0100 Subject: [PATCH 075/160] Updated lang files with new defines + comments --- tasmota/language/bg-BG.h | 5 ++++- tasmota/language/cs-CZ.h | 5 ++++- tasmota/language/de-DE.h | 5 ++++- tasmota/language/el-GR.h | 5 ++++- tasmota/language/es-ES.h | 5 ++++- tasmota/language/fr-FR.h | 5 ++++- tasmota/language/he-HE.h | 5 ++++- tasmota/language/hu-HU.h | 5 ++++- tasmota/language/it-IT.h | 5 ++++- tasmota/language/ko-KO.h | 5 ++++- tasmota/language/nl-NL.h | 5 ++++- tasmota/language/pl-PL.h | 5 ++++- tasmota/language/pt-BR.h | 5 ++++- tasmota/language/pt-PT.h | 5 ++++- tasmota/language/ru-RU.h | 5 ++++- tasmota/language/sk-SK.h | 5 ++++- tasmota/language/sv-SE.h | 5 ++++- tasmota/language/tr-TR.h | 5 ++++- tasmota/language/uk-UA.h | 5 ++++- tasmota/language/zh-CN.h | 5 ++++- tasmota/language/zh-TW.h | 5 ++++- tasmota/my_user_config.h | 2 +- tasmota/tasmota_post.h | 10 +++++----- 23 files changed, 90 insertions(+), 27 deletions(-) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 8f1c82bc3..b91a2e6e4 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Фазов ъгъл" #define D_IMPORT_ACTIVE "Входна активна мощност" #define D_EXPORT_ACTIVE "Изходна активна мощност" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Общо реактивна мощност" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "°" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "Напрежение на PV1" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 3b11a7ebc..4bf6a8355 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Phase Angle" #define D_IMPORT_ACTIVE "Import Active" #define D_EXPORT_ACTIVE "Export Active" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Total Reactive" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index e09278526..944ce7123 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Phasenwinkel" #define D_IMPORT_ACTIVE "Importiere Wirk" #define D_EXPORT_ACTIVE "Exportiere Wirk" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Total Blind" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Grad" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Spannung" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index 070267215..82def9666 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Phase Angle" #define D_IMPORT_ACTIVE "Import Active" #define D_EXPORT_ACTIVE "Export Active" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Total Reactive" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 8ff2b415f..48d0f26e0 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Ángulo de Fase" #define D_IMPORT_ACTIVE "P. Activa Entrante" #define D_EXPORT_ACTIVE "P. Activa Saliente" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "P. Reactiva Total" #define D_UNIT_KWARH "kVArH" #define D_UNIT_ANGLE "Grados" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltaje" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index 3829a8681..c5f7dcc38 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Esclave Rst" #define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Angle de phase" #define D_IMPORT_ACTIVE "Énergie act conso" #define D_EXPORT_ACTIVE "Énergie act fournie" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Énergie réa totale" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "°" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "Tension PV1" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index d0c5e364b..491e85192 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Phase Angle" #define D_IMPORT_ACTIVE "Import Active" #define D_EXPORT_ACTIVE "Export Active" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Total Reactive" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 70f219c98..eb0b6d6b4 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Fázisszög" #define D_IMPORT_ACTIVE "Bejövő aktív" #define D_EXPORT_ACTIVE "Kimenő aktív" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Összes reaktív" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "fok" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index 73830deca..a5255e9ed 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Angolo Fase" #define D_IMPORT_ACTIVE "Potenza Attiva Importata" #define D_EXPORT_ACTIVE "Potenza Attiva Esportata" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Potenza Reattiva Totale" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "°" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltaggio" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index 328acc568..036f4adbb 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Phase Angle" #define D_IMPORT_ACTIVE "Import Active" #define D_EXPORT_ACTIVE "Export Active" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Total Reactive" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 3d5ec8b7d..de15f5d05 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Fase hoek" #define D_IMPORT_ACTIVE "Import werkelijk" #define D_EXPORT_ACTIVE "Export werkelijk" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Totaal blind" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 spanning" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 63fe6fcad..ac2da9524 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Przesunięcie faz" #define D_IMPORT_ACTIVE "Czynna pobrana" #define D_EXPORT_ACTIVE "Czynna oddana" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Bierna całkowita" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Całkowita czynna" //SOLAXX1 #define D_PV1_VOLTAGE "Napięcie PV1" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index da6e8ca1b..6695e144d 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "W/h" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Ângulo de Fase" #define D_IMPORT_ACTIVE "Importar Ativo" #define D_EXPORT_ACTIVE "Exportar Ativo" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Reativo total" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltagem" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 47137b90b..53e31cb5a 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Ângulo de fase" #define D_IMPORT_ACTIVE "Ativo importado" #define D_EXPORT_ACTIVE "Ativo exportado" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Reactivo total" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "Voltagem PV1" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 31c295059..3cf388240 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "А" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "ВтЧ" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Угол фазы" #define D_IMPORT_ACTIVE "Импорт активной мощности" #define D_EXPORT_ACTIVE "Экспорт активной мощности" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Итого реактивная мощность" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Град" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index 89f3d7353..b3d007214 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Phase Angle" #define D_IMPORT_ACTIVE "Import Active" #define D_EXPORT_ACTIVE "Export Active" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Total Reactive" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index ddc2307b4..23badaeed 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Fasvinkel" #define D_IMPORT_ACTIVE "Import aktiv" #define D_EXPORT_ACTIVE "Export aktiv" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Total reaktiv" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total aktiv" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 38f125d6c..03b49afc1 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "A" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Phase Angle" #define D_IMPORT_ACTIVE "Import Active" #define D_EXPORT_ACTIVE "Export Active" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Total Reactive" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/language/uk-UA.h b/tasmota/language/uk-UA.h index b634935cf..067a50c31 100644 --- a/tasmota/language/uk-UA.h +++ b/tasmota/language/uk-UA.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "А" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "Вт/г" #define D_UNIT_WATT_METER_QUADRAT "Вт/м²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Кут фази" #define D_IMPORT_ACTIVE "Активна вхід" #define D_EXPORT_ACTIVE "Активна вихід" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Всього реактивна" #define D_UNIT_KWARH "кВАр/г" #define D_UNIT_ANGLE "Град" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Напруга" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 97b41a29a..0c9d56922 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "安" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "瓦时" #define D_UNIT_WATT_METER_QUADRAT "瓦/平米" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "相位角" #define D_IMPORT_ACTIVE "有功输入" #define D_EXPORT_ACTIVE "有功输出" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "总无功功率" #define D_UNIT_KWARH "千乏时" #define D_UNIT_ANGLE "度" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 1fd30e6e4..6f1033c54 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -634,6 +634,8 @@ #define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" // Units #define D_UNIT_AMPERE "安" @@ -669,7 +671,7 @@ #define D_UNIT_WATTHOUR "瓦時" #define D_UNIT_WATT_METER_QUADRAT "W/m²" -//SDM220 +//SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Phase Angle" #define D_IMPORT_ACTIVE "Import Active" #define D_EXPORT_ACTIVE "Export Active" @@ -678,6 +680,7 @@ #define D_TOTAL_REACTIVE "Total Reactive" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Active" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 Voltage" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 8a709c2dd..d72e8cce9 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -499,7 +499,7 @@ #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) #define SOLAXX1_PV2 // Solax X1 using second PV //#define USE_LE01MR // Add support for F&F LE-01MR modbus energy meter - #define LE01MR_SPEED 2400 // LE-01MR modbus baudrate (9600 default) (+2k code, +36 RAM) + #define LE01MR_SPEED 9600 // LE-01MR modbus baudrate (9600 default) (+2k code, +36 RAM) #define LE01MR_ADDR 1 // LE-01MR modbus address (0x01 default) // -- Low level interface devices ----------------- #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code) diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 8a16ffead..c1b897920 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -194,7 +194,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) //#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k1 code) -//#define USE_LE01MR // Add support for F&F LE-01MR modbus energy meter +//#define USE_LE01MR // Add support for F&F LE-01MR modbus energy meter (+2k code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI @@ -282,7 +282,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) - #undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter + #undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter (+2k code) #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #define USE_DISPLAY // Add I2C Display Support (+2k code) @@ -364,7 +364,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) - #undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter + #undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter (+2k code) //#undef USE_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) @@ -484,7 +484,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) -#undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter +#undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter (+2k code) #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -596,7 +596,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) -#undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter +#undef USE_LE01MR // Disable support for F&F LE-01MR Modbus energy meter (+2k code) #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI From 3b71173a09931098250e102981f6267e45d00fd5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 23 Jan 2020 18:13:32 +0100 Subject: [PATCH 076/160] Add precision to Moisture sensor Add precision to Moisture sensor (#7402) --- tasmota/settings.h | 3 ++- tasmota/xsns_02_analog.ino | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 74023ff60..dba74eb7d 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -467,8 +467,9 @@ struct SYSCFG { uint8_t hotplug_scan; // F03 uint8_t reserved1; // F04 - reserved for s-hadinger - uint8_t free_f05[215]; // F05 + uint8_t free_f05[211]; // F05 + int adc_param4; // FD8 uint32_t shutter_button[MAX_KEYS]; // FDC uint32_t i2c_drivers[3]; // FEC I2cDriver uint32_t cfg_timestamp; // FF8 diff --git a/tasmota/xsns_02_analog.ino b/tasmota/xsns_02_analog.ino index f4de98d9a..93df3d5e1 100644 --- a/tasmota/xsns_02_analog.ino +++ b/tasmota/xsns_02_analog.ino @@ -71,7 +71,7 @@ struct { void AdcInit(void) { - if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000) || (Settings.adc_param1 < 100)) { + if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000)) { if (ADC0_TEMP == my_adc0) { // Default Shelly 2.5 and 1PM parameters Settings.adc_param_type = ADC0_TEMP; @@ -90,6 +90,7 @@ void AdcInit(void) Settings.adc_param1 = 0; Settings.adc_param2 = 1023; Settings.adc_param3 = 0; + Settings.adc_param4 = 100; } else if (ADC0_CT_POWER == my_adc0) { Settings.adc_param_type = ADC0_CT_POWER; @@ -147,13 +148,10 @@ uint16_t AdcGetLux(void) uint16_t AdcGetMoist(void) { // formula for calibration: value, fromLow, fromHigh, toHigh, toLow - // Example: 632, 0, 1023, 100, 0 + // Example: 632, 0, 1023, 0, 100 // int( ( ( ( - ) / ( - ) ) * ( - ) ) + ) - // double amoist = ((Settings.adc_param2 - (double)adc) / (Settings.adc_param2 - Settings.adc_param1) * 100; - // int((((1023 - ) / ( 1023 - 0 )) * ( 100 - 0 )) + 0 ) int adc = AdcRead(2); - double amoist = ((double)Settings.adc_param2 - (double)adc) / ((double)Settings.adc_param2 - (double)Settings.adc_param1) * 100; - //double amoist = ((1023 - (double)adc) / 1023) * 100; + double amoist = ( ((double)Settings.adc_param2 - (double)adc) / ( ((double)Settings.adc_param2 - (double)Settings.adc_param1)) * ((double)Settings.adc_param3 - (double)Settings.adc_param4) + (double)Settings.adc_param4 ); return (uint16_t)amoist; } @@ -348,10 +346,14 @@ void CmndAdcParam(void) char sub_string[XdrvMailbox.data_len +1]; // AdcParam 2, 32000, 10000, 3350 // AdcParam 3, 10000, 12518931, -1.405 + // AdcParam 6, 0, 1023, 0, 100 Settings.adc_param_type = XdrvMailbox.payload; Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); - if (!ADC0_MOIST == XdrvMailbox.payload) { + if (ADC0_MOIST == XdrvMailbox.payload) { + Settings.adc_param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10)); + Settings.adc_param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10)); + } else { Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); } if (ADC0_CT_POWER == XdrvMailbox.payload) { @@ -373,7 +375,9 @@ void CmndAdcParam(void) // AdcParam Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d"), Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2); - if (ADC0_MOIST != my_adc0) { + if (ADC0_MOIST == my_adc0) { + ResponseAppend_P(PSTR(",%d,%d"), Settings.adc_param3, Settings.adc_param4); + } else { int value = Settings.adc_param3; uint8_t precision; for (precision = 4; precision > 0; precision--) { From b977c2843576132cb372c7c774f7e2f829d5b005 Mon Sep 17 00:00:00 2001 From: Leonid Muravjev Date: Thu, 23 Jan 2020 23:28:39 +0300 Subject: [PATCH 077/160] ds1624/ds1621: Stabilization and bug fixes * ds1621 datasheet is wrong for higher resolution, fixed * ds1621 sometimes reset on bad (long) i2c bus, added autoreconfigure * hotplug bug fixes --- tasmota/xsns_59_ds1624.ino | 60 ++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/tasmota/xsns_59_ds1624.ino b/tasmota/xsns_59_ds1624.ino index 9fe34b7d8..be0bcf9e5 100644 --- a/tasmota/xsns_59_ds1624.ino +++ b/tasmota/xsns_59_ds1624.ino @@ -38,6 +38,9 @@ #define DS1621_COUNTER_REGISTER 0xA8 //exists on 1621 and 1624(undocumented) #define DS1621_SLOPE_REGISTER 0xA9 //exists on 1624 and 1624(undocumented) +#define DS1621_CFG_1SHOT (1<<0) +#define DS1621_CFG_DONE (1<<7) + enum { DS1624_TYPE_DS1624, DS1624_TYPE_DS1621 @@ -50,6 +53,8 @@ bool ds1624_init = false; struct { float value; uint8_t type; + int errcnt; + int misscnt; bool valid; char name[9]; } ds1624_sns[DS1624_MAX_SENSORS]; @@ -58,6 +63,17 @@ uint32_t DS1624_Idx2Addr(uint32_t idx) { return 0x48 + idx; } +int DS1624_Restart(uint8_t config, uint32_t idx) { + uint32_t addr = DS1624_Idx2Addr(idx); + if ((config & 1) == 1) { + config &= ~(DS1621_CFG_DONE|DS1621_CFG_1SHOT); + I2cWrite8(addr, DS1624_CONF_REGISTER, config); // 1shot off + delay(10); // by spec after writing + AddLog_P2(LOG_LEVEL_ERROR, "%s addr %x is reset, reconfig: %x", ds1624_sns[idx].name, addr, config); + } + I2cValidRead(addr, DS1624_START_REGISTER, 1); +} + void DS1624_HotPlugUp(uint32_t idx) { uint32_t addr = DS1624_Idx2Addr(idx); @@ -75,12 +91,9 @@ void DS1624_HotPlugUp(uint32_t idx) I2cSetActiveFound(addr, ds1624_sns[idx].name); ds1624_sns[idx].valid = true; - if ((config & 1) == 1) { - config &= 0xfe; - I2cWrite8(addr, DS1624_CONF_REGISTER, config); // 1show off - delay(10); // by spec after writing - } - I2cValidRead(addr, DS1624_START_REGISTER, 1); // FIXME 0 must read, but 0 isn't work for tasmota + ds1624_sns[idx].errcnt = 0; + ds1624_sns[idx].misscnt = 0; + DS1624_Restart(config,idx); AddLog_P2(LOG_LEVEL_INFO, "Hot Plug %s addr %x config: %x", ds1624_sns[idx].name, addr, config); } } @@ -98,16 +111,37 @@ bool DS1624GetTemp(float *value, int idx) { uint32_t addr = DS1624_Idx2Addr(idx); + uint8_t config; + if (!I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { + ds1624_sns[idx].misscnt++; + AddLog_P2(LOG_LEVEL_INFO, "%s device missing (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].misscnt); + return false; + } + ds1624_sns[idx].misscnt=0; + if (config & (DS1621_CFG_1SHOT|DS1621_CFG_DONE)) { + ds1624_sns[idx].errcnt++; + AddLog_P2(LOG_LEVEL_INFO, "%s config error, restart... (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].errcnt); + DS1624_Restart(config, idx); + return false; + } + uint16_t t; if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { return false; } - *value = ((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625; - if (ds1624_sns[idx].type == DS1624_TYPE_DS1621) { // Higher resolution + if (ds1624_sns[idx].type == DS1624_TYPE_DS1624) { + *value = ((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625; + } else { //type == DS1624_TYPE_DS1621 + // Datasheet for ds1621 is wrong for high resolution, real is: + *value = ((float)(int8_t)(t>>8)); uint8_t remain; if (!I2cValidRead8(&remain, addr, DS1621_COUNTER_REGISTER)) { return true; } uint8_t perc; if (!I2cValidRead8(&perc, addr, DS1621_SLOPE_REGISTER)) { return true; } - *value += ((float)perc - (float)remain)/((float)perc) - 0.25; + float fix=(float)(perc - remain)/(float)perc; + *value+=fix; } + ds1624_sns[idx].errcnt=0; + config &= ~(DS1621_CFG_DONE); + I2cWrite8(addr, DS1624_CONF_REGISTER, config); return true; } @@ -120,9 +154,11 @@ void DS1624HotPlugScan(void) if (I2cActive(addr) && !ds1624_sns[idx].valid) { continue; // is busy by another driver } - if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { - DS1624_HotPlugDown(idx); - continue; + if (ds1624_sns[idx].valid) { + if ((ds1624_sns[idx].misscnt>2)||(ds1624_sns[idx].errcnt>2)) { + DS1624_HotPlugDown(idx); + continue; + } } DS1624_HotPlugUp(idx); } From 60f54927655027931c115e440859a3ec614117ed Mon Sep 17 00:00:00 2001 From: Hadinger Date: Thu, 23 Jan 2020 21:55:10 +0100 Subject: [PATCH 078/160] Add Zigbee support for Aqara Cube rotate --- tasmota/xdrv_23_zigbee_5_converters.ino | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index af691876e..795b9db1a 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -356,7 +356,12 @@ uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer // TODO case 0x39: // float - i += 4; + { + uint32_t uint32_val = buf.get32(i); + float * float_val = (float*) &uint32_val; + i += 4; + json[attrid_str] = *float_val; + } break; case 0xE0: // ToD @@ -401,7 +406,12 @@ uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer i += 2; break; case 0x3A: // double precision - i += 8; + { + uint64_t uint64_val = buf.get64(i); + double * double_val = (double*) &uint64_val; + i += 8; + json[attrid_str] = *double_val; + } break; } @@ -561,7 +571,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x000C, 0x0041, "MaxPresentValue", &Z_Copy }, { 0x000C, 0x0045, "MinPresentValue", &Z_Copy }, { 0x000C, 0x0051, "OutOfService", &Z_Copy }, - { 0x000C, 0x0055, "PresentValue", &Z_Copy }, + { 0x000C, 0x0055, "AqaraRotate", &Z_Copy }, { 0x000C, 0x0057, "PriorityArray", &Z_Copy }, { 0x000C, 0x0067, "Reliability", &Z_Copy }, { 0x000C, 0x0068, "RelinquishDefault", &Z_Copy }, @@ -569,6 +579,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x000C, 0x006F, "StatusFlags", &Z_Copy }, { 0x000C, 0x0075, "EngineeringUnits", &Z_Copy }, { 0x000C, 0x0100, "ApplicationType", &Z_Copy }, + { 0x000C, 0xFF05, "Aqara_FF05", &Z_Copy }, // Binary Output cluster { 0x0010, 0x0004, "ActiveText", &Z_Copy }, { 0x0010, 0x001C, "Description", &Z_Copy }, From 6757d9731a58db59609de709980648eec7ede419 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Thu, 23 Jan 2020 19:17:15 -0300 Subject: [PATCH 079/160] new ADC Range definition --- tasmota/language/bg-BG.h | 1 + tasmota/language/cs-CZ.h | 1 + tasmota/language/de-DE.h | 1 + tasmota/language/el-GR.h | 1 + tasmota/language/en-GB.h | 1 + tasmota/language/es-ES.h | 1 + tasmota/language/fr-FR.h | 1 + tasmota/language/he-HE.h | 1 + tasmota/language/hu-HU.h | 1 + tasmota/language/it-IT.h | 1 + tasmota/language/ko-KO.h | 1 + tasmota/language/nl-NL.h | 1 + tasmota/language/pl-PL.h | 1 + tasmota/language/pt-BR.h | 1 + tasmota/language/pt-PT.h | 1 + tasmota/language/ru-RU.h | 1 + tasmota/language/sk-SK.h | 1 + tasmota/language/sv-SE.h | 1 + tasmota/language/tr-TR.h | 1 + tasmota/language/uk-UA.h | 1 + tasmota/language/zh-CN.h | 1 + tasmota/language/zh-TW.h | 1 + 22 files changed, 22 insertions(+) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 8f1c82bc3..e89903cee 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Размер на програмата" #define D_PROJECT "Проект" #define D_RAIN "Дъжд" +#define D_RANGE "Range" #define D_RECEIVED "Получено" #define D_RESTART "Рестарт" #define D_RESTARTING "Рестартиране" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 3b11a7ebc..d7e8e188e 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Velikost programu" #define D_PROJECT "Projekt" #define D_RAIN "Rain" +#define D_RANGE "Range" #define D_RECEIVED "Přijatý" #define D_RESTART "Restart" #define D_RESTARTING "Restartování" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index e09278526..b710e2975 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Ben. Flash Speicher" #define D_PROJECT "Projekt" #define D_RAIN "Regen" +#define D_RANGE "Range" #define D_RECEIVED "erhalten" #define D_RESTART "Neustart" #define D_RESTARTING "starte neu" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index 070267215..1c76125fa 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Μέγεθος προγράμματος" #define D_PROJECT "Έργο" #define D_RAIN "Rain" +#define D_RANGE "Range" #define D_RECEIVED "Ελήφθη" #define D_RESTART "Επανεκκίνηση" #define D_RESTARTING "Επανεκκινεί" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index 5121a7471..b994b0409 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Program Size" #define D_PROJECT "Project" #define D_RAIN "Rain" +#define D_RANGE "Range" #define D_RECEIVED "Received" #define D_RESTART "Restart" #define D_RESTARTING "Restarting" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 8ff2b415f..6b8d60d01 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Tamaño Programa" #define D_PROJECT "Proyecto" #define D_RAIN "Lluvia" +#define D_RANGE "Range" #define D_RECEIVED "Recibido" #define D_RESTART "Reiniciar" #define D_RESTARTING "Reiniciando" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index 3829a8681..4a861bd82 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Taille programme" #define D_PROJECT "Projet" #define D_RAIN "Pluie" +#define D_RANGE "Range" #define D_RECEIVED "Reçu" #define D_RESTART "Redémarrage" #define D_RESTARTING "Redémarre" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index d0c5e364b..166c5c735 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "גודל תוכנית" #define D_PROJECT "פרויקט" #define D_RAIN "גשם" +#define D_RANGE "Range" #define D_RECEIVED "התקבל" #define D_RESTART "איתחול" #define D_RESTARTING "הפעלה מחדש" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 70f219c98..e1cec813a 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Program méret" #define D_PROJECT "Projekt" #define D_RAIN "Eső" +#define D_RANGE "Range" #define D_RECEIVED "Érkezett" #define D_RESTART "Újraindítás" #define D_RESTARTING "Újraindítás" diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index 73830deca..d7ec1e0e5 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Dimensione Programma" #define D_PROJECT "Progetto" #define D_RAIN "Rain" +#define D_RANGE "Range" #define D_RECEIVED "Ricevuto" #define D_RESTART "Riavvio" #define D_RESTARTING "Riavviando" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index 328acc568..55b8dba97 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "프로그램 용량" #define D_PROJECT "프로젝트" #define D_RAIN "비" +#define D_RANGE "Range" #define D_RECEIVED "받음" #define D_RESTART "재시작" #define D_RESTARTING "재시작 중.." diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 3d5ec8b7d..c0b5a9862 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Programma Grootte" #define D_PROJECT "Project" #define D_RAIN "Regen" +#define D_RANGE "Range" #define D_RECEIVED "Ontvangen" #define D_RESTART "Herstart" #define D_RESTARTING "Herstarten" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 63fe6fcad..237bc66f1 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Rozmiar programu" #define D_PROJECT "Projekt" #define D_RAIN "Deszcz" +#define D_RANGE "Range" #define D_RECEIVED "Otrzymany" #define D_RESTART "Restart" #define D_RESTARTING "Restartowanie" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index da6e8ca1b..c56262b11 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Tamanho do programa" #define D_PROJECT "Projeto" #define D_RAIN "Rain" +#define D_RANGE "Range" #define D_RECEIVED "Recebido" #define D_RESTART "Reiniciar" #define D_RESTARTING "Reiniciando" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 47137b90b..be9c6d493 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Tamanho do Programa" #define D_PROJECT "Projeto" #define D_RAIN "Chuva" +#define D_RANGE "Range" #define D_RECEIVED "Recebido" #define D_RESTART "Reiniciar" #define D_RESTARTING "A reiniciar" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 31c295059..57dfa40e1 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Размер программы " #define D_PROJECT "Проект" #define D_RAIN "Rain" +#define D_RANGE "Range" #define D_RECEIVED "Получено" #define D_RESTART "Перезапуск" #define D_RESTARTING "Перезапуск" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index 89f3d7353..ee7afb49f 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Veľkosť programu" #define D_PROJECT "Projekt" #define D_RAIN "Dážď" +#define D_RANGE "Range" #define D_RECEIVED "Prijatý" #define D_RESTART "Reštart" #define D_RESTARTING "Reštartuje sa" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index ddc2307b4..351bf6dbb 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Programstorlek" #define D_PROJECT "Projekt" #define D_RAIN "Regn" +#define D_RANGE "Range" #define D_RECEIVED "Mottagen" #define D_RESTART "Omstart" #define D_RESTARTING "Startar om" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 38f125d6c..fced504d3 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Yazılım Boyutu" #define D_PROJECT "Proje" #define D_RAIN "Rain" +#define D_RANGE "Range" #define D_RECEIVED "Alınan" #define D_RESTART "Yeniden Başlat" #define D_RESTARTING "Yeniden Başlatılıyor" diff --git a/tasmota/language/uk-UA.h b/tasmota/language/uk-UA.h index b634935cf..81d02a8b3 100644 --- a/tasmota/language/uk-UA.h +++ b/tasmota/language/uk-UA.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "Розмір програми" #define D_PROJECT "Проект" #define D_RAIN "Дощ" +#define D_RANGE "Range" #define D_RECEIVED "Отримано" #define D_RESTART "Перезавантаження" #define D_RESTARTING "Перезавантаження" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 97b41a29a..12c368cd3 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "固件大小" #define D_PROJECT "项目:" #define D_RAIN "降水量" +#define D_RANGE "Range" #define D_RECEIVED "已接收" #define D_RESTART "重启" #define D_RESTARTING "正在重启" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 1fd30e6e4..7c1b2e3fb 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -137,6 +137,7 @@ #define D_PROGRAM_SIZE "韌體大小" #define D_PROJECT "項目:" #define D_RAIN "Rain" +#define D_RANGE "Range" #define D_RECEIVED "已接收" #define D_RESTART "重啟" #define D_RESTARTING "正在重啟" From 26755202c7336ac6256646591c4397b3bea93e2b Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Thu, 23 Jan 2020 19:21:49 -0300 Subject: [PATCH 080/160] New ADC Range --- tasmota/i18n.h | 4 ++++ tasmota/tasmota_template.h | 4 ++-- tasmota/xsns_02_analog.ino | 32 ++++++++++++++++---------------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 20207bcb4..6437bc2dc 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -114,6 +114,7 @@ #define D_JSON_ACTIVE_POWERUSAGE "ActivePower" #define D_JSON_APPARENT_POWERUSAGE "ApparentPower" #define D_JSON_REACTIVE_POWERUSAGE "ReactivePower" +#define D_JSON_RANGE "Range" #define D_JSON_PRESSURE "Pressure" #define D_JSON_PRESSUREATSEALEVEL "SeaPressure" #define D_JSON_PRESSURE_UNIT "PressureUnit" @@ -605,6 +606,7 @@ const char JSON_SNS_TEMPHUM[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s, const char JSON_SNS_ILLUMINANCE[] PROGMEM = ",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d}"; const char JSON_SNS_MOISTURE[] PROGMEM = ",\"%s\":{\"" D_JSON_MOISTURE "\":%d}"; +const char JSON_SNS_RANGE[] PROGMEM = ",\"%s\":{\"" D_JSON_RANGE "\":%d}"; const char JSON_SNS_GNGPM[] PROGMEM = ",\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}"; @@ -636,6 +638,8 @@ const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PE const char HTTP_SNS_GALLONS[] PROGMEM = "{s}%s " D_TOTAL_USAGE "{m}%s " D_UNIT_GALLONS " {e}"; const char HTTP_SNS_GPM[] PROGMEM = "{s}%s " D_FLOW_RATE "{m}%s " D_UNIT_GALLONS_PER_MIN" {e}"; const char HTTP_SNS_MOISTURE[] PROGMEM = "{s}%s " D_MOISTURE "{m}%d %%{e}"; +const char HTTP_SNS_RANGE[] PROGMEM = "{s}%s " D_RANGE "{m}%d %%{e}"; + const char HTTP_SNS_VOLTAGE[] PROGMEM = "{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"; const char HTTP_SNS_CURRENT[] PROGMEM = "{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"; diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 9bb98ce6e..f041620c6 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -311,7 +311,7 @@ enum UserSelectableAdc0 { ADC0_LIGHT, // Light sensor ADC0_BUTTON, // Button ADC0_BUTTON_INV, - ADC0_MOIST, // Moisture + ADC0_RANGE, // Range ADC0_CT_POWER, // Current // ADC0_SWITCH, // Switch // ADC0_SWITCH_INV, @@ -328,7 +328,7 @@ const char kAdc0Names[] PROGMEM = D_SENSOR_NONE "|" D_ANALOG_INPUT "|" D_TEMPERATURE "|" D_LIGHT "|" D_SENSOR_BUTTON "|" D_SENSOR_BUTTON "i|" - D_MOISTURE "|" + D_RANGE "|" D_CT_POWER "|" // D_SENSOR_SWITCH "|" D_SENSOR_SWITCH "i|" ; diff --git a/tasmota/xsns_02_analog.ino b/tasmota/xsns_02_analog.ino index 93df3d5e1..038da9fa5 100644 --- a/tasmota/xsns_02_analog.ino +++ b/tasmota/xsns_02_analog.ino @@ -85,8 +85,8 @@ void AdcInit(void) Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR; Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; } - else if (ADC0_MOIST == my_adc0) { - Settings.adc_param_type = ADC0_MOIST; + else if (ADC0_RANGE == my_adc0) { + Settings.adc_param_type = ADC0_RANGE; Settings.adc_param1 = 0; Settings.adc_param2 = 1023; Settings.adc_param3 = 0; @@ -145,14 +145,14 @@ uint16_t AdcGetLux(void) return (uint16_t)ldrLux; } -uint16_t AdcGetMoist(void) +uint16_t AdcGetRange(void) { - // formula for calibration: value, fromLow, fromHigh, toHigh, toLow - // Example: 632, 0, 1023, 0, 100 - // int( ( ( ( - ) / ( - ) ) * ( - ) ) + ) + // formula for calibration: value, fromLow, fromHigh, toLow, toHigh + // Example: 514, 632, 236, 0, 100 + // int( (( - ) / ( - ) ) * ( - ) ) + ) int adc = AdcRead(2); - double amoist = ( ((double)Settings.adc_param2 - (double)adc) / ( ((double)Settings.adc_param2 - (double)Settings.adc_param1)) * ((double)Settings.adc_param3 - (double)Settings.adc_param4) + (double)Settings.adc_param4 ); - return (uint16_t)amoist; + double adcrange = ( ((double)Settings.adc_param2 - (double)adc) / ( ((double)Settings.adc_param2 - (double)Settings.adc_param1)) * ((double)Settings.adc_param3 - (double)Settings.adc_param4) + (double)Settings.adc_param4 ); + return (uint16_t)adcrange; } void AdcGetCurrentPower(uint8_t factor) @@ -253,14 +253,14 @@ void AdcShow(bool json) } } - else if (ADC0_MOIST == my_adc0) { - uint16_t adc_moist = AdcGetMoist(); + else if (ADC0_RANGE == my_adc0) { + uint16_t adc_range = AdcGetRange(); if (json) { - ResponseAppend_P(JSON_SNS_MOISTURE, "ANALOG", adc_moist); + ResponseAppend_P(JSON_SNS_RANGE, "ANALOG", adc_range); #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_SNS_MOISTURE, "", adc_moist); + WSContentSend_PD(HTTP_SNS_RANGE, "", adc_range); #endif // USE_WEBSERVER } } @@ -340,7 +340,7 @@ void CmndAdcParam(void) if (XdrvMailbox.data_len) { if ((ADC0_TEMP == XdrvMailbox.payload) || (ADC0_LIGHT == XdrvMailbox.payload) || - (ADC0_MOIST == XdrvMailbox.payload) || + (ADC0_RANGE == XdrvMailbox.payload) || (ADC0_CT_POWER == XdrvMailbox.payload)) { if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len +1]; @@ -350,7 +350,7 @@ void CmndAdcParam(void) Settings.adc_param_type = XdrvMailbox.payload; Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); - if (ADC0_MOIST == XdrvMailbox.payload) { + if (ADC0_RANGE == XdrvMailbox.payload) { Settings.adc_param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10)); Settings.adc_param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10)); } else { @@ -375,7 +375,7 @@ void CmndAdcParam(void) // AdcParam Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d"), Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2); - if (ADC0_MOIST == my_adc0) { + if (ADC0_RANGE == my_adc0) { ResponseAppend_P(PSTR(",%d,%d"), Settings.adc_param3, Settings.adc_param4); } else { int value = Settings.adc_param3; @@ -407,7 +407,7 @@ bool Xsns02(uint8_t function) if ((ADC0_INPUT == my_adc0) || (ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0) || - (ADC0_MOIST == my_adc0) || + (ADC0_RANGE == my_adc0) || (ADC0_CT_POWER == my_adc0)) { switch (function) { #ifdef USE_RULES From ddd1f4c379f99ed6892b8120fe693ee93de8c196 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 24 Jan 2020 12:48:50 +0100 Subject: [PATCH 081/160] Return state information when wakeup is complete Return state information when wakeup is complete (#7583) --- tasmota/xdrv_04_light.ino | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 2de7432a0..4ef8b409e 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1723,8 +1723,16 @@ void LightAnimate(void) Light.new_color[i] = Light.current_color[i]; } } else { +/* Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_CMND_WAKEUP)); +*/ + Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"")); + LightState(1); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WAKEUP)); + XdrvRulesProcess(); + Light.wakeup_active = 0; Settings.light_scheme = LS_POWER; } From 473299ffcd987d93fbe8eee5e1328bbf6bda54b5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 24 Jan 2020 17:13:39 +0100 Subject: [PATCH 082/160] Refactor rules JSON decoding Refactor rules JSON decoding allowing up to 10 subtypes deep --- tasmota/xdrv_10_rules.ino | 53 +++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index b750ebcbe..89fbfebe9 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -255,37 +255,42 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) } // Step2: Search rule_task and rule_name - StaticJsonBuffer<1024> jsonBuf; - JsonObject &root = jsonBuf.parseObject(event); - if (!root.success()) { return false; } // No valid JSON data - - String rule_subfield = ""; - const char* str_value; - if ((pos = rule_name.indexOf("[")) > 0) { // "CURRENT[1]" - int rule_name_idx = rule_name.substring(pos +1).toInt(); + int rule_name_idx = 0; + if ((pos = rule_name.indexOf("[")) > 0) { // "SUBTYPE1#CURRENT[1]" + rule_name_idx = rule_name.substring(pos +1).toInt(); if ((rule_name_idx < 1) || (rule_name_idx > 6)) { // Allow indexes 1 to 6 rule_name_idx = 1; } - rule_name = rule_name.substring(0, pos); // "CURRENT" - str_value = root[rule_task][rule_name][rule_name_idx -1]; // "ENERGY" and "CURRENT" and 0 - } - else if ((pos = rule_name.indexOf("#")) > 0) { // "VIBRATION_SENSOR#AQARACUBESIDE" - rule_subfield = rule_name.substring(pos +1); // "AQARACUBESIDE" - rule_name = rule_name.substring(0, pos); // "VIBRATION_SENSOR" - str_value = root[rule_task][rule_name][rule_subfield]; // "ZIGBEERECEIVED", "VIBRATION_SENSOR" and "AQARACUBESIDE" - } else { - str_value = root[rule_task][rule_name]; // "INA219" and "CURRENT" + rule_name = rule_name.substring(0, pos); // "SUBTYPE1#CURRENT" } -//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"), -// rule_task.c_str(), rule_name.c_str(), rule_svalue, Rules.trigger_count[rule_set], bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none"); + StaticJsonBuffer<1024> jsonBuf; + JsonObject &root = jsonBuf.parseObject(event); + if (!root.success()) { return false; } // No valid JSON data + if (!root[rule_task].success()) { return false; } // No rule_task in JSON data - if (rule_subfield.length()) { - if (!root[rule_task][rule_name][rule_subfield].success()) { return false; } - } else { - if (!root[rule_task][rule_name].success()) { return false; } + JsonObject &obj1 = root[rule_task]; + JsonObject *obj = &obj1; + String subtype; + uint32_t i = 0; + while ((pos = rule_name.indexOf("#")) > 0) { // "SUBTYPE1#SUBTYPE2#CURRENT" + subtype = rule_name.substring(0, pos); + if (!(*obj)[subtype].success()) { return false; } // No subtype in JSON data + JsonObject &obj2 = (*obj)[subtype]; + obj = &obj2; + rule_name = rule_name.substring(pos +1); + if (i++ > 10) { return false; } // Abandon possible loop } - // No value but rule_name is ok + if (!(*obj)[rule_name].success()) { return false; } // No name in JSON data + const char* str_value; + if (rule_name_idx) { + str_value = (*obj)[rule_name][rule_name_idx -1]; // "CURRENT[1]" + } else { + str_value = (*obj)[rule_name]; // "CURRENT" + } + +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"), +// rule_task.c_str(), rule_name.c_str(), rule_svalue, Rules.trigger_count[rule_set], bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none"); Rules.event_value = str_value; // Prepare %value% From cfbd1cb85d870085276d7592a69c0e238de2237a Mon Sep 17 00:00:00 2001 From: RemiDing Date: Sat, 25 Jan 2020 11:22:28 +0100 Subject: [PATCH 083/160] optimized --- tasmota/support_switch.ino | 41 +++++++++++++++++++++++++++++++++++++- tasmota/tasmota.h | 4 ++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/tasmota/support_switch.ino b/tasmota/support_switch.ino index 9cc3c336f..6df39c5d7 100644 --- a/tasmota/support_switch.ino +++ b/tasmota/support_switch.ino @@ -154,6 +154,22 @@ void SwitchHandler(uint8_t mode) case FOLLOWMULTI_INV: switchflag = ~button &1; // Follow inverted wall switch state after hold break; + case PUSHHOLDMULTI: + if (PRESSED == button){ + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; + SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + } + else + SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT + break; + case PUSHHOLDMULTI_INV: + if (NOT_PRESSED == button){ + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; + SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + } + else + SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT + break; default: SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT break; @@ -213,8 +229,31 @@ void SwitchHandler(uint8_t mode) Switch.hold_timer[i] = loops_per_second / 2; // 0.5 second multi press window } break; + case PUSHHOLDMULTI: + if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { + if(Switch.hold_timer[i]!=0) + SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { + if(Switch.hold_timer[i] > loops_per_second * Settings.param[P_HOLD_TIME] / 25) + switchflag = POWER_TOGGLE; // Toggle with pushbutton + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + break; + case PUSHHOLDMULTI_INV: + if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { + if(Switch.hold_timer[i]!=0) + SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { + if(Switch.hold_timer[i] > loops_per_second * Settings.param[P_HOLD_TIME] / 25) + switchflag = POWER_TOGGLE; // Toggle with pushbutton + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + break; } - Switch.last_state[i] = button; } if (switchflag <= POWER_TOGGLE) { diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index b4b944d80..d12bb22ef 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -231,7 +231,7 @@ enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_D enum WifiConfigOptions {WIFI_RESTART, EX_WIFI_SMARTCONFIG, WIFI_MANAGER, EX_WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY, MAX_WIFI_OPTION}; -enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEMULTI, FOLLOWMULTI, FOLLOWMULTI_INV, MAX_SWITCH_OPTION}; +enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEMULTI, FOLLOWMULTI, FOLLOWMULTI_INV, PUSHHOLDMULTI, PUSHHOLDMULTI_INV, MAX_SWITCH_OPTION}; enum LedStateOptions {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION}; @@ -242,7 +242,7 @@ enum TopicOptions { CMND, STAT, TELE, nu1, RESULT_OR_CMND, RESULT_OR_STAT, RESUL enum ExecuteCommandPowerOptions { POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK, POWER_BLINK_STOP, POWER_OFF_NO_STATE = 8, POWER_ON_NO_STATE, POWER_TOGGLE_NO_STATE, POWER_SHOW_STATE = 16 }; -enum SendKeyPowerOptions { POWER_HOLD = 3, CLEAR_RETAIN = 9 }; +enum SendKeyPowerOptions { POWER_HOLD = 3, POWER_INV = 4, POWER_CLEAR = 5, CLEAR_RETAIN = 9 }; enum SendKeyOptions { KEY_BUTTON, KEY_SWITCH }; enum PowerOnStateOptions { POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON }; From febabec3bb70968b500de7bb359c4b84b16b9fe3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 25 Jan 2020 12:17:35 +0100 Subject: [PATCH 084/160] Fix Gui ADC Range unit --- tasmota/i18n.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 6437bc2dc..dbee3246c 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -638,8 +638,7 @@ const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PE const char HTTP_SNS_GALLONS[] PROGMEM = "{s}%s " D_TOTAL_USAGE "{m}%s " D_UNIT_GALLONS " {e}"; const char HTTP_SNS_GPM[] PROGMEM = "{s}%s " D_FLOW_RATE "{m}%s " D_UNIT_GALLONS_PER_MIN" {e}"; const char HTTP_SNS_MOISTURE[] PROGMEM = "{s}%s " D_MOISTURE "{m}%d %%{e}"; -const char HTTP_SNS_RANGE[] PROGMEM = "{s}%s " D_RANGE "{m}%d %%{e}"; - +const char HTTP_SNS_RANGE[] PROGMEM = "{s}%s " D_RANGE "{m}%d{e}"; const char HTTP_SNS_VOLTAGE[] PROGMEM = "{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"; const char HTTP_SNS_CURRENT[] PROGMEM = "{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"; From 53e93215df029310d5ab392180902a35aebfd41a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 25 Jan 2020 13:45:26 +0100 Subject: [PATCH 085/160] Fix trigger SYSTEM#BOOT Fix trigger SYSTEM#BOOT when mdns is disabled an no mqqthost is set (#7552) --- tasmota/xdrv_02_mqtt.ino | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 38bae9a01..529b3ce3c 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -667,11 +667,6 @@ void MqttCheck(void) if (!MqttIsConnected()) { global_state.mqtt_down = 1; if (!Mqtt.retry_counter) { -#ifdef USE_DISCOVERY -#ifdef MQTT_HOST_DISCOVERY - if (!strlen(SettingsText(SET_MQTT_HOST)) && !Wifi.mdns_begun) { return; } -#endif // MQTT_HOST_DISCOVERY -#endif // USE_DISCOVERY MqttReconnect(); } else { Mqtt.retry_counter--; @@ -681,7 +676,9 @@ void MqttCheck(void) } } else { global_state.mqtt_down = 0; - if (Mqtt.initial_connection_state) MqttReconnect(); + if (Mqtt.initial_connection_state) { + MqttReconnect(); + } } } From e34cc3cbcc371196fd5e072eca1e212e45541941 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 25 Jan 2020 17:42:53 +0100 Subject: [PATCH 086/160] Change Zigbee commands renamed to ``Zb*`` --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 39 ++++++++++--------- tasmota/my_user_config.h | 2 +- tasmota/xdrv_23_zigbee_3_devices.ino | 20 ++++++++-- tasmota/xdrv_23_zigbee_4_persistence.ino | 2 +- tasmota/xdrv_23_zigbee_5_converters.ino | 2 +- tasmota/xdrv_23_zigbee_7_statemachine.ino | 2 +- tasmota/xdrv_23_zigbee_8_parsers.ino | 2 +- tasmota/xdrv_23_zigbee_9_impl.ino | 47 +++++++++++++---------- 9 files changed, 70 insertions(+), 47 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 5c7073c6e..a28cf36b4 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -11,6 +11,7 @@ - Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) - Add optional parameter to command ``Scheme , `` to control initial start color - Add rule trigger on one level deeper using syntax with two ``#`` like ``on zigbeereceived#vibration_sensor#aqaracubeside=0 do ...`` +- Change Zigbee commands renamed to ``Zb*`` ### 8.1.0.3 20200106 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index dbee3246c..fdf07acd6 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -467,29 +467,32 @@ #define D_JSON_TUYA_MCU_RECEIVED "TuyaReceived" // Commands xdrv_23_zigbee.ino +#define D_PRFX_ZB "Zb" +#define D_PRFX_ZIGBEE "Zigbee" #define D_ZIGBEE_NOT_STARTED "Zigbee not started (yet)" -#define D_CMND_ZIGBEE_PERMITJOIN "ZigbeePermitJoin" -#define D_CMND_ZIGBEE_STATUS "ZigbeeStatus" -#define D_CMND_ZIGBEE_RESET "ZigbeeReset" +#define D_CMND_ZIGBEE_PERMITJOIN "PermitJoin" +#define D_CMND_ZIGBEE_STATUS "Status" +#define D_CMND_ZIGBEE_RESET "Reset" #define D_JSON_ZIGBEE_CC2530 "CC2530" -#define D_CMND_ZIGBEEZNPRECEIVE "ZigbeeZNPReceive" // only for debug -#define D_CMND_ZIGBEEZNPSEND "ZigbeeZNPSend" - #define D_JSON_ZIGBEE_STATE "ZigbeeState" - #define D_JSON_ZIGBEEZNPRECEIVED "ZigbeeZNPReceived" - #define D_JSON_ZIGBEEZNPSENT "ZigbeeZNPSent" - #define D_JSON_ZIGBEEZCL_RECEIVED "ZigbeeZCLReceived" - #define D_JSON_ZIGBEEZCL_RAW_RECEIVED "ZigbeeZCLRawReceived" +#define D_CMND_ZIGBEEZNPRECEIVE "ZNPReceive" // only for debug +#define D_CMND_ZIGBEEZNPSEND "ZNPSend" + #define D_JSON_ZIGBEE_STATE "ZbState" + #define D_JSON_ZIGBEEZNPRECEIVED "ZbZNPReceived" + #define D_JSON_ZIGBEEZNPSENT "ZbZNPSent" + #define D_JSON_ZIGBEEZCL_RECEIVED "ZbZCLReceived" + #define D_JSON_ZIGBEEZCL_RAW_RECEIVED "ZbZCLRawReceived" #define D_JSON_ZIGBEE_DEVICE "Device" #define D_JSON_ZIGBEE_NAME "Name" -#define D_CMND_ZIGBEE_NAME "ZigbeeName" -#define D_CMND_ZIGBEE_PROBE "ZigbeeProbe" -#define D_CMND_ZIGBEE_FORGET "ZigbeeForget" -#define D_CMND_ZIGBEE_SAVE "ZigbeeSave" -#define D_CMND_ZIGBEE_RECEIVED "ZigbeeReceived" +#define D_CMND_ZIGBEE_NAME "Name" +#define D_CMND_ZIGBEE_PROBE "Probe" +#define D_CMND_ZIGBEE_FORGET "Forget" +#define D_CMND_ZIGBEE_SAVE "Save" #define D_CMND_ZIGBEE_LINKQUALITY "LinkQuality" -#define D_CMND_ZIGBEE_READ "ZigbeeRead" -#define D_CMND_ZIGBEE_SEND "ZigbeeSend" - #define D_JSON_ZIGBEE_ZCL_SENT "ZigbeeZCLSent" +#define D_CMND_ZIGBEE_READ "Read" +#define D_CMND_ZIGBEE_SEND "Send" + #define D_JSON_ZIGBEE_ZCL_SENT "ZbZCLSent" +#define D_JSON_ZIGBEE_RECEIVED "ZbReceived" +#define D_JSON_ZIGBEE_RECEIVED_LEGACY "ZigbeeReceived" // Commands xdrv_25_A4988_Stepper.ino #define D_CMND_MOTOR "MOTOR" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index ec40b4c8d..8b52aa7a7 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -594,7 +594,7 @@ #define IR_RCV_MIN_UNKNOWN_SIZE 6 // Set the smallest sized "UNKNOWN" message packets we actually care about (default 6, max 255) // -- Zigbee interface ---------------------------- -//#define USE_ZIGBEE // Enable serial communication with Zigbee CC2530 flashed with ZNP +//#define USE_ZIGBEE // Enable serial communication with Zigbee CC2530 flashed with ZNP (+35k code, +3.2k mem) #define USE_ZIGBEE_PANID 0x1A63 // arbitrary PAN ID for Zigbee network, must be unique in the home #define USE_ZIGBEE_EXTPANID 0xCCCCCCCCCCCCCCCCL // arbitrary extended PAN ID #define USE_ZIGBEE_CHANNEL 11 // Zigbee Channel (11-26) diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index 339737b57..5db3986e4 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -681,12 +681,24 @@ void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { zigbee_devices.jsonClear(shortaddr); if (use_fname) { - Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + // DEPRECATED TODO + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); } else { - Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + // DEPRECATED TODO + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); } - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); + // MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + // XdrvRulesProcess(); } void Z_Devices::jsonPublishNow(uint16_t shortaddr, JsonObject & values) { diff --git a/tasmota/xdrv_23_zigbee_4_persistence.ino b/tasmota/xdrv_23_zigbee_4_persistence.ino index c3003854f..fcf1dcdc3 100644 --- a/tasmota/xdrv_23_zigbee_4_persistence.ino +++ b/tasmota/xdrv_23_zigbee_4_persistence.ino @@ -184,7 +184,7 @@ class SBuffer hibernateDevices(void) { // Log char *hex_char = (char*) malloc((buf_len * 2) + 2); if (hex_char) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZigbeeFlashStore %s"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZbFlashStore %s"), ToHex_P(buf.getBuffer(), buf_len, hex_char, (buf_len * 2) + 2)); free(hex_char); } diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 795b9db1a..0518ec6be 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -483,7 +483,7 @@ void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { uint32_t len = _payload.len(); char attrid_str[12]; - snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X!%02X"), _cmd_id, _cluster_id); + snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X!%02X"), _cluster_id, _cmd_id); char hex_char[_payload.len()*2+2]; ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index 683375bf1..5a3d78e85 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -545,7 +545,7 @@ void ZigbeeStateMachine_Run(void) { } // load current instruction details - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Executing instruction pc=%d"), zigbee.pc); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Executing instruction pc=%d"), zigbee.pc); const Zigbee_Instruction *cur_instr_line = &zb_prog[zigbee.pc]; cur_instr = pgm_read_byte(&cur_instr_line->i.i); cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 26185fd6c..74a900f00 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -445,7 +445,7 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { String msg(""); msg.reserve(100); json.printTo(msg); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZigbeeZCLRawReceived: {\"0x%04X\":%s}"), srcaddr, msg.c_str()); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":%s}"), srcaddr, msg.c_str()); zcl_received.postProcessAttributes(srcaddr, json); // Add linkquality diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 9b44ce35e..2b529c8d6 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -28,12 +28,18 @@ const uint8_t ZIGBEE_SOF_ALT = 0xFF; #include TasmotaSerial *ZigbeeSerial = nullptr; -const char kZigbeeCommands[] PROGMEM = "|" + +const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME - ; + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME ; + +const char kZigbeeCommands[] PROGMEM = D_PRFX_ZIGBEE "|" // legacy prefix -- deprecated + D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" + D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" + D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME ; void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZigbeeZNPSend, &CmndZigbeePermitJoin, @@ -64,7 +70,7 @@ int32_t ZigbeeProcessInput(class SBuffer &buf) { } } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "ZigbeeProcessInput: recv_prefix_match = %d, recv_filter_match = %d"), recv_prefix_match, recv_filter_match); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "ZbProcessInput: recv_prefix_match = %d, recv_filter_match = %d"), recv_prefix_match, recv_filter_match); } // if there is a recv_callback, call it now @@ -103,7 +109,7 @@ int32_t ZigbeeProcessInput(class SBuffer &buf) { res = (*zigbee.recv_unexpected)(res, buf); } } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "ZigbeeProcessInput: res = %d"), res); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "ZbProcessInput: res = %d"), res); // change state accordingly if (0 == res) { @@ -136,7 +142,7 @@ void ZigbeeInput(void) while (ZigbeeSerial->available()) { yield(); uint8_t zigbee_in_byte = ZigbeeSerial->read(); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZigbeeInput byte=%d len=%d"), zigbee_in_byte, zigbee_buffer->len()); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZbInput byte=%d len=%d"), zigbee_in_byte, zigbee_buffer->len()); if (0 == zigbee_buffer->len()) { // make sure all variables are correctly initialized zigbee_frame_len = 5; @@ -145,14 +151,14 @@ void ZigbeeInput(void) // in this case the first bit (lsb) is missed and Tasmota receives 0xFF instead of 0xFE // We forgive this mistake, and next bytes are automatically resynchronized if (ZIGBEE_SOF_ALT == zigbee_in_byte) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeInput forgiven first byte %02X (only for statistics)"), zigbee_in_byte); + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput forgiven first byte %02X (only for statistics)"), zigbee_in_byte); zigbee_in_byte = ZIGBEE_SOF; } } if ((0 == zigbee_buffer->len()) && (ZIGBEE_SOF != zigbee_in_byte)) { // waiting for SOF (Start Of Frame) byte, discard anything else - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeInput discarding byte %02X"), zigbee_in_byte); + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput discarding byte %02X"), zigbee_in_byte); continue; // discard } @@ -212,7 +218,7 @@ void ZigbeeInit(void) { zigbee.active = false; if ((pin[GPIO_ZIGBEE_RX] < 99) && (pin[GPIO_ZIGBEE_TX] < 99)) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("Zigbee: GPIOs Rx:%d Tx:%d"), pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX]); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "GPIOs Rx:%d Tx:%d"), pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX]); // if seriallog_level is 0, we allow GPIO 13/15 to switch to Hardware Serial ZigbeeSerial = new TasmotaSerial(pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], seriallog_level ? 1 : 2, 0, 256); // set a receive buffer of 256 bytes ZigbeeSerial->begin(115200); @@ -316,17 +322,17 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) { uint8_t fcs = data_len; ZigbeeSerial->write(ZIGBEE_SOF); // 0xFE - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend SOF %02X"), ZIGBEE_SOF); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend SOF %02X"), ZIGBEE_SOF); ZigbeeSerial->write(data_len); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend LEN %02X"), data_len); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend LEN %02X"), data_len); for (uint32_t i = 0; i < len; i++) { uint8_t b = pgm_read_byte(msg + i); ZigbeeSerial->write(b); fcs ^= b; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend byt %02X"), b); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend byt %02X"), b); } ZigbeeSerial->write(fcs); // finally send fcs checksum byte - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend FCS %02X"), fcs); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend FCS %02X"), fcs); } // Now send a MQTT message to report the sent message char hex_char[(len * 2) + 2]; @@ -417,13 +423,13 @@ void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { if (0 == endpoint) { // endpoint is not specified, let's try to find it from shortAddr endpoint = zigbee_devices.findClusterEndpointIn(dstAddr, cluster); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeSend: guessing endpoint 0x%02X"), endpoint); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeSend: dstAddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: dstAddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), dstAddr, cluster, endpoint, cmd, data); if (0 == endpoint) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeSend: unspecified endpoint")); + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint")); return; } @@ -518,9 +524,9 @@ void CmndZigbeeSend(void) { } } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeSend: command_template = %s"), cmd_str.c_str()); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_template = %s"), cmd_str.c_str()); cmd_str = zigbeeCmdAddParams(cmd_str.c_str(), x, y, z); // fill in parameters - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeSend: command_final = %s"), cmd_str.c_str()); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_final = %s"), cmd_str.c_str()); } else { // we have zero command, pass through until last error for missing command } @@ -531,7 +537,7 @@ void CmndZigbeeSend(void) { // we have an unsupported command type, just ignore it and fallback to missing command } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%s\"}"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%s\"}"), device, endpoint, cmd_str.c_str()); zigbeeZCLSendStr(device, endpoint, cmd_str.c_str()); } else { @@ -717,7 +723,8 @@ bool Xdrv23(uint8_t function) ZigbeeInit(); break; case FUNC_COMMAND: - result = DecodeCommand(kZigbeeCommands, ZigbeeCommand); + result = DecodeCommand(kZbCommands, ZigbeeCommand); + result = result || DecodeCommand(kZigbeeCommands, ZigbeeCommand); // deprecated break; } } From 81c6355b8f8068697f3364ab382319388625f5eb Mon Sep 17 00:00:00 2001 From: "CORP\\vdi" Date: Sat, 25 Jan 2020 11:22:40 -0700 Subject: [PATCH 087/160] Address multiple WiFI connectivity /stability issues. 1) Reduce the roam threshold to 5dBm to fix issues where a device might connect at -80dBM which is marginal operation, but would not roam to a -72dBm AP 2) Reduce the scan rate from 44 minutes to 5 minutes to accelerate network harmony 3) Arduino SDK was allowed to control re-connections which resulted in a de-authentication attack on teh WiFi AP. Explicitly disable with WiFi.setAutoReconnect(false); 4) Reduce WIFI_CHECK_SEC to 5, and Wifi.retry_init times to accommodate Tasmota dealing with retransmissions. 5) WifiBeginAfterScan: Save the last BSSID a connection attempt was made on. Should that error, pick the next strongest AP for the next attempt. Addresses situations where an AP has a high RSSI, but poor channel health due to it being overloaded. 6) WifiCheckIPAddrStatus: Error cases did not properly alternate between AP's, with some error cases geeting hug up where they did not initiate a reconnection so the device became non-responsive. Device now starts at Wifi.retry_init, tries to connect, does again at Wifi.retry_init/2, and then does a WifiConfig. Should no IP address be received, restart DHCP each second during this time. Test Environment: 27 Tasmota devices 3 SonicWALL corporate AP's Highly interfered 801.11n network --- tasmota/support_wifi.ino | 105 ++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 40 deletions(-) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 954e2fb3c..1dab28ff1 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -22,14 +22,19 @@ \*********************************************************************************************/ #ifndef WIFI_RSSI_THRESHOLD -#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network +// decrease the roam threshold to address devices connecting at very low RSSI and being close to inoperative +//#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network +#define WIFI_RSSI_THRESHOLD 5 // Difference in dB between current network and scanned network #endif #ifndef WIFI_RESCAN_MINUTES -#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan +// increase rescan interval to 5 minutes to improve ability for devices to reach network harmony +//#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan +#define WIFI_RESCAN_MINUTES 5 // Number of minutes between wifi network rescan #endif const uint8_t WIFI_CONFIG_SEC = 180; // seconds before restart -const uint8_t WIFI_CHECK_SEC = 20; // seconds +// drop from 20 seconds to 5 seconds since we control the reconnections, not the Arduino SDK +const uint8_t WIFI_CHECK_SEC = 5; // seconds const uint8_t WIFI_RETRY_OFFSET_SEC = 20; // seconds #include // Wifi, MQTT, Ota, WifiManager @@ -49,7 +54,8 @@ struct WIFI { uint8_t config_counter = 0; uint8_t mdns_begun = 0; // mDNS active uint8_t scan_state; - uint8_t bssid[6]; + uint8_t bssid[6] = {0}; + uint8_t bssid_last[6] = {0}; // store the last connect bssid } Wifi; int WifiGetRssiAsQuality(int rssi) @@ -162,6 +168,7 @@ void WiFiSetSleepMode(void) void WifiBegin(uint8_t flag, uint8_t channel) { const char kWifiPhyMode[] = " BGN"; + char hex_char[18]; #ifdef USE_EMULATION UdpDisconnect(); @@ -183,6 +190,9 @@ void WifiBegin(uint8_t flag, uint8_t channel) // if (WiFi.getPhyMode() != WIFI_PHY_MODE_11G) { WiFi.setPhyMode(WIFI_PHY_MODE_11G); } // B/G if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } // WiFi.setAutoReconnect(true); + // handle the reconnection in WifiCheckIp() since the autoreconnect keeps sending deauthentication messages which causes the AP to block traffic as it looks like an DoS attack +// this needs to be explicitly called as "false" otherwise the default is enabled + WiFi.setAutoReconnect(false); switch (flag) { case 0: // AP1 case 1: // AP2 @@ -200,12 +210,15 @@ void WifiBegin(uint8_t flag, uint8_t channel) WiFi.hostname(my_hostname); if (channel) { WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid); + // add debug output to console to show connected BSSID and channel for multi-AP installations + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s Channel %d BSSId %s " D_IN_MODE " 11%c " D_AS " %s..."), + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':'),kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); } else { WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s " D_IN_MODE " 11%c " D_AS " %s..."), + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); - + #if LWIP_IPV6 for (bool configured = false; !configured;) { uint16_t cfgcnt = 0; @@ -259,6 +272,12 @@ void WifiBeginAfterScan(void) } // Scan done if (5 == Wifi.scan_state) { + uint32_t number_known = 0; // count the number of known AP's so we can clear the Wifi.bssid_last if there is only one + int32_t channel_max = 0; // No scan result + int8_t ap_max = 3; // AP default if not found + uint8_t bssid_max[6]; // Save last bssid + memcpy((void*) &bssid_max, (void*) &Wifi.bssid, sizeof(bssid_max)); // store the strongest bssid + int32_t channel = 0; // No scan result int8_t ap = 3; // AP default if not found uint8_t last_bssid[6]; // Save last bssid @@ -282,12 +301,25 @@ void WifiBeginAfterScan(void) for (j = 0; j < MAX_SSIDS; j++) { if (ssid_scan == SettingsText(SET_STASSID1 + j)) { // SSID match known = true; + number_known++; if (rssi_scan > best_network_db) { // Best network if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { // Check for passphrase if not open wlan - best_network_db = (int8_t)rssi_scan; - channel = chan_scan; - ap = j; // AP1 or AP2 - memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); + // store the max values in case there is only one AP and we need to try to reconnect + memcpy((void*) &bssid_max, (void*) bssid_scan, sizeof(bssid_max)); + channel_max = chan_scan; + ap_max = j; + // if the bssid is not the same as the last failed attempt, force picking the next strongest AP to prevent getting stuck on a strong RSSI, but poor channel health + for (uint32_t i = 0; i < sizeof(Wifi.bssid_last); i++) { + if (bssid_scan[i] != Wifi.bssid_last[i]) { + best_network_db = (int8_t)rssi_scan; + channel = chan_scan; + ap = j; // AP1 or AP2 + memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); + // save the last bssid used + memcpy((void*) &Wifi.bssid_last, (void*) bssid_scan, sizeof(Wifi.bssid_last)); + break; + } + } } } break; @@ -307,6 +339,16 @@ void WifiBeginAfterScan(void) WiFi.scanDelete(); // Clean up Ram delay(0); } + + // reset the last bssid if there is only one AP to allow the reconnect of the same AP on the next cycle + if (number_known == 1) { + // clear the last value + memset((void*) &Wifi.bssid_last, 0, sizeof(Wifi.bssid_last)); + memcpy((void*) &Wifi.bssid, (void*) bssid_max, sizeof(Wifi.bssid)); + channel = channel_max; + ap = ap_max; + } + Wifi.scan_state = 0; // If bssid changed then (re)connect wifi for (uint32_t i = 0; i < sizeof(Wifi.bssid); i++) { @@ -381,17 +423,11 @@ void WifiCheckIp(void) #else if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { #endif // LWIP_IPV6=1 + // initialize the last connect bssid since we had a successful connection + memset((void*) &Wifi.bssid_last, 0, sizeof(Wifi.bssid_last)); WifiSetState(1); Wifi.counter = WIFI_CHECK_SEC; Wifi.retry = Wifi.retry_init; - AddLog_P((Wifi.status != WL_CONNECTED) ? LOG_LEVEL_INFO : LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CONNECTED)); - if (Wifi.status != WL_CONNECTED) { -// AddLog_P(LOG_LEVEL_INFO, PSTR("Wifi: Set IP addresses")); - Settings.ip_address[1] = (uint32_t)WiFi.gatewayIP(); - Settings.ip_address[2] = (uint32_t)WiFi.subnetMask(); - Settings.ip_address[3] = (uint32_t)WiFi.dnsIP(); - } - Wifi.status = WL_CONNECTED; #ifdef USE_DISCOVERY #ifdef WEBSERVER_ADVERTISE if (2 == Wifi.mdns_begun) { @@ -407,32 +443,18 @@ void WifiCheckIp(void) switch (Wifi.status) { case WL_CONNECTED: AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_NO_IP_ADDRESS)); - Wifi.status = 0; - Wifi.retry = Wifi.retry_init; + // if poor channel health prevents DHCP broadcast from succeeding, restart the request + // The code will eventually do a recoonect when the 1/2 interval is hit to try another access point if this remains unsuccessful + wifi_station_dhcpc_start(); break; case WL_NO_SSID_AVAIL: AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_NOT_REACHED)); - if (WIFI_WAIT == Settings.sta_config) { - Wifi.retry = Wifi.retry_init; - } else { - if (Wifi.retry > (Wifi.retry_init / 2)) { - Wifi.retry = Wifi.retry_init / 2; - } - else if (Wifi.retry) { - Wifi.retry = 0; - } - } break; case WL_CONNECT_FAILED: AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_WRONG_PASSWORD)); - if (Wifi.retry > (Wifi.retry_init / 2)) { - Wifi.retry = Wifi.retry_init / 2; - } - else if (Wifi.retry) { - Wifi.retry = 0; - } break; default: // WL_IDLE_STATUS and WL_DISCONNECTED + // log on the 1/2 or full interval if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); } else { @@ -444,9 +466,11 @@ void WifiCheckIp(void) } } } + if (Wifi.retry) { if (Settings.flag3.use_wifi_scan) { // SetOption56 - Scan wifi network at restart for configured AP's - if (Wifi.retry_init == Wifi.retry) { + // check the 1/2 interval as well when rescanning - scan state machine takes 4 seconds + if ((Wifi.retry_init == Wifi.retry) || ((Wifi.retry_init / 2) == Wifi.retry)){ Wifi.scan_state = 1; // Select scanned SSID } } else { @@ -593,7 +617,6 @@ String WifiGetOutputPower(void) dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1); return String(stemp1); } - void WifiSetOutputPower(void) { WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); @@ -605,7 +628,9 @@ void WifiConnect(void) WifiSetOutputPower(); WiFi.persistent(false); // Solve possible wifi init errors Wifi.status = 0; - Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); + // lower the rety times now Tasmota control the reconnections, not the Arduino SDK + // Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); + Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + (ESP.getChipId() & 0xF); Wifi.retry = Wifi.retry_init; Wifi.counter = 1; } From a935dda9ac6a78ff694929fb780aa87f171f1cd0 Mon Sep 17 00:00:00 2001 From: jay-wilkinson <49291581+jay-wilkinson@users.noreply.github.com> Date: Sat, 25 Jan 2020 21:15:56 -0600 Subject: [PATCH 088/160] Update BUILDS.md If you read enough issues you can finally find a vague reference to "Enable ALL protocols" and tasmota-ir but not in the same issue. Wasted a day on this. Looks like many others have too. --- BUILDS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILDS.md b/BUILDS.md index 5cac6108f..aa1834061 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -128,6 +128,7 @@ | | | | | | | | | | USE_IR_REMOTE | - | - | x | x | x | x | x | | USE_IR_RECEIVE | - | - | x | x | x | x | x | +| USE_IR_REMOTE_FULL | - | - | - | - | - | x | - | Enable ALL protocols | | | | | | | | | | USE_SR04 | - | - | x | x | x | - | x | | USE_TM1638 | - | - | - | - | x | - | - | From 5b0259e7c3bc00b5b02bd5644074e91a1fd50460 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 26 Jan 2020 14:16:44 +0100 Subject: [PATCH 089/160] Keep legacy support --- tasmota/settings.ino | 4 ++++ tasmota/xdrv_02_mqtt.ino | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 363ebbd9f..33da93562 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -700,7 +700,11 @@ void EspErase(uint32_t start_sector, uint32_t end_sector) // bool result = EsptoolEraseSector(sector); // Esptool - erases flash completely (slow) if (serial_output) { +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 + Serial.printf(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n", sector, (result) ? D_OK : D_ERROR); +#else Serial.printf_P(PSTR(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n"), sector, (result) ? D_OK : D_ERROR); +#endif delay(10); } else { yield(); diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 529b3ce3c..05072d5c7 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -1118,8 +1118,12 @@ void CmndTlsDump(void) { uint32_t start = (uint32_t)tls_spi_start + tls_block_offset; uint32_t end = start + tls_block_len -1; for (uint32_t pos = start; pos < end; pos += 0x10) { - uint32_t* values = (uint32_t*)(pos); - Serial.printf_P(PSTR("%08x: %08x %08x %08x %08x\n"), pos, bswap32(values[0]), bswap32(values[1]), bswap32(values[2]), bswap32(values[3])); + uint32_t* values = (uint32_t*)(pos); +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 + Serial.printf("%08x: %08x %08x %08x %08x\n", pos, bswap32(values[0]), bswap32(values[1]), bswap32(values[2]), bswap32(values[3])); +#else + Serial.printf_P(PSTR("%08x: %08x %08x %08x %08x\n"), pos, bswap32(values[0]), bswap32(values[1]), bswap32(values[2]), bswap32(values[3])); +#endif } } #endif // DEBUG_DUMP_TLS From ff01f934e28d117a626310dd2297111a3e5eaec7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 26 Jan 2020 14:20:40 +0100 Subject: [PATCH 090/160] Bump version 8.1.0.5 --- RELEASENOTES.md | 3 ++- tasmota/CHANGELOG.md | 6 +++++- tasmota/tasmota_version.h | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ef8df5f8d..de6a1930b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,11 +52,12 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.1.0.4 +### Version 8.1.0.5 - Change Lights: simplified gamma correction and 10 bits internal computation - Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items - Change IRremoteESP8266 library updated to v2.7.2 +- Change Zigbee command prefix from ``Zigbee*`` to ``Zb*`` - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Fix ``White`` added to light status (#7142) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index a28cf36b4..49fecc225 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,7 +1,12 @@ ## Unreleased (development) +### 8.1.0.5 20200126 + +- Bump version + ### 8.1.0.4 20200116 +- Change Zigbee command prefix from ``Zigbee*`` to ``Zb*`` - Fix ``PowerDelta`` zero power detection (#7515) - Fix OTA minimal gzipped detection regression from 8.1.0.3 - Fix ``RGBWWTable`` ignored (#7572) @@ -11,7 +16,6 @@ - Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) - Add optional parameter to command ``Scheme , `` to control initial start color - Add rule trigger on one level deeper using syntax with two ``#`` like ``on zigbeereceived#vibration_sensor#aqaracubeside=0 do ...`` -- Change Zigbee commands renamed to ``Zb*`` ### 8.1.0.3 20200106 diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 1539def62..e38f4cad0 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08010004; +const uint32_t VERSION = 0x08010005; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; From 3d00c4f0930d65e2b8ec25454ed44553810b21d5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 26 Jan 2020 14:30:11 +0100 Subject: [PATCH 091/160] Change wifi connectivity stability Change wifi connectivity stability (#7602) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 2 +- tasmota/support_wifi.ino | 11 +++++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index de6a1930b..10e9a8139 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -58,6 +58,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items - Change IRremoteESP8266 library updated to v2.7.2 - Change Zigbee command prefix from ``Zigbee*`` to ``Zb*`` +- Change wifi connectivity stability (#7602) - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Fix ``White`` added to light status (#7142) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 49fecc225..edf6108e0 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,7 +2,7 @@ ### 8.1.0.5 20200126 -- Bump version +- Change wifi connectivity stability (#7602) ### 8.1.0.4 20200116 diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 1dab28ff1..5053d89ce 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -211,14 +211,17 @@ void WifiBegin(uint8_t flag, uint8_t channel) if (channel) { WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid); // add debug output to console to show connected BSSID and channel for multi-AP installations - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s Channel %d BSSId %s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':'),kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s Channel %d BSSId %s " D_IN_MODE " 11%c " D_AS " %s..."), + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), + channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':'), + kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); } else { WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), + kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); } - + #if LWIP_IPV6 for (bool configured = false; !configured;) { uint16_t cfgcnt = 0; From 9efe67127d796fadb1e7961c8898b93faf67c8c7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 26 Jan 2020 15:52:26 +0100 Subject: [PATCH 092/160] Refactor wifi code --- tasmota/support_wifi.ino | 46 ++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 5053d89ce..2a3951147 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -22,18 +22,16 @@ \*********************************************************************************************/ #ifndef WIFI_RSSI_THRESHOLD -// decrease the roam threshold to address devices connecting at very low RSSI and being close to inoperative -//#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network +// Decrease the roam threshold from 10 to 5 to address devices connecting at very low RSSI and being close to inoperative #define WIFI_RSSI_THRESHOLD 5 // Difference in dB between current network and scanned network #endif #ifndef WIFI_RESCAN_MINUTES -// increase rescan interval to 5 minutes to improve ability for devices to reach network harmony -//#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan -#define WIFI_RESCAN_MINUTES 5 // Number of minutes between wifi network rescan +// Increase rescan interval from 44 to 5 minutes to improve ability for devices to reach network harmony +#define WIFI_RESCAN_MINUTES 5 // Number of minutes between wifi network rescan #endif const uint8_t WIFI_CONFIG_SEC = 180; // seconds before restart -// drop from 20 seconds to 5 seconds since we control the reconnections, not the Arduino SDK +// Drop from 20 seconds to 5 seconds since we control the reconnections, not the Arduino SDK const uint8_t WIFI_CHECK_SEC = 5; // seconds const uint8_t WIFI_RETRY_OFFSET_SEC = 20; // seconds @@ -56,6 +54,7 @@ struct WIFI { uint8_t scan_state; uint8_t bssid[6] = {0}; uint8_t bssid_last[6] = {0}; // store the last connect bssid + int8_t best_network_db; } Wifi; int WifiGetRssiAsQuality(int rssi) @@ -168,7 +167,6 @@ void WiFiSetSleepMode(void) void WifiBegin(uint8_t flag, uint8_t channel) { const char kWifiPhyMode[] = " BGN"; - char hex_char[18]; #ifdef USE_EMULATION UdpDisconnect(); @@ -189,9 +187,8 @@ void WifiBegin(uint8_t flag, uint8_t channel) // if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } // B/G/N // if (WiFi.getPhyMode() != WIFI_PHY_MODE_11G) { WiFi.setPhyMode(WIFI_PHY_MODE_11G); } // B/G if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } -// WiFi.setAutoReconnect(true); - // handle the reconnection in WifiCheckIp() since the autoreconnect keeps sending deauthentication messages which causes the AP to block traffic as it looks like an DoS attack -// this needs to be explicitly called as "false" otherwise the default is enabled + // Handle the reconnection in WifiCheckIp() since the autoreconnect keeps sending deauthentication messages which causes the AP to block traffic as it looks like an DoS attack + // This needs to be explicitly called as "false" otherwise the default is enabled WiFi.setAutoReconnect(false); switch (flag) { case 0: // AP1 @@ -208,19 +205,18 @@ void WifiBegin(uint8_t flag, uint8_t channel) WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); // Set static IP } WiFi.hostname(my_hostname); + + char stemp[40] = { 0 }; if (channel) { WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid); - // add debug output to console to show connected BSSID and channel for multi-AP installations - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s Channel %d BSSId %s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), - channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':'), - kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); + // Add connected BSSID and channel for multi-AP installations + char hex_char[18]; + snprintf_P(stemp, sizeof(stemp), PSTR(" Channel %d BSSId %s"), channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':')); } else { WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), - kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " 11%c " D_AS " %s..."), + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); #if LWIP_IPV6 for (bool configured = false; !configured;) { @@ -239,22 +235,22 @@ void WifiBegin(uint8_t flag, uint8_t channel) void WifiBeginAfterScan(void) { - static int8_t best_network_db; - // Not active if (0 == Wifi.scan_state) { return; } // Init scan when not connected if (1 == Wifi.scan_state) { memset((void*) &Wifi.bssid, 0, sizeof(Wifi.bssid)); - best_network_db = -127; + Wifi.best_network_db = -127; Wifi.scan_state = 3; } // Init scan when connected if (2 == Wifi.scan_state) { uint8_t* bssid = WiFi.BSSID(); // Get current bssid memcpy((void*) &Wifi.bssid, (void*) bssid, sizeof(Wifi.bssid)); - best_network_db = WiFi.RSSI(); // Get current rssi and add threshold - if (best_network_db < -WIFI_RSSI_THRESHOLD) { best_network_db += WIFI_RSSI_THRESHOLD; } + Wifi.best_network_db = WiFi.RSSI(); // Get current rssi and add threshold + if (Wifi.best_network_db < -WIFI_RSSI_THRESHOLD) { + Wifi.best_network_db += WIFI_RSSI_THRESHOLD; + } Wifi.scan_state = 3; } // Init scan @@ -305,7 +301,7 @@ void WifiBeginAfterScan(void) if (ssid_scan == SettingsText(SET_STASSID1 + j)) { // SSID match known = true; number_known++; - if (rssi_scan > best_network_db) { // Best network + if (rssi_scan > Wifi.best_network_db) { // Best network if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { // Check for passphrase if not open wlan // store the max values in case there is only one AP and we need to try to reconnect memcpy((void*) &bssid_max, (void*) bssid_scan, sizeof(bssid_max)); @@ -314,7 +310,7 @@ void WifiBeginAfterScan(void) // if the bssid is not the same as the last failed attempt, force picking the next strongest AP to prevent getting stuck on a strong RSSI, but poor channel health for (uint32_t i = 0; i < sizeof(Wifi.bssid_last); i++) { if (bssid_scan[i] != Wifi.bssid_last[i]) { - best_network_db = (int8_t)rssi_scan; + Wifi.best_network_db = (int8_t)rssi_scan; channel = chan_scan; ap = j; // AP1 or AP2 memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); From fab03d817356e710fb8de119a76e2cdb9f5d1695 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 26 Jan 2020 23:08:52 +0100 Subject: [PATCH 093/160] Add ``SetOption84 1`` sends AWS IoT device shadow updates (alternative to retained) --- tasmota/CHANGELOG.md | 1 + tasmota/settings.h | 4 ++-- tasmota/xdrv_02_mqtt.ino | 32 +++++++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index edf6108e0..b5036467c 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.1.0.5 20200126 - Change wifi connectivity stability (#7602) +- Add ``SetOption84 1`` sends AWS IoT device shadow updates (alternative to retained) ### 8.1.0.4 20200116 diff --git a/tasmota/settings.h b/tasmota/settings.h index dba74eb7d..cef401a94 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -102,8 +102,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t data; // Allow bit manipulation using SetOption struct { // SetOption82 .. SetOption113 uint32_t alexa_ct_range : 1; // bit 0 (v8.1.0.2) - SetOption82 - Reduced CT range for Alexa - uint32_t zigbee_use_names : 1; // bit 1 (V8.1.0.4) - SetOption83 - Use FriendlyNames instead of ShortAddresses when possible - uint32_t spare02 : 1; + uint32_t zigbee_use_names : 1; // bit 1 (v8.1.0.4) - SetOption83 - Use FriendlyNames instead of ShortAddresses when possible + uint32_t awsiot_shadow : 1; // bit 2 (v8.1.0.5) - SetOption84 - (AWS IoT) publish MQTT state to a device shadow uint32_t spare03 : 1; uint32_t spare04 : 1; uint32_t spare05 : 1; diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 05072d5c7..55b63c4de 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -362,7 +362,7 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retain * prefix 5 = stat using subtopic or RESULT * prefix 6 = tele using subtopic or RESULT */ - char romram[33]; + char romram[64]; char stopic[TOPSZ]; snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings.flag.mqtt_response) ? S_RSLT_RESULT : subtopic); // SetOption4 - Switch between MQTT RESULT or COMMAND @@ -372,6 +372,36 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retain prefix &= 3; GetTopic_P(stopic, prefix, mqtt_topic, romram); MqttPublish(stopic, retained); + +#ifdef USE_MQTT_AWS_IOT + if ((prefix > 0) && (Settings.flag4.awsiot_shadow)) { // placeholder for SetOptionXX + // compute the target topic + char *topic = SettingsText(SET_MQTT_TOPIC); + char topic2[strlen(topic)+1]; // save buffer onto stack + strcpy(topic2, topic); + // replace any '/' with '_' + char *s = topic2; + while (*s) { + if ('/' == *s) { + *s = '_'; + } + s++; + } + // update topic is "$aws/things//shadow/update" + snprintf_P(romram, sizeof(romram), PSTR("$aws/things/%s/shadow/update"), topic2); + + // copy buffer + char *mqtt_save = (char*) malloc(strlen(mqtt_data)+1); + if (!mqtt_save) { return; } // abort + strcpy(mqtt_save, mqtt_data); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"state\":{\"reported\":%s}}"), mqtt_save); + free(mqtt_save); + + bool result = MqttClient.publish(romram, mqtt_data, false); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Updated shadow: %s"), romram); + yield(); // #3313 + } +#endif // USE_MQTT_AWS_IOT } void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic) From 0d03c1682e3973879868793f2ad3891d5d4d5eb5 Mon Sep 17 00:00:00 2001 From: to-scho Date: Mon, 27 Jan 2020 09:46:39 +0100 Subject: [PATCH 094/160] fix position wrap around when shutterendstoptime is enabled --- tasmota/xdrv_27_shutter.ino | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index e112416b1..fa3cce4e7 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -102,6 +102,8 @@ void ShutterRtc50mS(void) int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) { + if (0 == percent) return 0; + if (100 == percent) return Shutter.open_max[index]; if (Settings.shutter_set50percent[index] != 50) { return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; } else { @@ -136,6 +138,8 @@ int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) { + if (0 >= realpos) return 0; + if (Shutter.open_max[index] <= realpos) return 100; if (Settings.shutter_set50percent[index] != 50) { return (Settings.shuttercoeff[2][index] * 5 > realpos) ? SHT_DIV_ROUND(realpos, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos-Settings.shuttercoeff[0][index], Settings.shuttercoeff[1][index]); } else { @@ -774,18 +778,16 @@ void CmndShutterPosition(void) target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; if (XdrvMailbox.payload != -99) { //target_pos_percent = (Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent; - if (0 == target_pos_percent) { - Shutter.target_position[index] = (Settings.shutter_options[index] & 4) ? (-1 * 2000) : 0; - } else if (100 == target_pos_percent) { - Shutter.target_position[index] = (Settings.shutter_options[index] & 4) ? (Shutter.open_max[index] + 1 * 2000) : Shutter.open_max[index]; - } else { - Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); - } + Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); Shutter.accelerator[index] = Shutter.max_pwm_frequency / ((Shutter.motordelay[index] > 0) ? Shutter.motordelay[index] : 1); //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); } if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) { + if (Settings.shutter_options[index] & 4) { + if (0 == target_pos_percent) Shutter.target_position[index] -= 1 * 2000; + if (100 == target_pos_percent) Shutter.target_position[index] += 1 * 2000; + } int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1; if (Shutter.direction[index] == -new_shutterdirection) { // direction need to be changed. on momentary switches first stop the Shutter @@ -806,26 +808,32 @@ void CmndShutterPosition(void) ShutterWaitForMotorStop(index); ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); - // Code for shutters with circuit safe configuration, switch the direction Relay - ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); - // power on - ExecuteCommandPower(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); + if (Shutter.skip_relay_change == 0) { + // Code for shutters with circuit safe configuration, switch the direction Relay + ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); + // power on + ExecuteCommandPower(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); + } } else { // now start the motor for the right direction, work for momentary and normal shutters. AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start in dir %d"), Shutter.direction[index]); ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); - ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); + if (Shutter.skip_relay_change == 0) { + ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); + } //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay6 5s, xdrv %d"), XdrvMailbox.payload); } Shutter.switched_relay = 0; } } else { target_pos_percent = ShutterRealToPercentPosition(Shutter.real_position[index], index); + ShutterReportPosition(true); } XdrvMailbox.index = index +1; // Fix random index for ShutterClose if (XdrvMailbox.command) ResponseCmndIdxNumber((Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent); } else { + ShutterReportPosition(true); if (XdrvMailbox.command) ResponseCmndIdxChar("Locked"); } From 11b13f73b0e026b4a3b0c8e27478368cb204d343 Mon Sep 17 00:00:00 2001 From: to-scho Date: Mon, 27 Jan 2020 11:05:11 +0100 Subject: [PATCH 095/160] fix shutterposition call w/o arguments after boot --- tasmota/xdrv_27_shutter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index fa3cce4e7..0a226c2ea 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -233,7 +233,7 @@ void ShutterInit(void) Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i); //Shutter.real_position[i] = Settings.shutter_position[i] <= 5 ? Settings.shuttercoeff[2][i] * Settings.shutter_position[i] : Settings.shuttercoeff[1][i] * Settings.shutter_position[i] + Settings.shuttercoeff[0,i]; - Shutter.start_position[i] = Shutter.real_position[i]; + Shutter.start_position[i] = Shutter.target_position[i] = Shutter.real_position[i]; Shutter.motordelay[i] = Settings.shutter_motordelay[i]; char shutter_open_chr[10]; From 42461aaaf36952be9d910783ed935d9fb5e6268e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 27 Jan 2020 17:38:32 +0100 Subject: [PATCH 096/160] Fix command Publish payload handling --- tasmota/xdrv_02_mqtt.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 55b63c4de..4d574a9f1 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -389,7 +389,7 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retain } // update topic is "$aws/things//shadow/update" snprintf_P(romram, sizeof(romram), PSTR("$aws/things/%s/shadow/update"), topic2); - + // copy buffer char *mqtt_save = (char*) malloc(strlen(mqtt_data)+1); if (!mqtt_save) { return; } // abort @@ -852,13 +852,13 @@ void CmndPrefix(void) void CmndPublish(void) { if (XdrvMailbox.data_len > 0) { - char *mqtt_part = strtok(XdrvMailbox.data, " "); + char *payload_part; + char *mqtt_part = strtok_r(XdrvMailbox.data, " ", &payload_part); if (mqtt_part) { char stemp1[TOPSZ]; strlcpy(stemp1, mqtt_part, sizeof(stemp1)); - mqtt_part = strtok(nullptr, " "); - if (mqtt_part) { - strlcpy(mqtt_data, mqtt_part, sizeof(mqtt_data)); + if ((payload_part != nullptr) && strlen(payload_part)) { + strlcpy(mqtt_data, payload_part, sizeof(mqtt_data)); } else { mqtt_data[0] = '\0'; } From 72935bdcc644152dc10ef0710f2a7a3600afee8c Mon Sep 17 00:00:00 2001 From: to-scho Date: Tue, 28 Jan 2020 11:22:36 +0100 Subject: [PATCH 097/160] Buzzer extensions Add infinite mode (count==-1), add follow led mode (count==-2), add count>1 for tune playback --- tasmota/support_tasmota.ino | 6 +++++ tasmota/xdrv_24_buzzer.ino | 54 ++++++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 9095a09bf..c69647b18 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -347,6 +347,9 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) } DigitalWrite(GPIO_LED1 + led, bitRead(led_inverted, led) ? !state : state); } + #ifdef USE_BUZZER + if (led == 0) { BuzzerSetStateToLed(state); } + #endif // USE_BUZZER } void SetLedPower(uint32_t state) @@ -382,6 +385,9 @@ void SetLedLink(uint32_t state) if (state) { state = 1; } digitalWrite(led_pin, (led_inv) ? !state : state); } + #ifdef USE_BUZZER + BuzzerSetStateToLed(state); + #endif // USE_BUZZER } void SetPulseTimer(uint32_t index, uint32_t time) diff --git a/tasmota/xdrv_24_buzzer.ino b/tasmota/xdrv_24_buzzer.ino index 78246f0f6..40af3128c 100644 --- a/tasmota/xdrv_24_buzzer.ino +++ b/tasmota/xdrv_24_buzzer.ino @@ -26,10 +26,12 @@ struct BUZZER { uint32_t tune = 0; + uint32_t tune_reload = 0; bool active = true; bool enable = false; uint8_t inverted = 0; // Buzzer inverted flag (1 = (0 = On, 1 = Off)) uint8_t count = 0; // Number of buzzes + uint8_t mode = 0; // Buzzer mode (0 = (0 = regular, 2 = infinite, 3 = follow LED)) uint8_t set[2]; uint8_t duration; uint8_t state = 0; @@ -42,13 +44,15 @@ void BuzzerOff(void) DigitalWrite(GPIO_BUZZER, Buzzer.inverted); // Buzzer Off } -//void BuzzerBeep(uint32_t count = 1, uint32_t on = 1, uint32_t off = 1, uint32_t tune = 0); -void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune) +//void BuzzerBeep(uint32_t count = 1, uint32_t on = 1, uint32_t off = 1, uint32_t tune = 0, uint32_t mode = 0); +void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode) { Buzzer.set[0] = off; // off duration in 100 mSec steps Buzzer.set[1] = on; // on duration in 100 mSec steps Buzzer.duration = 1; // Start buzzer on first step - Buzzer.tune = 0; + Buzzer.tune_reload = 0; + Buzzer.mode = mode; + if (tune) { uint32_t tune1 = tune; uint32_t tune2 = tune; @@ -56,15 +60,14 @@ void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune) if (!(tune2 & 0x80000000)) { tune2 <<= 1; // Skip leading silence } else { - Buzzer.tune <<= 1; // Add swapped tune - Buzzer.tune |= tune1 & 1; + Buzzer.tune_reload <<= 1; // Add swapped tune + Buzzer.tune_reload |= tune1 & 1; tune1 >>= 1; } } - Buzzer.count = 1; // Allow tune only once - } else { - Buzzer.count = count * 2; // Start buzzer + Buzzer.tune = Buzzer.tune_reload; } + Buzzer.count = count * 2; // Start buzzer AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X)"), count, Buzzer.count, on, off, tune, Buzzer.tune); @@ -74,14 +77,21 @@ void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune) } } +void BuzzerSetStateToLed(uint32_t state) { + if ((Buzzer.enable) && (Buzzer.mode==2)) { + Buzzer.state = (state!=0); + DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); + } +} + void BuzzerBeep(uint32_t count) { - BuzzerBeep(count, 1, 1, 0); + BuzzerBeep(count, 1, 1, 0, 0); } void BuzzerEnabledBeep(uint32_t count, uint32_t duration) { if (Settings.flag3.buzzer_enable) { // SetOption67 - Enable buzzer when available - BuzzerBeep(count, duration, 1, 0); + BuzzerBeep(count, duration, 1, 0, 0); } } @@ -109,7 +119,7 @@ void BuzzerInit(void) void BuzzerEvery100mSec(void) { - if (Buzzer.enable) { + if ((Buzzer.enable) && (Buzzer.mode != 2)) { if (Buzzer.count) { if (Buzzer.duration) { Buzzer.duration--; @@ -118,8 +128,10 @@ void BuzzerEvery100mSec(void) Buzzer.state = Buzzer.tune & 1; Buzzer.tune >>= 1; } else { - Buzzer.count--; + Buzzer.tune = Buzzer.tune_reload; + Buzzer.count-= (Buzzer.tune_reload) ? 2 : 1; Buzzer.state = Buzzer.count & 1; + if (Buzzer.mode) { Buzzer.count |= 2; } } Buzzer.duration = Buzzer.set[Buzzer.state]; } @@ -151,16 +163,20 @@ void CmndBuzzer(void) // Buzzer 2 = Beep twice with duration 200mS and pause 100mS // Buzzer 2,3 = Beep twice with duration 300mS and pause 100mS // Buzzer 2,3,4 = Beep twice with duration 300mS and pause 400mS - // Buzzer 2,3,4,0xF54 = Beep a sequence once indicated by 0xF54 = 1111 0101 01 with duration 300mS and pause 400mS + // Buzzer 2,3,4,0xF54 = Beep a sequence twice indicated by 0xF54 = 1111 0101 01 with duration 300mS and pause 400mS if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload > 0) { - uint32_t parm[4] = { 0 }; + if (XdrvMailbox.payload != 0) { + uint32_t parm[4] = { 0 }, mode = 0; ParseParameters(4, parm); - for (uint32_t i = 0; i < 3; i++) { - if (parm[i] < 1) { parm[i] = 1; } // Default Count, On time, Off time + if (XdrvMailbox.payload <= 0) { + parm[0] = 1; // Default Count + mode = -XdrvMailbox.payload; } - BuzzerBeep(parm[0], parm[1], parm[2], parm[3]); + for (uint32_t i = 1; i < 3; i++) { + if (parm[i] < 1) { parm[i] = 1; } // Default On time, Off time + } + BuzzerBeep(parm[0], parm[1], parm[2], parm[3], mode); } else { BuzzerBeep(0); } @@ -197,4 +213,4 @@ bool Xdrv24(uint8_t function) return result; } -#endif // USE_BUZZER \ No newline at end of file +#endif // USE_BUZZER From 7892bad81bb9a68993db21945ff9e5098a0efe9b Mon Sep 17 00:00:00 2001 From: RemiDing Date: Tue, 28 Jan 2020 15:10:23 +0100 Subject: [PATCH 098/160] toggle pressed and not_pressed --- tasmota/support_switch.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tasmota/support_switch.ino b/tasmota/support_switch.ino index 6df39c5d7..0cb88d05d 100644 --- a/tasmota/support_switch.ino +++ b/tasmota/support_switch.ino @@ -155,17 +155,17 @@ void SwitchHandler(uint8_t mode) switchflag = ~button &1; // Follow inverted wall switch state after hold break; case PUSHHOLDMULTI: - if (PRESSED == button){ + if (NOT_PRESSED == button){ Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; - SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT } else SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT break; case PUSHHOLDMULTI_INV: - if (NOT_PRESSED == button){ + if (PRESSED == button){ Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; - SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT } else SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT @@ -177,7 +177,7 @@ void SwitchHandler(uint8_t mode) } } -// enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEMULTI, FOLLOWMULTI, FOLLOWMULTI_INV, MAX_SWITCH_OPTION}; +// enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, TOGGLEMULTI, FOLLOWMULTI, FOLLOWMULTI_INV, PUSHHOLDMULTI, PUSHHOLDMULTI_INV, MAX_SWITCH_OPTION}; if (button != Switch.last_state[i]) { switch (Settings.switchmode[i]) { @@ -230,24 +230,24 @@ void SwitchHandler(uint8_t mode) } break; case PUSHHOLDMULTI: - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { + if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { if(Switch.hold_timer[i]!=0) SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; } - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { + if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { if(Switch.hold_timer[i] > loops_per_second * Settings.param[P_HOLD_TIME] / 25) switchflag = POWER_TOGGLE; // Toggle with pushbutton Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; } break; case PUSHHOLDMULTI_INV: - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { + if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { if(Switch.hold_timer[i]!=0) SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; } - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { + if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { if(Switch.hold_timer[i] > loops_per_second * Settings.param[P_HOLD_TIME] / 25) switchflag = POWER_TOGGLE; // Toggle with pushbutton Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; From deb8398d0bbb02dc6b097beab8cf67b0c4486f3a Mon Sep 17 00:00:00 2001 From: RemiDing Date: Tue, 28 Jan 2020 15:15:49 +0100 Subject: [PATCH 099/160] maybe needed --- tasmota/xdrv_10_rules.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 13287d009..c58fb10a6 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -563,7 +563,7 @@ void RulesEvery50ms(void) #else if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 - bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i]) || (FOLLOWMULTI_INV == Settings.switchmode[i])); + bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i]) || (FOLLOWMULTI_INV == Settings.switchmode[i]) || (PUSHHOLDMULTI_INV == Settings.switchmode[i])); snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (swm ^ SwitchLastState(i))); RulesProcessEvent(json_event); } From 5278a842529e3ef2870ffd7a86e4cfba63a10d28 Mon Sep 17 00:00:00 2001 From: RemiDing Date: Tue, 28 Jan 2020 15:37:18 +0100 Subject: [PATCH 100/160] POWER_INCREMENT added --- tasmota/tasmota.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index d12bb22ef..d39ea72a7 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -242,7 +242,7 @@ enum TopicOptions { CMND, STAT, TELE, nu1, RESULT_OR_CMND, RESULT_OR_STAT, RESUL enum ExecuteCommandPowerOptions { POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK, POWER_BLINK_STOP, POWER_OFF_NO_STATE = 8, POWER_ON_NO_STATE, POWER_TOGGLE_NO_STATE, POWER_SHOW_STATE = 16 }; -enum SendKeyPowerOptions { POWER_HOLD = 3, POWER_INV = 4, POWER_CLEAR = 5, CLEAR_RETAIN = 9 }; +enum SendKeyPowerOptions { POWER_HOLD = 3, POWER_INCREMENT = 4, POWER_INV = 5, POWER_CLEAR = 6, CLEAR_RETAIN = 9 }; enum SendKeyOptions { KEY_BUTTON, KEY_SWITCH }; enum PowerOnStateOptions { POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON }; From 07df4c1dfb4f1718cc3bea655e1f6ce4e137a2d2 Mon Sep 17 00:00:00 2001 From: Staars Date: Thu, 30 Jan 2020 08:39:28 +0100 Subject: [PATCH 101/160] start hm-10-driver --- tasmota/xsns_92_MI_HM10.ino | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tasmota/xsns_92_MI_HM10.ino diff --git a/tasmota/xsns_92_MI_HM10.ino b/tasmota/xsns_92_MI_HM10.ino new file mode 100644 index 000000000..6defdb76f --- /dev/null +++ b/tasmota/xsns_92_MI_HM10.ino @@ -0,0 +1,29 @@ +/* + xsns_92_Ml_BLE.ino - MI-BLE-sensors via HM-10 support for Tasmota + + Copyright (C) 2020 Christian Baars and Theo Arends + + 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 . + + + -------------------------------------------------------------------------------------------- + Version yyyymmdd Action Description + -------------------------------------------------------------------------------------------- + + --- + 0.9.0.0 20191127 started - further development by Christian Baars + base - no real base project + forked - from arendst/tasmota - https://github.com/arendst/Tasmota + +*/ From 15428f59e9004e71b34c35ca6719eba9acabb4c5 Mon Sep 17 00:00:00 2001 From: Staars Date: Thu, 30 Jan 2020 09:18:21 +0100 Subject: [PATCH 102/160] add some stuff from the mp3-driver --- tasmota/xsns_92_MI_HM10.ino | 229 +++++++++++++++++++++++++++++++++++- 1 file changed, 228 insertions(+), 1 deletion(-) diff --git a/tasmota/xsns_92_MI_HM10.ino b/tasmota/xsns_92_MI_HM10.ino index 6defdb76f..f86d434b6 100644 --- a/tasmota/xsns_92_MI_HM10.ino +++ b/tasmota/xsns_92_MI_HM10.ino @@ -22,8 +22,235 @@ -------------------------------------------------------------------------------------------- --- - 0.9.0.0 20191127 started - further development by Christian Baars + 0.9.0.0 20200130 started - further development by Christian Baars base - no real base project forked - from arendst/tasmota - https://github.com/arendst/Tasmota */ + +#define XSNS_92 92 + +#include + +TasmotaSerial *HM10Serial; + +#define HM10_MAX_TASK_NUMBER 12 +uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; // first value: kind of task - second value: delay in x * 100ms +uint8_t HM10_CURRENT_TASK_DELAY = 0; // number of 100ms-cycles +uint8_t HM10_LAST_COMMAND; // task command code + +uint16_t HM10_CURRENT_PAYLOAD = 0; // payload of a supported command + +#define HM10_MAX_RX_BUF 512 +char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; // make a buffer bigger than the usual 10-byte-message + + + + + +/*********************************************************************************************\ + * constants +\*********************************************************************************************/ + +#define D_CMND_HM10 "HM10" + +const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; +const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s\"}"; +const char kHM10_Commands[] PROGMEM = "Track|Play"; + +/*********************************************************************************************\ + * enumerations +\*********************************************************************************************/ + +enum HM10_Commands { + CMND_HM10_TRACK +}; + +/*********************************************************************************************\ + * command defines +\*********************************************************************************************/ + + + +/*********************************************************************************************\ + * Task codes defines +\*********************************************************************************************/ + +#define TASK_HM10_NOTASK 0 // nothing to be done +#define TASK_HM10_FEEDBACK 1 // check the feedback from the device +#define TASK_HM10_DONE 99 // used, if there was a task in the slot or just to wait + +/*********************************************************************************************\ + * Helper functions +\*********************************************************************************************/ + +void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay){ + HM10_TASK_LIST[slot][0] = task; + HM10_TASK_LIST[slot][1] = delay; + HM10_TASK_LIST[slot+1][0] = TASK_HM10_NOTASK; // the tasks must always be launched in ascending order!! + HM10_CURRENT_TASK_DELAY = HM10_TASK_LIST[0][1]; +} + +void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ + HM10_LAST_COMMAND = HM10_TASK_LIST[slot][0]; // save command + HM10_TASK_LIST[slot][0] = task; +} + +void HM10_Reset(void) { HM10_LAST_COMMAND = TASK_HM10_DONE; // task command code + HM10State.activeFolder = 0; // see the line above + HM10_Launchtask(TASK_HM10_DONE,0,10); // just wait for some time , equals delay(1000) -> 10 * 100 + HM10_Launchtask(TASK_HM10_RESET_DEVICE, 1,0); // reset Device + HM10_Launchtask(TASK_HM10_Q_VERSION, 2,10); // read SW Version at startup + } // ASAP + + +/*********************************************************************************************\ + * init serial + * define serial rx/tx port fixed with 115200 baud +\*********************************************************************************************/ + +void HM10SerialInit(void) { + HM10Serial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 1, 0, HM10_MAX_RX_BUF); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sstart serial communication fixed to 115200 baud"),S_CONTROL_HM10); + if (HM10Serial->begin(115200)) { + if (UBXSerial->hardwareSerial()) { + ClaimSerial(); + DEBUG_SENSOR_LOG(PSTR("HM10: claim HW")); + } + HM10_Reset(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK_LIST initialized, now return to main loop"),S_CONTROL_HM10); + } + return; +} + +/*********************************************************************************************\ + * create the HM10 commands payload, and send it via serial interface to the HM10 player + \*********************************************************************************************/ + +void HM10_CMD(uint8_t _cmd,uint16_t _val) { + + HM10Serial->write(cmd, sizeof(cmd)); / + return; +} + +/*********************************************************************************************\ + * handle the return value from the HM10 +\*********************************************************************************************/ + +bool HM10SerialHandleFeedback(){ + bool success = true; // true disables possible repetition of commands, set to false only for debugging + uint8_t i = 0; + uint8_t ret[HM10_MAX_RX_BUF] = {0}; // reset array with zeros + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%swaiting for response"),S_CONTROL_HM10); + bool receive_data_message = false; // special response with the format d,a, ...,a,d + + while(HM10Serial->available()) { + // delay(0); + if(iread(); + } + i++; + } + return success; +} + +/*********************************************************************************************\ + * execute the next Task +\*********************************************************************************************/ + +void HM10_TaskEvery100ms(){ + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK to be done %u"),S_CONTROL_HM10,HM10_TASK_LIST[0][0]); + if (HM10_CURRENT_TASK_DELAY == 0) { + uint8_t i = 0; + bool runningTaskLoop = true; + while (runningTaskLoop) { // always iterate through the whole task list + switch(HM10_TASK_LIST[i][0]) { // handle the kind of task + case TASK_HM10_FEEDBACK: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s%sFeedback"),S_CONTROL_HM10,S_TASK_HM10); + if(HM10_RETRIES>0) { + if (HM10SerialHandleFeedback()) { + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // mark slot as handled if successful + HM10_CURRENT_TASK_DELAY = HM10_TASK_LIST[i+1][1]; // assign the delay of the next slot to the current global delay + } + else { + HM10_TASK_LIST[i][0] = HM10_LAST_COMMAND; // reinsert unsuccessful task into the current slot + HM10_CURRENT_TASK_DELAY++; + HM10_RETRIES--; + } + } + else { + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // mark slot as handled even if not successful + HM10_CURRENT_TASK_DELAY = HM10_TASK_LIST[i+1][1]; // assign the delay of the next slot to the current global delay + HM10_RETRIES = 3; + } + runningTaskLoop = false; // return to main loop + break; + case TASK_HM10_PLAY: + HM10_CMD(HM10_CMD_PLAY, 0); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s%sPlay"),S_CONTROL_HM10,S_TASK_HM10); + HM10State.PlayMode = 1; + HM10_TaskReplaceInSlot(TASK_HM10_Q_TRACK,i); + runningTaskLoop = false; + break; + + case TASK_HM10_RESET_DEVICE: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s%sReset Device"),S_CONTROL_HM10,S_TASK_HM10); + HM10_CMD(HM10_CMD_RESET, HM10_CMD_RESET_VALUE); + HM10_CURRENT_TASK_DELAY = HM10_TASK_LIST[i+1][1]; // set task delay + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset + runningTaskLoop = false; // return to main loop + break; + + case TASK_HM10_DONE: // this entry was already handled + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sFound done HM10_TASK"),S_CONTROL_HM10); + if(HM10_TASK_LIST[i+1][0] == TASK_HM10_NOTASK) { // check the next entry and if there is none + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s%sno Tasks left"),S_CONTROL_HM10,S_TASK_HM10); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK_DONE current slot %u"),S_CONTROL_HM10, i); + for (uint8_t j = 0; j < HM10_MAX_TASK_NUMBER+1; j++) { // do a clean-up: + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK cleanup slot %u"),S_CONTROL_HM10, j); + HM10_TASK_LIST[j][0] = TASK_HM10_NOTASK; // reset all task entries + HM10_TASK_LIST[j][1] = 0; // reset all delays + } + runningTaskLoop = false; // return to main loop + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sUpdate GUI via AJAX"),S_CONTROL_HM10); + // HM10_GUI_NEEDS_UPDATE = true; + break; + } + } + i++; + } + } + else { + HM10_CURRENT_TASK_DELAY--; // count down every 100 ms + } +} + + + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv92(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_RXD] < 99) && (pin[GPIO_TXD] < 99)) { + switch (function) { + case FUNC_PRE_INIT: + HM10SerialInit(); // init and start communication + break; + case FUNC_EVERY_100_MSECOND: + if (HM10_TASK_LIST[0][0] == TASK_HM10_NOTASK) { // no task running + HM10SerialHandleFeedback(); // -> sniff for device feedback + break; + } + else { + HM10_TaskEvery100ms(); // something has to be done, we'll check in the next step + break; + } + } + } + return result; +} + From c6a2854a6ec1925cee7a93fa4bfdf0d0bd2a9f98 Mon Sep 17 00:00:00 2001 From: to-scho Date: Thu, 30 Jan 2020 14:33:33 +0100 Subject: [PATCH 103/160] simultaneous shutter button press per shutter detect simultaneous press per shutter and not for whole module --- tasmota/xdrv_27_shutter.ino | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 0a226c2ea..c353a1dd4 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -513,11 +513,11 @@ void ShutterRelayChanged(void) } } -bool ShutterButtonIsSimultaneousHold(uint32_t button_index) { +bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) { // check for simultaneous shutter button hold uint32 min_shutterbutton_hold_timer = -1; for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((Settings.shutter_button[i] & (1<<31)) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) min_shutterbutton_hold_timer = Button.hold_timer[i]; } return (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1)); @@ -562,10 +562,10 @@ void ShutterButtonHandler(void) } if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10)) { // press still valid && SetOption32 (40) - Button hold // check for simultaneous shutter button hold - if (ShutterButtonIsSimultaneousHold(button_index)) { + if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { // simultaneous shutter button hold detected for (uint32_t i = 0; i < MAX_KEYS; i++) - if (Settings.shutter_button[i] & (1<<31)) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings press_index = 0; buttonState = SHT_PRESSED_HOLD_SIMULTANEOUS; @@ -578,7 +578,7 @@ void ShutterButtonHandler(void) } if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer // check for simultaneous shutter button extend hold - if (ShutterButtonIsSimultaneousHold(button_index)) { + if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { // simultaneous shutter button extend hold detected press_index = 0; buttonState = SHT_PRESSED_EXT_HOLD_SIMULTANEOUS; @@ -596,14 +596,14 @@ void ShutterButtonHandler(void) // check for simultaneous shutter button press uint32 min_shutterbutton_press_counter = -1; for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((Settings.shutter_button[i] & (1<<31)) && (Button.press_counter[i] < min_shutterbutton_press_counter)) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) min_shutterbutton_press_counter = Button.press_counter[i]; } if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { // simultaneous shutter button press detected press_index = Button.press_counter[button_index]; for (uint32_t i = 0; i < MAX_KEYS; i++) - if (Settings.shutter_button[i] & (1<<31)) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS; } From b9e38153587e2e0adbf182d93bc323a8bc354572 Mon Sep 17 00:00:00 2001 From: Staars Date: Fri, 31 Jan 2020 10:12:48 +0100 Subject: [PATCH 104/160] adding stuff --- tasmota/xsns_92_MI_HM10.ino | 192 ++++++++++++++++++++++++------------ 1 file changed, 127 insertions(+), 65 deletions(-) diff --git a/tasmota/xsns_92_MI_HM10.ino b/tasmota/xsns_92_MI_HM10.ino index f86d434b6..51c02ea07 100644 --- a/tasmota/xsns_92_MI_HM10.ino +++ b/tasmota/xsns_92_MI_HM10.ino @@ -30,11 +30,14 @@ #define XSNS_92 92 +#define HM_PIN_RX 5 // D1 Hardcoded while developing +#define HM_PIN_TX 4 // D2 + #include TasmotaSerial *HM10Serial; -#define HM10_MAX_TASK_NUMBER 12 +#define HM10_MAX_TASK_NUMBER 8 uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; // first value: kind of task - second value: delay in x * 100ms uint8_t HM10_CURRENT_TASK_DELAY = 0; // number of 100ms-cycles uint8_t HM10_LAST_COMMAND; // task command code @@ -44,8 +47,13 @@ uint16_t HM10_CURRENT_PAYLOAD = 0; // payload of a supported c #define HM10_MAX_RX_BUF 512 char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; // make a buffer bigger than the usual 10-byte-message - - +struct { + uint8_t current_task_delay; + struct { + uint32_t init:1; + // TODO: more to come + } mode; +} HM10; /*********************************************************************************************\ @@ -72,12 +80,23 @@ enum HM10_Commands { + /*********************************************************************************************\ * Task codes defines \*********************************************************************************************/ #define TASK_HM10_NOTASK 0 // nothing to be done -#define TASK_HM10_FEEDBACK 1 // check the feedback from the device +#define TASK_HM10_ROLE1 1 // change role to 1 +#define TASK_HM10_IMME1 2 // change imme to 1 +#define TASK_HM10_RENEW 3 // device factory setting +#define TASK_HM10_RESET 4 // device reset +#define TASK_HM10_DISC 5 // device discovery scan +#define TASK_HM10_CONN 6 // connect to given MAC +#define TASK_HM10_VERSION 7 // query FW version +#define TASK_HM10_NAME 8 // query device name +#define TASK_HM10_FEEDBACK 9 // get device response + + #define TASK_HM10_DONE 99 // used, if there was a task in the slot or just to wait /*********************************************************************************************\ @@ -96,12 +115,14 @@ void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ HM10_TASK_LIST[slot][0] = task; } -void HM10_Reset(void) { HM10_LAST_COMMAND = TASK_HM10_DONE; // task command code - HM10State.activeFolder = 0; // see the line above - HM10_Launchtask(TASK_HM10_DONE,0,10); // just wait for some time , equals delay(1000) -> 10 * 100 - HM10_Launchtask(TASK_HM10_RESET_DEVICE, 1,0); // reset Device - HM10_Launchtask(TASK_HM10_Q_VERSION, 2,10); // read SW Version at startup - } // ASAP +void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_ROLE1,0,10); // set role to 1 + HM10_Launchtask(TASK_HM10_IMME1,1,10); // set imme to 1 + HM10_Launchtask(TASK_HM10_RESET,2,10); // reset Device + HM10_Launchtask(TASK_HM10_VERSION,3,10); // read SW Version + HM10_Launchtask(TASK_HM10_NAME,4,10); // read name + } + + /*********************************************************************************************\ @@ -110,15 +131,17 @@ void HM10_Reset(void) { HM10_LAST_COMMAND = TASK_HM10_DONE; \*********************************************************************************************/ void HM10SerialInit(void) { - HM10Serial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 1, 0, HM10_MAX_RX_BUF); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sstart serial communication fixed to 115200 baud"),S_CONTROL_HM10); + HM10.mode.init = false; + HM10Serial = new TasmotaSerial(HM_PIN_RX, HM_PIN_TX, 1, 0, HM10_MAX_RX_BUF); if (HM10Serial->begin(115200)) { - if (UBXSerial->hardwareSerial()) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sstart serial communication fixed to 115200 baud"),D_CMND_HM10); + if (HM10Serial->hardwareSerial()) { ClaimSerial(); DEBUG_SENSOR_LOG(PSTR("HM10: claim HW")); } HM10_Reset(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK_LIST initialized, now return to main loop"),S_CONTROL_HM10); + HM10.mode.init = true; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); } return; } @@ -127,10 +150,22 @@ void HM10SerialInit(void) { * create the HM10 commands payload, and send it via serial interface to the HM10 player \*********************************************************************************************/ -void HM10_CMD(uint8_t _cmd,uint16_t _val) { +// void HM10_CMD(uint8_t _cmd,uint16_t _val) { - HM10Serial->write(cmd, sizeof(cmd)); / - return; +// HM10Serial->write(cmd, sizeof(cmd)); / +// return; +// } + +/*********************************************************************************************\ + * parse the response +\*********************************************************************************************/ +void HM10ParseResponse(char *buf) { + if (!strncmp(buf,"OK",2)) { + DEBUG_SENSOR_LOG(PSTR("HM10: got OK")); + } + else { + DEBUG_SENSOR_LOG(PSTR("HM10: empty response")); + } } /*********************************************************************************************\ @@ -138,19 +173,26 @@ void HM10_CMD(uint8_t _cmd,uint16_t _val) { \*********************************************************************************************/ bool HM10SerialHandleFeedback(){ - bool success = true; // true disables possible repetition of commands, set to false only for debugging - uint8_t i = 0; - uint8_t ret[HM10_MAX_RX_BUF] = {0}; // reset array with zeros - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%swaiting for response"),S_CONTROL_HM10); - bool receive_data_message = false; // special response with the format d,a, ...,a,d - + bool success = false; // true disables possible repetition of commands, set to false only for debugging + uint32_t i = 0; + char ret[HM10_MAX_RX_BUF] = {0}; // reset array with zeros + + while(HM10Serial->available()) { // delay(0); if(iread(); } i++; - } + success = true; + } + if(success) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s response: %s"),D_CMND_HM10, (char *)ret); + HM10ParseResponse(ret); + } + else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s got no response"),D_CMND_HM10); + } return success; } @@ -159,65 +201,82 @@ bool HM10SerialHandleFeedback(){ \*********************************************************************************************/ void HM10_TaskEvery100ms(){ - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK to be done %u"),S_CONTROL_HM10,HM10_TASK_LIST[0][0]); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK to be done %u"),D_CMND_HM10,HM10_TASK_LIST[0][0]); if (HM10_CURRENT_TASK_DELAY == 0) { uint8_t i = 0; bool runningTaskLoop = true; while (runningTaskLoop) { // always iterate through the whole task list switch(HM10_TASK_LIST[i][0]) { // handle the kind of task - case TASK_HM10_FEEDBACK: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s%sFeedback"),S_CONTROL_HM10,S_TASK_HM10); - if(HM10_RETRIES>0) { - if (HM10SerialHandleFeedback()) { - HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // mark slot as handled if successful - HM10_CURRENT_TASK_DELAY = HM10_TASK_LIST[i+1][1]; // assign the delay of the next slot to the current global delay - } - else { - HM10_TASK_LIST[i][0] = HM10_LAST_COMMAND; // reinsert unsuccessful task into the current slot - HM10_CURRENT_TASK_DELAY++; - HM10_RETRIES--; - } - } - else { - HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // mark slot as handled even if not successful - HM10_CURRENT_TASK_DELAY = HM10_TASK_LIST[i+1][1]; // assign the delay of the next slot to the current global delay - HM10_RETRIES = 3; - } - runningTaskLoop = false; // return to main loop + case TASK_HM10_ROLE1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set role to 1"),D_CMND_HM10); + HM10_CURRENT_TASK_DELAY = 5; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+ROLE1"); break; - case TASK_HM10_PLAY: - HM10_CMD(HM10_CMD_PLAY, 0); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s%sPlay"),S_CONTROL_HM10,S_TASK_HM10); - HM10State.PlayMode = 1; - HM10_TaskReplaceInSlot(TASK_HM10_Q_TRACK,i); + case TASK_HM10_IMME1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set imme to 1"),D_CMND_HM10); + HM10_CURRENT_TASK_DELAY = 5; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+IMME1"); + break; + case TASK_HM10_DISC: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set role to 1"),D_CMND_HM10); + HM10_CURRENT_TASK_DELAY = 35; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+DISC?"); + break; + case TASK_HM10_VERSION: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read version"),D_CMND_HM10); + HM10_CURRENT_TASK_DELAY = 5; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+VERR?"); + break; + case TASK_HM10_NAME: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read name"),D_CMND_HM10); + HM10_CURRENT_TASK_DELAY = 5; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+NAME?"); + break; + + case TASK_HM10_RESET: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s Reset Device"),D_CMND_HM10); + HM10Serial->write("AT+RESET"); + HM10_CURRENT_TASK_DELAY = 5; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; break; - case TASK_HM10_RESET_DEVICE: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s%sReset Device"),S_CONTROL_HM10,S_TASK_HM10); - HM10_CMD(HM10_CMD_RESET, HM10_CMD_RESET_VALUE); - HM10_CURRENT_TASK_DELAY = HM10_TASK_LIST[i+1][1]; // set task delay + case TASK_HM10_FEEDBACK: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s get response"),D_CMND_HM10); + HM10SerialHandleFeedback(); + HM10_CURRENT_TASK_DELAY = HM10_TASK_LIST[i+1][1];; // set task delay HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset - runningTaskLoop = false; // return to main loop + runningTaskLoop = false; break; case TASK_HM10_DONE: // this entry was already handled - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sFound done HM10_TASK"),S_CONTROL_HM10); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sFound done HM10_TASK"),D_CMND_HM10); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%snext slot:%u, i: %u"),D_CMND_HM10, HM10_TASK_LIST[i+1][0],i); if(HM10_TASK_LIST[i+1][0] == TASK_HM10_NOTASK) { // check the next entry and if there is none - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s%sno Tasks left"),S_CONTROL_HM10,S_TASK_HM10); - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK_DONE current slot %u"),S_CONTROL_HM10, i); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sno Tasks left"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK_DONE current slot %u"),D_CMND_HM10, i); for (uint8_t j = 0; j < HM10_MAX_TASK_NUMBER+1; j++) { // do a clean-up: - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK cleanup slot %u"),S_CONTROL_HM10, j); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK cleanup slot %u"),D_CMND_HM10, j); HM10_TASK_LIST[j][0] = TASK_HM10_NOTASK; // reset all task entries HM10_TASK_LIST[j][1] = 0; // reset all delays } runningTaskLoop = false; // return to main loop - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sUpdate GUI via AJAX"),S_CONTROL_HM10); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sUpdate GUI via AJAX"),D_CMND_HM10); // HM10_GUI_NEEDS_UPDATE = true; break; } } - i++; + i++; } } else { @@ -231,26 +290,29 @@ void HM10_TaskEvery100ms(){ * Interface \*********************************************************************************************/ -bool Xdrv92(uint8_t function) +bool Xsns92(uint8_t function) { bool result = false; - if ((pin[GPIO_RXD] < 99) && (pin[GPIO_TXD] < 99)) { + // if ((pin[HM_PIN_RX] < 99) && (pin[HM_PIN_TX] < 99)) { + if (true) { switch (function) { - case FUNC_PRE_INIT: + case FUNC_INIT: HM10SerialInit(); // init and start communication break; case FUNC_EVERY_100_MSECOND: if (HM10_TASK_LIST[0][0] == TASK_HM10_NOTASK) { // no task running + // DEBUG_SENSOR_LOG(PSTR("HM10: no TASK in array")); HM10SerialHandleFeedback(); // -> sniff for device feedback break; } else { + // DEBUG_SENSOR_LOG(PSTR("HM10: every 100msec")); HM10_TaskEvery100ms(); // something has to be done, we'll check in the next step break; } + break; } } return result; -} - +} \ No newline at end of file From a1d7d2baf81a15510ac0c0ae5a7318258d6c4a27 Mon Sep 17 00:00:00 2001 From: Staars Date: Fri, 31 Jan 2020 15:28:34 +0100 Subject: [PATCH 105/160] output working --- tasmota/xsns_92_MI_HM10.ino | 165 +++++++++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 29 deletions(-) diff --git a/tasmota/xsns_92_MI_HM10.ino b/tasmota/xsns_92_MI_HM10.ino index 51c02ea07..045392d73 100644 --- a/tasmota/xsns_92_MI_HM10.ino +++ b/tasmota/xsns_92_MI_HM10.ino @@ -37,24 +37,32 @@ TasmotaSerial *HM10Serial; -#define HM10_MAX_TASK_NUMBER 8 +#define HM10_MAX_TASK_NUMBER 12 uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; // first value: kind of task - second value: delay in x * 100ms -uint8_t HM10_CURRENT_TASK_DELAY = 0; // number of 100ms-cycles -uint8_t HM10_LAST_COMMAND; // task command code +// uint8_t HM10.current_task_delay = 0; // number of 100ms-cycles +// uint8_t HM10.last_command; -uint16_t HM10_CURRENT_PAYLOAD = 0; // payload of a supported command #define HM10_MAX_RX_BUF 512 char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; // make a buffer bigger than the usual 10-byte-message struct { uint8_t current_task_delay; + uint8_t last_command; + uint16_t firmware; struct { uint32_t init:1; + uint32_t subscribed:1; // TODO: more to come } mode; } HM10; +#pragma pack(1) +struct { + uint16_t temp; + uint8_t hum; +} LYWSD03; +#pragma pack(0) /*********************************************************************************************\ * constants @@ -95,7 +103,10 @@ enum HM10_Commands { #define TASK_HM10_VERSION 7 // query FW version #define TASK_HM10_NAME 8 // query device name #define TASK_HM10_FEEDBACK 9 // get device response - +#define TASK_HM10_DISCONN 10 // disconnect +#define TASK_HM10_SUBSCR 11 // subscribe to service handle +#define TASK_HM10_READ 12 // read from handle +#define TASK_HM10_FINDALLCHARS 13 // read all available characteristics #define TASK_HM10_DONE 99 // used, if there was a task in the slot or just to wait @@ -107,19 +118,26 @@ void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay){ HM10_TASK_LIST[slot][0] = task; HM10_TASK_LIST[slot][1] = delay; HM10_TASK_LIST[slot+1][0] = TASK_HM10_NOTASK; // the tasks must always be launched in ascending order!! - HM10_CURRENT_TASK_DELAY = HM10_TASK_LIST[0][1]; + HM10.current_task_delay = HM10_TASK_LIST[0][1]; } void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ - HM10_LAST_COMMAND = HM10_TASK_LIST[slot][0]; // save command + HM10.last_command = HM10_TASK_LIST[slot][0]; // save command HM10_TASK_LIST[slot][0] = task; } -void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_ROLE1,0,10); // set role to 1 - HM10_Launchtask(TASK_HM10_IMME1,1,10); // set imme to 1 - HM10_Launchtask(TASK_HM10_RESET,2,10); // reset Device +void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_ROLE1,0,1); // set role to 1 + HM10_Launchtask(TASK_HM10_IMME1,1,1); // set imme to 1 + HM10_Launchtask(TASK_HM10_RESET,2,1); // reset Device HM10_Launchtask(TASK_HM10_VERSION,3,10); // read SW Version - HM10_Launchtask(TASK_HM10_NAME,4,10); // read name + HM10_Launchtask(TASK_HM10_DISC,4,1); // disscovery + HM10_Launchtask(TASK_HM10_CONN,5,5); // connect + HM10_Launchtask(TASK_HM10_FEEDBACK,6,35); // get OK+CONN + HM10_Launchtask(TASK_HM10_SUBSCR,7,20); // subscribe + HM10_Launchtask(TASK_HM10_READ,8,35); // read + HM10_Launchtask(TASK_HM10_READ,9,35); // read + HM10_Launchtask(TASK_HM10_READ,10,35); // read + HM10_Launchtask(TASK_HM10_DISCONN,11,250); // disconnect } @@ -134,14 +152,14 @@ void HM10SerialInit(void) { HM10.mode.init = false; HM10Serial = new TasmotaSerial(HM_PIN_RX, HM_PIN_TX, 1, 0, HM10_MAX_RX_BUF); if (HM10Serial->begin(115200)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sstart serial communication fixed to 115200 baud"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start serial communication fixed to 115200 baud"),D_CMND_HM10); if (HM10Serial->hardwareSerial()) { ClaimSerial(); DEBUG_SENSOR_LOG(PSTR("HM10: claim HW")); } HM10_Reset(); HM10.mode.init = true; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); } return; } @@ -160,12 +178,19 @@ void HM10SerialInit(void) { * parse the response \*********************************************************************************************/ void HM10ParseResponse(char *buf) { - if (!strncmp(buf,"OK",2)) { + if (!strncmp(buf,"OK",2)) { DEBUG_SENSOR_LOG(PSTR("HM10: got OK")); } - else { - DEBUG_SENSOR_LOG(PSTR("HM10: empty response")); + if (!strncmp(buf,"HMSoft",6)) { //8 + const char* _fw = "000"; + memcpy((void *)_fw,(void *)(buf+8),3); + HM10.firmware = atoi(_fw); + DEBUG_SENSOR_LOG(PSTR("HM10: Firmware: %d"), HM10.firmware); } + + else { + DEBUG_SENSOR_LOG(PSTR("HM10: empty response")); + } } /*********************************************************************************************\ @@ -186,7 +211,14 @@ bool HM10SerialHandleFeedback(){ i++; success = true; } - if(success) { + if(HM10.mode.subscribed) { + DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),ret[0],ret[1],ret[2],ret[3],ret[4],ret[5],ret[6]); + if(ret[0] != 0 && ret[1] != 0){ + memcpy(&LYWSD03,(void *)ret,3); + DEBUG_SENSOR_LOG(PSTR("HM10: Temperature * 100: %u, Humidity: %u"),LYWSD03.temp,LYWSD03.hum); + } + } + else if(success) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s response: %s"),D_CMND_HM10, (char *)ret); HM10ParseResponse(ret); } @@ -202,59 +234,92 @@ bool HM10SerialHandleFeedback(){ void HM10_TaskEvery100ms(){ // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK to be done %u"),D_CMND_HM10,HM10_TASK_LIST[0][0]); - if (HM10_CURRENT_TASK_DELAY == 0) { + if (HM10.current_task_delay == 0) { uint8_t i = 0; bool runningTaskLoop = true; while (runningTaskLoop) { // always iterate through the whole task list switch(HM10_TASK_LIST[i][0]) { // handle the kind of task case TASK_HM10_ROLE1: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set role to 1"),D_CMND_HM10); - HM10_CURRENT_TASK_DELAY = 5; // set task delay + HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+ROLE1"); break; case TASK_HM10_IMME1: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set imme to 1"),D_CMND_HM10); - HM10_CURRENT_TASK_DELAY = 5; // set task delay + HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+IMME1"); break; case TASK_HM10_DISC: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set role to 1"),D_CMND_HM10); - HM10_CURRENT_TASK_DELAY = 35; // set task delay + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start discovery"),D_CMND_HM10); + HM10.current_task_delay = 35; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+DISC?"); break; case TASK_HM10_VERSION: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read version"),D_CMND_HM10); - HM10_CURRENT_TASK_DELAY = 5; // set task delay + HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+VERR?"); break; case TASK_HM10_NAME: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read name"),D_CMND_HM10); - HM10_CURRENT_TASK_DELAY = 5; // set task delay + HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+NAME?"); break; - + case TASK_HM10_CONN: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s connect"),D_CMND_HM10); + HM10.current_task_delay = 2; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+CONA4C138ED815A"); + break; + case TASK_HM10_DISCONN: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s disconnect"),D_CMND_HM10); + HM10.current_task_delay = 5; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT"); + HM10.mode.subscribed = false; + break; case TASK_HM10_RESET: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s Reset Device"),D_CMND_HM10); HM10Serial->write("AT+RESET"); - HM10_CURRENT_TASK_DELAY = 5; // set task delay + HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; break; - + case TASK_HM10_SUBSCR: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); + HM10.current_task_delay = 15; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+NOTIFY_ON0037"); + + case TASK_HM10_READ: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0036"),D_CMND_HM10); + HM10.current_task_delay = 0; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0036?"); + HM10.mode.subscribed = true; + case TASK_HM10_FINDALLCHARS: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s find all chars"),D_CMND_HM10); + HM10.current_task_delay = 35; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+FINDALLCHARS?"); case TASK_HM10_FEEDBACK: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s get response"),D_CMND_HM10); HM10SerialHandleFeedback(); - HM10_CURRENT_TASK_DELAY = HM10_TASK_LIST[i+1][1];; // set task delay + HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; // set task delay HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset runningTaskLoop = false; break; @@ -280,11 +345,45 @@ void HM10_TaskEvery100ms(){ } } else { - HM10_CURRENT_TASK_DELAY--; // count down every 100 ms + HM10.current_task_delay--; // count down every 100 ms } } +const char HTTP_HM10[] PROGMEM = + "{s}HM10" " Firmware " "{m}%u{e}"; + +void HM10Show(bool json) +{ + if (HM10.firmware>0) { + char temperature[33]; + float _temp = (float)LYWSD03.temp/100.0F; + dtostrfd(_temp, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(LYWSD03.hum, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, F("LYWSD03"), temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif // USE_DOMOTICZ +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, _temp); + KnxSensor(KNX_HUMIDITY, LYWSD03.hum); + } +#endif // USE_KNX +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_HM10, HM10.firmware); + WSContentSend_PD(HTTP_SNS_TEMP, F("LYWSD03"), temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, F("LYWSD03"), humidity); +#endif // USE_WEBSERVER + } + } +} /*********************************************************************************************\ * Interface @@ -312,6 +411,14 @@ bool Xsns92(uint8_t function) break; } break; + case FUNC_JSON_APPEND: + HM10Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HM10Show(0); + break; +#endif // USE_WEBSERVER } } return result; From f6a93a8d60ce876cacd494ff157606576a522841 Mon Sep 17 00:00:00 2001 From: Staars Date: Fri, 31 Jan 2020 18:50:11 +0100 Subject: [PATCH 106/160] unify codebase --- tasmota/xsns_92_MI_HM10.ino | 131 +++++++++++++++++++++++++++++------- 1 file changed, 107 insertions(+), 24 deletions(-) diff --git a/tasmota/xsns_92_MI_HM10.ino b/tasmota/xsns_92_MI_HM10.ino index 045392d73..a384d446a 100644 --- a/tasmota/xsns_92_MI_HM10.ino +++ b/tasmota/xsns_92_MI_HM10.ino @@ -34,20 +34,20 @@ #define HM_PIN_TX 4 // D2 #include +#include TasmotaSerial *HM10Serial; #define HM10_MAX_TASK_NUMBER 12 uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; // first value: kind of task - second value: delay in x * 100ms -// uint8_t HM10.current_task_delay = 0; // number of 100ms-cycles -// uint8_t HM10.last_command; + #define HM10_MAX_RX_BUF 512 -char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; // make a buffer bigger than the usual 10-byte-message +char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; struct { - uint8_t current_task_delay; + uint8_t current_task_delay; // number of 100ms-cycles uint8_t last_command; uint16_t firmware; struct { @@ -64,6 +64,32 @@ struct { } LYWSD03; #pragma pack(0) +struct mi_sensor_t{ + uint8_t type; //flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4 + uint8_t serial[6]; + uint8_t showedUp; + union { + struct { + float temp; + float moisture; + float fertility; + uint16_t lux; + } Flora; + struct { + float temp; + float hum; + uint8_t bat; + } MJ_HT_V1; + struct { + float temp; + float hum; + uint8_t bat; + } LYWSD0x; // LYWSD02 and LYWSD03 + }; +}; + +std::vector MIBLEsensors; + /*********************************************************************************************\ * constants \*********************************************************************************************/ @@ -140,7 +166,56 @@ void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_ROLE1,0,1); // set r HM10_Launchtask(TASK_HM10_DISCONN,11,250); // disconnect } - +/** + * @brief Return the slot number of a known sensor or return create new sensor slot + * + * @param _serial BLE address of the sensor + * @param _type Type number of the sensor + * @return uint32_t Known or new slot in the sensors-vector + */ +uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ + DEBUG_SENSOR_LOG(PSTR("MIBLE: vector size %u"), MIBLEsensors.size()); + for(uint32_t i=0; i0) { - char temperature[33]; - float _temp = (float)LYWSD03.temp/100.0F; - dtostrfd(_temp, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(LYWSD03.hum, Settings.flag2.humidity_resolution, humidity); - if (json) { + if (MIBLEsensors.size()==0) return; + + char temperature[33]; + dtostrfd(MIBLEsensors.at(0).LYWSD0x.temp, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(MIBLEsensors.at(0).LYWSD0x.hum, Settings.flag2.humidity_resolution, humidity); + ResponseAppend_P(JSON_SNS_TEMPHUM, F("LYWSD03"), temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif // USE_DOMOTICZ -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, _temp); - KnxSensor(KNX_HUMIDITY, LYWSD03.hum); - } -#endif // USE_KNX #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_HM10, HM10.firmware); + if (MIBLEsensors.size()==0) return; + + char temperature[33]; + dtostrfd(MIBLEsensors.at(0).LYWSD0x.temp, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(MIBLEsensors.at(0).LYWSD0x.hum, Settings.flag2.humidity_resolution, humidity); + WSContentSend_PD(HTTP_SNS_TEMP, F("LYWSD03"), temperature, TempUnit()); WSContentSend_PD(HTTP_SNS_HUM, F("LYWSD03"), humidity); #endif // USE_WEBSERVER } - } } /*********************************************************************************************\ From 3b61d7768083054c367193406d8f202c92b2200f Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 1 Feb 2020 14:23:13 +0100 Subject: [PATCH 107/160] Fix wrong CT channel for Module 48 --- tasmota/xdrv_04_light.ino | 62 ++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 4ef8b409e..a45a5499d 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2030,38 +2030,40 @@ void calcGammaMultiChannels(uint16_t cur_col_10[5]) { void calcGammaBulbs(uint16_t cur_col_10[5]) { // Apply gamma correction for 8 and 10 bits resolutions, if needed - if (Settings.light_correction) { - // First apply combined correction to the overall white power - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - // channels for white are always the last two channels - uint32_t cw1 = Light.subtype - 1; // address for the ColorTone PWM - uint32_t cw0 = Light.subtype - 2; // address for the White Brightness PWM - uint16_t white_bri10 = cur_col_10[cw0] + cur_col_10[cw1]; // cumulated brightness - uint16_t white_bri10_1023 = (white_bri10 > 1023) ? 1023 : white_bri10; // max 1023 - if (PHILIPS == my_module_type) { // channel 1 is the color tone, mapped to cold channel (0..255) - // Xiaomi Philips bulbs follow a different scheme: - cur_col_10[cw1] = light_state.getCT10bits(); - // channel 0=intensity, channel1=temperature - if (Settings.light_correction) { // gamma correction - cur_col_10[cw0] = ledGamma10_10(white_bri10_1023); // 10 bits gamma correction - } else { - cur_col_10[cw0] = white_bri10_1023; // no gamma, extend to 10 bits - } + // First apply combined correction to the overall white power + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + // channels for white are always the last two channels + uint32_t cw1 = Light.subtype - 1; // address for the ColorTone PWM + uint32_t cw0 = Light.subtype - 2; // address for the White Brightness PWM + uint16_t white_bri10 = cur_col_10[cw0] + cur_col_10[cw1]; // cumulated brightness + uint16_t white_bri10_1023 = (white_bri10 > 1023) ? 1023 : white_bri10; // max 1023 + + if (PHILIPS == my_module_type) { // channel 1 is the color tone, mapped to cold channel (0..255) + // Xiaomi Philips bulbs follow a different scheme: + cur_col_10[cw1] = light_state.getCT10bits(); + // channel 0=intensity, channel1=temperature + if (Settings.light_correction) { // gamma correction + cur_col_10[cw0] = ledGamma10_10(white_bri10_1023); // 10 bits gamma correction } else { - // if sum of both channels is > 255, then channels are probably uncorrelated - if (white_bri10 <= 1031) { // take a margin of 8 above 1023 to account for rounding errors - // we calculate the gamma corrected sum of CW + WW - uint16_t white_bri_gamma10 = ledGamma10_10(white_bri10_1023); - // then we split the total energy among the cold and warm leds - cur_col_10[cw0] = changeUIntScale(cur_col_10[cw0], 0, white_bri10_1023, 0, white_bri_gamma10); - cur_col_10[cw1] = changeUIntScale(cur_col_10[cw1], 0, white_bri10_1023, 0, white_bri_gamma10); - } else { - cur_col_10[cw0] = ledGamma10_10(cur_col_10[cw0]); - cur_col_10[cw1] = ledGamma10_10(cur_col_10[cw1]); - } + cur_col_10[cw0] = white_bri10_1023; // no gamma, extend to 10 bits + } + } else if (Settings.light_correction) { + // if sum of both channels is > 255, then channels are probably uncorrelated + if (white_bri10 <= 1031) { // take a margin of 8 above 1023 to account for rounding errors + // we calculate the gamma corrected sum of CW + WW + uint16_t white_bri_gamma10 = ledGamma10_10(white_bri10_1023); + // then we split the total energy among the cold and warm leds + cur_col_10[cw0] = changeUIntScale(cur_col_10[cw0], 0, white_bri10_1023, 0, white_bri_gamma10); + cur_col_10[cw1] = changeUIntScale(cur_col_10[cw1], 0, white_bri10_1023, 0, white_bri_gamma10); + } else { + cur_col_10[cw0] = ledGamma10_10(cur_col_10[cw0]); + cur_col_10[cw1] = ledGamma10_10(cur_col_10[cw1]); } } + } + + if (Settings.light_correction) { // then apply gamma correction to RGB channels if (LST_RGB <= Light.subtype) { for (uint32_t i = 0; i < 3; i++) { @@ -2069,8 +2071,8 @@ void calcGammaBulbs(uint16_t cur_col_10[5]) { } } // If RGBW or Single channel, also adjust White channel - if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { - cur_col_10[3] = ledGamma10_10(cur_col_10[3]); + if ((LST_SINGLE == Light.subtype) || (LST_RGBW == Light.subtype)) { + cur_col_10[Light.subtype - 1] = ledGamma10_10(cur_col_10[Light.subtype - 1]); } } } From cb067237ad1d56be59697454b1043a850977b95c Mon Sep 17 00:00:00 2001 From: Staars Date: Sat, 1 Feb 2020 16:17:20 +0100 Subject: [PATCH 108/160] stabilize readings --- tasmota/xsns_92_MI_HM10.ino | 184 ++++++++++++++++++++++++++---------- 1 file changed, 136 insertions(+), 48 deletions(-) diff --git a/tasmota/xsns_92_MI_HM10.ino b/tasmota/xsns_92_MI_HM10.ino index a384d446a..b91d75d31 100644 --- a/tasmota/xsns_92_MI_HM10.ino +++ b/tasmota/xsns_92_MI_HM10.ino @@ -47,14 +47,19 @@ uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; // first value: kind of ta char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; struct { - uint8_t current_task_delay; // number of 100ms-cycles + uint8_t current_task_delay; // number of 100ms-cycles uint8_t last_command; uint16_t firmware; struct { uint32_t init:1; uint32_t subscribed:1; + uint32_t pending_task:1; // TODO: more to come } mode; + struct { + uint8_t sensor; // points to to the number 0...255 + // TODO: more to come + } state; } HM10; #pragma pack(1) @@ -96,17 +101,32 @@ std::vector MIBLEsensors; #define D_CMND_HM10 "HM10" -const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; -const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s\"}"; -const char kHM10_Commands[] PROGMEM = "Track|Play"; +// const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; +// const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s\"}"; +// const char kHM10_Commands[] PROGMEM = "Track|Play"; + +const char kHM10SlaveID0[] PROGMEM = ""; +const char kHM10SlaveID1[] PROGMEM = ""; +const char kHM10SlaveID2[] PROGMEM = ""; +const char kHM10SlaveID3[] PROGMEM = ""; +const char kHM10SlaveID4[] PROGMEM = "A4C138"; +const char * kHM10SlaveID[] PROGMEM = {kHM10SlaveID0,kHM10SlaveID1,kHM10SlaveID2,kHM10SlaveID3,kHM10SlaveID4}; + + +// const char kHM10Mac0[] PROGMEM = "A4C138ED815A"; +// const char kHM10Mac1[] PROGMEM = "A4C1382AC8B3"; +// const char * kHM10Mac[] PROGMEM ={kHM10Mac0, kHM10Mac1}; + +uint8_t HM10Mac[2][6]={0xA4,0xC1,0x38,0xED,0x81,0x5A, + 0xA4,0xC1,0x38,0x2A,0xC8,0xB3}; /*********************************************************************************************\ * enumerations \*********************************************************************************************/ -enum HM10_Commands { - CMND_HM10_TRACK -}; +// enum HM10_Commands { +// CMND_HM10_TRACK +// }; /*********************************************************************************************\ * command defines @@ -130,9 +150,11 @@ enum HM10_Commands { #define TASK_HM10_NAME 8 // query device name #define TASK_HM10_FEEDBACK 9 // get device response #define TASK_HM10_DISCONN 10 // disconnect -#define TASK_HM10_SUBSCR 11 // subscribe to service handle -#define TASK_HM10_READ 12 // read from handle +#define TASK_HM10_SUBSCR 11 // subscribe to service handle 37 +#define TASK_HM10_READ 12 // read from handle 36 #define TASK_HM10_FINDALLCHARS 13 // read all available characteristics +#define TASK_HM10_UNSUBSCR 14 // subscribe service handle 37 +#define TASK_HM10_DELAY_SUB 15 // start reading from subscription delayed #define TASK_HM10_DONE 99 // used, if there was a task in the slot or just to wait @@ -152,19 +174,33 @@ void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ HM10_TASK_LIST[slot][0] = task; } -void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_ROLE1,0,1); // set role to 1 - HM10_Launchtask(TASK_HM10_IMME1,1,1); // set imme to 1 - HM10_Launchtask(TASK_HM10_RESET,2,1); // reset Device - HM10_Launchtask(TASK_HM10_VERSION,3,10); // read SW Version - HM10_Launchtask(TASK_HM10_DISC,4,1); // disscovery - HM10_Launchtask(TASK_HM10_CONN,5,5); // connect - HM10_Launchtask(TASK_HM10_FEEDBACK,6,35); // get OK+CONN - HM10_Launchtask(TASK_HM10_SUBSCR,7,20); // subscribe - HM10_Launchtask(TASK_HM10_READ,8,35); // read - HM10_Launchtask(TASK_HM10_READ,9,35); // read - HM10_Launchtask(TASK_HM10_READ,10,35); // read - HM10_Launchtask(TASK_HM10_DISCONN,11,250); // disconnect - } +void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disconnect + HM10_Launchtask(TASK_HM10_ROLE1,1,1); // set role to 1 + HM10_Launchtask(TASK_HM10_IMME1,2,1); // set imme to 1 + HM10_Launchtask(TASK_HM10_RESET,3,1); // reset Device + HM10_Launchtask(TASK_HM10_VERSION,4,10); // read SW Version + HM10_Launchtask(TASK_HM10_DISC,5,1); // disscovery + } + +void HM10_Read_Sensor(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); // connect + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); // get OK+CONN + HM10_Launchtask(TASK_HM10_SUBSCR,2,10); // subscribe + HM10_Launchtask(TASK_HM10_READ,3,15); // read + HM10_Launchtask(TASK_HM10_READ,4,15); // read + HM10_Launchtask(TASK_HM10_READ,5,15); // read + HM10_Launchtask(TASK_HM10_UNSUBSCR,6,10); // unsubscribe + HM10_Launchtask(TASK_HM10_DISCONN,7,0); // disconnect + } + +void HM10_Read_Sensor1(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); // connect + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); // get OK+CONN + HM10_Launchtask(TASK_HM10_SUBSCR,2,10); // subscribe + HM10_Launchtask(TASK_HM10_UNSUBSCR,3,60); // unsubscribe + HM10_Launchtask(TASK_HM10_DISCONN,4,0); // disconnect + } + /** * @brief Return the slot number of a known sensor or return create new sensor slot @@ -233,7 +269,8 @@ void HM10SerialInit(void) { DEBUG_SENSOR_LOG(PSTR("HM10: claim HW")); } HM10_Reset(); - HM10.mode.init = true; + HM10.mode.pending_task = 1; + HM10.mode.init = 1; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); } return; @@ -268,12 +305,33 @@ void HM10ParseResponse(char *buf) { } } +void HM10readTempHum(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0] != 0 && _buf[1] != 0){ + memcpy(&LYWSD03,(void *)_buf,3); + DEBUG_SENSOR_LOG(PSTR("HM10: Temperature * 100: %u, Humidity: %u"),LYWSD03.temp,LYWSD03.hum); + // uint8_t _serial[6] = {0}; + uint32_t _slot = MIBLEgetSensorSlot(HM10Mac[HM10.state.sensor], 4); + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + static float _tempFloat; + _tempFloat=(float)(LYWSD03.temp)/100.0f; + if(_tempFloat<60){ + MIBLEsensors.at(_slot).LYWSD0x.temp=_tempFloat; + } + _tempFloat=(float)LYWSD03.hum; + if(_tempFloat<100){ + MIBLEsensors.at(_slot).LYWSD0x.hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("LYWSD03: hum updated")); + } + } +} + /*********************************************************************************************\ * handle the return value from the HM10 \*********************************************************************************************/ bool HM10SerialHandleFeedback(){ - bool success = false; // true disables possible repetition of commands, set to false only for debugging + bool success = false; // true disables possible repetition of commands, set to false only for debugging uint32_t i = 0; char ret[HM10_MAX_RX_BUF] = {0}; // reset array with zeros @@ -287,31 +345,14 @@ bool HM10SerialHandleFeedback(){ success = true; } if(HM10.mode.subscribed) { - DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),ret[0],ret[1],ret[2],ret[3],ret[4],ret[5],ret[6]); - if(ret[0] != 0 && ret[1] != 0){ - memcpy(&LYWSD03,(void *)ret,3); - DEBUG_SENSOR_LOG(PSTR("HM10: Temperature * 100: %u, Humidity: %u"),LYWSD03.temp,LYWSD03.hum); - uint8_t _serial[6] = {0}; - uint32_t _slot = MIBLEgetSensorSlot(_serial, 4); - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - static float _tempFloat; - _tempFloat=(float)(LYWSD03.temp)/100.0f; - if(_tempFloat<60){ - MIBLEsensors.at(_slot).LYWSD0x.temp=_tempFloat; - } - _tempFloat=(float)LYWSD03.hum; - if(_tempFloat<100){ - MIBLEsensors.at(_slot).LYWSD0x.hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1: hum updated")); - } - } + HM10readTempHum(ret); } else if(success) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s response: %s"),D_CMND_HM10, (char *)ret); HM10ParseResponse(ret); } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s got no response"),D_CMND_HM10); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s got no response"),D_CMND_HM10); } return success; } @@ -321,6 +362,7 @@ bool HM10SerialHandleFeedback(){ \*********************************************************************************************/ void HM10_TaskEvery100ms(){ + HM10SerialHandleFeedback(); // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sHM10_TASK to be done %u"),D_CMND_HM10,HM10_TASK_LIST[0][0]); if (HM10.current_task_delay == 0) { uint8_t i = 0; @@ -367,7 +409,11 @@ void HM10_TaskEvery100ms(){ HM10.current_task_delay = 2; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; - HM10Serial->write("AT+CONA4C138ED815A"); + // HM10Serial->write("AT+CONA4C138ED815A"); + char _con[20]; + sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",HM10Mac[HM10.state.sensor][0],HM10Mac[HM10.state.sensor][1],HM10Mac[HM10.state.sensor][2],HM10Mac[HM10.state.sensor][3],HM10Mac[HM10.state.sensor][4],HM10Mac[HM10.state.sensor][5]); + HM10Serial->write(_con); + // HM10Serial->write(kHM10Mac[HM10.state.sensor]); break; case TASK_HM10_DISCONN: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s disconnect"),D_CMND_HM10); @@ -375,7 +421,6 @@ void HM10_TaskEvery100ms(){ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT"); - HM10.mode.subscribed = false; break; case TASK_HM10_RESET: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s Reset Device"),D_CMND_HM10); @@ -386,11 +431,19 @@ void HM10_TaskEvery100ms(){ break; case TASK_HM10_SUBSCR: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); - HM10.current_task_delay = 15; // set task delay - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + HM10.current_task_delay = 25; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); runningTaskLoop = false; HM10Serial->write("AT+NOTIFY_ON0037"); - + break; + case TASK_HM10_UNSUBSCR: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); + HM10.current_task_delay = 5; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.subscribed = false; + HM10Serial->write("AT+NOTIFYOFF0037"); + break; case TASK_HM10_READ: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0036"),D_CMND_HM10); HM10.current_task_delay = 0; // set task delay @@ -398,12 +451,14 @@ void HM10_TaskEvery100ms(){ runningTaskLoop = false; HM10Serial->write("AT+READDATA0036?"); HM10.mode.subscribed = true; + break; case TASK_HM10_FINDALLCHARS: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s find all chars"),D_CMND_HM10); HM10.current_task_delay = 35; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+FINDALLCHARS?"); + break; case TASK_HM10_FEEDBACK: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s get response"),D_CMND_HM10); HM10SerialHandleFeedback(); @@ -411,6 +466,14 @@ void HM10_TaskEvery100ms(){ HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset runningTaskLoop = false; break; + case TASK_HM10_DELAY_SUB: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start reading"),D_CMND_HM10); + HM10SerialHandleFeedback(); + HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; // set task delay + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset + HM10.mode.subscribed = true; + runningTaskLoop = false; + break; case TASK_HM10_DONE: // this entry was already handled // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sFound done HM10_TASK"),D_CMND_HM10); @@ -426,6 +489,7 @@ void HM10_TaskEvery100ms(){ runningTaskLoop = false; // return to main loop // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sUpdate GUI via AJAX"),D_CMND_HM10); // HM10_GUI_NEEDS_UPDATE = true; + HM10.mode.pending_task = 0; break; } } @@ -437,6 +501,26 @@ void HM10_TaskEvery100ms(){ } } +void HM10EverySecond(){ + if(HM10.firmware == 0) return; + if(HM10.mode.pending_task == 1) return; + static uint32_t _counter = 0; + if(_counter == 0) { + HM10_Read_Sensor1(); + HM10.mode.pending_task == 1; + _counter = 60; + HM10.state.sensor++; + if (HM10.state.sensor>1) { + HM10.state.sensor=0; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); + } + _counter--; +} + +/*********************************************************************************************\ + * Presentation +\*********************************************************************************************/ const char HTTP_HM10[] PROGMEM = "{s}HM10" " Firmware " "{m}%u{e}"; @@ -494,6 +578,10 @@ bool Xsns92(uint8_t function) break; } break; + case FUNC_EVERY_SECOND: + HM10EverySecond(); + DEBUG_SENSOR_LOG(PSTR("HM10: every second")); + break; case FUNC_JSON_APPEND: HM10Show(1); break; From ed455df7604837d12caa2acb55aec49c293a7548 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 2 Feb 2020 13:13:44 +0100 Subject: [PATCH 109/160] Fix PWM flickering at low levels (#7415) --- tasmota/CHANGELOG.md | 1 + tasmota/core_esp8266_waveform.cpp | 317 ++++++++++++++++++++++++++++++ 2 files changed, 318 insertions(+) create mode 100644 tasmota/core_esp8266_waveform.cpp diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index b5036467c..e82a7c082 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Change wifi connectivity stability (#7602) - Add ``SetOption84 1`` sends AWS IoT device shadow updates (alternative to retained) +- Fix PWM flickering at low levels (#7415) ### 8.1.0.4 20200116 diff --git a/tasmota/core_esp8266_waveform.cpp b/tasmota/core_esp8266_waveform.cpp new file mode 100644 index 000000000..14cec9789 --- /dev/null +++ b/tasmota/core_esp8266_waveform.cpp @@ -0,0 +1,317 @@ +/* + esp8266_waveform - General purpose waveform generation and control, + supporting outputs on all pins in parallel. + + Copyright (c) 2018 Earle F. Philhower, III. All rights reserved. + + The core idea is to have a programmable waveform generator with a unique + high and low period (defined in microseconds). TIMER1 is set to 1-shot + mode and is always loaded with the time until the next edge of any live + waveforms. + + Up to one waveform generator per pin supported. + + Each waveform generator is synchronized to the ESP cycle counter, not the + timer. This allows for removing interrupt jitter and delay as the counter + always increments once per 80MHz clock. Changes to a waveform are + contiguous and only take effect on the next waveform transition, + allowing for smooth transitions. + + This replaces older tone(), analogWrite(), and the Servo classes. + + Everywhere in the code where "cycles" is used, it means ESP.getCycleTime() + cycles, not TIMER1 cycles (which may be 2 CPU clocks @ 160MHz). + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +// Use PWM from core 2.4.0 as all versions below 2.5.0-beta3 produce LED flickering when settings are saved to flash +#include +#if defined(ARDUINO_ESP8266_RELEASE_2_6_1) || defined(ARDUINO_ESP8266_RELEASE_2_6_2) || defined(ARDUINO_ESP8266_RELEASE_2_6_3) +#warning **** Tasmota is using a patched PWM Arduino version as planned **** + + +#include +#include "ets_sys.h" +#include "core_esp8266_waveform.h" + +extern "C" { + +// Maximum delay between IRQs +#define MAXIRQUS (10000) + +// Set/clear GPIO 0-15 by bitmask +#define SetGPIO(a) do { GPOS = a; } while (0) +#define ClearGPIO(a) do { GPOC = a; } while (0) + +// Waveform generator can create tones, PWM, and servos +typedef struct { + uint32_t nextServiceCycle; // ESP cycle timer when a transition required + uint32_t expiryCycle; // For time-limited waveform, the cycle when this waveform must stop + uint32_t nextTimeHighCycles; // Copy over low->high to keep smooth waveform + uint32_t nextTimeLowCycles; // Copy over high->low to keep smooth waveform +} Waveform; + +static Waveform waveform[17]; // State of all possible pins +static volatile uint32_t waveformState = 0; // Is the pin high or low, updated in NMI so no access outside the NMI code +static volatile uint32_t waveformEnabled = 0; // Is it actively running, updated in NMI so no access outside the NMI code + +// Enable lock-free by only allowing updates to waveformState and waveformEnabled from IRQ service routine +static volatile uint32_t waveformToEnable = 0; // Message to the NMI handler to start a waveform on a inactive pin +static volatile uint32_t waveformToDisable = 0; // Message to the NMI handler to disable a pin from waveform generation + +static uint32_t (*timer1CB)() = NULL; + + +// Non-speed critical bits +#pragma GCC optimize ("Os") + +static inline ICACHE_RAM_ATTR uint32_t GetCycleCount() { + uint32_t ccount; + __asm__ __volatile__("esync; rsr %0,ccount":"=a"(ccount)); + return ccount; +} + +// Interrupt on/off control +static ICACHE_RAM_ATTR void timer1Interrupt(); +static bool timerRunning = false; + +static void initTimer() { + timer1_disable(); + ETS_FRC_TIMER1_INTR_ATTACH(NULL, NULL); + ETS_FRC_TIMER1_NMI_INTR_ATTACH(timer1Interrupt); + timer1_enable(TIM_DIV1, TIM_EDGE, TIM_SINGLE); + timerRunning = true; +} + +static void ICACHE_RAM_ATTR deinitTimer() { + ETS_FRC_TIMER1_NMI_INTR_ATTACH(NULL); + timer1_disable(); + timer1_isr_init(); + timerRunning = false; +} + +// Set a callback. Pass in NULL to stop it +void setTimer1Callback(uint32_t (*fn)()) { + timer1CB = fn; + if (!timerRunning && fn) { + initTimer(); + timer1_write(microsecondsToClockCycles(1)); // Cause an interrupt post-haste + } else if (timerRunning && !fn && !waveformEnabled) { + deinitTimer(); + } +} + +// Start up a waveform on a pin, or change the current one. Will change to the new +// waveform smoothly on next low->high transition. For immediate change, stopWaveform() +// first, then it will immediately begin. +int startWaveform(uint8_t pin, uint32_t timeHighUS, uint32_t timeLowUS, uint32_t runTimeUS) { + if ((pin > 16) || isFlashInterfacePin(pin)) { + return false; + } + Waveform *wave = &waveform[pin]; + // Adjust to shave off some of the IRQ time, approximately + wave->nextTimeHighCycles = microsecondsToClockCycles(timeHighUS); + wave->nextTimeLowCycles = microsecondsToClockCycles(timeLowUS); + wave->expiryCycle = runTimeUS ? GetCycleCount() + microsecondsToClockCycles(runTimeUS) : 0; + if (runTimeUS && !wave->expiryCycle) { + wave->expiryCycle = 1; // expiryCycle==0 means no timeout, so avoid setting it + } + + uint32_t mask = 1<nextServiceCycle = GetCycleCount() + microsecondsToClockCycles(1); + waveformToEnable |= mask; + if (!timerRunning) { + initTimer(); + timer1_write(microsecondsToClockCycles(10)); + } else { + // Ensure timely service.... + if (T1L > microsecondsToClockCycles(10)) { + timer1_write(microsecondsToClockCycles(10)); + } + } + while (waveformToEnable) { + delay(0); // Wait for waveform to update + } + } + + return true; +} + +// Speed critical bits +#pragma GCC optimize ("O2") +// Normally would not want two copies like this, but due to different +// optimization levels the inline attribute gets lost if we try the +// other version. + +static inline ICACHE_RAM_ATTR uint32_t GetCycleCountIRQ() { + uint32_t ccount; + __asm__ __volatile__("rsr %0,ccount":"=a"(ccount)); + return ccount; +} + +static inline ICACHE_RAM_ATTR uint32_t min_u32(uint32_t a, uint32_t b) { + if (a < b) { + return a; + } + return b; +} + +// Stops a waveform on a pin +int ICACHE_RAM_ATTR stopWaveform(uint8_t pin) { + // Can't possibly need to stop anything if there is no timer active + if (!timerRunning) { + return false; + } + // If user sends in a pin >16 but <32, this will always point to a 0 bit + // If they send >=32, then the shift will result in 0 and it will also return false + uint32_t mask = 1< microsecondsToClockCycles(10)) { + timer1_write(microsecondsToClockCycles(10)); + } + while (waveformToDisable) { + /* no-op */ // Can't delay() since stopWaveform may be called from an IRQ + } + if (!waveformEnabled && !timer1CB) { + deinitTimer(); + } + return true; +} + +// The SDK and hardware take some time to actually get to our NMI code, so +// decrement the next IRQ's timer value by a bit so we can actually catch the +// real CPU cycle counter we want for the waveforms. +#if F_CPU == 80000000 + #define DELTAIRQ (microsecondsToClockCycles(3)) +#else + #define DELTAIRQ (microsecondsToClockCycles(2)) +#endif + + +static ICACHE_RAM_ATTR void timer1Interrupt() { + // Optimize the NMI inner loop by keeping track of the min and max GPIO that we + // are generating. In the common case (1 PWM) these may be the same pin and + // we can avoid looking at the other pins. + static int startPin = 0; + static int endPin = 0; + + uint32_t nextEventCycles = microsecondsToClockCycles(MAXIRQUS); + uint32_t timeoutCycle = GetCycleCountIRQ() + microsecondsToClockCycles(14); + + if (waveformToEnable || waveformToDisable) { + // Handle enable/disable requests from main app. + waveformEnabled = (waveformEnabled & ~waveformToDisable) | waveformToEnable; // Set the requested waveforms on/off + waveformState &= ~waveformToEnable; // And clear the state of any just started + waveformToEnable = 0; + waveformToDisable = 0; + // Find the first GPIO being generated by checking GCC's find-first-set (returns 1 + the bit of the first 1 in an int32_t) + startPin = __builtin_ffs(waveformEnabled) - 1; + // Find the last bit by subtracting off GCC's count-leading-zeros (no offset in this one) + endPin = 32 - __builtin_clz(waveformEnabled); + } + + bool done = false; + if (waveformEnabled) { + do { + nextEventCycles = microsecondsToClockCycles(MAXIRQUS); + for (int i = startPin; i <= endPin; i++) { + uint32_t mask = 1<expiryCycle) { + int32_t expiryToGo = wave->expiryCycle - now; + if (expiryToGo < 0) { + // Done, remove! + waveformEnabled &= ~mask; + if (i == 16) { + GP16O &= ~1; + } else { + ClearGPIO(mask); + } + continue; + } + } + + // Check for toggles + int32_t cyclesToGo = wave->nextServiceCycle - now; + if (cyclesToGo < 0) { + waveformState ^= mask; + if (waveformState & mask) { + if (i == 16) { + GP16O |= 1; // GPIO16 write slow as it's RMW + } else { + SetGPIO(mask); + } + wave->nextServiceCycle = now + wave->nextTimeHighCycles + cyclesToGo; + nextEventCycles = min_u32(nextEventCycles, min_u32(wave->nextTimeHighCycles + cyclesToGo, 1)); + } else { + if (i == 16) { + GP16O &= ~1; // GPIO16 write slow as it's RMW + } else { + ClearGPIO(mask); + } + wave->nextServiceCycle = now + wave->nextTimeLowCycles + cyclesToGo; + nextEventCycles = min_u32(nextEventCycles, min_u32(wave->nextTimeLowCycles + cyclesToGo, 1)); + } + } else { + uint32_t deltaCycles = wave->nextServiceCycle - now; + nextEventCycles = min_u32(nextEventCycles, deltaCycles); + } + } + + // Exit the loop if we've hit the fixed runtime limit or the next event is known to be after that timeout would occur + uint32_t now = GetCycleCountIRQ(); + int32_t cycleDeltaNextEvent = timeoutCycle - (now + nextEventCycles); + int32_t cyclesLeftTimeout = timeoutCycle - now; + done = (cycleDeltaNextEvent < 0) || (cyclesLeftTimeout < 0); + } while (!done); + } // if (waveformEnabled) + + if (timer1CB) { + nextEventCycles = min_u32(nextEventCycles, timer1CB()); + } + + if (nextEventCycles < microsecondsToClockCycles(10)) { + nextEventCycles = microsecondsToClockCycles(10); + } + nextEventCycles -= DELTAIRQ; + + // Do it here instead of global function to save time and because we know it's edge-IRQ +#if F_CPU == 160000000 + T1L = nextEventCycles >> 1; // Already know we're in range by MAXIRQUS +#else + T1L = nextEventCycles; // Already know we're in range by MAXIRQUS +#endif + TEIE |= TEIE1; // Edge int enable +} + +}; + +#endif // ARDUINO_ESP8266_RELEASE \ No newline at end of file From b64abc9757e2ec211a4adedf5d6227e90a015bc6 Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 2 Feb 2020 17:44:26 +0100 Subject: [PATCH 110/160] dynamic sensor discovery --- tasmota/xsns_92_MI_HM10.ino | 204 +++++++++++++++++++++++------------- 1 file changed, 130 insertions(+), 74 deletions(-) diff --git a/tasmota/xsns_92_MI_HM10.ino b/tasmota/xsns_92_MI_HM10.ino index b91d75d31..8e1b1e699 100644 --- a/tasmota/xsns_92_MI_HM10.ino +++ b/tasmota/xsns_92_MI_HM10.ino @@ -70,26 +70,20 @@ struct { #pragma pack(0) struct mi_sensor_t{ - uint8_t type; //flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4 + uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4 uint8_t serial[6]; uint8_t showedUp; + float temp; //Flora, MJ_HT_V1, LYWSD0x union { struct { - float temp; float moisture; float fertility; uint16_t lux; - } Flora; + }; // Flora struct { - float temp; float hum; uint8_t bat; - } MJ_HT_V1; - struct { - float temp; - float hum; - uint8_t bat; - } LYWSD0x; // LYWSD02 and LYWSD03 + }; // MJ_HT_V1, LYWSD0x }; }; @@ -101,24 +95,21 @@ std::vector MIBLEsensors; #define D_CMND_HM10 "HM10" -// const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; -// const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s\"}"; -// const char kHM10_Commands[] PROGMEM = "Track|Play"; +uint8_t kHM10SlaveID[4][3] = { 0xC4,0x7C,0x8D, // Flora + 0x58,0x2D,0x34, // MJ_HT_V1 + 0xE7,0x2E,0x00, // LYWSD02 + 0xA4,0xC1,0x38, // LYWSD03 + }; -const char kHM10SlaveID0[] PROGMEM = ""; -const char kHM10SlaveID1[] PROGMEM = ""; -const char kHM10SlaveID2[] PROGMEM = ""; -const char kHM10SlaveID3[] PROGMEM = ""; -const char kHM10SlaveID4[] PROGMEM = "A4C138"; -const char * kHM10SlaveID[] PROGMEM = {kHM10SlaveID0,kHM10SlaveID1,kHM10SlaveID2,kHM10SlaveID3,kHM10SlaveID4}; +const char kHM10SlaveType1[] PROGMEM = "Flora"; +const char kHM10SlaveType2[] PROGMEM = "MJ_HT_V1"; +const char kHM10SlaveType3[] PROGMEM = "LYWSD02"; +const char kHM10SlaveType4[] PROGMEM = "LYWSD03"; +const char * kHM10SlaveType[] PROGMEM = {kHM10SlaveType1,kHM10SlaveType2,kHM10SlaveType3,kHM10SlaveType4}; -// const char kHM10Mac0[] PROGMEM = "A4C138ED815A"; -// const char kHM10Mac1[] PROGMEM = "A4C1382AC8B3"; -// const char * kHM10Mac[] PROGMEM ={kHM10Mac0, kHM10Mac1}; - -uint8_t HM10Mac[2][6]={0xA4,0xC1,0x38,0xED,0x81,0x5A, - 0xA4,0xC1,0x38,0x2A,0xC8,0xB3}; +// uint8_t HM10Mac[2][6]={0xA4,0xC1,0x38,0xED,0x81,0x5A, +// 0xA4,0xC1,0x38,0x2A,0xC8,0xB3}; /*********************************************************************************************\ * enumerations @@ -174,12 +165,12 @@ void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ HM10_TASK_LIST[slot][0] = task; } -void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disconnect +void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disconnect HM10_Launchtask(TASK_HM10_ROLE1,1,1); // set role to 1 HM10_Launchtask(TASK_HM10_IMME1,2,1); // set imme to 1 HM10_Launchtask(TASK_HM10_RESET,3,1); // reset Device - HM10_Launchtask(TASK_HM10_VERSION,4,10); // read SW Version - HM10_Launchtask(TASK_HM10_DISC,5,1); // disscovery + HM10_Launchtask(TASK_HM10_VERSION,4,10); // read SW Version + HM10_Launchtask(TASK_HM10_DISC,5,50); // discovery } void HM10_Read_Sensor(void) { @@ -206,10 +197,24 @@ void HM10_Read_Sensor1(void) { * @brief Return the slot number of a known sensor or return create new sensor slot * * @param _serial BLE address of the sensor - * @param _type Type number of the sensor + * @param _type Type number of the sensor, 0xff for Auto-type * @return uint32_t Known or new slot in the sensors-vector */ uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ + if(_type==0xff){ + DEBUG_SENSOR_LOG(PSTR("MIBLE: will test MAC-type")); + for (uint32_t i=0;i<4;i++){ + if(memcmp(_serial,kHM10SlaveID+i,3)==0){ + DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC is type %u"), i); + _type = i+1; + } + else { + DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC-type is unknown")); + } + } + } + if(_type==0xff) return _type; // error + DEBUG_SENSOR_LOG(PSTR("MIBLE: vector size %u"), MIBLEsensors.size()); for(uint32_t i=0; i= '0' && c <= '9') + value = (c - '0'); + else if (c >= 'A' && c <= 'F') + value = (10 + (c - 'A')); + _mac[(index/2)] += value << (((index + 1) % 2) * 4); + // DEBUG_SENSOR_LOG(PSTR("HM10: Char: %c, Value: %x, Index/2: %u, valueadded: %x, MAC-index: %x"), c, value,(index/2),value << (((index + 1) % 2) * 4), _mac[index/2]); + index++; + } + DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_mac[0],_mac[1],_mac[2],_mac[3],_mac[4],_mac[5]); +} + + /*********************************************************************************************\ * parse the response \*********************************************************************************************/ @@ -298,8 +317,18 @@ void HM10ParseResponse(char *buf) { memcpy((void *)_fw,(void *)(buf+8),3); HM10.firmware = atoi(_fw); DEBUG_SENSOR_LOG(PSTR("HM10: Firmware: %d"), HM10.firmware); + return; } - + char * _pos = strstr(buf, "IS0:"); + if(_pos) { + const char* _mac = "000000000000"; + memcpy((void *)_mac,(void *)(_pos+4),12); + DEBUG_SENSOR_LOG(PSTR("HM10: found Mac: %s"), _mac); + uint8_t _newMacArray[6] = {0}; + HM10datahex(_mac, _newMacArray); + DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]); + MIBLEgetSensorSlot(_newMacArray, 0xff); + } else { DEBUG_SENSOR_LOG(PSTR("HM10: empty response")); } @@ -311,16 +340,18 @@ void HM10readTempHum(char *_buf){ memcpy(&LYWSD03,(void *)_buf,3); DEBUG_SENSOR_LOG(PSTR("HM10: Temperature * 100: %u, Humidity: %u"),LYWSD03.temp,LYWSD03.hum); // uint8_t _serial[6] = {0}; - uint32_t _slot = MIBLEgetSensorSlot(HM10Mac[HM10.state.sensor], 4); + // uint32_t _slot = MIBLEgetSensorSlot(HM10Mac[HM10.state.sensor], 4); + uint32_t _slot = HM10.state.sensor; + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); static float _tempFloat; _tempFloat=(float)(LYWSD03.temp)/100.0f; if(_tempFloat<60){ - MIBLEsensors.at(_slot).LYWSD0x.temp=_tempFloat; + MIBLEsensors.at(_slot).temp=_tempFloat; } _tempFloat=(float)LYWSD03.hum; if(_tempFloat<100){ - MIBLEsensors.at(_slot).LYWSD0x.hum = _tempFloat; + MIBLEsensors.at(_slot).hum = _tempFloat; DEBUG_SENSOR_LOG(PSTR("LYWSD03: hum updated")); } } @@ -411,7 +442,7 @@ void HM10_TaskEvery100ms(){ runningTaskLoop = false; // HM10Serial->write("AT+CONA4C138ED815A"); char _con[20]; - sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",HM10Mac[HM10.state.sensor][0],HM10Mac[HM10.state.sensor][1],HM10Mac[HM10.state.sensor][2],HM10Mac[HM10.state.sensor][3],HM10Mac[HM10.state.sensor][4],HM10Mac[HM10.state.sensor][5]); + sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors.at(HM10.state.sensor).serial[0],MIBLEsensors.at(HM10.state.sensor).serial[1],MIBLEsensors.at(HM10.state.sensor).serial[2],MIBLEsensors.at(HM10.state.sensor).serial[3],MIBLEsensors.at(HM10.state.sensor).serial[4],MIBLEsensors.at(HM10.state.sensor).serial[5]); HM10Serial->write(_con); // HM10Serial->write(kHM10Mac[HM10.state.sensor]); break; @@ -505,17 +536,31 @@ void HM10EverySecond(){ if(HM10.firmware == 0) return; if(HM10.mode.pending_task == 1) return; static uint32_t _counter = 0; - if(_counter == 0) { - HM10_Read_Sensor1(); - HM10.mode.pending_task == 1; - _counter = 60; - HM10.state.sensor++; - if (HM10.state.sensor>1) { + if(_counter==0 && HM10.mode.pending_task==0) { + if (MIBLEsensors.size()>0) { + if(MIBLEsensors.at(HM10.state.sensor).type==3) { + HM10.mode.pending_task = 1; + HM10_Read_Sensor1(); + } + else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s active sensor not type 3: %u"),D_CMND_HM10, HM10.state.sensor); + } + } + else { + HM10.mode.pending_task = 1; + HM10_Launchtask(TASK_HM10_DISC,0,1); // start new discovery + return; + } + if (HM10.state.sensor==MIBLEsensors.size()-1) { HM10.state.sensor=0; + _counter = 60; + } + else { + HM10.state.sensor++; } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); } - _counter--; + if(_counter>0) _counter--; } /*********************************************************************************************\ @@ -525,29 +570,37 @@ void HM10EverySecond(){ const char HTTP_HM10[] PROGMEM = "{s}HM10" " Firmware " "{m}%u{e}"; +const char HTTP_HM10_SERIAL[] PROGMEM = + "{s}%s" " Address" "{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; + void HM10Show(bool json) { - if (json) { - if (MIBLEsensors.size()==0) return; - - char temperature[33]; - dtostrfd(MIBLEsensors.at(0).LYWSD0x.temp, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(MIBLEsensors.at(0).LYWSD0x.hum, Settings.flag2.humidity_resolution, humidity); - - ResponseAppend_P(JSON_SNS_TEMPHUM, F("LYWSD03"), temperature, humidity); + if (json) { + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + // char slave[33]; + // sprintf_P(slave,"%s-%02x%02x%02x",MIBLESlaveFlora,MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[0]); + char temperature[33]; // all sensors have temperature + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + if (MIBLEsensors.at(i).type>1){ + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + ResponseAppend_P(JSON_SNS_TEMPHUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, humidity); + } + } #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_HM10, HM10.firmware); - if (MIBLEsensors.size()==0) return; - - char temperature[33]; - dtostrfd(MIBLEsensors.at(0).LYWSD0x.temp, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(MIBLEsensors.at(0).LYWSD0x.hum, Settings.flag2.humidity_resolution, humidity); - - WSContentSend_PD(HTTP_SNS_TEMP, F("LYWSD03"), temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, F("LYWSD03"), humidity); + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + WSContentSend_PD(HTTP_HM10_SERIAL, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).serial[5], MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[0]); + char temperature[33]; + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + WSContentSend_PD(HTTP_SNS_TEMP, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); + if (MIBLEsensors.at(i).type>1){ // everything "above" Flora + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + WSContentSend_PD(HTTP_SNS_HUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], humidity); + } + } #endif // USE_WEBSERVER } } @@ -566,10 +619,13 @@ bool Xsns92(uint8_t function) case FUNC_INIT: HM10SerialInit(); // init and start communication break; + case FUNC_EVERY_50_MSECOND: + HM10SerialHandleFeedback(); // -> sniff for device feedback + break; case FUNC_EVERY_100_MSECOND: if (HM10_TASK_LIST[0][0] == TASK_HM10_NOTASK) { // no task running // DEBUG_SENSOR_LOG(PSTR("HM10: no TASK in array")); - HM10SerialHandleFeedback(); // -> sniff for device feedback + // HM10SerialHandleFeedback(); // -> sniff for device feedback break; } else { @@ -580,7 +636,7 @@ bool Xsns92(uint8_t function) break; case FUNC_EVERY_SECOND: HM10EverySecond(); - DEBUG_SENSOR_LOG(PSTR("HM10: every second")); + // DEBUG_SENSOR_LOG(PSTR("HM10: every second")); break; case FUNC_JSON_APPEND: HM10Show(1); From 02df35b6b5d9173e76fd3a5589c0672a1a7da441 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 2 Feb 2020 18:02:31 +0100 Subject: [PATCH 111/160] Safeguard if delay is too high --- tasmota/core_esp8266_waveform.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/core_esp8266_waveform.cpp b/tasmota/core_esp8266_waveform.cpp index 14cec9789..8ee2d9eba 100644 --- a/tasmota/core_esp8266_waveform.cpp +++ b/tasmota/core_esp8266_waveform.cpp @@ -262,6 +262,7 @@ static ICACHE_RAM_ATTR void timer1Interrupt() { // Check for toggles int32_t cyclesToGo = wave->nextServiceCycle - now; if (cyclesToGo < 0) { + cyclesToGo = -((-cyclesToGo) % (wave->nextTimeHighCycles + wave->nextTimeLowCycles)); waveformState ^= mask; if (waveformState & mask) { if (i == 16) { From 9ce92d7df8135f39a802a3e647a1c35488fcba06 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 2 Feb 2020 18:38:27 +0100 Subject: [PATCH 112/160] Fixed comment --- tasmota/core_esp8266_waveform.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tasmota/core_esp8266_waveform.cpp b/tasmota/core_esp8266_waveform.cpp index 8ee2d9eba..a17b63a9b 100644 --- a/tasmota/core_esp8266_waveform.cpp +++ b/tasmota/core_esp8266_waveform.cpp @@ -37,7 +37,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -// Use PWM from core 2.4.0 as all versions below 2.5.0-beta3 produce LED flickering when settings are saved to flash #include #if defined(ARDUINO_ESP8266_RELEASE_2_6_1) || defined(ARDUINO_ESP8266_RELEASE_2_6_2) || defined(ARDUINO_ESP8266_RELEASE_2_6_3) #warning **** Tasmota is using a patched PWM Arduino version as planned **** From 46e06a6fcb832f46cfa99fbd09213a4f473ad2bf Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 2 Feb 2020 19:07:31 +0100 Subject: [PATCH 113/160] error fixes --- tasmota/xsns_92_MI_HM10.ino | 112 ++++++++++++++++++++++++++---------- 1 file changed, 81 insertions(+), 31 deletions(-) diff --git a/tasmota/xsns_92_MI_HM10.ino b/tasmota/xsns_92_MI_HM10.ino index 8e1b1e699..18c101101 100644 --- a/tasmota/xsns_92_MI_HM10.ino +++ b/tasmota/xsns_92_MI_HM10.ino @@ -41,8 +41,6 @@ TasmotaSerial *HM10Serial; #define HM10_MAX_TASK_NUMBER 12 uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; // first value: kind of task - second value: delay in x * 100ms - - #define HM10_MAX_RX_BUF 512 char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; @@ -535,29 +533,27 @@ void HM10_TaskEvery100ms(){ void HM10EverySecond(){ if(HM10.firmware == 0) return; if(HM10.mode.pending_task == 1) return; - static uint32_t _counter = 0; - if(_counter==0 && HM10.mode.pending_task==0) { - if (MIBLEsensors.size()>0) { - if(MIBLEsensors.at(HM10.state.sensor).type==3) { - HM10.mode.pending_task = 1; - HM10_Read_Sensor1(); - } - else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s active sensor not type 3: %u"),D_CMND_HM10, HM10.state.sensor); - } - } - else { + if (MIBLEsensors.size()==0) { HM10.mode.pending_task = 1; HM10_Launchtask(TASK_HM10_DISC,0,1); // start new discovery return; + } + static uint32_t _counter = 0; + static uint32_t _nextSensorSlot = 0; + if(_counter==0) { + HM10.state.sensor = _nextSensorSlot; + _nextSensorSlot++; + if(MIBLEsensors.at(HM10.state.sensor).type==4) { + HM10.mode.pending_task = 1; + HM10_Read_Sensor1(); + } + else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s active sensor not type 3: %u"),D_CMND_HM10, HM10.state.sensor); } if (HM10.state.sensor==MIBLEsensors.size()-1) { - HM10.state.sensor=0; + _nextSensorSlot= 0; _counter = 60; } - else { - HM10.state.sensor++; - } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); } if(_counter>0) _counter--; @@ -573,32 +569,86 @@ const char HTTP_HM10[] PROGMEM = const char HTTP_HM10_SERIAL[] PROGMEM = "{s}%s" " Address" "{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; +const char HTTP_BATTERY[] PROGMEM = + "{s}%s" " Battery" "{m}%u%%{e}"; + +const char HTTP_HM10_FLORA_DATA[] PROGMEM = + "{s}%s" " Fertility" "{m}%sus/cm{e}"; + void HM10Show(bool json) { if (json) { for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - // char slave[33]; - // sprintf_P(slave,"%s-%02x%02x%02x",MIBLESlaveFlora,MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[0]); + char slave[33]; + sprintf_P(slave,"%s-%02x%02x%02x",kHM10SlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[0]); char temperature[33]; // all sensors have temperature dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - if (MIBLEsensors.at(i).type>1){ - char humidity[33]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - ResponseAppend_P(JSON_SNS_TEMPHUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, humidity); - } + + ResponseAppend_P(PSTR(",\"%s\":{"),slave); + if(MIBLEsensors.at(i).temp!=-1000.0f){ // this is the error code -> no temperature + ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); + } + if (MIBLEsensors.at(i).type==1){ + char lux[33]; + char moisture[33]; + char fertility[33]; + dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux); + dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture); + dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); + if(MIBLEsensors.at(i).lux!=0xffff){ // this is the error code -> no temperature + ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); + } + if(MIBLEsensors.at(i).moisture!=-1000.0f){ // this is the error code -> no temperature + ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture); + } + if(MIBLEsensors.at(i).fertility!=-1000.0f){ // this is the error code -> no temperature + ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility); + } + } + if (MIBLEsensors.at(i).type>1){ + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no temperature + ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); + } + if(MIBLEsensors.at(i).bat!=0xff){ // this is the error code -> no temperature + ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); + } + } + ResponseAppend_P(PSTR("}")); } #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_HM10, HM10.firmware); for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { WSContentSend_PD(HTTP_HM10_SERIAL, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).serial[5], MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[0]); - char temperature[33]; - dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - WSContentSend_PD(HTTP_SNS_TEMP, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); + if(MIBLEsensors.at(i).temp!=-1000.0f){ + char temperature[33]; + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + WSContentSend_PD(HTTP_SNS_TEMP, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); + } + if (MIBLEsensors.at(i).type==1){ + if(MIBLEsensors.at(i).lux!=0xffff){ // this is the error code -> no temperature + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); + } + if(MIBLEsensors.at(i).moisture!=-1000.0f){ // this is the error code -> no temperature + WSContentSend_PD(HTTP_SNS_MOISTURE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); + } + if(MIBLEsensors.at(i).fertility!=-1000.0f){ // this is the error code -> no temperature + char fertility[33]; + dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); + WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10SlaveType[MIBLEsensors.at(i).type-1], fertility); + } + } if (MIBLEsensors.at(i).type>1){ // everything "above" Flora - char humidity[33]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - WSContentSend_PD(HTTP_SNS_HUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], humidity); + if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no humidity + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + WSContentSend_PD(HTTP_SNS_HUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], humidity); + } + if(MIBLEsensors.at(i).bat!=0xff){ + WSContentSend_PD(HTTP_BATTERY, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); + } } } #endif // USE_WEBSERVER From 49ebd870ca256febaf74f7dbd33310cad2d4991e Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 2 Feb 2020 20:53:49 +0100 Subject: [PATCH 114/160] Add ``ZbBind`` (experimental) and bug fixes --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 1 + tasmota/xdrv_23_zigbee_3_devices.ino | 22 ++++- tasmota/xdrv_23_zigbee_5_converters.ino | 19 ++-- tasmota/xdrv_23_zigbee_8_parsers.ino | 3 + tasmota/xdrv_23_zigbee_9_impl.ino | 125 ++++++++++++++++++------ 6 files changed, 134 insertions(+), 37 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index b5036467c..4d2834a4e 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Change wifi connectivity stability (#7602) - Add ``SetOption84 1`` sends AWS IoT device shadow updates (alternative to retained) +- Add ``ZbBind`` (experimental) and bug fixes ### 8.1.0.4 20200116 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index fdf07acd6..d44030569 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -493,6 +493,7 @@ #define D_JSON_ZIGBEE_ZCL_SENT "ZbZCLSent" #define D_JSON_ZIGBEE_RECEIVED "ZbReceived" #define D_JSON_ZIGBEE_RECEIVED_LEGACY "ZigbeeReceived" +#define D_CMND_ZIGBEE_BIND "Bind" // Commands xdrv_25_A4988_Stepper.ino #define D_CMND_MOTOR "MOTOR" diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index 5db3986e4..984842380 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -71,6 +71,8 @@ public: uint16_t isKnownIndex(uint32_t index) const; uint16_t isKnownFriendlyName(const char * name) const; + uint64_t getDeviceLongAddr(uint16_t shortaddr) const; + // Add new device, provide ShortAddr and optional longAddr // If it is already registered, update information, otherwise create the entry void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); @@ -142,6 +144,7 @@ private: static int32_t findClusterEndpoint(const std::vector & vecOfElements, uint16_t element); Z_Device & getShortAddr(uint16_t shortaddr); // find Device from shortAddr, creates it if does not exist + const Z_Device & getShortAddrConst(uint16_t shortaddr) const ; // find Device from shortAddr, creates it if does not exist Z_Device & getLongAddr(uint64_t longaddr); // find Device from shortAddr, creates it if does not exist int32_t findShortAddr(uint16_t shortaddr) const; @@ -160,6 +163,9 @@ private: Z_Devices zigbee_devices = Z_Devices(); +// Local coordinator information +uint64_t localIEEEAddr = 0; + // https://thispointer.com/c-how-to-find-an-element-in-vector-and-get-its-index/ template < typename T> bool Z_Devices::findInVector(const std::vector & vecOfElements, const T & element) { @@ -326,6 +332,11 @@ uint16_t Z_Devices::isKnownFriendlyName(const char * name) const { } } +uint64_t Z_Devices::getDeviceLongAddr(uint16_t shortaddr) const { + const Z_Device & device = getShortAddrConst(shortaddr); + return device.longaddr; +} + // // We have a seen a shortaddr on the network, get the corresponding // @@ -335,9 +346,18 @@ Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) { if (found >= 0) { return _devices[found]; } -//Serial.printf("Device entry created for shortaddr = 0x%02X, found = %d\n", shortaddr, found); + //Serial.printf("Device entry created for shortaddr = 0x%02X, found = %d\n", shortaddr, found); return createDeviceEntry(shortaddr, 0); } +// Same version but Const +const Z_Device & Z_Devices::getShortAddrConst(uint16_t shortaddr) const { + if (!shortaddr) { return *(Z_Device*) nullptr; } // this is not legal + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + return _devices[found]; + } + return *((Z_Device*)nullptr); +} // find the Device object by its longaddr (unique key if not null) Z_Device & Z_Devices::getLongAddr(uint64_t longaddr) { diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 0518ec6be..fa79a0796 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -39,10 +39,10 @@ class ZCLFrame { public: ZCLFrame(uint8_t frame_control, uint16_t manuf_code, uint8_t transact_seq, uint8_t cmd_id, - const char *buf, size_t buf_len, uint16_t clusterid = 0, uint16_t groupid = 0, - uint16_t srcaddr = 0, uint8_t srcendpoint = 0, uint8_t dstendpoint = 0, uint8_t wasbroadcast = 0, - uint8_t linkquality = 0, uint8_t securityuse = 0, uint8_t seqnumber = 0, - uint32_t timestamp = 0): + const char *buf, size_t buf_len, uint16_t clusterid, uint16_t groupid, + uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, + uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, + uint32_t timestamp): _cmd_id(cmd_id), _manuf_code(manuf_code), _transact_seq(transact_seq), _payload(buf_len ? buf_len : 250), // allocate the data frame from source or preallocate big enough _cluster_id(clusterid), _group_id(groupid), @@ -74,9 +74,9 @@ public: } static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid, - uint16_t srcaddr = 0, uint8_t srcendpoint = 0, uint8_t dstendpoint = 0, uint8_t wasbroadcast = 0, - uint8_t linkquality = 0, uint8_t securityuse = 0, uint8_t seqnumber = 0, - uint32_t timestamp = 0) { // parse a raw frame and build the ZCL frame object + uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, + uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, + uint32_t timestamp) { // parse a raw frame and build the ZCL frame object uint32_t i = offset; ZCLHeaderFrameControl_t frame_control; uint16_t manuf_code = 0; @@ -92,7 +92,10 @@ public: cmd_id = buf.get8(i++); ZCLFrame zcl_frame(frame_control.d8, manuf_code, transact_seq, cmd_id, (const char *)(buf.buf() + i), len + offset - i, - clusterid, groupid); + clusterid, groupid, + srcaddr, srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber, + timestamp); return zcl_frame; } diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 74a900f00..668f85471 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -33,6 +33,9 @@ int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { uint8_t device_state = buf.get8(14); uint8_t device_associated = buf.get8(15); + // keep track of the local IEEE address + localIEEEAddr = long_adr; + char hex[20]; Uint64toHex(long_adr, hex, 64); Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 2b529c8d6..43f7a2ef4 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -33,19 +33,19 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME ; + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND ; const char kZigbeeCommands[] PROGMEM = D_PRFX_ZIGBEE "|" // legacy prefix -- deprecated D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME ; + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND ; void (* const ZigbeeCommand[])(void) PROGMEM = { - &CmndZigbeeZNPSend, &CmndZigbeePermitJoin, - &CmndZigbeeStatus, &CmndZigbeeReset, &CmndZigbeeSend, - &CmndZigbeeProbe, &CmndZigbeeRead, &CmndZigbeeZNPReceive, - &CmndZigbeeForget, &CmndZigbeeSave, &CmndZigbeeName + &CmndZbZNPSend, &CmndZbPermitJoin, + &CmndZbStatus, &CmndZbReset, &CmndZbSend, + &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, + &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind }; int32_t ZigbeeProcessInput(class SBuffer &buf) { @@ -257,7 +257,7 @@ const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM = { Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 /* len */, 0x01 /* STARTOPT_CLEAR_CONFIG */}; //"2605030101"; // Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 len, 0x01 STARTOPT_CLEAR_CONFIG // Do a factory reset of the CC2530 -void CmndZigbeeReset(void) { +void CmndZbReset(void) { if (ZigbeeSerial) { switch (XdrvMailbox.payload) { case 1: @@ -272,7 +272,7 @@ void CmndZigbeeReset(void) { } } -void CmndZigbeeZNPSendOrReceive(bool send) +void CmndZbZNPSendOrReceive(bool send) { if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { uint8_t code; @@ -300,14 +300,14 @@ void CmndZigbeeZNPSendOrReceive(bool send) } // For debug purposes only, simulates a message received -void CmndZigbeeZNPReceive(void) +void CmndZbZNPReceive(void) { - CmndZigbeeZNPSendOrReceive(false); + CmndZbZNPSendOrReceive(false); } -void CmndZigbeeZNPSend(void) +void CmndZbZNPSend(void) { - CmndZigbeeZNPSendOrReceive(true); + CmndZbZNPSendOrReceive(true); } void ZigbeeZNPSend(const uint8_t *msg, size_t len) { @@ -442,7 +442,7 @@ void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { ResponseCmndDone(); } -void CmndZigbeeSend(void) { +void CmndZbSend(void) { // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":1} } // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":"3"} } // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":"0xFF"} } @@ -465,9 +465,14 @@ void CmndZigbeeSend(void) { uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint String cmd_str = ""; // the actual low-level command, either specified or computed - const JsonVariant &val_device = getCaseInsensitive(json, PSTR("device")); - if (nullptr != &val_device) { device = strToUInt(val_device); } - const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("endpoint")); + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } + } + if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } + + const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } const JsonVariant &val_cmd = getCaseInsensitive(json, PSTR("Send")); if (nullptr != &val_cmd) { @@ -547,8 +552,64 @@ void CmndZigbeeSend(void) { } +ZBM(ZBS_BIND_REQ, Z_SREQ | Z_ZDO, ZDO_BIND_REQ, + 0,0, // dstAddr - 16 bits, device to send the bind to + 0,0,0,0,0,0,0,0, // srcAddr - 64 bits, IEEE binding source + 0x00, // source endpoint + 0x00, 0x00, // cluster + 0x03, // DstAddrMode - 0x03 = ADDRESS_64_BIT + 0,0,0,0,0,0,0,0, // dstAddr - 64 bits, IEEE binding destination, i.e. coordinator + 0x01 // dstEndpoint - 0x01 for coordinator +) + +void CmndZbBind(void) { + // ZbBind { "device":"0x1234", "endpoint":1, "cluster":6 } + + // local endpoint is always 1, IEEE addresses are calculated + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); + if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } + + // params + // static char delim[] = ", "; // delimiters for parameters + uint16_t device = 0xFFFF; // 0xFFFF is broadcast, so considered valid + uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint + uint16_t cluster = 0; // 0xFFFF is invalid + uint32_t group = 0xFFFFFFFF; // 16 bits values, otherwise 0xFFFFFFFF is unspecified + + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } + } + if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } + + const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); + if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } + const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); + if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } + + // TODO compute endpoint from cluster + + SBuffer buf(sizeof(ZBS_BIND_REQ)); + buf.add8(Z_SREQ | Z_ZDO); + buf.add8(ZDO_BIND_REQ); + buf.add16(device); + buf.add64(zigbee_devices.getDeviceLongAddr(device)); + buf.add8(endpoint); + buf.add16(cluster); + buf.add8(0x03); // DstAddrMode - 0x03 = ADDRESS_64_BIT + buf.add64(localIEEEAddr); // coordinatore IEEE address + buf.add8(0x01); // local endpoint = 1 + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); + + ResponseCmndDone(); +} + // Probe a specific device to get its endpoints and supported clusters -void CmndZigbeeProbe(void) { +void CmndZbProbe(void) { if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } @@ -560,7 +621,7 @@ void CmndZigbeeProbe(void) { } // Specify, read or erase a Friendly Name -void CmndZigbeeName(void) { +void CmndZbName(void) { // Syntax is: // ZigbeeName , - assign a friendly name // ZigbeeName - display the current friendly name @@ -589,7 +650,7 @@ void CmndZigbeeName(void) { } // Remove an old Zigbee device from the list of known devices, use ZigbeeStatus to know all registered devices -void CmndZigbeeForget(void) { +void CmndZbForget(void) { if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } @@ -604,7 +665,7 @@ void CmndZigbeeForget(void) { } // Save Zigbee information to flash -void CmndZigbeeSave(void) { +void CmndZbSave(void) { if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } saveZigbeeDevices(); @@ -613,7 +674,7 @@ void CmndZigbeeSave(void) { } // Send an attribute read command to a device, specifying cluster and list of attributes -void CmndZigbeeRead(void) { +void CmndZbRead(void) { // ZigbeeRead {"Device":"0xF289","Cluster":0,"Endpoint":3,"Attr":5} // ZigbeeRead {"Device":"0xF289","Cluster":"0x0000","Endpoint":"0x0003","Attr":"0x0005"} // ZigbeeRead {"Device":"0xF289","Cluster":0,"Endpoint":3,"Attr":[5,6,7,4]} @@ -629,10 +690,14 @@ void CmndZigbeeRead(void) { size_t attrs_len = 0; uint8_t* attrs = nullptr; // empty string is valid - const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); - if (nullptr != &val_device) { device = strToUInt(val_device); } - const JsonVariant val_cluster = getCaseInsensitive(json, PSTR("Cluster")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } + } + if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } + + const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } @@ -659,14 +724,18 @@ void CmndZigbeeRead(void) { } } - ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + if ((0 != endpoint) && (attrs_len > 0)) { + ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + ResponseCmndDone(); + } else { + ResponseCmndChar("Missing parameters"); + } if (attrs) { delete[] attrs; } - ResponseCmndDone(); } // Allow or Deny pairing of new Zigbee devices -void CmndZigbeePermitJoin(void) +void CmndZbPermitJoin(void) { if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } uint32_t payload = XdrvMailbox.payload; @@ -683,7 +752,7 @@ void CmndZigbeePermitJoin(void) ResponseCmndDone(); } -void CmndZigbeeStatus(void) { +void CmndZbStatus(void) { if (ZigbeeSerial) { if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); From 97f49246397c73883d902f8ccafb67f74f5e672f Mon Sep 17 00:00:00 2001 From: Hadinger Date: Mon, 3 Feb 2020 19:41:35 +0100 Subject: [PATCH 115/160] Change update IRRemoteESP8266 v2.7.3 --- .../CPPLINT.cfg | 0 .../LICENSE.txt | 0 .../README.md | 4 +- .../README_fr.md | 4 +- .../ReleaseNotes.md | 17 + .../SupportedProtocols.md | 29 +- .../CommonAcControl/CommonAcControl.ino | 0 .../examples/CommonAcControl/platformio.ini | 0 .../ControlSamsungAC/ControlSamsungAC.ino | 0 .../examples/ControlSamsungAC/platformio.ini | 0 .../DumbIRRepeater/DumbIRRepeater.ino | 3 + .../examples/DumbIRRepeater/platformio.ini | 0 .../examples/IRGCSendDemo/IRGCSendDemo.ino | 0 .../examples/IRGCSendDemo/platformio.ini | 0 .../examples/IRGCTCPServer/IRGCTCPServer.ino | 0 .../examples/IRGCTCPServer/platformio.ini | 0 .../examples/IRMQTTServer/IRMQTTServer.h | 1 + .../examples/IRMQTTServer/IRMQTTServer.ino | 2 +- .../examples/IRMQTTServer/platformio.ini | 0 .../examples/IRServer/IRServer.ino | 0 .../examples/IRServer/platformio.ini | 0 .../examples/IRrecvDemo/IRrecvDemo.ino | 1 + .../examples/IRrecvDemo/platformio.ini | 0 .../examples/IRrecvDump/IRrecvDump.ino | 0 .../examples/IRrecvDump/platformio.ini | 0 .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 1 + .../examples/IRrecvDumpV2/platformio.ini | 0 .../examples/IRsendDemo/IRsendDemo.ino | 0 .../examples/IRsendDemo/platformio.ini | 0 .../IRsendProntoDemo/IRsendProntoDemo.ino | 0 .../examples/IRsendProntoDemo/platformio.ini | 0 .../JVCPanasonicSendDemo.ino | 0 .../JVCPanasonicSendDemo/platformio.ini | 0 .../examples/LGACSend/LGACSend.ino | 0 .../examples/LGACSend/platformio.ini | 0 .../SmartIRRepeater/SmartIRRepeater.ino | 3 + .../examples/SmartIRRepeater/platformio.ini | 0 .../examples/TurnOnArgoAC/TurnOnArgoAC.ino | 0 .../examples/TurnOnArgoAC/platformio.ini | 0 .../TurnOnDaikinAC/TurnOnDaikinAC.ino | 0 .../examples/TurnOnDaikinAC/platformio.ini | 0 .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 0 .../examples/TurnOnFujitsuAC/platformio.ini | 0 .../TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino | 0 .../TurnOnKelvinatorAC/platformio.ini | 0 .../TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino | 0 .../TurnOnMitsubishiAC/platformio.ini | 0 .../TurnOnMitsubishiHeavyAc.ino | 0 .../TurnOnMitsubishiHeavyAc/platformio.ini | 0 .../TurnOnPanasonicAC/TurnOnPanasonicAC.ino | 0 .../examples/TurnOnPanasonicAC/platformio.ini | 0 .../TurnOnToshibaAC/TurnOnToshibaAC.ino | 0 .../examples/TurnOnToshibaAC/platformio.ini | 0 .../TurnOnTrotecAC/TurnOnTrotecAC.ino | 0 .../examples/TurnOnTrotecAC/platformio.ini | 0 .../examples/Web-AC-control/README.md | 0 .../Web-AC-control/Web-AC-control.ino | 0 .../examples/Web-AC-control/platformio.ini | 0 .../examples/Web-AC-control/printscreen.png | Bin .../Web-AC-control/upload/favicon.ico | Bin .../Web-AC-control/upload/level_1_off.svg | 0 .../Web-AC-control/upload/level_1_on.svg | 0 .../Web-AC-control/upload/level_2_off.svg | 0 .../Web-AC-control/upload/level_2_on.svg | 0 .../Web-AC-control/upload/level_3_off.svg | 0 .../Web-AC-control/upload/level_3_on.svg | 0 .../Web-AC-control/upload/level_4_off.svg | 0 .../Web-AC-control/upload/level_4_on.svg | 0 .../examples/Web-AC-control/upload/ui.html | 0 .../examples/Web-AC-control/upload/ui.js | 0 .../keywords.txt | 7 + .../library.json | 2 +- .../library.properties | 2 +- .../pylintrc | 0 .../src/CPPLINT.cfg | 0 .../src/IRac.cpp | 8 +- .../src/IRac.h | 3 +- .../src/IRrecv.cpp | 0 .../src/IRrecv.h | 0 .../src/IRremoteESP8266.h | 915 ++++++++++-------- .../src/IRsend.cpp | 6 + .../src/IRsend.h | 8 +- .../src/IRtext.cpp | 0 .../src/IRtext.h | 0 .../src/IRtimer.cpp | 0 .../src/IRtimer.h | 0 .../src/IRutils.cpp | 5 + .../src/IRutils.h | 0 .../src/i18n.h | 0 .../src/ir_Aiwa.cpp | 0 .../src/ir_Amcor.cpp | 0 .../src/ir_Amcor.h | 0 .../src/ir_Argo.cpp | 0 .../src/ir_Argo.h | 0 .../src/ir_Carrier.cpp | 0 .../src/ir_Coolix.cpp | 19 +- .../src/ir_Coolix.h | 0 .../src/ir_Daikin.cpp | 0 .../src/ir_Daikin.h | 0 .../src/ir_Denon.cpp | 0 .../src/ir_Dish.cpp | 0 .../src/ir_Electra.cpp | 0 .../src/ir_Electra.h | 2 + .../src/ir_Fujitsu.cpp | 0 .../src/ir_Fujitsu.h | 0 .../src/ir_GICable.cpp | 0 .../src/ir_GlobalCache.cpp | 0 .../src/ir_Goodweather.cpp | 0 .../src/ir_Goodweather.h | 0 .../src/ir_Gree.cpp | 0 .../src/ir_Gree.h | 0 .../src/ir_Haier.cpp | 0 .../src/ir_Haier.h | 0 .../src/ir_Hitachi.cpp | 0 .../src/ir_Hitachi.h | 0 .../src/ir_Inax.cpp | 0 .../src/ir_JVC.cpp | 0 .../src/ir_Kelvinator.cpp | 0 .../src/ir_Kelvinator.h | 0 .../src/ir_LG.cpp | 0 .../src/ir_LG.h | 0 .../src/ir_Lasertag.cpp | 0 .../src/ir_Lego.cpp | 0 .../src/ir_Lutron.cpp | 0 .../src/ir_MWM.cpp | 0 .../src/ir_Magiquest.cpp | 0 .../src/ir_Magiquest.h | 0 .../src/ir_Midea.cpp | 0 .../src/ir_Midea.h | 0 .../src/ir_Mitsubishi.cpp | 0 .../src/ir_Mitsubishi.h | 0 .../src/ir_MitsubishiHeavy.cpp | 0 .../src/ir_MitsubishiHeavy.h | 0 .../src/ir_NEC.cpp | 0 .../src/ir_NEC.h | 7 +- .../src/ir_Neoclima.cpp | 0 .../src/ir_Neoclima.h | 0 .../src/ir_Nikai.cpp | 0 .../src/ir_Panasonic.cpp | 32 +- .../src/ir_Panasonic.h | 18 +- .../src/ir_Pioneer.cpp | 0 .../src/ir_Pronto.cpp | 0 .../src/ir_RC5_RC6.cpp | 0 .../src/ir_RCMM.cpp | 0 .../src/ir_Samsung.cpp | 0 .../src/ir_Samsung.h | 0 .../src/ir_Sanyo.cpp | 0 .../src/ir_Sharp.cpp | 0 .../src/ir_Sharp.h | 0 .../src/ir_Sherwood.cpp | 0 .../src/ir_Sony.cpp | 52 +- .../src/ir_Tcl.cpp | 0 .../src/ir_Tcl.h | 0 .../src/ir_Teco.cpp | 0 .../src/ir_Teco.h | 0 .../src/ir_Toshiba.cpp | 0 .../src/ir_Toshiba.h | 0 .../src/ir_Trotec.cpp | 0 .../src/ir_Trotec.h | 0 .../src/ir_Vestel.cpp | 0 .../src/ir_Vestel.h | 0 .../src/ir_Whirlpool.cpp | 0 .../src/ir_Whirlpool.h | 0 .../src/ir_Whynter.cpp | 0 .../src/locale/README.md | 0 .../src/locale/de-CH.h | 0 .../src/locale/de-DE.h | 0 .../src/locale/defaults.h | 0 .../src/locale/en-AU.h | 0 .../src/locale/en-IE.h | 0 .../src/locale/en-UK.h | 0 .../src/locale/en-US.h | 0 .../src/locale/es-ES.h | 0 .../src/locale/fr-FR.h | 0 .../test/IRac_test.cpp | 103 +- .../test/IRrecv_test.cpp | 72 +- .../test/IRrecv_test.h | 0 .../test/IRsend_test.cpp | 0 .../test/IRsend_test.h | 0 .../test/IRutils_test.cpp | 0 .../test/Makefile | 0 .../test/ir_Aiwa_test.cpp | 0 .../test/ir_Amcor_test.cpp | 0 .../test/ir_Argo_test.cpp | 0 .../test/ir_Carrier_test.cpp | 0 .../test/ir_Coolix_test.cpp | 292 +++--- .../test/ir_Daikin_test.cpp | 0 .../test/ir_Denon_test.cpp | 0 .../test/ir_Dish_test.cpp | 0 .../test/ir_Electra_test.cpp | 0 .../test/ir_Fujitsu_test.cpp | 0 .../test/ir_GICable_test.cpp | 0 .../test/ir_GlobalCache_test.cpp | 0 .../test/ir_Goodweather_test.cpp | 0 .../test/ir_Gree_test.cpp | 0 .../test/ir_Haier_test.cpp | 0 .../test/ir_Hitachi_test.cpp | 0 .../test/ir_Inax_test.cpp | 0 .../test/ir_JVC_test.cpp | 0 .../test/ir_Kelvinator_test.cpp | 0 .../test/ir_LG_test.cpp | 0 .../test/ir_Lasertag_test.cpp | 0 .../test/ir_Lego_test.cpp | 0 .../test/ir_Lutron_test.cpp | 0 .../test/ir_MWM_test.cpp | 0 .../test/ir_Magiquest_test.cpp | 0 .../test/ir_Midea_test.cpp | 0 .../test/ir_MitsubishiHeavy_test.cpp | 0 .../test/ir_Mitsubishi_test.cpp | 0 .../test/ir_NEC_test.cpp | 0 .../test/ir_Neoclima_test.cpp | 0 .../test/ir_Nikai_test.cpp | 0 .../test/ir_Panasonic_test.cpp | 57 +- .../test/ir_Pioneer_test.cpp | 0 .../test/ir_Pronto_test.cpp | 0 .../test/ir_RC5_RC6_test.cpp | 0 .../test/ir_RCMM_test.cpp | 0 .../test/ir_Samsung_test.cpp | 0 .../test/ir_Sanyo_test.cpp | 0 .../test/ir_Sharp_test.cpp | 0 .../test/ir_Sherwood_test.cpp | 0 .../test/ir_Sony_test.cpp | 225 +++++ .../test/ir_Tcl_test.cpp | 0 .../test/ir_Teco_test.cpp | 0 .../test/ir_Toshiba_test.cpp | 0 .../test/ir_Trotec_test.cpp | 0 .../test/ir_Vestel_test.cpp | 0 .../test/ir_Whirlpool_test.cpp | 0 .../test/ir_Whynter_test.cpp | 0 .../tools/Makefile | 0 .../tools/RawToGlobalCache.sh | 0 .../tools/auto_analyse_raw_data.py | 26 +- .../tools/auto_analyse_raw_data_test.py | 218 +++++ .../tools/gc_decode.cpp | 0 .../tools/generate_irtext_h.sh | 0 .../tools/mkkeywords | 0 .../tools/mode2_decode.cpp | 0 .../tools/scrape_supported_devices.py | 76 +- platformio.ini | 9 + platformio_tasmota_env.ini | 4 +- tasmota/CHANGELOG.md | 1 + 241 files changed, 1504 insertions(+), 730 deletions(-) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/CPPLINT.cfg (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/LICENSE.txt (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/README.md (98%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/README_fr.md (98%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/ReleaseNotes.md (97%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/SupportedProtocols.md (91%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/CommonAcControl/CommonAcControl.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/CommonAcControl/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/ControlSamsungAC/ControlSamsungAC.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/ControlSamsungAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/DumbIRRepeater/DumbIRRepeater.ino (96%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/DumbIRRepeater/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRGCSendDemo/IRGCSendDemo.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRGCSendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRGCTCPServer/IRGCTCPServer.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRGCTCPServer/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRMQTTServer/IRMQTTServer.h (99%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRMQTTServer/IRMQTTServer.ino (99%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRMQTTServer/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRServer/IRServer.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRServer/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRrecvDemo/IRrecvDemo.ino (95%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRrecvDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRrecvDump/IRrecvDump.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRrecvDump/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRrecvDumpV2/IRrecvDumpV2.ino (98%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRrecvDumpV2/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRsendDemo/IRsendDemo.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRsendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRsendProntoDemo/IRsendProntoDemo.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/IRsendProntoDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/JVCPanasonicSendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/LGACSend/LGACSend.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/LGACSend/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/SmartIRRepeater/SmartIRRepeater.ino (96%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/SmartIRRepeater/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnArgoAC/TurnOnArgoAC.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnArgoAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnDaikinAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnFujitsuAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnKelvinatorAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnMitsubishiAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnMitsubishiHeavyAc/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnPanasonicAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnToshibaAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/TurnOnTrotecAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/README.md (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/Web-AC-control.ino (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/printscreen.png (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/favicon.ico (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/level_1_off.svg (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/level_1_on.svg (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/level_2_off.svg (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/level_2_on.svg (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/level_3_off.svg (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/level_3_on.svg (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/level_4_off.svg (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/level_4_on.svg (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/ui.html (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/examples/Web-AC-control/upload/ui.js (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/keywords.txt (99%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/library.json (97%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/library.properties (97%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/pylintrc (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/CPPLINT.cfg (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRac.cpp (99%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRac.h (99%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRrecv.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRrecv.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRremoteESP8266.h (54%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRsend.cpp (99%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRsend.h (98%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRtext.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRtext.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRtimer.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRtimer.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRutils.cpp (99%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/IRutils.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/i18n.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Aiwa.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Amcor.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Amcor.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Argo.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Argo.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Carrier.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Coolix.cpp (97%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Coolix.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Daikin.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Daikin.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Denon.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Dish.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Electra.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Electra.h (97%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Fujitsu.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Fujitsu.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_GICable.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_GlobalCache.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Goodweather.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Goodweather.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Gree.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Gree.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Haier.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Haier.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Hitachi.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Hitachi.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Inax.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_JVC.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Kelvinator.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Kelvinator.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_LG.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_LG.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Lasertag.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Lego.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Lutron.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_MWM.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Magiquest.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Magiquest.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Midea.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Midea.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Mitsubishi.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Mitsubishi.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_MitsubishiHeavy.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_MitsubishiHeavy.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_NEC.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_NEC.h (93%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Neoclima.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Neoclima.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Nikai.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Panasonic.cpp (97%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Panasonic.h (94%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Pioneer.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Pronto.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_RC5_RC6.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_RCMM.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Samsung.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Samsung.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Sanyo.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Sharp.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Sharp.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Sherwood.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Sony.cpp (74%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Tcl.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Tcl.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Teco.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Teco.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Toshiba.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Toshiba.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Trotec.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Trotec.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Vestel.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Vestel.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Whirlpool.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Whirlpool.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/ir_Whynter.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/locale/README.md (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/locale/de-CH.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/locale/de-DE.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/locale/defaults.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/locale/en-AU.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/locale/en-IE.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/locale/en-UK.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/locale/en-US.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/locale/es-ES.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/src/locale/fr-FR.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/IRac_test.cpp (95%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/IRrecv_test.cpp (95%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/IRrecv_test.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/IRsend_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/IRsend_test.h (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/IRutils_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/Makefile (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Aiwa_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Amcor_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Argo_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Carrier_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Coolix_test.cpp (69%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Daikin_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Denon_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Dish_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Electra_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Fujitsu_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_GICable_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_GlobalCache_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Goodweather_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Gree_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Haier_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Hitachi_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Inax_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_JVC_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Kelvinator_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_LG_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Lasertag_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Lego_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Lutron_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_MWM_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Magiquest_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Midea_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_MitsubishiHeavy_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Mitsubishi_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_NEC_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Neoclima_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Nikai_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Panasonic_test.cpp (96%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Pioneer_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Pronto_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_RC5_RC6_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_RCMM_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Samsung_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Sanyo_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Sharp_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Sherwood_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Sony_test.cpp (61%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Tcl_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Teco_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Toshiba_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Trotec_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Vestel_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Whirlpool_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/test/ir_Whynter_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/tools/Makefile (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/tools/RawToGlobalCache.sh (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/tools/auto_analyse_raw_data.py (97%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/tools/auto_analyse_raw_data_test.py (84%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/tools/gc_decode.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/tools/generate_irtext_h.sh (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/tools/mkkeywords (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/tools/mode2_decode.cpp (100%) rename lib/{IRremoteESP8266-2.7.2 => IRremoteESP8266-2.7.3}/tools/scrape_supported_devices.py (76%) diff --git a/lib/IRremoteESP8266-2.7.2/CPPLINT.cfg b/lib/IRremoteESP8266-2.7.3/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.7.2/CPPLINT.cfg rename to lib/IRremoteESP8266-2.7.3/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.7.2/LICENSE.txt b/lib/IRremoteESP8266-2.7.3/LICENSE.txt similarity index 100% rename from lib/IRremoteESP8266-2.7.2/LICENSE.txt rename to lib/IRremoteESP8266-2.7.3/LICENSE.txt diff --git a/lib/IRremoteESP8266-2.7.2/README.md b/lib/IRremoteESP8266-2.7.3/README.md similarity index 98% rename from lib/IRremoteESP8266-2.7.2/README.md rename to lib/IRremoteESP8266-2.7.3/README.md index 18066c612..9ca606af8 100644 --- a/lib/IRremoteESP8266-2.7.2/README.md +++ b/lib/IRremoteESP8266-2.7.3/README.md @@ -9,8 +9,8 @@ This library enables you to **send _and_ receive** infra-red signals on an [ESP8266](https://github.com/esp8266/Arduino) or an [ESP32](https://github.com/espressif/arduino-esp32) using the [Arduino framework](https://www.arduino.cc/) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* demodulators etc. -## v2.7.2 Now Available -Version 2.7.2 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. +## v2.7.3 Now Available +Version 2.7.3 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. #### Upgrading from pre-v2.0 Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/IRremoteESP8266-2.7.2/README_fr.md b/lib/IRremoteESP8266-2.7.3/README_fr.md similarity index 98% rename from lib/IRremoteESP8266-2.7.2/README_fr.md rename to lib/IRremoteESP8266-2.7.3/README_fr.md index 8dad47961..ca31b3b7b 100644 --- a/lib/IRremoteESP8266-2.7.2/README_fr.md +++ b/lib/IRremoteESP8266-2.7.3/README_fr.md @@ -9,8 +9,8 @@ Cette librairie vous permetra de **recevoir et d'envoyer des signaux** infrarouge sur le protocole [ESP8266](https://github.com/esp8266/Arduino) ou sur le protocole [ESP32](https://github.com/espressif/arduino-esp32) en utilisant le [Arduino framework](https://www.arduino.cc/) qui utilise la norme 940nm IR LEDs et le module basique de reception d'onde IR. Exemple : TSOP{17,22,24,36,38,44,48}* modules etc. -## v2.7.2 disponible -Version 2.7.2 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants. +## v2.7.3 disponible +Version 2.7.3 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants. #### mise à jour depuis pre-v2.0 L'utilisation de la librairie à un peu changer depuis la version in v2.0. Si vous voulez l'utiliser vous devrez changer votre utilisation aussi. Vous pouvez vous renseigner sur les précondition d'utilisation ici : [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/IRremoteESP8266-2.7.2/ReleaseNotes.md b/lib/IRremoteESP8266-2.7.3/ReleaseNotes.md similarity index 97% rename from lib/IRremoteESP8266-2.7.2/ReleaseNotes.md rename to lib/IRremoteESP8266-2.7.3/ReleaseNotes.md index 04dee7b81..a7218fc07 100644 --- a/lib/IRremoteESP8266-2.7.2/ReleaseNotes.md +++ b/lib/IRremoteESP8266-2.7.3/ReleaseNotes.md @@ -1,5 +1,22 @@ # Release Notes +## _v2.7.3 (20200130)_ + +**[Features]** +- Allow protocols to be enabled or disabled with compiler flags. (#1013, #1012) +- Panasonic AC: Add Ion Filter support for DKE models. (#1025, #1024) +- Add support for sending Sony at 38Khz (#1029, #1018, #1019) +- auto_analyse_raw_data.py: Handle analysing messages with no headers. (#1017) + +**[Misc]** +- Fix Coolix unit test errors when using Apple c++ compiler. (#1030, #1028) +- Fix Apple clang c++ compiler error in unit tests. (#1027, #1026) +- Improve/fix scraping of supported devices (#1022) +- Panasonic PKR series A/C uses DKE protocol. (#1020, #1021) +- Update NEC supported devices. (#1018) +- Add note to avoid GPIO16 on the ESP8266 for receiving. (#1016, #1015) + + ## _v2.7.2 (20200106)_ **[Bug Fixes]** diff --git a/lib/IRremoteESP8266-2.7.2/SupportedProtocols.md b/lib/IRremoteESP8266-2.7.3/SupportedProtocols.md similarity index 91% rename from lib/IRremoteESP8266-2.7.2/SupportedProtocols.md rename to lib/IRremoteESP8266-2.7.3/SupportedProtocols.md index 440fe8e20..c9b2f85c7 100644 --- a/lib/IRremoteESP8266-2.7.2/SupportedProtocols.md +++ b/lib/IRremoteESP8266-2.7.3/SupportedProtocols.md @@ -1,6 +1,6 @@ + Last generated: Thu Jan 30 20:05:33 2020 ---> # IR Protocols supported by this library | Protocol | Brand | Model | A/C Model | Detailed A/C Support | @@ -11,20 +11,20 @@ | [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **Carrier/Surrey** | 42QG5A55970 remote
53NGK009/012 Inverter
619EGX0090E0 A/C
619EGX0120E0 A/C
619EGX0180E0 A/C
619EGX0220E0 A/C | | - | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Beko](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | BINR 070/071 split-type A/C
BINR 070/071 split-type A/C
RG57K7(B)/BGEF Remote
RG57K7(B)/BGEF Remote | | Yes | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | MS12FU-10HRDN1-QRD0GW(B) A/C
MS12FU-10HRDN1-QRD0GW(B) A/C
MSABAU-07HRFN1-QRD0GW A/C (circa 2016)
MSABAU-07HRFN1-QRD0GW A/C (circa 2016)
RG52D/BGE Remote
RG52D/BGE Remote | | Yes | -| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Tokio](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | AATOEMF17-12CHR1SW split-type RG51|50/BGE Remote
AATOEMF17-12CHR1SW split-type RG51|50/BGE Remote | | Yes | +| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Tokio](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | AATOEMF17-12CHR1SW split-type RG51\|50/BGE Remote
AATOEMF17-12CHR1SW split-type RG51\|50/BGE Remote | | Yes | | [Daikin](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Daikin.cpp) | **[Daikin](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Daikin.h)** | 17 Series A/C (DAIKIN128)
ARC423A5 remote
ARC433** remote
ARC433B69 remote
ARC477A1 remote
ARC480A5 remote (DAIKIN152)
BRC4C153 remote
BRC52B63 remote (DAIKIN128)
FTE12HV2S A/C
FTXB09AXVJU A/C (DAIKIN128)
FTXB12AXVJU A/C (DAIKIN128)
FTXZ25NV1B A/C
FTXZ35NV1B A/C
FTXZ50NV1B A/C | | Yes | | [Denon](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Denon.cpp) | **Unknown** | | | - | | [Dish](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Dish.cpp) | **DISH NETWORK** | echostar 301 | | - | | [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[AUX](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | KFR-35GW/BpNFW=3 A/C
YKR-T/011 remote | | Yes | -| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AGTV14LAC A/C
AR-DB1 remote
AR-DL10 remote
AR-RAC1E remote
AR-RAE1E remote
AR-RAH2E remote
AR-REB1E remote
AR-RY4 remote
AST9RSGCW A/C
ASTB09LBC A/C
ASU30C1 A/C
ASYG30LFCA A/C
ASYG7LMCA A/C | | Yes | -| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AR-JW2 remote | | Yes | +| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AGTV14LAC A/C
AR-DB1 remote
AR-DL10 remote
AR-RAC1E remote
AR-RAE1E remote
AR-RAH2E remote
AR-REB1E remote
AR-RY4 remote
AST9RSGCW A/C
ASTB09LBC A/C
ASU30C1 A/C
ASYG30LFCA A/C
ASYG7LMCA A/C | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARRY4 | Yes | +| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AR-JW2 remote | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARRY4 | Yes | | [GICable](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GICable.cpp) | **Unknown** | | | - | | [GlobalCache](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GlobalCache.cpp) | **Unknown** | | | - | | [Goodweather](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Goodweather.cpp) | **[Goodweather](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Goodweather.h)** | ZH/JT-03 remote | | Yes | -| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[EKOKAI](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | A/C | | Yes | -| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Green](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | YBOFB remote
YBOFB2 remote | | Yes | -| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[RusClimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | EACS/I-09HAR_X/N3 A/C
YAW1F remote | | Yes | -| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Ultimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | Heat Pump | | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[EKOKAI](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | A/C | YAW1F
YBOFB | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Green](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | YBOFB remote
YBOFB2 remote | YAW1F
YBOFB | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[RusClimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | EACS/I-09HAR_X/N3 A/C
YAW1F remote | YAW1F
YBOFB | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Ultimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | Heat Pump | YAW1F
YBOFB | Yes | | [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | HSU-09HMC203 A/C
HSU07-HEA03 remote
YR-W02 remote | | Yes | | [Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.cpp) | **[Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.h)** | LT0541-HTA remote
RAR-8P2 remote
RAS-35THA6 remote
RAS-AJ25H A/C
Series VI A/C (Circa 2007) | | Yes | | [Inax](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Inax.cpp) | **Lixil** | Inax DT-BA283 Toilet | | - | @@ -45,10 +45,11 @@ | [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi Electric](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | 001CP T7WE10714 remote
KPOA remote
MSH-A24WV / MUH-A24WV A/C
PEAD-RP71JAA Ducted A/C | | Yes | | [MitsubishiHeavy](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.cpp) | **[Mitsubishi Heavy Industries](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.h)** | RKX502A001C remote
RLA502A700B remote
SRKxxZJ-S A/C
SRKxxZM-S A/C
SRKxxZMXA-S A/C | | Yes | | [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Aloka](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | SleepyLights LED Lamp | | - | +| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | 42TL838 LCD TV | | - | | [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Yamaha](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | RAV561 remote
RXV585B A/V Receiver | | - | | [Neoclima](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Neoclima.cpp) | **[Neoclima](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Neoclima.h)** | NS-09AHTI A/C
NS-09AHTI A/C
ZH/TY-01 remote
ZH/TY-01 remote | | Yes | | [Nikai](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Nikai.cpp) | **Unknown** | | | - | -| [Panasonic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Panasonic.cpp) | **[Panasonic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Panasonic.h)** | A75C2311 remote (CKP)
A75C3704 remote
A75C3747 remote
A75C3747 remote
A75C3747 remote
A75C3747 remote
CKP series A/C
CS-ME10CKPG A/C
CS-ME12CKPG A/C
CS-ME14CKPG A/C
CS-YW9MKD A/C
CS-Z9RKR A/C
DKE series A/C
JKE series A/C
NKE series A/C
RKR series A/C
TV | | Yes | +| [Panasonic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Panasonic.cpp) | **[Panasonic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Panasonic.h)** | A75C2311 remote (CKP)
A75C2616-1 remote (DKE)
A75C3704 remote
A75C3747 remote
CKP series A/C
CS-E7PKR A/C (DKE)
CS-ME10CKPG A/C
CS-ME12CKPG A/C
CS-ME14CKPG A/C
CS-YW9MKD A/C
CS-Z9RKR A/C
DKE series A/C
DKW series A/C (DKE)
JKE series A/C
NKE series A/C
PKR series A/C (DKE)
RKR series A/C
TV | CKP
DKE
JKE
LKE
NKE
RKR | Yes | | [Pioneer](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Pioneer.cpp) | **Unknown** | | | - | | [Pronto](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Pronto.cpp) | **Unknown** | | | - | | [RC5_RC6](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp) | **Unknown** | | | - | @@ -57,24 +58,23 @@ | [Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.cpp) | **Unknown** | | | - | | [Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.cpp) | **[Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.h)** | AY-ZP40KR A/C
LC-52D62U TV | | Yes | | [Sherwood](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sherwood.cpp) | **Sherwood** | RC-138 remote
RD6505(B) Receiver | | - | -| [Sony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sony.cpp) | **Unknown** | | | - | +| [Sony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sony.cpp) | **Sony** | HT-CT380 Soundbar (Uses 38kHz & 3 repeats) | | - | | [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Leberg](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | LBS-TOR07 A/C | | Yes | | [Teco](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.cpp) | **[Alaska](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.h)** | SAC9010QC A/C
SAC9010QC remote | | Yes | | [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | Akita EVO II
RAS 18SKP-ES
RAS-B13N3KV2
RAS-B13N3KVP-E
WC-L03SE
WH-TA04NE | | Yes | | [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Unknown](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | | | Yes | | [Vestel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Vestel.cpp) | **[Vestel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Vestel.h)** | BIOX CXP-9 A/C (9K BTU) | | Yes | -| [Whirlpool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whirlpool.cpp) | **[Whirlpool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whirlpool.h)** | DG11J1-04 remote
DG11J1-3A remote
DG11J1-91 remote
SPIS409L A/C
SPIS412L A/C
SPIW409L A/C
SPIW412L A/C
SPIW418L A/C | | Yes | +| [Whirlpool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whirlpool.cpp) | **[Whirlpool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whirlpool.h)** | DG11J1-04 remote
DG11J1-3A remote
DG11J1-91 remote
SPIS409L A/C
SPIS412L A/C
SPIW409L A/C
SPIW412L A/C
SPIW418L A/C | DG11J13A
DG11J191 | Yes | | [Whynter](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whynter.cpp) | **Whynter** | ARC-110WD A/C | | - | ## Send only protocols: - GLOBALCACHE -- MITSUBISHI112 - PRONTO - RAW - SHERWOOD -- TCL112AC +- SONY_38K ## Send & decodable protocols: @@ -115,6 +115,7 @@ - MAGIQUEST - MIDEA - MITSUBISHI +- MITSUBISHI112 - MITSUBISHI136 - MITSUBISHI2 - MITSUBISHI_AC @@ -140,10 +141,10 @@ - SHARP - SHARP_AC - SONY +- TCL112AC - TECO - TOSHIBA_AC - TROTEC - VESTEL_AC - WHIRLPOOL_AC - WHYNTER -- typeguess diff --git a/lib/IRremoteESP8266-2.7.2/examples/CommonAcControl/CommonAcControl.ino b/lib/IRremoteESP8266-2.7.3/examples/CommonAcControl/CommonAcControl.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/CommonAcControl/CommonAcControl.ino rename to lib/IRremoteESP8266-2.7.3/examples/CommonAcControl/CommonAcControl.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/CommonAcControl/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/CommonAcControl/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/CommonAcControl/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/CommonAcControl/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/ControlSamsungAC/ControlSamsungAC.ino b/lib/IRremoteESP8266-2.7.3/examples/ControlSamsungAC/ControlSamsungAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/ControlSamsungAC/ControlSamsungAC.ino rename to lib/IRremoteESP8266-2.7.3/examples/ControlSamsungAC/ControlSamsungAC.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/ControlSamsungAC/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/ControlSamsungAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/ControlSamsungAC/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/ControlSamsungAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/DumbIRRepeater/DumbIRRepeater.ino b/lib/IRremoteESP8266-2.7.3/examples/DumbIRRepeater/DumbIRRepeater.ino similarity index 96% rename from lib/IRremoteESP8266-2.7.2/examples/DumbIRRepeater/DumbIRRepeater.ino rename to lib/IRremoteESP8266-2.7.3/examples/DumbIRRepeater/DumbIRRepeater.ino index 80f5ce64a..d3ddbdb6a 100644 --- a/lib/IRremoteESP8266-2.7.2/examples/DumbIRRepeater/DumbIRRepeater.ino +++ b/lib/IRremoteESP8266-2.7.3/examples/DumbIRRepeater/DumbIRRepeater.ino @@ -37,6 +37,8 @@ * * Pin 0/D3: Can interfere with the boot/program mode & support circuits. * * Pin 1/TX/TXD0: Any serial transmissions from the ESP will interfere. * * Pin 3/RX/RXD0: Any serial transmissions to the ESP will interfere. + * * Pin 16/D0: Has no interrupts on the ESP8266, so can't be used for IR + * receiving with this library. * * ESP-01 modules are tricky. We suggest you use a module with more GPIOs * for your first time. e.g. ESP-12 etc. * @@ -54,6 +56,7 @@ // ==================== start of TUNEABLE PARAMETERS ==================== // The GPIO an IR detector/demodulator is connected to. Recommended: 14 (D5) +// Note: GPIO 16 won't work on the ESP8266 as it does not have interrupts. const uint16_t kRecvPin = 14; // GPIO to use to control the IR LED circuit. Recommended: 4 (D2). diff --git a/lib/IRremoteESP8266-2.7.2/examples/DumbIRRepeater/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/DumbIRRepeater/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/DumbIRRepeater/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/DumbIRRepeater/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRGCSendDemo/IRGCSendDemo.ino b/lib/IRremoteESP8266-2.7.3/examples/IRGCSendDemo/IRGCSendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRGCSendDemo/IRGCSendDemo.ino rename to lib/IRremoteESP8266-2.7.3/examples/IRGCSendDemo/IRGCSendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRGCSendDemo/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/IRGCSendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRGCSendDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/IRGCSendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRGCTCPServer/IRGCTCPServer.ino b/lib/IRremoteESP8266-2.7.3/examples/IRGCTCPServer/IRGCTCPServer.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRGCTCPServer/IRGCTCPServer.ino rename to lib/IRremoteESP8266-2.7.3/examples/IRGCTCPServer/IRGCTCPServer.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRGCTCPServer/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/IRGCTCPServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRGCTCPServer/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/IRGCTCPServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRMQTTServer/IRMQTTServer.h b/lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.h similarity index 99% rename from lib/IRremoteESP8266-2.7.2/examples/IRMQTTServer/IRMQTTServer.h rename to lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.h index c9d4898b9..0693a4908 100644 --- a/lib/IRremoteESP8266-2.7.2/examples/IRMQTTServer/IRMQTTServer.h +++ b/lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.h @@ -47,6 +47,7 @@ const int8_t kDefaultIrLed = 4; // <=- CHANGE_ME (optional) const bool kInvertTxOutput = false; // Default GPIO the IR demodulator is connected to/controlled by. GPIO 14 = D5. +// Note: GPIO 16 won't work on the ESP8266 as it does not have interrupts. const int8_t kDefaultIrRx = 14; // <=- CHANGE_ME (optional) // Enable/disable receiving/decoding IR messages entirely. diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRMQTTServer/IRMQTTServer.ino b/lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.ino similarity index 99% rename from lib/IRremoteESP8266-2.7.2/examples/IRMQTTServer/IRMQTTServer.ino rename to lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.ino index dfb1aa044..1824c660a 100644 --- a/lib/IRremoteESP8266-2.7.2/examples/IRMQTTServer/IRMQTTServer.ino +++ b/lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.ino @@ -271,7 +271,7 @@ * * #### Home Assistant MQTT Discovery * There is an option for this: 'Send MQTT Discovery' under the 'Admin' menu. - * It will produce a single MQTT Cliamte Discovery message for Home Assistant + * It will produce a single MQTT Climate Discovery message for Home Assistant * provided you have everything configured correctly here and in HA. * This message has MQTT RETAIN set on it, so it only ever needs to be sent * once or if the config details change etc. diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRMQTTServer/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRMQTTServer/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRServer/IRServer.ino b/lib/IRremoteESP8266-2.7.3/examples/IRServer/IRServer.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRServer/IRServer.ino rename to lib/IRremoteESP8266-2.7.3/examples/IRServer/IRServer.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRServer/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/IRServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRServer/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/IRServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRrecvDemo/IRrecvDemo.ino b/lib/IRremoteESP8266-2.7.3/examples/IRrecvDemo/IRrecvDemo.ino similarity index 95% rename from lib/IRremoteESP8266-2.7.2/examples/IRrecvDemo/IRrecvDemo.ino rename to lib/IRremoteESP8266-2.7.3/examples/IRrecvDemo/IRrecvDemo.ino index 5fd03f4b4..945f94055 100644 --- a/lib/IRremoteESP8266-2.7.2/examples/IRrecvDemo/IRrecvDemo.ino +++ b/lib/IRremoteESP8266-2.7.3/examples/IRrecvDemo/IRrecvDemo.ino @@ -23,6 +23,7 @@ // An IR detector/demodulator is connected to GPIO pin 14(D5 on a NodeMCU // board). +// Note: GPIO 16 won't work on the ESP8266 as it does not have interrupts. const uint16_t kRecvPin = 14; IRrecv irrecv(kRecvPin); diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/IRrecvDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRrecvDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/IRrecvDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRrecvDump/IRrecvDump.ino b/lib/IRremoteESP8266-2.7.3/examples/IRrecvDump/IRrecvDump.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRrecvDump/IRrecvDump.ino rename to lib/IRremoteESP8266-2.7.3/examples/IRrecvDump/IRrecvDump.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/IRrecvDump/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRrecvDump/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/IRrecvDump/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/IRremoteESP8266-2.7.3/examples/IRrecvDumpV2/IRrecvDumpV2.ino similarity index 98% rename from lib/IRremoteESP8266-2.7.2/examples/IRrecvDumpV2/IRrecvDumpV2.ino rename to lib/IRremoteESP8266-2.7.3/examples/IRrecvDumpV2/IRrecvDumpV2.ino index fc61f9b84..beed6c746 100644 --- a/lib/IRremoteESP8266-2.7.2/examples/IRrecvDumpV2/IRrecvDumpV2.ino +++ b/lib/IRremoteESP8266-2.7.3/examples/IRrecvDumpV2/IRrecvDumpV2.ino @@ -34,6 +34,7 @@ // ==================== start of TUNEABLE PARAMETERS ==================== // An IR detector/demodulator is connected to GPIO pin 14 // e.g. D5 on a NodeMCU board. +// Note: GPIO 16 won't work on the ESP8266 as it does not have interrupts. const uint16_t kRecvPin = 14; // The Serial connection baud rate. diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/IRrecvDumpV2/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRrecvDumpV2/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/IRrecvDumpV2/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRsendDemo/IRsendDemo.ino b/lib/IRremoteESP8266-2.7.3/examples/IRsendDemo/IRsendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRsendDemo/IRsendDemo.ino rename to lib/IRremoteESP8266-2.7.3/examples/IRsendDemo/IRsendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/IRsendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRsendDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/IRsendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRsendProntoDemo/IRsendProntoDemo.ino b/lib/IRremoteESP8266-2.7.3/examples/IRsendProntoDemo/IRsendProntoDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRsendProntoDemo/IRsendProntoDemo.ino rename to lib/IRremoteESP8266-2.7.3/examples/IRsendProntoDemo/IRsendProntoDemo.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/IRsendProntoDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/IRsendProntoDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/IRsendProntoDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib/IRremoteESP8266-2.7.3/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino rename to lib/IRremoteESP8266-2.7.3/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/JVCPanasonicSendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/JVCPanasonicSendDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/JVCPanasonicSendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/LGACSend/LGACSend.ino b/lib/IRremoteESP8266-2.7.3/examples/LGACSend/LGACSend.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/LGACSend/LGACSend.ino rename to lib/IRremoteESP8266-2.7.3/examples/LGACSend/LGACSend.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/LGACSend/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/LGACSend/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/LGACSend/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/LGACSend/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/SmartIRRepeater/SmartIRRepeater.ino b/lib/IRremoteESP8266-2.7.3/examples/SmartIRRepeater/SmartIRRepeater.ino similarity index 96% rename from lib/IRremoteESP8266-2.7.2/examples/SmartIRRepeater/SmartIRRepeater.ino rename to lib/IRremoteESP8266-2.7.3/examples/SmartIRRepeater/SmartIRRepeater.ino index 8dd202382..576abb516 100644 --- a/lib/IRremoteESP8266-2.7.2/examples/SmartIRRepeater/SmartIRRepeater.ino +++ b/lib/IRremoteESP8266-2.7.3/examples/SmartIRRepeater/SmartIRRepeater.ino @@ -40,6 +40,8 @@ * * Pin 0/D3: Can interfere with the boot/program mode & support circuits. * * Pin 1/TX/TXD0: Any serial transmissions from the ESP will interfere. * * Pin 3/RX/RXD0: Any serial transmissions to the ESP will interfere. + * * Pin 16/D0: Has no interrupts on the ESP8266, so can't be used for IR + * receiving with this library. * * ESP-01 modules are tricky. We suggest you use a module with more GPIOs * for your first time. e.g. ESP-12 etc. * @@ -57,6 +59,7 @@ // ==================== start of TUNEABLE PARAMETERS ==================== // The GPIO an IR detector/demodulator is connected to. Recommended: 14 (D5) +// Note: GPIO 16 won't work on the ESP8266 as it does not have interrupts. const uint16_t kRecvPin = 14; // GPIO to use to control the IR LED circuit. Recommended: 4 (D2). diff --git a/lib/IRremoteESP8266-2.7.2/examples/SmartIRRepeater/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/SmartIRRepeater/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/SmartIRRepeater/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/SmartIRRepeater/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnArgoAC/TurnOnArgoAC.ino b/lib/IRremoteESP8266-2.7.3/examples/TurnOnArgoAC/TurnOnArgoAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnArgoAC/TurnOnArgoAC.ino rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnArgoAC/TurnOnArgoAC.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/TurnOnArgoAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnArgoAC/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnArgoAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib/IRremoteESP8266-2.7.3/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/TurnOnDaikinAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnDaikinAC/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnDaikinAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/IRremoteESP8266-2.7.3/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/TurnOnFujitsuAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnFujitsuAC/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnFujitsuAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib/IRremoteESP8266-2.7.3/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/TurnOnKelvinatorAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnKelvinatorAC/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnKelvinatorAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnMitsubishiAC/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino b/lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnMitsubishiHeavyAc/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiHeavyAc/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnMitsubishiHeavyAc/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiHeavyAc/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino b/lib/IRremoteESP8266-2.7.3/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnPanasonicAC/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/TurnOnPanasonicAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnPanasonicAC/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnPanasonicAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino b/lib/IRremoteESP8266-2.7.3/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnToshibaAC/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/TurnOnToshibaAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnToshibaAC/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnToshibaAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino b/lib/IRremoteESP8266-2.7.3/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/TurnOnTrotecAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/TurnOnTrotecAC/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/TurnOnTrotecAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/README.md b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/README.md similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/README.md rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/README.md diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/Web-AC-control.ino b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/Web-AC-control.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/Web-AC-control.ino rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/Web-AC-control.ino diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/platformio.ini b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/platformio.ini rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/printscreen.png b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/printscreen.png similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/printscreen.png rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/printscreen.png diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/favicon.ico b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/favicon.ico similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/favicon.ico rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/favicon.ico diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_1_off.svg b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_1_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_1_off.svg rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_1_off.svg diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_1_on.svg b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_1_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_1_on.svg rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_1_on.svg diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_2_off.svg b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_2_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_2_off.svg rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_2_off.svg diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_2_on.svg b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_2_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_2_on.svg rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_2_on.svg diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_3_off.svg b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_3_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_3_off.svg rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_3_off.svg diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_3_on.svg b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_3_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_3_on.svg rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_3_on.svg diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_4_off.svg b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_4_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_4_off.svg rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_4_off.svg diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_4_on.svg b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_4_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/level_4_on.svg rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_4_on.svg diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/ui.html b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/ui.html similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/ui.html rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/ui.html diff --git a/lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/ui.js b/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/ui.js similarity index 100% rename from lib/IRremoteESP8266-2.7.2/examples/Web-AC-control/upload/ui.js rename to lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/ui.js diff --git a/lib/IRremoteESP8266-2.7.2/keywords.txt b/lib/IRremoteESP8266-2.7.3/keywords.txt similarity index 99% rename from lib/IRremoteESP8266-2.7.2/keywords.txt rename to lib/IRremoteESP8266-2.7.3/keywords.txt index 2c8018ea6..65b0d8b2e 100644 --- a/lib/IRremoteESP8266-2.7.2/keywords.txt +++ b/lib/IRremoteESP8266-2.7.3/keywords.txt @@ -84,6 +84,7 @@ _delayMicroseconds KEYWORD2 _getTime KEYWORD2 _getTimer KEYWORD2 _matchGeneric KEYWORD2 +_sendSony KEYWORD2 _setMode KEYWORD2 _setTemp KEYWORD2 _setTime KEYWORD2 @@ -459,6 +460,7 @@ sendSharpAc KEYWORD2 sendSharpRaw KEYWORD2 sendSherwood KEYWORD2 sendSony KEYWORD2 +sendSony38 KEYWORD2 sendTcl112Ac KEYWORD2 sendTeco KEYWORD2 sendToshibaAC KEYWORD2 @@ -1024,6 +1026,7 @@ SONY LITERAL1 SONY_12_BITS LITERAL1 SONY_15_BITS LITERAL1 SONY_20_BITS LITERAL1 +SONY_38K LITERAL1 TCL112AC LITERAL1 TECO LITERAL1 TIMEOUT_MS LITERAL1 @@ -2606,6 +2609,8 @@ kPanasonicAcFanMed LITERAL1 kPanasonicAcFanMin LITERAL1 kPanasonicAcFanModeTemp LITERAL1 kPanasonicAcHeat LITERAL1 +kPanasonicAcIonFilterByte LITERAL1 +kPanasonicAcIonFilterOffset LITERAL1 kPanasonicAcMaxTemp LITERAL1 kPanasonicAcMessageGap LITERAL1 kPanasonicAcMinTemp LITERAL1 @@ -2896,6 +2901,7 @@ kSlowStr LITERAL1 kSony12Bits LITERAL1 kSony15Bits LITERAL1 kSony20Bits LITERAL1 +kSonyAltFreq LITERAL1 kSonyHdrMark LITERAL1 kSonyHdrMarkTicks LITERAL1 kSonyMinBits LITERAL1 @@ -2908,6 +2914,7 @@ kSonyRptLength LITERAL1 kSonyRptLengthTicks LITERAL1 kSonySpace LITERAL1 kSonySpaceTicks LITERAL1 +kSonyStdFreq LITERAL1 kSonyTick LITERAL1 kSonyZeroMark LITERAL1 kSonyZeroMarkTicks LITERAL1 diff --git a/lib/IRremoteESP8266-2.7.2/library.json b/lib/IRremoteESP8266-2.7.3/library.json similarity index 97% rename from lib/IRremoteESP8266-2.7.2/library.json rename to lib/IRremoteESP8266-2.7.3/library.json index 4ade0fa6b..b28b1b218 100644 --- a/lib/IRremoteESP8266-2.7.2/library.json +++ b/lib/IRremoteESP8266-2.7.3/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.7.2", + "version": "2.7.3", "keywords": "infrared, ir, remote, esp8266, esp32", "description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)", "repository": diff --git a/lib/IRremoteESP8266-2.7.2/library.properties b/lib/IRremoteESP8266-2.7.3/library.properties similarity index 97% rename from lib/IRremoteESP8266-2.7.2/library.properties rename to lib/IRremoteESP8266-2.7.3/library.properties index b5d866c3d..b22e7f8cc 100644 --- a/lib/IRremoteESP8266-2.7.2/library.properties +++ b/lib/IRremoteESP8266-2.7.3/library.properties @@ -1,5 +1,5 @@ name=IRremoteESP8266 -version=2.7.2 +version=2.7.3 author=David Conran, Sebastien Warin, Mark Szabo, Ken Shirriff maintainer=Mark Szabo, David Conran, Sebastien Warin, Roi Dayan, Massimiliano Pinto sentence=Send and receive infrared signals with multiple protocols (ESP8266/ESP32) diff --git a/lib/IRremoteESP8266-2.7.2/pylintrc b/lib/IRremoteESP8266-2.7.3/pylintrc similarity index 100% rename from lib/IRremoteESP8266-2.7.2/pylintrc rename to lib/IRremoteESP8266-2.7.3/pylintrc diff --git a/lib/IRremoteESP8266-2.7.2/src/CPPLINT.cfg b/lib/IRremoteESP8266-2.7.3/src/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/CPPLINT.cfg rename to lib/IRremoteESP8266-2.7.3/src/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.7.2/src/IRac.cpp b/lib/IRremoteESP8266-2.7.3/src/IRac.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.2/src/IRac.cpp rename to lib/IRremoteESP8266-2.7.3/src/IRac.cpp index 5cb56b974..7b8b0f378 100644 --- a/lib/IRremoteESP8266-2.7.2/src/IRac.cpp +++ b/lib/IRremoteESP8266-2.7.3/src/IRac.cpp @@ -940,7 +940,8 @@ void IRac::panasonic(IRPanasonicAc *ac, const panasonic_ac_remote_model_t model, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, - const bool quiet, const bool turbo, const int16_t clock) { + const bool quiet, const bool turbo, const bool filter, + const int16_t clock) { ac->begin(); ac->setModel(model); ac->setPower(on); @@ -951,9 +952,9 @@ void IRac::panasonic(IRPanasonicAc *ac, const panasonic_ac_remote_model_t model, ac->setSwingHorizontal(ac->convertSwingH(swingh)); ac->setQuiet(quiet); ac->setPowerful(turbo); + ac->setIon(filter); // No Light setting available. // No Econo setting available. - // No Filter setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. @@ -1799,7 +1800,8 @@ int16_t IRac::strToModel(const char *str, const int16_t def) { return panasonic_ac_remote_model_t::kPanasonicLke; } else if (!strcasecmp(str, "NKE") || !strcasecmp(str, "PANASONICNKE")) { return panasonic_ac_remote_model_t::kPanasonicNke; - } else if (!strcasecmp(str, "DKE") || !strcasecmp(str, "PANASONICDKE")) { + } else if (!strcasecmp(str, "DKE") || !strcasecmp(str, "PANASONICDKE") || + !strcasecmp(str, "PKR") || !strcasecmp(str, "PANASONICPKR")) { return panasonic_ac_remote_model_t::kPanasonicDke; } else if (!strcasecmp(str, "JKE") || !strcasecmp(str, "PANASONICJKE")) { return panasonic_ac_remote_model_t::kPanasonicJke; diff --git a/lib/IRremoteESP8266-2.7.2/src/IRac.h b/lib/IRremoteESP8266-2.7.3/src/IRac.h similarity index 99% rename from lib/IRremoteESP8266-2.7.2/src/IRac.h rename to lib/IRremoteESP8266-2.7.3/src/IRac.h index 0f49943e4..4945bfac9 100644 --- a/lib/IRremoteESP8266-2.7.2/src/IRac.h +++ b/lib/IRremoteESP8266-2.7.3/src/IRac.h @@ -292,7 +292,8 @@ void electra(IRElectraAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, - const bool quiet, const bool turbo, const int16_t clock = -1); + const bool quiet, const bool turbo, const bool filter, + const int16_t clock = -1); #endif // SEND_PANASONIC_AC #if SEND_SAMSUNG_AC void samsung(IRSamsungAc *ac, diff --git a/lib/IRremoteESP8266-2.7.2/src/IRrecv.cpp b/lib/IRremoteESP8266-2.7.3/src/IRrecv.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/IRrecv.cpp rename to lib/IRremoteESP8266-2.7.3/src/IRrecv.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/IRrecv.h b/lib/IRremoteESP8266-2.7.3/src/IRrecv.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/IRrecv.h rename to lib/IRremoteESP8266-2.7.3/src/IRrecv.h diff --git a/lib/IRremoteESP8266-2.7.2/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.7.3/src/IRremoteESP8266.h similarity index 54% rename from lib/IRremoteESP8266-2.7.2/src/IRremoteESP8266.h rename to lib/IRremoteESP8266-2.7.3/src/IRremoteESP8266.h index 856ec880a..eb8a67f5c 100644 --- a/lib/IRremoteESP8266-2.7.2/src/IRremoteESP8266.h +++ b/lib/IRremoteESP8266-2.7.3/src/IRremoteESP8266.h @@ -52,428 +52,518 @@ #endif // UNIT_TEST // Library Version -#define _IRREMOTEESP8266_VERSION_ "2.7.2" +#define _IRREMOTEESP8266_VERSION_ "2.7.3" // Set the language & locale for the library. See the `locale` dir for options. #ifndef _IR_LOCALE_ #define _IR_LOCALE_ en-AU #endif // _IR_LOCALE_ +// Do we enable all the protocols by default (true), or disable them (false)? +// This allows users of the library to disable or enable all protocols at +// compile-time with `-D_IR_ENABLE_DEFAULT_=true` or +// `-D_IR_ENABLE_DEFAULT_=false` compiler flags respectively. +// Everything is included by default. +// e.g. If you only want to enable use of he NEC protocol to save program space, +// you would use something like: +// `-D_IR_ENABLE_DEFAULT_=false -DDECODE_NEC=true -DSEND_NEC=true` +// +// or alter your 'platform.ini' file accordingly: +// ``` +// build_flags = -D_IR_ENABLE_DEFAULT_=false +// -DDECODE_NEC=true +// -DSEND_NEC=true +// ``` +// If you want to enable support for every protocol *except* _decoding_ the +// Kelvinator protocol, you would use: +// `-DDECODE_KELVINATOR=false` +#ifndef _IR_ENABLE_DEFAULT_ +#define _IR_ENABLE_DEFAULT_ true // Unless set externally, the default is on. +#endif // _IR_ENABLE_DEFAULT_ + // Supported IR protocols // Each protocol you include costs memory and, during decode, costs time // Disable (set to false) all the protocols you do not need/want! // The Air Conditioner protocols are the most expensive memory-wise. // -#ifdef USE_IR_REMOTE_FULL // full IR protocols -#define DECODE_HASH true // Semi-unique code for unknown messages - -#define SEND_RAW true - -#define DECODE_NEC true -#define SEND_NEC true - -#define DECODE_SHERWOOD true // Doesn't exist. Actually is DECODE_NEC -#define SEND_SHERWOOD true - -#define DECODE_RC5 true -#define SEND_RC5 true - -#define DECODE_RC6 true -#define SEND_RC6 true - -#define DECODE_RCMM true -#define SEND_RCMM true - -#define DECODE_SONY true -#define SEND_SONY true - -#define DECODE_PANASONIC true -#define SEND_PANASONIC true - -#define DECODE_JVC true -#define SEND_JVC true - -#define DECODE_SAMSUNG true -#define SEND_SAMSUNG true - -#define DECODE_SAMSUNG36 true -#define SEND_SAMSUNG36 true - -#define DECODE_SAMSUNG_AC true -#define SEND_SAMSUNG_AC true - -#define DECODE_WHYNTER true -#define SEND_WHYNTER true - -#define DECODE_AIWA_RC_T501 true -#define SEND_AIWA_RC_T501 true - -#define DECODE_LG true -#define SEND_LG true - -#define DECODE_SANYO true -#define SEND_SANYO true - -#define DECODE_MITSUBISHI true -#define SEND_MITSUBISHI true - -#define DECODE_MITSUBISHI2 true -#define SEND_MITSUBISHI2 true - -#define DECODE_DISH true -#define SEND_DISH true - -#define DECODE_SHARP true -#define SEND_SHARP true - -#define DECODE_SHARP_AC true -#define SEND_SHARP_AC true - -#define DECODE_DENON true -#define SEND_DENON true - -#define DECODE_KELVINATOR true -#define SEND_KELVINATOR true - -#define DECODE_MITSUBISHI_AC true // Beta. -#define SEND_MITSUBISHI_AC true - -#define DECODE_MITSUBISHI136 true -#define SEND_MITSUBISHI136 true - -#define DECODE_MITSUBISHI112 true -#define SEND_MITSUBISHI112 true - -#define DECODE_FUJITSU_AC true -#define SEND_FUJITSU_AC true - -#define DECODE_INAX true -#define SEND_INAX true - -#define DECODE_DAIKIN true -#define SEND_DAIKIN true - -#define DECODE_COOLIX true -#define SEND_COOLIX true - -#define DECODE_GLOBALCACHE false // Not written. -#define SEND_GLOBALCACHE true - -#define DECODE_GOODWEATHER true -#define SEND_GOODWEATHER true - -#define DECODE_GREE true -#define SEND_GREE true - -#define DECODE_PRONTO false // Not written. -#define SEND_PRONTO true - -#define DECODE_ARGO true // Experimental -#define SEND_ARGO true - -#define DECODE_TROTEC true -#define SEND_TROTEC true - -#define DECODE_NIKAI true -#define SEND_NIKAI true - -#define DECODE_TOSHIBA_AC true -#define SEND_TOSHIBA_AC true - -#define DECODE_MAGIQUEST true -#define SEND_MAGIQUEST true - -#define DECODE_MIDEA true -#define SEND_MIDEA true - -#define DECODE_LASERTAG true -#define SEND_LASERTAG true - -#define DECODE_CARRIER_AC true -#define SEND_CARRIER_AC true - -#define DECODE_HAIER_AC true -#define SEND_HAIER_AC true - -#define DECODE_HITACHI_AC true -#define SEND_HITACHI_AC true - -#define DECODE_HITACHI_AC1 true -#define SEND_HITACHI_AC1 true - -#define DECODE_HITACHI_AC2 true -#define SEND_HITACHI_AC2 true - -#define DECODE_GICABLE true -#define SEND_GICABLE true - -#define DECODE_HAIER_AC_YRW02 true -#define SEND_HAIER_AC_YRW02 true - -#define DECODE_WHIRLPOOL_AC true -#define SEND_WHIRLPOOL_AC true - -#define DECODE_LUTRON true -#define SEND_LUTRON true - -#define DECODE_ELECTRA_AC true -#define SEND_ELECTRA_AC true - -#define DECODE_PANASONIC_AC true -#define SEND_PANASONIC_AC true - -#define DECODE_MWM true -#define SEND_MWM true - -#define DECODE_PIONEER true -#define SEND_PIONEER true - -#define DECODE_DAIKIN2 true -#define SEND_DAIKIN2 true - -#define DECODE_VESTEL_AC true -#define SEND_VESTEL_AC true - -#define DECODE_TECO true -#define SEND_TECO true - -#define DECODE_TCL112AC true -#define SEND_TCL112AC true - -#define DECODE_LEGOPF true -#define SEND_LEGOPF true - -#define DECODE_MITSUBISHIHEAVY true -#define SEND_MITSUBISHIHEAVY true - -#define DECODE_DAIKIN216 true -#define SEND_DAIKIN216 true - -#define DECODE_DAIKIN160 true -#define SEND_DAIKIN160 true - -#define DECODE_NEOCLIMA true -#define SEND_NEOCLIMA true - -#define DECODE_DAIKIN176 true -#define SEND_DAIKIN176 true - -#define DECODE_DAIKIN128 true -#define SEND_DAIKIN128 true - -#define DECODE_AMCOR true -#define SEND_AMCOR true - -#define DECODE_DAIKIN152 true -#define SEND_DAIKIN152 true - -#define DECODE_HITACHI_AC424 true -#define SEND_HITACHI_AC424 true - -#else // defined(FIRMWARE_IR) || defined(FIRMWARE_IR_CUSTOM) // full IR protocols - -// Tasmota supported protocols (less protocols is less code size) -#define DECODE_HASH true // Semi-unique code for unknown messages - -#define SEND_RAW false - -#define DECODE_NEC true -#define SEND_NEC true - -#define DECODE_SHERWOOD false // Doesn't exist. Actually is DECODE_NEC -#define SEND_SHERWOOD false - -#define DECODE_RC5 true -#define SEND_RC5 true - -#define DECODE_RC6 true -#define SEND_RC6 true - -#define DECODE_RCMM false -#define SEND_RCMM false - -#define DECODE_SONY false -#define SEND_SONY false - -#define DECODE_PANASONIC false -#define SEND_PANASONIC false - -#define DECODE_JVC false -#define SEND_JVC false - -#define DECODE_SAMSUNG false -#define SEND_SAMSUNG false - -#define DECODE_SAMSUNG36 false -#define SEND_SAMSUNG36 false - -#define DECODE_SAMSUNG_AC false -#define SEND_SAMSUNG_AC false - -#define DECODE_WHYNTER false -#define SEND_WHYNTER false - -#define DECODE_AIWA_RC_T501 false -#define SEND_AIWA_RC_T501 false - -#define DECODE_LG false -#define SEND_LG false - -#define DECODE_SANYO false -#define SEND_SANYO false - -#define DECODE_MITSUBISHI false -#define SEND_MITSUBISHI false - -#define DECODE_MITSUBISHI2 false -#define SEND_MITSUBISHI2 false - -#define DECODE_DISH false -#define SEND_DISH false - -#define DECODE_SHARP false -#define SEND_SHARP false - -#define DECODE_SHARP_AC false -#define SEND_SHARP_AC false - -#define DECODE_DENON false -#define SEND_DENON false - -#define DECODE_KELVINATOR false -#define SEND_KELVINATOR false - -#define DECODE_MITSUBISHI_AC false // Beta. -#define SEND_MITSUBISHI_AC false - -#define DECODE_FUJITSU_AC false -#define SEND_FUJITSU_AC false - -#define DECODE_INAX false -#define SEND_INAX false - -#define DECODE_DAIKIN false -#define SEND_DAIKIN false - -#define DECODE_COOLIX false -#define SEND_COOLIX false - -#define DECODE_GLOBALCACHE false // Not written. -#define SEND_GLOBALCACHE false - -#define DECODE_GOODWEATHER false -#define SEND_GOODWEATHER false - -#define DECODE_GREE false -#define SEND_GREE false - -#define DECODE_PRONTO false // Not written. -#define SEND_PRONTO false - -#define DECODE_ARGO false // Experimental -#define SEND_ARGO false - -#define DECODE_TROTEC false -#define SEND_TROTEC false - -#define DECODE_NIKAI false -#define SEND_NIKAI false - -#define DECODE_TOSHIBA_AC false -#define SEND_TOSHIBA_AC false - -#define DECODE_MAGIQUEST false -#define SEND_MAGIQUEST false - -#define DECODE_MIDEA false -#define SEND_MIDEA false - -#define DECODE_LASERTAG false -#define SEND_LASERTAG false - -#define DECODE_CARRIER_AC false -#define SEND_CARRIER_AC false - -#define DECODE_HAIER_AC false -#define SEND_HAIER_AC false - -#define DECODE_HITACHI_AC false -#define SEND_HITACHI_AC false - -#define DECODE_HITACHI_AC1 false -#define SEND_HITACHI_AC1 false - -#define DECODE_HITACHI_AC2 false -#define SEND_HITACHI_AC2 false - -#define DECODE_GICABLE false -#define SEND_GICABLE false - -#define DECODE_HAIER_AC_YRW02 false -#define SEND_HAIER_AC_YRW02 false - -#define DECODE_WHIRLPOOL_AC false -#define SEND_WHIRLPOOL_AC false - -#define DECODE_LUTRON false -#define SEND_LUTRON false - -#define DECODE_ELECTRA_AC false -#define SEND_ELECTRA_AC false - -#define DECODE_PANASONIC_AC false -#define SEND_PANASONIC_AC false - -#define DECODE_MWM false -#define SEND_MWM false - -#define DECODE_PIONEER false -#define SEND_PIONEER false - -#define DECODE_DAIKIN2 false -#define SEND_DAIKIN2 false - -#define DECODE_VESTEL_AC false -#define SEND_VESTEL_AC false - -#define DECODE_TECO false -#define SEND_TECO false - -#define DECODE_TCL112AC false -#define SEND_TCL112AC false - -#define DECODE_LEGOPF false -#define SEND_LEGOPF false - -#define DECODE_MITSUBISHIHEAVY false -#define SEND_MITSUBISHIHEAVY false - -#define DECODE_DAIKIN216 false -#define SEND_DAIKIN216 false - -#define DECODE_DAIKIN160 false -#define SEND_DAIKIN160 false - -#define DECODE_NEOCLIMA false -#define SEND_NEOCLIMA false - -#define DECODE_DAIKIN176 false -#define SEND_DAIKIN176 false - -#define DECODE_DAIKIN128 false -#define SEND_DAIKIN128 false - -#define DECODE_AMCOR false -#define SEND_AMCOR false - -#define DECODE_DAIKIN152 false -#define SEND_DAIKIN152 false - -#define DECODE_HITACHI_AC424 false -#define SEND_HITACHI_AC424 false - -#endif // defined(FIRMWARE_IR) || defined(FIRMWARE_IR_CUSTOM) // full IR protocols +// Semi-unique code for unknown messages +#ifndef DECODE_HASH +#define DECODE_HASH _IR_ENABLE_DEFAULT_ +#endif // DECODE_HASH + +#ifndef SEND_RAW +#define SEND_RAW _IR_ENABLE_DEFAULT_ +#endif // SEND_RAW + +#ifndef DECODE_NEC +#define DECODE_NEC _IR_ENABLE_DEFAULT_ +#endif // DECODE_NEC +#ifndef SEND_NEC +#define SEND_NEC _IR_ENABLE_DEFAULT_ +#endif // SEND_NEC + +#ifndef DECODE_SHERWOOD +#define DECODE_SHERWOOD false // Not applicable. Actually is DECODE_NEC +#endif // DECODE_SHERWOOD +#ifndef SEND_SHERWOOD +#define SEND_SHERWOOD _IR_ENABLE_DEFAULT_ +#endif // SEND_SHERWOOD + +#ifndef DECODE_RC5 +#define DECODE_RC5 _IR_ENABLE_DEFAULT_ +#endif // DECODE_RC5 +#ifndef SEND_RC5 +#define SEND_RC5 _IR_ENABLE_DEFAULT_ +#endif // SEND_RC5 + +#ifndef DECODE_RC6 +#define DECODE_RC6 _IR_ENABLE_DEFAULT_ +#endif // DECODE_RC6 +#ifndef SEND_RC6 +#define SEND_RC6 _IR_ENABLE_DEFAULT_ +#endif // SEND_RC6 + +#ifndef DECODE_RCMM +#define DECODE_RCMM _IR_ENABLE_DEFAULT_ +#endif // DECODE_RCMM +#ifndef SEND_RCMM +#define SEND_RCMM _IR_ENABLE_DEFAULT_ +#endif // SEND_RCMM + +#ifndef DECODE_SONY +#define DECODE_SONY _IR_ENABLE_DEFAULT_ +#endif // DECODE_SONY +#ifndef SEND_SONY +#define SEND_SONY _IR_ENABLE_DEFAULT_ +#endif // SEND_SONY + +#ifndef DECODE_PANASONIC +#define DECODE_PANASONIC _IR_ENABLE_DEFAULT_ +#endif // DECODE_PANASONIC +#ifndef SEND_PANASONIC +#define SEND_PANASONIC _IR_ENABLE_DEFAULT_ +#endif // SEND_PANASONIC + +#ifndef DECODE_JVC +#define DECODE_JVC _IR_ENABLE_DEFAULT_ +#endif // DECODE_JVC +#ifndef SEND_JVC +#define SEND_JVC _IR_ENABLE_DEFAULT_ +#endif // SEND_JVC + +#ifndef DECODE_SAMSUNG +#define DECODE_SAMSUNG _IR_ENABLE_DEFAULT_ +#endif // DECODE_SAMSUNG +#ifndef SEND_SAMSUNG +#define SEND_SAMSUNG _IR_ENABLE_DEFAULT_ +#endif // SEND_SAMSUNG + +#ifndef DECODE_SAMSUNG36 +#define DECODE_SAMSUNG36 _IR_ENABLE_DEFAULT_ +#endif // DECODE_SAMSUNG36 +#ifndef SEND_SAMSUNG36 +#define SEND_SAMSUNG36 _IR_ENABLE_DEFAULT_ +#endif // SEND_SAMSUNG36 + +#ifndef DECODE_SAMSUNG_AC +#define DECODE_SAMSUNG_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_SAMSUNG_AC +#ifndef SEND_SAMSUNG_AC +#define SEND_SAMSUNG_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_SAMSUNG_AC + +#ifndef DECODE_WHYNTER +#define DECODE_WHYNTER _IR_ENABLE_DEFAULT_ +#endif // DECODE_WHYNTER +#ifndef SEND_WHYNTER +#define SEND_WHYNTER _IR_ENABLE_DEFAULT_ +#endif // SEND_WHYNTER + +#ifndef DECODE_AIWA_RC_T501 +#define DECODE_AIWA_RC_T501 _IR_ENABLE_DEFAULT_ +#endif // DECODE_AIWA_RC_T501 +#ifndef SEND_AIWA_RC_T501 +#define SEND_AIWA_RC_T501 _IR_ENABLE_DEFAULT_ +#endif // SEND_AIWA_RC_T501 + +#ifndef DECODE_LG +#define DECODE_LG _IR_ENABLE_DEFAULT_ +#endif // DECODE_LG +#ifndef SEND_LG +#define SEND_LG _IR_ENABLE_DEFAULT_ +#endif // SEND_LG + +#ifndef DECODE_SANYO +#define DECODE_SANYO _IR_ENABLE_DEFAULT_ +#endif // DECODE_SANYO +#ifndef SEND_SANYO +#define SEND_SANYO _IR_ENABLE_DEFAULT_ +#endif // SEND_SANYO + +#ifndef DECODE_MITSUBISHI +#define DECODE_MITSUBISHI _IR_ENABLE_DEFAULT_ +#endif // DECODE_MITSUBISHI +#ifndef SEND_MITSUBISHI +#define SEND_MITSUBISHI _IR_ENABLE_DEFAULT_ +#endif // SEND_MITSUBISHI + +#ifndef DECODE_MITSUBISHI2 +#define DECODE_MITSUBISHI2 _IR_ENABLE_DEFAULT_ +#endif // DECODE_MITSUBISHI2 +#ifndef SEND_MITSUBISHI2 +#define SEND_MITSUBISHI2 _IR_ENABLE_DEFAULT_ +#endif // SEND_MITSUBISHI2 + +#ifndef DECODE_DISH +#define DECODE_DISH _IR_ENABLE_DEFAULT_ +#endif // DECODE_DISH +#ifndef SEND_DISH +#define SEND_DISH _IR_ENABLE_DEFAULT_ +#endif // SEND_DISH + +#ifndef DECODE_SHARP +#define DECODE_SHARP _IR_ENABLE_DEFAULT_ +#endif // DECODE_SHARP +#ifndef SEND_SHARP +#define SEND_SHARP _IR_ENABLE_DEFAULT_ +#endif // SEND_SHARP + +#ifndef DECODE_SHARP_AC +#define DECODE_SHARP_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_SHARP_AC +#ifndef SEND_SHARP_AC +#define SEND_SHARP_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_SHARP_AC + +#ifndef DECODE_DENON +#define DECODE_DENON _IR_ENABLE_DEFAULT_ +#endif // DECODE_DENON +#ifndef SEND_DENON +#define SEND_DENON _IR_ENABLE_DEFAULT_ +#endif // SEND_DENON + +#ifndef DECODE_KELVINATOR +#define DECODE_KELVINATOR _IR_ENABLE_DEFAULT_ +#endif // DECODE_KELVINATOR +#ifndef SEND_KELVINATOR +#define SEND_KELVINATOR _IR_ENABLE_DEFAULT_ +#endif // SEND_KELVINATOR + +#ifndef DECODE_MITSUBISHI_AC +#define DECODE_MITSUBISHI_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_MITSUBISHI_AC +#ifndef SEND_MITSUBISHI_AC +#define SEND_MITSUBISHI_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_MITSUBISHI_AC + +#ifndef DECODE_MITSUBISHI136 +#define DECODE_MITSUBISHI136 _IR_ENABLE_DEFAULT_ +#endif // DECODE_MITSUBISHI136 +#ifndef SEND_MITSUBISHI136 +#define SEND_MITSUBISHI136 _IR_ENABLE_DEFAULT_ +#endif // SEND_MITSUBISHI136 + +#ifndef DECODE_MITSUBISHI112 +#define DECODE_MITSUBISHI112 _IR_ENABLE_DEFAULT_ +#endif // DECODE_MITSUBISHI112 +#ifndef SEND_MITSUBISHI112 +#define SEND_MITSUBISHI112 _IR_ENABLE_DEFAULT_ +#endif // SEND_MITSUBISHI112 + +#ifndef DECODE_FUJITSU_AC +#define DECODE_FUJITSU_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_FUJITSU_AC +#ifndef SEND_FUJITSU_AC +#define SEND_FUJITSU_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_FUJITSU_AC + +#ifndef DECODE_INAX +#define DECODE_INAX _IR_ENABLE_DEFAULT_ +#endif // DECODE_INAX +#ifndef SEND_INAX +#define SEND_INAX _IR_ENABLE_DEFAULT_ +#endif // SEND_INAX + +#ifndef DECODE_DAIKIN +#define DECODE_DAIKIN _IR_ENABLE_DEFAULT_ +#endif // DECODE_DAIKIN +#ifndef SEND_DAIKIN +#define SEND_DAIKIN _IR_ENABLE_DEFAULT_ +#endif // SEND_DAIKIN + +#ifndef DECODE_COOLIX +#define DECODE_COOLIX _IR_ENABLE_DEFAULT_ +#endif // DECODE_COOLIX +#ifndef SEND_COOLIX +#define SEND_COOLIX _IR_ENABLE_DEFAULT_ +#endif // SEND_COOLIX + +#ifndef DECODE_GLOBALCACHE +#define DECODE_GLOBALCACHE false // Not applicable. +#endif // DECODE_GLOBALCACHE +#ifndef SEND_GLOBALCACHE +#define SEND_GLOBALCACHE _IR_ENABLE_DEFAULT_ +#endif // SEND_GLOBALCACHE + +#ifndef DECODE_GOODWEATHER +#define DECODE_GOODWEATHER _IR_ENABLE_DEFAULT_ +#endif // DECODE_GOODWEATHER +#ifndef SEND_GOODWEATHER +#define SEND_GOODWEATHER _IR_ENABLE_DEFAULT_ +#endif // SEND_GOODWEATHER + +#ifndef DECODE_GREE +#define DECODE_GREE _IR_ENABLE_DEFAULT_ +#endif // DECODE_GREE +#ifndef SEND_GREE +#define SEND_GREE _IR_ENABLE_DEFAULT_ +#endif // SEND_GREE + +#ifndef DECODE_PRONTO +#define DECODE_PRONTO false // Not applicable. +#endif // DECODE_PRONTO +#ifndef SEND_PRONTO +#define SEND_PRONTO _IR_ENABLE_DEFAULT_ +#endif // SEND_PRONTO + +#ifndef DECODE_ARGO +#define DECODE_ARGO _IR_ENABLE_DEFAULT_ +#endif // DECODE_ARGO +#ifndef SEND_ARGO +#define SEND_ARGO _IR_ENABLE_DEFAULT_ +#endif // SEND_ARGO + +#ifndef DECODE_TROTEC +#define DECODE_TROTEC _IR_ENABLE_DEFAULT_ +#endif // DECODE_TROTEC +#ifndef SEND_TROTEC +#define SEND_TROTEC _IR_ENABLE_DEFAULT_ +#endif // SEND_TROTEC + +#ifndef DECODE_NIKAI +#define DECODE_NIKAI _IR_ENABLE_DEFAULT_ +#endif // DECODE_NIKAI +#ifndef SEND_NIKAI +#define SEND_NIKAI _IR_ENABLE_DEFAULT_ +#endif // SEND_NIKAI + +#ifndef DECODE_TOSHIBA_AC +#define DECODE_TOSHIBA_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_TOSHIBA_AC +#ifndef SEND_TOSHIBA_AC +#define SEND_TOSHIBA_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_TOSHIBA_AC + +#ifndef DECODE_MAGIQUEST +#define DECODE_MAGIQUEST _IR_ENABLE_DEFAULT_ +#endif // DECODE_MAGIQUEST +#ifndef SEND_MAGIQUEST +#define SEND_MAGIQUEST _IR_ENABLE_DEFAULT_ +#endif // SEND_MAGIQUEST + +#ifndef DECODE_MIDEA +#define DECODE_MIDEA _IR_ENABLE_DEFAULT_ +#endif // DECODE_MIDEA +#ifndef SEND_MIDEA +#define SEND_MIDEA _IR_ENABLE_DEFAULT_ +#endif // SEND_MIDEA + +#ifndef DECODE_LASERTAG +#define DECODE_LASERTAG _IR_ENABLE_DEFAULT_ +#endif // DECODE_LASERTAG +#ifndef SEND_LASERTAG +#define SEND_LASERTAG _IR_ENABLE_DEFAULT_ +#endif // SEND_LASERTAG + +#ifndef DECODE_CARRIER_AC +#define DECODE_CARRIER_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_CARRIER_AC +#ifndef SEND_CARRIER_AC +#define SEND_CARRIER_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_CARRIER_AC + +#ifndef DECODE_HAIER_AC +#define DECODE_HAIER_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_HAIER_AC +#ifndef SEND_HAIER_AC +#define SEND_HAIER_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_HAIER_AC + +#ifndef DECODE_HITACHI_AC +#define DECODE_HITACHI_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_HITACHI_AC +#ifndef SEND_HITACHI_AC +#define SEND_HITACHI_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_HITACHI_AC + +#ifndef DECODE_HITACHI_AC1 +#define DECODE_HITACHI_AC1 _IR_ENABLE_DEFAULT_ +#endif // DECODE_HITACHI_AC1 +#ifndef SEND_HITACHI_AC1 +#define SEND_HITACHI_AC1 _IR_ENABLE_DEFAULT_ +#endif // SEND_HITACHI_AC1 + +#ifndef DECODE_HITACHI_AC2 +#define DECODE_HITACHI_AC2 _IR_ENABLE_DEFAULT_ +#endif // DECODE_HITACHI_AC2 +#ifndef SEND_HITACHI_AC2 +#define SEND_HITACHI_AC2 _IR_ENABLE_DEFAULT_ +#endif // SEND_HITACHI_AC2 + +#ifndef DECODE_GICABLE +#define DECODE_GICABLE _IR_ENABLE_DEFAULT_ +#endif // DECODE_GICABLE +#ifndef SEND_GICABLE +#define SEND_GICABLE _IR_ENABLE_DEFAULT_ +#endif // SEND_GICABLE + +#ifndef DECODE_HAIER_AC_YRW02 +#define DECODE_HAIER_AC_YRW02 _IR_ENABLE_DEFAULT_ +#endif // DECODE_HAIER_AC_YRW02 +#ifndef SEND_HAIER_AC_YRW02 +#define SEND_HAIER_AC_YRW02 _IR_ENABLE_DEFAULT_ +#endif // SEND_HAIER_AC_YRW02 + +#ifndef DECODE_WHIRLPOOL_AC +#define DECODE_WHIRLPOOL_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_WHIRLPOOL_AC +#ifndef SEND_WHIRLPOOL_AC +#define SEND_WHIRLPOOL_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_WHIRLPOOL_AC + +#ifndef DECODE_LUTRON +#define DECODE_LUTRON _IR_ENABLE_DEFAULT_ +#endif // DECODE_LUTRON +#ifndef SEND_LUTRON +#define SEND_LUTRON _IR_ENABLE_DEFAULT_ +#endif // SEND_LUTRON + +#ifndef DECODE_ELECTRA_AC +#define DECODE_ELECTRA_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_ELECTRA_AC +#ifndef SEND_ELECTRA_AC +#define SEND_ELECTRA_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_ELECTRA_AC + +#ifndef DECODE_PANASONIC_AC +#define DECODE_PANASONIC_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_PANASONIC_AC +#ifndef SEND_PANASONIC_AC +#define SEND_PANASONIC_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_PANASONIC_AC + +#ifndef DECODE_MWM +#define DECODE_MWM _IR_ENABLE_DEFAULT_ +#endif // DECODE_MWM +#ifndef SEND_MWM +#define SEND_MWM _IR_ENABLE_DEFAULT_ +#endif // SEND_MWM + +#ifndef DECODE_PIONEER +#define DECODE_PIONEER _IR_ENABLE_DEFAULT_ +#endif // DECODE_PIONEER +#ifndef SEND_PIONEER +#define SEND_PIONEER _IR_ENABLE_DEFAULT_ +#endif // SEND_PIONEER + +#ifndef DECODE_DAIKIN2 +#define DECODE_DAIKIN2 _IR_ENABLE_DEFAULT_ +#endif // DECODE_DAIKIN2 +#ifndef SEND_DAIKIN2 +#define SEND_DAIKIN2 _IR_ENABLE_DEFAULT_ +#endif // SEND_DAIKIN2 + +#ifndef DECODE_VESTEL_AC +#define DECODE_VESTEL_AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_VESTEL_AC +#ifndef SEND_VESTEL_AC +#define SEND_VESTEL_AC _IR_ENABLE_DEFAULT_ +#endif // SEND_VESTEL_AC + +#ifndef DECODE_TECO +#define DECODE_TECO _IR_ENABLE_DEFAULT_ +#endif // DECODE_TECO +#ifndef SEND_TECO +#define SEND_TECO _IR_ENABLE_DEFAULT_ +#endif // SEND_TECO + +#ifndef DECODE_TCL112AC +#define DECODE_TCL112AC _IR_ENABLE_DEFAULT_ +#endif // DECODE_TCL112AC +#ifndef SEND_TCL112AC +#define SEND_TCL112AC _IR_ENABLE_DEFAULT_ +#endif // SEND_TCL112AC + +#ifndef DECODE_LEGOPF +#define DECODE_LEGOPF _IR_ENABLE_DEFAULT_ +#endif // DECODE_LEGOPF +#ifndef SEND_LEGOPF +#define SEND_LEGOPF _IR_ENABLE_DEFAULT_ +#endif // SEND_LEGOPF + +#ifndef DECODE_MITSUBISHIHEAVY +#define DECODE_MITSUBISHIHEAVY _IR_ENABLE_DEFAULT_ +#endif // DECODE_MITSUBISHIHEAVY +#ifndef SEND_MITSUBISHIHEAVY +#define SEND_MITSUBISHIHEAVY _IR_ENABLE_DEFAULT_ +#endif // SEND_MITSUBISHIHEAVY + +#ifndef DECODE_DAIKIN216 +#define DECODE_DAIKIN216 _IR_ENABLE_DEFAULT_ +#endif // DECODE_DAIKIN216 +#ifndef SEND_DAIKIN216 +#define SEND_DAIKIN216 _IR_ENABLE_DEFAULT_ +#endif // SEND_DAIKIN216 + +#ifndef DECODE_DAIKIN160 +#define DECODE_DAIKIN160 _IR_ENABLE_DEFAULT_ +#endif // DECODE_DAIKIN160 +#ifndef SEND_DAIKIN160 +#define SEND_DAIKIN160 _IR_ENABLE_DEFAULT_ +#endif // SEND_DAIKIN160 + +#ifndef DECODE_NEOCLIMA +#define DECODE_NEOCLIMA _IR_ENABLE_DEFAULT_ +#endif // DECODE_NEOCLIMA +#ifndef SEND_NEOCLIMA +#define SEND_NEOCLIMA _IR_ENABLE_DEFAULT_ +#endif // SEND_NEOCLIMA + +#ifndef DECODE_DAIKIN176 +#define DECODE_DAIKIN176 _IR_ENABLE_DEFAULT_ +#endif // DECODE_DAIKIN176 +#ifndef SEND_DAIKIN176 +#define SEND_DAIKIN176 _IR_ENABLE_DEFAULT_ +#endif // SEND_DAIKIN176 + +#ifndef DECODE_DAIKIN128 +#define DECODE_DAIKIN128 _IR_ENABLE_DEFAULT_ +#endif // DECODE_DAIKIN128 +#ifndef SEND_DAIKIN128 +#define SEND_DAIKIN128 _IR_ENABLE_DEFAULT_ +#endif // SEND_DAIKIN128 + +#ifndef DECODE_AMCOR +#define DECODE_AMCOR _IR_ENABLE_DEFAULT_ +#endif // DECODE_AMCOR +#ifndef SEND_AMCOR +#define SEND_AMCOR _IR_ENABLE_DEFAULT_ +#endif // SEND_AMCOR + +#ifndef DECODE_DAIKIN152 +#define DECODE_DAIKIN152 _IR_ENABLE_DEFAULT_ +#endif // DECODE_DAIKIN152 +#ifndef SEND_DAIKIN152 +#define SEND_DAIKIN152 _IR_ENABLE_DEFAULT_ +#endif // SEND_DAIKIN152 + +#ifndef DECODE_HITACHI_AC424 +#define DECODE_HITACHI_AC424 _IR_ENABLE_DEFAULT_ +#endif // DECODE_HITACHI_AC424 +#ifndef SEND_HITACHI_AC424 +#define SEND_HITACHI_AC424 _IR_ENABLE_DEFAULT_ +#endif // SEND_HITACHI_AC424 #if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \ DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \ @@ -495,7 +585,9 @@ // Note: If you plan to send IR messages in the callbacks of the AsyncWebserver // library, you need to set ALLOW_DELAY_CALLS to false. // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/430 +#ifndef ALLOW_DELAY_CALLS #define ALLOW_DELAY_CALLS true +#endif // ALLOW_DELAY_CALLS /* * Always add to the end of the list and should never remove entries @@ -578,8 +670,9 @@ enum decode_type_t { MITSUBISHI136, MITSUBISHI112, HITACHI_AC424, + SONY_38K, // Add new entries before this one, and update it to point to the last entry. - kLastDecodeType = HITACHI_AC424, + kLastDecodeType = SONY_38K, }; // Message lengths & required repeat values diff --git a/lib/IRremoteESP8266-2.7.2/src/IRsend.cpp b/lib/IRremoteESP8266-2.7.3/src/IRsend.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.2/src/IRsend.cpp rename to lib/IRremoteESP8266-2.7.3/src/IRsend.cpp index 18e2eb559..4bc16a75c 100644 --- a/lib/IRremoteESP8266-2.7.2/src/IRsend.cpp +++ b/lib/IRremoteESP8266-2.7.3/src/IRsend.cpp @@ -515,6 +515,8 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) { return kDishMinRepeat; case SONY: return kSonyMinRepeat; + case SONY_38K: + return kSonyMinRepeat + 1; default: return kNoRepeat; } @@ -545,6 +547,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { return 16; case RC6: case SONY: + case SONY_38K: return 20; case COOLIX: case INAX: @@ -818,6 +821,9 @@ bool IRsend::send(const decode_type_t type, const uint64_t data, case SONY: sendSony(data, nbits, min_repeat); break; + case SONY_38K: + sendSony38(data, nbits, min_repeat); + break; #endif #if SEND_TECO case TECO: diff --git a/lib/IRremoteESP8266-2.7.2/src/IRsend.h b/lib/IRremoteESP8266-2.7.3/src/IRsend.h similarity index 98% rename from lib/IRremoteESP8266-2.7.2/src/IRsend.h rename to lib/IRremoteESP8266-2.7.3/src/IRsend.h index e86f4e7de..ff801210d 100644 --- a/lib/IRremoteESP8266-2.7.2/src/IRsend.h +++ b/lib/IRremoteESP8266-2.7.3/src/IRsend.h @@ -130,7 +130,7 @@ enum panasonic_ac_remote_model_t { kPanasonicUnknown = 0, kPanasonicLke = 1, kPanasonicNke = 2, - kPanasonicDke = 3, + kPanasonicDke = 3, // PKR too. kPanasonicJke = 4, kPanasonicCkp = 5, kPanasonicRkr = 6, @@ -203,6 +203,8 @@ class IRsend { // a Sony command that will be accepted be a device. void sendSony(uint64_t data, uint16_t nbits = kSony20Bits, uint16_t repeat = kSonyMinRepeat); + void sendSony38(uint64_t data, uint16_t nbits = kSony20Bits, + uint16_t repeat = kSonyMinRepeat + 1); uint32_t encodeSony(uint16_t nbits, uint16_t command, uint16_t address, uint16_t extended = 0); #endif @@ -561,6 +563,10 @@ class IRsend { uint8_t _dutycycle; bool modulation; uint32_t calcUSecPeriod(uint32_t hz, bool use_offset = true); +#if SEND_SONY + void _sendSony(uint64_t data, uint16_t nbits, + uint16_t repeat, uint16_t freq); +#endif }; #endif // IRSEND_H_ diff --git a/lib/IRremoteESP8266-2.7.2/src/IRtext.cpp b/lib/IRremoteESP8266-2.7.3/src/IRtext.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/IRtext.cpp rename to lib/IRremoteESP8266-2.7.3/src/IRtext.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/IRtext.h b/lib/IRremoteESP8266-2.7.3/src/IRtext.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/IRtext.h rename to lib/IRremoteESP8266-2.7.3/src/IRtext.h diff --git a/lib/IRremoteESP8266-2.7.2/src/IRtimer.cpp b/lib/IRremoteESP8266-2.7.3/src/IRtimer.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/IRtimer.cpp rename to lib/IRremoteESP8266-2.7.3/src/IRtimer.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/IRtimer.h b/lib/IRremoteESP8266-2.7.3/src/IRtimer.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/IRtimer.h rename to lib/IRremoteESP8266-2.7.3/src/IRtimer.h diff --git a/lib/IRremoteESP8266-2.7.2/src/IRutils.cpp b/lib/IRremoteESP8266-2.7.3/src/IRutils.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.2/src/IRutils.cpp rename to lib/IRremoteESP8266-2.7.3/src/IRutils.cpp index e785f625d..bbb9ed491 100644 --- a/lib/IRremoteESP8266-2.7.2/src/IRutils.cpp +++ b/lib/IRremoteESP8266-2.7.3/src/IRutils.cpp @@ -228,6 +228,8 @@ decode_type_t strToDecodeType(const char * const str) { return decode_type_t::SHERWOOD; else if (!strcasecmp(str, "SONY")) return decode_type_t::SONY; + else if (!strcasecmp(str, "SONY_38K")) + return decode_type_t::SONY_38K; else if (!strcasecmp(str, "TCL112AC")) return decode_type_t::TCL112AC; else if (!strcasecmp(str, "TECO")) @@ -461,6 +463,9 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) { case SONY: result = F("SONY"); break; + case SONY_38K: + result = F("SONY_38K"); + break; case TCL112AC: result = F("TCL112AC"); break; diff --git a/lib/IRremoteESP8266-2.7.2/src/IRutils.h b/lib/IRremoteESP8266-2.7.3/src/IRutils.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/IRutils.h rename to lib/IRremoteESP8266-2.7.3/src/IRutils.h diff --git a/lib/IRremoteESP8266-2.7.2/src/i18n.h b/lib/IRremoteESP8266-2.7.3/src/i18n.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/i18n.h rename to lib/IRremoteESP8266-2.7.3/src/i18n.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Aiwa.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Aiwa.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Aiwa.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Aiwa.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Amcor.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Amcor.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Amcor.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Amcor.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Amcor.h b/lib/IRremoteESP8266-2.7.3/src/ir_Amcor.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Amcor.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Amcor.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Argo.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Argo.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Argo.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Argo.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Argo.h b/lib/IRremoteESP8266-2.7.3/src/ir_Argo.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Argo.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Argo.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Carrier.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Carrier.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Carrier.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Carrier.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Coolix.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Coolix.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.2/src/ir_Coolix.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Coolix.cpp index 0dbd68d63..8b184bf9f 100644 --- a/lib/IRremoteESP8266-2.7.2/src/ir_Coolix.cpp +++ b/lib/IRremoteESP8266-2.7.3/src/ir_Coolix.cpp @@ -27,16 +27,16 @@ // Pulse parms are *50-100 for the Mark and *50+100 for the space // First MARK is the one after the long gap // pulse parameters in usec -const uint16_t kCoolixTick = 560; // Approximately 21 cycles at 38kHz -const uint16_t kCoolixBitMarkTicks = 1; +const uint16_t kCoolixTick = 276; // Approximately 10.5 cycles at 38kHz +const uint16_t kCoolixBitMarkTicks = 2; const uint16_t kCoolixBitMark = kCoolixBitMarkTicks * kCoolixTick; -const uint16_t kCoolixOneSpaceTicks = 3; +const uint16_t kCoolixOneSpaceTicks = 6; const uint16_t kCoolixOneSpace = kCoolixOneSpaceTicks * kCoolixTick; -const uint16_t kCoolixZeroSpaceTicks = 1; +const uint16_t kCoolixZeroSpaceTicks = 2; const uint16_t kCoolixZeroSpace = kCoolixZeroSpaceTicks * kCoolixTick; -const uint16_t kCoolixHdrMarkTicks = 8; +const uint16_t kCoolixHdrMarkTicks = 17; const uint16_t kCoolixHdrMark = kCoolixHdrMarkTicks * kCoolixTick; -const uint16_t kCoolixHdrSpaceTicks = 8; +const uint16_t kCoolixHdrSpaceTicks = 16; const uint16_t kCoolixHdrSpace = kCoolixHdrSpaceTicks * kCoolixTick; const uint16_t kCoolixMinGapTicks = kCoolixHdrMarkTicks + kCoolixZeroSpaceTicks; const uint16_t kCoolixMinGap = kCoolixMinGapTicks * kCoolixTick; @@ -57,11 +57,10 @@ using irutils::setBits; // nbits: Nr. of bits of data to be sent. Typically kCoolixBits. // repeat: Nr. of additional times the message is to be sent. // -// Status: BETA / Probably works. +// Status: STABLE / Confirmed Working. // // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_COOLIX.cpp -// TODO(anyone): Verify repeat functionality against a real unit. void IRsend::sendCOOLIX(uint64_t data, uint16_t nbits, uint16_t repeat) { if (nbits % 8 != 0) return; // nbits is required to be a multiple of 8. @@ -443,7 +442,11 @@ stdAc::state_t IRCoolixAC::toCommon(const stdAc::state_t *prev) { } else { // Set defaults for non-zero values that are not implicitly set for when // there is no previous state. + // e.g. Any setting that toggles should probably go here. result.swingv = stdAc::swingv_t::kOff; + result.turbo = false; + result.clean = false; + result.light = false; result.sleep = -1; } // Not supported. diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Coolix.h b/lib/IRremoteESP8266-2.7.3/src/ir_Coolix.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Coolix.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Coolix.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Daikin.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Daikin.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Daikin.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Daikin.h b/lib/IRremoteESP8266-2.7.3/src/ir_Daikin.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Daikin.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Daikin.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Denon.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Denon.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Denon.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Denon.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Dish.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Dish.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Dish.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Dish.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Electra.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Electra.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Electra.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Electra.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Electra.h b/lib/IRremoteESP8266-2.7.3/src/ir_Electra.h similarity index 97% rename from lib/IRremoteESP8266-2.7.2/src/ir_Electra.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Electra.h index ef28b44cf..a120bcd28 100644 --- a/lib/IRremoteESP8266-2.7.2/src/ir_Electra.h +++ b/lib/IRremoteESP8266-2.7.3/src/ir_Electra.h @@ -19,6 +19,8 @@ // Supports: // Brand: AUX, Model: KFR-35GW/BpNFW=3 A/C // Brand: AUX, Model: YKR-T/011 remote +// Brand: Electra, Model: Classic INV 17 / AXW12DCS A/C +// Brand: Electra, Model: YKR-M/003E remote // Ref: // https://github.com/ToniA/arduino-heatpumpir/blob/master/AUXHeatpumpIR.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Fujitsu.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Fujitsu.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Fujitsu.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Fujitsu.h b/lib/IRremoteESP8266-2.7.3/src/ir_Fujitsu.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Fujitsu.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Fujitsu.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_GICable.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_GICable.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_GICable.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_GICable.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_GlobalCache.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_GlobalCache.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_GlobalCache.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_GlobalCache.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Goodweather.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Goodweather.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Goodweather.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Goodweather.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Goodweather.h b/lib/IRremoteESP8266-2.7.3/src/ir_Goodweather.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Goodweather.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Goodweather.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Gree.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Gree.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Gree.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Gree.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Gree.h b/lib/IRremoteESP8266-2.7.3/src/ir_Gree.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Gree.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Gree.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Haier.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Haier.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Haier.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Haier.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Haier.h b/lib/IRremoteESP8266-2.7.3/src/ir_Haier.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Haier.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Haier.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Hitachi.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Hitachi.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Hitachi.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Hitachi.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Hitachi.h b/lib/IRremoteESP8266-2.7.3/src/ir_Hitachi.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Hitachi.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Hitachi.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Inax.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Inax.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Inax.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Inax.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_JVC.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_JVC.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_JVC.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_JVC.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Kelvinator.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Kelvinator.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Kelvinator.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Kelvinator.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Kelvinator.h b/lib/IRremoteESP8266-2.7.3/src/ir_Kelvinator.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Kelvinator.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Kelvinator.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_LG.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_LG.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_LG.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_LG.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_LG.h b/lib/IRremoteESP8266-2.7.3/src/ir_LG.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_LG.h rename to lib/IRremoteESP8266-2.7.3/src/ir_LG.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Lasertag.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Lasertag.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Lasertag.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Lasertag.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Lego.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Lego.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Lego.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Lego.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Lutron.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Lutron.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Lutron.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Lutron.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_MWM.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_MWM.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_MWM.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_MWM.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Magiquest.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Magiquest.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Magiquest.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Magiquest.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Magiquest.h b/lib/IRremoteESP8266-2.7.3/src/ir_Magiquest.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Magiquest.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Magiquest.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Midea.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Midea.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Midea.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Midea.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Midea.h b/lib/IRremoteESP8266-2.7.3/src/ir_Midea.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Midea.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Midea.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Mitsubishi.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Mitsubishi.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Mitsubishi.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Mitsubishi.h b/lib/IRremoteESP8266-2.7.3/src/ir_Mitsubishi.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Mitsubishi.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Mitsubishi.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_MitsubishiHeavy.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_MitsubishiHeavy.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_MitsubishiHeavy.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_MitsubishiHeavy.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_MitsubishiHeavy.h b/lib/IRremoteESP8266-2.7.3/src/ir_MitsubishiHeavy.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_MitsubishiHeavy.h rename to lib/IRremoteESP8266-2.7.3/src/ir_MitsubishiHeavy.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_NEC.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_NEC.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_NEC.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_NEC.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_NEC.h b/lib/IRremoteESP8266-2.7.3/src/ir_NEC.h similarity index 93% rename from lib/IRremoteESP8266-2.7.2/src/ir_NEC.h rename to lib/IRremoteESP8266-2.7.3/src/ir_NEC.h index 6319d32dc..cf6191100 100644 --- a/lib/IRremoteESP8266-2.7.2/src/ir_NEC.h +++ b/lib/IRremoteESP8266-2.7.3/src/ir_NEC.h @@ -10,9 +10,10 @@ #include "IRremoteESP8266.h" // Supports: -// Brand: Yamaha, Model: RAV561 remote -// Brand: Yamaha, Model: RXV585B A/V Receiver -// Brand: Aloka, Model: SleepyLights LED Lamp +// Brand: Yamaha, Model: RAV561 remote +// Brand: Yamaha, Model: RXV585B A/V Receiver +// Brand: Aloka, Model: SleepyLights LED Lamp +// Brand: Toshiba, Model: 42TL838 LCD TV // Constants // Ref: diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Neoclima.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Neoclima.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Neoclima.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Neoclima.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Neoclima.h b/lib/IRremoteESP8266-2.7.3/src/ir_Neoclima.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Neoclima.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Neoclima.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Nikai.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Nikai.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Nikai.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Nikai.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Panasonic.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.2/src/ir_Panasonic.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.cpp index a25f4cb02..511986a11 100644 --- a/lib/IRremoteESP8266-2.7.2/src/ir_Panasonic.cpp +++ b/lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.cpp @@ -25,8 +25,8 @@ // Code by crankyoldgit // Panasonic A/C models supported: // A/C Series/models: -// JKE, LKE, DKE, CKP, RKR, & NKE series. (In theory) -// CS-YW9MKD, CS-Z9RKR (confirmed) +// JKE, LKE, DKE, CKP, PKR, RKR, & NKE series. (In theory) +// CS-YW9MKD, CS-Z9RKR, CS-E7PKR (confirmed) // CS-ME14CKPG / CS-ME12CKPG / CS-ME10CKPG // A/C Remotes: // A75C3747 (confirmed) @@ -202,8 +202,9 @@ bool IRrecv::decodePanasonic(decode_results *results, const uint16_t nbits, //: // Panasonic A/C models supported: // A/C Series/models: -// JKE, LKE, DKE, CKP, RKR, & NKE series. +// JKE, LKE, DKE, CKP, PKR, RKR, & NKE series. // CS-YW9MKD +// CS-E7PKR // A/C Remotes: // A75C3747 // A75C3704 @@ -310,6 +311,8 @@ void IRPanasonicAc::setModel(const panasonic_ac_remote_model_t model) { default: break; } + // Reset the Ion filter. + setIon(getIon()); } panasonic_ac_remote_model_t IRPanasonicAc::getModel(void) { @@ -588,6 +591,22 @@ bool IRPanasonicAc::isOffTimerEnabled(void) { return GETBIT8(remote_state[13], kPanasonicAcOffTimerOffset); } +bool IRPanasonicAc::getIon(void) { + switch (this->getModel()) { + case kPanasonicDke: + return GETBIT8(remote_state[kPanasonicAcIonFilterByte], + kPanasonicAcIonFilterOffset); + default: + return false; + } +} + +void IRPanasonicAc::setIon(const bool on) { + if (this->getModel() == kPanasonicDke) + setBit(&remote_state[kPanasonicAcIonFilterByte], + kPanasonicAcIonFilterOffset, on); +} + // Convert a standard A/C mode into its native mode. uint8_t IRPanasonicAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { @@ -692,10 +711,10 @@ stdAc::state_t IRPanasonicAc::toCommon(void) { result.swingh = this->toCommonSwingH(this->getSwingHorizontal()); result.quiet = this->getQuiet(); result.turbo = this->getPowerful(); + result.filter = this->getIon(); // Not supported. result.econo = false; result.clean = false; - result.filter = false; result.light = false; result.beep = false; result.sleep = -1; @@ -774,6 +793,8 @@ String IRPanasonicAc::toString(void) { } result += addBoolToString(getQuiet(), kQuietStr); result += addBoolToString(getPowerful(), kPowerfulStr); + if (getModel() == kPanasonicDke) + result += addBoolToString(getIon(), kIonStr); result += addLabeledString(minsToString(getClock()), kClockStr); result += addLabeledString( isOnTimerEnabled() ? minsToString(getOnTimer()) : kOffStr, @@ -798,8 +819,9 @@ String IRPanasonicAc::toString(void) { // // Panasonic A/C models supported: // A/C Series/models: -// JKE, LKE, DKE, & NKE series. +// JKE, LKE, DKE, PKR, & NKE series. // CS-YW9MKD +// CS-E7PKR // A/C Remotes: // A75C3747 (Confirmed) // A75C3704 diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Panasonic.h b/lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.h similarity index 94% rename from lib/IRremoteESP8266-2.7.2/src/ir_Panasonic.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.h index 89c2e5395..42e771fb3 100644 --- a/lib/IRremoteESP8266-2.7.2/src/ir_Panasonic.h +++ b/lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.h @@ -4,19 +4,20 @@ // Brand: Panasonic, Model: TV // Brand: Panasonic, Model: JKE series A/C // Brand: Panasonic, Model: DKE series A/C +// Brand: Panasonic, Model: DKW series A/C (DKE) +// Brand: Panasonic, Model: PKR series A/C (DKE) // Brand: Panasonic, Model: CKP series A/C +// Brand: Panasonic, Model: NKE series A/C +// Brand: Panasonic, Model: RKR series A/C // Brand: Panasonic, Model: CS-ME10CKPG A/C // Brand: Panasonic, Model: CS-ME12CKPG A/C // Brand: Panasonic, Model: CS-ME14CKPG A/C -// Brand: Panasonic, Model: RKR series A/C +// Brand: Panasonic, Model: CS-E7PKR A/C (DKE) // Brand: Panasonic, Model: CS-Z9RKR A/C -// Brand: Panasonic, Model: NKE series A/C // Brand: Panasonic, Model: CS-YW9MKD A/C -// Brand: Panasonic, Model: A75C3747 remote -// Brand: Panasonic, Model: A75C3704 remote // Brand: Panasonic, Model: A75C2311 remote (CKP) -// Brand: Panasonic, Model: A75C3747 remote -// Brand: Panasonic, Model: A75C3747 remote +// Brand: Panasonic, Model: A75C2616-1 remote (DKE) +// Brand: Panasonic, Model: A75C3704 remote // Brand: Panasonic, Model: A75C3747 remote #ifndef IR_PANASONIC_H_ @@ -84,6 +85,9 @@ const uint8_t kPanasonicAcTimeOverflowSize = 3; // Bits const uint16_t kPanasonicAcTimeMax = 23 * 60 + 59; // Mins since midnight. const uint16_t kPanasonicAcTimeSpecial = 0x600; +const uint8_t kPanasonicAcIonFilterByte = 22; // Byte +const uint8_t kPanasonicAcIonFilterOffset = 0; // Bit + const uint8_t kPanasonicKnownGoodState[kPanasonicAcStateLength] = { 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, @@ -121,6 +125,8 @@ class IRPanasonicAc { bool getQuiet(void); void setPowerful(const bool on); bool getPowerful(void); + void setIon(const bool on); + bool getIon(void); void setModel(const panasonic_ac_remote_model_t model); panasonic_ac_remote_model_t getModel(void); void setSwingVertical(const uint8_t elevation); diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Pioneer.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Pioneer.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Pioneer.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Pioneer.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Pronto.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Pronto.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Pronto.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Pronto.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_RC5_RC6.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_RC5_RC6.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_RC5_RC6.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_RC5_RC6.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_RCMM.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_RCMM.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_RCMM.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_RCMM.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Samsung.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Samsung.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Samsung.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Samsung.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Samsung.h b/lib/IRremoteESP8266-2.7.3/src/ir_Samsung.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Samsung.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Samsung.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Sanyo.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Sanyo.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Sanyo.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Sanyo.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Sharp.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Sharp.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Sharp.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Sharp.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Sharp.h b/lib/IRremoteESP8266-2.7.3/src/ir_Sharp.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Sharp.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Sharp.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Sherwood.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Sherwood.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Sherwood.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Sherwood.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Sony.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Sony.cpp similarity index 74% rename from lib/IRremoteESP8266-2.7.2/src/ir_Sony.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Sony.cpp index 6fc39b7b5..d0f4b3c7a 100644 --- a/lib/IRremoteESP8266-2.7.2/src/ir_Sony.cpp +++ b/lib/IRremoteESP8266-2.7.3/src/ir_Sony.cpp @@ -1,9 +1,12 @@ // Copyright 2009 Ken Shirriff // Copyright 2016 marcosamarinho -// Copyright 2017 David Conran +// Copyright 2017,2020 David Conran // Sony Remote Emulation +// Supports: +// Brand: Sony, Model: HT-CT380 Soundbar (Uses 38kHz & 3 repeats) + #include #include "IRrecv.h" #include "IRsend.h" @@ -28,9 +31,11 @@ const uint16_t kSonyRptLengthTicks = 225; const uint16_t kSonyRptLength = kSonyRptLengthTicks * kSonyTick; const uint16_t kSonyMinGapTicks = 50; const uint16_t kSonyMinGap = kSonyMinGapTicks * kSonyTick; +const uint16_t kSonyStdFreq = 40000; // kHz +const uint16_t kSonyAltFreq = 38000; // kHz #if SEND_SONY -// Send a Sony/SIRC(Serial Infra-Red Control) message. +// Send a standard Sony/SIRC(Serial Infra-Red Control) message. (40kHz) // // Args: // data: message to be sent. @@ -46,10 +51,50 @@ const uint16_t kSonyMinGap = kSonyMinGapTicks * kSonyTick; // Ref: // http://www.sbprojects.com/knowledge/ir/sirc.php void IRsend::sendSony(uint64_t data, uint16_t nbits, uint16_t repeat) { + _sendSony(data, nbits, repeat, kSonyStdFreq); +} + +// Send an alternative 38kHz Sony/SIRC(Serial Infra-Red Control) message. +// +// Args: +// data: message to be sent. +// nbits: Nr. of bits of the message to be sent. +// repeat: Nr. of additional times the message is to be sent. (Default: 3) +// +// Status: STABLE / Known working. +// +// Notes: +// - `sendSony38()`` should typically be called with repeat=3 as these Sony +// devices expect the message to be sent at least 4 times. +// - Messages send via this method will be detected by this library as just +// `SONY`, not `SONY_38K` as the library has no way to determine the +// modulation frequency used. Hence, there is no `decodeSony38()`. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/sirc.php +// https://github.com/crankyoldgit/IRremoteESP8266/issues/1018 +void IRsend::sendSony38(uint64_t data, uint16_t nbits, uint16_t repeat) { + _sendSony(data, nbits, repeat, kSonyAltFreq); +} + +// Internal procedure to generate a Sony/SIRC(Serial Infra-Red Control) message. +// +// Args: +// data: message to be sent. +// nbits: Nr. of bits of the message to be sent. +// repeat: Nr. of additional times the message is to be sent. +// freq: Frequency of the modulation to transmit at. (Hz or kHz) +// +// Status: STABLE / Known working. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/sirc.php +void IRsend::_sendSony(uint64_t data, uint16_t nbits, uint16_t repeat, + uint16_t freq) { sendGeneric(kSonyHdrMark, kSonySpace, kSonyOneMark, kSonySpace, kSonyZeroMark, kSonySpace, 0, // No Footer mark. - kSonyMinGap, kSonyRptLength, data, nbits, 40, true, repeat, 33); + kSonyMinGap, kSonyRptLength, data, nbits, freq, true, repeat, 33); } // Convert Sony/SIRC command, address, & extended bits into sendSony format. @@ -149,6 +194,7 @@ bool IRrecv::decodeSony(decode_results *results, uint16_t nbits, bool strict) { // Success results->bits = actualBits; results->value = data; + // We can't detect SONY_38K messages so always assume it is just `SONY` 40kHz. results->decode_type = SONY; // Message comes in LSB first. Convert ot MSB first. data = reverseBits(data, actualBits); diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Tcl.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Tcl.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Tcl.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Tcl.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Tcl.h b/lib/IRremoteESP8266-2.7.3/src/ir_Tcl.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Tcl.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Tcl.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Teco.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Teco.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Teco.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Teco.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Teco.h b/lib/IRremoteESP8266-2.7.3/src/ir_Teco.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Teco.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Teco.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Toshiba.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Toshiba.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Toshiba.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Toshiba.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Toshiba.h b/lib/IRremoteESP8266-2.7.3/src/ir_Toshiba.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Toshiba.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Toshiba.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Trotec.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Trotec.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Trotec.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Trotec.h b/lib/IRremoteESP8266-2.7.3/src/ir_Trotec.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Trotec.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Trotec.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Vestel.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Vestel.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Vestel.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Vestel.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Vestel.h b/lib/IRremoteESP8266-2.7.3/src/ir_Vestel.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Vestel.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Vestel.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Whirlpool.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Whirlpool.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Whirlpool.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Whirlpool.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Whirlpool.h b/lib/IRremoteESP8266-2.7.3/src/ir_Whirlpool.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Whirlpool.h rename to lib/IRremoteESP8266-2.7.3/src/ir_Whirlpool.h diff --git a/lib/IRremoteESP8266-2.7.2/src/ir_Whynter.cpp b/lib/IRremoteESP8266-2.7.3/src/ir_Whynter.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/ir_Whynter.cpp rename to lib/IRremoteESP8266-2.7.3/src/ir_Whynter.cpp diff --git a/lib/IRremoteESP8266-2.7.2/src/locale/README.md b/lib/IRremoteESP8266-2.7.3/src/locale/README.md similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/locale/README.md rename to lib/IRremoteESP8266-2.7.3/src/locale/README.md diff --git a/lib/IRremoteESP8266-2.7.2/src/locale/de-CH.h b/lib/IRremoteESP8266-2.7.3/src/locale/de-CH.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/locale/de-CH.h rename to lib/IRremoteESP8266-2.7.3/src/locale/de-CH.h diff --git a/lib/IRremoteESP8266-2.7.2/src/locale/de-DE.h b/lib/IRremoteESP8266-2.7.3/src/locale/de-DE.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/locale/de-DE.h rename to lib/IRremoteESP8266-2.7.3/src/locale/de-DE.h diff --git a/lib/IRremoteESP8266-2.7.2/src/locale/defaults.h b/lib/IRremoteESP8266-2.7.3/src/locale/defaults.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/locale/defaults.h rename to lib/IRremoteESP8266-2.7.3/src/locale/defaults.h diff --git a/lib/IRremoteESP8266-2.7.2/src/locale/en-AU.h b/lib/IRremoteESP8266-2.7.3/src/locale/en-AU.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/locale/en-AU.h rename to lib/IRremoteESP8266-2.7.3/src/locale/en-AU.h diff --git a/lib/IRremoteESP8266-2.7.2/src/locale/en-IE.h b/lib/IRremoteESP8266-2.7.3/src/locale/en-IE.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/locale/en-IE.h rename to lib/IRremoteESP8266-2.7.3/src/locale/en-IE.h diff --git a/lib/IRremoteESP8266-2.7.2/src/locale/en-UK.h b/lib/IRremoteESP8266-2.7.3/src/locale/en-UK.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/locale/en-UK.h rename to lib/IRremoteESP8266-2.7.3/src/locale/en-UK.h diff --git a/lib/IRremoteESP8266-2.7.2/src/locale/en-US.h b/lib/IRremoteESP8266-2.7.3/src/locale/en-US.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/locale/en-US.h rename to lib/IRremoteESP8266-2.7.3/src/locale/en-US.h diff --git a/lib/IRremoteESP8266-2.7.2/src/locale/es-ES.h b/lib/IRremoteESP8266-2.7.3/src/locale/es-ES.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/locale/es-ES.h rename to lib/IRremoteESP8266-2.7.3/src/locale/es-ES.h diff --git a/lib/IRremoteESP8266-2.7.2/src/locale/fr-FR.h b/lib/IRremoteESP8266-2.7.3/src/locale/fr-FR.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/src/locale/fr-FR.h rename to lib/IRremoteESP8266-2.7.3/src/locale/fr-FR.h diff --git a/lib/IRremoteESP8266-2.7.2/test/IRac_test.cpp b/lib/IRremoteESP8266-2.7.3/test/IRac_test.cpp similarity index 95% rename from lib/IRremoteESP8266-2.7.2/test/IRac_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/IRac_test.cpp index 2c17e2a92..875485eee 100644 --- a/lib/IRremoteESP8266-2.7.2/test/IRac_test.cpp +++ b/lib/IRremoteESP8266-2.7.3/test/IRac_test.cpp @@ -108,29 +108,29 @@ TEST(TestIRac, Coolix) { "f38000d50" // 38kHz Frequency and 50% duty-cycle. // Start of message #1 (i.e. Repeat '0') // Header - "m4480s4480" + "m4692s4416" // Data - "m560s1680m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" - "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s560" - "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656" + "m552s552m552s552m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s1656m552s1656m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s552m552s552" + "m552s1656m552s552m552s552m552s1656m552s552m552s552m552s1656m552s1656" // Footer - "m560s5040" + "m552s5244" // End of message #1 (i.e. Repeat '0') // Start of message #2 (i.e. Repeat '1') // Header - "m4480s4480" + "m4692s4416" // Data - "m560s1680m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" - "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s560" - "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656" + "m552s552m552s552m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s1656m552s1656m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s552m552s552" + "m552s1656m552s552m552s552m552s1656m552s552m552s552m552s1656m552s1656" // Footer - "m560s105040", + "m552s105244", // End of message #2 (i.e. Repeat '1') // Note: the two messages (#1 & #2) are identical. ac._irsend.outputStr()); @@ -851,6 +851,7 @@ TEST(TestIRac, Panasonic) { stdAc::swingh_t::kLeft, // Horizontal swing true, // Quiet false, // Turbo + false, // Filter 19 * 60 + 17); // Clock ASSERT_EQ(expected_nke, ac.toString()); ac._irsend.makeDecodeResult(); @@ -862,7 +863,8 @@ TEST(TestIRac, Panasonic) { char expected_dke[] = "Model: 3 (DKE), Power: On, Mode: 3 (Cool), Temp: 18C, Fan: 4 (High), " "Swing(V): 2 (High), Swing(H): 6 (Middle), " - "Quiet: Off, Powerful: On, Clock: 19:17, On Timer: Off, Off Timer: Off"; + "Quiet: Off, Powerful: On, Ion: On, " + "Clock: 19:17, On Timer: Off, Off Timer: Off"; ac._irsend.reset(); irac.panasonic(&ac, kPanasonicDke, // Model @@ -874,6 +876,7 @@ TEST(TestIRac, Panasonic) { stdAc::swingh_t::kMiddle, // Horizontal swing false, // Quiet true, // Turbo + true, // Filter 19 * 60 + 17); // Clock ASSERT_EQ(expected_dke, ac.toString()); ac._irsend.makeDecodeResult(); @@ -1475,39 +1478,39 @@ TEST(TestIRac, Issue821) { ASSERT_EQ("Power: On, Light: Toggle", IRAcUtils::resultAcToString(&ac._irsend.capture)); EXPECT_EQ( - "f38000d50m" - "4480s4480" - "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s560m560s560m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560" - "m560s5040" - "m4480s4480" - "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s560m560s560m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560" - "m560s105040" - "m4480s4480" - "m560s1680m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" - "m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560" - "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680" - "m560s5040" - "m4480s4480" - "m560s1680m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" - "m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560" - "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680" - "m560s105040", + "f38000d50" + "m4692s4416" + "m552s1656m552s552m552s1656m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s552m552s552m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s1656m552s1656m552s552m552s1656m552s552" + "m552s5244" + "m4692s4416" + "m552s1656m552s552m552s1656m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s552m552s552m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s1656m552s1656m552s552m552s1656m552s552" + "m552s105244" + "m4692s4416" + "m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656" + "m552s552m552s552m552s552m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s1656m552s1656m552s1656m552s552m552s552m552s552m552s552m552s552" + "m552s552m552s1656m552s552m552s552m552s1656m552s552m552s552m552s552" + "m552s1656m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s1656" + "m552s5244" + "m4692s4416" + "m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656" + "m552s552m552s552m552s552m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s1656m552s1656m552s1656m552s552m552s552m552s552m552s552m552s552" + "m552s552m552s1656m552s552m552s552m552s1656m552s552m552s552m552s552" + "m552s1656m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s1656" + "m552s105244", ac._irsend.outputStr()); } diff --git a/lib/IRremoteESP8266-2.7.2/test/IRrecv_test.cpp b/lib/IRremoteESP8266-2.7.3/test/IRrecv_test.cpp similarity index 95% rename from lib/IRremoteESP8266-2.7.2/test/IRrecv_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/IRrecv_test.cpp index cda7b747f..9dff78c75 100644 --- a/lib/IRremoteESP8266-2.7.2/test/IRrecv_test.cpp +++ b/lib/IRremoteESP8266-2.7.3/test/IRrecv_test.cpp @@ -565,8 +565,8 @@ TEST(TestMatchGeneric, NormalWithNoAtleast) { IRrecv irrecv(1); irsend.begin(); - uint16_t good_entries_trailing_space = 12; - uint16_t good_trailing_space_data[good_entries_trailing_space] = { + const uint16_t kgood_entries_trailing_space = 12; + uint16_t good_trailing_space_data[kgood_entries_trailing_space] = { 8000, // Header mark 4000, // Header space 500, 2000, // Bit #0 (1) @@ -576,8 +576,8 @@ TEST(TestMatchGeneric, NormalWithNoAtleast) { 3000, // Footer mark 15000}; // Footer space - uint16_t good_entries_no_trailing_space = 11; - uint16_t good_no_trailing_space_data[good_entries_no_trailing_space] = { + const uint16_t kgood_entries_no_trailing_space = 11; + uint16_t good_no_trailing_space_data[kgood_entries_no_trailing_space] = { 8000, // Header mark 4000, // Header space 500, 2000, // Bit #0 (1) @@ -588,7 +588,7 @@ TEST(TestMatchGeneric, NormalWithNoAtleast) { uint16_t offset = kStartOffset; irsend.reset(); - irsend.sendRaw(good_trailing_space_data, good_entries_trailing_space, 38000); + irsend.sendRaw(good_trailing_space_data, kgood_entries_trailing_space, 38000); irsend.makeDecodeResult(); uint64_t result_data = 0; uint16_t entries_used = 0; @@ -607,7 +607,7 @@ TEST(TestMatchGeneric, NormalWithNoAtleast) { ASSERT_NE(0, entries_used); EXPECT_EQ(0b1010, result_data); EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used); - EXPECT_EQ(good_entries_trailing_space, entries_used); + EXPECT_EQ(kgood_entries_trailing_space, entries_used); // Same again but with a footer space mis-match, which should fail. result_data = 0; @@ -628,7 +628,7 @@ TEST(TestMatchGeneric, NormalWithNoAtleast) { // Same again as first part but with no footer space data as the last entry. irsend.reset(); result_data = 0; - irsend.sendRaw(good_no_trailing_space_data, good_entries_no_trailing_space, + irsend.sendRaw(good_no_trailing_space_data, kgood_entries_no_trailing_space, 38000); irsend.makeDecodeResult(); entries_used = irrecv.matchGeneric( @@ -646,7 +646,7 @@ TEST(TestMatchGeneric, NormalWithNoAtleast) { ASSERT_NE(0, entries_used); EXPECT_EQ(0b1010, result_data); EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used); - EXPECT_EQ(good_entries_no_trailing_space, entries_used); + EXPECT_EQ(kgood_entries_no_trailing_space, entries_used); } @@ -655,8 +655,8 @@ TEST(TestMatchGeneric, NormalWithAtleast) { IRrecv irrecv(1); irsend.begin(); - uint16_t good_entries_trailing_space = 12; - uint16_t good_trailing_space_data[good_entries_trailing_space] = { + const uint16_t kgood_entries_trailing_space = 12; + uint16_t good_trailing_space_data[kgood_entries_trailing_space] = { 8000, // Header mark 4000, // Header space 500, 2000, // Bit #0 (1) @@ -666,8 +666,8 @@ TEST(TestMatchGeneric, NormalWithAtleast) { 3000, // Footer mark 15000}; // Footer space - uint16_t good_entries_no_trailing_space = 11; - uint16_t good_no_trailing_space_data[good_entries_no_trailing_space] = { + const uint16_t kgood_entries_no_trailing_space = 11; + uint16_t good_no_trailing_space_data[kgood_entries_no_trailing_space] = { 8000, // Header mark 4000, // Header space 500, 2000, // Bit #0 (1) @@ -678,7 +678,7 @@ TEST(TestMatchGeneric, NormalWithAtleast) { uint16_t offset = kStartOffset; irsend.reset(); - irsend.sendRaw(good_trailing_space_data, good_entries_trailing_space, 38000); + irsend.sendRaw(good_trailing_space_data, kgood_entries_trailing_space, 38000); irsend.makeDecodeResult(); uint64_t result_data = 0; uint16_t entries_used = 0; @@ -697,7 +697,7 @@ TEST(TestMatchGeneric, NormalWithAtleast) { ASSERT_NE(0, entries_used); EXPECT_EQ(0b1010, result_data); EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used); - EXPECT_EQ(good_entries_trailing_space, entries_used); + EXPECT_EQ(kgood_entries_trailing_space, entries_used); // Same again but with a footer space under-match. result_data = 0; @@ -716,7 +716,7 @@ TEST(TestMatchGeneric, NormalWithAtleast) { ASSERT_NE(0, entries_used); EXPECT_EQ(0b1010, result_data); EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used); - EXPECT_EQ(good_entries_trailing_space, entries_used); + EXPECT_EQ(kgood_entries_trailing_space, entries_used); // Same again but with a footer space under-match using less bits so the // atleast footer isn't the last entry in the buffer. @@ -737,7 +737,7 @@ TEST(TestMatchGeneric, NormalWithAtleast) { EXPECT_EQ(0b101, result_data); // -2 because we reduced nbits by 1. EXPECT_EQ(irsend.capture.rawlen - kStartOffset - 2, entries_used); - EXPECT_EQ(good_entries_trailing_space - 2, entries_used); + EXPECT_EQ(kgood_entries_trailing_space - 2, entries_used); // Same again but with a footer space over-match, which should fail. result_data = 0; @@ -758,7 +758,7 @@ TEST(TestMatchGeneric, NormalWithAtleast) { // Same as first part but with no footer space data as the last entry. irsend.reset(); result_data = 0; - irsend.sendRaw(good_no_trailing_space_data, good_entries_no_trailing_space, + irsend.sendRaw(good_no_trailing_space_data, kgood_entries_no_trailing_space, 38000); irsend.makeDecodeResult(); entries_used = irrecv.matchGeneric( @@ -776,7 +776,7 @@ TEST(TestMatchGeneric, NormalWithAtleast) { ASSERT_NE(0, entries_used); EXPECT_EQ(0b1010, result_data); EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used); - EXPECT_EQ(good_entries_no_trailing_space, entries_used); + EXPECT_EQ(kgood_entries_no_trailing_space, entries_used); } TEST(TestMatchGeneric, FailureCases) { @@ -784,8 +784,8 @@ TEST(TestMatchGeneric, FailureCases) { IRrecv irrecv(1); irsend.begin(); - uint16_t entries = 11; - uint16_t data[entries] = { + const uint16_t kentries = 11; + uint16_t data[kentries] = { 8000, // Header mark 4000, // Header space 500, 2000, // Bit #0 (1) @@ -796,7 +796,7 @@ TEST(TestMatchGeneric, FailureCases) { uint16_t offset = kStartOffset; irsend.reset(); - irsend.sendRaw(data, entries, 38000); + irsend.sendRaw(data, kentries, 38000); irsend.makeDecodeResult(); uint16_t entries_used = 0; @@ -942,8 +942,8 @@ TEST(TestMatchGeneric, MissingHeaderFooter) { IRrecv irrecv(1); irsend.begin(); - uint16_t entries = 11; - uint16_t data[entries] = { + const uint16_t kentries = 11; + uint16_t data[kentries] = { 8000, // Header mark 4000, // Header space 500, 2000, // Bit #0 (1) @@ -954,7 +954,7 @@ TEST(TestMatchGeneric, MissingHeaderFooter) { uint16_t offset = kStartOffset; irsend.reset(); - irsend.sendRaw(data, entries, 38000); + irsend.sendRaw(data, kentries, 38000); irsend.makeDecodeResult(); uint16_t entries_used = 0; @@ -976,7 +976,7 @@ TEST(TestMatchGeneric, MissingHeaderFooter) { ASSERT_NE(0, entries_used); EXPECT_EQ(0b1010, result_data); EXPECT_EQ(irsend.capture.rawlen - kStartOffset - 1, entries_used); - EXPECT_EQ(entries - 1, entries_used); + EXPECT_EQ(kentries - 1, entries_used); // No header match (should fail) entries_used = irrecv.matchGeneric( @@ -1010,7 +1010,7 @@ TEST(TestMatchGeneric, MissingHeaderFooter) { ASSERT_NE(0, entries_used); EXPECT_EQ(0b1010, result_data); EXPECT_EQ(irsend.capture.rawlen - offset, entries_used); - EXPECT_EQ(entries - 2, entries_used); + EXPECT_EQ(kentries - 2, entries_used); } TEST(TestMatchGeneric, BitOrdering) { @@ -1018,8 +1018,8 @@ TEST(TestMatchGeneric, BitOrdering) { IRrecv irrecv(1); irsend.begin(); - uint16_t entries = 11; - uint16_t data[entries] = { + const uint16_t kentries = 11; + uint16_t data[kentries] = { 8000, // Header mark 4000, // Header space 500, 2000, // Bit #0 (1) @@ -1030,7 +1030,7 @@ TEST(TestMatchGeneric, BitOrdering) { uint16_t offset = kStartOffset; irsend.reset(); - irsend.sendRaw(data, entries, 38000); + irsend.sendRaw(data, kentries, 38000); irsend.makeDecodeResult(); uint16_t entries_used = 0; @@ -1052,7 +1052,7 @@ TEST(TestMatchGeneric, BitOrdering) { ASSERT_NE(0, entries_used); EXPECT_EQ(0b1010, result_data); EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used); - EXPECT_EQ(entries, entries_used); + EXPECT_EQ(kentries, entries_used); // LSB order entries_used = irrecv.matchGeneric( @@ -1070,7 +1070,7 @@ TEST(TestMatchGeneric, BitOrdering) { ASSERT_NE(0, entries_used); EXPECT_EQ(0b0101, result_data); EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used); - EXPECT_EQ(entries, entries_used); + EXPECT_EQ(kentries, entries_used); } TEST(TestMatchGeneric, UsingBytes) { @@ -1078,8 +1078,8 @@ TEST(TestMatchGeneric, UsingBytes) { IRrecv irrecv(1); irsend.begin(); - uint16_t entries = 32; - uint16_t data[entries] = { + const uint16_t kentries = 32; + uint16_t data[kentries] = { // No header 500, 2000, // Byte #0 Bit #0 (1) 500, 1000, // Byte #0 Bit #1 (0) @@ -1100,7 +1100,7 @@ TEST(TestMatchGeneric, UsingBytes) { uint16_t offset = kStartOffset; irsend.reset(); - irsend.sendRaw(data, entries, 38000); + irsend.sendRaw(data, kentries, 38000); irsend.makeDecodeResult(); uint16_t entries_used = 0; @@ -1123,7 +1123,7 @@ TEST(TestMatchGeneric, UsingBytes) { EXPECT_EQ(0b10101010, result_data[0]); EXPECT_EQ(0b11110000, result_data[1]); EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used); - EXPECT_EQ(entries, entries_used); + EXPECT_EQ(kentries, entries_used); // LSB order entries_used = irrecv.matchGeneric( @@ -1142,7 +1142,7 @@ TEST(TestMatchGeneric, UsingBytes) { EXPECT_EQ(0b01010101, result_data[0]); EXPECT_EQ(0b00001111, result_data[1]); EXPECT_EQ(irsend.capture.rawlen - kStartOffset, entries_used); - EXPECT_EQ(entries, entries_used); + EXPECT_EQ(kentries, entries_used); // Asking for too much. entries_used = irrecv.matchGeneric( diff --git a/lib/IRremoteESP8266-2.7.2/test/IRrecv_test.h b/lib/IRremoteESP8266-2.7.3/test/IRrecv_test.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/IRrecv_test.h rename to lib/IRremoteESP8266-2.7.3/test/IRrecv_test.h diff --git a/lib/IRremoteESP8266-2.7.2/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.7.3/test/IRsend_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/IRsend_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/IRsend_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/IRsend_test.h b/lib/IRremoteESP8266-2.7.3/test/IRsend_test.h similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/IRsend_test.h rename to lib/IRremoteESP8266-2.7.3/test/IRsend_test.h diff --git a/lib/IRremoteESP8266-2.7.2/test/IRutils_test.cpp b/lib/IRremoteESP8266-2.7.3/test/IRutils_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/IRutils_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/IRutils_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/Makefile b/lib/IRremoteESP8266-2.7.3/test/Makefile similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/Makefile rename to lib/IRremoteESP8266-2.7.3/test/Makefile diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Aiwa_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Aiwa_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Aiwa_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Aiwa_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Amcor_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Amcor_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Amcor_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Amcor_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Argo_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Argo_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Argo_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Argo_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Carrier_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Carrier_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Carrier_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Carrier_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Coolix_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Coolix_test.cpp similarity index 69% rename from lib/IRremoteESP8266-2.7.2/test/ir_Coolix_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Coolix_test.cpp index 514e16dba..226e1aa68 100644 --- a/lib/IRremoteESP8266-2.7.2/test/ir_Coolix_test.cpp +++ b/lib/IRremoteESP8266-2.7.3/test/ir_Coolix_test.cpp @@ -17,66 +17,66 @@ TEST(TestSendCoolix, SendDataOnly) { irsend.sendCOOLIX(0x0); EXPECT_EQ( "f38000d50" - "m4480s4480" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s5040" - "m4480s4480" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s105040", + "m4692s4416" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s5244" + "m4692s4416" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s105244", irsend.outputStr()); irsend.reset(); irsend.sendCOOLIX(0xAA55AA); EXPECT_EQ( "f38000d50" - "m4480s4480" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s5040" - "m4480s4480" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s105040", + "m4692s4416" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s5244" + "m4692s4416" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s105244", irsend.outputStr()); irsend.reset(); irsend.sendCOOLIX(0xFFFFFF); EXPECT_EQ( "f38000d50" - "m4480s4480" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s5040" - "m4480s4480" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s105040", + "m4692s4416" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s5244" + "m4692s4416" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s105244", irsend.outputStr()); } @@ -89,50 +89,50 @@ TEST(TestSendCoolix, SendWithRepeats) { irsend.sendCOOLIX(0xAA55AA, kCoolixBits, 1); // 1 repeat. EXPECT_EQ( "f38000d50" - "m4480s4480" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s5040" - "m4480s4480" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s105040", + "m4692s4416" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s5244" + "m4692s4416" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s105244", irsend.outputStr()); irsend.sendCOOLIX(0xAA55AA, kCoolixBits, 2); // 2 repeats. EXPECT_EQ( "f38000d50" - "m4480s4480" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s5040" - "m4480s4480" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s5040" - "m4480s4480" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s105040", + "m4692s4416" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s5244" + "m4692s4416" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s5244" + "m4692s4416" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656" + "m552s105244", irsend.outputStr()); } @@ -145,56 +145,56 @@ TEST(TestSendCoolix, SendUnusualSize) { irsend.sendCOOLIX(0x0, 8); EXPECT_EQ( "f38000d50" - "m4480s4480" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s5040" - "m4480s4480" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s105040", + "m4692s4416" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s5244" + "m4692s4416" + "m552s552m552s552m552s552m552s552m552s552m552s552m552s552m552s552" + "m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s105244", irsend.outputStr()); irsend.reset(); irsend.sendCOOLIX(0x1234567890ABCDEF, 64); EXPECT_EQ( "f38000d50" - "m4480s4480" - "m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680m560s560" - "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s1680" - "m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" - "m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560m560s1680" - "m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680" - "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560" - "m560s1680m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" - "m560s560m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" - "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" - "m560s5040" - "m4480s4480" - "m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680m560s560" - "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s1680" - "m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" - "m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560m560s1680" - "m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680" - "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680" - "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560" - "m560s1680m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" - "m560s560m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" - "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" - "m560s560m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" - "m560s105040", + "m4692s4416" + "m552s552m552s552m552s552m552s1656m552s552m552s552m552s1656m552s552" + "m552s1656m552s1656m552s1656m552s552m552s1656m552s1656m552s552m552s1656" + "m552s552m552s552m552s1656m552s1656m552s552m552s1656m552s552m552s552" + "m552s1656m552s1656m552s552m552s552m552s1656m552s552m552s1656m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s552m552s1656" + "m552s552m552s1656m552s1656m552s1656m552s1656m552s552m552s552m552s552" + "m552s1656m552s552m552s552m552s552m552s552m552s1656m552s1656m552s1656" + "m552s1656m552s552m552s552m552s1656m552s552m552s552m552s552m552s552" + "m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s1656m552s1656" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s552" + "m552s1656m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656" + "m552s552m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552" + "m552s1656m552s1656m552s1656m552s552m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s1656m552s552m552s552m552s552m552s552" + "m552s5244" + "m4692s4416" + "m552s552m552s552m552s552m552s1656m552s552m552s552m552s1656m552s552" + "m552s1656m552s1656m552s1656m552s552m552s1656m552s1656m552s552m552s1656" + "m552s552m552s552m552s1656m552s1656m552s552m552s1656m552s552m552s552" + "m552s1656m552s1656m552s552m552s552m552s1656m552s552m552s1656m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s1656m552s552" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s552m552s1656" + "m552s552m552s1656m552s1656m552s1656m552s1656m552s552m552s552m552s552" + "m552s1656m552s552m552s552m552s552m552s552m552s1656m552s1656m552s1656" + "m552s1656m552s552m552s552m552s1656m552s552m552s552m552s552m552s552" + "m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s1656m552s1656" + "m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s1656" + "m552s552m552s1656m552s552m552s1656m552s552m552s1656m552s552m552s552" + "m552s1656m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656" + "m552s552m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552" + "m552s1656m552s1656m552s1656m552s552m552s1656m552s1656m552s1656m552s1656" + "m552s552m552s552m552s552m552s1656m552s552m552s552m552s552m552s552" + "m552s105244", irsend.outputStr()); // Bit sizes must be a multiple of 8. @@ -719,33 +719,33 @@ TEST(TestCoolixACClass, Issue722) { // Raw data supplied by @mariusmotea "f38000d50" // 4434,4376, - "m4480s4480" + "m4692s4416" // 566,1614,592,504,566,1618,566,1616,568,528,564,532,564,1616,568,532, - "m560s1680m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" + "m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552" // 566,530,566,1620,568,528,566,530,566,1618,564,1618,566,530,564,1624, - "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" + "m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656" // 538,560,566,530,564,1620,566,1618,566,1618,566,1616,566,1616,566,1620, - "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m552s552m552s552m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" // 568,1620,566,1616,566,530,566,530,564,530,562,532,564,530,566,530, - "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" + "m552s1656m552s1656m552s552m552s552m552s552m552s552m552s552m552s552" // 566,1622,566,1616,540,1642,566,528,566,530,566,1616,566,530,566,532, - "m560s1680m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s560" + "m552s1656m552s1656m552s1656m552s552m552s552m552s1656m552s552m552s552" // 564,532,564,530,566,530,566,1614,566,1616,562,532,564,1620,566,1618, - "m560s560m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s1680" + "m552s552m552s552m552s552m552s1656m552s1656m552s552m552s1656m552s1656" // 538,5254,4432,4364,566,1616,568,530,564,1620,568,1616,564,532,564,530, - "m560s5040m4480s4480m560s1680m560s560m560s1680m560s1680m560s560m560s560" + "m552s5244m4692s4416m552s1656m552s552m552s1656m552s1656m552s552m552s552" // 566,1616,566,532,564,532,566,1620,568,528,566,530,566,1616,564,1618, - "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m552s1656m552s552m552s552m552s1656m552s552m552s552m552s1656m552s1656" // 566,530,566,1622,566,532,566,528,566,1620,568,1614,566,1618,566,1618, - "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s1656m552s1656" // 566,1614,568,1618,566,1622,568,1616,566,530,564,530,566,530,566,528, - "m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m552s1656m552s1656m552s1656m552s1656m552s552m552s552m552s552m552s552" // 564,530,566,532,566,1622,564,1616,566,1616,564,532,564,530,564,1616, - "m560s560m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s1680" + "m552s552m552s552m552s1656m552s1656m552s1656m552s552m552s552m552s1656" // 564,530,564,532,566,530,564,530,566,528,564,1618,564,1618,564,532, - "m560s560m560s560m560s560m560s560m560s560m560s1680m560s1680m560s560" + "m552s552m552s552m552s552m552s552m552s552m552s1656m552s1656m552s552" // 564,1620,566,1618,562 // Raw data matches what is expected. - "m560s1680m560s1680m560s105040", ac._irsend.outputStr()); + "m552s1656m552s1656m552s105244", ac._irsend.outputStr()); } TEST(TestCoolixACClass, Issue985) { diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Daikin_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Daikin_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Daikin_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Daikin_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Denon_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Denon_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Denon_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Denon_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Dish_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Dish_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Dish_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Dish_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Electra_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Electra_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Electra_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Electra_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Fujitsu_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Fujitsu_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Fujitsu_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Fujitsu_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_GICable_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_GICable_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_GICable_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_GICable_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_GlobalCache_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_GlobalCache_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_GlobalCache_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_GlobalCache_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Goodweather_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Goodweather_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Goodweather_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Goodweather_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Gree_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Gree_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Gree_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Gree_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Haier_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Haier_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Haier_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Haier_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Hitachi_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Hitachi_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Hitachi_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Hitachi_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Inax_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Inax_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Inax_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Inax_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_JVC_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_JVC_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_JVC_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_JVC_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Kelvinator_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Kelvinator_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Kelvinator_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Kelvinator_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_LG_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_LG_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_LG_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_LG_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Lasertag_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Lasertag_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Lasertag_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Lasertag_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Lego_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Lego_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Lego_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Lego_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Lutron_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Lutron_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Lutron_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Lutron_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_MWM_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_MWM_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_MWM_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_MWM_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Magiquest_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Magiquest_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Magiquest_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Magiquest_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Midea_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Midea_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Midea_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Midea_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_MitsubishiHeavy_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_MitsubishiHeavy_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_MitsubishiHeavy_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_MitsubishiHeavy_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Mitsubishi_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Mitsubishi_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Mitsubishi_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Mitsubishi_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_NEC_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_NEC_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_NEC_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_NEC_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Neoclima_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Neoclima_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Neoclima_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Neoclima_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Nikai_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Nikai_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Nikai_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Nikai_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Panasonic_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Panasonic_test.cpp similarity index 96% rename from lib/IRremoteESP8266-2.7.2/test/ir_Panasonic_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Panasonic_test.cpp index 471a324c8..97f9bbb28 100644 --- a/lib/IRremoteESP8266-2.7.2/test/ir_Panasonic_test.cpp +++ b/lib/IRremoteESP8266-2.7.3/test/ir_Panasonic_test.cpp @@ -736,6 +736,26 @@ TEST(TestIRPanasonicAcClass, QuietAndPowerful) { EXPECT_FALSE(pana.getPowerful()); } +TEST(TestIRPanasonicAcClass, SetAndGetIon) { + IRPanasonicAc ac(0); + // Ion Filter only works for DKE. + ac.setModel(kPanasonicDke); + ac.setIon(true); + EXPECT_TRUE(ac.getIon()); + ac.setIon(false); + EXPECT_FALSE(ac.getIon()); + ac.setIon(true); + EXPECT_TRUE(ac.getIon()); + + // Now try a different (a guess at unsupported) model. + ac.setModel(kPanasonicRkr); + EXPECT_FALSE(ac.getIon()); + ac.setIon(true); + EXPECT_FALSE(ac.getIon()); + ac.setIon(false); + EXPECT_FALSE(ac.getIon()); +} + TEST(TestIRPanasonicAcClass, HumanReadable) { IRPanasonicAc pana(0); EXPECT_EQ( @@ -767,7 +787,7 @@ TEST(TestIRPanasonicAcClass, HumanReadable) { EXPECT_EQ( "Model: 3 (DKE), Power: Off, Mode: 4 (Heat), Temp: 30C, " "Fan: 4 (High), Swing(V): 15 (Auto), " - "Swing(H): 11 (Right), Quiet: On, Powerful: Off, " + "Swing(H): 11 (Right), Quiet: On, Powerful: Off, Ion: Off, " "Clock: 00:00, On Timer: Off, Off Timer: Off", pana.toString()); } @@ -1180,3 +1200,38 @@ TEST(TestIRPanasonicAcClass, toCommon) { ASSERT_EQ(kPanasonicAcSwingVMiddle, IRPanasonicAc::convertSwingV(stdAc::swingv_t::kMiddle)); } + +// +// Test for DKE/DKW model / see issue #1024 +TEST(TestDecodePanasonicAC, DkeIonRealMessages) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Data from Issue #1024 + // 0x0220E004000000060220E004004F3280AF0D000660000001000630 + uint8_t dkeIonOff[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x4F, 0x32, 0x80, 0xAF, 0x0D, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x01, 0x00, 0x06, 0x30}; + + // 0x0220E004000000060220E004004F3280AF0D000660000101000631 + uint8_t dkeIonOn[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x4F, 0x32, 0x80, 0xAF, 0x0D, + 0x00, 0x06, 0x60, 0x00, 0x01, 0x01, 0x00, 0x06, 0x31}; + + IRPanasonicAc ac(0); + ac.setRaw(dkeIonOff); + EXPECT_EQ( + "Model: 3 (DKE), Power: On, Mode: 4 (Heat), Temp: 25C, Fan: 7 (Auto), " + "Swing(V): 15 (Auto), Swing(H): 13 (Auto), Quiet: Off, Powerful: Off, " + "Ion: Off, Clock: 00:00, On Timer: 00:00, Off Timer: 00:00", + ac.toString()); + ac.setRaw(dkeIonOn); + EXPECT_EQ( + "Model: 3 (DKE), Power: On, Mode: 4 (Heat), Temp: 25C, Fan: 7 (Auto), " + "Swing(V): 15 (Auto), Swing(H): 13 (Auto), Quiet: Off, Powerful: Off, " + "Ion: On, Clock: 00:00, On Timer: 00:00, Off Timer: 00:00", + ac.toString()); +} diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Pioneer_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Pioneer_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Pioneer_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Pioneer_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Pronto_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Pronto_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Pronto_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Pronto_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_RC5_RC6_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_RC5_RC6_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_RC5_RC6_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_RC5_RC6_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_RCMM_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_RCMM_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_RCMM_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_RCMM_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Samsung_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Samsung_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Samsung_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Samsung_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Sanyo_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Sanyo_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Sanyo_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Sanyo_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Sharp_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Sharp_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Sharp_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Sharp_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Sherwood_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Sherwood_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Sherwood_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Sherwood_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Sony_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Sony_test.cpp similarity index 61% rename from lib/IRremoteESP8266-2.7.2/test/ir_Sony_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Sony_test.cpp index 51bacbd6d..18fc58334 100644 --- a/lib/IRremoteESP8266-2.7.2/test/ir_Sony_test.cpp +++ b/lib/IRremoteESP8266-2.7.3/test/ir_Sony_test.cpp @@ -360,3 +360,228 @@ TEST(TestEncodeSony, Issue476) { EXPECT_EQ(0xE2, (0x7156 >> 7) & 0xFF); // extended (top 8 of 15 bits) EXPECT_EQ(0x6AB47, irsend.encodeSony(20, 0x56, 0x1A, 0xE2)); } + +// Encoding & Decode 15 bit Sony messages. Issue #1018 +TEST(TestEncodeSony, Issue1018) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendSony(0x240C, 15); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(15, irsend.capture.bits); + EXPECT_EQ(0x240C, irsend.capture.value); // 15 bits + EXPECT_EQ(0x30, irsend.capture.address); + EXPECT_EQ(0x12, irsend.capture.command); + EXPECT_EQ( + "f40000d33" + "m2400s600" // Message + "m600s600m1200s600m600s600m600s600m1200s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200" + "m2400s600" // Repeat #1 + "m600s600m1200s600m600s600m600s600m1200s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200" + "m2400s600" // Repeat #2 + "m600s600m1200s600m600s600m600s600m1200s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200", + irsend.outputStr()); + + irsend.reset(); + uint16_t rawData[127] = { + 2448, 550, + 648, 544, 1250, 546, 648, 548, 648, 550, 1272, 524, 648, 550, 644, 550, + 674, 524, 648, 550, 648, 544, 674, 524, 1270, 524, 1246, 550, 674, 524, + 648, 22404, + 2474, 524, + 674, 520, 1250, 548, 648, 544, 674, 524, 1270, 524, 648, 550, 648, 546, + 674, 524, 648, 546, 652, 546, 674, 524, 1270, 524, 1272, 522, 674, 520, + 648, 22404, + 2452, 544, + 674, 524, 1270, 524, 674, 518, 674, 522, 1246, 550, 674, 524, 648, 544, + 674, 524, 648, 546, 674, 524, 674, 518, 1276, 518, 1276, 524, 648, 546, + 674, 22380, + 2474, 520, + 674, 524, 1250, 544, 674, 524, 674, 518, 1276, 520, 674, 522, 674, 524, + 674, 520, 674, 524, 674, 524, 674, 518, 1276, 518, 1276, 524, 672, 524, + 648}; // SONY 240C + + irsend.sendRaw(rawData, 127, 40); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(15, irsend.capture.bits); + EXPECT_EQ(0x240C, irsend.capture.value); // 15 bits + EXPECT_EQ(0x30, irsend.capture.address); + EXPECT_EQ(0x12, irsend.capture.command); + EXPECT_EQ( + "f40000d50" + "m2448s550" // Message + "m648s544m1250s546m648s548m648s550m1272s524m648s550m644s550" + "m674s524m648s550m648s544m674s524m1270s524m1246s550m674s524" + "m648s22404" + "m2474s524" // Repeat #1 + "m674s520m1250s548m648s544m674s524m1270s524m648s550m648s546" + "m674s524m648s546m652s546m674s524m1270s524m1272s522m674s520" + "m648s22404" + "m2452s544" // Repeat #2 + "m674s524m1270s524m674s518m674s522m1246s550m674s524m648s544" + "m674s524m648s546m674s524m674s518m1276s518m1276s524m648s546" + "m674s22380" + "m2474s520" // Repeat #3 + "m674s524m1250s544m674s524m674s518m1276s520m674s522m674s524" + "m674s520m674s524m674s524m674s518m1276s518m1276s524m672s524" + "m648", + irsend.outputStr()); + + // Now see if we can reproduce it with `sendSony` + irsend.reset(); + irsend.sendSony(0x240C, 15, 3); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(15, irsend.capture.bits); + EXPECT_EQ(0x240C, irsend.capture.value); // 15 bits + EXPECT_EQ(0x30, irsend.capture.address); + EXPECT_EQ(0x12, irsend.capture.command); + + // Compare expected result with real `rawData` result. + // Comparison notes: + // * Seems visually the same. i.e. '1' where '1's should be etc. + // * Timings are *roughly* the same. They should be within device + // tollerance. + // TL;DR: Looks fine/the same/as expected. + EXPECT_EQ( + "f40000d33" + "m2400s600" // Message + // "m2448s550" (Commented out data is from `rawData` sample above.) + "m600s600m1200s600m600s600m600s600m1200s600m600s600m600s600" + // "m648s544m1250s546m648s548m648s550m1272s524m648s550m644s550" + "m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + // "m674s524m648s550m648s544m674s524m1270s524m1246s550m674s524" + "m600s22200" + // "m648s22404" + "m2400s600" // Repeat #1 + // "m2474s524" + "m600s600m1200s600m600s600m600s600m1200s600m600s600m600s600" + // "m674s520m1250s548m648s544m674s524m1270s524m648s550m648s546" + "m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + // "m674s524m648s546m652s546m674s524m1270s524m1272s522m674s520" + "m600s22200" + // "m648s22404" + "m2400s600" // Repeat #2 + // "m2452s544" + "m600s600m1200s600m600s600m600s600m1200s600m600s600m600s600" + // "m674s524m1270s524m674s518m674s522m1246s550m674s524m648s544" + "m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + // "m674s524m648s546m674s524m674s518m1276s518m1276s524m648s546" + "m600s22200" + // "m674s22380" + "m2400s600" // Repeat #3 + // "m2474s520" + "m600s600m1200s600m600s600m600s600m1200s600m600s600m600s600" + // "m674s524m1250s544m674s524m674s518m1276s520m674s522m674s524" + "m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + // "m674s520m674s524m674s524m674s518m1276s518m1276s524m672s524" + "m600s22200", + // "m648" // (Trailing space is ignored in real captures.) + irsend.outputStr()); + + // Now see if we can reproduce it with `sendSony38` + irsend.reset(); + irsend.sendSony38(0x240C, 15); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(15, irsend.capture.bits); + EXPECT_EQ(0x240C, irsend.capture.value); // 15 bits + EXPECT_EQ(0x30, irsend.capture.address); + EXPECT_EQ(0x12, irsend.capture.command); +} + +// Test sending typical data only. +TEST(TestSendSony38, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendSony38(0); + // We expect three 20-bit commands to be sent. + EXPECT_EQ( + "f38000d33" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s18600" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s18600" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s18600" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s18600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendSony38(0x240C, kSony20Bits); + // We expect three 20-bit commands to be sent. + EXPECT_EQ( + "f38000d33" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200", + irsend.outputStr()); + + irsend.reset(); + irsend.sendSony38(0x240C, kSony15Bits); + // We expect three 15-bit commands to be sent. + EXPECT_EQ( + "f38000d33" + "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200" + "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200" + "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200" + "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200", + irsend.outputStr()); + + irsend.reset(); + irsend.sendSony38(0xA90, kSony12Bits); + // We expect three 15-bit commands to be sent. + EXPECT_EQ( + "f38000d33" + "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" + "m600s600m1200s600m600s600m600s600m600s600m600s25800" + "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" + "m600s600m1200s600m600s600m600s600m600s600m600s25800" + "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" + "m600s600m1200s600m600s600m600s600m600s600m600s25800" + "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" + "m600s600m1200s600m600s600m600s600m600s600m600s25800", + irsend.outputStr()); +} diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Tcl_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Tcl_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Tcl_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Tcl_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Teco_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Teco_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Teco_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Teco_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Toshiba_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Toshiba_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Toshiba_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Toshiba_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Trotec_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Trotec_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Trotec_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Trotec_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Vestel_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Vestel_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Vestel_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Vestel_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Whirlpool_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Whirlpool_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Whirlpool_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Whirlpool_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/test/ir_Whynter_test.cpp b/lib/IRremoteESP8266-2.7.3/test/ir_Whynter_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/test/ir_Whynter_test.cpp rename to lib/IRremoteESP8266-2.7.3/test/ir_Whynter_test.cpp diff --git a/lib/IRremoteESP8266-2.7.2/tools/Makefile b/lib/IRremoteESP8266-2.7.3/tools/Makefile similarity index 100% rename from lib/IRremoteESP8266-2.7.2/tools/Makefile rename to lib/IRremoteESP8266-2.7.3/tools/Makefile diff --git a/lib/IRremoteESP8266-2.7.2/tools/RawToGlobalCache.sh b/lib/IRremoteESP8266-2.7.3/tools/RawToGlobalCache.sh similarity index 100% rename from lib/IRremoteESP8266-2.7.2/tools/RawToGlobalCache.sh rename to lib/IRremoteESP8266-2.7.3/tools/RawToGlobalCache.sh diff --git a/lib/IRremoteESP8266-2.7.2/tools/auto_analyse_raw_data.py b/lib/IRremoteESP8266-2.7.3/tools/auto_analyse_raw_data.py similarity index 97% rename from lib/IRremoteESP8266-2.7.2/tools/auto_analyse_raw_data.py rename to lib/IRremoteESP8266-2.7.3/tools/auto_analyse_raw_data.py index d673d52d4..5bea3926a 100755 --- a/lib/IRremoteESP8266-2.7.2/tools/auto_analyse_raw_data.py +++ b/lib/IRremoteESP8266-2.7.3/tools/auto_analyse_raw_data.py @@ -65,6 +65,8 @@ class RawIRMessage(): def _usec_compare(self, seen, expected): """Compare two usec values and see if they match within a subtractive margin.""" + if expected is None: + return False return expected - self.margin < seen <= expected def _usec_compares(self, usecs, expecteds): @@ -214,19 +216,25 @@ class RawIRMessage(): if len(self.marks) > 2: # Possible leader mark? self.ldr_mark = self.marks[0] self.hdr_mark = self.marks[1] - else: + elif len(self.marks) > 1: # At least two marks # Largest mark is likely the kHdrMark self.hdr_mark = self.marks[0] + else: + # Probably no header mark. + self.hdr_mark = 0 - if self.is_space_encoded() and len(self.spaces) >= 3: + if self.is_space_encoded() and len(self.spaces) >= 2: if self.verbose and len(self.marks) > 2: self.output.write("DANGER: Unusual number of mark timings!") # We should have 3 space candidates at least. # They should be: zero_space (smallest), one_space, & hdr_space (largest) spaces = list(self.spaces) - self.zero_space = spaces.pop() - self.one_space = spaces.pop() - self.hdr_space = spaces.pop() + if spaces: + self.zero_space = spaces.pop() + if spaces: + self.one_space = spaces.pop() + if spaces: + self.hdr_space = spaces.pop() # Rest are probably message gaps self.gaps = spaces @@ -302,11 +310,15 @@ def convert_rawdata(data_str): def dump_constants(message, defines, name="", output=sys.stdout): """Dump the key constants and generate the C++ #defines.""" ldr_mark = None + hdr_mark = 0 + hdr_space = 0 if message.ldr_mark is not None: ldr_mark = avg_list(message.mark_buckets[message.ldr_mark]) - hdr_mark = avg_list(message.mark_buckets[message.hdr_mark]) + if message.hdr_mark != 0: + hdr_mark = avg_list(message.mark_buckets[message.hdr_mark]) bit_mark = avg_list(message.mark_buckets[message.bit_mark]) - hdr_space = avg_list(message.space_buckets[message.hdr_space]) + if message.hdr_space is not None: + hdr_space = avg_list(message.space_buckets[message.hdr_space]) one_space = avg_list(message.space_buckets[message.one_space]) zero_space = avg_list(message.space_buckets[message.zero_space]) diff --git a/lib/IRremoteESP8266-2.7.2/tools/auto_analyse_raw_data_test.py b/lib/IRremoteESP8266-2.7.3/tools/auto_analyse_raw_data_test.py similarity index 84% rename from lib/IRremoteESP8266-2.7.2/tools/auto_analyse_raw_data_test.py rename to lib/IRremoteESP8266-2.7.3/tools/auto_analyse_raw_data_test.py index c2fd7ba64..fa3a87933 100755 --- a/lib/IRremoteESP8266-2.7.2/tools/auto_analyse_raw_data_test.py +++ b/lib/IRremoteESP8266-2.7.3/tools/auto_analyse_raw_data_test.py @@ -1165,6 +1165,224 @@ class TestAutoAnalyseRawData(unittest.TestCase): '}\n' '#endif // DECODE_FOO\n') + def test_no_headers(self): + """Tests for no space or mark headers in parse_and_report() function.""" + + # Tests for mark or space headers. (Issue #1014) + output = StringIO() + input_str = """ + uint16_t rawData[257] = {472, 1016, 490, 536, 446, 1038, 464, 544, 490, + 516, 492, 1008, 418, 592, 462, 1042, 476, 532, 444, 1062, 474, 532, 470, + 1014, 492, 1010, 446, 562, 460, 1046, 474, 532, 472, 534, 416, 590, 458, + 548, 486, 520, 490, 516, 490, 534, 470, 534, 470, 534, 470, 536, 416, + 590, 460, 546, 488, 518, 490, 536, 468, 536, 470, 534, 470, 536, 442, + 564, 414, 1092, 470, 536, 468, 536, 416, 590, 414, 592, 486, 520, 490, + 536, 470, 534, 470, 534, 468, 536, 416, 590, 432, 574, 486, 520, 490, + 536, 470, 534, 468, 536, 468, 536, 468, 538, 420, 590, 454, 546, 488, + 518, 488, 536, 468, 536, 468, 536, 468, 536, 440, 566, 414, 592, 462, + 546, 490, 536, 468, 536, 468, 538, 468, 536, 468, 538, 414, 592, 460, + 546, 488, 518, 490, 536, 468, 536, 470, 536, 468, 536, 442, 564, 414, + 592, 462, 546, 490, 518, 488, 536, 470, 534, 470, 536, 470, 536, 416, + 590, 460, 548, 488, 518, 490, 536, 470, 534, 470, 534, 470, 536, 468, + 536, 414, 592, 462, 546, 490, 518, 488, 534, 470, 536, 468, 536, 468, + 536, 414, 590, 462, 546, 488, 518, 466, 560, 444, 560, 446, 560, 446, + 560, 444, 562, 416, 592, 462, 546, 464, 542, 464, 560, 444, 560, 446, + 560, 446, 560, 416, 590, 460, 546, 464, 544, 464, 562, 444, 560, 446, + 560, 446, 560, 444, 560, 416, 592, 462, 1042, 446, 560, 444, 560, 416, + 592, 462, 544, 488, 520, 466, 558, 446, 560, 446};""" + analyse.parse_and_report(input_str, 200, True, "", output) + self.assertEqual( + output.getvalue(), 'Found 257 timing entries.\n' + 'Potential Mark Candidates:\n' + '[492]\n' + 'Potential Space Candidates:\n' + '[1092, 592]\n' + '\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kHdrMark = 0\n' + 'kHdrSpace = 0\n' + 'kBitMark = 460\n' + 'kOneSpace = 1037\n' + 'kZeroSpace = 547\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kBitMark(UNEXPECTED)10100101010110100000000000000000010000000000000000' + '0000000000000000000000000000000000000000000000000000000000000000000000' + '10000000\n' + ' Bits: 128\n' + ' Hex: 0xA55A0000400000000000000000000080 (MSB first)\n' + ' 0x01000000000000000000000200005AA5 (LSB first)\n' + ' Dec: 219789926041586294144261994014272651392 (MSB first)\n' + ' 1329227995784915872903807068870302373 (LSB first)\n' + ' Bin: 0b101001010101101000000000000000000100000000000000000000000000' + '00000000000000000000000000000000000000000000000000000000000010000000' + ' (MSB first)\n' + ' 0b000000010000000000000000000000000000000000000000000000000000' + '00000000000000000000000000000000001000000000000000000101101010100101' + ' (LSB first)\n' + '\n' + 'Total Nr. of suspected bits: 128\n' + '\n' + 'Generating a VERY rough code outline:\n' + '\n' + '// Copyright 2019 David Conran (crankyoldgit)\n' + '// Support for TBD protocol\n' + '\n' + '#include "IRrecv.h"\n' + '#include "IRsend.h"\n' + '#include "IRutils.h"\n' + '\n' + "// WARNING: This probably isn't directly usable. It's a guide only.\n" + '\n' + '// See https://github.com/crankyoldgit/IRremoteESP8266/wiki/' + 'Adding-support-for-a-new-IR-protocol\n' + '// for details of how to include this in the library.\n' + 'const uint16_t kHdrMark = 0;\n' + 'const uint16_t kBitMark = 460;\n' + 'const uint16_t kHdrSpace = 0;\n' + 'const uint16_t kOneSpace = 1037;\n' + 'const uint16_t kZeroSpace = 547;\n' + 'const uint16_t kFreq = 38000; // Hz. (Guessing the most common' + ' frequency.)\n' + 'const uint16_t kBits = 128; // Move to IRremoteESP8266.h\n' + 'const uint16_t kStateLength = 16; // Move to IRremoteESP8266.h\n' + 'const uint16_t kOverhead = 1;\n' + "// DANGER: More than 64 bits detected. A uint64_t for 'data' won't" + ' work!\n' + '#if SEND_TBD\n' + '// Function should be safe up to 64 bits.\n' + 'void IRsend::sendTBD(const uint64_t data, const uint16_t nbits, const' + ' uint16_t repeat) {\n' + ' enableIROut(kFreq);\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' uint64_t send_data = data;\n' + ' // Data Section #1\n' + ' // e.g. data = 0xA55A0000400000000000000000000080, nbits = 128\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, send_data,' + ' 128, true);\n' + ' send_data >>= 128;\n' + ' // Footer\n' + ' mark(kBitMark);\n' + ' space(kDefaultMessageGap); // A 100% made up guess of the gap' + ' between messages.\n' + ' }\n' + '}\n' + '#endif // SEND_TBD\n' + '\n' + '#if SEND_TBD\n' + '// Alternative >64bit function to send TBD messages\n' + '// Where data is:\n' + '// uint8_t data[kStateLength] = {0xA5, 0x5A, 0x00, 0x00, 0x40, 0x00,' + ' 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80};\n' + '//\n' + '// Args:\n' + '// data: An array of bytes containing the IR command.\n' + '// It is assumed to be in MSB order for this code.\n' + '// nbytes: Nr. of bytes of data in the array. (>=kStateLength)\n' + '// repeat: Nr. of times the message is to be repeated.\n' + '//\n' + '// Status: ALPHA / Untested.\n' + 'void IRsend::sendTBD(const uint8_t data[], const uint16_t nbytes,' + ' const uint16_t repeat) {\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' uint16_t pos = 0;\n' + ' // Data Section #1\n' + ' // e.g.\n' + ' // bits = 128; bytes = 16;\n' + ' // *(data + pos) = {0xA5, 0x5A, 0x00, 0x00, 0x40, 0x00, 0x00,' + ' 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80};\n' + ' sendGeneric(0, 0,\n' + ' kBitMark, kOneSpace,\n' + ' kBitMark, kZeroSpace,\n' + ' kBitMark, kDefaultMessageGap,\n' + ' data + pos, 16, // Bytes\n' + ' kFreq, true, kNoRepeat, kDutyDefault);\n' + ' pos += 16; // Adjust by how many bytes of data we sent\n' + ' }\n' + '}\n' + '#endif // SEND_TBD\n' + '\n' + "// DANGER: More than 64 bits detected. A uint64_t for 'data' won't" + ' work!\n' + '#if DECODE_TBD\n' + '// Function should be safe up to 64 bits.\n' + 'bool IRrecv::decodeTBD(decode_results *results, const uint16_t nbits,' + ' const bool strict) {\n' + ' if (results->rawlen < 2 * nbits + kOverhead)\n' + ' return false; // Too short a message to match.\n' + ' if (strict && nbits != kBits)\n' + ' return false;\n' + '\n' + ' uint16_t offset = kStartOffset;\n' + ' uint64_t data = 0;\n' + ' match_result_t data_result;\n' + '\n' + ' // Data Section #1\n' + ' // e.g. data_result.data = 0xA55A0000400000000000000000000080, nbits' + ' = 128\n' + ' data_result = matchData(&(results->rawbuf[offset]), 128,\n' + ' kBitMark, kOneSpace,\n' + ' kBitMark, kZeroSpace);\n' + ' offset += data_result.used;\n' + ' if (data_result.success == false) return false; // Fail\n' + ' data <<= 128; // Make room for the new bits of data.\n' + ' data |= data_result.data;\n' + '\n' + ' // Footer\n' + ' if (!matchMark(results->rawbuf[offset++], kBitMark))\n' + ' return false;\n' + '\n' + ' // Success\n' + ' results->decode_type = decode_type_t::TBD;\n' + ' results->bits = nbits;\n' + ' results->value = data;\n' + ' results->command = 0;\n' + ' results->address = 0;\n' + ' return true;\n' + '}\n' + '#endif // DECODE_TBD\n' + '\n' + '// Note: This should be 64+ bit safe.\n' + '#if DECODE_TBD\n' + '// Function should be safe over 64 bits.\n' + 'bool IRrecv::decodeTBD(decode_results *results, const uint16_t nbits,' + ' const bool strict) {\n' + ' if (results->rawlen < 2 * nbits + kOverhead)\n' + ' return false; // Too short a message to match.\n' + ' if (strict && nbits != kBits)\n' + ' return false;\n' + '\n' + ' uint16_t offset = kStartOffset;\n' + ' uint16_t pos = 0;\n' + ' uint16_t used = 0;\n' + '\n' + ' // Data Section #1\n' + ' // e.g.\n' + ' // bits = 128; bytes = 16;\n' + ' // *(results->state + pos) = {0xA5, 0x5A, 0x00, 0x00, 0x40, 0x00,' + ' 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80};\n' + ' used = matchGeneric(results->rawbuf + offset, results->state + pos,' + '\n' + ' results->rawlen - offset, 128,\n' + ' 0, 0,\n' + ' kBitMark, kOneSpace,\n' + ' kBitMark, kZeroSpace,\n' + ' kBitMark, kDefaultMessageGap, true);\n' + ' if (used == 0) return false; // We failed to find any data.\n' + ' offset += used; // Adjust for how much of the message we read.\n' + ' pos += 16; // Adjust by how many bytes of data we read\n' + '\n' + ' // Success\n' + ' results->decode_type = decode_type_t::TBD;\n' + ' results->bits = nbits;\n' + ' return true;\n' + '}\n' + '#endif // DECODE_TBD\n') + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/lib/IRremoteESP8266-2.7.2/tools/gc_decode.cpp b/lib/IRremoteESP8266-2.7.3/tools/gc_decode.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/tools/gc_decode.cpp rename to lib/IRremoteESP8266-2.7.3/tools/gc_decode.cpp diff --git a/lib/IRremoteESP8266-2.7.2/tools/generate_irtext_h.sh b/lib/IRremoteESP8266-2.7.3/tools/generate_irtext_h.sh similarity index 100% rename from lib/IRremoteESP8266-2.7.2/tools/generate_irtext_h.sh rename to lib/IRremoteESP8266-2.7.3/tools/generate_irtext_h.sh diff --git a/lib/IRremoteESP8266-2.7.2/tools/mkkeywords b/lib/IRremoteESP8266-2.7.3/tools/mkkeywords similarity index 100% rename from lib/IRremoteESP8266-2.7.2/tools/mkkeywords rename to lib/IRremoteESP8266-2.7.3/tools/mkkeywords diff --git a/lib/IRremoteESP8266-2.7.2/tools/mode2_decode.cpp b/lib/IRremoteESP8266-2.7.3/tools/mode2_decode.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.2/tools/mode2_decode.cpp rename to lib/IRremoteESP8266-2.7.3/tools/mode2_decode.cpp diff --git a/lib/IRremoteESP8266-2.7.2/tools/scrape_supported_devices.py b/lib/IRremoteESP8266-2.7.3/tools/scrape_supported_devices.py similarity index 76% rename from lib/IRremoteESP8266-2.7.2/tools/scrape_supported_devices.py rename to lib/IRremoteESP8266-2.7.3/tools/scrape_supported_devices.py index a0efd0774..c859bbf06 100755 --- a/lib/IRremoteESP8266-2.7.2/tools/scrape_supported_devices.py +++ b/lib/IRremoteESP8266-2.7.3/tools/scrape_supported_devices.py @@ -9,14 +9,16 @@ import time CODE_URL = "https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_" BRAND_MODEL = re.compile(r"Brand: *(?P.+), *Model: *(?P.+)") -ENUMS = re.compile(r"enum \w+ {(.+?)};", re.DOTALL) +ENUMS = re.compile(r"enum (\w+) {(.+?)};", re.DOTALL) ENUM_ENTRY = re.compile(r"^\s+(\w+)", re.MULTILINE) -DECODED_PROTOCOLS = re.compile(r".*results->decode_type *=.*?(\w+);") +DECODED_PROTOCOLS = re.compile(r".*(?:results->decode_type *=.*?|" + r"typeguess\s*=\s*decode_type_t::)(\w+);") AC_FN = re.compile(r"ir_(.+)\.h") - +AC_MODEL_ENUM_RE = re.compile(r"(.+)_ac_remote_model_t") +IRSEND_FN_RE = re.compile(r"IRsend\.h") ALL_FN = re.compile(r"ir_(.+)\.(h|cpp)") -EXCLUDED_PROTOCOLS = ["UNKNOWN", "UNUSED", "kLastDecodeType"] +EXCLUDED_PROTOCOLS = ["UNKNOWN", "UNUSED", "kLastDecodeType", "typeguess"] EXCLUDED_ACS = ["Magiquest", "NEC"] MARKDOWN_HEADER = """