From 41a4d2d771d3c1fa009b8071949c883a2ab5d563 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Wed, 23 Oct 2019 13:43:10 +0200 Subject: [PATCH 001/196] Remove 1MB no SPIFFS... explanations since default supported core is pre 2.6. For platformio the needed linker script for core 2.3.0 is included Explanation is littering the readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59cce39ab..489638ec0 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Download one of the released binaries from https://github.com/arendst/Sonoff-Tas If you want to compile Sonoff-Tasmota yourself keep in mind the following: - Only Flash Mode **DOUT** is supported. Do not use Flash Mode DIO / QIO / QOUT as it might seem to brick your device. See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Flashing) for background information. -- Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. If you compile using ESP/Arduino library 2.3.0 then download the provided new linker script to your Arduino IDE or Platformio base folder. Later versions of ESP/Arduino library already contain the correct linker script. See [Wiki > Prerequisites](https://github.com/arendst/Sonoff-Tasmota/wiki/Prerequisites). +- Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. - To make compile time changes to Sonoff-Tasmota it can use the ``user_config_override.h`` file. It assures keeping your settings when you download and compile a new version. To use ``user_config.override.h`` you will have to make a copy of the provided ``user_config_override_sample.h`` file and add your setting overrides. To enable the override file you will need to use a compile define as documented in the ``user_config_override_sample.h`` file. ## Configuration Information From 312ee893f51918c6e573f7631d81d639dbb2d877 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 23 Oct 2019 16:06:15 +0200 Subject: [PATCH 002/196] Prep release 6.7 --- README.md | 28 ++++++++--- RELEASENOTES.md | 121 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 59cce39ab..2da0e0a01 100644 --- a/README.md +++ b/README.md @@ -25,11 +25,11 @@ In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/r See [sonoff/_changelog.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_changelog.ino) for detailed change information. -Unless your Tasmota powered device exhibits a problem or you need to make use of a feature that is not available in the Tasmota version currently installed on your device, leave your device alone - it works so don't make unnecessary changes! If the release version (i.e., the master branch) exhibits unexpected behaviour for your device and configuration, you should upgrade to the latest development version instead to see if your problem is resolved as some bugs in previous releases or development builds may already have been resolved. +Unless your Tasmota powered device exhibits a problem or you need to make use of a feature that is not available in the Tasmota version currently installed on your device, leave your device alone - it works so don't make unnecessary changes! If the release version (i.e., the master branch) exhibits unexpected behaviour for your device and configuration, you should upgrade to the latest development version instead to see if your problem is resolved as some bugs in previous releases or development builds may already have been resolved. -The Tasmota development codebase is checked every 1-2 hours for changes. If new commits have been merged and they compile successfuly, new binary files for every variant (excluding non-English languages) will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA updates too). The last compiled commit number is also indicated on the same page. It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with all the available configuration options permitted. +The Tasmota development codebase is checked every 1-2 hours for changes. If new commits have been merged and they compile successfuly, new binary files for every variant (excluding non-English languages) will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA updates too). The last compiled commit number is also indicated on the same page. It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with all the available configuration options permitted. -Note that there is a chance, as with any upgrade, that the device may not function as expected. You must always account for the possibility that you may need to flash the device via the serial programming interface if the OTA upgrade fails. Even with the master release, you should always attempt to test the device or a similar prototype before upgrading a device which is in production or is hard to reach. And, as always, make a backup of the device configuration before beginning any firmware update. +Note that there is a chance, as with any upgrade, that the device may not function as expected. You must always account for the possibility that you may need to flash the device via the serial programming interface if the OTA upgrade fails. Even with the master release, you should always attempt to test the device or a similar prototype before upgrading a device which is in production or is hard to reach. And, as always, make a backup of the device configuration before beginning any firmware update. ## Disclaimer :warning: **DANGER OF ELECTROCUTION** :warning: @@ -88,17 +88,26 @@ Libraries used with Sonoff-Tasmota are: - [Adafruit CCS811](https://github.com/adafruit/Adafruit_CCS811) - [Adafruit ILI9341](https://github.com/adafruit/Adafruit_ILI9341) - [Adafruit LED Backpack](https://github.com/adafruit/Adafruit-LED-Backpack-Library) +- [Adafruit MAX31865](https://github.com/adafruit/Adafruit_MAX31865) - [Adafruit SGP30](https://github.com/adafruit/Adafruit_SGP30) +- Adafruit based SH1106 - [Adafruit SSD1306](https://github.com/adafruit/Adafruit_SSD1306) +- Adafruit based SSD1351 - [Adafruit GFX](https://github.com/adafruit/Adafruit-GFX-Library) +- Arduino Hex Parser - [ArduinoJson](https://arduinojson.org/) +- AT24C256 I2C eeprom +- [Base64](https://github.com/Densaugeo/base64_arduino) +- [Bear SSL](https://github.com/earlephilhower/bearssl-esp8266.git) - [Bosch BME680](https://github.com/BoschSensortec/BME680_driver) - [C2 Programmer](http://app.cear.ufpb.br/~lucas.hartmann/tag/efm8bb1/) - [esp-epaper-29-ws-20171230-gemu](https://github.com/gemu2015/Sonoff-Tasmota/tree/displays/lib) - [esp-knx-ip](https://github.com/envy/esp-knx-ip) - FrogmoreScd30 +- FT6236 - [I2Cdevlib](https://github.com/jrowberg/i2cdevlib) - [IRremoteEsp8266](https://github.com/markszabo/IRremoteESP8266) +- [JaretBurkett ILI9488](https://github.com/jaretburkett/ILI9488) - [JobaTsl2561](https://github.com/joba-1/Joba_Tsl2561) - [LinkedList](https://github.com/ivanseidel/LinkedList) - [Liquid Cristal](https://github.com/marcoschwartz/LiquidCrystal_I2C) @@ -108,6 +117,10 @@ Libraries used with Sonoff-Tasmota are: - [OneWire](https://github.com/PaulStoffregen/OneWire) - [PubSubClient](https://github.com/knolleary/pubsubclient) - [rc-switch](https://github.com/sui77/rc-switch) +- TasmotaModbus +- TasmotaSerial +- [Vl53l0x](https://github.com/pololu/vl53l0x-arduino) +- Xlatb Ra8876 ### People inspiring me People helping to keep the show on the road: @@ -132,12 +145,13 @@ People helping to keep the show on the road: - Raymond Mouthaan for managing Wemos Wiki information - Norbert Richter for his decode-config.py tool - Andre Thomas for providing [thehackbox](http://thehackbox.org/tasmota/) OTA support and daily development builds -- Joel Stein and digiblur for their Tuya research and driver +- Joel Stein, digiblur and Shantur Rathore for their Tuya research and driver - Frogmore42 and Jason2866 for providing many issue answers - Blakadder for editing the wiki and providing template management -- Stephan Hadinger for refactoring light driver and enhancing HueEmulation -- tmo for designing the official logo -- Many more providing Tips, Wips, Pocs or PRs +- Stephan Hadinger for refactoring light driver, enhancing HueEmulation and Zigbee support +- tmo for designing the official Tasmota logo +- Stefan Bode for his Shutter and Deep sleep drivers +- Many more providing Tips, Wips, Pocs, PRs and Donations ## License diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 89efea9d5..3c511dd85 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -99,6 +99,8 @@ Module | Description 71 Sonoff iFan03 | Sonoff iFan03 Wifi Smart Ceiling Fan with Light 72 EXS Dimmer | EXS Wifi Dimmer v4 +Over 500 additional devices are supported using [templates](TEMPLATES.md). + ## Provided Binary Downloads The following binary downloads have been compiled with ESP8266/Arduino library core version **pre-2.6.0**. @@ -257,5 +259,120 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | ## Changelog -Version 6.7.0 20191101 - * TBS +Version 6.7.0 20191025 + * Remove support for WPS and SmartConfig in favour of Web server (!) based WifiManager (#6680) + * Remove binary sonoff-classic (#6680) + * Remove command ``SetOption2`` + * Remove default DS18B20 driver and only support define **USE_DS18x20** (#6647) + * Remove support for define **USE_DS18x20_LEGACY** and legacy DS18x20 driver (#6486) + * Replace xsns_23_sdm120 with xnrg_08_sdm120 + * Replace xsns_25_sdm630 with xnrg_10_sdm630 + * Replace xsns_49_solaxX1 with xnrg_12_solaxX1 (#6677) + * Change Sonoff L1 support by adding define **USE_SONOFF_L1** + * Change light drivers internals to ease management + * Change command ``PulseTime`` JSON message format and allow display of all pulsetimer information (#6519) + * Change command ``SetOption43`` to make it more general. Now supports PS_16_DZ driver too (#6544) + * Change command handling by moving buffers up in chain solving ``MQTTlog`` support (#6529) + * Change commands ``Var`` and ``Mem`` to show all parameters when no index is given (#6107) + * Change detection of non-MQTT commands by allowing non-space characters as delimiter (#6540) + * Change rename "Data" to "Hash" and limit to 32 bits when receiving UNKNOWN IR protocol (see DECODE_HASH from IRremoteESP8266) + * Change JSON output format for commands ``Adc``, ``Adcs``, ``Modules``, ``Gpio`` and ``Gpios`` from list to dictionary (#6407) + * Change energy sensors for three phase/channel support + * Change Settings crc calculation allowing short term backward compatibility + * Change Improve reliability of TasmotaSerial at 115200 bauds and reduce IRAM usage + * Change Tuya support by Shantur Rathore removing commands ``SetOption34, 41, 44, 45, 46 and 65`` (#6353) + * Change theoretical baudrate range to 300..19660500 bps in 300 increments (#6294) + * Change Settings area to 4k for future use + * Change some table locations from RAM to Flash + * Change filename of configuration backup from using FriendlyName1 to Hostname solving diacritic issues (#2422) + * Change Store AWS IoT Private Key and Certificate in SPI Flash avoiding device-specific compilations + * Change defines **USE_TX20_WIND_SENSOR** and **USE_RC_SWITCH** in my_user_config.h to disable to lower iram usage enabling latest core compilation (#6060, #6062) + * Fix handling of ligth channels when pwm_multichannel (``SetOption68``) is enabled + * Fix better handling of PWM White Temperature mode for Module 48 (#6534) + * Fix TasmotaSerial: move serial send to IRAM for high speed baud rates + * Fix Domoticz battery level set to 100 if define **USE_ADC_VCC** is not used (#6033) + * Fix Force Elliptic Curve for Letsencrypt TLS #6042 + * Fix WeMo emulation for 1G echo and 2G echo dot (#6086) + * Fix Xiaomi Philips brightness (#6091) + * Add support for EX-Store WiFi Dimmer V4 (#5856) + * Add support for Arduino serial connection (EXPERIMENTAL) + * Add support for Zigbee devices Xiaomi lumi.weather air quality sensor, Osram mini-switch + * Add support for Zigbee device cc2530 initialization and basic ZCL decoding + * Add support for PMS3003 dust particle sensor + * Add support for Chint DDSU666 Modbus energy meter by Pablo Zerón + * Add support for SM2135 as used in Action LSC Smart Led E14 (#6495) + * Add support for Shelly 2.5 dual energy (#6160) + * Add support for shutters by Stefan Bode (#288) + * Add support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode + * Add support for up to three PZEM-014/-016 on one serial modbus connection with addresses 1 (default), 2 and 3 (#2315) + * Add support for up to three PZEM-004T on one serial connection with addresses 192.168.1.1 (default), 2 and 3 (#2315) + * Add support for up to three PZEM-003/-017 on one serial modbus connection with addresses 1 (default), 2 and 3 (#2315) + * Add support for up to 4 INA226 Voltage and Current sensors by Steve Rogers (#6342) + * Add support for A4988 stepper-motor-driver-circuit by Tim Leuschner (#6370) + * Add support for Hiking DDS238-2 Modbus energy meter by Matteo Campanella (#6384) + * Add support for HM17 bluetooth LE passive scan of ibeacon devices by Gerhard Mutz + * Add support for Solax X1 inverter by Pablo Zerón + * Add support for PAJ7620 gesture sensor by Christian Baars + * Add support for MAX31865 Thermocouple sensor by Alberto Lopez Siemens + * Add support for RDM6300 125kHz RFID Reader by Gerhard Mutz + * Add support for CHIRP soil moisture sensor by Christian Baars + * Add support for Sonoff iFan03 as module 71 (#5988) + * Add support for a buzzer + * Add support for IRSend long press ('repeat' feature from IRRemoteESP8266) (#6074) + * Add support for IRHVAC Midea/Komeco protocol (#3227) + * Add support for more IRSend protocols enabled in my_user_config.h + * Add support for IRSend Pioneer protocol (#6100) + * Add support for up to 4 INA219 sensors (#6046) + * Add support for I2C display driver SH1106 oled by Gerhard Mutz + * Add support for SPI display drivers epaper 4.2 inch, ILI9488 TFT, SSD1351 Color oled and RA8876 TFT by Gerhard Mutz + * Add command ``Buzzer`` with optional parameters ,, enabled when a buzzer is configured (#5988) + * Add command ``DimmerRange`` in Light module to support 2 byte dimming ranges from Tuya + * Add command ``DisplayHeight`` to set pixel height on supported devices + * Add command ``DisplayWidth`` to set pixel width on supported devices + * Add command ``EnergyReset4 x,x`` to initialize total usage for two tarrifs + * Add command ``EnergyReset5 x,x`` to initialize total export (or production) for two tarrifs + * Add command ``Gpio 255/All`` to show physical GPIO configuration of all non-flash pins (#6407) + * Add command ``Gpios 255/All`` to show all available GPIO components (#6407) + * Add command ``ModuleAddress 1/2/3`` to set Pzem module address when a single module is connected (#2315) + * Add command ``MqttLog `` for support of MQTT logging (#6498) + * Add command ``Power0 0/1/2/Off/On/Toggle`` to control all power outputs at once (#6340) + * Add command ``PowerDelta 101..32000`` for absolute power delta where 101 = 101-100 = 1W, 202 = 202-100 = 102W (#5901) + * Add command ``Reset 99`` to reset bootcount to zero (#684, #6351) + * Add command ``Sensor29 pin,0/1/2`` for OFF/ON/TOGGLE + * Add command ``Sensor34 8,0`` and ``Sensor34 8,1`` to disable/enable JSON message on weight change over 4 gram + * Add command ``SetOption34 0..255`` to set backlog delay. Default value is 200 (mSeconds) (#6562) + * Add command ``SetOption42 0..255`` to set overtemperature (Celsius only) threshold resulting in power off all on energy monitoring devices. Default setting is 90 (#6036) + * Add command ``SetOption65 0/1`` to disable (1) fast power cycle detection fixing unwanted brownout trigger + * Add command ``SetOption66 0/1`` to enable or disable Tuya dimmer range 255 slider control + * Add command ``SetOption67 0/1`` to disable or enable a buzzer as used in iFan03 + * Add command ``SetOption68 0/1`` to enable multi-channel PWM instead of a single light (#6134) + * Add command ``SetOption71 0/1`` to switch between different Modbus Active Energy registers on DDS238-2 energy meters (#6531) + * Add command ``SetOption72 0/1`` to switch between software (0) or hardware (1) energy total counter (#6561) + * Add command ``Time`` to disable NTP and set UTC time as Epoch value if above 1451602800 (=20160101). ``Time 0`` re-enables NTP (#5279) + * Add command ``Time 1/2/3`` to select JSON time format ISO + Epoch, ISO or Epoch + * Add command ``Tariff`` to default to 0 (=disabled) and allowing to set both Standard Time (ST) and Daylight Savings Time (DST) start hour + ex. ``Tariff1 22,23`` = Tariff1 (Off-Peak) ST,DST ``Tariff2 6,7`` = Tariff2 (Standard) ST,DST ``Tariff9 0/1`` = Weekend toggle (1 = Off-Peak during weekend) + * Add command ``WebSensor 0/1`` to control display of sensor data in web GUI (#6085) + * Add command ``ZigbeeRead`` (#6095) + * Add define **USE_DEEPSLEEP** and command ``DeepSleepTime 0 or 10..86400`` (seconds) to enter deepsleep mode (#6638) + * Add define **USE_ENERGY_MARGIN_DETECTION** to disable Energy Margin and Power Limit detection + * Add define **USE_ENERGY_POWER_LIMIT** to disable Energy Power Limit detection while Energy Margin detection is active + * Add define **USE_SONOFF_RF** to enable/disable Sonoff Rf support (#6648) + * Add define **USE_WS2812_HARDWARE** to select hardware type WS2812, WS2812X, WS2813, SK6812, LC8812 or APA106 (DMA mode only) + * Add incremental beeps to Ifan03 remote control fan speed buttons (#6636) + * Add rule support after every command execution like Fanspeed#Data=2 (#6636) + * Add WebUI for multiple, independent PWM channels + * Add JSON array index support to rules evaluation allowing trigger on ENERGY#POWER[2]>0.60 from JSON ..,"Power":[0.00,0.68],.. (#6160) + * Add Full support of all protocols in IRremoteESP8266, to be used on dedicated-IR Tasmota version. Warning: +81k Flash when compiling with **USE_IR_REMOTE_FULL** + * Add 'sonoff-ir' pre-packaged IR-dedicated firmware and 'sonoff-ircustom' to customize firmware with IR Full protocol support + * Add Tuya Energy monitoring by Shantur Rathore + * Add Domoticz P1 Smart Meter support using energy sensors handled by xdrv_03_energy.ino based on an idea by pablozg + * Add debug compile features using defines **DEBUG_TASMOTA_CORE**, **DEBUG_TASMOTA_DRIVER** and **DEBUG_TASMOTA_SENSOR**. + See **DEBUG_CORE_LOG** example in sonoff.ino and **DEBUG_DRIVER_LOG** example in xdrv_09_timers.ino + * Add option 0 to ``Width1`` (Marker), ``Width2`` (Second), ``Width3`` (Minute) and ``Width4`` (Hour) disabling display (#6152) + * Add MqttCount metric to STATE (#6155) + * Add allow repeat/longpress for IRSend raw, introduced ``IRSend`` option (#6074) + * Add Oled reset GPIO option "OLED reset" + * Add blend RGB leds with White leds for better whites (#5895, #5704) + * Add AZ7798 automatic setting of clock display (#6034) + * Add Epoch and UptimeSec to JSON messages (#6068) From 313e72da617a202a12e80bcd762dd60d2365e34b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 23 Oct 2019 17:58:23 +0200 Subject: [PATCH 003/196] Prep release 6.7 --- RELEASENOTES.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3c511dd85..6afa69295 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -280,7 +280,7 @@ Version 6.7.0 20191025 * Change energy sensors for three phase/channel support * Change Settings crc calculation allowing short term backward compatibility * Change Improve reliability of TasmotaSerial at 115200 bauds and reduce IRAM usage - * Change Tuya support by Shantur Rathore removing commands ``SetOption34, 41, 44, 45, 46 and 65`` (#6353) + * Change Tuya support by Shantur Rathore removing commands ``SetOption34, 41, 44, 45, 46, 65, 66 and 69`` (#6353) * Change theoretical baudrate range to 300..19660500 bps in 300 increments (#6294) * Change Settings area to 4k for future use * Change some table locations from RAM to Flash @@ -343,7 +343,6 @@ Version 6.7.0 20191025 * Add command ``SetOption34 0..255`` to set backlog delay. Default value is 200 (mSeconds) (#6562) * Add command ``SetOption42 0..255`` to set overtemperature (Celsius only) threshold resulting in power off all on energy monitoring devices. Default setting is 90 (#6036) * Add command ``SetOption65 0/1`` to disable (1) fast power cycle detection fixing unwanted brownout trigger - * Add command ``SetOption66 0/1`` to enable or disable Tuya dimmer range 255 slider control * Add command ``SetOption67 0/1`` to disable or enable a buzzer as used in iFan03 * Add command ``SetOption68 0/1`` to enable multi-channel PWM instead of a single light (#6134) * Add command ``SetOption71 0/1`` to switch between different Modbus Active Energy registers on DDS238-2 energy meters (#6531) From 247355a12579790aecd14cce602fe1d77087b29a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 23 Oct 2019 18:02:56 +0200 Subject: [PATCH 004/196] Prep release 6.7 --- RELEASENOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6afa69295..6f02b4a74 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -280,7 +280,7 @@ Version 6.7.0 20191025 * Change energy sensors for three phase/channel support * Change Settings crc calculation allowing short term backward compatibility * Change Improve reliability of TasmotaSerial at 115200 bauds and reduce IRAM usage - * Change Tuya support by Shantur Rathore removing commands ``SetOption34, 41, 44, 45, 46, 65, 66 and 69`` (#6353) + * Change Tuya support by Shantur Rathore removing tuya related commands ``SetOption34, 41, 44, 45, 46, 65, 66 and 69`` (#6353) * Change theoretical baudrate range to 300..19660500 bps in 300 increments (#6294) * Change Settings area to 4k for future use * Change some table locations from RAM to Flash From 87562deeae58a7cb9e40e0dd54075aa2917ec735 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 24 Oct 2019 08:17:19 +0200 Subject: [PATCH 005/196] fix scripter bracketed conditions --- sonoff/xdrv_10_scripter.ino | 57 ++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index 3e1487b64..e4610c830 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -2211,33 +2211,49 @@ char *Evaluate_expression(char *lp,uint8_t and_or, uint8_t *result,JsonObject * struct T_INDEX ind; uint8_t vtype=0,lastop; uint8_t res=0; + char *llp=lp; + char *slp; SCRIPT_SKIP_SPACES - if (*lp=='(') { + uint8_t res=0; + uint8_t xand_or=0; lp++; - lp=Evaluate_expression(lp,and_or,result,jo); - lp++; + +loop: + SCRIPT_SKIP_SPACES + lp=Evaluate_expression(lp,xand_or,&res,jo); + if (*lp==')') { + lp++; + goto exit0; + } // check for next and or SCRIPT_SKIP_SPACES if (!strncmp(lp,"or",2)) { lp+=2; - and_or=1; - SCRIPT_SKIP_SPACES - lp=Evaluate_expression(lp,and_or,result,jo); + xand_or=1; + goto loop; } else if (!strncmp(lp,"and",3)) { lp+=3; - and_or=2; - SCRIPT_SKIP_SPACES - lp=Evaluate_expression(lp,and_or,result,jo); + xand_or=2; + goto loop; } - return lp; +exit0: + if (!and_or) { + *result=res; + } else if (and_or==1) { + *result|=res; + } else { + *result&=res; + } + goto exit10; } + llp=lp; // compare dfvar=&fvar; glob_script_mem.glob_error=0; - char *slp=lp; + slp=lp; numeric=1; lp=GetNumericResult(lp,OPER_EQU,dfvar,0); if (glob_script_mem.glob_error==1) { @@ -2252,23 +2268,15 @@ char *Evaluate_expression(char *lp,uint8_t and_or, uint8_t *result,JsonObject * char str[SCRIPT_MAXSSIZE]; lp=GetStringResult(lp,OPER_EQU,str,jo); if (lastop==OPER_EQUEQU || lastop==OPER_NOTEQU) { - uint8_t res=0; res=strcmp(cmpstr,str); if (lastop==OPER_EQUEQU) res=!res; - if (!and_or) { - *result=res; - } else if (and_or==1) { - *result|=res; - } else { - *result&=res; - } + goto exit; } } else { // numeric // evaluate operand lp=getop(lp,&lastop); - lp=GetNumericResult(lp,OPER_EQU,&fvar1,jo); switch (lastop) { case OPER_EQUEQU: @@ -2294,6 +2302,7 @@ char *Evaluate_expression(char *lp,uint8_t and_or, uint8_t *result,JsonObject * break; } +exit: if (!and_or) { *result=res; } else if (and_or==1) { @@ -2302,11 +2311,13 @@ char *Evaluate_expression(char *lp,uint8_t and_or, uint8_t *result,JsonObject * *result&=res; } } -exit: + + +exit10: #if SCRIPT_DEBUG>0 char tbuff[128]; - sprintf(tbuff,"p1=%d,p2=%d,cmpres=%d line: ",(int32_t)*dfvar,(int32_t)fvar1,*result); - toLogEOL(tbuff,lp); + sprintf(tbuff,"p1=%d,p2=%d,cmpres=%d,and_or=%d line: ",(int32_t)*dfvar,(int32_t)fvar1,*result,and_or); + toLogEOL(tbuff,llp); #endif return lp; } From 42fc1d57af557efc22a69c497489f8b1aa272312 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 24 Oct 2019 08:55:00 +0200 Subject: [PATCH 006/196] Fix loglevel anomaly Fix loglevel anomaly (#6726) --- sonoff/sonoff.h | 2 +- sonoff/support_command.ino | 4 ++-- sonoff/xdrv_01_webserver.ino | 4 ++-- sonoff/xdrv_02_mqtt.ino | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 40b3dcb98..9dd173167 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -220,7 +220,7 @@ enum MonthNamesOptions {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, enum HemisphereOptions {North, South}; enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART, DT_ENERGY }; -enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; +enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE}; 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}; diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 4704e14e1..fdf65ecf7 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -524,7 +524,7 @@ void CmndOtaUrl(void) void CmndSeriallog(void) { - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { Settings.flag.mqtt_serial = 0; SetSeriallog(XdrvMailbox.payload); } @@ -1075,7 +1075,7 @@ void CmndSerialDelimiter(void) void CmndSyslog(void) { - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { SetSyslog(XdrvMailbox.payload); } Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.syslog_level, syslog_level); diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 1f3fc3733..40b3bab83 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1625,7 +1625,7 @@ void HandleLoggingConfiguration(void) GetTextIndexed(stemp1, sizeof(stemp1), idx, kLoggingOptions), GetTextIndexed(stemp2, sizeof(stemp2), dlevel[idx], kLoggingLevels), idx); - for (uint32_t i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { + for (uint32_t i = LOG_LEVEL_NONE; i <= LOG_LEVEL_DEBUG_MORE; i++) { WSContentSend_P(PSTR("%d %s"), (i == llevel) ? " selected" : "", i, i, GetTextIndexed(stemp1, sizeof(stemp1), i, kLoggingLevels)); @@ -2676,7 +2676,7 @@ void CmndWebPassword(void) void CmndWeblog(void) { - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { Settings.weblog_level = XdrvMailbox.payload; } ResponseCmndNumber(Settings.weblog_level); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index edc844448..50f66c8ce 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -764,7 +764,7 @@ void CmndMqttPassword(void) void CmndMqttlog(void) { - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { Settings.mqttlog_level = XdrvMailbox.payload; } ResponseCmndNumber(Settings.mqttlog_level); From 90a161bec8aaae475a7ae14c4a24633913ff163c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 24 Oct 2019 09:47:28 +0200 Subject: [PATCH 007/196] Add Mqtt Button and Switch status Add Mqtt Button and Switch status (#6725) --- sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 7 +++--- sonoff/xdrv_11_knx.ino | 27 ++++++++++++--------- sonoff/xdrv_12_home_assistant.ino | 39 +++++++++++++++++++++++-------- 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 9dd173167..62dce5e2f 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -270,7 +270,7 @@ enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FU FUNC_SAVE_AT_MIDNIGHT, FUNC_SAVE_BEFORE_RESTART, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_AFTER_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, - FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, + FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, FUNC_ANY_KEY, FUNC_ENERGY_EVERY_SECOND, FUNC_ENERGY_RESET, FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER, FUNC_SET_CHANNELS, FUNC_SET_SCHEME}; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 18afb76c7..ef42e85eb 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -537,9 +537,10 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); result = XdrvRulesProcess(); } -#ifdef USE_KNX - KnxSendButtonPower(key, device, state); -#endif // USE_KNX + int32_t payload_save = XdrvMailbox.payload; + XdrvMailbox.payload = key << 16 | state << 8 | device; + XsnsCall(FUNC_ANY_KEY); + XdrvMailbox.payload = payload_save; return result; } diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 6fa6231c0..a1b45800e 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -672,8 +672,13 @@ void KnxUpdatePowerState(uint8_t device, power_t state) } -void KnxSendButtonPower(uint8_t key, uint8_t device, uint8_t state) +void KnxSendButtonPower(void) { + if (!(Settings.flag.knx_enabled)) { return; } + + uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; + uint32_t device = XdrvMailbox.payload & 0xFF; + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; // key 0 = button_topic // key 1 = switch_topic // state 0 = off @@ -681,9 +686,6 @@ void KnxSendButtonPower(uint8_t key, uint8_t device, uint8_t state) // state 2 = toggle // state 3 = hold // state 9 = clear retain flag - if (!(Settings.flag.knx_enabled)) { return; } -// if (key) -// { // Search all the registered GA that has that output (variable: device) as parameter uint8_t i = KNX_GA_Search(device + 8); @@ -1207,8 +1209,13 @@ bool Xdrv11(uint8_t function) case FUNC_LOOP: if (!global_state.wifi_down) { knx.loop(); } // Process knx events break; - case FUNC_PRE_INIT: - KNX_INIT(); + case FUNC_EVERY_50_MSECOND: + if (toggle_inhibit) { + toggle_inhibit--; + } + break; + case FUNC_ANY_KEY: + KnxSendButtonPower(); break; #ifdef USE_WEBSERVER #ifdef USE_KNX_WEB_MENU @@ -1220,14 +1227,12 @@ bool Xdrv11(uint8_t function) break; #endif // USE_KNX_WEB_MENU #endif // USE_WEBSERVER - case FUNC_EVERY_50_MSECOND: - if (toggle_inhibit) { - toggle_inhibit--; - } - break; case FUNC_COMMAND: result = DecodeCommand(kKnxCommands, KnxCommand); break; + case FUNC_PRE_INIT: + KNX_INIT(); + break; // case FUNC_SET_POWER: // break; } diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index d5a52a491..b90a52fee 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -404,13 +404,13 @@ void HAssAnnounceButtons(void) } } -void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) +void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) { char stopic[TOPSZ]; char stemp1[TOPSZ]; char stemp2[TOPSZ]; char unique_id[30]; - bool is_sensor = true; + bool is_sensor = true; // Announce sensor, special handling of temperature and humidity sensors mqtt_data[0] = '\0'; // Clear retained message @@ -466,10 +466,10 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) } else if (!strcmp_P(subsensortype, PSTR(D_JSON_ILLUMINANCE))){ TryResponseAppend_P(HASS_DISCOVER_SENSOR_ILLUMINANCE, sensorname, subsensortype); } else { - if (is_sensor){ - TryResponseAppend_P(PSTR(",\"unit_of_meas\":\" \"")); // " " As unit of measurement to get a value graph (not available for binary sensors) - } - TryResponseAppend_P(HASS_DISCOVER_SENSOR_ANY, sensorname, subsensortype); + if (is_sensor){ + TryResponseAppend_P(PSTR(",\"unit_of_meas\":\" \"")); // " " As unit of measurement to get a value graph (not available for binary sensors) + } + TryResponseAppend_P(HASS_DISCOVER_SENSOR_ANY, sensorname, subsensortype); } TryResponseAppend_P(PSTR("}")); } @@ -611,6 +611,22 @@ void HAssDiscover(void) hass_init_step = 1; // Delayed discovery } +void HAssAnyKey(void) +{ + if (!Settings.flag.hass_discovery) { return; } + + uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; + uint32_t device = XdrvMailbox.payload & 0xFF; + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; + + char scommand[CMDSZ]; + snprintf_P(scommand, sizeof(scommand), PSTR("%s%d"), (key) ? "SWITCH" : "BUTTON", device); + char stopic[TOPSZ]; + GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); + Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(state, device -1))); + MqttPublish(stopic); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -621,10 +637,6 @@ bool Xdrv12(uint8_t function) if (Settings.flag.mqtt_enabled) { switch (function) { - case FUNC_MQTT_INIT: - hass_mode = 0; // Discovery only if Settings.flag.hass_discovery is set - hass_init_step = 2; // Delayed discovery - break; case FUNC_EVERY_SECOND: if (hass_init_step) { hass_init_step--; @@ -641,6 +653,13 @@ bool Xdrv12(uint8_t function) } } break; + case FUNC_ANY_KEY: + HAssAnyKey(); + break; + case FUNC_MQTT_INIT: + hass_mode = 0; // Discovery only if Settings.flag.hass_discovery is set + hass_init_step = 2; // Delayed discovery + break; } } return result; From 32c26b6a11a3805a801fcd2f1dca2b83238a3de4 Mon Sep 17 00:00:00 2001 From: Bohdan Kmit Date: Thu, 24 Oct 2019 10:54:00 +0300 Subject: [PATCH 008/196] Little Ukrainian translation correction --- sonoff/language/uk-UK.h | 2 +- sonoff/xdrv_02_mqtt.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 8030b1f2a..67999ef11 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -139,7 +139,7 @@ #define D_RESTARTING "Перезавантаження" #define D_RESTART_REASON "Причина перезавантаження" #define D_RESTORE "відновлення" -#define D_RETAINED "нерозподілений" +#define D_RETAINED "зберігати" #define D_RULE "Правило" #define D_SAVE "Зберегти" #define D_SENSOR "Давач" diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 50f66c8ce..22ecf5f58 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -346,7 +346,7 @@ void MqttPublishLogging(const char *mxtime) void MqttPublishDirect(const char* topic, bool retained) { char sretained[CMDSZ]; - char slog_type[10]; + char slog_type[20]; #ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("MqttPublishDirect")); From f1aaf11f03b5c12c4848d7484630f1717724166e Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 24 Oct 2019 10:29:40 +0200 Subject: [PATCH 009/196] Update de-DE.h --- sonoff/language/de-DE.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 92e456f96..261935e86 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.6.0.14 + * Updated until v6.6.0.21 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -157,7 +157,7 @@ #define D_TO "zu" #define D_TOGGLE "An/Aus" #define D_TOPIC "topic" -#define D_TOTAL_USAGE "Total Usage" +#define D_TOTAL_USAGE "Gesamtnutzung" #define D_TRANSMIT "Übertragen" #define D_TRUE "wahr" #define D_TVOC "TVOC" @@ -320,11 +320,11 @@ #define D_MAC_ADDRESS "MAC-Adresse" #define D_MQTT_HOST "MQTT Host" #define D_MQTT_PORT "MQTT Port" -#define D_MQTT_CLIENT "MQTT client" -#define D_MQTT_USER "MQTT-Benutzer" -#define D_MQTT_TOPIC "MQTT topic" -#define D_MQTT_GROUP_TOPIC "MQTT group topic" -#define D_MQTT_FULL_TOPIC "MQTT full topic" +#define D_MQTT_CLIENT "MQTT Client" +#define D_MQTT_USER "MQTT Benutzer" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" #define D_MDNS_DISCOVERY "mDNS-Ermittlung" #define D_MDNS_ADVERTISE "mDNS-Bekanntmachung" #define D_ESP_CHIP_ID "ESP Chip ID" @@ -335,15 +335,15 @@ #define D_UPGRADE_BY_WEBSERVER "Update über Web-Server" #define D_OTA_URL "OTA-URL" #define D_START_UPGRADE "Update starten" -#define D_UPGRADE_BY_FILE_UPLOAD "Update-Datei hochladen" +#define D_UPGRADE_BY_FILE_UPLOAD "Update Datei hochladen" #define D_UPLOAD_STARTED "Upload gestartet" #define D_UPGRADE_STARTED "Update gestartet" #define D_UPLOAD_DONE "Upload abgeschlossen" -#define D_UPLOAD_ERR_1 "keine Datei ausgewählt" -#define D_UPLOAD_ERR_2 "ungenügend Speicherplatz" -#define D_UPLOAD_ERR_3 "magic byte ist nicht 0xE9" -#define D_UPLOAD_ERR_4 "Flash-Größe des Programmes ist größer als der reale Flashspeicher" -#define D_UPLOAD_ERR_5 "Upload-buffer-Vergleich weicht ab" +#define D_UPLOAD_ERR_1 "Keine Datei ausgewählt" +#define D_UPLOAD_ERR_2 "Ungenügend Speicherplatz" +#define D_UPLOAD_ERR_3 "Magic Byte ist nicht 0xE9" +#define D_UPLOAD_ERR_4 "Datei überschreitet vorhdn. Flashspeicher" +#define D_UPLOAD_ERR_5 "Upload Buffer Vergleich weicht ab" #define D_UPLOAD_ERR_6 "Upload fehlgeschlagen. Aktiviere logging 3" #define D_UPLOAD_ERR_7 "Upload abgebrochen" #define D_UPLOAD_ERR_8 "Datei ungültig" @@ -641,7 +641,7 @@ #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" -#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" From 14d39052547569116a07289ba0ce11861259fb5d Mon Sep 17 00:00:00 2001 From: hkrupp Date: Thu, 24 Oct 2019 13:13:16 +0200 Subject: [PATCH 010/196] Replace original WiFi.Status() check with !addr.isLocal() in IPv6 code to allow plain v4, v6 or Dualstack. --- sonoff/support_wifi.ino | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index a0f4bd3e5..bfbc3631f 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -323,12 +323,22 @@ bool WifiCheckIPv6(void) } return ipv6_global; } + +bool WifiCheckIPAddrStatus(void) // Return false for 169.254.x.x or fe80::/64 +{ + bool ip_global=false; + + for (auto a : addrList) { + if(!a.isLocal()) ip_global=true; + } + return ip_global; +} #endif // LWIP_IPV6=1 void WifiCheckIp(void) { #if LWIP_IPV6 - if(WifiCheckIPv6()) { + if(WifiCheckIPAddrStatus()) { Wifi.status = WL_CONNECTED; #else if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { @@ -456,7 +466,7 @@ void WifiCheck(uint8_t param) WifiCheckIp(); } #if LWIP_IPV6 - if (WifiCheckIPv6()) { + if (WifiCheckIPAddrStatus()) { #else if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !Wifi.config_type) { #endif // LWIP_IPV6=1 From 28bba13b427f522db8d097b250d2f015a69fc014 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 24 Oct 2019 15:34:50 +0200 Subject: [PATCH 011/196] Update de-DE.h --- sonoff/language/de-DE.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 261935e86..acff5f96b 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -157,7 +157,7 @@ #define D_TO "zu" #define D_TOGGLE "An/Aus" #define D_TOPIC "topic" -#define D_TOTAL_USAGE "Gesamtnutzung" +#define D_TOTAL_USAGE "Gesamtverbrauch" #define D_TRANSMIT "Übertragen" #define D_TRUE "wahr" #define D_TVOC "TVOC" From 3d4ed40804939b3f8edb064ea1eca698c37a1296 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Thu, 24 Oct 2019 16:06:03 +0100 Subject: [PATCH 012/196] TuyaMcu: Fix Relays aren't using correct DpIds. --- sonoff/xdrv_16_tuyamcu.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index 797cdba8f..2cf63c8d0 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -276,8 +276,11 @@ bool TuyaSetPower(void) uint8_t rpower = XdrvMailbox.index; int16_t source = XdrvMailbox.payload; + uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1 + active_device - 1); + if (dpid == 0) dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1_INV + active_device - 1); + if (source != SRC_SWITCH && TuyaSerial) { // ignore to prevent loop from pushing state from faceplate interaction - TuyaSendBool(active_device, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); + TuyaSendBool(dpid, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); status = true; } return status; From 2e0bf40d40caf57980c08e85d08dd242a2c375c3 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Thu, 24 Oct 2019 13:44:00 -0300 Subject: [PATCH 013/196] Update sonoff.ino --- sonoff/sonoff.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ef42e85eb..18a699350 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -539,7 +539,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) } int32_t payload_save = XdrvMailbox.payload; XdrvMailbox.payload = key << 16 | state << 8 | device; - XsnsCall(FUNC_ANY_KEY); + XdrvCall(FUNC_ANY_KEY); XdrvMailbox.payload = payload_save; return result; } From 3047ae8f589e7149fa22e025b7232a287a1d6b94 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Thu, 24 Oct 2019 18:29:06 -0300 Subject: [PATCH 014/196] Update xdrv_12_home_assistant.ino --- sonoff/xdrv_12_home_assistant.ino | 43 ++++++++++++++----------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index b90a52fee..e27f4a4d7 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -28,17 +28,15 @@ const char HASS_DISCOVER_RELAY[] PROGMEM = "\"val_tpl\":\"{{value_json.%s}}\"," // POWER2 "\"pl_off\":\"%s\"," // OFF "\"pl_on\":\"%s\"," // ON -// "\"optimistic\":\"false\"," // false is Hass default when state_topic is set "\"avty_t\":\"%s\"," // tele/dualr2/LWT "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN - "\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") -// "\"value_template\":\"{{value_json.%s}}\"," // POWER2 - "\"pl_on\":\"%s\"," // TOGGLE -// "\"optimistic\":\"false\"," // false is Hass default when state_topic is set + "\"stat_t\":\"%s\"," // stat/RESULT/ (implies "\"optimistic\":\"false\",") + "\"value_template\":\"{{value_json.%s}}\"," // BUTTON1 + "\"pl_on\":\"%s\"," // ON "\"avty_t\":\"%s\"," // tele/dualr2/LWT "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline @@ -91,10 +89,6 @@ const char HASS_DISCOVER_SENSOR_TEMP[] PROGMEM = "\"val_tpl\":\"{{value_json['%s'].Temperature}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Temperature }} "\"dev_cla\":\"temperature\""; // temperature -const char HASS_DISCOVER_DS18X20_MULTI[] PROGMEM = - ",\"json_attributes_topic\":\"%s\"," - "\"json_attributes_template\":\"{{{'Id':value_json['%s'].Id}|tojson}}\""; // Add DS18X20 Id as information field - const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM = ",\"unit_of_meas\":\"%%\"," // % "\"val_tpl\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }} @@ -115,10 +109,12 @@ const char HASS_DISCOVER_SENSOR_WATT[] PROGMEM = ",\"unit_of_meas\":\"W\"," // W "\"val_tpl\":\"{{value_json['%s'].%s}}\"," // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].POWER }} "\"dev_cla\":\"power\""; + const char HASS_DISCOVER_SENSOR_VOLTAGE[] PROGMEM = ",\"unit_of_meas\":\"V\"," // V "\"val_tpl\":\"{{value_json['%s'].%s}}\"," // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Voltage }} "\"dev_cla\":\"power\""; + const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = ",\"unit_of_meas\":\"A\"," // A "\"val_tpl\":\"{{value_json['%s'].%s}}\"," // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} @@ -127,7 +123,7 @@ const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = //ILLUMINANCE const char HASS_DISCOVER_SENSOR_ILLUMINANCE[] PROGMEM = ",\"unit_of_meas\":\"LX\"," // LX by default - "\"val_tpl\":\"{{value_json['%s'].Illuminance}}\"," // "ANALOG":{"Illuminance":34}} + "\"val_tpl\":\"{{value_json['%s'].Illuminance}}\"," // "ANALOG":{"Illuminance":34}} "\"dev_cla\":\"illuminance\""; // illuminance const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = @@ -135,8 +131,9 @@ const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = ",\"json_attributes_topic\":\"%s\"," - "\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass - "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} + "\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass + "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"," // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} + "\"ic\":\"mdi:information-outline\""; const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = ",\"uniq_id\":\"%s\"," @@ -319,20 +316,20 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint char prefix[TOPSZ]; char *state_topic = stemp1; char *availability_topic = stemp2; + char jsoname[8]; - if (device+1 > MAX_FRIENDLYNAMES) { - snprintf_P(name, sizeof(name), PSTR("%s %s %d"), Settings.friendlyname[0], key?"SW":"BTN", device+1); - } else { - snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[device], key?"SW":"BTN"); - } + snprintf_P(name, sizeof(name), PSTR("%s %s%d"), Settings.friendlyname[0], key?"Switch":"Button", device+1); GetPowerDevice(value_template, device+1, sizeof(value_template), key + Settings.flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by Settings.flag.device_index_enable - GetTopic_P(state_topic, CMND, topic, value_template); // State of button is sent as CMND TOGGLE, state of switch is sent as ON/OFF + //GetTopic_P(state_topic, CMND, topic, value_template); // State of button is sent as CMND TOGGLE, state of switch is sent as ON/OFF + GetTopic_P(state_topic, STAT, mqtt_topic, PSTR(D_RSLT_RESULT)); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(state_topic, availability_topic, prefix); + Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - Response_P(HASS_DISCOVER_BUTTON_SWITCH, name, state_topic, Settings.state_text[toggle?2:1], availability_topic); + snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key?"SWITCH":"BUTTON", device+1); + Response_P(HASS_DISCOVER_BUTTON_SWITCH, name, state_topic, jsoname, Settings.state_text[toggle?2:1], availability_topic); TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); if (strlen(prefix) > 0 ) TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); if (toggle) TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_TOGGLE); @@ -350,7 +347,7 @@ void HAssAnnounceSwitches(void) // Send info about buttons char *tmp = Settings.switch_topic; Format(sw_topic, tmp, sizeof(sw_topic)); - if ((strlen(sw_topic) != 0) && strcmp(sw_topic, "0")) { + if (!strcmp_P(sw_topic, "0") || strlen(sw_topic) == 0 ) { for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { uint8_t switch_present = 0; uint8_t toggle = 1; @@ -379,7 +376,7 @@ void HAssAnnounceButtons(void) // Send info about buttons char *tmp = Settings.button_topic; Format(key_topic, tmp, sizeof(key_topic)); - if ((strlen(key_topic) != 0) && strcmp(key_topic, "0")) { + if (!strcmp_P(key_topic, "0") || strlen(key_topic) == 0 ) { for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { uint8_t button_present = 0; uint8_t toggle = 1; @@ -623,8 +620,8 @@ void HAssAnyKey(void) snprintf_P(scommand, sizeof(scommand), PSTR("%s%d"), (key) ? "SWITCH" : "BUTTON", device); char stopic[TOPSZ]; GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); - Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(state, device -1))); - MqttPublish(stopic); + Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(state)); + MqttPublish(stopic); } /*********************************************************************************************\ From 6a0a0860f7c7e2bff1e6c72fda296c307d9ac4bd Mon Sep 17 00:00:00 2001 From: Vasco Baptista Date: Fri, 25 Oct 2019 10:38:17 +0200 Subject: [PATCH 015/196] Updated pt-PT language --- sonoff/language/pt-PT.h | 378 ++++++++++++++++++++-------------------- 1 file changed, 189 insertions(+), 189 deletions(-) diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index bfa234599..f060ec5d3 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -57,7 +57,7 @@ #define D_AS "como" #define D_AUTO "AUTO" #define D_BLINK "Piscar" -#define D_BLINKOFF "Piscar desligado" +#define D_BLINKOFF "Piscar Desligado" #define D_BOOT_COUNT "Contagem de Inicialização" #define D_BRIGHTLIGHT "Brilho" #define D_BSSID "BSSId" @@ -65,7 +65,7 @@ #define D_BY "por" // Write by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" -#define D_CHANNEL "Channel" +#define D_CHANNEL "Canal" #define D_CO2 "Dioxido de Carbono" #define D_CODE "Código" // Button code #define D_COLDLIGHT "Luz Fria" @@ -78,7 +78,7 @@ #define D_DARKLIGHT "Luz Escura" #define D_DEBUG "Depurar" #define D_DISABLED "Disabilitado" -#define D_DISTANCE "Distance" +#define D_DISTANCE "Distância" #define D_DNS_SERVER "Servidor DNS" #define D_DONE "Concluído" #define D_DST_TIME "DST" @@ -93,9 +93,9 @@ #define D_FALLBACK_TOPIC "Tópico para retornar" #define D_FALSE "Falso" #define D_FILE "Ficheiro" -#define D_FLOW_RATE "Flow rate" +#define D_FLOW_RATE "Taxa de Fluxo" #define D_FREE_MEMORY "Memoria Livre" -#define D_FREQUENCY "Frequency" +#define D_FREQUENCY "Frequência" #define D_GAS "Gás" #define D_GATEWAY "Gateway" #define D_GROUP "Grupo" @@ -106,7 +106,7 @@ #define D_IMMEDIATE "Immediato" // Button immediate #define D_INDEX "Indíce" #define D_INFO "Info" -#define D_INFRARED "Infrared" +#define D_INFRARED "Infravermelho" #define D_INITIALIZED "Inicializado" #define D_IP_ADDRESS "Endereço IP" #define D_LIGHT "Luz" @@ -125,39 +125,39 @@ #define D_PORT "Porta" #define D_POWER_FACTOR "Factor de Potência" #define D_POWERUSAGE "Potência" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_POWERUSAGE_ACTIVE "Potência Ativa" +#define D_POWERUSAGE_APPARENT "Potência Aparente" +#define D_POWERUSAGE_REACTIVE "Potência Reativa" #define D_PRESSURE "Pressão" #define D_PRESSUREATSEALEVEL "Pressão ao nível do Mar" #define D_PROGRAM_FLASH_SIZE "Tamanho do Programa na Flash" #define D_PROGRAM_SIZE "Tamanho do Programa" #define D_PROJECT "Projeto" -#define D_RAIN "Rain" +#define D_RAIN "Chuva" #define D_RECEIVED "Recebido" #define D_RESTART "Reiniciar" #define D_RESTARTING "A reiniciar" #define D_RESTART_REASON "Razão do reinicio" #define D_RESTORE "Restauro" #define D_RETAINED "Manter" -#define D_RULE "Rule" -#define D_SAVE "Salvar" +#define D_RULE "Regra" +#define D_SAVE "Guardar" #define D_SENSOR "Sensor" #define D_SSID "SSId" #define D_START "Início" #define D_STD_TIME "STD" #define D_STOP "Parar" #define D_SUBNET_MASK "Mascara sub rede" -#define D_SUBSCRIBE_TO "Subescrever para" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUBSCRIBE_TO "Subscrever" +#define D_UNSUBSCRIBE_FROM "Cancelar subscrição de" #define D_SUCCESSFUL "Successo" -#define D_SUNRISE "Sunrise" -#define D_SUNSET "Sunset" +#define D_SUNRISE "Nascer do Sol" +#define D_SUNSET "Pôr do Sol" #define D_TEMPERATURE "Temperatura" #define D_TO "para" #define D_TOGGLE "Pressionar" #define D_TOPIC "Tópico" -#define D_TOTAL_USAGE "Total Usage" +#define D_TOTAL_USAGE "Uso total" #define D_TRANSMIT "Transmitir" #define D_TRUE "Verdadeiro" #define D_TVOC "TVOC" @@ -167,38 +167,38 @@ #define D_USER "Utilizador" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Indíce UV" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_1 "Baixo" +#define D_UV_INDEX_2 "Médio" +#define D_UV_INDEX_3 "Elevado" +#define D_UV_INDEX_4 "Perigoso" +#define D_UV_INDEX_5 "QueimaduraL1/2" +#define D_UV_INDEX_6 "QueimaduraL3" #define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "Nível UV" -#define D_UV_POWER "UV Power" +#define D_UV_POWER "Poder UV" #define D_VERSION "Versão" #define D_VOLTAGE "Voltagem" -#define D_WEIGHT "Weight" +#define D_WEIGHT "Peso" #define D_WARMLIGHT "Luz Quente" -#define D_WEB_SERVER "servidor WEB" +#define D_WEB_SERVER "Servidor WEB" // sonoff.ino #define D_WARNING_MINIMAL_VERSION "AVISO esta versão não supporta configurações persistentes" #define D_LEVEL_10 "nível 1-0" #define D_LEVEL_01 "nível 0-1" -#define D_SERIAL_LOGGING_DISABLED "Registro em serie desabilitado" +#define D_SERIAL_LOGGING_DISABLED "Registro de porta série desabilitado" #define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" #define D_SET_BAUDRATE_TO "Ajuste da velocidade para" #define D_RECEIVED_TOPIC "Topico Recebido" -#define D_DATA_SIZE "Tamanho de dados" +#define D_DATA_SIZE "Tamanho de Dados" #define D_ANALOG_INPUT "Entrada Analógica" // support.ino #define D_OSWATCH "osWatch" #define D_BLOCKED_LOOP "Loop Bloqueado" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig Falha de estado" -#define D_ACTIVE_FOR_3_MINUTES "ativo por 3 minutes" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FALHOU com estado" +#define D_ACTIVE_FOR_3_MINUTES "ativo por 3 minutos" #define D_FAILED_TO_START "Falha ao iníciar" #define D_PATCH_ISSUE_2186 "Questão 2186" #define D_CONNECTING_TO_AP "Ligando ao AP" @@ -212,17 +212,17 @@ #define D_QUERY_DONE "Consulta finalizada. Serviço MQTT não encontrado" #define D_MQTT_SERVICE_FOUND "Serviço MQTT encontrado em" #define D_FOUND_AT "encontrado em" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog anfitrião não encontrado" +#define D_SYSLOG_HOST_NOT_FOUND "Anfitrião Syslog não encontrado" // settings.ino #define D_SAVED_TO_FLASH_AT "Guardado na flash em" #define D_LOADED_FROM_FLASH_AT "Lido da flash em" #define D_USE_DEFAULTS "Usar predefinições" -#define D_ERASED_SECTOR "Apagar setores" +#define D_ERASED_SECTOR "Apagado setor" // xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware
Atualizar Por favor" +#define D_NOSCRIPT "Para utilizar o Tasmota, por favor ative o JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
Por favor atualize" #define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" #define D_WITH_IP_ADDRESS "com o endereço IP" #define D_WEBSERVER_STOPPED "Servitor WEB parou" @@ -235,20 +235,20 @@ #define D_RESTART_IN "Reinicia em" #define D_SECONDS "segundos" #define D_DEVICE_WILL_RESTART "O dispositivo irá reiniciar dentro de alguns segundos" -#define D_BUTTON_TOGGLE "Pressionar" +#define D_BUTTON_TOGGLE "Alternar" #define D_CONFIGURATION "Configuração" #define D_INFORMATION "Informação" #define D_FIRMWARE_UPGRADE "Atualização de Firmware" #define D_CONSOLE "Consola" -#define D_CONFIRM_RESTART "Confirmar o reinicio" +#define D_CONFIRM_RESTART "Confirmar o reinício" #define D_CONFIGURE_MODULE "Configurar Módulo" #define D_CONFIGURE_WIFI "Configurar WiFi" #define D_CONFIGURE_MQTT "Configurar MQTT" #define D_CONFIGURE_DOMOTICZ "Configurar Domoticz" -#define D_CONFIGURE_LOGGING "Configurar Logging" +#define D_CONFIGURE_LOGGING "Configurar registro" #define D_CONFIGURE_OTHER "Configurar outras opções" -#define D_CONFIRM_RESET_CONFIGURATION "Apagar configuração Confirmar" +#define D_CONFIRM_RESET_CONFIGURATION "Confirme o reinício da configuração" #define D_RESET_CONFIGURATION "Apagar configuração" #define D_BACKUP_CONFIGURATION "Guardar configuração" #define D_RESTORE_CONFIGURATION "Repor configuração" @@ -256,102 +256,102 @@ #define D_MODULE_PARAMETERS "Parametros do Módulo" #define D_MODULE_TYPE "Tipo de Módulo" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_PULLUP_ENABLE "Sem pull-up de Botão/Interruptor" #define D_ADC "ADC" #define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial Entrada" -#define D_SERIAL_OUT "Serial Saída" +#define D_SERIAL_IN "Entrada de porta série" +#define D_SERIAL_OUT "Saída de porta série" #define D_WIFI_PARAMETERS "Parametros Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Em busca de redes wifi" -#define D_SCAN_DONE "Busca finalizada" -#define D_NO_NETWORKS_FOUND "Sem redes" -#define D_REFRESH_TO_SCAN_AGAIN "Nova busca" -#define D_DUPLICATE_ACCESSPOINT "Ponto de Acesso duplicado" +#define D_SCAN_FOR_WIFI_NETWORKS "Procurar redes Wifi" +#define D_SCAN_DONE "Pesquisa terminada" +#define D_NO_NETWORKS_FOUND "Sem redes encontradas" +#define D_REFRESH_TO_SCAN_AGAIN "Atualize para realizar nova pesquisa" +#define D_DUPLICATE_ACCESSPOINT "Duplicar ponto de Acesso" #define D_SKIPPING_LOW_QUALITY "Ignorado devido a baixa qualidade do sinal" #define D_RSSI "RSSI" #define D_WEP "WEP" #define D_WPA_PSK "WPA PSK" #define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Palavra Chave" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Palavra Chave" +#define D_AP1_SSID "SSId do AP1" +#define D_AP1_PASSWORD "Palavra Chave do AP1" +#define D_AP2_SSID "SSId do AP2" +#define D_AP2_PASSWORD "Palavra Chave do AP2" #define D_MQTT_PARAMETERS "Parametros MQTT" #define D_CLIENT "Cliente" #define D_FULL_TOPIC "Tópico completo" -#define D_LOGGING_PARAMETERS "Parametros Logging" -#define D_SERIAL_LOG_LEVEL "Nível de registro serial" -#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_LOGGING_PARAMETERS "Parametros para registro" +#define D_SERIAL_LOG_LEVEL "Nível de registro na porta série" +#define D_MQTT_LOG_LEVEL "Nível de registro MQTT" #define D_WEB_LOG_LEVEL "Nível de registro WEB" -#define D_SYS_LOG_LEVEL "Nível de registro Syslog" +#define D_SYS_LOG_LEVEL "Nível de registro do Syslog" #define D_MORE_DEBUG "Depurar mais" -#define D_SYSLOG_HOST "Syslog anfitrião" +#define D_SYSLOG_HOST "Anfitrião Syslog" #define D_SYSLOG_PORT "Porta Syslog" -#define D_TELEMETRY_PERIOD "Periodo de Telemetria" +#define D_TELEMETRY_PERIOD "Período de Telemetria" #define D_OTHER_PARAMETERS "Outros parametros" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Palavra Chave de WEB Admin" +#define D_TEMPLATE "Modelo" +#define D_ACTIVATE "Ativar" +#define D_WEB_ADMIN_PASSWORD "Palavra Chave do Admin WEB" #define D_MQTT_ENABLE "MQTT habilitado" #define D_FRIENDLY_NAME "Nome amigável" #define D_BELKIN_WEMO "Belkin WeMo" #define D_HUE_BRIDGE "Hue Bridge" #define D_SINGLE_DEVICE "dispositivo único" -#define D_MULTI_DEVICE "multiplos dispositivos" +#define D_MULTI_DEVICE "dispositivo múltiplo" -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" +#define D_CONFIGURE_TEMPLATE "Configurar Modelo" +#define D_TEMPLATE_PARAMETERS "Parametros do Modelo" +#define D_TEMPLATE_NAME "Nome do Modelo" +#define D_BASE_TYPE "Baseado em" +#define D_TEMPLATE_FLAGS "Opções" -#define D_SAVE_CONFIGURATION "Salvar configuração" +#define D_SAVE_CONFIGURATION "Guardar configuração" #define D_CONFIGURATION_SAVED "Configuração guardada" -#define D_CONFIGURATION_RESET "Reinicialização da configuração" +#define D_CONFIGURATION_RESET "Reinicializar a configuração" #define D_PROGRAM_VERSION "Versão do Programa" -#define D_BUILD_DATE_AND_TIME "Data e Hora da construção" +#define D_BUILD_DATE_AND_TIME "Data e Hora de criação" #define D_CORE_AND_SDK_VERSION "Versão Core/SDK" -#define D_FLASH_WRITE_COUNT "contagem de gravação flash" +#define D_FLASH_WRITE_COUNT "Contagem de gravação da flash" #define D_MAC_ADDRESS "Endereço MAC" -#define D_MQTT_HOST "MQTT Servidor" -#define D_MQTT_PORT "MQTT Porta" -#define D_MQTT_CLIENT "MQTT Cliente" -#define D_MQTT_USER "MQTT Utilizador" -#define D_MQTT_TOPIC "MQTT Tópico" -#define D_MQTT_GROUP_TOPIC "MQTT Tópico Grupo" -#define D_MQTT_FULL_TOPIC "MQTT Tópico Completo" +#define D_MQTT_HOST "Servidor MQTT" +#define D_MQTT_PORT "Porta MQTT" +#define D_MQTT_CLIENT "Cliente MQTT" +#define D_MQTT_USER "Utilizador MQTT" +#define D_MQTT_TOPIC "Tópico MQTT" +#define D_MQTT_GROUP_TOPIC "Tópico MQTT de Grupo" +#define D_MQTT_FULL_TOPIC "Tópico MQTT Completo" #define D_MDNS_DISCOVERY "Descobrir mDNS" #define D_MDNS_ADVERTISE "Anunciar mDNS" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash Size" -#define D_FREE_PROGRAM_SPACE "Espaço Livre Programa" +#define D_ESP_CHIP_ID "ID do chip ESP" +#define D_FLASH_CHIP_ID "ID do chip da Flash" +#define D_FLASH_CHIP_SIZE "Tamanho da Flash" +#define D_FREE_PROGRAM_SPACE "Espaço de Programa Livre" #define D_UPGRADE_BY_WEBSERVER "Atualizar pelo servidor WEB" -#define D_OTA_URL "OTA Url" +#define D_OTA_URL "Url OTA" #define D_START_UPGRADE "Iniciar atualização" -#define D_UPGRADE_BY_FILE_UPLOAD "Atualização por envio de ficheiro" -#define D_UPLOAD_STARTED "Início do envio" +#define D_UPGRADE_BY_FILE_UPLOAD "Atualizar por envio de ficheiro" +#define D_UPLOAD_STARTED "Envio Iniciado" #define D_UPGRADE_STARTED "Atualização Iniciada" #define D_UPLOAD_DONE "Atualização Finalizada" #define D_UPLOAD_ERR_1 "Nenhum ficheiro selecionado" -#define D_UPLOAD_ERR_2 "Nao existe espaço disponível" -#define D_UPLOAD_ERR_3 "Byte mágico não é 0xE9" +#define D_UPLOAD_ERR_2 "Não existe espaço disponível" +#define D_UPLOAD_ERR_3 "O Byte mágico não é 0xE9" #define D_UPLOAD_ERR_4 "O tamanho do programa e maior do que o tamanho real da flash" -#define D_UPLOAD_ERR_5 "Envio buffer miscompare" -#define D_UPLOAD_ERR_6 "Falha no envio. Hablitar logging 3" +#define D_UPLOAD_ERR_5 "Comparação incorreta do buffer de upload" +#define D_UPLOAD_ERR_6 "Falha no envio. Habilitar registro 3" #define D_UPLOAD_ERR_7 "Envio cancelado" #define D_UPLOAD_ERR_8 "Ficheiro inválido" #define D_UPLOAD_ERR_9 "Ficheiro demasiado grande" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERR_10 "Falha ao iniciar o chip de RF" +#define D_UPLOAD_ERR_11 "Falha ao apagar o chip de RF" +#define D_UPLOAD_ERR_12 "Falha ao escrever no chip de RF" +#define D_UPLOAD_ERR_13 "Falha ao descodificar o firmware RF" #define D_UPLOAD_ERROR_CODE "Código de erro do envio" #define D_ENTER_COMMAND "Inserir comando" @@ -361,14 +361,14 @@ // xdrv_01_mqtt.ino #define D_FINGERPRINT "Verifique a impressão digital TLS..." #define D_TLS_CONNECT_FAILED_TO "TLS não conseguiu ligar" -#define D_RETRY_IN "Tentativa em" -#define D_VERIFIED "Verificado impressão digital " +#define D_RETRY_IN "Nova tentativa em" +#define D_VERIFIED "Verificado usando impressão digital" #define D_INSECURE "Ligação insegura devido à impressão digital inválida" #define D_CONNECT_FAILED_TO "A ligação falhou ao" // xplg_wemohue.ino #define D_MULTICAST_DISABLED "Multicast desabilitado" -#define D_MULTICAST_REJOINED "Multicast (re)ingressou" +#define D_MULTICAST_REJOINED "Multicast (re)ingressado" #define D_MULTICAST_JOIN_FAILED "Multicast falha no reingresso" #define D_FAILED_TO_SEND_RESPONSE "Falha no envio de reposta" @@ -377,13 +377,13 @@ #define D_WEMO_EVENT_SERVICE "WeMo evento de serviço" #define D_WEMO_META_SERVICE "WeMo serviço meta" #define D_WEMO_SETUP "WeMo configuração" -#define D_RESPONSE_SENT "Rsposta enviada" +#define D_RESPONSE_SENT "Resposta enviada" #define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API nao implementada" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" +#define D_HUE_BRIDGE_SETUP "Configuração do Hue" +#define D_HUE_API_NOT_IMPLEMENTED "API Hue nao implementada" +#define D_HUE_API "API Hue" +#define D_HUE_POST_ARGS "Argumentos de POST HUE" #define D_3_RESPONSE_PACKETS_SENT "3 pacotes de resposta enviados" // xdrv_07_domoticz.ino @@ -402,71 +402,71 @@ #define D_DOMOTICZ_CURRENT "Corrente/PM10" #define D_DOMOTICZ_AIRQUALITY "Qualidade do Ar" #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Tempo de atualização" +#define D_DOMOTICZ_UPDATE_TIMER "Temporizador de atualização" // xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configure Timer" -#define D_TIMER_PARAMETERS "Timer parameters" -#define D_TIMER_ENABLE "Enable Timers" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Time" -#define D_TIMER_DAYS "Days" -#define D_TIMER_REPEAT "Repeat" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Action" +#define D_CONFIGURE_TIMER "Configurar temporizador" +#define D_TIMER_PARAMETERS "Parâmetros do temporizador" +#define D_TIMER_ENABLE "Habilitar Temporizadores" +#define D_TIMER_ARM "Armar" +#define D_TIMER_TIME "Tempo" +#define D_TIMER_DAYS "Dias" +#define D_TIMER_REPEAT "Repetir" +#define D_TIMER_OUTPUT "Aaída" +#define D_TIMER_ACTION "Açao" // xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configure KNX" -#define D_KNX_PARAMETERS "KNX Parameters" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Physical Address" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "Enable KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Add" -#define D_DELETE "Delete" -#define D_REPLY "Reply" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_CONFIGURE_KNX "Configurar KNX" +#define D_KNX_PARAMETERS "Parâmetros KNX" +#define D_KNX_GENERAL_CONFIG "Geral" +#define D_KNX_PHYSICAL_ADDRESS "Endereço físico" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Deve ser exclusivo na rede KNX )" +#define D_KNX_ENABLE "Habilitar KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dados para enviar para Endereços de Grupo" +#define D_ADD "Adicionar" +#define D_DELETE "Remover" +#define D_REPLY "Responder" +#define D_KNX_GROUP_ADDRESS_TO_READ "Endereços de Grupo de onde receber dados" #define D_LOG_KNX "KNX: " -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Write" -#define D_KNX_COMMAND_READ "Read" -#define D_KNX_COMMAND_OTHER "Other" -#define D_SENT_TO "sent to" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_RECEIVED_FROM "Recebido de" +#define D_KNX_COMMAND_WRITE "Escrever" +#define D_KNX_COMMAND_READ "Ler" +#define D_KNX_COMMAND_OTHER "Outro" +#define D_SENT_TO "enviar para" +#define D_KNX_WARNING "O Endereço de Grupo ( 0 / 0 / 0 ) está reservado e não pode ser usado." +#define D_KNX_ENHANCEMENT "Melhoria de Comunicação" #define D_KNX_TX_SLOT "KNX TX" #define D_KNX_RX_SLOT "KNX RX" // xdrv_03_energy.ino #define D_ENERGY_TODAY "Consumo energético de hoje" #define D_ENERGY_YESTERDAY "Consumo energético de ontem" -#define D_ENERGY_TOTAL "Consumo total de energial" +#define D_ENERGY_TOTAL "Consumo energético total" // xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" +#define D_OPEN "Abrir" +#define D_CLOSE "Fechar" +#define D_DOMOTICZ_SHUTTER "Estore" // xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" +#define D_CONFIGURE_PCF8574 "Configurar PCF8574" +#define D_PCF8574_PARAMETERS "Parâmetros PCF8574" +#define D_INVERT_PORTS "Inverter Portas" +#define D_DEVICE "Dispositivo" +#define D_DEVICE_INPUT "Entrada" +#define D_DEVICE_OUTPUT "Saída" // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor ocupado" -#define D_SENSOR_CRC_ERROR "Erro Sensor CRC" -#define D_SENSORS_FOUND "Sensors encontrados" +#define D_SENSOR_CRC_ERROR "Erro no CRC do sensor" +#define D_SENSORS_FOUND "Sensores encontrados" // xsns_06_dht.ino #define D_TIMEOUT_WAITING_FOR "Fim do tempo de espera" #define D_START_SIGNAL_LOW "Sinal de início baixo" #define D_START_SIGNAL_HIGH "Sinal de início elevado" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "Falha Checksum" +#define D_PULSE "pulso" +#define D_CHECKSUM_FAILURE "Falha na soma de verificação" // xsns_07_sht1x.ino #define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor não aceitou o comando ACK" @@ -486,27 +486,27 @@ #define D_GZ_AXIS "Gyro Z-Axis" // xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" +#define D_HX_CAL_REMOVE "Remover peso" +#define D_HX_CAL_REFERENCE "Carregar peso de referência" +#define D_HX_CAL_DONE "Calibrado" +#define D_HX_CAL_FAIL "Falha na calibração" +#define D_RESET_HX711 "Reiniciar balança" +#define D_CONFIGURE_HX711 "Configurar balança" +#define D_HX711_PARAMETERS "Parâmetros da balança" +#define D_ITEM_WEIGHT "Peso do item" +#define D_REFERENCE_WEIGHT "Peso de referência" +#define D_CALIBRATE "Calibrar" +#define D_CALIBRATION "Calibração" //xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_WIND_DIRECTION "Direção do vento +#define D_TX20_WIND_SPEED "Velocidade do vento" +#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" +#define D_TX20_WIND_SPEED_MAX "Velocidade máxima do vento" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" #define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" +#define D_TX20_WEST "O" //xsns_43_hre.ino #define D_LOG_HRE "HRE: " @@ -544,7 +544,7 @@ #define D_SENSOR_SPI_MISO "SPI MISO" #define D_SENSOR_SPI_MOSI "SPI MOSI" #define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Luz negra" +#define D_SENSOR_BACKLIGHT "Luz fundo" #define D_SENSOR_PMS5003 "PMS5003" #define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" #define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" @@ -573,7 +573,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_RF_SENSOR "Sensor RF" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" #define D_SENSOR_MAX31855_CS "MX31855 CS" @@ -599,7 +599,7 @@ #define D_SENSOR_ARIRFSEL "ALux IrSel" #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_ROTARY "Rotativo" // Suffix "1A" #define D_SENSOR_HRE_CLOCK "HRE Clock" #define D_SENSOR_HRE_DATA "HRE Data" #define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" @@ -657,7 +657,7 @@ #define D_UNIT_PARTS_PER_MILLION "ppm" #define D_UNIT_PRESSURE "hPa" #define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectors" +#define D_UNIT_SECTORS "setores" #define D_UNIT_VA "VA" #define D_UNIT_VAR "VAr" #define D_UNIT_VOLT "V" @@ -691,37 +691,37 @@ #define D_LOG_WIFI "WIF: " // Wifi //SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" +#define D_PHASE_ANGLE "Ângulo de fase" +#define D_IMPORT_ACTIVE "Ativo importado" +#define D_EXPORT_ACTIVE "Ativo exportado" +#define D_IMPORT_REACTIVE "Reativo importado" +#define D_EXPORT_REACTIVE "Reativo exportado" +#define D_TOTAL_REACTIVE "Reactivo total" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" //SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" +#define D_PV1_VOLTAGE "Voltagem PV1" +#define D_PV1_CURRENT "Corrente PV1" +#define D_PV1_POWER "Potência PV1" +#define D_PV2_VOLTAGE "Voltagem PV2" +#define D_PV2_CURRENT "Corrente PV2" +#define D_PV2_POWER "Potência PV2" +#define D_SOLAR_POWER "Potência Solar" +#define D_INVERTER_POWER "Potência do Inversor" +#define D_STATUS "Estado" +#define D_WAITING "Esperando" +#define D_CHECKING "Verificando" +#define D_WORKING "Trabalhando" +#define D_FAILURE "Falha" +#define D_SOLAX_ERROR_0 "Nenhum código de erro" +#define D_SOLAX_ERROR_1 "Falha devido a perda de rede" +#define D_SOLAX_ERROR_2 "Falha devido a perda de tensão" +#define D_SOLAX_ERROR_3 "Falha devido a perda de frequência" +#define D_SOLAX_ERROR_4 "Falha de tensão de Pv" +#define D_SOLAX_ERROR_5 "Falha de isolamento" +#define D_SOLAX_ERROR_6 "Falha de temperatura excessiva" +#define D_SOLAX_ERROR_7 "Falha no ventilador" +#define D_SOLAX_ERROR_8 "Outra falha no dispositivo" #endif // _LANGUAGE_PT_PT_H_ From 0cffc0207f7475c7d9d12c4c0b19d71ed5a57820 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 25 Oct 2019 11:37:49 +0200 Subject: [PATCH 016/196] Update nl-NL.h --- sonoff/language/nl-NL.h | 108 ++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 4091f9928..0e81cebff 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.0.0a + * Updated until v6.7.0 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -93,7 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "Onwaar" #define D_FILE "Bestand" -#define D_FLOW_RATE "Flow rate" +#define D_FLOW_RATE "Debiet" #define D_FREE_MEMORY "Vrij geheugen" #define D_FREQUENCY "Frequentie" #define D_GAS "Gas" @@ -149,7 +149,7 @@ #define D_STOP "Stop" #define D_SUBNET_MASK "Subnet Masker" #define D_SUBSCRIBE_TO "Abonneer op" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_UNSUBSCRIBE_FROM "Uitschrijven van" #define D_SUCCESSFUL "Gelukt" #define D_SUNRISE "Zonsopgang" #define D_SUNSET "Zonsondergang" @@ -157,7 +157,7 @@ #define D_TO "naar" #define D_TOGGLE "Toggle" // Wissel, Tuimel #define D_TOPIC "Topic" // Onderwerp -#define D_TOTAL_USAGE "Total Usage" +#define D_TOTAL_USAGE "Totaal verbruik" #define D_TRANSMIT "Verzend" #define D_TRUE "Waar" #define D_TVOC "TVOC" @@ -167,15 +167,15 @@ #define D_USER "Gebruiker" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV-index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" +#define D_UV_INDEX_1 "Laag" +#define D_UV_INDEX_2 "Gemiddeld" +#define D_UV_INDEX_3 "Hoog" +#define D_UV_INDEX_4 "Intens" +#define D_UV_INDEX_5 "Gevaarlijk" +#define D_UV_INDEX_6 "Schadelijk" +#define D_UV_INDEX_7 "Uitzonderlijk" #define D_UV_LEVEL "UV niveau" -#define D_UV_POWER "UV Power" +#define D_UV_POWER "UV intensiteit" #define D_VERSION "Versie" #define D_VOLTAGE "Spanning" #define D_WEIGHT "Gewicht" @@ -227,7 +227,7 @@ #define D_WITH_IP_ADDRESS "met IP adres" #define D_WEBSERVER_STOPPED "Webserver gestopt" #define D_FILE_NOT_FOUND "Bestand niet gevonden" -#define D_REDIRECTED "Redirected to captive portal" +#define D_REDIRECTED "Omleiding naar captive portal" #define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager start AccessPoint en hou Station" #define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager start AccessPoint" #define D_TRYING_TO_CONNECT "Apparaat probeert te verbinden met netwerk" @@ -284,7 +284,7 @@ #define D_LOGGING_PARAMETERS "Logging parameters" #define D_SERIAL_LOG_LEVEL "Serieel log niveau" -#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_MQTT_LOG_LEVEL "Mqtt log niveau" #define D_WEB_LOG_LEVEL "Web log niveau" #define D_SYS_LOG_LEVEL "Syslog niveau" #define D_MORE_DEBUG "Meer debug" @@ -444,17 +444,17 @@ #define D_ENERGY_TOTAL "Verbruik totaal" // xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" +#define D_OPEN "Openen" +#define D_CLOSE "Sluiten" +#define D_DOMOTICZ_SHUTTER "Rolluik" // xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" +#define D_CONFIGURE_PCF8574 "Configureer PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 Parameters" +#define D_INVERT_PORTS "Inverteer Poorten" +#define D_DEVICE "Apparaat" +#define D_DEVICE_INPUT "Ingang" +#define D_DEVICE_OUTPUT "Uitgang" // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor bezet" @@ -641,12 +641,12 @@ #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" #define D_UNIT_MILLIAMPERE "mA" #define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" @@ -691,37 +691,37 @@ #define D_LOG_WIFI "WIF: " // Wifi //SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" +#define D_PHASE_ANGLE "Fase hoek" +#define D_IMPORT_ACTIVE "Import werkelijk" +#define D_EXPORT_ACTIVE "Export werkelijk" +#define D_IMPORT_REACTIVE "Import blind" +#define D_EXPORT_REACTIVE "Export blind" +#define D_TOTAL_REACTIVE "Totaal blind" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" //SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" +#define D_PV1_VOLTAGE "PV1 spanning" +#define D_PV1_CURRENT "PV1 stroom" +#define D_PV1_POWER "PV1 vermogen" +#define D_PV2_VOLTAGE "PV2 spanning" +#define D_PV2_CURRENT "PV2 stroom" +#define D_PV2_POWER "PV2 vermogen" +#define D_SOLAR_POWER "Zon vermogen" +#define D_INVERTER_POWER "Omvormer vermogen" #define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" +#define D_WAITING "Wacht" +#define D_CHECKING "Controle" +#define D_WORKING "Actief" +#define D_FAILURE "Fout" +#define D_SOLAX_ERROR_0 "Geen" +#define D_SOLAX_ERROR_1 "Netverbinding" +#define D_SOLAX_ERROR_2 "Netspanning" +#define D_SOLAX_ERROR_3 "Netfrequentie" +#define D_SOLAX_ERROR_4 "Pv spanning" +#define D_SOLAX_ERROR_5 "Isolatie" +#define D_SOLAX_ERROR_6 "Overtemperatuur" +#define D_SOLAX_ERROR_7 "Ventilator" +#define D_SOLAX_ERROR_8 "Overige" #endif // _LANGUAGE_NL_NL_H_ From 4c22d80c73087cc4e1f1dd93c5d7b2f40729c557 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 25 Oct 2019 13:14:05 +0200 Subject: [PATCH 017/196] Bump version to 6.7 --- sonoff/_changelog.ino | 3 +++ sonoff/sonoff_version.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 1c37b3664..b964b449d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ /*********************************************************************************************\ + * 6.7.0 20191025 + * Release + * * 6.6.0.21 20191022 * Remove support for WPS and SmartConfig in favour of Web server (!) based WifiManager (#6680) * Remove binary sonoff-classic (#6680) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 22e12ed7b..1731d80a5 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06060015; +const uint32_t VERSION = 0x06070000; #endif // _SONOFF_VERSION_H_ From e4b032315b2906655516fcc655d52921c304d2a2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 25 Oct 2019 13:28:53 +0200 Subject: [PATCH 018/196] Release 6.7 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2da0e0a01..b2d85c6d7 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest) the binaries can also be downloaded from http://thehackbox.org/tasmota/release/ ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v6.6.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v6.7.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota) From 958ddcad919c2589948480a753a0c15f709bf633 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 25 Oct 2019 18:16:09 +0200 Subject: [PATCH 019/196] Fix exception 0 on power delta Fix exception 0 on power delta (#6741) --- sonoff/xdrv_03_energy.ino | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 30b0237e2..aa580421d 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -292,11 +292,13 @@ void EnergyMarginCheck(void) DEBUG_DRIVER_LOG(PSTR("NRG: Delta %d, Power %d"), delta, min_power); - 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; - Energy.power_history[1] = Energy.active_power[0]; // We only want one report so reset history - Energy.power_history[2] = Energy.active_power[0]; + if (delta) { // 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; + Energy.power_history[1] = Energy.active_power[0]; // We only want one report so reset history + Energy.power_history[2] = Energy.active_power[0]; + } } } Energy.power_history[0] = Energy.power_history[1]; // Shift in history every second allowing power changes to settle for up to three seconds From 6529820e0abe9f662ac7a8242a79a0b787e4ee10 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 25 Oct 2019 18:27:14 +0200 Subject: [PATCH 020/196] Revert cleaning unused settings Revert cleaning unused settings to aide fallback scenarios --- sonoff/settings.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 0a34123df..f49eb9495 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -1199,6 +1199,7 @@ void SettingsDelta(void) } if (Settings.version < 0x06060014) { // Clear unused parameters for future use +/* Settings.flag3.ex_tuya_dimmer_range_255 = 0; Settings.flag3.ex_tuya_dimmer_min_limit = 0; Settings.param[P_ex_TUYA_RELAYS] = 0; @@ -1208,7 +1209,7 @@ void SettingsDelta(void) Settings.param[P_ex_TUYA_POWER_ID] = 0; Settings.ex_baudrate = 0; Settings.ex_sbaudrate = 0; - +*/ Settings.flag3.fast_power_cycle_disable = 0; Settings.energy_power_delta = Settings.ex_energy_power_delta; Settings.ex_energy_power_delta = 0; From b2ea36a400842556923bdf8902f1831b8fb9491c Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Mon, 14 Oct 2019 14:20:47 +0100 Subject: [PATCH 021/196] TuyaMcu: Implement support for battery powered protocol --- sonoff/xdrv_16_tuyamcu.ino | 234 ++++++++++++++++++++++++------------- 1 file changed, 155 insertions(+), 79 deletions(-) diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index 2cf63c8d0..a1761ca2f 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -37,8 +37,14 @@ #define TUYA_CMD_STATE 0x07 #define TUYA_CMD_QUERY_STATE 0x08 +#define TUYA_LOW_POWER_CMD_WIFI_STATE 0x02 +#define TUYA_LOW_POWER_CMD_WIFI_RESET 0x03 +#define TUYA_LOW_POWER_CMD_WIFI_CONFIG 0x04 +#define TUYA_LOW_POWER_CMD_STATE 0x05 + #define TUYA_TYPE_BOOL 0x01 #define TUYA_TYPE_VALUE 0x02 +#define TUYA_TYPE_ENUM 0x04 #define TUYA_BUFFER_SIZE 256 @@ -52,13 +58,15 @@ struct TUYA { uint8_t cmd_status = 0; // Current status of serial-read uint8_t cmd_checksum = 0; // Checksum of tuya command uint8_t data_len = 0; // Data lenght of command - int8_t wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() + uint8_t wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() uint8_t heartbeat_timer = 0; // 10 second heartbeat timer for tuya module #ifdef USE_ENERGY_SENSOR uint32_t lastPowerCheckTime = 0; // Time when last power was checked #endif // USE_ENERGY_SENSOR char *buffer = nullptr; // Serial receive buffer int byte_counter = 0; // Index in serial receive buffer + bool low_power_mode = false; // Normal or Low power mode protocol + bool send_success_next_second = false; // Second command success in low power mode } Tuya; @@ -80,6 +88,8 @@ enum TuyaSupportedFunctions { TUYA_MCU_FUNC_POWER = 31, TUYA_MCU_FUNC_CURRENT, TUYA_MCU_FUNC_VOLTAGE, + TUYA_MCU_FUNC_BATTERY_STATE, + TUYA_MCU_FUNC_BATTERY_PERCENTAGE, TUYA_MCU_FUNC_REL1_INV = 41, // Inverted Relays TUYA_MCU_FUNC_REL2_INV, TUYA_MCU_FUNC_REL3_INV, @@ -88,6 +98,7 @@ enum TuyaSupportedFunctions { TUYA_MCU_FUNC_REL6_INV, TUYA_MCU_FUNC_REL7_INV, TUYA_MCU_FUNC_REL8_INV, + TUYA_MCU_FUNC_LOWPOWER_MODE = 51, TUYA_MCU_FUNC_LAST = 255 }; @@ -190,7 +201,8 @@ inline bool TuyaFuncIdValid(uint8_t fnId) { (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || fnId == TUYA_MCU_FUNC_DIMMER || (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE) || - (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV); + (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) || + (fnId == TUYA_MCU_FUNC_LOWPOWER_MODE); } uint8_t TuyaGetFuncId(uint8_t dpid) { @@ -331,12 +343,110 @@ void TuyaResetWifi(void) } } -void TuyaPacketProcess(void) -{ +void TuyaProcessStatePacket(void) { char scmnd[20]; - uint8_t fnId = TUYA_MCU_FUNC_NONE; + uint8_t fnId = TuyaGetFuncId(Tuya.buffer[6]); + 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 + + 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)); + + if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[10]) { + SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[10]); + SwitchHandler(1); + } + } + + } + 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) && (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); + } + } + +#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); + + 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; + } +#endif // USE_ENERGY_SENSOR + + } + // } else { + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Unknown FnId=%s for dpId=%s"), fnId, Tuya.buffer[6]); + // } +} + +void TuyaLowPowerModePacketProcess(void) { switch (Tuya.buffer[3]) { + case TUYA_CMD_QUERY_PRODUCT: + TuyaHandleProductInfoPacket(); + TuyaSetWifiLed(); + break; + + case TUYA_LOW_POWER_CMD_STATE: + TuyaProcessStatePacket(); + Tuya.send_success_next_second = true; + break; + } + +} + +void TuyaHandleProductInfoPacket(void) { + uint16_t dataLength = Tuya.buffer[4] << 8 | Tuya.buffer[5]; + char *data = &Tuya.buffer[6]; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TYA: MCU Product ID: %.*s"), dataLength, data); +} + +void TuyaSendLowPowerSuccessIfNeeded(void) { + uint8_t success = 1; + + if (Tuya.send_success_next_second) { + TuyaSendCmd(TUYA_LOW_POWER_CMD_STATE, &success, 1); + Tuya.send_success_next_second = false; + } +} + +void TuyaNormalPowerModePacketProcess(void) +{ + switch (Tuya.buffer[3]) { + case TUYA_CMD_QUERY_PRODUCT: + TuyaHandleProductInfoPacket(); + TuyaSendCmd(TUYA_CMD_MCU_CONF); + break; case TUYA_CMD_HEARTBEAT: AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); @@ -347,68 +457,7 @@ void TuyaPacketProcess(void) break; case TUYA_CMD_STATE: - fnId = TuyaGetFuncId(Tuya.buffer[6]); - 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 - - 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)); - - if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[10]) { - SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[10]); - SwitchHandler(1); - } - } - - } - 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) && (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); - } - } - - #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); - - 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; - } - #endif // USE_ENERGY_SENSOR - - } - // } else { - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Unknown FnId=%s for dpId=%s"), fnId, Tuya.buffer[6]); - // } + TuyaProcessStatePacket(); break; case TUYA_CMD_WIFI_RESET: @@ -419,7 +468,7 @@ void TuyaPacketProcess(void) case TUYA_CMD_WIFI_STATE: AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi LED set ACK")); - Tuya.wifi_state = WifiState(); + Tuya.wifi_state = TuyaGetTuyaWifiState(); break; case TUYA_CMD_MCU_CONF: @@ -491,6 +540,10 @@ bool TuyaModuleSelected(void) light_type = LT_BASIC; } + if (TuyaGetDpId(TUYA_MCU_FUNC_LOWPOWER_MODE) != 0) { + Tuya.low_power_mode = true; + } + UpdateDevices(); return true; } @@ -505,7 +558,7 @@ void TuyaInit(void) // Get MCU Configuration AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration")); - TuyaSendCmd(TUYA_CMD_MCU_CONF); + TuyaSendCmd(TUYA_CMD_QUERY_PRODUCT); } } Tuya.heartbeat_timer = 0; // init heartbeat timer when dimmer init is done @@ -546,7 +599,12 @@ void TuyaSerialInput(void) MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); XdrvRulesProcess(); - TuyaPacketProcess(); + if (!Tuya.low_power_mode) { + TuyaNormalPowerModePacketProcess(); + } else { + TuyaLowPowerModePacketProcess(); + } + Tuya.byte_counter = 0; Tuya.cmd_status = 0; Tuya.cmd_checksum = 0; @@ -574,8 +632,8 @@ bool TuyaButtonPressed(void) return false; // Don't serve other buttons } -void TuyaSetWifiLed(void) -{ +uint8_t TuyaGetTuyaWifiState(void) { + uint8_t wifi_state = 0x02; switch(WifiState()){ case WIFI_MANAGER: @@ -586,9 +644,23 @@ void TuyaSetWifiLed(void) break; } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED %d (%d)"), wifi_state, WifiState()); + if (MqttIsConnected()) { + wifi_state = 0x04; + } - TuyaSendCmd(TUYA_CMD_WIFI_STATE, &wifi_state, 1); + return wifi_state; +} + +void TuyaSetWifiLed(void) +{ + Tuya.wifi_state = TuyaGetTuyaWifiState(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED %d (%d)"), Tuya.wifi_state, WifiState()); + + if (Tuya.low_power_mode) { + TuyaSendCmd(TUYA_LOW_POWER_CMD_WIFI_STATE, &Tuya.wifi_state, 1); + } else { + TuyaSendCmd(TUYA_CMD_WIFI_STATE, &Tuya.wifi_state, 1); + } } #ifdef USE_ENERGY_SENSOR @@ -643,11 +715,15 @@ bool Xdrv16(uint8_t function) result = TuyaButtonPressed(); break; case FUNC_EVERY_SECOND: - if (TuyaSerial && Tuya.wifi_state != WifiState()) { TuyaSetWifiLed(); } - Tuya.heartbeat_timer++; - if (Tuya.heartbeat_timer > 10) { - Tuya.heartbeat_timer = 0; - TuyaSendCmd(TUYA_CMD_HEARTBEAT); + if (TuyaSerial && Tuya.wifi_state != TuyaGetTuyaWifiState()) { TuyaSetWifiLed(); } + if (!Tuya.low_power_mode) { + Tuya.heartbeat_timer++; + if (Tuya.heartbeat_timer > 10) { + Tuya.heartbeat_timer = 0; + TuyaSendCmd(TUYA_CMD_HEARTBEAT); + } + } else { + TuyaSendLowPowerSuccessIfNeeded(); } break; case FUNC_SET_CHANNELS: From e6f94fe37b26e427e580e2485140c4cae962bbce Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Tue, 22 Oct 2019 17:41:31 +0100 Subject: [PATCH 022/196] TuyaMcu: Add TuyaSend command to communicate with Tuya MCU --- sonoff/i18n.h | 1 + sonoff/xdrv_16_tuyamcu.ino | 72 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index d8d0db151..234e2ee59 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -452,6 +452,7 @@ // Commands xdrv_16_tuyadimmer.ino #define D_CMND_TUYA_MCU "TuyaMCU" +#define D_CMND_TUYA_MCU_SEND_STATE "TuyaSend" #define D_JSON_TUYA_MCU_RECEIVED "TuyaMcuReceived" // Commands xdrv_23_zigbee.ino diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index a1761ca2f..ac5b66266 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -44,6 +44,7 @@ #define TUYA_TYPE_BOOL 0x01 #define TUYA_TYPE_VALUE 0x02 +#define TUYA_TYPE_STRING 0x03 #define TUYA_TYPE_ENUM 0x04 #define TUYA_BUFFER_SIZE 256 @@ -103,12 +104,55 @@ enum TuyaSupportedFunctions { }; const char kTuyaCommand[] PROGMEM = "|" // No prefix - D_CMND_TUYA_MCU; + D_CMND_TUYA_MCU "|" D_CMND_TUYA_MCU_SEND_STATE; void (* const TuyaCommand[])(void) PROGMEM = { - &CmndTuyaMcu + &CmndTuyaMcu, &CmndTuyaSend }; +/* + +TuyaSend dpId,data + +TuyaSend1 11,1 -> Sends boolean (Type 1) data 0/1 to dpId 11 (Max data length 1 byte) +TuyaSend2 11,100 -> Sends integer (Type 2) data 100 to dpId 11 (Max data length 4 bytes) +TuyaSend2 11,0xAABBCCDD -> Sends 4 bytes (Type 2) data to dpId 11 (Max data length 4 bytes) +TuyaSend3 11,ThisIsTheData -> Sends the supplied string (Type 3) to dpId 11 ( Max data length not-known) +TuyaSend4 11,1 -> Sends enum (Type 4) data 0/1/2/3/4/5 to dpId 11 (Max data length 1 bytes) + +*/ + + +void CmndTuyaSend(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { + if (XdrvMailbox.data_len > 0) { + + char *p; + char *data; + uint8_t i = 0; + uint8_t dpId = 0; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { + if ( i == 0) { + dpId = strtoul(str, nullptr, 0); + } else { + data = str; + } + i++; + } + + if (1 == XdrvMailbox.index) { + TuyaSendBool(dpId, strtoul(data, nullptr, 0)); + } else if (2 == XdrvMailbox.index) { + TuyaSendValue(dpId, strtoull(data, nullptr, 0)); + } else if (3 == XdrvMailbox.index) { + TuyaSendString(dpId, data); + } else if (4 == XdrvMailbox.index) { + TuyaSendEnum(dpId, strtoul(data, nullptr, 0)); + } + } + ResponseCmndDone(); + } +} /* @@ -252,6 +296,7 @@ void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value) payload_buffer[1] = type; switch (type) { case TUYA_TYPE_BOOL: + case TUYA_TYPE_ENUM: payload_len += 1; payload_buffer[2] = 0x00; payload_buffer[3] = 0x01; @@ -266,6 +311,7 @@ void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value) payload_buffer[6] = value[1]; payload_buffer[7] = value[0]; break; + } TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); @@ -281,6 +327,28 @@ void TuyaSendValue(uint8_t id, uint32_t value) TuyaSendState(id, TUYA_TYPE_VALUE, (uint8_t*)(&value)); } +void TuyaSendEnum(uint8_t id, uint32_t value) +{ + TuyaSendState(id, TUYA_TYPE_ENUM, (uint8_t*)(&value)); +} + +void TuyaSendString(uint8_t id, char data[]) { + + uint16_t len = strlen(data); + uint16_t payload_len = 4 + len; + uint8_t payload_buffer[payload_len]; + payload_buffer[0] = id; + payload_buffer[1] = TUYA_TYPE_STRING; + payload_buffer[2] = len >> 8; + payload_buffer[3] = len & 0xFF; + + for (uint16_t i = 0; i < len; i++) { + payload_buffer[4+i] = data[i]; + } + + TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + bool TuyaSetPower(void) { bool status = false; From 8a0765a67bf4d82b621d3b6f9eabac18973676ba Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Thu, 24 Oct 2019 16:03:07 +0100 Subject: [PATCH 023/196] TuyaMcu: Add more details to TuyaMcuReceived --- sonoff/xdrv_16_tuyamcu.ino | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index ac5b66266..0e983b483 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -415,7 +415,7 @@ void TuyaProcessStatePacket(void) { char scmnd[20]; uint8_t fnId = TuyaGetFuncId(Tuya.buffer[6]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: FnId=%d is set for dpId=%d"), fnId, Tuya.buffer[6]); + 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 @@ -663,7 +663,22 @@ void TuyaSerialInput(void) Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; char hex_char[(Tuya.byte_counter * 2) + 2]; - Response_P(PSTR("{\"" D_JSON_TUYA_MCU_RECEIVED "\":\"%s\"}"), ToHex_P((unsigned char*)Tuya.buffer, Tuya.byte_counter, hex_char, sizeof(hex_char))); + uint16_t len = Tuya.buffer[4] << 8 | Tuya.buffer[5]; + Response_P(PSTR("{\"" D_JSON_TUYA_MCU_RECEIVED "\":{\"Data\":\"%s\",\"Cmnd\":%d"), ToHex_P((unsigned char*)Tuya.buffer, Tuya.byte_counter, hex_char, sizeof(hex_char)), Tuya.buffer[3]); + + 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]); + } + } + } + + ResponseAppend_P(PSTR("}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); XdrvRulesProcess(); From 3d7e122d34c584e0d318e2dd92c9ca3c6cc40d7a Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Thu, 24 Oct 2019 17:42:18 +0100 Subject: [PATCH 024/196] TuyaMcu: Disable fast reset in low power devices Battery powered devices don't stay up for long which could lead to reset. --- sonoff/xdrv_16_tuyamcu.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index 0e983b483..f9f412968 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -610,6 +610,7 @@ bool TuyaModuleSelected(void) if (TuyaGetDpId(TUYA_MCU_FUNC_LOWPOWER_MODE) != 0) { Tuya.low_power_mode = true; + Settings.flag3.fast_power_cycle_disable = true; } UpdateDevices(); From 4944b308304b9eb7f84dc567a72f7b4a56a9fe50 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Fri, 25 Oct 2019 07:05:12 +0100 Subject: [PATCH 025/196] TuyaMcu : Use SetOption66 to enable / disable publishing TuyaMcuReceived over Mqtt --- sonoff/settings.h | 2 +- sonoff/settings.ino | 4 ++-- sonoff/xdrv_16_tuyamcu.ino | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 80960260a..5f8e2f6ce 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -79,7 +79,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t no_power_feedback : 1; // bit 13 (v6.5.0.9) - SetOption63 - Don't scan relay power state at restart uint32_t use_underscore : 1; // bit 14 (v6.5.0.12) - SetOption64 - Enable "_" instead of "-" as sensor index separator uint32_t fast_power_cycle_disable : 1; // bit 15 (v6.6.0.20) - SetOption65 - Disable fast power cycle detection for device reset - uint32_t ex_tuya_dimmer_range_255 : 1; // bit 16 (v6.6.0.1) - SetOption66 - Enable or Disable Dimmer range 255 slider control + uint32_t tuya_serial_mqtt_publish : 1; // bit 16 (v6.6.0.21) - SetOption66 - Enable or Disable TuyaMcuReceived messages over Mqtt uint32_t buzzer_enable : 1; // bit 17 (v6.6.0.1) - SetOption67 - Enable buzzer when available uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM uint32_t ex_tuya_dimmer_min_limit : 1; // bit 19 (v6.6.0.5) - SetOption69 - Limits Tuya dimmers to minimum of 10% (25) when enabled. diff --git a/sonoff/settings.ino b/sonoff/settings.ino index f49eb9495..76dcade8c 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -1126,7 +1126,7 @@ void SettingsDelta(void) } if (Settings.version < 0x06060008) { // Move current tuya dimmer range to the new param. - if (Settings.flag3.ex_tuya_dimmer_range_255) { + if (Settings.flag3.tuya_serial_mqtt_publish) { // ex Settings.flag3.ex_tuya_dimmer_range_255 SetOption Settings.param[P_ex_DIMMER_MAX] = 100; } else { Settings.param[P_ex_DIMMER_MAX] = 255; @@ -1200,7 +1200,7 @@ void SettingsDelta(void) if (Settings.version < 0x06060014) { // Clear unused parameters for future use /* - Settings.flag3.ex_tuya_dimmer_range_255 = 0; + Settings.flag3.tuya_serial_mqtt_publish = 0; // ex Settings.flag3.ex_tuya_dimmer_range_255 Settings.flag3.ex_tuya_dimmer_min_limit = 0; Settings.param[P_ex_TUYA_RELAYS] = 0; Settings.param[P_ex_DIMMER_MAX] = 0; diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index f9f412968..f0aeccdbd 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -680,7 +680,11 @@ void TuyaSerialInput(void) ResponseAppend_P(PSTR("}}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); + if (Settings.flag3.tuya_serial_mqtt_publish) { + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); + } else { + AddLog_P(LOG_LEVEL_DEBUG, mqtt_data); + } XdrvRulesProcess(); if (!Tuya.low_power_mode) { From c5f5bd81fe3d6a00a535fda5fd01a5c4d0994339 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sat, 26 Oct 2019 10:31:27 +0200 Subject: [PATCH 026/196] scripter fix array bug --- sonoff/xdrv_10_scripter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index e4610c830..850451264 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -2731,7 +2731,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { uint8_t index=glob_script_mem.type[ind.index].index; if ((vtype&STYPE)==0) { // numeric result - if (ind.bits.settable) { + if (ind.bits.settable || ind.bits.is_filter) { dfvar=&sysvar; sysv_type=ind.index; } else { From 5c45fb20b7fd078e3d86986d2a579373a46b21b2 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sat, 26 Oct 2019 10:36:41 +0200 Subject: [PATCH 027/196] Update xdrv_10_scripter.ino --- sonoff/xdrv_10_scripter.ino | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index 850451264..434c1716a 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -2733,7 +2733,12 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { // numeric result if (ind.bits.settable || ind.bits.is_filter) { dfvar=&sysvar; - sysv_type=ind.index; + if (ind.bits.settable) { + sysv_type=ind.index; + } else { + sysv_type=0; + } + } else { dfvar=&glob_script_mem.fvars[index]; sysv_type=0; From b44040af0f30ec904d624771130546c6bd4e1c66 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 26 Oct 2019 13:13:16 +0200 Subject: [PATCH 028/196] Bump version 6.7.1 * Fix on energy monitoring devices using PowerDelta Exception0 with epc1:0x4000dce5 = Divide by zero (#6750) * Fix Script array bug (#6751) --- sonoff/_changelog.ino | 5 +++++ sonoff/sonoff_version.h | 2 +- sonoff/xdrv_03_energy.ino | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b964b449d..1cb954c7b 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,9 @@ /*********************************************************************************************\ + * 6.7.1 20191026 + * Release + * Fix on energy monitoring devices using PowerDelta Exception0 with epc1:0x4000dce5 = Divide by zero (#6750) + * Fix Script array bug (#6751) + * * 6.7.0 20191025 * Release * diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 1731d80a5..4780ef5e3 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06070000; +const uint32_t VERSION = 0x06070100; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index aa580421d..263b2fa15 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -292,7 +292,7 @@ void EnergyMarginCheck(void) DEBUG_DRIVER_LOG(PSTR("NRG: Delta %d, Power %d"), delta, min_power); - if (delta) { // Fix divide by 0 exception (#6741) + 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; From 915fc274fae54f3937f7a6ebc22a8b010ff6d3d7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 26 Oct 2019 15:29:15 +0200 Subject: [PATCH 029/196] Update docs to 6.7.1 --- README.md | 2 +- RELEASENOTES.md | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b2d85c6d7..cdfdb7757 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest) the binaries can also be downloaded from http://thehackbox.org/tasmota/release/ ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v6.7.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v6.7.1.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6f02b4a74..747baccca 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -154,7 +154,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_ARILUX_RF | - | - | x | x | x | - | - | | USE_SHUTTER | - | - | - | - | - | - | - | | USE_DEEPSLEEP | - | - | - | - | - | - | - | -| USE_EXS_DIMMER | - | - | - | - | - | - | - | +| USE_EXS_DIMMER | - | - | x | x | - | - | - | | | | | | | | | | | Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks | USE_LIGHT | - | x | x | x | x | x | x | @@ -252,14 +252,14 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_DISPLAY_MATRIX | - | - | - | - | - | - | x | | USE_DISPLAY_SH1106 | - | - | - | - | - | - | x | | USE_DISPLAY_ILI9341 | - | - | - | - | - | - | x | -| USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | x | Disabled for core 2.3.0 -| USE_DISPLAY_EPAPER_42 | - | - | - | - | - | - | x | Disabled for core 2.3.0 +| USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | x | +| USE_DISPLAY_EPAPER_42 | - | - | - | - | - | - | x | | USE_DISPLAY_ILI9488 | - | - | - | - | - | - | - | | USE_DISPLAY_SSD1351 | - | - | - | - | - | - | - | | USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | ## Changelog -Version 6.7.0 20191025 +Version 6.7.1 20191026 * Remove support for WPS and SmartConfig in favour of Web server (!) based WifiManager (#6680) * Remove binary sonoff-classic (#6680) * Remove command ``SetOption2`` @@ -287,6 +287,7 @@ Version 6.7.0 20191025 * Change filename of configuration backup from using FriendlyName1 to Hostname solving diacritic issues (#2422) * Change Store AWS IoT Private Key and Certificate in SPI Flash avoiding device-specific compilations * Change defines **USE_TX20_WIND_SENSOR** and **USE_RC_SWITCH** in my_user_config.h to disable to lower iram usage enabling latest core compilation (#6060, #6062) + * Fix PowerDelta related exception0: epc1:0x4000dce5 (#6750) * Fix handling of ligth channels when pwm_multichannel (``SetOption68``) is enabled * Fix better handling of PWM White Temperature mode for Module 48 (#6534) * Fix TasmotaSerial: move serial send to IRAM for high speed baud rates From 9cede73667b1f394c152ddec3ed8c7ded9d26a90 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 26 Oct 2019 22:51:55 +0200 Subject: [PATCH 030/196] Remove unused library --- lib/ArduinoHexParse/README.md | 3 - lib/ArduinoHexParse/keywords.txt | 25 ---- lib/ArduinoHexParse/library.json | 12 -- lib/ArduinoHexParse/library.properties | 9 -- lib/ArduinoHexParse/src/ArduinoHexParse.cpp | 134 -------------------- lib/ArduinoHexParse/src/ArduinoHexParse.h | 47 ------- 6 files changed, 230 deletions(-) delete mode 100644 lib/ArduinoHexParse/README.md delete mode 100644 lib/ArduinoHexParse/keywords.txt delete mode 100644 lib/ArduinoHexParse/library.json delete mode 100644 lib/ArduinoHexParse/library.properties delete mode 100644 lib/ArduinoHexParse/src/ArduinoHexParse.cpp delete mode 100644 lib/ArduinoHexParse/src/ArduinoHexParse.h diff --git a/lib/ArduinoHexParse/README.md b/lib/ArduinoHexParse/README.md deleted file mode 100644 index c5c6a6751..000000000 --- a/lib/ArduinoHexParse/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ArduinoHexParse - -Parse hex files created by Arduino for Uno/Mini/Nano diff --git a/lib/ArduinoHexParse/keywords.txt b/lib/ArduinoHexParse/keywords.txt deleted file mode 100644 index c60688578..000000000 --- a/lib/ArduinoHexParse/keywords.txt +++ /dev/null @@ -1,25 +0,0 @@ -####################################### -# Syntax Coloring Map for ArduinoHexParse -# (esp8266) -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -ArduinoHexParse KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -ArduinoHexParse KEYWORD2 -ParseLine KEYWORD2 -GetFlashPage KEYWORD2 -GetLoadAddress KEYWORD2 -IsFlashPageReady KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### - diff --git a/lib/ArduinoHexParse/library.json b/lib/ArduinoHexParse/library.json deleted file mode 100644 index 896b53f6d..000000000 --- a/lib/ArduinoHexParse/library.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "ArduinoHexParse", - "version": "0.0.1", - "description": "Parse hex files created by Arduino for Uno/Mini/Nano", - "repository": - { - "type": "git", - "url": "https://github.com/arendst/Sonoff-Tasmota/lib/ArduinoHexParse" - }, - "frameworks": "arduino", - "platforms": "espressif8266" -} diff --git a/lib/ArduinoHexParse/library.properties b/lib/ArduinoHexParse/library.properties deleted file mode 100644 index 034c22e64..000000000 --- a/lib/ArduinoHexParse/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=ArduinoHexParse -version=0.0.1 -author=Andre Thomas -maintainer=Andre Thomas -sentence=Parse hex files created by Arduino for Uno/Mini/Nano -paragraph= -category=Signal Input/Output -url= -architectures=esp8266 diff --git a/lib/ArduinoHexParse/src/ArduinoHexParse.cpp b/lib/ArduinoHexParse/src/ArduinoHexParse.cpp deleted file mode 100644 index d4125f2f5..000000000 --- a/lib/ArduinoHexParse/src/ArduinoHexParse.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - Copyright (C) 2019 Andre Thomas 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 . -*/ - -#include -#include "ArduinoHexParse.h" - -ArduinoHexParse::ArduinoHexParse(void) -{ - loadAddress[0] = 0; - loadAddress[1] = 0; -} - -void ArduinoHexParse::ParseLine(byte* hexline) -{ - recordType = GetRecordType(hexline); - if (0 == recordType) { - address = GetAddress(hexline); - len = GetLength(hexline); - GetData(hexline, len); - if (128 == PageMemIdx) { - if (!firstRun) { - loadAddress[1] += 0x40; - if (0 == loadAddress[1]) { - loadAddress[0] += 1; - } - } - firstRun = false; - FlashPageReady = true; - PageMemIdx = 0; - } - nextAddress = address + len; - } - if (1 == recordType) { - EndOfFile(); - FlashPageReady = true; - } -} - -bool ArduinoHexParse::IsFlashPageReady(void) -{ - return FlashPageReady; -} - -byte* ArduinoHexParse::GetFlashPage(void) -{ - FlashPageReady = false; - return FlashPage; -} - -byte* ArduinoHexParse::GetLoadAddress(void) -{ - return loadAddress; -} - -void ArduinoHexParse::GetLoadAddress(byte* hexline) -{ - char buff[3]; - buff[2] = '\0'; - buff[0] = hexline[3]; - buff[1] = hexline[4]; - loadAddress[0] = strtol(buff, 0, 16); - buff[0] = hexline[5]; - buff[1] = hexline[6]; - loadAddress[1] = strtol(buff, 0, 16); -} - -byte* ArduinoHexParse::GetData(byte* hexline, uint32_t len) -{ - uint32_t start = 9; - uint32_t end = (len * 2) + start; - char buff[3]; - buff[2] = '\0'; - for (uint32_t x = start; x < end; x = x+2) { - buff[0] = hexline[x]; - buff[1] = hexline[x+1]; - FlashPage[PageMemIdx] = strtol(buff, 0, 16); - PageMemIdx++; - } -} - -void ArduinoHexParse::EndOfFile(void) -{ - loadAddress[1] += 0x40; - if (0 == loadAddress[1]) { - loadAddress[0] += 1; - } - while (128 > PageMemIdx) { // Fill the remaing space in the memory page with 0xFF - FlashPage[PageMemIdx] = 0xFF; - PageMemIdx++; - } -} - -uint32_t ArduinoHexParse::GetAddress(byte* hexline) -{ - char buff[5]; - buff[0] = hexline[3]; - buff[1] = hexline[4]; - buff[2] = hexline[5]; - buff[3] = hexline[6]; - buff[4] = '\0'; - return strtol(buff, 0, 16); -} - -uint16_t ArduinoHexParse::GetLength(byte* hexline) -{ - char buff[3]; - buff[0] = hexline[1]; - buff[1] = hexline[2]; - buff[2] = '\0'; - return strtol(buff, 0, 16); -} - -uint16_t ArduinoHexParse::GetRecordType(byte* hexline) -{ - char buff[3]; - buff[0] = hexline[7]; - buff[1] = hexline[8]; - buff[2] = '\0'; - return strtol(buff, 0, 16); -} diff --git a/lib/ArduinoHexParse/src/ArduinoHexParse.h b/lib/ArduinoHexParse/src/ArduinoHexParse.h deleted file mode 100644 index 7b941eea1..000000000 --- a/lib/ArduinoHexParse/src/ArduinoHexParse.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2019 Andre Thomas 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 . -*/ - -#ifndef __ARDUINOHEXPARSE_H__ - -#include - -class ArduinoHexParse { - public: - ArduinoHexParse(void); - void ParseLine(byte* data); - byte* GetFlashPage(void); - byte* GetLoadAddress(void); - bool IsFlashPageReady(void); - private: - uint32_t address = 0; - uint32_t len = 0; - uint32_t nextAddress = 0; - uint32_t PageMemIdx = 0; - uint32_t recordType = 0; - byte FlashPage[128]; - byte loadAddress[2]; - bool FlashPageReady = false; - bool firstRun = true; - uint32_t GetAddress(byte* hexline); - uint16_t GetLength(byte* hexline); - uint16_t GetRecordType(byte* hexline); - byte* GetData(byte* hexline, uint32_t len); - void GetLoadAddress(byte* hexline); - void EndOfFile(void); -}; - -#endif // __ARDUINOHEXPARSE_H__ \ No newline at end of file From 6066eb0bfc90dd046eb4528c9c1f28fe009bc277 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 26 Oct 2019 22:55:18 +0200 Subject: [PATCH 031/196] Update my_user_config.h --- sonoff/my_user_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index cb067fbf7..9073d0699 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -534,9 +534,9 @@ //#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) //#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code) -//#define USE_ARDUINO_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) - #define USE_ARDUINO_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants - #define USE_ARDUINO_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini +//#define USE_TASMOTA_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) + #define USE_TASMOTA_SLAVE_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants + #define USE_TASMOTA_SLAVE_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini // -- End of general directives ------------------- From 8c5934890e8019372ff1406fac270bec97f85bbf Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 26 Oct 2019 22:58:04 +0200 Subject: [PATCH 032/196] ArduinoSlave->TasmotaSlave --- sonoff/sonoff_template.h | 18 +- sonoff/xdrv_01_webserver.ino | 30 +-- sonoff/xdrv_31_arduino_slave.ino | 412 ++++++++++++++++++++++--------- 3 files changed, 324 insertions(+), 136 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index f85543cd0..51cd2d0fd 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -208,10 +208,9 @@ enum UserSelectablePins { GPIO_SM2135_DAT, // SM2135 Dat GPIO_DEEPSLEEP, // Kill switch for deepsleep GPIO_EXS_ENABLE, // EXS MCU Enable - GPIO_ARDUINO_TXD, // Arduino Slave TX - GPIO_ARDUINO_RXD, // Arduino Slave RX - GPIO_ARDUINO_RST, // Arduino Reset Pin - GPIO_ARDUINO_RST_INV, // Arduino Reset Pin inverted + GPIO_TASMOTASLAVE_TXD, // Arduino Slave TX + GPIO_TASMOTASLAVE_RXD, // Arduino Slave RX + GPIO_TASMOTASLAVE_RST, // Arduino Reset Pin GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -290,7 +289,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|" D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" - D_SENSOR_ARDUINO_TX "|" D_SENSOR_ARDUINO_RX "|" D_SENSOR_ARDUINO_RESET "|" D_SENSOR_ARDUINO_RESET "i|" + D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -703,11 +702,10 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_PN532_TXD, // PN532 HSU Tx GPIO_PN532_RXD, // PN532 HSU Rx #endif -#ifdef USE_ARDUINO_SLAVE - GPIO_ARDUINO_TXD, // Arduino Slave TX - GPIO_ARDUINO_RXD, // Arduino Slave RX - GPIO_ARDUINO_RST, // Arduino Reset Pin - GPIO_ARDUINO_RST_INV, // Arduino Reset Pin inverted +#ifdef USE_TASMOTA_SLAVE + GPIO_TASMOTASLAVE_TXD, // Tasmota Slave TX + GPIO_TASMOTASLAVE_RXD, // Tasmota Slave RX + GPIO_TASMOTASLAVE_RST, // Tasmota Reset Pin #endif #ifdef USE_RDM6300 GPIO_RDM6300_RX, diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 40b3bab83..17622e920 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -44,7 +44,7 @@ const uint16_t HTTP_REFRESH_TIME = 2345; // milliseconds uint8_t *efm8bb1_update = nullptr; #endif // USE_RF_FLASH -enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_ARDUINOSLAVE }; +enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTASLAVE }; static const char * HEADER_KEYS[] = { "User-Agent", }; @@ -2037,8 +2037,8 @@ void HandleUploadDone(void) WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS)); WSContentSend_P(HTTP_MSG_RSTRT); ShowWebSource(SRC_WEBGUI); -#ifdef USE_ARDUINO_SLAVE - if (ArduinoSlave_GetFlagFlashing()) { +#ifdef USE_TASMOTA_SLAVE + if (TasmotaSlave_GetFlagFlashing()) { restart_flag = 0; } else { // It was a normal firmware file, or we are ready to restart device restart_flag = 2; @@ -2051,9 +2051,9 @@ void HandleUploadDone(void) WSContentSend_P(PSTR("
")); WSContentSpaceButton(BUTTON_MAIN); WSContentStop(); -#ifdef USE_ARDUINO_SLAVE - if (ArduinoSlave_GetFlagFlashing()) { - ArduinoSlave_Flash(); +#ifdef USE_TASMOTA_SLAVE + if (TasmotaSlave_GetFlagFlashing()) { + TasmotaSlave_Flash(); } #endif } @@ -2121,11 +2121,11 @@ void HandleUploadLoop(void) if (Web.upload_error != 0) { return; } } else #endif // USE_RF_FLASH -#ifdef USE_ARDUINO_SLAVE +#ifdef USE_TASMOTA_SLAVE if ((WEMOS == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a ARDUINO SLAVE hex file Update.end(); // End esp8266 update session - Web.upload_file_type = UPL_ARDUINOSLAVE; - Web.upload_error = ArduinoSlave_UpdateInit(); + Web.upload_file_type = UPL_TASMOTASLAVE; + Web.upload_error = TasmotaSlave_UpdateInit(); if (Web.upload_error != 0) { return; } } else #endif @@ -2187,9 +2187,9 @@ void HandleUploadLoop(void) } } #endif // USE_RF_FLASH -#ifdef USE_ARDUINO_SLAVE - else if (UPL_ARDUINOSLAVE == Web.upload_file_type) { - ArduinoSlave_WriteBuffer(upload.buf, upload.currentSize); +#ifdef USE_TASMOTA_SLAVE + else if (UPL_TASMOTASLAVE == Web.upload_file_type) { + TasmotaSlave_WriteBuffer(upload.buf, upload.currentSize); } #endif else { // firmware @@ -2243,10 +2243,10 @@ void HandleUploadLoop(void) Web.upload_file_type = UPL_TASMOTA; } #endif // USE_RF_FLASH -#ifdef USE_ARDUINO_SLAVE - else if (UPL_ARDUINOSLAVE == Web.upload_file_type) { +#ifdef USE_TASMOTA_SLAVE + else if (UPL_TASMOTASLAVE == Web.upload_file_type) { // Done writing the hex to SPI flash - ArduinoSlave_SetFlagFlashing(true); // So we know on upload success page if it needs to flash hex or do a normal restart + TasmotaSlave_SetFlagFlashing(true); // So we know on upload success page if it needs to flash hex or do a normal restart Web.upload_file_type = UPL_TASMOTA; } #endif diff --git a/sonoff/xdrv_31_arduino_slave.ino b/sonoff/xdrv_31_arduino_slave.ino index 497ab28dd..dff94182b 100644 --- a/sonoff/xdrv_31_arduino_slave.ino +++ b/sonoff/xdrv_31_arduino_slave.ino @@ -1,5 +1,5 @@ /* - xdrv_31_arduino_slave.ino - Support for Arduino Slave on Serial + xdrv_31_tasmota_slave.ino - Support for external microcontroller slave on serial Copyright (C) 2019 Andre Thomas and Theo Arends @@ -17,9 +17,9 @@ along with this program. If not, see . */ -#ifdef USE_ARDUINO_SLAVE +#ifdef USE_TASMOTA_SLAVE /*********************************************************************************************\ - * Arduino slave + * Tasmota slave \*********************************************************************************************/ #define XDRV_31 31 @@ -34,50 +34,182 @@ #define CMND_STK_LOAD_ADDRESS 0x55 #define CMND_STK_PROG_PAGE 0x64 -#include -#include +/*************************************************\ + * Tasmota Slave Specific Commands +\*************************************************/ -struct ASLAVE { +#define CMND_START 0xFC +#define CMND_END 0xFD + +#define CMND_FEATURES 0x01 +#define CMND_JSON 0x02 + +#define PARAM_DATA_START 0xFE +#define PARAM_DATA_END 0xFF + + +#include + +/* + * Embedding class in here since its rather specific to Arduino bootloader + */ + +class SimpleHexParse { + public: + SimpleHexParse(void); + uint8_t parseLine(char *hexline); + uint8_t ptr_l = 0; + uint8_t ptr_h = 0; + bool PageIsReady = false; + bool firstrun = true; + bool EndOfFile = false; + uint8_t FlashPage[128]; + uint8_t FlashPageIdx = 0; + uint8_t layoverBuffer[16]; + uint8_t layoverIdx = 0; + uint8_t getByte(char *hexline, uint8_t idx); +}; + +SimpleHexParse::SimpleHexParse(void) +{ + +} + +uint8_t SimpleHexParse::parseLine(char *hexline) +{ + if (layoverIdx) { + memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx); + FlashPageIdx = layoverIdx; + layoverIdx = 0; + } + uint8_t len = getByte(hexline, 1); + uint8_t addr_h = getByte(hexline, 2); + uint8_t addr_l = getByte(hexline, 3); + uint8_t rectype = getByte(hexline, 4); + for (uint8_t idx = 0; idx < len; idx++) { + if (FlashPageIdx < 128) { + FlashPage[FlashPageIdx] = getByte(hexline, idx+5); + FlashPageIdx++; + } else { // We have layover bytes + layoverBuffer[layoverIdx] = getByte(hexline, idx+5); + layoverIdx++; + } + } + if (1 == rectype) { + EndOfFile = true; + while (FlashPageIdx < 128) { + FlashPage[FlashPageIdx] = 0xFF; + FlashPageIdx++; + } + } + if (FlashPageIdx == 128) { + if (firstrun) { + firstrun = false; + } else { + ptr_l += 0x40; + if (ptr_l == 0) { + ptr_l = 0; + ptr_h++; + } + } + firstrun = false; + PageIsReady = true; + } + return 0; +} + +uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx) +{ + char buff[3]; + buff[3] = '\0'; + memcpy(&buff, &hexline[(idx*2)-1], 2); + return strtol(buff, 0, 16); +} + +/* + * End of embedded class SimpleHexParse + */ + +struct TSLAVE { uint32_t spi_hex_size = 0; uint32_t spi_sector_counter = 0; uint8_t spi_sector_cursor = 0; - uint8_t inverted = LOW; bool type = false; bool flashing = false; -} ASlave; + bool SerialEnabled = false; + uint8_t waitstate = 0; // We use this so that features detection does not slow down other stuff on startup +} TSlave; -TasmotaSerial *ArduinoSlave_Serial; +typedef union { + uint16_t data; + struct { + uint16_t json : 1; + uint16_t spare1 : 1; + uint16_t spare2 : 1; + uint16_t spare3 : 1; + uint16_t spare4 : 1; + uint16_t spare5 : 1; + uint16_t spare6 : 1; + uint16_t spare7 : 1; + uint16_t spare8 : 1; + uint16_t spare9 : 1; + uint16_t spare10 : 1; + uint16_t spare11 : 1; + uint16_t spare12 : 1; + uint16_t spare13 : 1; + uint16_t spare14 : 1; + uint16_t spare15 : 1; + }; +} TSlaveFeatureCfg; -uint32_t ArduinoSlaveFlashStart(void) +/* + * The structure below must remain 4 byte aligned to be compatible with + * Tasmota as master + */ + +struct FEATURES { + uint32_t features_version; + TSlaveFeatureCfg features; + uint16_t spare4; +} TSlaveSettings; + +struct COMMAND { + uint8_t command; + uint8_t parameter; + uint8_t unused2; + uint8_t unused3; +} Command; + +TasmotaSerial *TasmotaSlave_Serial; + +uint32_t TasmotaSlave_FlashStart(void) { return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side } -uint8_t ArduinoSlave_UpdateInit(void) +uint8_t TasmotaSlave_UpdateInit(void) { - ASlave.spi_hex_size = 0; - ASlave.spi_sector_counter = ArduinoSlaveFlashStart(); // Reset the pre-defined write address where firmware will temporarily be stored - ASlave.spi_sector_cursor = 0; + TSlave.spi_hex_size = 0; + TSlave.spi_sector_counter = TasmotaSlave_FlashStart(); // Reset the pre-defined write address where firmware will temporarily be stored + TSlave.spi_sector_cursor = 0; return 0; } -void ArduinoSlave_Reset(void) +void TasmotaSlave_Reset(void) { - if (ASlave.type) { - digitalWrite(pin[GPIO_ARDUINO_RST], !ASlave.inverted); + if (TSlave.SerialEnabled) { + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], LOW); delay(1); - digitalWrite(pin[GPIO_ARDUINO_RST], ASlave.inverted); - delay(1); - digitalWrite(pin[GPIO_ARDUINO_RST], !ASlave.inverted); + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], HIGH); delay(5); } } -uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout) +uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout) { int timer = 0; while (timer < timeout) { - if (ArduinoSlave_Serial->available() >= dataCount) { + if (TasmotaSlave_Serial->available() >= dataCount) { return 1; } delay(1); @@ -86,25 +218,25 @@ uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout) return 0; } -uint8_t ArduinoSlave_sendBytes(uint8_t* bytes, int count) +uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count) { - ArduinoSlave_Serial->write(bytes, count); - ArduinoSlave_waitForSerialData(2, 1000); - uint8_t sync = ArduinoSlave_Serial->read(); - uint8_t ok = ArduinoSlave_Serial->read(); - if (sync == 0x14 && ok == 0x10) { + TasmotaSlave_Serial->write(bytes, count); + TasmotaSlave_waitForSerialData(2, 1000); + uint8_t sync = TasmotaSlave_Serial->read(); + uint8_t ok = TasmotaSlave_Serial->read(); + if ((sync == 0x14) && (ok == 0x10)) { return 1; } return 0; } -uint8_t ArduinoSlave_execCmd(uint8_t cmd) +uint8_t TasmotaSlave_execCmd(uint8_t cmd) { uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP }; - return ArduinoSlave_sendBytes(bytes, 2); + return TasmotaSlave_sendBytes(bytes, 2); } -uint8_t ArduinoSlave_execParam(uint8_t cmd, uint8_t* params, int count) +uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count) { uint8_t bytes[32]; bytes[0] = cmd; @@ -114,50 +246,87 @@ uint8_t ArduinoSlave_execParam(uint8_t cmd, uint8_t* params, int count) i++; } bytes[i + 1] = CONST_STK_CRC_EOP; - return ArduinoSlave_sendBytes(bytes, i + 2); + return TasmotaSlave_sendBytes(bytes, i + 2); } -uint8_t ArduinoSlave_exitProgMode(void) +uint8_t TasmotaSlave_exitProgMode(void) { - return ArduinoSlave_execCmd(CMND_STK_LEAVE_PROGMODE); // Exit programming mode + return TasmotaSlave_execCmd(CMND_STK_LEAVE_PROGMODE); // Exit programming mode } -void ArduinoSlave_SetupFlash(void) +void TasmotaSlave_SetupFlash(void) { - uint8_t ProgParams[] = {0x86,0x00,0x00,0x01,0x01,0x01,0x01,0x03,0xff,0xff,0xff,0xff,0x00,0x80,0x04,0x00,0x00,0x00,0x80,0x00}; - uint8_t ExtProgParams[] = {0x05,0x04,0xd7,0xc2,0x00}; - ArduinoSlave_Serial->begin(USE_ARDUINO_FLASH_SPEED); - if (ArduinoSlave_Serial->hardwareSerial()) { + uint8_t ProgParams[] = {0x86, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; + uint8_t ExtProgParams[] = {0x05, 0x04, 0xd7, 0xc2, 0x00}; + TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_FLASH_SPEED); + if (TasmotaSlave_Serial->hardwareSerial()) { ClaimSerial(); } - ArduinoSlave_Reset(); - ArduinoSlave_execCmd(CMND_STK_GET_SYNC); - ArduinoSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams)); // Set programming parameters - ArduinoSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams)); // Set extended programming parameters - ArduinoSlave_execCmd(CMND_STK_ENTER_PROGMODE); // Enter programming mode + TasmotaSlave_Reset(); + + uint8_t timer = 0; + bool no_error = false; + while (200 > timer) { + if (TasmotaSlave_execCmd(CMND_STK_GET_SYNC)) { + timer = 200; + no_error = true; + } + delay(1); + } + + if (no_error) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Found bootloader")); + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Bootloader could not be found")); + } + + if (no_error) { + if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) { + } else { + no_error = true; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (1)")); + } + } + + if (no_error) { + if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) { + } else { + no_error = true; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (2)")); + } + } + + if (no_error) { + if (TasmotaSlave_execCmd(CMND_STK_ENTER_PROGMODE)) { + } else { + no_error = true; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Failed to put bootloader into programming mode")); + } + } + } -uint8_t ArduinoSlave_loadAddress(uint8_t adrHi, uint8_t adrLo) +uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo) { - uint8_t params[] = { adrHi, adrLo }; - return ArduinoSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); + uint8_t params[] = { adrLo, adrHi }; + return TasmotaSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); } -void ArduinoSlave_FlashPage(uint8_t* address, uint8_t* data) +void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) { uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; - ArduinoSlave_loadAddress(address[1], address[0]); - ArduinoSlave_Serial->write(Header, 4); + TasmotaSlave_loadAddress(addr_h, addr_l); + TasmotaSlave_Serial->write(Header, 4); for (int i = 0; i < 128; i++) { - ArduinoSlave_Serial->write(data[i]); + TasmotaSlave_Serial->write(data[i]); } - ArduinoSlave_Serial->write(CONST_STK_CRC_EOP); - ArduinoSlave_waitForSerialData(2, 1000); - ArduinoSlave_Serial->read(); - ArduinoSlave_Serial->read(); + TasmotaSlave_Serial->write(CONST_STK_CRC_EOP); + TasmotaSlave_waitForSerialData(2, 1000); + TasmotaSlave_Serial->read(); + TasmotaSlave_Serial->read(); } -void ArduinoSlave_Flash(void) +void TasmotaSlave_Flash(void) { bool reading = true; uint32_t read = 0; @@ -165,31 +334,31 @@ void ArduinoSlave_Flash(void) char thishexline[50]; uint8_t position = 0; char* flash_buffer; - ArduinoHexParse hexParse = ArduinoHexParse(); + SimpleHexParse hexParse = SimpleHexParse(); - ArduinoSlave_SetupFlash(); + TasmotaSlave_SetupFlash(); flash_buffer = new char[SPI_FLASH_SEC_SIZE]; - uint32_t flash_start = ArduinoSlaveFlashStart() * SPI_FLASH_SEC_SIZE; + uint32_t flash_start = TasmotaSlave_FlashStart() * SPI_FLASH_SEC_SIZE; while (reading) { ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE); read = read + SPI_FLASH_SEC_SIZE; - if (read >= ASlave.spi_hex_size) { + if (read >= TSlave.spi_hex_size) { reading = false; } for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) { processed++; - if (processed <= ASlave.spi_hex_size) { + if ((processed <= TSlave.spi_hex_size) && (!hexParse.EndOfFile)) { if (':' == flash_buffer[ca]) { position = 0; } if (0x0D == flash_buffer[ca]) { thishexline[position] = 0; - hexParse.ParseLine((uint8_t*)thishexline); - if (hexParse.IsFlashPageReady()) { - uint8_t* page = hexParse.GetFlashPage(); - uint8_t* address = hexParse.GetLoadAddress(); - ArduinoSlave_FlashPage(address, page); + hexParse.parseLine(thishexline); + if (hexParse.PageIsReady) { + TasmotaSlave_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage); + hexParse.PageIsReady = false; + hexParse.FlashPageIdx = 0; } } else { if (0x0A != flash_buffer[ca]) { @@ -200,72 +369,93 @@ void ArduinoSlave_Flash(void) } } } - ASlave.flashing = false; - ArduinoSlave_exitProgMode(); + TasmotaSlave_exitProgMode(); + TSlave.flashing = false; restart_flag = 2; } -void ArduinoSlave_SetFlagFlashing(bool value) +void TasmotaSlave_SetFlagFlashing(bool value) { - ASlave.flashing = value; + TSlave.flashing = value; } -bool ArduinoSlave_GetFlagFlashing(void) +bool TasmotaSlave_GetFlagFlashing(void) { - return ASlave.flashing ; + return TSlave.flashing; } -void ArduinoSlave_WriteBuffer(uint8_t *buf, size_t size) +void TasmotaSlave_WriteBuffer(uint8_t *buf, size_t size) { - if (0 == ASlave.spi_sector_cursor) { // Starting a new sector write so we need to erase it first - ESP.flashEraseSector(ASlave.spi_sector_counter); + if (0 == TSlave.spi_sector_cursor) { // Starting a new sector write so we need to erase it first + ESP.flashEraseSector(TSlave.spi_sector_counter); } - ASlave.spi_sector_cursor++; - ESP.flashWrite((ASlave.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((ASlave.spi_sector_cursor-1)*2048), (uint32_t*)buf, size); - ASlave.spi_hex_size = ASlave.spi_hex_size + size; - if (2 == ASlave.spi_sector_cursor) { // The web upload sends 2048 bytes at a time so keep track of the cursor position to reset it for the next flash sector erase - ASlave.spi_sector_cursor = 0; - ASlave.spi_sector_counter++; + TSlave.spi_sector_cursor++; + ESP.flashWrite((TSlave.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((TSlave.spi_sector_cursor-1)*2048), (uint32_t*)buf, size); + TSlave.spi_hex_size = TSlave.spi_hex_size + size; + if (2 == TSlave.spi_sector_cursor) { // The web upload sends 2048 bytes at a time so keep track of the cursor position to reset it for the next flash sector erase + TSlave.spi_sector_cursor = 0; + TSlave.spi_sector_counter++; } } -void ArduinoSlave_Init(void) +void TasmotaSlave_Init(void) { - if (ASlave.type) { + if (TSlave.type) { return; } - if ((pin[GPIO_ARDUINO_RXD] < 99) && (pin[GPIO_ARDUINO_TXD] < 99) && - ((pin[GPIO_ARDUINO_RST] < 99) || (pin[GPIO_ARDUINO_RST_INV] < 99))) { - ArduinoSlave_Serial = new TasmotaSerial(pin[GPIO_ARDUINO_RXD], pin[GPIO_ARDUINO_TXD], 1, 0, 200); - if (ArduinoSlave_Serial->begin(USE_ARDUINO_SERIAL_SPEED)) { - if (ArduinoSlave_Serial->hardwareSerial()) { - ClaimSerial(); + if (10 > TSlave.waitstate) { + TSlave.waitstate++; + return; + } + if (!TSlave.SerialEnabled) { + if ((pin[GPIO_TASMOTASLAVE_RXD] < 99) && (pin[GPIO_TASMOTASLAVE_TXD] < 99) && (pin[GPIO_TASMOTASLAVE_RST] < 99)) { + TasmotaSlave_Serial = new TasmotaSerial(pin[GPIO_TASMOTASLAVE_RXD], pin[GPIO_TASMOTASLAVE_TXD], 1, 0, 200); + if (TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_SERIAL_SPEED)) { + if (TasmotaSlave_Serial->hardwareSerial()) { + ClaimSerial(); + } + pinMode(pin[GPIO_TASMOTASLAVE_RST], OUTPUT); + TasmotaSlave_Reset(); + TSlave.SerialEnabled = true; + AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Enabled")); } - if (pin[GPIO_ARDUINO_RST_INV] < 99) { - pin[GPIO_ARDUINO_RST] = pin[GPIO_ARDUINO_RST_INV]; - pin[GPIO_ARDUINO_RST_INV] = 99; - ASlave.inverted = HIGH; - } - pinMode(pin[GPIO_ARDUINO_RST], OUTPUT); - ASlave.type = true; - ArduinoSlave_Reset(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("Arduino Slave Enabled")); + } + } + if (TSlave.SerialEnabled) { // All go for hardware now we need to detect features if there are any + TasmotaSlave_sendCmnd(CMND_FEATURES, 0); + char buffer[32]; + TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)); + uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)); + memcpy(&TSlaveSettings, &buffer, sizeof(TSlaveSettings)); + if (20191026 <= TSlaveSettings.features_version) { + TSlave.type = true; + AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u"), TSlaveSettings.features_version); } } } -void ArduinoSlave_Show(bool json) +void TasmotaSlave_Show(void) { - if (ASlave.type) { - ArduinoSlave_Serial->flush(); - ArduinoSlave_Serial->print("JSON"); - ArduinoSlave_Serial->find(char(0xFE)); + if ((TSlave.type) && (TSlaveSettings.features.json)) { char buffer[100]; - uint16_t haveread = ArduinoSlave_Serial->readBytesUntil(char(0xFF), buffer, sizeof(buffer)-1); - buffer[haveread] = '\0'; - if (json) { - ResponseAppend_P(PSTR(",\"ArduinoSlave\":%s"), buffer); - } + TasmotaSlave_sendCmnd(CMND_JSON, 0); + TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1); + uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1); + buffer[len] = '\0'; + ResponseAppend_P(PSTR(",\"TasmotaSlave\":%s"), buffer); + } +} + +void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param) +{ + Command.command = cmnd; + Command.parameter = param; + char buffer[sizeof(Command)+2]; + buffer[0] = CMND_START; + memcpy(&buffer[1], &Command, sizeof(Command)); + buffer[sizeof(Command)+1] = CMND_END; + for (uint8_t ca = 0; ca < sizeof(buffer); ca++) { + TasmotaSlave_Serial->write(buffer[ca]); } } @@ -279,13 +469,13 @@ bool Xdrv31(uint8_t function) switch (function) { case FUNC_EVERY_SECOND: - ArduinoSlave_Init(); + TasmotaSlave_Init(); break; case FUNC_JSON_APPEND: - ArduinoSlave_Show(1); + TasmotaSlave_Show(); break; } return result; } -#endif // USE_ARDUINO_SLAVE \ No newline at end of file +#endif // USE_TASMOTA_SLAVE \ No newline at end of file From 71b5caa7c117c76b86124fe56a0d3779d539e269 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 26 Oct 2019 22:58:48 +0200 Subject: [PATCH 033/196] Update language files --- sonoff/language/bg-BG.h | 6 +++--- sonoff/language/cs-CZ.h | 6 +++--- sonoff/language/de-DE.h | 6 +++--- sonoff/language/el-GR.h | 6 +++--- sonoff/language/en-GB.h | 6 +++--- sonoff/language/es-ES.h | 6 +++--- sonoff/language/fr-FR.h | 6 +++--- sonoff/language/he-HE.h | 6 +++--- sonoff/language/hu-HU.h | 6 +++--- sonoff/language/it-IT.h | 6 +++--- sonoff/language/ko-KO.h | 6 +++--- sonoff/language/nl-NL.h | 6 +++--- sonoff/language/pl-PL.h | 6 +++--- sonoff/language/pt-BR.h | 6 +++--- sonoff/language/pt-PT.h | 6 +++--- sonoff/language/ru-RU.h | 6 +++--- sonoff/language/sk-SK.h | 6 +++--- sonoff/language/sv-SE.h | 6 +++--- sonoff/language/tr-TR.h | 6 +++--- sonoff/language/uk-UK.h | 6 +++--- sonoff/language/zh-CN.h | 6 +++--- sonoff/language/zh-TW.h | 6 +++--- 22 files changed, 66 insertions(+), 66 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index d765614f6..aacf93d87 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index fd654c148..30a59a144 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index acff5f96b..e0a9b5d5e 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 680633d6a..cf558c58f 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 74a2fdca0..93540788d 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index 2530fd6e4..56496dc5f 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 1522ec15f..c98ef6740 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 3e5fe4031..2fcfa7215 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index f55f8ed38..80df2a8bc 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 912e95ec1..113ab15ce 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 35ae260b6..3ccbee135 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 0e81cebff..14e4635c1 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index bd03d60e3..3c28ec248 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 5d7b02613..a2e89cb5d 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index f060ec5d3..6a27ce711 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 13b721092..d5ce8af77 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index d35fff407..99e1790bd 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 701ed43ac..9fb0b0b20 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 295664ae0..f7989f244 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 67999ef11..9c07a8da1 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 36f71ea4c..db3d9e979 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 53bd3e1a7..482134c6e 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_ARDUINO_TX "Arduino TX" -#define D_SENSOR_ARDUINO_RX "Arduino RX" -#define D_SENSOR_ARDUINO_RESET "Arduino RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "安" From 2f90708e90a1b0ec63ee90aa3aebf9c54c570853 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 26 Oct 2019 23:07:09 +0200 Subject: [PATCH 034/196] Rename slave driver file --- sonoff/{xdrv_31_arduino_slave.ino => xdrv_31_tasmota_slave.ino} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename sonoff/{xdrv_31_arduino_slave.ino => xdrv_31_tasmota_slave.ino} (100%) diff --git a/sonoff/xdrv_31_arduino_slave.ino b/sonoff/xdrv_31_tasmota_slave.ino similarity index 100% rename from sonoff/xdrv_31_arduino_slave.ino rename to sonoff/xdrv_31_tasmota_slave.ino From 85facc96dfe23f1d9885c0e4e264384f120aea9a Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 26 Oct 2019 23:11:35 +0200 Subject: [PATCH 035/196] Update my_user_config.h resource usage --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 9073d0699..e73613466 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -534,7 +534,7 @@ //#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) //#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code) -//#define USE_TASMOTA_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) +//#define USE_TASMOTA_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k6 code, 64 mem) #define USE_TASMOTA_SLAVE_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants #define USE_TASMOTA_SLAVE_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini From 8571af489587a2d6358f97973c85cedc36672200 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sat, 26 Oct 2019 23:13:40 +0200 Subject: [PATCH 036/196] ArduinoSlave->TasmotaSlave --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 1cb954c7b..332276b28 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Release * Fix on energy monitoring devices using PowerDelta Exception0 with epc1:0x4000dce5 = Divide by zero (#6750) * Fix Script array bug (#6751) + * Move ArduinoSlave to TasmotaSlave (Experimental) * * 6.7.0 20191025 * Release From 30b821beed80866d87721d5f7dd26fd3cad731f4 Mon Sep 17 00:00:00 2001 From: blakadder Date: Sun, 27 Oct 2019 00:23:13 +0200 Subject: [PATCH 037/196] tuyasen --- sonoff/i18n.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 234e2ee59..9b3e7acec 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -453,7 +453,7 @@ #define D_CMND_TUYA_MCU "TuyaMCU" #define D_CMND_TUYA_MCU_SEND_STATE "TuyaSend" -#define D_JSON_TUYA_MCU_RECEIVED "TuyaMcuReceived" +#define D_JSON_TUYA_MCU_RECEIVED "TuyaReceived" // Commands xdrv_23_zigbee.ino #define D_CMND_ZIGBEE_PERMITJOIN "ZigbeePermitJoin" From 837808b03ab1482a2cc9fe6e788aa5aa33dd9125 Mon Sep 17 00:00:00 2001 From: blakadder Date: Sun, 27 Oct 2019 00:31:33 +0200 Subject: [PATCH 038/196] tuya_mcu_received --- sonoff/xdrv_16_tuyamcu.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index f0aeccdbd..e80adef59 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -681,7 +681,7 @@ void TuyaSerialInput(void) ResponseAppend_P(PSTR("}}")); if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_TUYA_MCU_RECEIVED)); } else { AddLog_P(LOG_LEVEL_DEBUG, mqtt_data); } From 8b1362b6dfb6a10cbcdd373b50a29759316a948b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Oct 2019 10:48:50 +0100 Subject: [PATCH 039/196] Bump version 6.7.1.1 * Change ArduinoSlave to TasmotaSlave (Experimental) * Add support for Tuya battery powered devices (#6735) * Change repository name from Sonoff-Tasmota to Tasmota --- sonoff/_changelog.ino | 6 +++++- sonoff/sonoff_version.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 332276b28..02591fac0 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,9 +1,13 @@ /*********************************************************************************************\ + * 6.7.1.1 20191026 + * Change ArduinoSlave to TasmotaSlave (Experimental) + * Add support for Tuya battery powered devices (#6735) + * Change repository name from Sonoff-Tasmota to Tasmota + * * 6.7.1 20191026 * Release * Fix on energy monitoring devices using PowerDelta Exception0 with epc1:0x4000dce5 = Divide by zero (#6750) * Fix Script array bug (#6751) - * Move ArduinoSlave to TasmotaSlave (Experimental) * * 6.7.0 20191025 * Release diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 4780ef5e3..6fc555fd6 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06070100; +const uint32_t VERSION = 0x06070101; #endif // _SONOFF_VERSION_H_ From ffb8496c3a253df769a9356134dcbd33551cfe2c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Oct 2019 11:13:24 +0100 Subject: [PATCH 040/196] Change reference Sonoff-Tasmota to Tasmota --- sonoff/i18n.h | 2 +- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-ES.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/ko-KO.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- sonoff/my_user_config.h | 4 +- sonoff/settings.h | 2 +- sonoff/settings.ino | 2 +- sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 4 +- sonoff/sonoff_ca.ino | 2 +- sonoff/sonoff_post.h | 4 +- sonoff/sonoff_template.h | 2 +- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 2 +- sonoff/support_button.ino | 2 +- sonoff/support_command.ino | 2 +- sonoff/support_features.ino | 2 +- sonoff/support_float.ino | 2 +- sonoff/support_rotary.ino | 2 +- sonoff/support_rtc.ino | 2 +- sonoff/support_static_buffer.ino | 2 +- sonoff/support_switch.ino | 2 +- sonoff/support_udp.ino | 2 +- sonoff/support_wifi.ino | 4 +- sonoff/user_config_override_sample.h | 2 +- sonoff/xdrv_01_webserver.ino | 4 +- sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_03_energy.ino | 2 +- sonoff/xdrv_04_light.ino | 2 +- sonoff/xdrv_05_irremote.ino | 2 +- sonoff/xdrv_05_irremote_full.ino | 2 +- sonoff/xdrv_06_snfbridge.ino | 4 +- sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_08_serial_bridge.ino | 2 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_10_rules.ino | 2 +- sonoff/xdrv_10_scripter.ino | 2 +- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xdrv_12_home_assistant.ino | 8 +-- sonoff/xdrv_13_display.ino | 2 +- sonoff/xdrv_14_mp3.ino | 4 +- sonoff/xdrv_15_pca9685.ino | 2 +- sonoff/xdrv_16_tuyamcu.ino | 2 +- sonoff/xdrv_17_rcswitch.ino | 2 +- sonoff/xdrv_18_armtronix_dimmers.ino | 2 +- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- sonoff/xdrv_20_hue.ino | 2 +- sonoff/xdrv_21_wemo.ino | 2 +- sonoff/xdrv_22_sonoff_ifan.ino | 2 +- sonoff/xdrv_23_zigbee_0_constants.ino | 2 +- sonoff/xdrv_23_zigbee_3_devices.ino | 4 +- sonoff/xdrv_23_zigbee_5_converters.ino | 46 +++++++------- sonoff/xdrv_23_zigbee_6_commands.ino | 2 +- sonoff/xdrv_23_zigbee_7_statemachine.ino | 2 +- sonoff/xdrv_23_zigbee_8_parsers.ino | 6 +- sonoff/xdrv_23_zigbee_9_impl.ino | 2 +- sonoff/xdrv_24_buzzer.ino | 2 +- sonoff/xdrv_25_A4988_Stepper.ino | 2 +- sonoff/xdrv_26_ariluxrf.ino | 2 +- sonoff/xdrv_27_shutter.ino | 2 +- sonoff/xdrv_28_pcf8574.ino | 2 +- sonoff/xdrv_29_deepsleep.ino | 2 +- sonoff/xdrv_30_exs_dimmer.ino | 2 +- sonoff/xdrv_99_debug.ino | 2 +- sonoff/xdrv_interface.ino | 2 +- sonoff/xdsp_01_lcd.ino | 2 +- sonoff/xdsp_02_ssd1306.ino | 2 +- sonoff/xdsp_03_matrix.ino | 2 +- sonoff/xdsp_04_ili9341.ino | 2 +- sonoff/xdsp_05_epaper_29.ino | 2 +- sonoff/xdsp_06_epaper_42.ino | 2 +- sonoff/xdsp_07_sh1106.ino | 2 +- sonoff/xdsp_08_ILI9488.ino | 2 +- sonoff/xdsp_09_SSD1351.ino | 2 +- sonoff/xdsp_10_RA8876.ino | 2 +- sonoff/xdsp_interface.ino | 2 +- sonoff/xlgt_01_ws2812.ino | 2 +- sonoff/xlgt_02_my92x1.ino | 2 +- sonoff/xlgt_03_sm16716.ino | 2 +- sonoff/xlgt_04_sm2135.ino | 2 +- sonoff/xlgt_05_sonoff_l1.ino | 2 +- sonoff/xlgt_interface.ino | 2 +- sonoff/xnrg_01_hlw8012.ino | 2 +- sonoff/xnrg_02_cse7766.ino | 2 +- sonoff/xnrg_03_pzem004t.ino | 2 +- sonoff/xnrg_04_mcp39f501.ino | 2 +- sonoff/xnrg_05_pzem_ac.ino | 2 +- sonoff/xnrg_06_pzem_dc.ino | 2 +- sonoff/xnrg_07_ade7953.ino | 2 +- sonoff/xnrg_08_sdm120.ino | 2 +- sonoff/xnrg_09_dds2382.ino | 2 +- sonoff/xnrg_10_sdm630.ino | 2 +- sonoff/xnrg_11_ddsu666.ino | 4 +- sonoff/xnrg_12_solaxX1.ino | 2 +- sonoff/xnrg_interface.ino | 2 +- sonoff/xsns_01_counter.ino | 2 +- sonoff/xsns_02_analog.ino | 2 +- sonoff/xsns_04_snfsc.ino | 2 +- sonoff/xsns_05_ds18x20.ino | 2 +- sonoff/xsns_06_dht.ino | 2 +- sonoff/xsns_07_sht1x.ino | 2 +- sonoff/xsns_08_htu21.ino | 2 +- sonoff/xsns_09_bmp.ino | 2 +- sonoff/xsns_10_bh1750.ino | 2 +- sonoff/xsns_11_veml6070.ino | 6 +- sonoff/xsns_12_ads1115.ino | 2 +- sonoff/xsns_12_ads1115_i2cdev.ino | 2 +- sonoff/xsns_13_ina219.ino | 8 +-- sonoff/xsns_14_sht3x.ino | 2 +- sonoff/xsns_15_mhz19.ino | 2 +- sonoff/xsns_16_tsl2561.ino | 2 +- sonoff/xsns_17_senseair.ino | 2 +- sonoff/xsns_18_pms5003.ino | 4 +- sonoff/xsns_19_mgs.ino | 2 +- sonoff/xsns_20_novasds.ino | 4 +- sonoff/xsns_21_sgp30.ino | 2 +- sonoff/xsns_22_sr04.ino | 2 +- sonoff/xsns_24_si1145.ino | 2 +- sonoff/xsns_27_apds9960.ino | 2 +- sonoff/xsns_28_tm1638.ino | 2 +- sonoff/xsns_29_mcp230xx.ino | 2 +- sonoff/xsns_30_mpr121.ino | 4 +- sonoff/xsns_31_ccs811.ino | 2 +- sonoff/xsns_32_mpu6050.ino | 2 +- sonoff/xsns_33_ds3231.ino | 2 +- sonoff/xsns_34_hx711.ino | 2 +- sonoff/xsns_35_tx20.ino | 2 +- sonoff/xsns_36_mgc3130.ino | 2 +- sonoff/xsns_37_rfsensor.ino | 2 +- sonoff/xsns_38_az7798.ino | 4 +- sonoff/xsns_39_max31855.ino | 2 +- sonoff/xsns_40_pn532.ino | 2 +- sonoff/xsns_41_max44009.ino | 2 +- sonoff/xsns_42_scd30.ino | 2 +- sonoff/xsns_44_sps30.ino | 2 +- sonoff/xsns_45_vl53l0x.ino | 2 +- sonoff/xsns_47_max31865.ino | 2 +- sonoff/xsns_48_chirp.ino | 78 ++++++++++++------------ sonoff/xsns_50_paj7620.ino | 34 +++++------ sonoff/xsns_51_rdm6300.ino | 2 +- sonoff/xsns_52_ibeacon.ino | 2 +- sonoff/xsns_53_sml.ino | 2 +- sonoff/xsns_54_ina226.ino | 2 +- sonoff/xsns_interface.ino | 2 +- 163 files changed, 262 insertions(+), 262 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 9b3e7acec..bf73cc65b 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -1,5 +1,5 @@ /* - i18n.h - internationalization for Sonoff-Tasmota + i18n.h - internationalization for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index aacf93d87..986a93bdf 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -1,5 +1,5 @@ /* - bg-BG.h - localization for Bulgaria - Bulgarian for Sonoff-Tasmota + bg-BG.h - localization for Bulgaria - Bulgarian for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 30a59a144..ae887e534 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -1,5 +1,5 @@ /* - cs-CZ.h - localization for Czech with diacritics - Czech for Sonoff-Tasmota + cs-CZ.h - localization for Czech with diacritics - Czech for Tasmota Copyright (C) 2019 Vladimír Synek diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index e0a9b5d5e..0f96a77db 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -1,5 +1,5 @@ /* - de-DE.h - localization for German - Germany for Sonoff-Tasmota + de-DE.h - localization for German - Germany for Tasmota Copyright (C) 2019 VinceMasuka diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index cf558c58f..91088cb0c 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -1,5 +1,5 @@ /* - el-GR.h - localization for Greek - Greece for Sonoff-Tasmota + el-GR.h - localization for Greek - Greece for Tasmota Copyright (C) 2019 Theo Arends, translated by Nick Galfas diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 93540788d..87761b35f 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -1,5 +1,5 @@ /* - en-GB.h - localization for English - United Kingdom for Sonoff-Tasmota + en-GB.h - localization for English - United Kingdom for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index 56496dc5f..acc45837e 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -1,5 +1,5 @@ /* - es-ES.h - localization for Spanish - Spain for Sonoff-Tasmota + es-ES.h - localization for Spanish - Spain for Tasmota Copyright (C) 2019 Adrian Scillato diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index c98ef6740..f9dd3655c 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -1,5 +1,5 @@ /* - fr-FR.h - localization for French - France for Sonoff-Tasmota + fr-FR.h - localization for French - France for Tasmota Copyright (C) 2019 Olivier Francais diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 2fcfa7215..d5cb61c8a 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -1,5 +1,5 @@ /* - he-HE.h - localization for Hebrew - Israel for Sonoff-Tasmota + he-HE.h - localization for Hebrew - Israel for Tasmota Copyright (C) 2019 Yuval Mejahez diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 80df2a8bc..4dc310c8d 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -1,5 +1,5 @@ /* - hu-HU.h - localization for Hungarian in Hungary for Sonoff-Tasmota + hu-HU.h - localization for Hungarian in Hungary for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 113ab15ce..dcc3d786e 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -1,5 +1,5 @@ /* - it-IT.h - localization for Italian - Italy for Sonoff-Tasmota + it-IT.h - localization for Italian - Italy for Tasmota Copyright (C) 2019 Gennaro Tortone - some mods by Antonio Fragola diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 3ccbee135..82832fdbb 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -1,5 +1,5 @@ /* - ko-KO.h - localization for Korean - Korean for Sonoff-Tasmota + ko-KO.h - localization for Korean - Korean for Tasmota Copyright (C) 2019 Theo Arends (translated by NyaamZ) diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 14e4635c1..37f620ea5 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -1,5 +1,5 @@ /* - nl-NL.h - localization for Dutch - Nederland for Sonoff-Tasmota + nl-NL.h - localization for Dutch - Nederland for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 3c28ec248..19856e47f 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -1,5 +1,5 @@ /* - pl-PL-d.h - localization for Polish with diacritics - Poland for Sonoff-Tasmota + pl-PL-d.h - localization for Polish with diacritics - Poland for Tasmota Copyright (C) 2019 Theo Arends (translated by roblad - Robert L., upgraded by R. Turala) diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index a2e89cb5d..30cab1498 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -1,5 +1,5 @@ /* - pt-BR.h - localization for Portuguese - Brazil for Sonoff-Tasmota + pt-BR.h - localization for Portuguese - Brazil for Tasmota Copyright (C) 2019 Fabiano Bovo diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 6a27ce711..46d0bc3a4 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -1,5 +1,5 @@ /* - pt-PT.h - localization for Portuguese - Portugal for Sonoff-Tasmota + pt-PT.h - localization for Portuguese - Portugal for Tasmota Copyright (C) 2019 Paulo Paiva diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index d5ce8af77..1598a1d58 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -1,5 +1,5 @@ /* - ru-RU.h - localization for Russian - Rissia for Sonoff-Tasmota + ru-RU.h - localization for Russian - Rissia for Tasmota Copyright (C) 2019 Theo Arends / roman-vn diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 99e1790bd..594afb5d6 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -1,5 +1,5 @@ /* - sk-SK.h - localization for Slovak with diacritics - Slovak for Sonoff-Tasmota + sk-SK.h - localization for Slovak with diacritics - Slovak for Tasmota Copyright (C) 2019 Vladimír Jendroľ diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 9fb0b0b20..8ae40d324 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -1,5 +1,5 @@ /* - sv-SE.h - localization for Swedish - Svenska for Sonoff-Tasmota + sv-SE.h - localization for Swedish - Svenska for Tasmota Copyright (C) 2019 Gunnar Norin diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index f7989f244..18699b21c 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -1,5 +1,5 @@ /* - tr-TR.h - localization for Turkish - Turkey for Sonoff-Tasmota + tr-TR.h - localization for Turkish - Turkey for Tasmota Copyright (C) 2019 Ali Sait Teke and Theo Arends diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 9c07a8da1..d3124c4ab 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -1,5 +1,5 @@ /* - uk-UK.h - localization for Ukrainian - Ukraine for Sonoff-Tasmota + uk-UK.h - localization for Ukrainian - Ukraine for Tasmota Copyright (C) 2019 Theo Arends / vadym-adik diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index db3d9e979..4b443d490 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -1,5 +1,5 @@ /* - zh-CN.h - localization for Chinese (Simplified) - China for Sonoff-Tasmota + zh-CN.h - localization for Chinese (Simplified) - China for Tasmota Copyright (C) 2019 Theo Arends (translated by killadm) diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 482134c6e..179cc0177 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -1,5 +1,5 @@ /* - zh-TW.h - localization for Chinese (Traditional) - Taiwan for Sonoff-Tasmota + zh-TW.h - localization for Chinese (Traditional) - Taiwan for Tasmota Copyright (C) 2019 Theo Arends (translated by dannydu) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e73613466..48be22390 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -1,5 +1,5 @@ /* - my_user_config.h - user specific configuration for Sonoff-Tasmota + my_user_config.h - user specific configuration for Tasmota Copyright (C) 2019 Theo Arends @@ -264,7 +264,7 @@ // #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem) // #define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+11.9k code, +0.4k mem) // Note: you need to generate a private key + certificate per device and update 'sonoff/sonoff_aws_iot.cpp' - // Full documentation here: https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT + // Full documentation here: https://github.com/arendst/Tasmota/wiki/AWS-IoT // -- KNX IP Protocol ----------------------------- //#define USE_KNX // Enable KNX IP Protocol Support (+9.4k code, +3k7 mem) diff --git a/sonoff/settings.h b/sonoff/settings.h index 5f8e2f6ce..02674b6bc 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -1,5 +1,5 @@ /* - settings.h - setting variables for Sonoff-Tasmota + settings.h - setting variables for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 76dcade8c..75d1726c0 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -1,5 +1,5 @@ /* - settings.ino - user settings for Sonoff-Tasmota + settings.ino - user settings for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 62dce5e2f..2b2d12048 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -1,5 +1,5 @@ /* - sonoff.h - Master header file for Sonoff-Tasmota + sonoff.h - Master header file for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 18a699350..c369f20a1 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1,5 +1,5 @@ /* - sonoff.ino - Sonoff-Tasmota firmware for iTead Sonoff, Wemos and NodeMCU hardware + sonoff.ino - Tasmota firmware for iTead Sonoff, Wemos and NodeMCU hardware Copyright (C) 2019 Theo Arends @@ -27,7 +27,7 @@ // Location specific includes #include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) -#include "sonoff_version.h" // Sonoff-Tasmota version information +#include "sonoff_version.h" // Tasmota version information #include "sonoff.h" // Enumeration used in my_user_config.h #include "my_user_config.h" // Fixed user configurable options #ifdef USE_MQTT_TLS diff --git a/sonoff/sonoff_ca.ino b/sonoff/sonoff_ca.ino index 3dea12c9e..f34b87dec 100644 --- a/sonoff/sonoff_ca.ino +++ b/sonoff/sonoff_ca.ino @@ -1,5 +1,5 @@ /* - sonoff_ca.ino - Certificate authorities for Sonoff-Tasmota, LetsEncrypt and AWS + sonoff_ca.ino - Certificate authorities for Tasmota, LetsEncrypt and AWS Copyright (C) 2019 Theo Arends diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index b8b282fa7..309cc4e32 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -1,5 +1,5 @@ /* - sonoff_post.h - Post header file for Sonoff-Tasmota + sonoff_post.h - Post header file for Tasmota Copyright (C) 2019 Theo Arends @@ -97,7 +97,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #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_DEEPSLEEP // Add support for deepsleep (+1k code) -//#define USE_EXS_DIMMER // Add support for EX-Store WiFi Dimmer +#define USE_EXS_DIMMER // Add support for EX-Store WiFi Dimmer // -- Optional light modules ---------------------- #define USE_LIGHT // Add Dimmer/Light support diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 51cd2d0fd..a930dbd27 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1,5 +1,5 @@ /* - sonoff_template.h - template settings for Sonoff-Tasmota + sonoff_template.h - template settings for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 6fc555fd6..21ceb7cd4 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -1,5 +1,5 @@ /* - sonoff_version.h - Version header file for Sonoff-Tasmota + sonoff_version.h - Version header file for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/support.ino b/sonoff/support.ino index bb6a6aa72..6588f523e 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1,5 +1,5 @@ /* - support.ino - support for Sonoff-Tasmota + support.ino - support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index f449eb180..d4a269017 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -1,5 +1,5 @@ /* - support_button.ino - button support for Sonoff-Tasmota + support_button.ino - button support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index fdf65ecf7..3915e9ea7 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -1,5 +1,5 @@ /* - support_command.ino - command support for Sonoff-Tasmota + support_command.ino - command support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 638930d21..e4f5c1044 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -1,5 +1,5 @@ /* - support_features.ino - feature support for Sonoff-Tasmota + support_features.ino - feature support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/support_float.ino b/sonoff/support_float.ino index 6fe23192d..9ad556354 100644 --- a/sonoff/support_float.ino +++ b/sonoff/support_float.ino @@ -1,5 +1,5 @@ /* - support_float.ino - Small floating point support for Sonoff-Tasmota + support_float.ino - Small floating point support for Tasmota Copyright (C) 2019 Theo Arends and Stephan Hadinger diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index cc1ca0eb2..1adf2423d 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -1,5 +1,5 @@ /* - support_rotary.ino - rotary switch support for Sonoff-Tasmota + support_rotary.ino - rotary switch support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index b799003c4..94ea9bebe 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -1,5 +1,5 @@ /* - support_rtc.ino - Real Time Clock support for Sonoff-Tasmota + support_rtc.ino - Real Time Clock support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/support_static_buffer.ino b/sonoff/support_static_buffer.ino index 9d1cb1031..b19ed931f 100644 --- a/sonoff/support_static_buffer.ino +++ b/sonoff/support_static_buffer.ino @@ -1,5 +1,5 @@ /* - support_buffer.ino - Static binary buffer for Zigbee + support_buffer.ino - Static binary buffer for Zigbee on Tasmota Copyright (C) 2019 Theo Arends and Stephan Hadinger diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index 940fcdb1d..5415c1210 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -1,5 +1,5 @@ /* - support_switch.ino - switch support for Sonoff-Tasmota + support_switch.ino - switch support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/support_udp.ino b/sonoff/support_udp.ino index a33ca6973..f7c83775f 100644 --- a/sonoff/support_udp.ino +++ b/sonoff/support_udp.ino @@ -1,5 +1,5 @@ /* - support_udp.ino - Udp support for Sonoff-Tasmota + support_udp.ino - Udp support for Tasmota Copyright (C) 2019 Heiko Krupp and Theo Arends diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index bfbc3631f..ba0e95eae 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -1,5 +1,5 @@ /* - support_wifi.ino - wifi support for Sonoff-Tasmota + support_wifi.ino - wifi support for Tasmota Copyright (C) 2019 Theo Arends @@ -119,7 +119,7 @@ void WiFiSetSleepMode(void) * where there is a requirement for the accurancy of the TCP timer. * * Sleep is disabled in core 2.4.1 and 2.4.2 as there are bugs in their SDKs - * See https://github.com/arendst/Sonoff-Tasmota/issues/2559 + * See https://github.com/arendst/Tasmota/issues/2559 */ // Sleep explanation: https://github.com/esp8266/Arduino/blob/3f0c601cfe81439ce17e9bd5d28994a7ed144482/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp#L255 diff --git a/sonoff/user_config_override_sample.h b/sonoff/user_config_override_sample.h index 9a48d2d50..ef97e43cf 100644 --- a/sonoff/user_config_override_sample.h +++ b/sonoff/user_config_override_sample.h @@ -1,5 +1,5 @@ /* - user_config_override.h - user configuration overrides my_user_config.h for Sonoff-Tasmota + user_config_override.h - user configuration overrides my_user_config.h for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 17622e920..cab654c91 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1,5 +1,5 @@ /* - xdrv_01_webserver.ino - webserver for Sonoff-Tasmota + xdrv_01_webserver.ino - webserver for Tasmota Copyright (C) 2019 Theo Arends @@ -474,7 +474,7 @@ const char HTTP_COUNTER[] PROGMEM = "
"; const char HTTP_END[] PROGMEM = - "" + "" "" "" ""; diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 22ecf5f58..cafdc80da 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -1,5 +1,5 @@ /* - xdrv_02_mqtt.ino - mqtt support for Sonoff-Tasmota + xdrv_02_mqtt.ino - mqtt support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 263b2fa15..13bb8948a 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -1,5 +1,5 @@ /* - xdrv_03_energy.ino - Energy sensor support for Sonoff-Tasmota + xdrv_03_energy.ino - Energy sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 558b843da..67359634e 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1,5 +1,5 @@ /* - xdrv_04_light.ino - PWM, WS2812 and sonoff led support for Sonoff-Tasmota + xdrv_04_light.ino - PWM, WS2812 and sonoff led support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 4dd71f24f..b162825f5 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -1,5 +1,5 @@ /* - xdrv_05_irremote.ino - infra red support for Sonoff-Tasmota + xdrv_05_irremote.ino - infra red support for Tasmota Copyright (C) 2019 Heiko Krupp, Lazar Obradovic and Theo Arends diff --git a/sonoff/xdrv_05_irremote_full.ino b/sonoff/xdrv_05_irremote_full.ino index d78921b54..81a6ba8cf 100644 --- a/sonoff/xdrv_05_irremote_full.ino +++ b/sonoff/xdrv_05_irremote_full.ino @@ -1,5 +1,5 @@ /* - xdrv_05_irremote_full.ino - complete intefration of IRremoteESP8266 + xdrv_05_irremote_full.ino - complete integration of IRremoteESP8266 for Tasmota Copyright (C) 2019 Heiko Krupp, Lazar Obradovic, Theo Arends, Stephan Hadinger diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index fbd7a344a..f65ffd314 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -1,5 +1,5 @@ /* - xdrv_06_snfbridge.ino - sonoff RF bridge 433 support for Sonoff-Tasmota + xdrv_06_snfbridge.ino - sonoff RF bridge 433 support for Tasmota Copyright (C) 2019 Theo Arends and Erik Andrén Zachrisson (fw update) @@ -52,7 +52,7 @@ struct SONOFFBRIDGE { * EFM8BB1 RF microcontroller in-situ firmware update * * Enables upload of EFM8BB1 firmware provided by https://github.com/Portisch/RF-Bridge-EFM8BB1 using the web gui. - * Based on source by Erik Andrén Zachrisson (https://github.com/arendst/Sonoff-Tasmota/pull/2886) + * Based on source by Erik Andrén Zachrisson (https://github.com/arendst/Tasmota/pull/2886) \*********************************************************************************************/ #include "ihx.h" diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index e4f1b5ca1..164e2d751 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -1,5 +1,5 @@ /* - xdrv_07_domoticz.ino - domoticz support for Sonoff-Tasmota + xdrv_07_domoticz.ino - domoticz support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 117671d94..3414b0ccd 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -1,5 +1,5 @@ /* - xdrv_08_serial_bridge.ino - serial bridge support for Sonoff-Tasmota + xdrv_08_serial_bridge.ino - serial bridge support for Tasmota Copyright (C) 2019 Theo Arends and Dániel Zoltán Tolnai diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 130ef04c4..6e1bf4352 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -1,5 +1,5 @@ /* - xdrv_09_timers.ino - timer support for Sonoff-Tasmota + xdrv_09_timers.ino - timer support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index d5d074a6f..1a1f3c2c2 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -1,5 +1,5 @@ /* - xdrv_10_rules.ino - rule support for Sonoff-Tasmota + xdrv_10_rules.ino - rule support for Tasmota Copyright (C) 2019 ESP Easy Group and Theo Arends diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index 434c1716a..730c4b24c 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -1,5 +1,5 @@ /* - xdrv_10_scripter.ino - script support for Sonoff-Tasmota + xdrv_10_scripter.ino - script support for Tasmota Copyright (C) 2019 Gerhard Mutz and Theo Arends diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index a1b45800e..8ba54b73b 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1,5 +1,5 @@ /* - xdrv_11_knx.ino - KNX IP Protocol support for Sonoff-Tasmota + xdrv_11_knx.ino - KNX IP Protocol support for Tasmota Copyright (C) 2019 Adrian Scillato (https://github.com/ascillato) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index e27f4a4d7..81596e2b6 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -1,5 +1,5 @@ /* - xdrv_12_home_assistant.ino - home assistant support for Sonoff-Tasmota + xdrv_12_home_assistant.ino - home assistant support for Tasmota Copyright (C) 2019 Theo Arends @@ -133,7 +133,7 @@ const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = ",\"json_attributes_topic\":\"%s\"," "\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"," // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} - "\"ic\":\"mdi:information-outline\""; + "\"ic\":\"mdi:information-outline\""; const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = ",\"uniq_id\":\"%s\"," @@ -322,7 +322,7 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint GetPowerDevice(value_template, device+1, sizeof(value_template), key + Settings.flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by Settings.flag.device_index_enable //GetTopic_P(state_topic, CMND, topic, value_template); // State of button is sent as CMND TOGGLE, state of switch is sent as ON/OFF - GetTopic_P(state_topic, STAT, mqtt_topic, PSTR(D_RSLT_RESULT)); + GetTopic_P(state_topic, STAT, mqtt_topic, PSTR(D_RSLT_RESULT)); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(state_topic, availability_topic, prefix); @@ -621,7 +621,7 @@ void HAssAnyKey(void) char stopic[TOPSZ]; GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(state)); - MqttPublish(stopic); + MqttPublish(stopic); } /*********************************************************************************************\ diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 0317c4e03..2c0f7f229 100755 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -1,5 +1,5 @@ /* - xdrv_13_display.ino - Display support for Sonoff-Tasmota + xdrv_13_display.ino - Display support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index 91500a908..14af8df56 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -1,5 +1,5 @@ /* - xdrv_14_mp3.ino - MP3 support for Sonoff-Tasmota + xdrv_14_mp3.ino - MP3 support for Tasmota Copyright (C) 2019 gemu2015, mike2nl and Theo Arends @@ -57,7 +57,7 @@ --- 0.9.0.0 20180901 started - further development by mike2nl - https://github.com/mike2nl/Sonoff-Tasmota base - code base from gemu2015 ;-) - https://github.com/gemu2015/Sonoff-Tasmota - forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Tasmota */ diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index fb1a923d5..2093255c3 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -1,5 +1,5 @@ /* - xdrv_15_pca9685.ino - Support for I2C PCA9685 12bit 16 pin hardware PWM driver + xdrv_15_pca9685.ino - Support for I2C PCA9685 12bit 16 pin hardware PWM driver on Tasmota Copyright (C) 2019 Andre Thomas and Theo Arends diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index e80adef59..6cab4bb4d 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -1,5 +1,5 @@ /* - xdrv_16_tuyamcu.ino - Tuya MCU support for Sonoff-Tasmota + xdrv_16_tuyamcu.ino - Tuya MCU support for Tasmota Copyright (C) 2019 digiblur, Joel Stein and Theo Arends diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index 9d6d33660..5d448153a 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -1,5 +1,5 @@ /* - xdrv_17_rcswitch.ino - RF transceiver using RcSwitch library for Sonoff-Tasmota + xdrv_17_rcswitch.ino - RF transceiver using RcSwitch library for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_18_armtronix_dimmers.ino b/sonoff/xdrv_18_armtronix_dimmers.ino index abf366c14..2c60c8170 100644 --- a/sonoff/xdrv_18_armtronix_dimmers.ino +++ b/sonoff/xdrv_18_armtronix_dimmers.ino @@ -1,5 +1,5 @@ /* - xdrv_18_armtronix_dimmers.ino - Armtronix dimmers support for Sonoff-Tasmota + xdrv_18_armtronix_dimmers.ino - Armtronix dimmers support for Tasmota Copyright (C) 2019 wvdv2002 and Theo Arends diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 80c32ba47..bb7248eb8 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -1,5 +1,5 @@ /* - xdrv_19_ps16dz.dimmer.ino - PS_16_DZ dimmer support for Sonoff-Tasmota + xdrv_19_ps16dz.dimmer.ino - PS_16_DZ dimmer support for Tasmota Copyright (C) 2019 Joel Stein and Theo Arends diff --git a/sonoff/xdrv_20_hue.ino b/sonoff/xdrv_20_hue.ino index cd41a30ef..9289822fc 100644 --- a/sonoff/xdrv_20_hue.ino +++ b/sonoff/xdrv_20_hue.ino @@ -1,5 +1,5 @@ /* - xdrv_20_hue.ino - Philips Hue support for Sonoff-Tasmota + xdrv_20_hue.ino - Philips Hue support for Tasmota Copyright (C) 2019 Heiko Krupp and Theo Arends diff --git a/sonoff/xdrv_21_wemo.ino b/sonoff/xdrv_21_wemo.ino index 4858cd1f5..4a50560e2 100644 --- a/sonoff/xdrv_21_wemo.ino +++ b/sonoff/xdrv_21_wemo.ino @@ -1,5 +1,5 @@ /* - xdrv_21_wemo.ino - wemo support for Sonoff-Tasmota + xdrv_21_wemo.ino - wemo support for Tasmota Copyright (C) 2019 Heiko Krupp and Theo Arends diff --git a/sonoff/xdrv_22_sonoff_ifan.ino b/sonoff/xdrv_22_sonoff_ifan.ino index 490eb9c72..b05edc5e0 100644 --- a/sonoff/xdrv_22_sonoff_ifan.ino +++ b/sonoff/xdrv_22_sonoff_ifan.ino @@ -1,5 +1,5 @@ /* - xdrv_22_sonoff_ifan.ino - sonoff iFan02 and iFan03 support for Sonoff-Tasmota + xdrv_22_sonoff_ifan.ino - sonoff iFan02 and iFan03 support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_23_zigbee_0_constants.ino b/sonoff/xdrv_23_zigbee_0_constants.ino index 13d7dbb4f..996d877f8 100644 --- a/sonoff/xdrv_23_zigbee_0_constants.ino +++ b/sonoff/xdrv_23_zigbee_0_constants.ino @@ -1,5 +1,5 @@ /* - xdrv_23_zigbee_constants.ino - zigbee support for Sonoff-Tasmota + xdrv_23_zigbee_constants.ino - zigbee support for Tasmota Copyright (C) 2019 Theo Arends and Stephan Hadinger diff --git a/sonoff/xdrv_23_zigbee_3_devices.ino b/sonoff/xdrv_23_zigbee_3_devices.ino index 3596ef78e..7068973c0 100644 --- a/sonoff/xdrv_23_zigbee_3_devices.ino +++ b/sonoff/xdrv_23_zigbee_3_devices.ino @@ -1,5 +1,5 @@ /* - xdrv_23_zigbee.ino - zigbee support for Sonoff-Tasmota + xdrv_23_zigbee.ino - zigbee support for Tasmota Copyright (C) 2019 Theo Arends and Stephan Hadinger @@ -202,7 +202,7 @@ int32_t Z_Devices::findLongAddr(uint64_t longaddr) { } // -// We have a seen a shortaddr on the network, get the corresponding +// We have a seen a shortaddr on the network, get the corresponding // Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) { if (!shortaddr) { return *(Z_Device*) nullptr; } // this is not legal diff --git a/sonoff/xdrv_23_zigbee_5_converters.ino b/sonoff/xdrv_23_zigbee_5_converters.ino index 76df95aeb..ec4a29280 100644 --- a/sonoff/xdrv_23_zigbee_5_converters.ino +++ b/sonoff/xdrv_23_zigbee_5_converters.ino @@ -1,5 +1,5 @@ /* - xdrv_23_zigbee_converters.ino - zigbee support for Sonoff-Tasmota + xdrv_23_zigbee_converters.ino - zigbee support for Tasmota Copyright (C) 2019 Theo Arends and Stephan Hadinger @@ -459,7 +459,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0000, 0x0000, "ZCLVersion", &Z_Copy }, { 0x0000, 0x0001, "AppVersion", &Z_Copy }, { 0x0000, 0x0002, "StackVersion", &Z_Copy }, - { 0x0000, 0x0003, "HWVersion", &Z_Copy }, + { 0x0000, 0x0003, "HWVersion", &Z_Copy }, { 0x0000, 0x0004, "Manufacturer", &Z_ManufKeep }, // record Manufacturer { 0x0000, 0x0005, D_JSON_MODEL D_JSON_ID, &Z_ModelKeep }, // record Model { 0x0000, 0x0006, "DateCode", &Z_Copy }, @@ -670,10 +670,10 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0B01, 0x000E, "PowerThreshold", &Z_Copy }, { 0x0400, 0x0000, D_JSON_ILLUMINANCE, &Z_Copy }, // Illuminance (in Lux) - { 0x0400, 0x0001, "MinMeasuredValue", &Z_Copy }, // - { 0x0400, 0x0002, "MaxMeasuredValue", &Z_Copy }, // - { 0x0400, 0x0003, "Tolerance", &Z_Copy }, // - { 0x0400, 0x0004, "LightSensorType", &Z_Copy }, // + { 0x0400, 0x0001, "MinMeasuredValue", &Z_Copy }, // + { 0x0400, 0x0002, "MaxMeasuredValue", &Z_Copy }, // + { 0x0400, 0x0003, "Tolerance", &Z_Copy }, // + { 0x0400, 0x0004, "LightSensorType", &Z_Copy }, // { 0x0400, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values { 0x0401, 0x0000, "LevelStatus", &Z_Copy }, // Illuminance (in Lux) @@ -681,33 +681,33 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0401, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values { 0x0402, 0x0000, D_JSON_TEMPERATURE, &Z_FloatDiv100 }, // Temperature - { 0x0402, 0x0001, "MinMeasuredValue", &Z_FloatDiv100 }, // - { 0x0402, 0x0002, "MaxMeasuredValue", &Z_FloatDiv100 }, // - { 0x0402, 0x0003, "Tolerance", &Z_FloatDiv100 }, // + { 0x0402, 0x0001, "MinMeasuredValue", &Z_FloatDiv100 }, // + { 0x0402, 0x0002, "MaxMeasuredValue", &Z_FloatDiv100 }, // + { 0x0402, 0x0003, "Tolerance", &Z_FloatDiv100 }, // { 0x0402, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values { 0x0403, 0x0000, D_JSON_PRESSURE_UNIT, &Z_AddPressureUnit }, // Pressure Unit { 0x0403, 0x0000, D_JSON_PRESSURE, &Z_Copy }, // Pressure - { 0x0403, 0x0001, "MinMeasuredValue", &Z_Copy }, // - { 0x0403, 0x0002, "MaxMeasuredValue", &Z_Copy }, // - { 0x0403, 0x0003, "Tolerance", &Z_Copy }, // - { 0x0403, 0x0010, "ScaledValue", &Z_Copy }, // - { 0x0403, 0x0011, "MinScaledValue", &Z_Copy }, // - { 0x0403, 0x0012, "MaxScaledValue", &Z_Copy }, // - { 0x0403, 0x0013, "ScaledTolerance", &Z_Copy }, // - { 0x0403, 0x0014, "Scale", &Z_Copy }, // + { 0x0403, 0x0001, "MinMeasuredValue", &Z_Copy }, // + { 0x0403, 0x0002, "MaxMeasuredValue", &Z_Copy }, // + { 0x0403, 0x0003, "Tolerance", &Z_Copy }, // + { 0x0403, 0x0010, "ScaledValue", &Z_Copy }, // + { 0x0403, 0x0011, "MinScaledValue", &Z_Copy }, // + { 0x0403, 0x0012, "MaxScaledValue", &Z_Copy }, // + { 0x0403, 0x0013, "ScaledTolerance", &Z_Copy }, // + { 0x0403, 0x0014, "Scale", &Z_Copy }, // { 0x0403, 0xFFFF, nullptr, &Z_Remove }, // Remove all other Pressure values { 0x0404, 0x0000, D_JSON_FLOWRATE, &Z_FloatDiv10 }, // Flow (in m3/h) - { 0x0404, 0x0001, "MinMeasuredValue", &Z_Copy }, // - { 0x0404, 0x0002, "MaxMeasuredValue", &Z_Copy }, // - { 0x0404, 0x0003, "Tolerance", &Z_Copy }, // + { 0x0404, 0x0001, "MinMeasuredValue", &Z_Copy }, // + { 0x0404, 0x0002, "MaxMeasuredValue", &Z_Copy }, // + { 0x0404, 0x0003, "Tolerance", &Z_Copy }, // { 0x0404, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values { 0x0405, 0x0000, D_JSON_HUMIDITY, &Z_FloatDiv100 }, // Humidity - { 0x0405, 0x0001, "MinMeasuredValue", &Z_Copy }, // - { 0x0405, 0x0002, "MaxMeasuredValue", &Z_Copy }, // - { 0x0405, 0x0003, "Tolerance", &Z_Copy }, // + { 0x0405, 0x0001, "MinMeasuredValue", &Z_Copy }, // + { 0x0405, 0x0002, "MaxMeasuredValue", &Z_Copy }, // + { 0x0405, 0x0003, "Tolerance", &Z_Copy }, // { 0x0405, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values { 0x0406, 0x0000, "Occupancy", &Z_Copy }, // Occupancy (map8) diff --git a/sonoff/xdrv_23_zigbee_6_commands.ino b/sonoff/xdrv_23_zigbee_6_commands.ino index 017d2cd98..1dcbe3610 100644 --- a/sonoff/xdrv_23_zigbee_6_commands.ino +++ b/sonoff/xdrv_23_zigbee_6_commands.ino @@ -1,5 +1,5 @@ /* - xdrv_23_zigbee_converters.ino - zigbee support for Sonoff-Tasmota + xdrv_23_zigbee_converters.ino - zigbee support for Tasmota Copyright (C) 2019 Theo Arends and Stephan Hadinger diff --git a/sonoff/xdrv_23_zigbee_7_statemachine.ino b/sonoff/xdrv_23_zigbee_7_statemachine.ino index 844086bce..c8ba45717 100644 --- a/sonoff/xdrv_23_zigbee_7_statemachine.ino +++ b/sonoff/xdrv_23_zigbee_7_statemachine.ino @@ -1,5 +1,5 @@ /* - xdrv_23_zigbee.ino - zigbee support for Sonoff-Tasmota + xdrv_23_zigbee.ino - zigbee support for Tasmota Copyright (C) 2019 Theo Arends and Stephan Hadinger diff --git a/sonoff/xdrv_23_zigbee_8_parsers.ino b/sonoff/xdrv_23_zigbee_8_parsers.ino index 286596e33..d0d7a3079 100644 --- a/sonoff/xdrv_23_zigbee_8_parsers.ino +++ b/sonoff/xdrv_23_zigbee_8_parsers.ino @@ -1,5 +1,5 @@ /* - xdrv_23_zigbee.ino - zigbee support for Sonoff-Tasmota + xdrv_23_zigbee.ino - zigbee support for Tasmota Copyright (C) 2019 Theo Arends and Stephan Hadinger @@ -78,7 +78,7 @@ const char Z_RebootReason[] PROGMEM = "Power-up|External|Watchdog"; int32_t Z_Reboot(int32_t res, class SBuffer &buf) { // print information about the reboot of device // 4180.02.02.00.02.06.03 - // + // uint8_t reason = buf.get8(2); uint8_t transport_rev = buf.get8(3); uint8_t product_id = buf.get8(4); @@ -387,7 +387,7 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { JsonObject& json_root = jsonBuffer.createObject(); JsonObject& json1 = json_root.createNestedObject(F(D_CMND_ZIGBEE_RECEIVED)); JsonObject& json = json1.createNestedObject(shortaddr); - + // TODO add name field if it is known if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { zcl_received.parseRawAttributes(json); diff --git a/sonoff/xdrv_23_zigbee_9_impl.ino b/sonoff/xdrv_23_zigbee_9_impl.ino index 07fec54f4..a935ba08a 100644 --- a/sonoff/xdrv_23_zigbee_9_impl.ino +++ b/sonoff/xdrv_23_zigbee_9_impl.ino @@ -1,5 +1,5 @@ /* - xdrv_23_zigbee.ino - zigbee support for Sonoff-Tasmota + xdrv_23_zigbee.ino - zigbee support for Tasmota Copyright (C) 2019 Theo Arends and Stephan Hadinger diff --git a/sonoff/xdrv_24_buzzer.ino b/sonoff/xdrv_24_buzzer.ino index d6cf24683..f0238a3d6 100644 --- a/sonoff/xdrv_24_buzzer.ino +++ b/sonoff/xdrv_24_buzzer.ino @@ -1,5 +1,5 @@ /* - xdrv_24_Buzzer.ino - buzzer support for Sonoff-Tasmota + xdrv_24_Buzzer.ino - buzzer support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_25_A4988_Stepper.ino b/sonoff/xdrv_25_A4988_Stepper.ino index f863b9768..736d86e24 100644 --- a/sonoff/xdrv_25_A4988_Stepper.ino +++ b/sonoff/xdrv_25_A4988_Stepper.ino @@ -1,6 +1,6 @@ /* - xdrv_25_a4988_stepper.ino - A4988 StepMotorDriverCircuit- support for Sonoff-Tasmota + xdrv_25_a4988_stepper.ino - A4988 StepMotorDriverCircuit- support for Tasmota Copyright (C) 2019 Tim Leuscher and Theo Arends diff --git a/sonoff/xdrv_26_ariluxrf.ino b/sonoff/xdrv_26_ariluxrf.ino index 48eb1b46c..583f9a9bc 100644 --- a/sonoff/xdrv_26_ariluxrf.ino +++ b/sonoff/xdrv_26_ariluxrf.ino @@ -1,5 +1,5 @@ /* - xdrv_26_ariluxrf.ino - Arilux Rf support for Sonoff-Tasmota + xdrv_26_ariluxrf.ino - Arilux Rf support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_27_shutter.ino b/sonoff/xdrv_27_shutter.ino index 7c0f989d1..f7ba5c911 100644 --- a/sonoff/xdrv_27_shutter.ino +++ b/sonoff/xdrv_27_shutter.ino @@ -1,5 +1,5 @@ /* - xdrv_27_shutter.ino - Shutter/Blind support for Sonoff-Tasmota + xdrv_27_shutter.ino - Shutter/Blind support for Tasmota Copyright (C) 2019 Stefan Bode diff --git a/sonoff/xdrv_28_pcf8574.ino b/sonoff/xdrv_28_pcf8574.ino index ab63ff79b..d527fd330 100644 --- a/sonoff/xdrv_28_pcf8574.ino +++ b/sonoff/xdrv_28_pcf8574.ino @@ -1,5 +1,5 @@ /* - xdrv_28_pcf8574.ino - PCF8574 I2C support for Sonoff-Tasmota + xdrv_28_pcf8574.ino - PCF8574 I2C support for Tasmota Copyright (C) 2019 Stefan Bode diff --git a/sonoff/xdrv_29_deepsleep.ino b/sonoff/xdrv_29_deepsleep.ino index 13706798b..a3e091227 100644 --- a/sonoff/xdrv_29_deepsleep.ino +++ b/sonoff/xdrv_29_deepsleep.ino @@ -1,5 +1,5 @@ /* - xdrv_29_deepsleep.ino - DeepSleep support for Sonoff-Tasmota + xdrv_29_deepsleep.ino - DeepSleep support for Tasmota Copyright (C) 2019 Stefan Bode diff --git a/sonoff/xdrv_30_exs_dimmer.ino b/sonoff/xdrv_30_exs_dimmer.ino index a476db95c..2b4ef8dd0 100644 --- a/sonoff/xdrv_30_exs_dimmer.ino +++ b/sonoff/xdrv_30_exs_dimmer.ino @@ -1,5 +1,5 @@ /* - xdrv_30_exs_dimmer.ino - ex-store dimmer support for Sonoff-Tasmota + xdrv_30_exs_dimmer.ino - ex-store dimmer support for Tasmota Copyright (C) 2019 Andreas Schultz diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino index 78437ad33..717eafb71 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -1,5 +1,5 @@ /* - xdrv_99_debug.ino - debug support for Sonoff-Tasmota + xdrv_99_debug.ino - debug support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index ead58e613..d021cc5bd 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -1,5 +1,5 @@ /* - xdrv_interface.ino - Driver interface support for Sonoff-Tasmota + xdrv_interface.ino - Driver interface support for Tasmota Copyright (C) 2019 Theo Arends inspired by ESPEasy diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index 8ab867f48..b992b87c3 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -1,5 +1,5 @@ /* - xdsp_01_lcd.ino - Display LCD support for Sonoff-Tasmota + xdsp_01_lcd.ino - Display LCD support for Tasmota Copyright (C) 2019 Theo Arends and Adafruit diff --git a/sonoff/xdsp_02_ssd1306.ino b/sonoff/xdsp_02_ssd1306.ino index 04251b595..4b49c2329 100755 --- a/sonoff/xdsp_02_ssd1306.ino +++ b/sonoff/xdsp_02_ssd1306.ino @@ -1,5 +1,5 @@ /* - xdsp_02_ssd1306.ino - Display Oled SSD1306 support for Sonoff-Tasmota + xdsp_02_ssd1306.ino - Display Oled SSD1306 support for Tasmota Copyright (C) 2019 Theo Arends and Adafruit diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index 6635fb606..ed1d805b5 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -1,5 +1,5 @@ /* - xdsp_03_matrix.ino - Display 8x8 matrix support for Sonoff-Tasmota + xdsp_03_matrix.ino - Display 8x8 matrix support for Tasmota Copyright (C) 2019 Theo Arends and Adafruit diff --git a/sonoff/xdsp_04_ili9341.ino b/sonoff/xdsp_04_ili9341.ino index 8871e6586..f3b80e73a 100644 --- a/sonoff/xdsp_04_ili9341.ino +++ b/sonoff/xdsp_04_ili9341.ino @@ -1,5 +1,5 @@ /* - xdsp_04_ili9341.ino - Display Tft Ili9341 support for Sonoff-Tasmota + xdsp_04_ili9341.ino - Display Tft Ili9341 support for Tasmota Copyright (C) 2019 Theo Arends and Adafruit diff --git a/sonoff/xdsp_05_epaper_29.ino b/sonoff/xdsp_05_epaper_29.ino index 8d97bd123..47ed941c5 100644 --- a/sonoff/xdsp_05_epaper_29.ino +++ b/sonoff/xdsp_05_epaper_29.ino @@ -1,5 +1,5 @@ /* - xdsp_05_epaper.ino - Display e-paper support for Sonoff-Tasmota + xdsp_05_epaper.ino - Display e-paper support for Tasmota Copyright (C) 2019 Theo Arends, Gerhard Mutz and Waveshare diff --git a/sonoff/xdsp_06_epaper_42.ino b/sonoff/xdsp_06_epaper_42.ino index 0dd235186..1a9c9d557 100644 --- a/sonoff/xdsp_06_epaper_42.ino +++ b/sonoff/xdsp_06_epaper_42.ino @@ -1,5 +1,5 @@ /* - xdsp_05_epaper.ino - Display e-paper support for Sonoff-Tasmota + xdsp_05_epaper.ino - Display e-paper support for Tasmota Copyright (C) 2019 Theo Arends, Gerhard Mutz and Waveshare diff --git a/sonoff/xdsp_07_sh1106.ino b/sonoff/xdsp_07_sh1106.ino index 6c535b02a..f30cd10be 100644 --- a/sonoff/xdsp_07_sh1106.ino +++ b/sonoff/xdsp_07_sh1106.ino @@ -1,5 +1,5 @@ /* - xdsp_07_SH1106.ino - Display Oled SH1106 support for Sonoff-Tasmota + xdsp_07_SH1106.ino - Display Oled SH1106 support for Tasmota Copyright (C) 2019 Theo Arends and Adafruit diff --git a/sonoff/xdsp_08_ILI9488.ino b/sonoff/xdsp_08_ILI9488.ino index 071280601..c77f21bf2 100644 --- a/sonoff/xdsp_08_ILI9488.ino +++ b/sonoff/xdsp_08_ILI9488.ino @@ -1,5 +1,5 @@ /* - xdsp_08_ILI9488.ino - Display ILI9488 support for Sonoff-Tasmota + xdsp_08_ILI9488.ino - Display ILI9488 support for Tasmota Copyright (C) 2019 Theo Arends, Gerhard Mutz diff --git a/sonoff/xdsp_09_SSD1351.ino b/sonoff/xdsp_09_SSD1351.ino index 0a3b69b4e..ad7e86f99 100644 --- a/sonoff/xdsp_09_SSD1351.ino +++ b/sonoff/xdsp_09_SSD1351.ino @@ -1,5 +1,5 @@ /* - xdsp_09_SSD1351.ino - Display SSD1351 support for Sonoff-Tasmota + xdsp_09_SSD1351.ino - Display SSD1351 support for Tasmota Copyright (C) 2019 Gerhard Mutz and Theo Arends diff --git a/sonoff/xdsp_10_RA8876.ino b/sonoff/xdsp_10_RA8876.ino index d138ae154..a8c2763f9 100644 --- a/sonoff/xdsp_10_RA8876.ino +++ b/sonoff/xdsp_10_RA8876.ino @@ -1,5 +1,5 @@ /* - xdsp_09_SSD1351.ino - Display SSD1351 support for Sonoff-Tasmota + xdsp_09_SSD1351.ino - Display SSD1351 support for Tasmota Copyright (C) 2019 Gerhard Mutz and Theo Arends diff --git a/sonoff/xdsp_interface.ino b/sonoff/xdsp_interface.ino index bc0890f3b..8fa418f5a 100644 --- a/sonoff/xdsp_interface.ino +++ b/sonoff/xdsp_interface.ino @@ -1,5 +1,5 @@ /* - xdsp_interface.ino - Display interface support for Sonoff-Tasmota + xdsp_interface.ino - Display interface support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xlgt_01_ws2812.ino b/sonoff/xlgt_01_ws2812.ino index 2c0a11f0b..f763efd15 100644 --- a/sonoff/xlgt_01_ws2812.ino +++ b/sonoff/xlgt_01_ws2812.ino @@ -1,5 +1,5 @@ /* - xlgt_01_ws2812.ino - led string support for Sonoff-Tasmota + xlgt_01_ws2812.ino - led string support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xlgt_02_my92x1.ino b/sonoff/xlgt_02_my92x1.ino index 551249a01..254f1e78a 100644 --- a/sonoff/xlgt_02_my92x1.ino +++ b/sonoff/xlgt_02_my92x1.ino @@ -1,5 +1,5 @@ /* - xlgt_02_my92x1.ino - led support for Sonoff-Tasmota + xlgt_02_my92x1.ino - led support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xlgt_03_sm16716.ino b/sonoff/xlgt_03_sm16716.ino index d12636e85..6ae2066e4 100644 --- a/sonoff/xlgt_03_sm16716.ino +++ b/sonoff/xlgt_03_sm16716.ino @@ -1,5 +1,5 @@ /* - xlgt_03_sm16716.ino - sm16716 three channel led support for Sonoff-Tasmota + xlgt_03_sm16716.ino - sm16716 three channel led support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xlgt_04_sm2135.ino b/sonoff/xlgt_04_sm2135.ino index 21755d656..dc4c7dafc 100644 --- a/sonoff/xlgt_04_sm2135.ino +++ b/sonoff/xlgt_04_sm2135.ino @@ -1,5 +1,5 @@ /* - xlgt_04_sm2135.ino - sm2135 five channel led support for Sonoff-Tasmota + xlgt_04_sm2135.ino - sm2135 five channel led support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xlgt_05_sonoff_l1.ino b/sonoff/xlgt_05_sonoff_l1.ino index f9f49aaa5..e6938401c 100644 --- a/sonoff/xlgt_05_sonoff_l1.ino +++ b/sonoff/xlgt_05_sonoff_l1.ino @@ -1,5 +1,5 @@ /* - xlgt_05_sonoff_l1.ino - Sonoff L1 led support for Sonoff-Tasmota + xlgt_05_sonoff_l1.ino - Sonoff L1 led support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xlgt_interface.ino b/sonoff/xlgt_interface.ino index cb963dc5c..667f7a822 100644 --- a/sonoff/xlgt_interface.ino +++ b/sonoff/xlgt_interface.ino @@ -1,5 +1,5 @@ /* - xlgt_interface.ino - Light driver interface support for Sonoff-Tasmota + xlgt_interface.ino - Light driver interface support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 5c904f13d..488da7059 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -1,5 +1,5 @@ /* - xnrg_01_hlw8012.ino - HLW8012 (Sonoff Pow) energy sensor support for Sonoff-Tasmota + xnrg_01_hlw8012.ino - HLW8012 (Sonoff Pow) energy sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino index b83e7bcb3..339d4fee2 100644 --- a/sonoff/xnrg_02_cse7766.ino +++ b/sonoff/xnrg_02_cse7766.ino @@ -1,5 +1,5 @@ /* - xnrg_02_cse7766.ino - CSE7766 and HLW8032 energy sensor support for Sonoff-Tasmota + xnrg_02_cse7766.ino - CSE7766 and HLW8032 energy sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index 93657ae01..0ab29d778 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -1,5 +1,5 @@ /* - xnrg_03_pzem004t.ino - PZEM004T energy sensor support for Sonoff-Tasmota + xnrg_03_pzem004t.ino - PZEM004T energy sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index fa9f5cb59..2fa98276d 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -1,5 +1,5 @@ /* - xnrg_04_mcp39f501.ino - MCP39F501 energy sensor support for Sonoff-Tasmota + xnrg_04_mcp39f501.ino - MCP39F501 energy sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index 3758e68a3..0e9e68a40 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -1,5 +1,5 @@ /* - xnrg_05_pzem_ac.ino - PZEM-014,016 Modbus AC energy sensor support for Sonoff-Tasmota + xnrg_05_pzem_ac.ino - PZEM-014,016 Modbus AC energy sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index 2e85ac945..ec32e5d73 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -1,5 +1,5 @@ /* - xnrg_06_pzem_dc.ino - PZEM-003,017 Modbus DC energy sensor support for Sonoff-Tasmota + xnrg_06_pzem_dc.ino - PZEM-003,017 Modbus DC energy sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xnrg_07_ade7953.ino b/sonoff/xnrg_07_ade7953.ino index 81c7c458e..5f789e3c8 100644 --- a/sonoff/xnrg_07_ade7953.ino +++ b/sonoff/xnrg_07_ade7953.ino @@ -1,5 +1,5 @@ /* - xnrg_07_ade7953.ino - ADE7953 energy sensor support for Sonoff-Tasmota + xnrg_07_ade7953.ino - ADE7953 energy sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xnrg_08_sdm120.ino b/sonoff/xnrg_08_sdm120.ino index c60dd16a7..75c0962e9 100644 --- a/sonoff/xnrg_08_sdm120.ino +++ b/sonoff/xnrg_08_sdm120.ino @@ -1,5 +1,5 @@ /* - xnrg_08_sdm120.ino - Eastron SDM120-Modbus energy meter support for Sonoff-Tasmota + xnrg_08_sdm120.ino - Eastron SDM120-Modbus energy meter support for Tasmota Copyright (C) 2019 Gennaro Tortone and Theo Arends diff --git a/sonoff/xnrg_09_dds2382.ino b/sonoff/xnrg_09_dds2382.ino index 590a60186..06a54e39c 100644 --- a/sonoff/xnrg_09_dds2382.ino +++ b/sonoff/xnrg_09_dds2382.ino @@ -1,5 +1,5 @@ /* - xnrg_09_dds2382.ino - Hiking DDS238-2 Modbus energy meter support for Sonoff-Tasmota + xnrg_09_dds2382.ino - Hiking DDS238-2 Modbus energy meter support for Tasmota Copyright (C) 2019 Matteo Campanella - based on the work of Gennaro Tortone diff --git a/sonoff/xnrg_10_sdm630.ino b/sonoff/xnrg_10_sdm630.ino index 8bf1827f8..31fb70031 100644 --- a/sonoff/xnrg_10_sdm630.ino +++ b/sonoff/xnrg_10_sdm630.ino @@ -1,5 +1,5 @@ /* - xnrg_10_sdm630.ino - Eastron SDM630-Modbus energy meter support for Sonoff-Tasmota + xnrg_10_sdm630.ino - Eastron SDM630-Modbus energy meter support for Tasmota Copyright (C) 2019 Gennaro Tortone and Theo Arends diff --git a/sonoff/xnrg_11_ddsu666.ino b/sonoff/xnrg_11_ddsu666.ino index 2f6dfbf36..daaadd72b 100644 --- a/sonoff/xnrg_11_ddsu666.ino +++ b/sonoff/xnrg_11_ddsu666.ino @@ -1,5 +1,5 @@ /* - xnrg_11_ddsu666.ino - Chint DDSU666-Modbus energy meter support for Sonoff-Tasmota + xnrg_11_ddsu666.ino - Chint DDSU666-Modbus energy meter support for Tasmota Copyright (C) 2019 Pablo Zerón and Theo Arends @@ -70,7 +70,7 @@ void DDSU666Every250ms(void) AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: Ddsu666 error %d"), error); } else { Energy.data_valid[0] = 0; - + // 0 1 2 3 4 5 6 7 8 // SA FC BC Fh Fl Sh Sl Cl Ch // 01 04 04 43 66 33 34 1B 38 = 230.2 Volt diff --git a/sonoff/xnrg_12_solaxX1.ino b/sonoff/xnrg_12_solaxX1.ino index 2c6c34a9e..b520302d3 100644 --- a/sonoff/xnrg_12_solaxX1.ino +++ b/sonoff/xnrg_12_solaxX1.ino @@ -1,5 +1,5 @@ /* - xnrg_12_solaxX1.ino - Solax X1 inverter RS485 support for Sonoff-Tasmota + xnrg_12_solaxX1.ino - Solax X1 inverter RS485 support for Tasmota Copyright (C) 2019 Pablo Zerón diff --git a/sonoff/xnrg_interface.ino b/sonoff/xnrg_interface.ino index 3e36b334b..80ac3cf55 100644 --- a/sonoff/xnrg_interface.ino +++ b/sonoff/xnrg_interface.ino @@ -1,5 +1,5 @@ /* - xnrg_interface.ino - Energy driver interface support for Sonoff-Tasmota + xnrg_interface.ino - Energy driver interface support for Tasmota Copyright (C) 2019 Theo Arends inspired by ESPEasy diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index e3b6a171a..296435579 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -1,5 +1,5 @@ /* - xsns_01_counter.ino - Counter sensors (water meters, electricity meters etc.) sensor support for Sonoff-Tasmota + xsns_01_counter.ino - Counter sensors (water meters, electricity meters etc.) sensor support for Tasmota Copyright (C) 2019 Maarten Damen and Theo Arends diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino index aebb12e4f..b65c23ab5 100644 --- a/sonoff/xsns_02_analog.ino +++ b/sonoff/xsns_02_analog.ino @@ -1,5 +1,5 @@ /* - xsns_02_analog.ino - ESP8266 ADC support for Sonoff-Tasmota + xsns_02_analog.ino - ESP8266 ADC support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index 98e842c76..060321349 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -1,5 +1,5 @@ /* - xsns_04_snfsc.ino - sonoff SC support for Sonoff-Tasmota + xsns_04_snfsc.ino - sonoff SC support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index ccbb5df5e..ca052c2f2 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -1,5 +1,5 @@ /* - xsns_05_ds18x20.ino - DS18x20 temperature sensor support for Sonoff-Tasmota + xsns_05_ds18x20.ino - DS18x20 temperature sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index 6604067e3..c4e877de9 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -1,5 +1,5 @@ /* - xsns_06_dht.ino - DHTxx, AM23xx and SI7021 temperature and humidity sensor support for Sonoff-Tasmota + xsns_06_dht.ino - DHTxx, AM23xx and SI7021 temperature and humidity sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index e3cffc6a3..3cff330dd 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -1,5 +1,5 @@ /* - xsns_07_sht1x.ino - SHT1x temperature and sensor support for Sonoff-Tasmota + xsns_07_sht1x.ino - SHT1x temperature and sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 96246e349..6425695bc 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -1,5 +1,5 @@ /* - xsns_08_htu21.ino - HTU21 temperature and humidity sensor support for Sonoff-Tasmota + xsns_08_htu21.ino - HTU21 temperature and humidity sensor support for Tasmota Copyright (C) 2019 Heiko Krupp and Theo Arends diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 8680d6dea..9d1976078 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -1,5 +1,5 @@ /* - xsns_09_bmp.ino - BMP pressure, temperature, humidity and gas sensor support for Sonoff-Tasmota + xsns_09_bmp.ino - BMP pressure, temperature, humidity and gas sensor support for Tasmota Copyright (C) 2019 Heiko Krupp and Theo Arends diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index d9af1b572..ab6137fd6 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -1,5 +1,5 @@ /* - xsns_10_bh1750.ino - BH1750 ambient light sensor support for Sonoff-Tasmota + xsns_10_bh1750.ino - BH1750 ambient light sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index 42beba939..c919be232 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -1,5 +1,5 @@ /* - xsns_11_veml6070.ino - VEML6070 ultra violet light sensor support for Sonoff-Tasmota + xsns_11_veml6070.ino - VEML6070 ultra violet light sensor support for Tasmota Copyright (C) 2019 Theo Arends @@ -73,7 +73,7 @@ - in user_config, show or show-NOT the uv raw value added - lots of #defines for automatic calulations to get the best possible values added - error messages for LOG_LEVEL_DEBUG - added - lots of information in one of the last postings in: https://github.com/arendst/Sonoff-Tasmota/issues/3844 + added - lots of information in one of the last postings in: https://github.com/arendst/Tasmota/issues/3844 debugging - without the softly hit ;-) from @andrethomas about Serial.print i would never done it. Thank You Andre safety - personal, please read this: http://www.segurancaetrabalho.com.br/download/uv_index_karel_vanicek.pdf next - possible i will add the calculation for LAT and LONG coordinates for much more precission @@ -81,7 +81,7 @@ - add a #define to select how many characters are shown benhind the decimal point for the UV Index --- 1.0.0.0 20180912 started - further development by mike2nl - https://github.com/mike2nl/Sonoff-Tasmota - forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Tasmota base - code base from arendst too */ diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index 270f4911a..a04f567a9 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -1,5 +1,5 @@ /* - xsns_12_ads1115_ada.ino - ADS1115 A/D Converter support for Sonoff-Tasmota + xsns_12_ads1115_ada.ino - ADS1115 A/D Converter support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index 9bfdd0ffe..871c3767a 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -1,5 +1,5 @@ /* - xsns_12_ads1115.ino - ADS1x15 A/D Converter support for Sonoff-Tasmota + xsns_12_ads1115.ino - ADS1x15 A/D Converter support for Tasmota Copyright (C) 2019 Stefan Bode and Theo Arends diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index 662db2209..5cdfaa692 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -1,5 +1,5 @@ /* - xsns_13_ina219.ino - INA219 Current Sensor support for Sonoff-Tasmota + xsns_13_ina219.ino - INA219 Current Sensor support for Tasmota Copyright (C) 2019 Stefan Bode and Theo Arends @@ -233,13 +233,13 @@ void Ina219Show(bool json) for (int i=0; i= Settings.tele_period-5 && tele_period <= Settings.tele_period-2) { //we are doing 4 measurements here diff --git a/sonoff/xsns_21_sgp30.ino b/sonoff/xsns_21_sgp30.ino index 7df1a65de..eaba63951 100644 --- a/sonoff/xsns_21_sgp30.ino +++ b/sonoff/xsns_21_sgp30.ino @@ -1,5 +1,5 @@ /* - xsns_21_sgp30.ino - SGP30 gas and air quality sensor support for Sonoff-Tasmota + xsns_21_sgp30.ino - SGP30 gas and air quality sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index f475790ae..e70fea52f 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -1,5 +1,5 @@ /* - xsns_22_sr04.ino - SR04 ultrasonic sensor support for Sonoff-Tasmota + xsns_22_sr04.ino - SR04 ultrasonic sensor support for Tasmota Copyright (C) 2019 Nuno Ferreira and Theo Arends diff --git a/sonoff/xsns_24_si1145.ino b/sonoff/xsns_24_si1145.ino index 2a1c26cd5..08e1d4b18 100644 --- a/sonoff/xsns_24_si1145.ino +++ b/sonoff/xsns_24_si1145.ino @@ -1,5 +1,5 @@ /* - xsns_24_si1145.ino - SI1145/46/47 UV Index / IR / Visible light sensor support for Sonoff-Tasmota + xsns_24_si1145.ino - SI1145/46/47 UV Index / IR / Visible light sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index 909bb607e..f8ef6f8b7 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -1,5 +1,5 @@ /* - xsns_27_apds9960.ino - Support for I2C APDS9960 Proximity Sensor for Sonoff-Tasmota + xsns_27_apds9960.ino - Support for I2C APDS9960 Proximity Sensor for Tasmota Copyright (C) 2019 Shawn Hymel/Sparkfun and Theo Arends diff --git a/sonoff/xsns_28_tm1638.ino b/sonoff/xsns_28_tm1638.ino index f9f95b73d..0f6a19078 100644 --- a/sonoff/xsns_28_tm1638.ino +++ b/sonoff/xsns_28_tm1638.ino @@ -1,5 +1,5 @@ /* - xsns_28_tm1638.ino - TM1638 8 switch, led and 7 segment unit support for Sonoff-Tasmota + xsns_28_tm1638.ino - TM1638 8 switch, led and 7 segment unit support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 0e9cc1039..1ed395900 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -1,5 +1,5 @@ /* - xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander + xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander on Tasmota Copyright (C) 2019 Andre Thomas and Theo Arends diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index 22fcc381d..a7a7651d1 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -2,7 +2,7 @@ * * @file xsns_30_mpr121.ino * - * @package Sonoff-Tasmota + * @package Tasmota * @subpackage Sensors * @name MPR121 * @@ -13,7 +13,7 @@ * @date $Date$ * @version $Id$ * - * @link https://github.com/arendst/Sonoff-Tasmota/wiki/MPR121 \endlink + * @link https://github.com/arendst/Tasmota/wiki/MPR121 \endlink * @link https://www.sparkfun.com/datasheets/Components/MPR121.pdf \endlink * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3891.pdf \endlink * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3892.pdf \endlink diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 550313b51..cdfdeb017 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -1,5 +1,5 @@ /* - xsns_31_ccs811.ino - CCS811 gas and air quality sensor support for Sonoff-Tasmota + xsns_31_ccs811.ino - CCS811 gas and air quality sensor support for Tasmota Copyright (C) 2019 Gerhard Mutz and Theo Arends diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index 58915efc9..9b7ff5d89 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -1,5 +1,5 @@ /* - xsns_32_mpu6050.ino - MPU6050 gyroscope and temperature sensor support for Sonoff-Tasmota + xsns_32_mpu6050.ino - MPU6050 gyroscope and temperature sensor support for Tasmota Copyright (C) 2019 Oliver Welter diff --git a/sonoff/xsns_33_ds3231.ino b/sonoff/xsns_33_ds3231.ino index ef2acfbd4..6fa9a6a54 100644 --- a/sonoff/xsns_33_ds3231.ino +++ b/sonoff/xsns_33_ds3231.ino @@ -1,5 +1,5 @@ /* - xsns_33_ds3231.ino - ds3231 RTC chip, act like sensor support for Sonoff-Tasmota + xsns_33_ds3231.ino - ds3231 RTC chip, act like sensor support for Tasmota Copyright (C) 2019 Guy Elgabsi (guy.elg AT gmail.com) diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 28e8d253c..1ba029f91 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -1,5 +1,5 @@ /* - xsns_34_hx711.ino - HX711 load cell support for Sonoff-Tasmota + xsns_34_hx711.ino - HX711 load cell support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino index ee3fca596..cc072d6ac 100644 --- a/sonoff/xsns_35_tx20.ino +++ b/sonoff/xsns_35_tx20.ino @@ -1,5 +1,5 @@ /* - xsns_35_Tx20.ino - La Crosse Tx20 wind sensor support for Sonoff-Tasmota + xsns_35_Tx20.ino - La Crosse Tx20 wind sensor support for Tasmota Copyright (C) 2019 Thomas Eckerstorfer and Theo Arends diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino index 055126c6d..1a545f614 100644 --- a/sonoff/xsns_36_mgc3130.ino +++ b/sonoff/xsns_36_mgc3130.ino @@ -1,5 +1,5 @@ /* - xsns_36_MGC3130.ino - Support for I2C MGC3130 Electric Field Sensor for Sonoff-Tasmota + xsns_36_MGC3130.ino - Support for I2C MGC3130 Electric Field Sensor for Tasmota Copyright (C) 2019 Christian Baars & Theo Arends diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index b5d3d6956..c3fb26a09 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -1,5 +1,5 @@ /* - xsns_37_rfsensor.ino - RF sensor receiver for Sonoff-Tasmota + xsns_37_rfsensor.ino - RF sensor receiver for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index e27a44bad..b1410bb5d 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -1,5 +1,5 @@ /* - xsns_38_az7798.ino - AZ_Instrument 7798 CO2/temperature/humidity meter support for Sonoff-Tasmota + xsns_38_az7798.ino - AZ_Instrument 7798 CO2/temperature/humidity meter support for Tasmota Copyright (C) 2019 Theo Arends @@ -38,7 +38,7 @@ * WeMos D1 Mini is powered from the incoming 5V. * * This implementation was derived from xsns_15_mhz19.ino from - * Sonoff-Tasmota-6.3.0 by Arthur de Beun. + * Tasmota-6.3.0 by Arthur de Beun. * * The serial comms protocol is not publicly documented, that I could find. * The info below was obtained by reverse-engineering. diff --git a/sonoff/xsns_39_max31855.ino b/sonoff/xsns_39_max31855.ino index 4f04c62db..22f649790 100644 --- a/sonoff/xsns_39_max31855.ino +++ b/sonoff/xsns_39_max31855.ino @@ -1,5 +1,5 @@ /* - xsns_39_max31855.ino - MAX31855 thermocouple sensor support for Sonoff-Tasmota + xsns_39_max31855.ino - MAX31855 thermocouple sensor support for Tasmota Copyright (C) 2019 Markus Past diff --git a/sonoff/xsns_40_pn532.ino b/sonoff/xsns_40_pn532.ino index 333ae7524..73f33929f 100644 --- a/sonoff/xsns_40_pn532.ino +++ b/sonoff/xsns_40_pn532.ino @@ -1,5 +1,5 @@ /* - xsns_40_pn532.ino - Support for PN532 (HSU) NFC Tag Reader + xsns_40_pn532.ino - Support for PN532 (HSU) NFC Tag Reader on Tasmota Copyright (C) 2019 Andre Thomas and Theo Arends diff --git a/sonoff/xsns_41_max44009.ino b/sonoff/xsns_41_max44009.ino index 28cca15ca..87045eda7 100644 --- a/sonoff/xsns_41_max44009.ino +++ b/sonoff/xsns_41_max44009.ino @@ -1,5 +1,5 @@ /* - xsns_41_max44009.ino - MAX44009 ambient light sensor support for Sonoff-Tasmota + xsns_41_max44009.ino - MAX44009 ambient light sensor support for Tasmota Copyright (C) 2019 Theo Arends diff --git a/sonoff/xsns_42_scd30.ino b/sonoff/xsns_42_scd30.ino index 2c8db00e4..5f629eb91 100644 --- a/sonoff/xsns_42_scd30.ino +++ b/sonoff/xsns_42_scd30.ino @@ -1,5 +1,5 @@ /* - xsns_42_scd30.ino - SC30 CO2 sensor support for Sonoff-Tasmota + xsns_42_scd30.ino - SC30 CO2 sensor support for Tasmota Copyright (C) 2019 Frogmore42 diff --git a/sonoff/xsns_44_sps30.ino b/sonoff/xsns_44_sps30.ino index 20dc8a8f0..3bc297661 100644 --- a/sonoff/xsns_44_sps30.ino +++ b/sonoff/xsns_44_sps30.ino @@ -1,5 +1,5 @@ /* - xsns_44_sps30.ino - Sensirion SPS30 + xsns_44_sps30.ino - Sensirion SPS30 support for Tasmota Copyright (C) 2019 Gerhard Mutz and Theo Arends diff --git a/sonoff/xsns_45_vl53l0x.ino b/sonoff/xsns_45_vl53l0x.ino index ce30460b7..e5e55c153 100755 --- a/sonoff/xsns_45_vl53l0x.ino +++ b/sonoff/xsns_45_vl53l0x.ino @@ -1,5 +1,5 @@ /* - xsns_99_vl53l0x.ino - VL53L0X + xsns_99_vl53l0x.ino - VL53L0X support for Tasmota Copyright (C) 2018 Theo Arends and Gerhard Mutz diff --git a/sonoff/xsns_47_max31865.ino b/sonoff/xsns_47_max31865.ino index 6383ecaa3..7416bb4a6 100644 --- a/sonoff/xsns_47_max31865.ino +++ b/sonoff/xsns_47_max31865.ino @@ -1,5 +1,5 @@ /* - xsns_39_MAX31865.ino - MAX31865 thermocouple sensor support for Sonoff-Tasmota + xsns_39_MAX31865.ino - MAX31865 thermocouple sensor support for Tasmota Copyright (C) 2019 Alberto Lopez Siemens diff --git a/sonoff/xsns_48_chirp.ino b/sonoff/xsns_48_chirp.ino index c2bf08f1d..57a086eae 100644 --- a/sonoff/xsns_48_chirp.ino +++ b/sonoff/xsns_48_chirp.ino @@ -1,5 +1,5 @@ /* - xsns_48_chirp.ino - soil moisture sensor support for Sonoff-Tasmota + xsns_48_chirp.ino - soil moisture sensor support for Tasmota Copyright (C) 2019 Theo Arends & Christian Baars @@ -27,7 +27,7 @@ added - now really support the (slower) CHIRP!-Sensor --- 1.0.0.0 20190608 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota - forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Tasmota base - code base from arendst and - https://github.com/Miceuz/i2c-moisture-sensor */ @@ -38,7 +38,7 @@ /*********************************************************************************************\ * CHIRP - Chirp!-sensor and I2C-soil-moisture-sensor * !! The I2C-soil-moisture-sensor is the preferred one !! - * + * * I2C Address: 0x20 - standard address, is changeable \*********************************************************************************************/ @@ -94,7 +94,7 @@ enum CHIRP_Commands { // commands useable in con void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg) { Wire.beginTransmission(addr); Wire.write(reg); - Wire.endTransmission(); + Wire.endTransmission(); } // now the original CHIRP needs 1100 ms delay uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr) { @@ -138,7 +138,7 @@ void ChirpReset(uint8_t addr) { void ChirpResetAll(void) { for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version) { + if (chirp_sensor[i].version) { ChirpReset(chirp_sensor[i].address); } } @@ -160,7 +160,7 @@ void ChirpSleep(uint8_t addr) { // void ChirpSleepAll(void) { // for (uint32_t i = 0; i < chirp_found_sensors; i++) { -// if (chirp_sensor[i].version) { +// if (chirp_sensor[i].version) { // ChirpSleep(chirp_sensor[i].address); // } // } @@ -170,7 +170,7 @@ void ChirpSleep(uint8_t addr) { // void ChirpAutoWakeAll(void) { // for (uint32_t i = 0; i < chirp_found_sensors; i++) { -// if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { +// if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { // ChirpReadVersion(chirp_sensor[i].address); // } // } @@ -200,8 +200,8 @@ bool ChirpSet(uint8_t addr) { if(addr < 128){ if (I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr)){ if(chirp_sensor[chirp_current].version>0x25 && chirp_sensor[chirp_current].version != 255){ - delay(5); - I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr); + delay(5); + I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr); // two calls are needed for sensor firmware version 2.6, but maybe dangerous before } DEBUG_SENSOR_LOG(PSTR("CHIRP: Wrote adress %u "), addr); @@ -231,7 +231,7 @@ bool ChirpScan() { delay(2); chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); if(chirp_sensor[chirp_found_sensors].version > 0) { - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "CHIRP:", address); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "CHIRP:", address); if(chirp_found_sensors no temperature - WSContentSend_PD(HTTP_SNS_TEMP, " ",str_temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_TEMP, " ",str_temperature, TempUnit()); } } - + #endif // USE_WEBSERVER } } - } + } } /*********************************************************************************************\ @@ -491,9 +491,9 @@ bool ChirpCmd(void) { else { if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(255); } //show active sensor Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); - } + } break; - case CMND_CHIRP_SCAN: + case CMND_CHIRP_SCAN: case CMND_CHIRP_SLEEP: case CMND_CHIRP_WAKE: case CMND_CHIRP_RESET: @@ -502,7 +502,7 @@ bool ChirpCmd(void) { if (command_code == CMND_CHIRP_SLEEP) { chirp_sensor[chirp_current].explicitSleep = true; // we do not touch this sensor in the read functions ChirpSleep(chirp_sensor[chirp_current].address); } if (command_code == CMND_CHIRP_WAKE) { chirp_sensor[chirp_current].explicitSleep = false; // back in action - ChirpReadVersion(chirp_sensor[chirp_current].address); } // just use read version as wakeup call + ChirpReadVersion(chirp_sensor[chirp_current].address); } // just use read version as wakeup call if (command_code == CMND_CHIRP_RESET) { ChirpReset(chirp_sensor[chirp_current].address); } Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); break; @@ -523,7 +523,7 @@ bool Xsns48(uint8_t function) { bool result = false; - if (i2c_flg) { + if (i2c_flg) { switch (function) { case FUNC_INIT: ChirpDetect(); // We can call CHIRPSCAN later to re-detect @@ -531,10 +531,10 @@ bool Xsns48(uint8_t function) case FUNC_EVERY_100_MSECOND: if(chirp_found_sensors > 0){ ChirpEvery100MSecond(); - } + } break; case FUNC_COMMAND: - result = ChirpCmd(); + result = ChirpCmd(); break; case FUNC_JSON_APPEND: ChirpShow(1); diff --git a/sonoff/xsns_50_paj7620.ino b/sonoff/xsns_50_paj7620.ino index 165d6b649..d12ba0900 100644 --- a/sonoff/xsns_50_paj7620.ino +++ b/sonoff/xsns_50_paj7620.ino @@ -1,5 +1,5 @@ /* - xsns_50_paj7620.ino - gesture sensor support for Sonoff-Tasmota + xsns_50_paj7620.ino - gesture sensor support for Tasmota Copyright (C) 2019 Theo Arends & Christian Baars @@ -23,7 +23,7 @@ --- 1.0.0.0 20190808 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota - forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Tasmota base - code base from arendst and - https://github.com/Seeed-Studio/Gesture_PAJ7620 */ @@ -33,7 +33,7 @@ /*********************************************************************************************\ * PAJ7620 - Gesture sensor - * + * * I2C Address: 0x73 - standard address \*********************************************************************************************/ @@ -43,7 +43,7 @@ #define PAJ7620_BANK_SEL 0xEF // 8 bit, write -> 0 or 1 -// the registers are organized in 2 banks +// the registers are organized in 2 banks // bank: 0 #define PAJ7620_GET_GESTURE 0x43 // 8 bit, read #define PAJ7620_PROXIMITY_AVG_Y 0x6c // 8 bit, read -> 255: near , lower numbers: far @@ -63,7 +63,7 @@ // bank: 1 // nothing at the moment -const uint8_t PAJ7620initRegisterArray[][2] PROGMEM = { // set all needed registers +const uint8_t PAJ7620initRegisterArray[][2] PROGMEM = { // set all needed registers {0xEF,0x00}, // bank 0 {0x32,0x29}, {0x33,0x01}, {0x34,0x00}, {0x35,0x01}, {0x36,0x00}, {0x37,0x07}, {0x38,0x17}, {0x39,0x06}, {0x3A,0x12}, {0x3F,0x00}, {0x40,0x02}, {0x41,0xFF}, {0x42,0x01}, {0x46,0x2D}, {0x47,0x0F}, {0x48,0x3C}, @@ -148,7 +148,7 @@ char PAJ7620_name[9]; uint32_t PAJ7620_timeout_counter = 10; // the time interval is 100 ms -> i.e. 10 is 1 second (= start up interval) uint32_t PAJ7620_next_job = 0; // 0 = detect, 1 = init, 2 = wait for gesture, 255 = sensor not found and do nothing -uint32_t PAJ7620_mode = 1; // 0 = mute, 1 = gestures only, 2 = gestures, 3 = corner, 4 = PIN, 5 = xy +uint32_t PAJ7620_mode = 1; // 0 = mute, 1 = gestures only, 2 = gestures, 3 = corner, 4 = PIN, 5 = xy struct { uint8_t current; @@ -160,7 +160,7 @@ struct { bool PAJ7620_finished_gesture = false; char PAJ7620_currentGestureName[6]; -struct{ +struct{ uint8_t x; uint8_t y; uint8_t last_x; @@ -279,7 +279,7 @@ void PAJ7620ReadGesture(void){ DEBUG_SENSOR_LOG(PSTR("PAJ7620: gesture: %u"),PAJ7620_gesture.current ); PAJ7620DecodeGesture(); } - + break; case 2: PAJ7620_state.proximity = I2cRead8(PAJ7620_ADDR, PAJ7620_PROXIMITY_AVG_Y); @@ -306,7 +306,7 @@ void PAJ7620ReadGesture(void){ // --- // 3|4 switch(PAJ7620_state.y){ - case 0: case 1: case 2: case 3: case 4: case 5:// case 0..5: would be nicer + case 0: case 1: case 2: case 3: case 4: case 5:// case 0..5: would be nicer PAJ7620_state.corner = 3; break; case 9: case 10: case 11: case 12: case 13: case 14: @@ -315,7 +315,7 @@ void PAJ7620ReadGesture(void){ default: break; } - if(PAJ7620_state.corner!=0){ + if(PAJ7620_state.corner!=0){ switch(PAJ7620_state.x){ case 0: case 1: case 2: case 3: case 4: case 5: break; @@ -373,7 +373,7 @@ void PAJ7620Detect(void) uint8_t PAJ7620_ver = I2cRead8(PAJ7620_ADDR,2); if (PAJ7620_id == 0x7620) { // this device ID makes sense ;) AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAJ7620: sensor found with ID: 0x%x and VER: %u"), PAJ7620_id, PAJ7620_ver); - uint8_t PAJ7620_model = 0; + uint8_t PAJ7620_model = 0; GetTextIndexed(PAJ7620_name, sizeof(PAJ7620_name), PAJ7620_model, kPAJ7620Types); PAJ7620_next_job = 1; // now init } @@ -391,7 +391,7 @@ void PAJ7620Init(void) uint32_t raw; uint8_t reg_val[4]; } buf; - for(uint32_t i = 0; i < (sizeof(PAJ7620initRegisterArray)/2); i+=2) + for(uint32_t i = 0; i < (sizeof(PAJ7620initRegisterArray)/2); i+=2) { buf.raw = pgm_read_dword(PAJ7620initRegisterArray+i); DEBUG_SENSOR_LOG("%x %x %x %x",buf.reg_val[0],buf.reg_val[1],buf.reg_val[2],buf.reg_val[3]); @@ -519,12 +519,12 @@ void PAJ7620Show(bool json) bool PAJ7620Cmd(void) { bool serviced = true; if (XdrvMailbox.data_len > 0) { - DEBUG_SENSOR_LOG(PSTR("PAJ7620: got argument for mode")); + DEBUG_SENSOR_LOG(PSTR("PAJ7620: got argument for mode")); PAJ7620SelectMode(XdrvMailbox.payload); //select mode Response_P(S_JSON_PAJ7620_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); } else { - DEBUG_SENSOR_LOG(PSTR("PAJ7620: show mode")); + DEBUG_SENSOR_LOG(PSTR("PAJ7620: show mode")); Response_P(S_JSON_PAJ7620_COMMAND_NVALUE, XdrvMailbox.command, PAJ7620_mode); } return serviced; @@ -538,15 +538,15 @@ bool Xsns50(uint8_t function) { bool result = false; - if (i2c_flg) { + if (i2c_flg) { switch (function) { case FUNC_INIT: - DEBUG_SENSOR_LOG(PSTR("PAJ7620: 1 second until init")); + DEBUG_SENSOR_LOG(PSTR("PAJ7620: 1 second until init")); break; case FUNC_COMMAND_SENSOR: if (XSNS_50 == XdrvMailbox.index){ result = PAJ7620Cmd(); - } + } break; case FUNC_EVERY_100_MSECOND: if(PAJ7620_next_job <255) { diff --git a/sonoff/xsns_51_rdm6300.ino b/sonoff/xsns_51_rdm6300.ino index 2a42b2a08..303799ed5 100644 --- a/sonoff/xsns_51_rdm6300.ino +++ b/sonoff/xsns_51_rdm6300.ino @@ -1,5 +1,5 @@ /* - xsns_51_rdm6300.ino - Support for RDM6300 NFC Tag Reader + xsns_51_rdm6300.ino - Support for RDM6300 NFC Tag Reader on Tasmota Copyright (C) 2019 Gerhard Mutz and Theo Arends diff --git a/sonoff/xsns_52_ibeacon.ino b/sonoff/xsns_52_ibeacon.ino index 1df541d82..f27ff3146 100644 --- a/sonoff/xsns_52_ibeacon.ino +++ b/sonoff/xsns_52_ibeacon.ino @@ -1,5 +1,5 @@ /* - xsns_52_ibeacon.ino - Support for HM17 BLE Module + ibeacon reader + xsns_52_ibeacon.ino - Support for HM17 BLE Module + ibeacon reader on Tasmota Copyright (C) 2019 Gerhard Mutz and Theo Arends diff --git a/sonoff/xsns_53_sml.ino b/sonoff/xsns_53_sml.ino index 158296e14..76c61b317 100644 --- a/sonoff/xsns_53_sml.ino +++ b/sonoff/xsns_53_sml.ino @@ -1,5 +1,5 @@ /* - xsns_53_sml.ino - SML,OBIS,EBUS,RAW,COUNTER interface for Sonoff-Tasmota + xsns_53_sml.ino - SML,OBIS,EBUS,RAW,COUNTER interface for Tasmota Created by Gerhard Mutz on 07.10.11. adapted for Tasmota diff --git a/sonoff/xsns_54_ina226.ino b/sonoff/xsns_54_ina226.ino index 9fc48c83b..b7129c557 100644 --- a/sonoff/xsns_54_ina226.ino +++ b/sonoff/xsns_54_ina226.ino @@ -1,5 +1,5 @@ /* - xsns_54_ina226.ino - INA226 Current Sensor support for Sonoff-Tasmota + xsns_54_ina226.ino - INA226 Current Sensor support for Tasmota Copyright (C) 2019 Stephen Rodgers and Theo Arends diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index cf469f930..222e3ecd6 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -1,5 +1,5 @@ /* - xsns_interface.ino - Sensor interface support for Sonoff-Tasmota + xsns_interface.ino - Sensor interface support for Tasmota Copyright (C) 2019 Theo Arends inspired by ESPEasy From 0e07397ff7be9200d91adb35b67d0627f09f6a3b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Oct 2019 12:04:08 +0100 Subject: [PATCH 041/196] Change Sonoff-Tasmota to Tasmota --- .github/ISSUE_TEMPLATE/Bug_report.md | 36 +- .github/ISSUE_TEMPLATE/Custom.md | 34 +- .github/PULL_REQUEST_TEMPLATE.md | 4 +- .gitignore | 2 +- API.md | 2 +- CONTRIBUTING.md | 8 +- Doxyfile | 126 +- README.md | 48 +- RELEASENOTES.md | 6 +- SUPPORT.md | 20 +- build-container/README.md | 20 +- lib/I2Cdevlib-MPU6050/MPU6050.cpp | 12 +- lib/I2Cdevlib-MPU6050/MPU6050.h | 32 +- .../MPU6050_6Axis_MotionApps20.h | 10 +- .../MPU6050_9Axis_MotionApps41.h | 26 +- lib/I2Cdevlib-MPU6050/helper_3dmath.h | 26 +- .../.github/ISSUE_TEMPLATE/bug_report.md | 34 + .../.github/ISSUE_TEMPLATE/feature_request.md | 20 + lib/TasmotaModbus-1.2.0/library.json | 2 +- lib/TasmotaSerial-2.4.1/library.json | 2 +- lib/readme.txt | 36 - platformio.ini | 2 +- {sonoff => tasmota}/Parsing.cpp | 1244 +++++++------- {sonoff => tasmota}/StackThunk_light.cpp | 0 {sonoff => tasmota}/StackThunk_light.h | 0 .../WiFiClientSecureLightBearSSL.cpp | 0 .../WiFiClientSecureLightBearSSL.h | 0 {sonoff => tasmota}/_changelog.ino | 6 +- {sonoff => tasmota}/core_esp8266_timer.c | 0 .../core_esp8266_wiring_digital.c | 0 {sonoff => tasmota}/core_esp8266_wiring_pwm.c | 0 {sonoff => tasmota}/i18n.h | 0 {sonoff => tasmota}/language/bg-BG.h | 0 {sonoff => tasmota}/language/cs-CZ.h | 0 {sonoff => tasmota}/language/de-DE.h | 0 {sonoff => tasmota}/language/el-GR.h | 0 {sonoff => tasmota}/language/en-GB.h | 0 {sonoff => tasmota}/language/es-ES.h | 0 {sonoff => tasmota}/language/fr-FR.h | 0 {sonoff => tasmota}/language/he-HE.h | 0 {sonoff => tasmota}/language/hu-HU.h | 0 {sonoff => tasmota}/language/it-IT.h | 0 {sonoff => tasmota}/language/ko-KO.h | 1454 ++++++++--------- {sonoff => tasmota}/language/nl-NL.h | 0 {sonoff => tasmota}/language/pl-PL.h | 0 {sonoff => tasmota}/language/pt-BR.h | 0 {sonoff => tasmota}/language/pt-PT.h | 0 {sonoff => tasmota}/language/ru-RU.h | 0 {sonoff => tasmota}/language/sk-SK.h | 0 {sonoff => tasmota}/language/sv-SE.h | 0 {sonoff => tasmota}/language/tr-TR.h | 0 {sonoff => tasmota}/language/uk-UK.h | 0 {sonoff => tasmota}/language/zh-CN.h | 0 {sonoff => tasmota}/language/zh-TW.h | 0 {sonoff => tasmota}/my_user_config.h | 18 +- {sonoff => tasmota}/sendemail.h | 0 {sonoff => tasmota}/sendemail.ino | 0 {sonoff => tasmota}/settings.h | 0 {sonoff => tasmota}/settings.ino | 0 {sonoff => tasmota}/support.ino | 0 {sonoff => tasmota}/support_button.ino | 0 {sonoff => tasmota}/support_command.ino | 0 {sonoff => tasmota}/support_features.ino | 0 {sonoff => tasmota}/support_float.ino | 0 {sonoff => tasmota}/support_rotary.ino | 0 {sonoff => tasmota}/support_rtc.ino | 0 {sonoff => tasmota}/support_static_buffer.ino | 0 {sonoff => tasmota}/support_switch.ino | 0 {sonoff => tasmota}/support_udp.ino | 0 {sonoff => tasmota}/support_wifi.ino | 0 sonoff/sonoff.h => tasmota/tasmota.h | 8 +- sonoff/sonoff.ino => tasmota/tasmota.ino | 14 +- .../sonoff_ca.ino => tasmota/tasmota_ca.ino | 2 +- .../sonoff_post.h => tasmota/tasmota_post.h | 8 +- .../tasmota_template.h | 8 +- .../tasmota_version.h | 8 +- .../user_config_override_sample.h | 0 {sonoff => tasmota}/xdrv_01_webserver.ino | 0 {sonoff => tasmota}/xdrv_02_mqtt.ino | 0 {sonoff => tasmota}/xdrv_03_energy.ino | 0 {sonoff => tasmota}/xdrv_04_light.ino | 0 {sonoff => tasmota}/xdrv_05_irremote.ino | 0 {sonoff => tasmota}/xdrv_05_irremote_full.ino | 0 {sonoff => tasmota}/xdrv_06_snfbridge.ino | 0 {sonoff => tasmota}/xdrv_07_domoticz.ino | 0 {sonoff => tasmota}/xdrv_08_serial_bridge.ino | 0 {sonoff => tasmota}/xdrv_09_timers.ino | 0 {sonoff => tasmota}/xdrv_10_rules.ino | 0 {sonoff => tasmota}/xdrv_10_scripter.ino | 0 {sonoff => tasmota}/xdrv_11_knx.ino | 0 .../xdrv_12_home_assistant.ino | 0 {sonoff => tasmota}/xdrv_13_display.ino | 0 {sonoff => tasmota}/xdrv_14_mp3.ino | 0 {sonoff => tasmota}/xdrv_15_pca9685.ino | 0 {sonoff => tasmota}/xdrv_16_tuyamcu.ino | 0 {sonoff => tasmota}/xdrv_17_rcswitch.ino | 0 .../xdrv_18_armtronix_dimmers.ino | 0 {sonoff => tasmota}/xdrv_19_ps16dz_dimmer.ino | 0 {sonoff => tasmota}/xdrv_20_hue.ino | 0 {sonoff => tasmota}/xdrv_21_wemo.ino | 0 {sonoff => tasmota}/xdrv_22_sonoff_ifan.ino | 0 .../xdrv_23_zigbee_0_constants.ino | 0 .../xdrv_23_zigbee_3_devices.ino | 0 .../xdrv_23_zigbee_5_converters.ino | 0 .../xdrv_23_zigbee_6_commands.ino | 0 .../xdrv_23_zigbee_7_statemachine.ino | 0 .../xdrv_23_zigbee_8_parsers.ino | 0 {sonoff => tasmota}/xdrv_23_zigbee_9_impl.ino | 0 {sonoff => tasmota}/xdrv_24_buzzer.ino | 0 {sonoff => tasmota}/xdrv_25_A4988_Stepper.ino | 0 {sonoff => tasmota}/xdrv_26_ariluxrf.ino | 0 {sonoff => tasmota}/xdrv_27_shutter.ino | 0 {sonoff => tasmota}/xdrv_28_pcf8574.ino | 0 {sonoff => tasmota}/xdrv_29_deepsleep.ino | 0 {sonoff => tasmota}/xdrv_30_exs_dimmer.ino | 0 {sonoff => tasmota}/xdrv_31_tasmota_slave.ino | 0 {sonoff => tasmota}/xdrv_99_debug.ino | 0 {sonoff => tasmota}/xdrv_interface.ino | 0 {sonoff => tasmota}/xdsp_01_lcd.ino | 0 {sonoff => tasmota}/xdsp_02_ssd1306.ino | 0 {sonoff => tasmota}/xdsp_03_matrix.ino | 0 {sonoff => tasmota}/xdsp_04_ili9341.ino | 0 {sonoff => tasmota}/xdsp_05_epaper_29.ino | 0 {sonoff => tasmota}/xdsp_06_epaper_42.ino | 0 {sonoff => tasmota}/xdsp_07_sh1106.ino | 0 {sonoff => tasmota}/xdsp_08_ILI9488.ino | 0 {sonoff => tasmota}/xdsp_09_SSD1351.ino | 0 {sonoff => tasmota}/xdsp_10_RA8876.ino | 0 {sonoff => tasmota}/xdsp_interface.ino | 0 {sonoff => tasmota}/xlgt_01_ws2812.ino | 0 {sonoff => tasmota}/xlgt_02_my92x1.ino | 0 {sonoff => tasmota}/xlgt_03_sm16716.ino | 0 {sonoff => tasmota}/xlgt_04_sm2135.ino | 0 {sonoff => tasmota}/xlgt_05_sonoff_l1.ino | 0 {sonoff => tasmota}/xlgt_interface.ino | 0 {sonoff => tasmota}/xnrg_01_hlw8012.ino | 0 {sonoff => tasmota}/xnrg_02_cse7766.ino | 0 {sonoff => tasmota}/xnrg_03_pzem004t.ino | 0 {sonoff => tasmota}/xnrg_04_mcp39f501.ino | 0 {sonoff => tasmota}/xnrg_05_pzem_ac.ino | 0 {sonoff => tasmota}/xnrg_06_pzem_dc.ino | 0 {sonoff => tasmota}/xnrg_07_ade7953.ino | 0 {sonoff => tasmota}/xnrg_08_sdm120.ino | 0 {sonoff => tasmota}/xnrg_09_dds2382.ino | 0 {sonoff => tasmota}/xnrg_10_sdm630.ino | 0 {sonoff => tasmota}/xnrg_11_ddsu666.ino | 0 {sonoff => tasmota}/xnrg_12_solaxX1.ino | 0 {sonoff => tasmota}/xnrg_interface.ino | 0 {sonoff => tasmota}/xsns_01_counter.ino | 0 {sonoff => tasmota}/xsns_02_analog.ino | 0 {sonoff => tasmota}/xsns_04_snfsc.ino | 0 {sonoff => tasmota}/xsns_05_ds18x20.ino | 0 {sonoff => tasmota}/xsns_06_dht.ino | 0 {sonoff => tasmota}/xsns_07_sht1x.ino | 0 {sonoff => tasmota}/xsns_08_htu21.ino | 0 {sonoff => tasmota}/xsns_09_bmp.ino | 0 {sonoff => tasmota}/xsns_10_bh1750.ino | 0 {sonoff => tasmota}/xsns_11_veml6070.ino | 0 {sonoff => tasmota}/xsns_12_ads1115.ino | 0 .../xsns_12_ads1115_i2cdev.ino | 0 {sonoff => tasmota}/xsns_13_ina219.ino | 0 {sonoff => tasmota}/xsns_14_sht3x.ino | 0 {sonoff => tasmota}/xsns_15_mhz19.ino | 0 {sonoff => tasmota}/xsns_16_tsl2561.ino | 0 {sonoff => tasmota}/xsns_17_senseair.ino | 0 {sonoff => tasmota}/xsns_18_pms5003.ino | 0 {sonoff => tasmota}/xsns_19_mgs.ino | 0 {sonoff => tasmota}/xsns_20_novasds.ino | 0 {sonoff => tasmota}/xsns_21_sgp30.ino | 0 {sonoff => tasmota}/xsns_22_sr04.ino | 0 {sonoff => tasmota}/xsns_24_si1145.ino | 0 {sonoff => tasmota}/xsns_26_lm75ad.ino | 0 {sonoff => tasmota}/xsns_27_apds9960.ino | 0 {sonoff => tasmota}/xsns_28_tm1638.ino | 0 {sonoff => tasmota}/xsns_29_mcp230xx.ino | 0 {sonoff => tasmota}/xsns_30_mpr121.ino | 0 {sonoff => tasmota}/xsns_31_ccs811.ino | 0 {sonoff => tasmota}/xsns_32_mpu6050.ino | 0 {sonoff => tasmota}/xsns_33_ds3231.ino | 0 {sonoff => tasmota}/xsns_34_hx711.ino | 0 {sonoff => tasmota}/xsns_35_tx20.ino | 0 {sonoff => tasmota}/xsns_36_mgc3130.ino | 0 {sonoff => tasmota}/xsns_37_rfsensor.ino | 0 {sonoff => tasmota}/xsns_38_az7798.ino | 0 {sonoff => tasmota}/xsns_39_max31855.ino | 0 {sonoff => tasmota}/xsns_40_pn532.ino | 0 {sonoff => tasmota}/xsns_41_max44009.ino | 0 {sonoff => tasmota}/xsns_42_scd30.ino | 0 {sonoff => tasmota}/xsns_43_hre.ino | 0 {sonoff => tasmota}/xsns_44_sps30.ino | 0 {sonoff => tasmota}/xsns_45_vl53l0x.ino | 0 {sonoff => tasmota}/xsns_46_MLX90614.ino | 0 {sonoff => tasmota}/xsns_47_max31865.ino | 0 {sonoff => tasmota}/xsns_48_chirp.ino | 0 {sonoff => tasmota}/xsns_50_paj7620.ino | 0 {sonoff => tasmota}/xsns_51_rdm6300.ino | 0 {sonoff => tasmota}/xsns_52_ibeacon.ino | 0 {sonoff => tasmota}/xsns_53_sml.ino | 0 {sonoff => tasmota}/xsns_54_ina226.ino | 0 {sonoff => tasmota}/xsns_interface.ino | 0 tools/decode-config.html | 56 +- tools/decode-config.md | 96 +- tools/decode-config.py | 92 +- tools/decode-status.py | 2 +- tools/fw_server/fw-server.py | 10 +- tools/fw_server/fw/README | 6 +- 206 files changed, 1779 insertions(+), 1761 deletions(-) create mode 100644 lib/NeoPixelBus-2.5.0.09/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 lib/NeoPixelBus-2.5.0.09/.github/ISSUE_TEMPLATE/feature_request.md delete mode 100644 lib/readme.txt rename {sonoff => tasmota}/Parsing.cpp (96%) rename {sonoff => tasmota}/StackThunk_light.cpp (100%) rename {sonoff => tasmota}/StackThunk_light.h (100%) rename {sonoff => tasmota}/WiFiClientSecureLightBearSSL.cpp (100%) rename {sonoff => tasmota}/WiFiClientSecureLightBearSSL.h (100%) rename {sonoff => tasmota}/_changelog.ino (99%) rename {sonoff => tasmota}/core_esp8266_timer.c (100%) rename {sonoff => tasmota}/core_esp8266_wiring_digital.c (100%) rename {sonoff => tasmota}/core_esp8266_wiring_pwm.c (100%) rename {sonoff => tasmota}/i18n.h (100%) rename {sonoff => tasmota}/language/bg-BG.h (100%) rename {sonoff => tasmota}/language/cs-CZ.h (100%) rename {sonoff => tasmota}/language/de-DE.h (100%) rename {sonoff => tasmota}/language/el-GR.h (100%) rename {sonoff => tasmota}/language/en-GB.h (100%) rename {sonoff => tasmota}/language/es-ES.h (100%) rename {sonoff => tasmota}/language/fr-FR.h (100%) rename {sonoff => tasmota}/language/he-HE.h (100%) rename {sonoff => tasmota}/language/hu-HU.h (100%) rename {sonoff => tasmota}/language/it-IT.h (100%) rename {sonoff => tasmota}/language/ko-KO.h (97%) rename {sonoff => tasmota}/language/nl-NL.h (100%) rename {sonoff => tasmota}/language/pl-PL.h (100%) rename {sonoff => tasmota}/language/pt-BR.h (100%) rename {sonoff => tasmota}/language/pt-PT.h (100%) rename {sonoff => tasmota}/language/ru-RU.h (100%) rename {sonoff => tasmota}/language/sk-SK.h (100%) rename {sonoff => tasmota}/language/sv-SE.h (100%) rename {sonoff => tasmota}/language/tr-TR.h (100%) mode change 100755 => 100644 rename {sonoff => tasmota}/language/uk-UK.h (100%) rename {sonoff => tasmota}/language/zh-CN.h (100%) rename {sonoff => tasmota}/language/zh-TW.h (100%) rename {sonoff => tasmota}/my_user_config.h (98%) rename {sonoff => tasmota}/sendemail.h (100%) mode change 100755 => 100644 rename {sonoff => tasmota}/sendemail.ino (100%) mode change 100755 => 100644 rename {sonoff => tasmota}/settings.h (100%) rename {sonoff => tasmota}/settings.ino (100%) rename {sonoff => tasmota}/support.ino (100%) rename {sonoff => tasmota}/support_button.ino (100%) rename {sonoff => tasmota}/support_command.ino (100%) rename {sonoff => tasmota}/support_features.ino (100%) rename {sonoff => tasmota}/support_float.ino (100%) rename {sonoff => tasmota}/support_rotary.ino (100%) rename {sonoff => tasmota}/support_rtc.ino (100%) rename {sonoff => tasmota}/support_static_buffer.ino (100%) rename {sonoff => tasmota}/support_switch.ino (100%) rename {sonoff => tasmota}/support_udp.ino (100%) rename {sonoff => tasmota}/support_wifi.ino (100%) rename sonoff/sonoff.h => tasmota/tasmota.h (99%) rename sonoff/sonoff.ino => tasmota/tasmota.ino (99%) mode change 100755 => 100644 rename sonoff/sonoff_ca.ino => tasmota/tasmota_ca.ino (98%) rename sonoff/sonoff_post.h => tasmota/tasmota_post.h (99%) rename sonoff/sonoff_template.h => tasmota/tasmota_template.h (99%) rename sonoff/sonoff_version.h => tasmota/tasmota_version.h (83%) rename {sonoff => tasmota}/user_config_override_sample.h (100%) rename {sonoff => tasmota}/xdrv_01_webserver.ino (100%) rename {sonoff => tasmota}/xdrv_02_mqtt.ino (100%) rename {sonoff => tasmota}/xdrv_03_energy.ino (100%) rename {sonoff => tasmota}/xdrv_04_light.ino (100%) rename {sonoff => tasmota}/xdrv_05_irremote.ino (100%) rename {sonoff => tasmota}/xdrv_05_irremote_full.ino (100%) rename {sonoff => tasmota}/xdrv_06_snfbridge.ino (100%) rename {sonoff => tasmota}/xdrv_07_domoticz.ino (100%) rename {sonoff => tasmota}/xdrv_08_serial_bridge.ino (100%) rename {sonoff => tasmota}/xdrv_09_timers.ino (100%) rename {sonoff => tasmota}/xdrv_10_rules.ino (100%) rename {sonoff => tasmota}/xdrv_10_scripter.ino (100%) rename {sonoff => tasmota}/xdrv_11_knx.ino (100%) rename {sonoff => tasmota}/xdrv_12_home_assistant.ino (100%) rename {sonoff => tasmota}/xdrv_13_display.ino (100%) mode change 100755 => 100644 rename {sonoff => tasmota}/xdrv_14_mp3.ino (100%) rename {sonoff => tasmota}/xdrv_15_pca9685.ino (100%) rename {sonoff => tasmota}/xdrv_16_tuyamcu.ino (100%) rename {sonoff => tasmota}/xdrv_17_rcswitch.ino (100%) rename {sonoff => tasmota}/xdrv_18_armtronix_dimmers.ino (100%) rename {sonoff => tasmota}/xdrv_19_ps16dz_dimmer.ino (100%) rename {sonoff => tasmota}/xdrv_20_hue.ino (100%) rename {sonoff => tasmota}/xdrv_21_wemo.ino (100%) rename {sonoff => tasmota}/xdrv_22_sonoff_ifan.ino (100%) rename {sonoff => tasmota}/xdrv_23_zigbee_0_constants.ino (100%) rename {sonoff => tasmota}/xdrv_23_zigbee_3_devices.ino (100%) rename {sonoff => tasmota}/xdrv_23_zigbee_5_converters.ino (100%) rename {sonoff => tasmota}/xdrv_23_zigbee_6_commands.ino (100%) rename {sonoff => tasmota}/xdrv_23_zigbee_7_statemachine.ino (100%) rename {sonoff => tasmota}/xdrv_23_zigbee_8_parsers.ino (100%) rename {sonoff => tasmota}/xdrv_23_zigbee_9_impl.ino (100%) rename {sonoff => tasmota}/xdrv_24_buzzer.ino (100%) rename {sonoff => tasmota}/xdrv_25_A4988_Stepper.ino (100%) rename {sonoff => tasmota}/xdrv_26_ariluxrf.ino (100%) rename {sonoff => tasmota}/xdrv_27_shutter.ino (100%) rename {sonoff => tasmota}/xdrv_28_pcf8574.ino (100%) rename {sonoff => tasmota}/xdrv_29_deepsleep.ino (100%) rename {sonoff => tasmota}/xdrv_30_exs_dimmer.ino (100%) rename {sonoff => tasmota}/xdrv_31_tasmota_slave.ino (100%) rename {sonoff => tasmota}/xdrv_99_debug.ino (100%) rename {sonoff => tasmota}/xdrv_interface.ino (100%) rename {sonoff => tasmota}/xdsp_01_lcd.ino (100%) rename {sonoff => tasmota}/xdsp_02_ssd1306.ino (100%) mode change 100755 => 100644 rename {sonoff => tasmota}/xdsp_03_matrix.ino (100%) rename {sonoff => tasmota}/xdsp_04_ili9341.ino (100%) rename {sonoff => tasmota}/xdsp_05_epaper_29.ino (100%) rename {sonoff => tasmota}/xdsp_06_epaper_42.ino (100%) rename {sonoff => tasmota}/xdsp_07_sh1106.ino (100%) rename {sonoff => tasmota}/xdsp_08_ILI9488.ino (100%) rename {sonoff => tasmota}/xdsp_09_SSD1351.ino (100%) rename {sonoff => tasmota}/xdsp_10_RA8876.ino (100%) rename {sonoff => tasmota}/xdsp_interface.ino (100%) rename {sonoff => tasmota}/xlgt_01_ws2812.ino (100%) rename {sonoff => tasmota}/xlgt_02_my92x1.ino (100%) rename {sonoff => tasmota}/xlgt_03_sm16716.ino (100%) rename {sonoff => tasmota}/xlgt_04_sm2135.ino (100%) rename {sonoff => tasmota}/xlgt_05_sonoff_l1.ino (100%) rename {sonoff => tasmota}/xlgt_interface.ino (100%) rename {sonoff => tasmota}/xnrg_01_hlw8012.ino (100%) rename {sonoff => tasmota}/xnrg_02_cse7766.ino (100%) rename {sonoff => tasmota}/xnrg_03_pzem004t.ino (100%) rename {sonoff => tasmota}/xnrg_04_mcp39f501.ino (100%) rename {sonoff => tasmota}/xnrg_05_pzem_ac.ino (100%) rename {sonoff => tasmota}/xnrg_06_pzem_dc.ino (100%) rename {sonoff => tasmota}/xnrg_07_ade7953.ino (100%) rename {sonoff => tasmota}/xnrg_08_sdm120.ino (100%) rename {sonoff => tasmota}/xnrg_09_dds2382.ino (100%) rename {sonoff => tasmota}/xnrg_10_sdm630.ino (100%) rename {sonoff => tasmota}/xnrg_11_ddsu666.ino (100%) rename {sonoff => tasmota}/xnrg_12_solaxX1.ino (100%) rename {sonoff => tasmota}/xnrg_interface.ino (100%) rename {sonoff => tasmota}/xsns_01_counter.ino (100%) rename {sonoff => tasmota}/xsns_02_analog.ino (100%) rename {sonoff => tasmota}/xsns_04_snfsc.ino (100%) rename {sonoff => tasmota}/xsns_05_ds18x20.ino (100%) rename {sonoff => tasmota}/xsns_06_dht.ino (100%) rename {sonoff => tasmota}/xsns_07_sht1x.ino (100%) rename {sonoff => tasmota}/xsns_08_htu21.ino (100%) rename {sonoff => tasmota}/xsns_09_bmp.ino (100%) mode change 100755 => 100644 rename {sonoff => tasmota}/xsns_10_bh1750.ino (100%) rename {sonoff => tasmota}/xsns_11_veml6070.ino (100%) rename {sonoff => tasmota}/xsns_12_ads1115.ino (100%) rename {sonoff => tasmota}/xsns_12_ads1115_i2cdev.ino (100%) rename {sonoff => tasmota}/xsns_13_ina219.ino (100%) rename {sonoff => tasmota}/xsns_14_sht3x.ino (100%) mode change 100755 => 100644 rename {sonoff => tasmota}/xsns_15_mhz19.ino (100%) rename {sonoff => tasmota}/xsns_16_tsl2561.ino (100%) rename {sonoff => tasmota}/xsns_17_senseair.ino (100%) rename {sonoff => tasmota}/xsns_18_pms5003.ino (100%) rename {sonoff => tasmota}/xsns_19_mgs.ino (100%) rename {sonoff => tasmota}/xsns_20_novasds.ino (100%) rename {sonoff => tasmota}/xsns_21_sgp30.ino (100%) rename {sonoff => tasmota}/xsns_22_sr04.ino (100%) rename {sonoff => tasmota}/xsns_24_si1145.ino (100%) rename {sonoff => tasmota}/xsns_26_lm75ad.ino (100%) rename {sonoff => tasmota}/xsns_27_apds9960.ino (100%) rename {sonoff => tasmota}/xsns_28_tm1638.ino (100%) rename {sonoff => tasmota}/xsns_29_mcp230xx.ino (100%) rename {sonoff => tasmota}/xsns_30_mpr121.ino (100%) rename {sonoff => tasmota}/xsns_31_ccs811.ino (100%) rename {sonoff => tasmota}/xsns_32_mpu6050.ino (100%) rename {sonoff => tasmota}/xsns_33_ds3231.ino (100%) rename {sonoff => tasmota}/xsns_34_hx711.ino (100%) rename {sonoff => tasmota}/xsns_35_tx20.ino (100%) rename {sonoff => tasmota}/xsns_36_mgc3130.ino (100%) rename {sonoff => tasmota}/xsns_37_rfsensor.ino (100%) rename {sonoff => tasmota}/xsns_38_az7798.ino (100%) rename {sonoff => tasmota}/xsns_39_max31855.ino (100%) rename {sonoff => tasmota}/xsns_40_pn532.ino (100%) rename {sonoff => tasmota}/xsns_41_max44009.ino (100%) rename {sonoff => tasmota}/xsns_42_scd30.ino (100%) rename {sonoff => tasmota}/xsns_43_hre.ino (100%) rename {sonoff => tasmota}/xsns_44_sps30.ino (100%) rename {sonoff => tasmota}/xsns_45_vl53l0x.ino (100%) mode change 100755 => 100644 rename {sonoff => tasmota}/xsns_46_MLX90614.ino (100%) rename {sonoff => tasmota}/xsns_47_max31865.ino (100%) rename {sonoff => tasmota}/xsns_48_chirp.ino (100%) rename {sonoff => tasmota}/xsns_50_paj7620.ino (100%) rename {sonoff => tasmota}/xsns_51_rdm6300.ino (100%) rename {sonoff => tasmota}/xsns_52_ibeacon.ino (100%) rename {sonoff => tasmota}/xsns_53_sml.ino (100%) rename {sonoff => tasmota}/xsns_54_ina226.ino (100%) rename {sonoff => tasmota}/xsns_interface.ino (100%) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 0d3d5f7f5..373d518cb 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -6,14 +6,14 @@ about: Create a report to help us improve > **GUIDE** > > This BUG issue template is meant to REPORT Tasmota software BUGS ONLY> -> +> > Please DO NOT OPEN AN ISSUE: -> - If your Tasmota version is not the latest from the development branch, please update your device before submitting your issue. Your problem might already be solved. The latest precompiled binaries of Tasmota can be downloaded from http://thehackbox.org/tasmota/ -> - If you have a issue when flashing was done via Tuya Convert -> - If your issue is a flashing issue, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) -> - If your issue is compilation problem, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) -> - If your issue has been addressed before (i.e., duplicated issue), please ask in the original issue -> - If your issue is a Wi-Fi problem or MQTT problem, please try the steps provided in the [FAQ](https://github.com/arendst/Sonoff-Tasmota/wiki/FAQ) and troubleshooting wiki articles +> - If your Tasmota version is not the latest from the development branch, please update your device before submitting your issue. Your problem might already be solved. The latest precompiled binaries of Tasmota can be downloaded from http://thehackbox.org/tasmota/ +> - If you have a issue when flashing was done via Tuya Convert +> - If your issue is a flashing issue, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) +> - If your issue is compilation problem, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) +> - If your issue has been addressed before (i.e., duplicated issue), please ask in the original issue +> - If your issue is a Wi-Fi problem or MQTT problem, please try the steps provided in the [FAQ](https://github.com/arendst/Tasmota/wiki/FAQ) and troubleshooting wiki articles > > Please take a few minutes to complete the requested information below. Our ability to provide assistance is greatly hampered without it. The details requested potentially affect which options to pursue. The small amount of time you spend completing the template will also help the volunteers providing the assistance to you to reduce the time required to help you. @@ -26,9 +26,9 @@ _Make sure your have performed every step and checked the applicable boxes befor **FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** -- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md) -- [ ] Searched the problem in [issues](https://github.com/arendst/Sonoff-Tasmota/issues) -- [ ] Searched the problem in the [wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting) +- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md) +- [ ] Searched the problem in [issues](https://github.com/arendst/Tasmota/issues) +- [ ] Searched the problem in the [wiki](https://github.com/arendst/Tasmota/wiki/Troubleshooting) - [ ] Searched the problem in the [forum](https://groups.google.com/d/forum/sonoffusers) - [ ] Searched the problem in the [chat](https://discord.gg/Ks2Kzd4) - [ ] Device used (e.g., Sonoff Basic): _____ @@ -40,27 +40,27 @@ _Make sure your have performed every step and checked the applicable boxes befor - [ ] Provide the output of command: ``Backlog Template; Module; GPIO``: ``` Configuration output here: - - + + ``` - [ ] If using rules, provide the output of this command: ``Backlog Rule1; Rule2; Rule3``: ``` Rules output here: - - + + ``` - [ ] Provide the output of this command: ``Status 0``: ``` STATUS 0 output here: - - + + ``` - [ ] Provide the output of the Console log output when you experience your issue; if applicable: _(Please use_ ``weblog 4`` _for more debug information)_ ``` Console output here: - - + + ``` ### TO REPRODUCE diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md index f0d6fafe0..3b30c5f18 100644 --- a/.github/ISSUE_TEMPLATE/Custom.md +++ b/.github/ISSUE_TEMPLATE/Custom.md @@ -3,33 +3,33 @@ name: Troubleshooting about: Users Troubleshooting Help --- -> **GUIDE** +> **GUIDE** > > This troubleshooting issue template is meant to help Tasmota users with difficult problems. It is aimed to be opened if using the wiki and the support chat could not solve the issue. The Github Issue tracker is NOT a general discussion forum! -> -> Please DO NOT OPEN AN ISSUE: +> +> Please DO NOT OPEN AN ISSUE: > - If you have general questions or you need help on Tasmota usage, go to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) -> - If your Tasmota version is not the latest from the development branch, please update your device before submitting your issue. Your problem might already be solved. The latest precompiled binaries of Tasmota can be downloaded from http://thehackbox.org/tasmota/ +> - If your Tasmota version is not the latest from the development branch, please update your device before submitting your issue. Your problem might already be solved. The latest precompiled binaries of Tasmota can be downloaded from http://thehackbox.org/tasmota/ > - If your issue is about a new device, please use the Tasmota [Template](../wiki/Templates) feature. > - If your issue is a flashing issue, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) > - If your issue is compilation problem, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) > - If your issue has been addressed before (i.e., duplicated issue), please ask in the original issue -> - If your issue is a Wi-Fi problem or MQTT problem, please try the steps provided in the [FAQ](https://github.com/arendst/Sonoff-Tasmota/wiki/FAQ) and troubleshooting wiki articles +> - If your issue is a Wi-Fi problem or MQTT problem, please try the steps provided in the [FAQ](https://github.com/arendst/Tasmota/wiki/FAQ) and troubleshooting wiki articles > > Please take a few minutes to complete the requested information below. Our ability to provide assistance is greatly hampered without it. The details requested potentially affect which options to pursue. The small amount of time you spend completing the template will also help the volunteers providing the assistance to you to reduce the time required to help you. ### ISSUE DESCRIPTION - TROUBLESHOOTING _A clear description of what the issue is and be as extensive as possible_ - + ### REQUESTED INFORMATION _Make sure these boxes are checked before submitting your issue. Thank you_ **FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** -- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md) -- [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues) -- [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting) +- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md) +- [ ] Searched the problem in issues (https://github.com/arendst/Tasmota/issues) +- [ ] Searched the problem in the wiki (https://github.com/arendst/Tasmota/wiki/Troubleshooting) - [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers) - [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4) - [ ] Device used (e.g., Sonoff Basic): _____ @@ -41,27 +41,27 @@ _Make sure these boxes are checked before submitting your issue. Thank you_ - [ ] Provide the output of this command: ``Backlog Template; Module; GPIO``: ``` Configuration output here: - - + + ``` - [ ] If using rules, provide the output of this command: ``Backlog Rule1; Rule2; Rule3``: ``` Rules output here: - - + + ``` - [ ] Provide the output of this command: ``Status 0``: ``` STATUS 0 output here: - - + + ``` - [ ] Provide the output of the Console log output when you experience your issue; if applicable: _(Please use_ ``weblog 4`` _for more debug information)_ ``` Console output here: - - + + ``` **(Please, remember to close the issue when the problem has been addressed)** diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 53b64f906..1dfaa83e5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ ## Description: -**Related issue (if applicable):** fixes # +**Related issue (if applicable):** fixes # ## Checklist: - [ ] The pull request is done against the latest dev branch @@ -8,4 +8,4 @@ - [ ] Only one feature/fix was added per PR. - [ ] The code change is tested and works on core pre-2.6 - [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass** - - [ ] I accept the [CLA](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla). + - [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla). diff --git a/.gitignore b/.gitignore index acdd5c610..ebf64d03f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ .clang_complete .gcc-flags.json .cache -sonoff/user_config_override.h +tasmota/user_config_override.h build firmware.map firmware.asm diff --git a/API.md b/API.md index dc3a7f6e3..ef74a1af6 100644 --- a/API.md +++ b/API.md @@ -2,7 +2,7 @@ # Basic API information -Sonoff-Tasmota can easily be extended by developers using provided function pointers as callback Ids. This document lists the available callback function Ids. See the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Sensor-API) for more information. +Tasmota can easily be extended by developers using provided function pointers as callback Ids. This document lists the available callback function Ids. See the wiki (https://github.com/arendst/Tasmota/wiki/Sensor-API) for more information. Callback availability can be checked by searching for either XdrvCall, XsnsCall, XdspCall and XnrgCall. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 96e1c3173..1bda5243a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,11 +4,11 @@ **Any contribution helps our team and makes Tasmota better for the entire community!** -Everybody is welcome and invited to contribute to Sonoff-Tasmota Project by: +Everybody is welcome and invited to contribute to Tasmota Project by: * Testing newly released features and reporting issues. * Providing Pull Requests (Features, Proof of Concepts, Language files or Fixes) -* Contributing missing documentation for features and devices on our [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Contributing) +* Contributing missing documentation for features and devices on our [Wiki](https://github.com/arendst/Tasmota/wiki/Contributing) This document describes rules that are in effect for this repository, meant for handling issues by contributors in the issue tracker and PRs. @@ -44,10 +44,10 @@ A Pull Request (PR) is the process where code modifications are managed in GitHu The process is straight-forward. - Read [How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) by Kubernetes (but skip step 0) - - Fork the Sonoff-Tasmota Repository [git repository](https://github.com/arendst/Sonoff-Tasmota). + - Fork the Tasmota Repository [git repository](https://github.com/arendst/Tasmota). - Write/Change the code in your Fork for a new feature, bug fix, new sensor, optimization, etc. - Ensure tests work. - - Create a Pull Request against the [**dev**](https://github.com/arendst/Sonoff-Tasmota/tree/dev) branch of Sonoff-Tasmota. + - Create a Pull Request against the [**dev**](https://github.com/arendst/Tasmota/tree/dev) branch of Tasmota. 1. All pull requests must be done against the dev branch. 2. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled). diff --git a/Doxyfile b/Doxyfile index 2df4d1c2c..0d2d7031d 100644 --- a/Doxyfile +++ b/Doxyfile @@ -32,13 +32,13 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = Sonoff-Tasmota +PROJECT_NAME = Tasmota # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = +PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -51,7 +51,7 @@ PROJECT_BRIEF = "Provide ESP8266 based itead Sonoff with Web, MQTT and # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = +PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is @@ -162,7 +162,7 @@ FULL_PATH_NAMES = NO # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -171,7 +171,7 @@ STRIP_FROM_PATH = # specify the list of include paths that are normally passed to the compiler # using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't @@ -250,7 +250,7 @@ ALIASES = "abstract=" \ # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. -TCL_SUBST = +TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For @@ -654,7 +654,7 @@ GENERATE_DEPRECATEDLIST= YES # sections, marked by \if ... \endif and \cond # ... \endcond blocks. -ENABLED_SECTIONS = +ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the @@ -696,7 +696,7 @@ SHOW_NAMESPACES = YES # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. -FILE_VERSION_FILTER = +FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated @@ -709,7 +709,7 @@ FILE_VERSION_FILTER = # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. -LAYOUT_FILE = +LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib @@ -719,7 +719,7 @@ LAYOUT_FILE = # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. -CITE_BIB_FILES = +CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages @@ -784,7 +784,7 @@ WARN_FORMAT = "$file:$line: $text" # messages should be written. If left blank the output is written to standard # error (stderr). -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files @@ -881,7 +881,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = +EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -908,13 +908,13 @@ EXCLUDE_PATTERNS = */.git* # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = +EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and @@ -934,7 +934,7 @@ EXAMPLE_RECURSIVE = NO # that contain images that are to be included in the documentation (see the # \image command). -IMAGE_PATH = +IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -955,7 +955,7 @@ IMAGE_PATH = # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. -INPUT_FILTER = +INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the @@ -968,7 +968,7 @@ INPUT_FILTER = # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. -FILTER_PATTERNS = +FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for @@ -983,14 +983,14 @@ FILTER_SOURCE_FILES = NO # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. -FILTER_SOURCE_PATTERNS = +FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -1102,7 +1102,7 @@ COLS_IN_ALPHA_INDEX = 5 # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. -IGNORE_PREFIX = +IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output @@ -1146,7 +1146,7 @@ HTML_FILE_EXTENSION = .xhtml # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_HEADER = +HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard @@ -1156,7 +1156,7 @@ HTML_HEADER = # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_FOOTER = +HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of @@ -1168,7 +1168,7 @@ HTML_FOOTER = # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_STYLESHEET = +HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets @@ -1181,7 +1181,7 @@ HTML_STYLESHEET = # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = +HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note @@ -1191,7 +1191,7 @@ HTML_EXTRA_STYLESHEET = # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_FILES = +HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to @@ -1331,7 +1331,7 @@ GENERATE_HTMLHELP = NO # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. -CHM_FILE = +CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, @@ -1339,7 +1339,7 @@ CHM_FILE = # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. -HHC_LOCATION = +HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the master .chm file (NO). @@ -1352,7 +1352,7 @@ GENERATE_CHI = NO # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. -CHM_INDEX_ENCODING = +CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it @@ -1383,7 +1383,7 @@ GENERATE_QHP = NO # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. -QCH_FILE = +QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace @@ -1406,28 +1406,28 @@ QHP_VIRTUAL_FOLDER = doc # Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_CUST_FILTER_ATTRS = +QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_SECT_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. -QHG_LOCATION = +QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To @@ -1560,7 +1560,7 @@ MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/ # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. -MATHJAX_EXTENSIONS = +MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site @@ -1568,7 +1568,7 @@ MATHJAX_EXTENSIONS = # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. -MATHJAX_CODEFILE = +MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and @@ -1628,7 +1628,7 @@ EXTERNAL_SEARCH = NO # Searching" for details. # This tag requires that the tag SEARCHENGINE is set to YES. -SEARCHENGINE_URL = +SEARCHENGINE_URL = # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed # search data is written to a file for indexing by an external tool. With the @@ -1644,7 +1644,7 @@ SEARCHDATA_FILE = searchdata.xml # projects and redirect the results back to the right project. # This tag requires that the tag SEARCHENGINE is set to YES. -EXTERNAL_SEARCH_ID = +EXTERNAL_SEARCH_ID = # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen # projects other than the one defined by this configuration file, but that are @@ -1654,7 +1654,7 @@ EXTERNAL_SEARCH_ID = # EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... # This tag requires that the tag SEARCHENGINE is set to YES. -EXTRA_SEARCH_MAPPINGS = +EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # Configuration options related to the LaTeX output @@ -1718,7 +1718,7 @@ PAPER_TYPE = a4 # If left blank no extra packages will be included. # This tag requires that the tag GENERATE_LATEX is set to YES. -EXTRA_PACKAGES = +EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for the # generated LaTeX document. The header should contain everything until the first @@ -1734,7 +1734,7 @@ EXTRA_PACKAGES = # to HTML_HEADER. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_HEADER = +LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the # generated LaTeX document. The footer should contain everything after the last @@ -1745,7 +1745,7 @@ LATEX_HEADER = # Note: Only use a user-defined footer if you know what you are doing! # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_FOOTER = +LATEX_FOOTER = # The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined # LaTeX style sheets that are included after the standard style sheets created @@ -1756,7 +1756,7 @@ LATEX_FOOTER = # list). # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_EXTRA_STYLESHEET = +LATEX_EXTRA_STYLESHEET = # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the LATEX_OUTPUT output @@ -1764,7 +1764,7 @@ LATEX_EXTRA_STYLESHEET = # markers available. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_EXTRA_FILES = +LATEX_EXTRA_FILES = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is # prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will @@ -1872,14 +1872,14 @@ RTF_HYPERLINKS = NO # default style sheet that doxygen normally uses. # This tag requires that the tag GENERATE_RTF is set to YES. -RTF_STYLESHEET_FILE = +RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is # similar to doxygen's config file. A template extensions file can be generated # using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. -RTF_EXTENSIONS_FILE = +RTF_EXTENSIONS_FILE = # If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code # with syntax highlighting in the RTF output. @@ -1924,7 +1924,7 @@ MAN_EXTENSION = .3 # MAN_EXTENSION with the initial . removed. # This tag requires that the tag GENERATE_MAN is set to YES. -MAN_SUBDIR = +MAN_SUBDIR = # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it # will generate one additional man file for each entity documented in the real @@ -2037,7 +2037,7 @@ PERLMOD_PRETTY = YES # overwrite each other's variables. # This tag requires that the tag GENERATE_PERLMOD is set to YES. -PERLMOD_MAKEVAR_PREFIX = +PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor @@ -2078,7 +2078,7 @@ SEARCH_INCLUDES = YES # preprocessor. # This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = +INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -2086,7 +2086,7 @@ INCLUDE_PATH = # used. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -INCLUDE_FILE_PATTERNS = +INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that are # defined before the preprocessor is started (similar to the -D option of e.g. @@ -2096,7 +2096,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = +PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2105,7 +2105,7 @@ PREDEFINED = # definition found in the source code. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_AS_DEFINED = +EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have @@ -2134,13 +2134,13 @@ SKIP_FUNCTION_MACROS = YES # the path). If a tag file is not located in the directory in which doxygen is # run, you must also specify the path to the tagfile here. -TAGFILES = +TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create a # tag file that is based on the input files it reads. See section "Linking to # external documentation" for more information about the usage of tag files. -GENERATE_TAGFILE = +GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES, all external class will be listed in # the class index. If set to NO, only the inherited external classes will be @@ -2189,14 +2189,14 @@ CLASS_DIAGRAMS = YES # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. -MSCGEN_PATH = +MSCGEN_PATH = # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The # DIA_PATH tag allows you to specify the directory where the dia binary resides. # If left empty dia is assumed to be found in the default search path. -DIA_PATH = +DIA_PATH = # If set to YES the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. @@ -2245,7 +2245,7 @@ DOT_FONTSIZE = 10 # the path where dot can find it using this tag. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTPATH = +DOT_FONTPATH = # If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for # each documented class showing the direct and indirect inheritance relations. @@ -2389,26 +2389,26 @@ INTERACTIVE_SVG = YES # found. If left blank, it is assumed the dot tool can be found in the path. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_PATH = +DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the \dotfile # command). # This tag requires that the tag HAVE_DOT is set to YES. -DOTFILE_DIRS = +DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the \mscfile # command). -MSCFILE_DIRS = +MSCFILE_DIRS = # The DIAFILE_DIRS tag can be used to specify one or more directories that # contain dia files that are included in the documentation (see the \diafile # command). -DIAFILE_DIRS = +DIAFILE_DIRS = # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the # path where java can find the plantuml.jar file. If left blank, it is assumed @@ -2416,17 +2416,17 @@ DIAFILE_DIRS = # generate a warning when it encounters a \startuml command in this case and # will not generate output for the diagram. -PLANTUML_JAR_PATH = +PLANTUML_JAR_PATH = # When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a # configuration file for plantuml. -PLANTUML_CFG_FILE = +PLANTUML_CFG_FILE = # When using plantuml, the specified paths are searched for files specified by # the !include statement in a plantuml block. -PLANTUML_INCLUDE_PATH = +PLANTUML_INCLUDE_PATH = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes # that will be shown in the graph. If the number of nodes in a graph becomes diff --git a/README.md b/README.md index a4b7482a5..e3435a83c 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,29 @@ Logo -# Sonoff-Tasmota +# Tasmota Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. -[![GitHub version](https://img.shields.io/github/release/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) -[![GitHub download](https://img.shields.io/github/downloads/arendst/Sonoff-Tasmota/total.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) -[![License](https://img.shields.io/github/license/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/blob/development/LICENSE.txt) +[![GitHub version](https://img.shields.io/github/release/arendst/Tasmota.svg)](https://github.com/arendst/Tasmota/releases/latest) +[![GitHub download](https://img.shields.io/github/downloads/arendst/Tasmota/total.svg)](https://github.com/arendst/Tasmota/releases/latest) +[![License](https://img.shields.io/github/license/arendst/Tasmota.svg)](https://github.com/arendst/Tasmota/blob/development/LICENSE.txt) [![Chat](https://img.shields.io/discord/479389167382691863.svg)](https://discord.gg/Ks2Kzd4) -If you like **Sonoff-Tasmota**, give it a star, or fork it, and contribute! +If you like **Tasmota**, give it a star, or fork it, and contribute! -[![GitHub stars](https://img.shields.io/github/stars/arendst/Sonoff-Tasmota.svg?style=social&label=Star)](https://github.com/arendst/Sonoff-Tasmota/stargazers) -[![GitHub forks](https://img.shields.io/github/forks/arendst/Sonoff-Tasmota.svg?style=social&label=Fork)](https://github.com/arendst/Sonoff-Tasmota/network) +[![GitHub stars](https://img.shields.io/github/stars/arendst/Tasmota.svg?style=social&label=Star)](https://github.com/arendst/Tasmota/stargazers) +[![GitHub forks](https://img.shields.io/github/forks/arendst/Tasmota.svg?style=social&label=Fork)](https://github.com/arendst/Tasmota/network) [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/tasmota) -See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development/RELEASENOTES.md) for release information. +See [RELEASENOTES.md](https://github.com/arendst/Tasmota/blob/development/RELEASENOTES.md) for release information. -In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest) the binaries can also be downloaded from http://thehackbox.org/tasmota/release/ +In addition to the [release webpage](https://github.com/arendst/Tasmota/releases/latest) the binaries can also be downloaded from http://thehackbox.org/tasmota/release/ ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v6.7.1.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v6.7.1.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) -[![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota) +[![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota) -See [sonoff/_changelog.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_changelog.ino) for detailed change information. +See [sonoff/_changelog.ino](https://github.com/arendst/Tasmota/blob/development/sonoff/_changelog.ino) for detailed change information. Unless your Tasmota powered device exhibits a problem or you need to make use of a feature that is not available in the Tasmota version currently installed on your device, leave your device alone - it works so don't make unnecessary changes! If the release version (i.e., the master branch) exhibits unexpected behaviour for your device and configuration, you should upgrade to the latest development version instead to see if your problem is resolved as some bugs in previous releases or development builds may already have been resolved. @@ -39,23 +39,23 @@ An ESP82xx Wi-Fi device is not a toy. It uses Mains AC so there is a danger of e We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. ## Note -Please do not ask to add new devices unless it requires additional code for new features. If the device is not listed as a module, try using [Templates](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates) first. If it is not listed in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) create your own [Template](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates#creating-your-template-). +Please do not ask to add new devices unless it requires additional code for new features. If the device is not listed as a module, try using [Templates](https://github.com/arendst/Tasmota/wiki/Templates) first. If it is not listed in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) create your own [Template](https://github.com/arendst/Tasmota/wiki/Templates#creating-your-template-). ## Quick Install -Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as [documented in the wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Flashing). +Download one of the released binaries from https://github.com/arendst/Tasmota/releases and flash it to your hardware as [documented in the wiki](https://github.com/arendst/Tasmota/wiki/Flashing). ## Important User Compilation Information -If you want to compile Sonoff-Tasmota yourself keep in mind the following: +If you want to compile Tasmota yourself keep in mind the following: -- Only Flash Mode **DOUT** is supported. Do not use Flash Mode DIO / QIO / QOUT as it might seem to brick your device. See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Flashing) for background information. -- Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. -- To make compile time changes to Sonoff-Tasmota it can use the ``user_config_override.h`` file. It assures keeping your settings when you download and compile a new version. To use ``user_config.override.h`` you will have to make a copy of the provided ``user_config_override_sample.h`` file and add your setting overrides. To enable the override file you will need to use a compile define as documented in the ``user_config_override_sample.h`` file. +- Only Flash Mode **DOUT** is supported. Do not use Flash Mode DIO / QIO / QOUT as it might seem to brick your device. See [Wiki](https://github.com/arendst/Tasmota/wiki/Flashing) for background information. +- Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. +- To make compile time changes to Tasmota it can use the ``user_config_override.h`` file. It assures keeping your settings when you download and compile a new version. To use ``user_config.override.h`` you will have to make a copy of the provided ``user_config_override_sample.h`` file and add your setting overrides. To enable the override file you will need to use a compile define as documented in the ``user_config_override_sample.h`` file. ## Configuration Information -Please refer to the Installation and configuration articles in the [wiki](https://github.com/arendst/Sonoff-Tasmota/wiki). +Please refer to the Installation and configuration articles in the [wiki](https://github.com/arendst/Tasmota/wiki). ## Migration Information -See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: +See [wiki migration path](https://github.com/arendst/Tasmota/wiki/Upgrade#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: 1. Migrate to **Sonoff-Tasmota 3.9.x** 2. Migrate to **Sonoff-Tasmota 4.x** @@ -67,23 +67,23 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade For a database of supported devices see [Tasmota Device Templates Repository](https://blakadder.github.io/templates) -See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for use instructions and how-to's.
+See [Wiki](https://github.com/arendst/Tasmota/wiki) for use instructions and how-to's.
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.
Visit [Discord Chat](https://discord.gg/Ks2Kzd4) for discussions and troubleshooting. ## Contribute -You can contribute to Sonoff-Tasmota by +You can contribute to Tasmota by - providing Pull Requests (Features, Proof of Concepts, Language files or Fixes) - testing new released features and report issues - donating to acquire hardware for testing and implementing or out of gratitude -- contributing missing documentation for features and devices on our [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) +- contributing missing documentation for features and devices on our [Wiki](https://github.com/arendst/Tasmota/wiki) [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/tasmota) ## Credits ### Libraries Used -Libraries used with Sonoff-Tasmota are: +Libraries used with Tasmota are: - [ESP8266 core for Arduino](https://github.com/esp8266/Arduino) - [Adafruit CCS811](https://github.com/adafruit/Adafruit_CCS811) - [Adafruit ILI9341](https://github.com/adafruit/Adafruit_ILI9341) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 747baccca..86abd9678 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,9 +1,9 @@ -Logo +Logo # RELEASE NOTES ## Migration Information -See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: +See [wiki migration path](https://github.com/arendst/Tasmota/wiki/Upgrade#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: 1. Migrate to **Sonoff-Tasmota 3.9.x** 2. Migrate to **Sonoff-Tasmota 4.x** @@ -16,7 +16,7 @@ This release will be supported from ESP8266/Arduino library Core version **pre-2 Although it might still compile on previous Core versions all support will be removed starting in the next Release. ## Support of TLS -To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. See full documentation on https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT +To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. See full documentation on https://github.com/arendst/Tasmota/wiki/AWS-IoT ## Initial configuration tools For initial configuration this release supports Webserver based **WifiManager** or **Serial** based command interface only. Support for **WPS** and **SmartConfig** has been removed. diff --git a/SUPPORT.md b/SUPPORT.md index 389c03002..ab4bc743a 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -2,24 +2,24 @@ # Support -If you're looking for support on **Sonoff-Tasmota** there are some options available: +If you're looking for support on **Tasmota** there are some options available: ## Documentation: -* [Wiki Pages](https://github.com/arendst/Sonoff-Tasmota/wiki): For information on how to Flash Tasmota, configure and use it. -* [FAQ](https://github.com/arendst/Sonoff-Tasmota/wiki/FAQ): For information on common problems and solutions. -* [Troubleshooting Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting): For ways to debug and troubleshoot. -* [Commands Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands): For information on all the commands supported by Tasmota. +* [Wiki Pages](https://github.com/arendst/Tasmota/wiki): For information on how to Flash Tasmota, configure and use it. +* [FAQ](https://github.com/arendst/Tasmota/wiki/FAQ): For information on common problems and solutions. +* [Troubleshooting Information](https://github.com/arendst/Tasmota/wiki/Troubleshooting): For ways to debug and troubleshoot. +* [Commands Information](https://github.com/arendst/Tasmota/wiki/Commands): For information on all the commands supported by Tasmota. ## Support's Community: * [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions. * [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community. -* [Search in Issues](https://github.com/arendst/Sonoff-Tasmota/issues): You might find an answer to your question by searching current or closed issues. +* [Search in Issues](https://github.com/arendst/Tasmota/issues): You might find an answer to your question by searching current or closed issues. ## Developers' Community: -* [Bug Report](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software. -* [Feature Request](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software. -* [Troubleshooting](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Custom.md): As a last resort, you can open new *Troubleshooting* issue on GitHub if the solution could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. -* [Issue a question](https://github.com/arendst/Sonoff-Tasmota/issues/new/choose): As a last resort, you can open a new *Question* issue on GitHub if the answer could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. +* [Bug Report](https://github.com/arendst/Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software. +* [Feature Request](https://github.com/arendst/Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software. +* [Troubleshooting](https://github.com/arendst/Tasmota/issues/new?template=Custom.md): As a last resort, you can open new *Troubleshooting* issue on GitHub if the solution could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. +* [Issue a question](https://github.com/arendst/Tasmota/issues/new/choose): As a last resort, you can open a new *Question* issue on GitHub if the answer could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. diff --git a/build-container/README.md b/build-container/README.md index a02f1860e..b89a84892 100644 --- a/build-container/README.md +++ b/build-container/README.md @@ -1,5 +1,5 @@ # Docker container for tasmota builds -This Container will setup a proper build environment for [Sonoff-Tasmota](https://github.com/arendst/Sonoff-Tasmota) +This Container will setup a proper build environment for [Tasmota](https://github.com/arendst/Tasmota) ## Create container `docker build -t mytasmota:latest .` @@ -8,19 +8,19 @@ This Container will setup a proper build environment for [Sonoff-Tasmota](https: Use instead of the container `mytasmota:latest` the published container `eddyhub/docker-tasmota:latest` from docker hub. ## Build all development binaries -`git clone https://github.com/arendst/Sonoff-Tasmota.git` -`docker run -ti --rm -v $(pwd)/Sonoff-Tasmota:/tasmota -u $UID:$GID mytasmota:latest` +`git clone https://github.com/arendst/Tasmota.git` +`docker run -ti --rm -v $(pwd)/Tasmota:/tasmota -u $UID:$GID mytasmota:latest` ## Build a specific binary with custom options -Checkout Sonoff-Tasmota: `git clone https://github.com/arendst/Sonoff-Tasmota.git` -Mount the source as volume in `/tasmota`. **Prefix** any parameter available in `Sonoff-Tasmota/sonoff/my_user_config.h` with `TASMOTA_` as a environment variable for the container. **Also don't forget to escape what needs to be escaped in your shell.** **Strings** should be in **double quotes**. My config example: -`docker run -ti --rm -v $(pwd)/Sonoff-Tasmota:/tasmota -e TASMOTA_STA_SSID1='"my-wifi"' -e TASMOTA_STA_PASS1='"my-wifi-password"' -e TASMOTA_MQTT_HOST='my-mqtt-host' -e TASMOTA_MQTT_USER='"my-mqtt-user"' -e TASMOTA_MQTT_PASS='"my-mqtt-password"' -e TASMOTA_WEB_PASSWORD='"my-web-password"' -u $UID:$GID mytasmota:latest --environment sonoff-DE +Checkout Tasmota: `git clone https://github.com/arendst/Tasmota.git` +Mount the source as volume in `/tasmota`. **Prefix** any parameter available in `Tasmota/sonoff/my_user_config.h` with `TASMOTA_` as a environment variable for the container. **Also don't forget to escape what needs to be escaped in your shell.** **Strings** should be in **double quotes**. My config example: +`docker run -ti --rm -v $(pwd)/Tasmota:/tasmota -e TASMOTA_STA_SSID1='"my-wifi"' -e TASMOTA_STA_PASS1='"my-wifi-password"' -e TASMOTA_MQTT_HOST='my-mqtt-host' -e TASMOTA_MQTT_USER='"my-mqtt-user"' -e TASMOTA_MQTT_PASS='"my-mqtt-password"' -e TASMOTA_WEB_PASSWORD='"my-web-password"' -u $UID:$GID mytasmota:latest --environment sonoff-DE -Now you should have the file Sonoff-Tasmota/.pioenvs/sonoff-DE/firmware.bin which can be flashed on your device. +Now you should have the file Tasmota/.pioenvs/sonoff-DE/firmware.bin which can be flashed on your device. ## Build a specific version of tasmota Checkout out the needed version before using the build instructions above: -- `git clone https://github.com/arendst/Sonoff-Tasmota.git` -- `git -C Sonoff-Tasmota checkout v6.6.0` +- `git clone https://github.com/arendst/Tasmota.git` +- `git -C Tasmota checkout v6.6.0` Build it: -- `docker run -ti --rm -v $(pwd)/Sonoff-Tasmota:/tasmota -u $UID:$GID mytasmota:latest` +- `docker run -ti --rm -v $(pwd)/Tasmota:/tasmota -u $UID:$GID mytasmota:latest` diff --git a/lib/I2Cdevlib-MPU6050/MPU6050.cpp b/lib/I2Cdevlib-MPU6050/MPU6050.cpp index 378a2c0ab..6b1466139 100644 --- a/lib/I2Cdevlib-MPU6050/MPU6050.cpp +++ b/lib/I2Cdevlib-MPU6050/MPU6050.cpp @@ -3,7 +3,7 @@ // 8/24/2011 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // -// Adapted for Sonoff-Tasmota by Oliver Welter 02-04-2018 +// Adapted for Tasmota by Oliver Welter 02-04-2018 // // Changelog: // ... - ongoing debug release @@ -871,7 +871,7 @@ void MPU6050::setMasterClockSpeed(uint8_t speed) { * operation, and if it is cleared, then it's a write operation. The remaining * bits (6-0) are the 7-bit device address of the slave device. * - * In read mode, the result of the read is placed in the lowest available + * In read mode, the result of the read is placed in the lowest available * EXT_SENS_DATA register. For further information regarding the allocation of * read results, please refer to the EXT_SENS_DATA register description * (Registers 73 - 96). @@ -2957,7 +2957,7 @@ void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, ui // read the chunk of data as specified I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i); - + // increase byte index by [chunkSize] i += chunkSize; @@ -2991,7 +2991,7 @@ bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t b // make sure this chunk doesn't go past the bank boundary (256 bytes) if (chunkSize > 256 - address) chunkSize = 256 - address; - + if (useProgMem) { // write the chunk of data as specified for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j); @@ -3105,7 +3105,7 @@ bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, b Serial.println(" found...");*/ if (special == 0x01) { // enable DMP-related interrupts - + //setIntZeroMotionEnabled(true); //setIntFIFOBufferOverflowEnabled(true); //setIntDMPEnabled(true); @@ -3117,7 +3117,7 @@ bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, b success = false; } } - + if (!success) { if (useProgMem) free(progBuffer); return false; // uh oh diff --git a/lib/I2Cdevlib-MPU6050/MPU6050.h b/lib/I2Cdevlib-MPU6050/MPU6050.h index 2d7dfd7b4..669743e63 100644 --- a/lib/I2Cdevlib-MPU6050/MPU6050.h +++ b/lib/I2Cdevlib-MPU6050/MPU6050.h @@ -4,7 +4,7 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // -// Adapted for Sonoff-Tasmota by Oliver Welter 02-04-2018 +// Adapted for Tasmota by Oliver Welter 02-04-2018 // // Changelog: // ... - ongoing debug release @@ -408,7 +408,7 @@ class MPU6050 { void initialize(); bool testConnection(); - + // Patch for Tasmota void setAddr(uint8_t address); @@ -682,9 +682,9 @@ class MPU6050 { // WHO_AM_I register uint8_t getDeviceID(); void setDeviceID(uint8_t id); - + // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== - + // XG_OFFS_TC register uint8_t getOTPBankValid(); void setOTPBankValid(bool enabled); @@ -734,13 +734,13 @@ class MPU6050 { // ZG_OFFS_USR* register int16_t getZGyroOffset(); void setZGyroOffset(int16_t offset); - + // INT_ENABLE register (DMP functions) bool getIntPLLReadyEnabled(); void setIntPLLReadyEnabled(bool enabled); bool getIntDMPEnabled(); void setIntDMPEnabled(bool enabled); - + // DMP_INT_STATUS bool getDMPInt5Status(); bool getDMPInt4Status(); @@ -752,18 +752,18 @@ class MPU6050 { // INT_STATUS register (DMP functions) bool getIntPLLReadyStatus(); bool getIntDMPStatus(); - + // USER_CTRL register (DMP functions) bool getDMPEnabled(); void setDMPEnabled(bool enabled); void resetDMP(); - + // BANK_SEL register void setMemoryBank(uint8_t bank, bool prefetchEnabled=false, bool userBank=false); - + // MEM_START_ADDR register void setMemoryStartAddress(uint8_t address); - + // MEM_R_W register uint8_t readMemoryByte(); void writeMemoryByte(uint8_t data); @@ -795,12 +795,12 @@ class MPU6050 { uint8_t dmpGetSampleStepSizeMS(); uint8_t dmpGetSampleFrequency(); int32_t dmpDecodeTemperature(int8_t tempReg); - + // Register callbacks after a packet of FIFO data is processed //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); uint8_t dmpRunFIFORateProcesses(); - + // Setup FIFO for various output uint8_t dmpSendQuaternion(uint_fast16_t accuracy); uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); @@ -860,7 +860,7 @@ class MPU6050 { uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); - + uint8_t dmpGetEuler(float *data, Quaternion *q); uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); @@ -896,12 +896,12 @@ class MPU6050 { uint8_t dmpGetSampleStepSizeMS(); uint8_t dmpGetSampleFrequency(); int32_t dmpDecodeTemperature(int8_t tempReg); - + // Register callbacks after a packet of FIFO data is processed //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); uint8_t dmpRunFIFORateProcesses(); - + // Setup FIFO for various output uint8_t dmpSendQuaternion(uint_fast16_t accuracy); uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); @@ -962,7 +962,7 @@ class MPU6050 { uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); - + uint8_t dmpGetEuler(float *data, Quaternion *q); uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); diff --git a/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h b/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h index 90704f0c7..69ab1b968 100644 --- a/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h @@ -3,7 +3,7 @@ // 5/20/2013 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // -// Adapted for Sonoff-Tasmota by Oliver Welter 02-04-2018 +// Adapted for Tasmota by Oliver Welter 02-04-2018 // // Changelog: // ... - ongoing debug release @@ -71,16 +71,16 @@ THE SOFTWARE. typedef uint16_t prog_uint16_t; typedef int32_t prog_int32_t; typedef uint32_t prog_uint32_t; - + #define strcpy_P(dest, src) strcpy((dest), (src)) #define strcat_P(dest, src) strcat((dest), (src)) #define strcmp_P(a, b) strcmp((a), (b)) - + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) #define pgm_read_word(addr) (*(const unsigned short *)(addr)) #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) #define pgm_read_float(addr) (*(const float *)(addr)) - + #define pgm_read_byte_near(addr) pgm_read_byte(addr) #define pgm_read_word_near(addr) pgm_read_word(addr) #define pgm_read_dword_near(addr) pgm_read_dword(addr) @@ -732,7 +732,7 @@ uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *proces // process packet if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; - + // increment external process count variable, if supplied if (processed != 0) *processed++; } diff --git a/lib/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h b/lib/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h index 73f3dff9d..f4a88b433 100644 --- a/lib/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/lib/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h @@ -3,7 +3,7 @@ // 6/18/2012 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // -// Adapted for Sonoff-Tasmota by Oliver Welter 02-04-2018 +// Adapted for Tasmota by Oliver Welter 02-04-2018 // // Changelog: // ... - ongoing debug release @@ -67,16 +67,16 @@ THE SOFTWARE. typedef uint16_t prog_uint16_t; typedef int32_t prog_int32_t; typedef uint32_t prog_uint32_t; - + #define strcpy_P(dest, src) strcpy((dest), (src)) #define strcat_P(dest, src) strcat((dest), (src)) #define strcmp_P(a, b) strcmp((a), (b)) - + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) #define pgm_read_word(addr) (*(const unsigned short *)(addr)) #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) #define pgm_read_float(addr) (*(const float *)(addr)) - + #define pgm_read_byte_near(addr) pgm_read_byte(addr) #define pgm_read_word_near(addr) pgm_read_word(addr) #define pgm_read_dword_near(addr) pgm_read_dword(addr) @@ -159,7 +159,7 @@ const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, - + // bank 2, 256 bytes 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, @@ -177,7 +177,7 @@ const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x78, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - + // bank 3, 256 bytes 0xD8, 0xDC, 0xF4, 0xD8, 0xB9, 0xAB, 0xF3, 0xF8, 0xFA, 0xF1, 0xBA, 0xA2, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x98, 0xF7, 0x4A, 0x90, 0x7F, 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, @@ -195,7 +195,7 @@ const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xF0, 0x00, 0x28, 0x50, 0xF5, 0xBA, 0xAD, 0x8F, 0x9F, 0x28, 0x54, 0x7C, 0xB9, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xDB, 0xB2, 0xB6, 0x8E, 0x9D, 0xAE, 0xF5, 0x60, 0x68, 0x70, 0xB1, 0xB5, 0xF1, 0xDA, 0xA6, 0xDF, 0xD9, 0xA6, 0xFA, 0xA3, 0x86, - + // bank 4, 256 bytes 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, @@ -213,7 +213,7 @@ const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, - + // bank 5, 256 bytes 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, @@ -249,7 +249,7 @@ const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0x81, 0xAD, 0xD9, 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD, 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E, 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, - + // bank 7, 170 bytes (remainder) 0x30, 0x18, 0xA8, 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89, 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, @@ -381,9 +381,9 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(ygOffset); DEBUG_PRINT(F("Z gyro offset = ")); DEBUG_PRINTLN(zgOffset); - + I2Cdev::readByte(devAddr, MPU6050_RA_USER_CTRL, buffer); // ? - + DEBUG_PRINTLN(F("Enabling interrupt latch, clear on any read, AUX bypass enabled")); I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x32); @@ -572,7 +572,7 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Writing final memory update 11/19 (function unknown)...")); for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - + DEBUG_PRINTLN(F("Reading final memory update 12/19 (function unknown)...")); for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); @@ -831,7 +831,7 @@ uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *proces // process packet if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; - + // increment external process count variable, if supplied if (processed != 0) *processed++; } diff --git a/lib/I2Cdevlib-MPU6050/helper_3dmath.h b/lib/I2Cdevlib-MPU6050/helper_3dmath.h index 5dafb54cf..b49aa801a 100644 --- a/lib/I2Cdevlib-MPU6050/helper_3dmath.h +++ b/lib/I2Cdevlib-MPU6050/helper_3dmath.h @@ -2,7 +2,7 @@ // 6/5/2012 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // -// Adapted for Sonoff-Tasmota by Oliver Welter 02-04-2018 +// Adapted for Tasmota by Oliver Welter 02-04-2018 // // Changelog: // 2012-06-05 - add 3D math helper file to DMP6 example sketch @@ -40,14 +40,14 @@ class Quaternion { float x; float y; float z; - + Quaternion() { w = 1.0f; x = 0.0f; y = 0.0f; z = 0.0f; } - + Quaternion(float nw, float nx, float ny, float nz) { w = nw; x = nx; @@ -71,11 +71,11 @@ class Quaternion { Quaternion getConjugate() { return Quaternion(w, -x, -y, -z); } - + float getMagnitude() { return sqrt(w*w + x*x + y*y + z*z); } - + void normalize() { float m = getMagnitude(); w /= m; @@ -83,7 +83,7 @@ class Quaternion { y /= m; z /= m; } - + Quaternion getNormalized() { Quaternion r(w, x, y, z); r.normalize(); @@ -102,7 +102,7 @@ class VectorInt16 { y = 0; z = 0; } - + VectorInt16(int16_t nx, int16_t ny, int16_t nz) { x = nx; y = ny; @@ -119,19 +119,19 @@ class VectorInt16 { y /= m; z /= m; } - + VectorInt16 getNormalized() { VectorInt16 r(x, y, z); r.normalize(); return r; } - + void rotate(Quaternion *q) { // http://www.cprogramming.com/tutorial/3d/quaternions.html // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/index.htm // http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation // ^ or: http://webcache.googleusercontent.com/search?q=cache:xgJAp3bDNhQJ:content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation&hl=en&gl=us&strip=1 - + // P_out = q * P_in * conj(q) // - P_out is the output vector // - q is the orientation quaternion @@ -169,7 +169,7 @@ class VectorFloat { y = 0; z = 0; } - + VectorFloat(float nx, float ny, float nz) { x = nx; y = ny; @@ -186,13 +186,13 @@ class VectorFloat { y /= m; z /= m; } - + VectorFloat getNormalized() { VectorFloat r(x, y, z); r.normalize(); return r; } - + void rotate(Quaternion *q) { Quaternion p(0, x, y, z); diff --git a/lib/NeoPixelBus-2.5.0.09/.github/ISSUE_TEMPLATE/bug_report.md b/lib/NeoPixelBus-2.5.0.09/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..9680fde4d --- /dev/null +++ b/lib/NeoPixelBus-2.5.0.09/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,34 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +**NOTE: If you are seeking help or have questions, this is NOT the place to do it.** For questions and support, jump on Gitter and ask away. +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Makuna/NeoPixelBus?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Development environment (please complete the following information):** + - OS: [e.g. Win10] + - Build Environment [e.g. Arduino IDE v.1.8.10] + - Board target [e.g. AVR Mege 2560, v 1.10.31 ] - you will need to check the board manager for this. + - Library version [e.g. v2.3.4] - you will need to check the library manager for this. If you used github to clone it, mention this and include the reference. + +**Minimal Sketch that reproduced the problem:** +If an example will demonstrate the problem, list which example you used. +If its your sketch, take the time to remove unneeded parts and minimize it to the smallest sketch that reproduces the problem. Then include the sketch here using `code` markup. Start with a line with three single left quotes and then end with a line with three single left quotes. + +**Additional context** +Add any other context about the problem here. diff --git a/lib/NeoPixelBus-2.5.0.09/.github/ISSUE_TEMPLATE/feature_request.md b/lib/NeoPixelBus-2.5.0.09/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..6daf08040 --- /dev/null +++ b/lib/NeoPixelBus-2.5.0.09/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +**NOTE: If you are seeking help or have questions, this is NOT the place to do it.** For questions and support, jump on Gitter and ask away. +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Makuna/NeoPixelBus?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/lib/TasmotaModbus-1.2.0/library.json b/lib/TasmotaModbus-1.2.0/library.json index c9639e164..6de11d0e0 100644 --- a/lib/TasmotaModbus-1.2.0/library.json +++ b/lib/TasmotaModbus-1.2.0/library.json @@ -8,7 +8,7 @@ "repository": { "type": "git", - "url": "https://github.com/arendst/Sonoff-Tasmota/lib/TasmotaModbus" + "url": "https://github.com/arendst/Tasmota/lib/TasmotaModbus" }, "frameworks": "arduino", "platforms": "espressif8266" diff --git a/lib/TasmotaSerial-2.4.1/library.json b/lib/TasmotaSerial-2.4.1/library.json index 554d9ea9e..64cde09c9 100644 --- a/lib/TasmotaSerial-2.4.1/library.json +++ b/lib/TasmotaSerial-2.4.1/library.json @@ -8,7 +8,7 @@ "repository": { "type": "git", - "url": "https://github.com/arendst/Sonoff-Tasmota/lib/TasmotaSerial" + "url": "https://github.com/arendst/Tasmota/lib/TasmotaSerial" }, "frameworks": "arduino", "platforms": "espressif8266" diff --git a/lib/readme.txt b/lib/readme.txt deleted file mode 100644 index dbadc3d63..000000000 --- a/lib/readme.txt +++ /dev/null @@ -1,36 +0,0 @@ - -This directory is intended for the project specific (private) libraries. -PlatformIO will compile them to static libraries and link to executable file. - -The source code of each library should be placed in separate directory, like -"lib/private_lib/[here are source files]". - -For example, see how can be organized `Foo` and `Bar` libraries: - -|--lib -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| |--Foo -| | |- Foo.c -| | |- Foo.h -| |- readme.txt --> THIS FILE -|- platformio.ini -|--src - |- main.c - -Then in `src/main.c` you should use: - -#include -#include - -// rest H/C/CPP code - -PlatformIO will find your libraries automatically, configure preprocessor's -include paths and build them. - -More information about PlatformIO Library Dependency Finder -- http://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini index 65f11515d..4ea6d30d6 100755 --- a/platformio.ini +++ b/platformio.ini @@ -8,7 +8,7 @@ ; http://docs.platformio.org/en/stable/projectconf.html [platformio] -src_dir = sonoff +src_dir = tasmota build_dir = .pioenvs build_cache_dir = .cache diff --git a/sonoff/Parsing.cpp b/tasmota/Parsing.cpp similarity index 96% rename from sonoff/Parsing.cpp rename to tasmota/Parsing.cpp index 6c68a3af4..145b72572 100644 --- a/sonoff/Parsing.cpp +++ b/tasmota/Parsing.cpp @@ -1,623 +1,623 @@ -/* - Parsing.cpp - HTTP request parsing. - - Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. - - 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 - Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) -*/ - -// Use patched Parsing.cpp to fix ALEXA parsing issue in v2.4.2 -#include -#if defined(ARDUINO_ESP8266_RELEASE_2_4_2) -#warning **** Tasmota is using v2.4.2 patched Parsing.cpp as planned **** - -#include -#include "WiFiServer.h" -#include "WiFiClient.h" -#include "ESP8266WebServer.h" -#include "detail/mimetable.h" - -//#define DEBUG_ESP_HTTP_SERVER -#ifdef DEBUG_ESP_PORT -#define DEBUG_OUTPUT DEBUG_ESP_PORT -#else -#define DEBUG_OUTPUT Serial -#endif - -static const char Content_Type[] PROGMEM = "Content-Type"; -static const char filename[] PROGMEM = "filename"; - -static char* readBytesWithTimeout(WiFiClient& client, size_t maxLength, size_t& dataLength, int timeout_ms) -{ - char *buf = nullptr; - dataLength = 0; - while (dataLength < maxLength) { - int tries = timeout_ms; - size_t newLength; - while (!(newLength = client.available()) && tries--) delay(1); - if (!newLength) { - break; - } - if (!buf) { - buf = (char *) malloc(newLength + 1); - if (!buf) { - return nullptr; - } - } - else { - char* newBuf = (char *) realloc(buf, dataLength + newLength + 1); - if (!newBuf) { - free(buf); - return nullptr; - } - buf = newBuf; - } - client.readBytes(buf + dataLength, newLength); - dataLength += newLength; - buf[dataLength] = '\0'; - } - return buf; -} - -bool ESP8266WebServer::_parseRequest(WiFiClient& client) { - // Read the first line of HTTP request - String req = client.readStringUntil('\r'); - client.readStringUntil('\n'); - //reset header value - for (int i = 0; i < _headerKeysCount; ++i) { - _currentHeaders[i].value =String(); - } - - // First line of HTTP request looks like "GET /path HTTP/1.1" - // Retrieve the "/path" part by finding the spaces - int addr_start = req.indexOf(' '); - int addr_end = req.indexOf(' ', addr_start + 1); - if (addr_start == -1 || addr_end == -1) { -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("Invalid request: "); - DEBUG_OUTPUT.println(req); -#endif - return false; - } - - String methodStr = req.substring(0, addr_start); - String url = req.substring(addr_start + 1, addr_end); - String versionEnd = req.substring(addr_end + 8); - _currentVersion = atoi(versionEnd.c_str()); - String searchStr = ""; - int hasSearch = url.indexOf('?'); - if (hasSearch != -1){ - searchStr = url.substring(hasSearch + 1); - url = url.substring(0, hasSearch); - } - _currentUri = url; - _chunked = false; - - HTTPMethod method = HTTP_GET; - if (methodStr == F("POST")) { - method = HTTP_POST; - } else if (methodStr == F("DELETE")) { - method = HTTP_DELETE; - } else if (methodStr == F("OPTIONS")) { - method = HTTP_OPTIONS; - } else if (methodStr == F("PUT")) { - method = HTTP_PUT; - } else if (methodStr == F("PATCH")) { - method = HTTP_PATCH; - } - _currentMethod = method; - -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("method: "); - DEBUG_OUTPUT.print(methodStr); - DEBUG_OUTPUT.print(" url: "); - DEBUG_OUTPUT.print(url); - DEBUG_OUTPUT.print(" search: "); - DEBUG_OUTPUT.println(searchStr); -#endif - - //attach handler - RequestHandler* handler; - for (handler = _firstHandler; handler; handler = handler->next()) { - if (handler->canHandle(_currentMethod, _currentUri)) - break; - } - _currentHandler = handler; - - String formData; - // below is needed only when POST type request - if (method == HTTP_POST || method == HTTP_PUT || method == HTTP_PATCH || method == HTTP_DELETE){ - String boundaryStr; - String headerName; - String headerValue; - bool isForm = false; - bool isEncoded = false; - uint32_t contentLength = 0; - //parse headers - while(1){ - req = client.readStringUntil('\r'); - client.readStringUntil('\n'); - if (req == "") break;//no moar headers - int headerDiv = req.indexOf(':'); - if (headerDiv == -1){ - break; - } - headerName = req.substring(0, headerDiv); - headerValue = req.substring(headerDiv + 1); - headerValue.trim(); - _collectHeader(headerName.c_str(),headerValue.c_str()); - - #ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("headerName: "); - DEBUG_OUTPUT.println(headerName); - DEBUG_OUTPUT.print("headerValue: "); - DEBUG_OUTPUT.println(headerValue); - #endif - - if (headerName.equalsIgnoreCase(FPSTR(Content_Type))){ - using namespace mime; - if (headerValue.startsWith(FPSTR(mimeTable[txt].mimeType))){ - isForm = false; - } else if (headerValue.startsWith(F("application/x-www-form-urlencoded"))){ - isForm = false; - isEncoded = true; - } else if (headerValue.startsWith(F("multipart/"))){ - boundaryStr = headerValue.substring(headerValue.indexOf('=') + 1); - boundaryStr.replace("\"",""); - isForm = true; - } - } else if (headerName.equalsIgnoreCase(F("Content-Length"))){ - contentLength = headerValue.toInt(); - } else if (headerName.equalsIgnoreCase(F("Host"))){ - _hostHeader = headerValue; - } - } - - if (!isForm){ - size_t plainLength; - char* plainBuf = readBytesWithTimeout(client, contentLength, plainLength, HTTP_MAX_POST_WAIT); - if (plainLength < contentLength) { - free(plainBuf); - return false; - } - if (contentLength > 0) { - if(isEncoded){ - //url encoded form - if (searchStr != "") searchStr += '&'; - searchStr += plainBuf; - } - _parseArguments(searchStr); - if(!isEncoded||(0==_currentArgCount)){ // @20180124OF01: Workarround for Alexa Bug - //plain post json or other data - RequestArgument& arg = _currentArgs[_currentArgCount++]; - arg.key = F("plain"); - arg.value = String(plainBuf); - } - - #ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("Plain: "); - DEBUG_OUTPUT.println(plainBuf); - #endif - free(plainBuf); - } else { - // No content - but we can still have arguments in the URL. - _parseArguments(searchStr); - } - } - - if (isForm){ - _parseArguments(searchStr); - if (!_parseForm(client, boundaryStr, contentLength)) { - return false; - } - } - } else { - String headerName; - String headerValue; - //parse headers - while(1){ - req = client.readStringUntil('\r'); - client.readStringUntil('\n'); - if (req == "") break;//no moar headers - int headerDiv = req.indexOf(':'); - if (headerDiv == -1){ - break; - } - headerName = req.substring(0, headerDiv); - headerValue = req.substring(headerDiv + 2); - _collectHeader(headerName.c_str(),headerValue.c_str()); - - #ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("headerName: "); - DEBUG_OUTPUT.println(headerName); - DEBUG_OUTPUT.print("headerValue: "); - DEBUG_OUTPUT.println(headerValue); - #endif - - if (headerName.equalsIgnoreCase("Host")){ - _hostHeader = headerValue; - } - } - _parseArguments(searchStr); - } - client.flush(); - -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("Request: "); - DEBUG_OUTPUT.println(url); - DEBUG_OUTPUT.print(" Arguments: "); - DEBUG_OUTPUT.println(searchStr); -#endif - - return true; -} - -bool ESP8266WebServer::_collectHeader(const char* headerName, const char* headerValue) { - for (int i = 0; i < _headerKeysCount; i++) { - if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) { - _currentHeaders[i].value=headerValue; - return true; - } - } - return false; -} - -void ESP8266WebServer::_parseArguments(String data) { -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("args: "); - DEBUG_OUTPUT.println(data); -#endif - if (_currentArgs) - delete[] _currentArgs; - _currentArgs = 0; - if (data.length() == 0) { - _currentArgCount = 0; - _currentArgs = new RequestArgument[1]; - return; - } - _currentArgCount = 1; - - for (int i = 0; i < (int)data.length(); ) { - i = data.indexOf('&', i); - if (i == -1) - break; - ++i; - ++_currentArgCount; - } -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("args count: "); - DEBUG_OUTPUT.println(_currentArgCount); -#endif - - _currentArgs = new RequestArgument[_currentArgCount+1]; - int pos = 0; - int iarg; - for (iarg = 0; iarg < _currentArgCount;) { - int equal_sign_index = data.indexOf('=', pos); - int next_arg_index = data.indexOf('&', pos); -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("pos "); - DEBUG_OUTPUT.print(pos); - DEBUG_OUTPUT.print("=@ "); - DEBUG_OUTPUT.print(equal_sign_index); - DEBUG_OUTPUT.print(" &@ "); - DEBUG_OUTPUT.println(next_arg_index); -#endif - if ((equal_sign_index == -1) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1))) { -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("arg missing value: "); - DEBUG_OUTPUT.println(iarg); -#endif - if (next_arg_index == -1) - break; - pos = next_arg_index + 1; - continue; - } - RequestArgument& arg = _currentArgs[iarg]; - arg.key = urlDecode(data.substring(pos, equal_sign_index)); - arg.value = urlDecode(data.substring(equal_sign_index + 1, next_arg_index)); -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("arg "); - DEBUG_OUTPUT.print(iarg); - DEBUG_OUTPUT.print(" key: "); - DEBUG_OUTPUT.print(arg.key); - DEBUG_OUTPUT.print(" value: "); - DEBUG_OUTPUT.println(arg.value); -#endif - ++iarg; - if (next_arg_index == -1) - break; - pos = next_arg_index + 1; - } - _currentArgCount = iarg; -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("args count: "); - DEBUG_OUTPUT.println(_currentArgCount); -#endif - -} - -void ESP8266WebServer::_uploadWriteByte(uint8_t b){ - if (_currentUpload->currentSize == HTTP_UPLOAD_BUFLEN){ - if(_currentHandler && _currentHandler->canUpload(_currentUri)) - _currentHandler->upload(*this, _currentUri, *_currentUpload); - _currentUpload->totalSize += _currentUpload->currentSize; - _currentUpload->currentSize = 0; - } - _currentUpload->buf[_currentUpload->currentSize++] = b; -} - -uint8_t ESP8266WebServer::_uploadReadByte(WiFiClient& client){ - int res = client.read(); - if(res == -1){ - while(!client.available() && client.connected()) - yield(); - res = client.read(); - } - return (uint8_t)res; -} - -bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t len){ - (void) len; -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("Parse Form: Boundary: "); - DEBUG_OUTPUT.print(boundary); - DEBUG_OUTPUT.print(" Length: "); - DEBUG_OUTPUT.println(len); -#endif - String line; - int retry = 0; - do { - line = client.readStringUntil('\r'); - ++retry; - } while (line.length() == 0 && retry < 3); - - client.readStringUntil('\n'); - //start reading the form - if (line == ("--"+boundary)){ - RequestArgument* postArgs = new RequestArgument[32]; - int postArgsLen = 0; - while(1){ - String argName; - String argValue; - String argType; - String argFilename; - bool argIsFile = false; - - line = client.readStringUntil('\r'); - client.readStringUntil('\n'); - if (line.length() > 19 && line.substring(0, 19).equalsIgnoreCase(F("Content-Disposition"))){ - int nameStart = line.indexOf('='); - if (nameStart != -1){ - argName = line.substring(nameStart+2); - nameStart = argName.indexOf('='); - if (nameStart == -1){ - argName = argName.substring(0, argName.length() - 1); - } else { - argFilename = argName.substring(nameStart+2, argName.length() - 1); - argName = argName.substring(0, argName.indexOf('"')); - argIsFile = true; -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("PostArg FileName: "); - DEBUG_OUTPUT.println(argFilename); -#endif - //use GET to set the filename if uploading using blob - if (argFilename == F("blob") && hasArg(FPSTR(filename))) - argFilename = arg(FPSTR(filename)); - } -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("PostArg Name: "); - DEBUG_OUTPUT.println(argName); -#endif - using namespace mime; - argType = FPSTR(mimeTable[txt].mimeType); - line = client.readStringUntil('\r'); - client.readStringUntil('\n'); - if (line.length() > 12 && line.substring(0, 12).equalsIgnoreCase(FPSTR(Content_Type))){ - argType = line.substring(line.indexOf(':')+2); - //skip next line - client.readStringUntil('\r'); - client.readStringUntil('\n'); - } -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("PostArg Type: "); - DEBUG_OUTPUT.println(argType); -#endif - if (!argIsFile){ - while(1){ - line = client.readStringUntil('\r'); - client.readStringUntil('\n'); - if (line.startsWith("--"+boundary)) break; - if (argValue.length() > 0) argValue += "\n"; - argValue += line; - } -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("PostArg Value: "); - DEBUG_OUTPUT.println(argValue); - DEBUG_OUTPUT.println(); -#endif - - RequestArgument& arg = postArgs[postArgsLen++]; - arg.key = argName; - arg.value = argValue; - - if (line == ("--"+boundary+"--")){ -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.println("Done Parsing POST"); -#endif - break; - } - } else { - _currentUpload.reset(new HTTPUpload()); - _currentUpload->status = UPLOAD_FILE_START; - _currentUpload->name = argName; - _currentUpload->filename = argFilename; - _currentUpload->type = argType; - _currentUpload->totalSize = 0; - _currentUpload->currentSize = 0; -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("Start File: "); - DEBUG_OUTPUT.print(_currentUpload->filename); - DEBUG_OUTPUT.print(" Type: "); - DEBUG_OUTPUT.println(_currentUpload->type); -#endif - if(_currentHandler && _currentHandler->canUpload(_currentUri)) - _currentHandler->upload(*this, _currentUri, *_currentUpload); - _currentUpload->status = UPLOAD_FILE_WRITE; - uint8_t argByte = _uploadReadByte(client); -readfile: - while(argByte != 0x0D){ - if (!client.connected()) return _parseFormUploadAborted(); - _uploadWriteByte(argByte); - argByte = _uploadReadByte(client); - } - - argByte = _uploadReadByte(client); - if (!client.connected()) return _parseFormUploadAborted(); - if (argByte == 0x0A){ - argByte = _uploadReadByte(client); - if (!client.connected()) return _parseFormUploadAborted(); - if ((char)argByte != '-'){ - //continue reading the file - _uploadWriteByte(0x0D); - _uploadWriteByte(0x0A); - goto readfile; - } else { - argByte = _uploadReadByte(client); - if (!client.connected()) return _parseFormUploadAborted(); - if ((char)argByte != '-'){ - //continue reading the file - _uploadWriteByte(0x0D); - _uploadWriteByte(0x0A); - _uploadWriteByte((uint8_t)('-')); - goto readfile; - } - } - - uint8_t endBuf[boundary.length()]; - client.readBytes(endBuf, boundary.length()); - - if (strstr((const char*)endBuf, boundary.c_str()) != nullptr){ - if(_currentHandler && _currentHandler->canUpload(_currentUri)) - _currentHandler->upload(*this, _currentUri, *_currentUpload); - _currentUpload->totalSize += _currentUpload->currentSize; - _currentUpload->status = UPLOAD_FILE_END; - if(_currentHandler && _currentHandler->canUpload(_currentUri)) - _currentHandler->upload(*this, _currentUri, *_currentUpload); -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("End File: "); - DEBUG_OUTPUT.print(_currentUpload->filename); - DEBUG_OUTPUT.print(" Type: "); - DEBUG_OUTPUT.print(_currentUpload->type); - DEBUG_OUTPUT.print(" Size: "); - DEBUG_OUTPUT.println(_currentUpload->totalSize); -#endif - line = client.readStringUntil(0x0D); - client.readStringUntil(0x0A); - if (line == "--"){ -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.println("Done Parsing POST"); -#endif - break; - } - continue; - } else { - _uploadWriteByte(0x0D); - _uploadWriteByte(0x0A); - _uploadWriteByte((uint8_t)('-')); - _uploadWriteByte((uint8_t)('-')); - uint32_t i = 0; - while(i < boundary.length()){ - _uploadWriteByte(endBuf[i++]); - } - argByte = _uploadReadByte(client); - goto readfile; - } - } else { - _uploadWriteByte(0x0D); - goto readfile; - } - break; - } - } - } - } - - int iarg; - int totalArgs = ((32 - postArgsLen) < _currentArgCount)?(32 - postArgsLen):_currentArgCount; - for (iarg = 0; iarg < totalArgs; iarg++){ - RequestArgument& arg = postArgs[postArgsLen++]; - arg.key = _currentArgs[iarg].key; - arg.value = _currentArgs[iarg].value; - } - if (_currentArgs) delete[] _currentArgs; - _currentArgs = new RequestArgument[postArgsLen]; - for (iarg = 0; iarg < postArgsLen; iarg++){ - RequestArgument& arg = _currentArgs[iarg]; - arg.key = postArgs[iarg].key; - arg.value = postArgs[iarg].value; - } - _currentArgCount = iarg; - if (postArgs) - delete[] postArgs; - return true; - } -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("Error: line: "); - DEBUG_OUTPUT.println(line); -#endif - return false; -} - -String ESP8266WebServer::urlDecode(const String& text) -{ - String decoded = ""; - char temp[] = "0x00"; - unsigned int len = text.length(); - unsigned int i = 0; - while (i < len) - { - char decodedChar; - char encodedChar = text.charAt(i++); - if ((encodedChar == '%') && (i + 1 < len)) - { - temp[2] = text.charAt(i++); - temp[3] = text.charAt(i++); - - decodedChar = strtol(temp, NULL, 16); - } - else { - if (encodedChar == '+') - { - decodedChar = ' '; - } - else { - decodedChar = encodedChar; // normal ascii char - } - } - decoded += decodedChar; - } - return decoded; -} - -bool ESP8266WebServer::_parseFormUploadAborted(){ - _currentUpload->status = UPLOAD_FILE_ABORTED; - if(_currentHandler && _currentHandler->canUpload(_currentUri)) - _currentHandler->upload(*this, _currentUri, *_currentUpload); - return false; -} - +/* + Parsing.cpp - HTTP request parsing. + + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + + 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 + Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) +*/ + +// Use patched Parsing.cpp to fix ALEXA parsing issue in v2.4.2 +#include +#if defined(ARDUINO_ESP8266_RELEASE_2_4_2) +#warning **** Tasmota is using v2.4.2 patched Parsing.cpp as planned **** + +#include +#include "WiFiServer.h" +#include "WiFiClient.h" +#include "ESP8266WebServer.h" +#include "detail/mimetable.h" + +//#define DEBUG_ESP_HTTP_SERVER +#ifdef DEBUG_ESP_PORT +#define DEBUG_OUTPUT DEBUG_ESP_PORT +#else +#define DEBUG_OUTPUT Serial +#endif + +static const char Content_Type[] PROGMEM = "Content-Type"; +static const char filename[] PROGMEM = "filename"; + +static char* readBytesWithTimeout(WiFiClient& client, size_t maxLength, size_t& dataLength, int timeout_ms) +{ + char *buf = nullptr; + dataLength = 0; + while (dataLength < maxLength) { + int tries = timeout_ms; + size_t newLength; + while (!(newLength = client.available()) && tries--) delay(1); + if (!newLength) { + break; + } + if (!buf) { + buf = (char *) malloc(newLength + 1); + if (!buf) { + return nullptr; + } + } + else { + char* newBuf = (char *) realloc(buf, dataLength + newLength + 1); + if (!newBuf) { + free(buf); + return nullptr; + } + buf = newBuf; + } + client.readBytes(buf + dataLength, newLength); + dataLength += newLength; + buf[dataLength] = '\0'; + } + return buf; +} + +bool ESP8266WebServer::_parseRequest(WiFiClient& client) { + // Read the first line of HTTP request + String req = client.readStringUntil('\r'); + client.readStringUntil('\n'); + //reset header value + for (int i = 0; i < _headerKeysCount; ++i) { + _currentHeaders[i].value =String(); + } + + // First line of HTTP request looks like "GET /path HTTP/1.1" + // Retrieve the "/path" part by finding the spaces + int addr_start = req.indexOf(' '); + int addr_end = req.indexOf(' ', addr_start + 1); + if (addr_start == -1 || addr_end == -1) { +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Invalid request: "); + DEBUG_OUTPUT.println(req); +#endif + return false; + } + + String methodStr = req.substring(0, addr_start); + String url = req.substring(addr_start + 1, addr_end); + String versionEnd = req.substring(addr_end + 8); + _currentVersion = atoi(versionEnd.c_str()); + String searchStr = ""; + int hasSearch = url.indexOf('?'); + if (hasSearch != -1){ + searchStr = url.substring(hasSearch + 1); + url = url.substring(0, hasSearch); + } + _currentUri = url; + _chunked = false; + + HTTPMethod method = HTTP_GET; + if (methodStr == F("POST")) { + method = HTTP_POST; + } else if (methodStr == F("DELETE")) { + method = HTTP_DELETE; + } else if (methodStr == F("OPTIONS")) { + method = HTTP_OPTIONS; + } else if (methodStr == F("PUT")) { + method = HTTP_PUT; + } else if (methodStr == F("PATCH")) { + method = HTTP_PATCH; + } + _currentMethod = method; + +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("method: "); + DEBUG_OUTPUT.print(methodStr); + DEBUG_OUTPUT.print(" url: "); + DEBUG_OUTPUT.print(url); + DEBUG_OUTPUT.print(" search: "); + DEBUG_OUTPUT.println(searchStr); +#endif + + //attach handler + RequestHandler* handler; + for (handler = _firstHandler; handler; handler = handler->next()) { + if (handler->canHandle(_currentMethod, _currentUri)) + break; + } + _currentHandler = handler; + + String formData; + // below is needed only when POST type request + if (method == HTTP_POST || method == HTTP_PUT || method == HTTP_PATCH || method == HTTP_DELETE){ + String boundaryStr; + String headerName; + String headerValue; + bool isForm = false; + bool isEncoded = false; + uint32_t contentLength = 0; + //parse headers + while(1){ + req = client.readStringUntil('\r'); + client.readStringUntil('\n'); + if (req == "") break;//no moar headers + int headerDiv = req.indexOf(':'); + if (headerDiv == -1){ + break; + } + headerName = req.substring(0, headerDiv); + headerValue = req.substring(headerDiv + 1); + headerValue.trim(); + _collectHeader(headerName.c_str(),headerValue.c_str()); + + #ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("headerName: "); + DEBUG_OUTPUT.println(headerName); + DEBUG_OUTPUT.print("headerValue: "); + DEBUG_OUTPUT.println(headerValue); + #endif + + if (headerName.equalsIgnoreCase(FPSTR(Content_Type))){ + using namespace mime; + if (headerValue.startsWith(FPSTR(mimeTable[txt].mimeType))){ + isForm = false; + } else if (headerValue.startsWith(F("application/x-www-form-urlencoded"))){ + isForm = false; + isEncoded = true; + } else if (headerValue.startsWith(F("multipart/"))){ + boundaryStr = headerValue.substring(headerValue.indexOf('=') + 1); + boundaryStr.replace("\"",""); + isForm = true; + } + } else if (headerName.equalsIgnoreCase(F("Content-Length"))){ + contentLength = headerValue.toInt(); + } else if (headerName.equalsIgnoreCase(F("Host"))){ + _hostHeader = headerValue; + } + } + + if (!isForm){ + size_t plainLength; + char* plainBuf = readBytesWithTimeout(client, contentLength, plainLength, HTTP_MAX_POST_WAIT); + if (plainLength < contentLength) { + free(plainBuf); + return false; + } + if (contentLength > 0) { + if(isEncoded){ + //url encoded form + if (searchStr != "") searchStr += '&'; + searchStr += plainBuf; + } + _parseArguments(searchStr); + if(!isEncoded||(0==_currentArgCount)){ // @20180124OF01: Workarround for Alexa Bug + //plain post json or other data + RequestArgument& arg = _currentArgs[_currentArgCount++]; + arg.key = F("plain"); + arg.value = String(plainBuf); + } + + #ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Plain: "); + DEBUG_OUTPUT.println(plainBuf); + #endif + free(plainBuf); + } else { + // No content - but we can still have arguments in the URL. + _parseArguments(searchStr); + } + } + + if (isForm){ + _parseArguments(searchStr); + if (!_parseForm(client, boundaryStr, contentLength)) { + return false; + } + } + } else { + String headerName; + String headerValue; + //parse headers + while(1){ + req = client.readStringUntil('\r'); + client.readStringUntil('\n'); + if (req == "") break;//no moar headers + int headerDiv = req.indexOf(':'); + if (headerDiv == -1){ + break; + } + headerName = req.substring(0, headerDiv); + headerValue = req.substring(headerDiv + 2); + _collectHeader(headerName.c_str(),headerValue.c_str()); + + #ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("headerName: "); + DEBUG_OUTPUT.println(headerName); + DEBUG_OUTPUT.print("headerValue: "); + DEBUG_OUTPUT.println(headerValue); + #endif + + if (headerName.equalsIgnoreCase("Host")){ + _hostHeader = headerValue; + } + } + _parseArguments(searchStr); + } + client.flush(); + +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Request: "); + DEBUG_OUTPUT.println(url); + DEBUG_OUTPUT.print(" Arguments: "); + DEBUG_OUTPUT.println(searchStr); +#endif + + return true; +} + +bool ESP8266WebServer::_collectHeader(const char* headerName, const char* headerValue) { + for (int i = 0; i < _headerKeysCount; i++) { + if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) { + _currentHeaders[i].value=headerValue; + return true; + } + } + return false; +} + +void ESP8266WebServer::_parseArguments(String data) { +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("args: "); + DEBUG_OUTPUT.println(data); +#endif + if (_currentArgs) + delete[] _currentArgs; + _currentArgs = 0; + if (data.length() == 0) { + _currentArgCount = 0; + _currentArgs = new RequestArgument[1]; + return; + } + _currentArgCount = 1; + + for (int i = 0; i < (int)data.length(); ) { + i = data.indexOf('&', i); + if (i == -1) + break; + ++i; + ++_currentArgCount; + } +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("args count: "); + DEBUG_OUTPUT.println(_currentArgCount); +#endif + + _currentArgs = new RequestArgument[_currentArgCount+1]; + int pos = 0; + int iarg; + for (iarg = 0; iarg < _currentArgCount;) { + int equal_sign_index = data.indexOf('=', pos); + int next_arg_index = data.indexOf('&', pos); +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("pos "); + DEBUG_OUTPUT.print(pos); + DEBUG_OUTPUT.print("=@ "); + DEBUG_OUTPUT.print(equal_sign_index); + DEBUG_OUTPUT.print(" &@ "); + DEBUG_OUTPUT.println(next_arg_index); +#endif + if ((equal_sign_index == -1) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1))) { +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("arg missing value: "); + DEBUG_OUTPUT.println(iarg); +#endif + if (next_arg_index == -1) + break; + pos = next_arg_index + 1; + continue; + } + RequestArgument& arg = _currentArgs[iarg]; + arg.key = urlDecode(data.substring(pos, equal_sign_index)); + arg.value = urlDecode(data.substring(equal_sign_index + 1, next_arg_index)); +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("arg "); + DEBUG_OUTPUT.print(iarg); + DEBUG_OUTPUT.print(" key: "); + DEBUG_OUTPUT.print(arg.key); + DEBUG_OUTPUT.print(" value: "); + DEBUG_OUTPUT.println(arg.value); +#endif + ++iarg; + if (next_arg_index == -1) + break; + pos = next_arg_index + 1; + } + _currentArgCount = iarg; +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("args count: "); + DEBUG_OUTPUT.println(_currentArgCount); +#endif + +} + +void ESP8266WebServer::_uploadWriteByte(uint8_t b){ + if (_currentUpload->currentSize == HTTP_UPLOAD_BUFLEN){ + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, *_currentUpload); + _currentUpload->totalSize += _currentUpload->currentSize; + _currentUpload->currentSize = 0; + } + _currentUpload->buf[_currentUpload->currentSize++] = b; +} + +uint8_t ESP8266WebServer::_uploadReadByte(WiFiClient& client){ + int res = client.read(); + if(res == -1){ + while(!client.available() && client.connected()) + yield(); + res = client.read(); + } + return (uint8_t)res; +} + +bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t len){ + (void) len; +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Parse Form: Boundary: "); + DEBUG_OUTPUT.print(boundary); + DEBUG_OUTPUT.print(" Length: "); + DEBUG_OUTPUT.println(len); +#endif + String line; + int retry = 0; + do { + line = client.readStringUntil('\r'); + ++retry; + } while (line.length() == 0 && retry < 3); + + client.readStringUntil('\n'); + //start reading the form + if (line == ("--"+boundary)){ + RequestArgument* postArgs = new RequestArgument[32]; + int postArgsLen = 0; + while(1){ + String argName; + String argValue; + String argType; + String argFilename; + bool argIsFile = false; + + line = client.readStringUntil('\r'); + client.readStringUntil('\n'); + if (line.length() > 19 && line.substring(0, 19).equalsIgnoreCase(F("Content-Disposition"))){ + int nameStart = line.indexOf('='); + if (nameStart != -1){ + argName = line.substring(nameStart+2); + nameStart = argName.indexOf('='); + if (nameStart == -1){ + argName = argName.substring(0, argName.length() - 1); + } else { + argFilename = argName.substring(nameStart+2, argName.length() - 1); + argName = argName.substring(0, argName.indexOf('"')); + argIsFile = true; +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("PostArg FileName: "); + DEBUG_OUTPUT.println(argFilename); +#endif + //use GET to set the filename if uploading using blob + if (argFilename == F("blob") && hasArg(FPSTR(filename))) + argFilename = arg(FPSTR(filename)); + } +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("PostArg Name: "); + DEBUG_OUTPUT.println(argName); +#endif + using namespace mime; + argType = FPSTR(mimeTable[txt].mimeType); + line = client.readStringUntil('\r'); + client.readStringUntil('\n'); + if (line.length() > 12 && line.substring(0, 12).equalsIgnoreCase(FPSTR(Content_Type))){ + argType = line.substring(line.indexOf(':')+2); + //skip next line + client.readStringUntil('\r'); + client.readStringUntil('\n'); + } +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("PostArg Type: "); + DEBUG_OUTPUT.println(argType); +#endif + if (!argIsFile){ + while(1){ + line = client.readStringUntil('\r'); + client.readStringUntil('\n'); + if (line.startsWith("--"+boundary)) break; + if (argValue.length() > 0) argValue += "\n"; + argValue += line; + } +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("PostArg Value: "); + DEBUG_OUTPUT.println(argValue); + DEBUG_OUTPUT.println(); +#endif + + RequestArgument& arg = postArgs[postArgsLen++]; + arg.key = argName; + arg.value = argValue; + + if (line == ("--"+boundary+"--")){ +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.println("Done Parsing POST"); +#endif + break; + } + } else { + _currentUpload.reset(new HTTPUpload()); + _currentUpload->status = UPLOAD_FILE_START; + _currentUpload->name = argName; + _currentUpload->filename = argFilename; + _currentUpload->type = argType; + _currentUpload->totalSize = 0; + _currentUpload->currentSize = 0; +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Start File: "); + DEBUG_OUTPUT.print(_currentUpload->filename); + DEBUG_OUTPUT.print(" Type: "); + DEBUG_OUTPUT.println(_currentUpload->type); +#endif + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, *_currentUpload); + _currentUpload->status = UPLOAD_FILE_WRITE; + uint8_t argByte = _uploadReadByte(client); +readfile: + while(argByte != 0x0D){ + if (!client.connected()) return _parseFormUploadAborted(); + _uploadWriteByte(argByte); + argByte = _uploadReadByte(client); + } + + argByte = _uploadReadByte(client); + if (!client.connected()) return _parseFormUploadAborted(); + if (argByte == 0x0A){ + argByte = _uploadReadByte(client); + if (!client.connected()) return _parseFormUploadAborted(); + if ((char)argByte != '-'){ + //continue reading the file + _uploadWriteByte(0x0D); + _uploadWriteByte(0x0A); + goto readfile; + } else { + argByte = _uploadReadByte(client); + if (!client.connected()) return _parseFormUploadAborted(); + if ((char)argByte != '-'){ + //continue reading the file + _uploadWriteByte(0x0D); + _uploadWriteByte(0x0A); + _uploadWriteByte((uint8_t)('-')); + goto readfile; + } + } + + uint8_t endBuf[boundary.length()]; + client.readBytes(endBuf, boundary.length()); + + if (strstr((const char*)endBuf, boundary.c_str()) != nullptr){ + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, *_currentUpload); + _currentUpload->totalSize += _currentUpload->currentSize; + _currentUpload->status = UPLOAD_FILE_END; + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, *_currentUpload); +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("End File: "); + DEBUG_OUTPUT.print(_currentUpload->filename); + DEBUG_OUTPUT.print(" Type: "); + DEBUG_OUTPUT.print(_currentUpload->type); + DEBUG_OUTPUT.print(" Size: "); + DEBUG_OUTPUT.println(_currentUpload->totalSize); +#endif + line = client.readStringUntil(0x0D); + client.readStringUntil(0x0A); + if (line == "--"){ +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.println("Done Parsing POST"); +#endif + break; + } + continue; + } else { + _uploadWriteByte(0x0D); + _uploadWriteByte(0x0A); + _uploadWriteByte((uint8_t)('-')); + _uploadWriteByte((uint8_t)('-')); + uint32_t i = 0; + while(i < boundary.length()){ + _uploadWriteByte(endBuf[i++]); + } + argByte = _uploadReadByte(client); + goto readfile; + } + } else { + _uploadWriteByte(0x0D); + goto readfile; + } + break; + } + } + } + } + + int iarg; + int totalArgs = ((32 - postArgsLen) < _currentArgCount)?(32 - postArgsLen):_currentArgCount; + for (iarg = 0; iarg < totalArgs; iarg++){ + RequestArgument& arg = postArgs[postArgsLen++]; + arg.key = _currentArgs[iarg].key; + arg.value = _currentArgs[iarg].value; + } + if (_currentArgs) delete[] _currentArgs; + _currentArgs = new RequestArgument[postArgsLen]; + for (iarg = 0; iarg < postArgsLen; iarg++){ + RequestArgument& arg = _currentArgs[iarg]; + arg.key = postArgs[iarg].key; + arg.value = postArgs[iarg].value; + } + _currentArgCount = iarg; + if (postArgs) + delete[] postArgs; + return true; + } +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Error: line: "); + DEBUG_OUTPUT.println(line); +#endif + return false; +} + +String ESP8266WebServer::urlDecode(const String& text) +{ + String decoded = ""; + char temp[] = "0x00"; + unsigned int len = text.length(); + unsigned int i = 0; + while (i < len) + { + char decodedChar; + char encodedChar = text.charAt(i++); + if ((encodedChar == '%') && (i + 1 < len)) + { + temp[2] = text.charAt(i++); + temp[3] = text.charAt(i++); + + decodedChar = strtol(temp, NULL, 16); + } + else { + if (encodedChar == '+') + { + decodedChar = ' '; + } + else { + decodedChar = encodedChar; // normal ascii char + } + } + decoded += decodedChar; + } + return decoded; +} + +bool ESP8266WebServer::_parseFormUploadAborted(){ + _currentUpload->status = UPLOAD_FILE_ABORTED; + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, *_currentUpload); + return false; +} + #endif // ARDUINO_ESP8266_RELEASE \ No newline at end of file diff --git a/sonoff/StackThunk_light.cpp b/tasmota/StackThunk_light.cpp similarity index 100% rename from sonoff/StackThunk_light.cpp rename to tasmota/StackThunk_light.cpp diff --git a/sonoff/StackThunk_light.h b/tasmota/StackThunk_light.h similarity index 100% rename from sonoff/StackThunk_light.h rename to tasmota/StackThunk_light.h diff --git a/sonoff/WiFiClientSecureLightBearSSL.cpp b/tasmota/WiFiClientSecureLightBearSSL.cpp similarity index 100% rename from sonoff/WiFiClientSecureLightBearSSL.cpp rename to tasmota/WiFiClientSecureLightBearSSL.cpp diff --git a/sonoff/WiFiClientSecureLightBearSSL.h b/tasmota/WiFiClientSecureLightBearSSL.h similarity index 100% rename from sonoff/WiFiClientSecureLightBearSSL.h rename to tasmota/WiFiClientSecureLightBearSSL.h diff --git a/sonoff/_changelog.ino b/tasmota/_changelog.ino similarity index 99% rename from sonoff/_changelog.ino rename to tasmota/_changelog.ino index 02591fac0..33d77decc 100644 --- a/sonoff/_changelog.ino +++ b/tasmota/_changelog.ino @@ -233,7 +233,7 @@ * Add command SetOption64 0/1 to switch between "-" or "_" as sensor index separator impacting DS18X20, DHT, BMP and SHT3X sensor names (#5689) * Add command SetOption65 0/1 and more Tuya Serial based device support (#5815) * Add command WebColor to change GUI colors on the fly - * Add support for AWS IoT with TLS 1.2 on core 2.4.2 and up. Full doc here: https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT + * Add support for AWS IoT with TLS 1.2 on core 2.4.2 and up. Full doc here: https://github.com/arendst/Tasmota/wiki/AWS-IoT * Add support for Badger HR-E Water Meter (#5539) * Add support for Shelly 2.5 Energy and overtemp Monitoring (#5592) * Add support for color and colortone for Philips Hue emulation via Alexa (#5600 #4809) @@ -583,7 +583,7 @@ * Revert sonoff-minimal removals causing failure of wifi connection (#3177) * * 6.1.0 20180706 - * Remove version 3, 4 and pre 5.2 settings auto-upgrade. See https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade#migration-path + * Remove version 3, 4 and pre 5.2 settings auto-upgrade. See https://github.com/arendst/Tasmota/wiki/Upgrade#migration-path * Change default CFG_HOLDER from 0x20161209 to 4617 (=0x1209) - no impact on default upgrades * Change number of supported switches from 4 to 8 (#2885, #3086) * Change BME680 driver from Adafruit to Bosch BME680 library (#2969) @@ -1175,7 +1175,7 @@ * 5.0.5 20170508 * Add command FullTopic with tokens %topic% (replaced by command Topic value) and * %prefix% (replaced by command Prefix values) for more flexible topic definitions (#244) - * See wiki > MQTT Features https://github.com/arendst/Sonoff-Tasmota/wiki/MQTT-Features for more information + * See wiki > MQTT Features https://github.com/arendst/Tasmota/wiki/MQTT-Features for more information * * 5.0.4 20170505 * Add Sonoff Pow Energy Total up to 40 MWh diff --git a/sonoff/core_esp8266_timer.c b/tasmota/core_esp8266_timer.c similarity index 100% rename from sonoff/core_esp8266_timer.c rename to tasmota/core_esp8266_timer.c diff --git a/sonoff/core_esp8266_wiring_digital.c b/tasmota/core_esp8266_wiring_digital.c similarity index 100% rename from sonoff/core_esp8266_wiring_digital.c rename to tasmota/core_esp8266_wiring_digital.c diff --git a/sonoff/core_esp8266_wiring_pwm.c b/tasmota/core_esp8266_wiring_pwm.c similarity index 100% rename from sonoff/core_esp8266_wiring_pwm.c rename to tasmota/core_esp8266_wiring_pwm.c diff --git a/sonoff/i18n.h b/tasmota/i18n.h similarity index 100% rename from sonoff/i18n.h rename to tasmota/i18n.h diff --git a/sonoff/language/bg-BG.h b/tasmota/language/bg-BG.h similarity index 100% rename from sonoff/language/bg-BG.h rename to tasmota/language/bg-BG.h diff --git a/sonoff/language/cs-CZ.h b/tasmota/language/cs-CZ.h similarity index 100% rename from sonoff/language/cs-CZ.h rename to tasmota/language/cs-CZ.h diff --git a/sonoff/language/de-DE.h b/tasmota/language/de-DE.h similarity index 100% rename from sonoff/language/de-DE.h rename to tasmota/language/de-DE.h diff --git a/sonoff/language/el-GR.h b/tasmota/language/el-GR.h similarity index 100% rename from sonoff/language/el-GR.h rename to tasmota/language/el-GR.h diff --git a/sonoff/language/en-GB.h b/tasmota/language/en-GB.h similarity index 100% rename from sonoff/language/en-GB.h rename to tasmota/language/en-GB.h diff --git a/sonoff/language/es-ES.h b/tasmota/language/es-ES.h similarity index 100% rename from sonoff/language/es-ES.h rename to tasmota/language/es-ES.h diff --git a/sonoff/language/fr-FR.h b/tasmota/language/fr-FR.h similarity index 100% rename from sonoff/language/fr-FR.h rename to tasmota/language/fr-FR.h diff --git a/sonoff/language/he-HE.h b/tasmota/language/he-HE.h similarity index 100% rename from sonoff/language/he-HE.h rename to tasmota/language/he-HE.h diff --git a/sonoff/language/hu-HU.h b/tasmota/language/hu-HU.h similarity index 100% rename from sonoff/language/hu-HU.h rename to tasmota/language/hu-HU.h diff --git a/sonoff/language/it-IT.h b/tasmota/language/it-IT.h similarity index 100% rename from sonoff/language/it-IT.h rename to tasmota/language/it-IT.h diff --git a/sonoff/language/ko-KO.h b/tasmota/language/ko-KO.h similarity index 97% rename from sonoff/language/ko-KO.h rename to tasmota/language/ko-KO.h index 82832fdbb..ffe507144 100644 --- a/sonoff/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -1,727 +1,727 @@ -/* - ko-KO.h - localization for Korean - Korean for Tasmota - - Copyright (C) 2019 Theo Arends (translated by NyaamZ) - - 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 . -*/ - -#ifndef _LANGUAGE_KO_KO_H_ -#define _LANGUAGE_KO_KO_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.2.1.11 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) -// https://www.science.co.il/language/Locale-codes.php -#define LANGUAGE_LCID 1042 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "ko" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "일 월 화 수 목 금 토 " -#define D_MONTH3LIST "1월 2월 3월 4월 5월 6월 7월 8월 9월 10월11월12월" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "공기질" -#define D_AP "AP" // Access Point -#define D_AS "as" -#define D_AUTO "자동" -#define D_BLINK "깜박임" -#define D_BLINKOFF "깜박임 끄기" -#define D_BOOT_COUNT "가동횟수" -#define D_BRIGHTLIGHT "밝기" -#define D_BSSID "BSSId" -#define D_BUTTON "버튼" -#define D_BY "by" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "섭씨" -#define D_CHANNEL "채널" -#define D_CO2 "이산화탄소" -#define D_CODE "코드" // Button code -#define D_COLDLIGHT "차갑게" -#define D_COMMAND "명령" -#define D_CONNECTED "연결됨" -#define D_COUNT "횟수" -#define D_COUNTER "Counter" -#define D_CURRENT "전류" // As in Voltage and Current -#define D_DATA "데이터" -#define D_DARKLIGHT "어둡게" -#define D_DEBUG "디버그" -#define D_DISABLED "사용 불가" -#define D_DISTANCE "거리" -#define D_DNS_SERVER "DNS 서버" -#define D_DONE "완료" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "에뮬레이션" -#define D_ENABLED "사용 가능" -#define D_ERASE "삭제" -#define D_ERROR "에러" -#define D_FAHRENHEIT "화씨" -#define D_FAILED "실패" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "거짓" -#define D_FILE "파일" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "남은 메모리" -#define D_FREQUENCY "빈도" -#define D_GAS "가스" -#define D_GATEWAY "게이트웨이" -#define D_GROUP "그룹" -#define D_HOST "호스트" -#define D_HOSTNAME "호스트이름" -#define D_HUMIDITY "습도" -#define D_ILLUMINANCE "조도" -#define D_IMMEDIATE "immediate" // Button immediate -#define D_INDEX "인덱스" -#define D_INFO "정보" -#define D_INFRARED "적외선" -#define D_INITIALIZED "초기화 완료" -#define D_IP_ADDRESS "IP 주소" -#define D_LIGHT "밝게" -#define D_LWT "LWT" -#define D_MODULE "모듈" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-press" -#define D_NOISE "소음" -#define D_NONE "없음" -#define D_OFF "꺼짐" -#define D_OFFLINE "오프라인" -#define D_OK "Ok" -#define D_ON "켜짐" -#define D_ONLINE "온라인" -#define D_PASSWORD "비밀번호" -#define D_PORT "포트" -#define D_POWER_FACTOR "Power Factor" -#define D_POWERUSAGE "전원" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" -#define D_PRESSURE "기압" -#define D_PRESSUREATSEALEVEL "해수면기압" -#define D_PROGRAM_FLASH_SIZE "플래시 용량" -#define D_PROGRAM_SIZE "프로그램 용량" -#define D_PROJECT "프로젝트" -#define D_RAIN "비" -#define D_RECEIVED "받음" -#define D_RESTART "재시작" -#define D_RESTARTING "재시작 중" -#define D_RESTART_REASON "재시작 이유" -#define D_RESTORE "복구" -#define D_RETAINED "보류" -#define D_RULE "규칙" -#define D_SAVE "저장" -#define D_SENSOR "센서" -#define D_SSID "SSId" -#define D_START "시작" -#define D_STD_TIME "STD" -#define D_STOP "정지" -#define D_SUBNET_MASK "서브넷 마스크" -#define D_SUBSCRIBE_TO "구독" -#define D_UNSUBSCRIBE_FROM "구독 해제" -#define D_SUCCESSFUL "성공" -#define D_SUNRISE "일출" -#define D_SUNSET "일몰" -#define D_TEMPERATURE "온도" -#define D_TO "to" -#define D_TOGGLE "전환" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "전송" -#define D_TRUE "참" -#define D_TVOC "TVOC" -#define D_UPGRADE "업그레이드" -#define D_UPLOAD "업로드" -#define D_UPTIME "가동시간" -#define D_USER "User" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV 색인" -#define D_UV_INDEX_1 "낮음" -#define D_UV_INDEX_2 "보통" -#define D_UV_INDEX_3 "높음" -#define D_UV_INDEX_4 "위험" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" // Out of Range -#define D_UV_LEVEL "UV 레벨" -#define D_UV_POWER "UV 파워" -#define D_VERSION "버전" -#define D_VOLTAGE "전압" -#define D_WEIGHT "무게" -#define D_WARMLIGHT "따뜻하게" -#define D_WEB_SERVER "웹 서버" - -// sonoff.ino -#define D_WARNING_MINIMAL_VERSION "경고: 이 버전은 영구 설정을 지원하지 않습니다" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serial log 사용 안함" -#define D_SYSLOG_LOGGING_REENABLED "Syslog log 다시 사용" - -#define D_SET_BAUDRATE_TO "Set Baudrate to" -#define D_RECEIVED_TOPIC "Received Topic" -#define D_DATA_SIZE "데이터 용량" -#define D_ANALOG_INPUT "아날로그" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPS설정 실패" -#define D_ACTIVE_FOR_3_MINUTES "3분동안 활성화" -#define D_FAILED_TO_START "시작 실패" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "AP에 연결 중" -#define D_IN_MODE "in mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP 주소가 수신되지 않아 연결이 실패했습니다" -#define D_CONNECT_FAILED_AP_NOT_REACHED "연결이 닿지 않아 AP에 연결할 수 없습니다" -#define D_CONNECT_FAILED_WRONG_PASSWORD "비밀번호가 틀려 AP에 연결할 수 없습니다" -#define D_CONNECT_FAILED_AP_TIMEOUT "시간초과로 AP에 연결할 수 없습니다" -#define D_ATTEMPTING_CONNECTION "연결 시도 중..." -#define D_CHECKING_CONNECTION "연결 체크 중..." -#define D_QUERY_DONE "쿼리 완료. MQTT 서비스 발견" -#define D_MQTT_SERVICE_FOUND "MQTT 서비스 발견" -#define D_FOUND_AT "다음에서 발견" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog 호스트가 발견되지 않았습니다" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "플래시에 저장" -#define D_LOADED_FROM_FLASH_AT "플래시에서 로드" -#define D_USE_DEFAULTS "디폴트 사용" -#define D_ERASED_SECTOR "삭제된 섹터" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오." -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" -#define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중" -#define D_WITH_IP_ADDRESS "IP 주소" -#define D_WEBSERVER_STOPPED "Web 서버 멈춤" -#define D_FILE_NOT_FOUND "파일을 찾을 수 없습니다" -#define D_REDIRECTED "인증 페이지로 리디렉션" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "와이파이 매니저가 AccessPoint와 keep Station을 설정" -#define D_WIFIMANAGER_SET_ACCESSPOINT "와이파이 매니저가 AccessPoint를 설정" -#define D_TRYING_TO_CONNECT "장치를 네트워크에 연결하려고 시도 중" - -#define D_RESTART_IN "재시작" -#define D_SECONDS "초" -#define D_DEVICE_WILL_RESTART "이 장치는 몇 초 후 재시작됩니다" -#define D_BUTTON_TOGGLE "켜기/끄기" -#define D_CONFIGURATION "설정" -#define D_INFORMATION "정보" -#define D_FIRMWARE_UPGRADE "펌웨어 업그레이드" -#define D_CONSOLE "콘솔" -#define D_CONFIRM_RESTART "재시작" - -#define D_CONFIGURE_MODULE "모듈 설정" -#define D_CONFIGURE_WIFI "WiFi 설정" -#define D_CONFIGURE_MQTT "MQTT 설정" -#define D_CONFIGURE_DOMOTICZ "Domoticz 설정" -#define D_CONFIGURE_LOGGING "로그 설정" -#define D_CONFIGURE_OTHER "기타 설정" -#define D_CONFIRM_RESET_CONFIGURATION "설정 초기화 확인" -#define D_RESET_CONFIGURATION "설정 초기화" -#define D_BACKUP_CONFIGURATION "백업 설정" -#define D_RESTORE_CONFIGURATION "복원 설정" -#define D_MAIN_MENU "메인 메뉴" - -#define D_MODULE_PARAMETERS "모듈 상세" -#define D_MODULE_TYPE "모듈 타입" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Wifi 상세" -#define D_SCAN_FOR_WIFI_NETWORKS "Wifi 네트워크를 검색 중" -#define D_SCAN_DONE "검색 완료" -#define D_NO_NETWORKS_FOUND "발견된 네트워크가 없습니다" -#define D_REFRESH_TO_SCAN_AGAIN "검색 재시도" -#define D_DUPLICATE_ACCESSPOINT "중복된 AccessPoint" -#define D_SKIPPING_LOW_QUALITY "약한 네트워크 신호 무시" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 비밀번호" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 비밀번호" - -#define D_MQTT_PARAMETERS "MQTT 상세" -#define D_CLIENT "클라이언트" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "로그 상세" -#define D_SERIAL_LOG_LEVEL "시리얼 로그 레벨" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web 로그 레벨" -#define D_SYS_LOG_LEVEL "Syslog 로그 레벨" -#define D_MORE_DEBUG "More debug" -#define D_SYSLOG_HOST "Syslog 호스트" -#define D_SYSLOG_PORT "Syslog 포트" -#define D_TELEMETRY_PERIOD "보고 주기" - -#define D_OTHER_PARAMETERS "기타 상세" -#define D_TEMPLATE "템플릿" -#define D_ACTIVATE "활성" -#define D_WEB_ADMIN_PASSWORD "Web Admin 비밀번호" -#define D_MQTT_ENABLE "MQTT 사용" -#define D_FRIENDLY_NAME "별칭" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "single device" -#define D_MULTI_DEVICE "multi device" - -#define D_CONFIGURE_TEMPLATE "템플릿 설정" -#define D_TEMPLATE_PARAMETERS "템플릿 상세" -#define D_TEMPLATE_NAME "이름" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "옵션" - -#define D_SAVE_CONFIGURATION "설정 저장" -#define D_CONFIGURATION_SAVED "설정 저장 완료" -#define D_CONFIGURATION_RESET "설정 초기화" - -#define D_PROGRAM_VERSION "프로그램 버전" -#define D_BUILD_DATE_AND_TIME "빌드 날짜" -#define D_CORE_AND_SDK_VERSION "Core/SDK 버전" -#define D_FLASH_WRITE_COUNT "플래시 쓰기 횟수" -#define D_MAC_ADDRESS "MAC 주소" -#define D_MQTT_HOST "MQTT 호스트" -#define D_MQTT_PORT "MQTT 포트" -#define D_MQTT_CLIENT "MQTT 클라이언트" -#define D_MQTT_USER "MQTT 아이디" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash 용량" -#define D_FREE_PROGRAM_SPACE "여유 프로그램 공간" - -#define D_UPGRADE_BY_WEBSERVER "웹 서버에서 업그레이드" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "업그레이드 시작" -#define D_UPGRADE_BY_FILE_UPLOAD "업로드 된 파일로 업그레이드" -#define D_UPLOAD_STARTED "업로드 시작됨" -#define D_UPGRADE_STARTED "업그레이드 시작됨" -#define D_UPLOAD_DONE "업그레이드 완료" -#define D_UPLOAD_ERR_1 "파일이 선택되지 않았습니다" -#define D_UPLOAD_ERR_2 "용량이 충분하지 않습니다" -#define D_UPLOAD_ERR_3 "Magic 바이트가 0xE9가 아닙니다" -#define D_UPLOAD_ERR_4 "플래시 프로그램이 실제 플래시 용량보다 큽니다" -#define D_UPLOAD_ERR_5 "업로드 버퍼가 일치하지 않습니다" -#define D_UPLOAD_ERR_6 "업로드 실패. 로그 3 사용" -#define D_UPLOAD_ERR_7 "업로드 중단" -#define D_UPLOAD_ERR_8 "파일이 유효하지 않습니다" -#define D_UPLOAD_ERR_9 "용량이 초과되었습니다" -#define D_UPLOAD_ERR_10 "RF chip 초기화 실패" -#define D_UPLOAD_ERR_11 "RF chip 삭제 실패" -#define D_UPLOAD_ERR_12 "RF chip 쓰기 실패" -#define D_UPLOAD_ERR_13 "RF 펌웨어 decode 실패" -#define D_UPLOAD_ERROR_CODE "업로드 에러 코드" - -#define D_ENTER_COMMAND "명령 입력" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "응답이 있다면 Weblog 2를 사용" -#define D_NEED_USER_AND_PASSWORD "user=<아이디>&password=<비밀번호> 필요" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "TLS 지문 확인..." -#define D_TLS_CONNECT_FAILED_TO "TLS 연결 실패" -#define D_RETRY_IN "재시도 중" -#define D_VERIFIED "지문 확인 완료" -#define D_INSECURE "유효하지 않은 지문으로 연결이 되지 않았습니다" -#define D_CONNECT_FAILED_TO "연결 실패" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast 사용 불가" -#define D_MULTICAST_REJOINED "Multicast (다시)가입됨" -#define D_MULTICAST_JOIN_FAILED "Multicast 가입 실패" -#define D_FAILED_TO_SEND_RESPONSE "요청 전송 실패" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo 기본 이벤트" -#define D_WEMO_EVENT_SERVICE "WeMo 이벤트 서비스" -#define D_WEMO_META_SERVICE "WeMo meta 서비스" -#define D_WEMO_SETUP "WeMo 설정" -#define D_RESPONSE_SENT "요청 전송됨" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue 설정" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API가 포함되지 않음" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 요청 패킷이 전송됨" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz 상세" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "스위치 idx" -#define D_DOMOTICZ_SENSOR_IDX "센서 idx" - #define D_DOMOTICZ_TEMP "온도" - #define D_DOMOTICZ_TEMP_HUM "온도,습도" - #define D_DOMOTICZ_TEMP_HUM_BARO "온도,습도,기압" - #define D_DOMOTICZ_POWER_ENERGY "전력,전력량" - #define D_DOMOTICZ_ILLUMINANCE "조도" - #define D_DOMOTICZ_COUNT "횟수/PM1" - #define D_DOMOTICZ_VOLTAGE "전압/PM2.5" - #define D_DOMOTICZ_CURRENT "전류/PM10" - #define D_DOMOTICZ_AIRQUALITY "공기질" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "타이머 갱신" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "타이머 설정" -#define D_TIMER_PARAMETERS "타이머 상세" -#define D_TIMER_ENABLE "타이머 사용" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "시간" -#define D_TIMER_DAYS "일" -#define D_TIMER_REPEAT "반복" -#define D_TIMER_OUTPUT "출력" -#define D_TIMER_ACTION "행동" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX 설정" -#define D_KNX_PARAMETERS "KNX 상세" -#define D_KNX_GENERAL_CONFIG "일반" -#define D_KNX_PHYSICAL_ADDRESS "물리적 주소" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( KNX 네트워크 상에서 반드시 고유한 이름이어야 합니다 )" -#define D_KNX_ENABLE "KNX 사용" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "그룹 주소로 데이타를 보냅니다" -#define D_ADD "추가" -#define D_DELETE "삭제" -#define D_REPLY "응답" -#define D_KNX_GROUP_ADDRESS_TO_READ "받은 데이터의 그룹 주소" -#define D_LOG_KNX "KNX: " -#define D_RECEIVED_FROM "다음에서 받음" -#define D_KNX_COMMAND_WRITE "쓰기" -#define D_KNX_COMMAND_READ "읽기" -#define D_KNX_COMMAND_OTHER "기타" -#define D_SENT_TO "다음으로 보내기" -#define D_KNX_WARNING "그룹 주소 ( 0 / 0 / 0 )은 예약되어 사용할 수 없습니다" -#define D_KNX_ENHANCEMENT "커뮤니케이션 강화" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "금일 전력 사용량" -#define D_ENERGY_YESTERDAY "어제 전력 사용량" -#define D_ENERGY_TOTAL "총 전력 사용량" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "센서가 사용 중" -#define D_SENSOR_CRC_ERROR "센서 CRC 에러" -#define D_SENSORS_FOUND "센서 발견" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "대기 시간 초과" -#define D_START_SIGNAL_LOW "시작 신호 낮음" -#define D_START_SIGNAL_HIGH "시작 신호 높음" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "체크섬 실패" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "센서가 ACK 명령을 수행하지 않음" -#define D_SHT1X_FOUND "SHT1X 발견" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "입자" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "중량 제거" -#define D_HX_CAL_REFERENCE "참조 중량 로드" -#define D_HX_CAL_DONE "교정됨" -#define D_HX_CAL_FAIL "교정 실패" -#define D_RESET_HX711 "스케일 초기화" -#define D_CONFIGURE_HX711 "스케일 설정" -#define D_HX711_PARAMETERS "스케일 상세" -#define D_ITEM_WEIGHT "아이템 중량" -#define D_REFERENCE_WEIGHT "참조 중량" -#define D_CALIBRATE "교정" -#define D_CALIBRATION "교정" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "풍향" -#define D_TX20_WIND_SPEED "풍속" -#define D_TX20_WIND_SPEED_AVG "평균 풍속" -#define D_TX20_WIND_SPEED_MAX "최대 풍속" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -//xsns_43_hre.ino -#define D_LOG_HRE "HRE: " - -// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "없음" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri" -#define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "시" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "마이크로미터" -#define D_UNIT_MICROSECOND "마이크로초" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "밀리초" -#define D_UNIT_MINUTE "분" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "초" -#define D_UNIT_SECTORS "섹터" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -// Log message prefix -#define D_LOG_APPLICATION "APP: " // Application -#define D_LOG_BRIDGE "BRG: " // Bridge -#define D_LOG_CONFIG "CFG: " // Settings -#define D_LOG_COMMAND "CMD: " // Command -#define D_LOG_DEBUG "DBG: " // Debug -#define D_LOG_DHT "DHT: " // DHT sensor -#define D_LOG_DOMOTICZ "DOM: " // Domoticz -#define D_LOG_DSB "DSB: " // DS18xB20 sensor -#define D_LOG_HTTP "HTP: " // HTTP webserver -#define D_LOG_I2C "I2C: " // I2C -#define D_LOG_IRR "IRR: " // Infra Red Received -#define D_LOG_LOG "LOG: " // Logging -#define D_LOG_MODULE "MOD: " // Module -#define D_LOG_MDNS "DNS: " // mDNS -#define D_LOG_MQTT "MQT: " // MQTT -#define D_LOG_OTHER "OTH: " // Other -#define D_LOG_RESULT "RSL: " // Result -#define D_LOG_RFR "RFR: " // RF Received -#define D_LOG_SERIAL "SER: " // Serial -#define D_LOG_SHT1 "SHT: " // SHT1x sensor -#define D_LOG_UPLOAD "UPL: " // Upload -#define D_LOG_UPNP "UPP: " // UPnP -#define D_LOG_WIFI "WIF: " // Wifi - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_KO_KO_H_ +/* + ko-KO.h - localization for Korean - Korean for Tasmota + + Copyright (C) 2019 Theo Arends (translated by NyaamZ) + + 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 . +*/ + +#ifndef _LANGUAGE_KO_KO_H_ +#define _LANGUAGE_KO_KO_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.2.1.11 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +// https://www.science.co.il/language/Locale-codes.php +#define LANGUAGE_LCID 1042 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "ko" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "일 월 화 수 목 금 토 " +#define D_MONTH3LIST "1월 2월 3월 4월 5월 6월 7월 8월 9월 10월11월12월" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "공기질" +#define D_AP "AP" // Access Point +#define D_AS "as" +#define D_AUTO "자동" +#define D_BLINK "깜박임" +#define D_BLINKOFF "깜박임 끄기" +#define D_BOOT_COUNT "가동횟수" +#define D_BRIGHTLIGHT "밝기" +#define D_BSSID "BSSId" +#define D_BUTTON "버튼" +#define D_BY "by" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "섭씨" +#define D_CHANNEL "채널" +#define D_CO2 "이산화탄소" +#define D_CODE "코드" // Button code +#define D_COLDLIGHT "차갑게" +#define D_COMMAND "명령" +#define D_CONNECTED "연결됨" +#define D_COUNT "횟수" +#define D_COUNTER "Counter" +#define D_CURRENT "전류" // As in Voltage and Current +#define D_DATA "데이터" +#define D_DARKLIGHT "어둡게" +#define D_DEBUG "디버그" +#define D_DISABLED "사용 불가" +#define D_DISTANCE "거리" +#define D_DNS_SERVER "DNS 서버" +#define D_DONE "완료" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "에뮬레이션" +#define D_ENABLED "사용 가능" +#define D_ERASE "삭제" +#define D_ERROR "에러" +#define D_FAHRENHEIT "화씨" +#define D_FAILED "실패" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "거짓" +#define D_FILE "파일" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "남은 메모리" +#define D_FREQUENCY "빈도" +#define D_GAS "가스" +#define D_GATEWAY "게이트웨이" +#define D_GROUP "그룹" +#define D_HOST "호스트" +#define D_HOSTNAME "호스트이름" +#define D_HUMIDITY "습도" +#define D_ILLUMINANCE "조도" +#define D_IMMEDIATE "immediate" // Button immediate +#define D_INDEX "인덱스" +#define D_INFO "정보" +#define D_INFRARED "적외선" +#define D_INITIALIZED "초기화 완료" +#define D_IP_ADDRESS "IP 주소" +#define D_LIGHT "밝게" +#define D_LWT "LWT" +#define D_MODULE "모듈" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-press" +#define D_NOISE "소음" +#define D_NONE "없음" +#define D_OFF "꺼짐" +#define D_OFFLINE "오프라인" +#define D_OK "Ok" +#define D_ON "켜짐" +#define D_ONLINE "온라인" +#define D_PASSWORD "비밀번호" +#define D_PORT "포트" +#define D_POWER_FACTOR "Power Factor" +#define D_POWERUSAGE "전원" +#define D_POWERUSAGE_ACTIVE "Active Power" +#define D_POWERUSAGE_APPARENT "Apparent Power" +#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_PRESSURE "기압" +#define D_PRESSUREATSEALEVEL "해수면기압" +#define D_PROGRAM_FLASH_SIZE "플래시 용량" +#define D_PROGRAM_SIZE "프로그램 용량" +#define D_PROJECT "프로젝트" +#define D_RAIN "비" +#define D_RECEIVED "받음" +#define D_RESTART "재시작" +#define D_RESTARTING "재시작 중" +#define D_RESTART_REASON "재시작 이유" +#define D_RESTORE "복구" +#define D_RETAINED "보류" +#define D_RULE "규칙" +#define D_SAVE "저장" +#define D_SENSOR "센서" +#define D_SSID "SSId" +#define D_START "시작" +#define D_STD_TIME "STD" +#define D_STOP "정지" +#define D_SUBNET_MASK "서브넷 마스크" +#define D_SUBSCRIBE_TO "구독" +#define D_UNSUBSCRIBE_FROM "구독 해제" +#define D_SUCCESSFUL "성공" +#define D_SUNRISE "일출" +#define D_SUNSET "일몰" +#define D_TEMPERATURE "온도" +#define D_TO "to" +#define D_TOGGLE "전환" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "전송" +#define D_TRUE "참" +#define D_TVOC "TVOC" +#define D_UPGRADE "업그레이드" +#define D_UPLOAD "업로드" +#define D_UPTIME "가동시간" +#define D_USER "User" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV 색인" +#define D_UV_INDEX_1 "낮음" +#define D_UV_INDEX_2 "보통" +#define D_UV_INDEX_3 "높음" +#define D_UV_INDEX_4 "위험" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" // Out of Range +#define D_UV_LEVEL "UV 레벨" +#define D_UV_POWER "UV 파워" +#define D_VERSION "버전" +#define D_VOLTAGE "전압" +#define D_WEIGHT "무게" +#define D_WARMLIGHT "따뜻하게" +#define D_WEB_SERVER "웹 서버" + +// sonoff.ino +#define D_WARNING_MINIMAL_VERSION "경고: 이 버전은 영구 설정을 지원하지 않습니다" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serial log 사용 안함" +#define D_SYSLOG_LOGGING_REENABLED "Syslog log 다시 사용" + +#define D_SET_BAUDRATE_TO "Set Baudrate to" +#define D_RECEIVED_TOPIC "Received Topic" +#define D_DATA_SIZE "데이터 용량" +#define D_ANALOG_INPUT "아날로그" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPS설정 실패" +#define D_ACTIVE_FOR_3_MINUTES "3분동안 활성화" +#define D_FAILED_TO_START "시작 실패" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "AP에 연결 중" +#define D_IN_MODE "in mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP 주소가 수신되지 않아 연결이 실패했습니다" +#define D_CONNECT_FAILED_AP_NOT_REACHED "연결이 닿지 않아 AP에 연결할 수 없습니다" +#define D_CONNECT_FAILED_WRONG_PASSWORD "비밀번호가 틀려 AP에 연결할 수 없습니다" +#define D_CONNECT_FAILED_AP_TIMEOUT "시간초과로 AP에 연결할 수 없습니다" +#define D_ATTEMPTING_CONNECTION "연결 시도 중..." +#define D_CHECKING_CONNECTION "연결 체크 중..." +#define D_QUERY_DONE "쿼리 완료. MQTT 서비스 발견" +#define D_MQTT_SERVICE_FOUND "MQTT 서비스 발견" +#define D_FOUND_AT "다음에서 발견" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog 호스트가 발견되지 않았습니다" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "플래시에 저장" +#define D_LOADED_FROM_FLASH_AT "플래시에서 로드" +#define D_USE_DEFAULTS "디폴트 사용" +#define D_ERASED_SECTOR "삭제된 섹터" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오." +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" +#define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중" +#define D_WITH_IP_ADDRESS "IP 주소" +#define D_WEBSERVER_STOPPED "Web 서버 멈춤" +#define D_FILE_NOT_FOUND "파일을 찾을 수 없습니다" +#define D_REDIRECTED "인증 페이지로 리디렉션" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "와이파이 매니저가 AccessPoint와 keep Station을 설정" +#define D_WIFIMANAGER_SET_ACCESSPOINT "와이파이 매니저가 AccessPoint를 설정" +#define D_TRYING_TO_CONNECT "장치를 네트워크에 연결하려고 시도 중" + +#define D_RESTART_IN "재시작" +#define D_SECONDS "초" +#define D_DEVICE_WILL_RESTART "이 장치는 몇 초 후 재시작됩니다" +#define D_BUTTON_TOGGLE "켜기/끄기" +#define D_CONFIGURATION "설정" +#define D_INFORMATION "정보" +#define D_FIRMWARE_UPGRADE "펌웨어 업그레이드" +#define D_CONSOLE "콘솔" +#define D_CONFIRM_RESTART "재시작" + +#define D_CONFIGURE_MODULE "모듈 설정" +#define D_CONFIGURE_WIFI "WiFi 설정" +#define D_CONFIGURE_MQTT "MQTT 설정" +#define D_CONFIGURE_DOMOTICZ "Domoticz 설정" +#define D_CONFIGURE_LOGGING "로그 설정" +#define D_CONFIGURE_OTHER "기타 설정" +#define D_CONFIRM_RESET_CONFIGURATION "설정 초기화 확인" +#define D_RESET_CONFIGURATION "설정 초기화" +#define D_BACKUP_CONFIGURATION "백업 설정" +#define D_RESTORE_CONFIGURATION "복원 설정" +#define D_MAIN_MENU "메인 메뉴" + +#define D_MODULE_PARAMETERS "모듈 상세" +#define D_MODULE_TYPE "모듈 타입" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Wifi 상세" +#define D_SCAN_FOR_WIFI_NETWORKS "Wifi 네트워크를 검색 중" +#define D_SCAN_DONE "검색 완료" +#define D_NO_NETWORKS_FOUND "발견된 네트워크가 없습니다" +#define D_REFRESH_TO_SCAN_AGAIN "검색 재시도" +#define D_DUPLICATE_ACCESSPOINT "중복된 AccessPoint" +#define D_SKIPPING_LOW_QUALITY "약한 네트워크 신호 무시" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 비밀번호" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 비밀번호" + +#define D_MQTT_PARAMETERS "MQTT 상세" +#define D_CLIENT "클라이언트" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "로그 상세" +#define D_SERIAL_LOG_LEVEL "시리얼 로그 레벨" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web 로그 레벨" +#define D_SYS_LOG_LEVEL "Syslog 로그 레벨" +#define D_MORE_DEBUG "More debug" +#define D_SYSLOG_HOST "Syslog 호스트" +#define D_SYSLOG_PORT "Syslog 포트" +#define D_TELEMETRY_PERIOD "보고 주기" + +#define D_OTHER_PARAMETERS "기타 상세" +#define D_TEMPLATE "템플릿" +#define D_ACTIVATE "활성" +#define D_WEB_ADMIN_PASSWORD "Web Admin 비밀번호" +#define D_MQTT_ENABLE "MQTT 사용" +#define D_FRIENDLY_NAME "별칭" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "single device" +#define D_MULTI_DEVICE "multi device" + +#define D_CONFIGURE_TEMPLATE "템플릿 설정" +#define D_TEMPLATE_PARAMETERS "템플릿 상세" +#define D_TEMPLATE_NAME "이름" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "옵션" + +#define D_SAVE_CONFIGURATION "설정 저장" +#define D_CONFIGURATION_SAVED "설정 저장 완료" +#define D_CONFIGURATION_RESET "설정 초기화" + +#define D_PROGRAM_VERSION "프로그램 버전" +#define D_BUILD_DATE_AND_TIME "빌드 날짜" +#define D_CORE_AND_SDK_VERSION "Core/SDK 버전" +#define D_FLASH_WRITE_COUNT "플래시 쓰기 횟수" +#define D_MAC_ADDRESS "MAC 주소" +#define D_MQTT_HOST "MQTT 호스트" +#define D_MQTT_PORT "MQTT 포트" +#define D_MQTT_CLIENT "MQTT 클라이언트" +#define D_MQTT_USER "MQTT 아이디" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash 용량" +#define D_FREE_PROGRAM_SPACE "여유 프로그램 공간" + +#define D_UPGRADE_BY_WEBSERVER "웹 서버에서 업그레이드" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "업그레이드 시작" +#define D_UPGRADE_BY_FILE_UPLOAD "업로드 된 파일로 업그레이드" +#define D_UPLOAD_STARTED "업로드 시작됨" +#define D_UPGRADE_STARTED "업그레이드 시작됨" +#define D_UPLOAD_DONE "업그레이드 완료" +#define D_UPLOAD_ERR_1 "파일이 선택되지 않았습니다" +#define D_UPLOAD_ERR_2 "용량이 충분하지 않습니다" +#define D_UPLOAD_ERR_3 "Magic 바이트가 0xE9가 아닙니다" +#define D_UPLOAD_ERR_4 "플래시 프로그램이 실제 플래시 용량보다 큽니다" +#define D_UPLOAD_ERR_5 "업로드 버퍼가 일치하지 않습니다" +#define D_UPLOAD_ERR_6 "업로드 실패. 로그 3 사용" +#define D_UPLOAD_ERR_7 "업로드 중단" +#define D_UPLOAD_ERR_8 "파일이 유효하지 않습니다" +#define D_UPLOAD_ERR_9 "용량이 초과되었습니다" +#define D_UPLOAD_ERR_10 "RF chip 초기화 실패" +#define D_UPLOAD_ERR_11 "RF chip 삭제 실패" +#define D_UPLOAD_ERR_12 "RF chip 쓰기 실패" +#define D_UPLOAD_ERR_13 "RF 펌웨어 decode 실패" +#define D_UPLOAD_ERROR_CODE "업로드 에러 코드" + +#define D_ENTER_COMMAND "명령 입력" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "응답이 있다면 Weblog 2를 사용" +#define D_NEED_USER_AND_PASSWORD "user=<아이디>&password=<비밀번호> 필요" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "TLS 지문 확인..." +#define D_TLS_CONNECT_FAILED_TO "TLS 연결 실패" +#define D_RETRY_IN "재시도 중" +#define D_VERIFIED "지문 확인 완료" +#define D_INSECURE "유효하지 않은 지문으로 연결이 되지 않았습니다" +#define D_CONNECT_FAILED_TO "연결 실패" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast 사용 불가" +#define D_MULTICAST_REJOINED "Multicast (다시)가입됨" +#define D_MULTICAST_JOIN_FAILED "Multicast 가입 실패" +#define D_FAILED_TO_SEND_RESPONSE "요청 전송 실패" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo 기본 이벤트" +#define D_WEMO_EVENT_SERVICE "WeMo 이벤트 서비스" +#define D_WEMO_META_SERVICE "WeMo meta 서비스" +#define D_WEMO_SETUP "WeMo 설정" +#define D_RESPONSE_SENT "요청 전송됨" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue 설정" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API가 포함되지 않음" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 요청 패킷이 전송됨" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz 상세" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "스위치 idx" +#define D_DOMOTICZ_SENSOR_IDX "센서 idx" + #define D_DOMOTICZ_TEMP "온도" + #define D_DOMOTICZ_TEMP_HUM "온도,습도" + #define D_DOMOTICZ_TEMP_HUM_BARO "온도,습도,기압" + #define D_DOMOTICZ_POWER_ENERGY "전력,전력량" + #define D_DOMOTICZ_ILLUMINANCE "조도" + #define D_DOMOTICZ_COUNT "횟수/PM1" + #define D_DOMOTICZ_VOLTAGE "전압/PM2.5" + #define D_DOMOTICZ_CURRENT "전류/PM10" + #define D_DOMOTICZ_AIRQUALITY "공기질" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "타이머 갱신" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "타이머 설정" +#define D_TIMER_PARAMETERS "타이머 상세" +#define D_TIMER_ENABLE "타이머 사용" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "시간" +#define D_TIMER_DAYS "일" +#define D_TIMER_REPEAT "반복" +#define D_TIMER_OUTPUT "출력" +#define D_TIMER_ACTION "행동" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX 설정" +#define D_KNX_PARAMETERS "KNX 상세" +#define D_KNX_GENERAL_CONFIG "일반" +#define D_KNX_PHYSICAL_ADDRESS "물리적 주소" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( KNX 네트워크 상에서 반드시 고유한 이름이어야 합니다 )" +#define D_KNX_ENABLE "KNX 사용" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "그룹 주소로 데이타를 보냅니다" +#define D_ADD "추가" +#define D_DELETE "삭제" +#define D_REPLY "응답" +#define D_KNX_GROUP_ADDRESS_TO_READ "받은 데이터의 그룹 주소" +#define D_LOG_KNX "KNX: " +#define D_RECEIVED_FROM "다음에서 받음" +#define D_KNX_COMMAND_WRITE "쓰기" +#define D_KNX_COMMAND_READ "읽기" +#define D_KNX_COMMAND_OTHER "기타" +#define D_SENT_TO "다음으로 보내기" +#define D_KNX_WARNING "그룹 주소 ( 0 / 0 / 0 )은 예약되어 사용할 수 없습니다" +#define D_KNX_ENHANCEMENT "커뮤니케이션 강화" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "금일 전력 사용량" +#define D_ENERGY_YESTERDAY "어제 전력 사용량" +#define D_ENERGY_TOTAL "총 전력 사용량" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "센서가 사용 중" +#define D_SENSOR_CRC_ERROR "센서 CRC 에러" +#define D_SENSORS_FOUND "센서 발견" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "대기 시간 초과" +#define D_START_SIGNAL_LOW "시작 신호 낮음" +#define D_START_SIGNAL_HIGH "시작 신호 높음" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "체크섬 실패" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "센서가 ACK 명령을 수행하지 않음" +#define D_SHT1X_FOUND "SHT1X 발견" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "입자" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "중량 제거" +#define D_HX_CAL_REFERENCE "참조 중량 로드" +#define D_HX_CAL_DONE "교정됨" +#define D_HX_CAL_FAIL "교정 실패" +#define D_RESET_HX711 "스케일 초기화" +#define D_CONFIGURE_HX711 "스케일 설정" +#define D_HX711_PARAMETERS "스케일 상세" +#define D_ITEM_WEIGHT "아이템 중량" +#define D_REFERENCE_WEIGHT "참조 중량" +#define D_CALIBRATE "교정" +#define D_CALIBRATION "교정" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "풍향" +#define D_TX20_WIND_SPEED "풍속" +#define D_TX20_WIND_SPEED_AVG "평균 풍속" +#define D_TX20_WIND_SPEED_MAX "최대 풍속" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +//xsns_43_hre.ino +#define D_LOG_HRE "HRE: " + +// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "없음" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri" +#define D_SENSOR_SR04_ECHO "SR04 Ech" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "시" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "마이크로미터" +#define D_UNIT_MICROSECOND "마이크로초" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "밀리초" +#define D_UNIT_MINUTE "분" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "초" +#define D_UNIT_SECTORS "섹터" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +// Log message prefix +#define D_LOG_APPLICATION "APP: " // Application +#define D_LOG_BRIDGE "BRG: " // Bridge +#define D_LOG_CONFIG "CFG: " // Settings +#define D_LOG_COMMAND "CMD: " // Command +#define D_LOG_DEBUG "DBG: " // Debug +#define D_LOG_DHT "DHT: " // DHT sensor +#define D_LOG_DOMOTICZ "DOM: " // Domoticz +#define D_LOG_DSB "DSB: " // DS18xB20 sensor +#define D_LOG_HTTP "HTP: " // HTTP webserver +#define D_LOG_I2C "I2C: " // I2C +#define D_LOG_IRR "IRR: " // Infra Red Received +#define D_LOG_LOG "LOG: " // Logging +#define D_LOG_MODULE "MOD: " // Module +#define D_LOG_MDNS "DNS: " // mDNS +#define D_LOG_MQTT "MQT: " // MQTT +#define D_LOG_OTHER "OTH: " // Other +#define D_LOG_RESULT "RSL: " // Result +#define D_LOG_RFR "RFR: " // RF Received +#define D_LOG_SERIAL "SER: " // Serial +#define D_LOG_SHT1 "SHT: " // SHT1x sensor +#define D_LOG_UPLOAD "UPL: " // Upload +#define D_LOG_UPNP "UPP: " // UPnP +#define D_LOG_WIFI "WIF: " // Wifi + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_KO_KO_H_ diff --git a/sonoff/language/nl-NL.h b/tasmota/language/nl-NL.h similarity index 100% rename from sonoff/language/nl-NL.h rename to tasmota/language/nl-NL.h diff --git a/sonoff/language/pl-PL.h b/tasmota/language/pl-PL.h similarity index 100% rename from sonoff/language/pl-PL.h rename to tasmota/language/pl-PL.h diff --git a/sonoff/language/pt-BR.h b/tasmota/language/pt-BR.h similarity index 100% rename from sonoff/language/pt-BR.h rename to tasmota/language/pt-BR.h diff --git a/sonoff/language/pt-PT.h b/tasmota/language/pt-PT.h similarity index 100% rename from sonoff/language/pt-PT.h rename to tasmota/language/pt-PT.h diff --git a/sonoff/language/ru-RU.h b/tasmota/language/ru-RU.h similarity index 100% rename from sonoff/language/ru-RU.h rename to tasmota/language/ru-RU.h diff --git a/sonoff/language/sk-SK.h b/tasmota/language/sk-SK.h similarity index 100% rename from sonoff/language/sk-SK.h rename to tasmota/language/sk-SK.h diff --git a/sonoff/language/sv-SE.h b/tasmota/language/sv-SE.h similarity index 100% rename from sonoff/language/sv-SE.h rename to tasmota/language/sv-SE.h diff --git a/sonoff/language/tr-TR.h b/tasmota/language/tr-TR.h old mode 100755 new mode 100644 similarity index 100% rename from sonoff/language/tr-TR.h rename to tasmota/language/tr-TR.h diff --git a/sonoff/language/uk-UK.h b/tasmota/language/uk-UK.h similarity index 100% rename from sonoff/language/uk-UK.h rename to tasmota/language/uk-UK.h diff --git a/sonoff/language/zh-CN.h b/tasmota/language/zh-CN.h similarity index 100% rename from sonoff/language/zh-CN.h rename to tasmota/language/zh-CN.h diff --git a/sonoff/language/zh-TW.h b/tasmota/language/zh-TW.h similarity index 100% rename from sonoff/language/zh-TW.h rename to tasmota/language/zh-TW.h diff --git a/sonoff/my_user_config.h b/tasmota/my_user_config.h similarity index 98% rename from sonoff/my_user_config.h rename to tasmota/my_user_config.h index 48be22390..6a46a15bb 100644 --- a/sonoff/my_user_config.h +++ b/tasmota/my_user_config.h @@ -47,10 +47,10 @@ #define CFG_HOLDER 4617 // [Reset 1] Change this value (max 32000) to load SECTION1 configuration parameters to flash // -- Project ------------------------------------- -#define PROJECT "sonoff" // PROJECT is used as the default topic delimiter +#define PROJECT "tasmota" // PROJECT is used as the default topic delimiter // If not selected the default will be SONOFF_BASIC -//#define MODULE SONOFF_BASIC // [Module] Select default model from sonoff_template.h +//#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) @@ -106,13 +106,13 @@ #define MQTT_FULLTOPIC "%prefix%/%topic%/" // [FullTopic] Subscribe and Publish full topic name - Legacy topic // %prefix% token options -#define SUB_PREFIX "cmnd" // [Prefix1] Sonoff devices subscribe to %prefix%/%topic% being SUB_PREFIX/MQTT_TOPIC and SUB_PREFIX/MQTT_GRPTOPIC -#define PUB_PREFIX "stat" // [Prefix2] Sonoff devices publish to %prefix%/%topic% being PUB_PREFIX/MQTT_TOPIC -#define PUB_PREFIX2 "tele" // [Prefix3] Sonoff devices publish telemetry data to %prefix%/%topic% being PUB_PREFIX2/MQTT_TOPIC/UPTIME, POWER and TIME +#define SUB_PREFIX "cmnd" // [Prefix1] Tasmota devices subscribe to %prefix%/%topic% being SUB_PREFIX/MQTT_TOPIC and SUB_PREFIX/MQTT_GRPTOPIC +#define PUB_PREFIX "stat" // [Prefix2] Tasmota devices publish to %prefix%/%topic% being PUB_PREFIX/MQTT_TOPIC +#define PUB_PREFIX2 "tele" // [Prefix3] Tasmota devices publish telemetry data to %prefix%/%topic% being PUB_PREFIX2/MQTT_TOPIC/UPTIME, POWER and TIME // May be named the same as PUB_PREFIX // %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 "sonoffs" // [GroupTopic] MQTT Group topic +#define MQTT_GRPTOPIC "tasmotas" // [GroupTopic] MQTT Group topic #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 @@ -130,7 +130,7 @@ // -- HTTP ---------------------------------------- #define WEB_SERVER 2 // [WebServer] Web server (0 = Off, 1 = Start as User, 2 = Start as Admin) #define WEB_PASSWORD "" // [WebPassword] Web server Admin mode Password for WEB_USERNAME (empty string = Disable) -#define FRIENDLY_NAME "Sonoff" // [FriendlyName] Friendlyname up to 32 characters used by webpages and Alexa +#define FRIENDLY_NAME "Tasmota" // [FriendlyName] Friendlyname up to 32 characters used by webpages and Alexa #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) // HTML hex color codes. Only 3 and 6 digit hex string values are supported!! See https://www.w3schools.com/colors/colors_hex.asp #define COLOR_TEXT "#000" // [WebColor1] Global text color - Black @@ -263,7 +263,7 @@ // #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use (+2.2k code, +1.9k mem during connection handshake) // #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem) // #define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+11.9k code, +0.4k mem) - // Note: you need to generate a private key + certificate per device and update 'sonoff/sonoff_aws_iot.cpp' + // Note: you need to generate a private key + certificate per device and update 'tasmota/tasmota_aws_iot.cpp' // Full documentation here: https://github.com/arendst/Tasmota/wiki/AWS-IoT // -- KNX IP Protocol ----------------------------- @@ -551,7 +551,7 @@ /*********************************************************************************************\ * Optional firmware configurations - * Select none or just one for optional features and sensors as configured in sonoff_post.h + * Select none or just one for optional features and sensors as configured in tasmota_post.h * See RELEASENOTES.md for selected features \*********************************************************************************************/ diff --git a/sonoff/sendemail.h b/tasmota/sendemail.h old mode 100755 new mode 100644 similarity index 100% rename from sonoff/sendemail.h rename to tasmota/sendemail.h diff --git a/sonoff/sendemail.ino b/tasmota/sendemail.ino old mode 100755 new mode 100644 similarity index 100% rename from sonoff/sendemail.ino rename to tasmota/sendemail.ino diff --git a/sonoff/settings.h b/tasmota/settings.h similarity index 100% rename from sonoff/settings.h rename to tasmota/settings.h diff --git a/sonoff/settings.ino b/tasmota/settings.ino similarity index 100% rename from sonoff/settings.ino rename to tasmota/settings.ino diff --git a/sonoff/support.ino b/tasmota/support.ino similarity index 100% rename from sonoff/support.ino rename to tasmota/support.ino diff --git a/sonoff/support_button.ino b/tasmota/support_button.ino similarity index 100% rename from sonoff/support_button.ino rename to tasmota/support_button.ino diff --git a/sonoff/support_command.ino b/tasmota/support_command.ino similarity index 100% rename from sonoff/support_command.ino rename to tasmota/support_command.ino diff --git a/sonoff/support_features.ino b/tasmota/support_features.ino similarity index 100% rename from sonoff/support_features.ino rename to tasmota/support_features.ino diff --git a/sonoff/support_float.ino b/tasmota/support_float.ino similarity index 100% rename from sonoff/support_float.ino rename to tasmota/support_float.ino diff --git a/sonoff/support_rotary.ino b/tasmota/support_rotary.ino similarity index 100% rename from sonoff/support_rotary.ino rename to tasmota/support_rotary.ino diff --git a/sonoff/support_rtc.ino b/tasmota/support_rtc.ino similarity index 100% rename from sonoff/support_rtc.ino rename to tasmota/support_rtc.ino diff --git a/sonoff/support_static_buffer.ino b/tasmota/support_static_buffer.ino similarity index 100% rename from sonoff/support_static_buffer.ino rename to tasmota/support_static_buffer.ino diff --git a/sonoff/support_switch.ino b/tasmota/support_switch.ino similarity index 100% rename from sonoff/support_switch.ino rename to tasmota/support_switch.ino diff --git a/sonoff/support_udp.ino b/tasmota/support_udp.ino similarity index 100% rename from sonoff/support_udp.ino rename to tasmota/support_udp.ino diff --git a/sonoff/support_wifi.ino b/tasmota/support_wifi.ino similarity index 100% rename from sonoff/support_wifi.ino rename to tasmota/support_wifi.ino diff --git a/sonoff/sonoff.h b/tasmota/tasmota.h similarity index 99% rename from sonoff/sonoff.h rename to tasmota/tasmota.h index 2b2d12048..73fc192a8 100644 --- a/sonoff/sonoff.h +++ b/tasmota/tasmota.h @@ -1,5 +1,5 @@ /* - sonoff.h - Master header file for Tasmota + tasmota.h - Master header file for Tasmota Copyright (C) 2019 Theo Arends @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef _SONOFF_H_ -#define _SONOFF_H_ +#ifndef _TASMOTA_H_ +#define _TASMOTA_H_ /*********************************************************************************************\ * Performance ROM (PROGMEM) vs RAM (RODATA) @@ -285,4 +285,4 @@ const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Seri const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; -#endif // _SONOFF_H_ +#endif // _TASMOTA_H_ diff --git a/sonoff/sonoff.ino b/tasmota/tasmota.ino old mode 100755 new mode 100644 similarity index 99% rename from sonoff/sonoff.ino rename to tasmota/tasmota.ino index c369f20a1..c4526a808 --- a/sonoff/sonoff.ino +++ b/tasmota/tasmota.ino @@ -1,5 +1,5 @@ /* - sonoff.ino - Tasmota firmware for iTead Sonoff, Wemos and NodeMCU hardware + tasmota.ino - Tasmota firmware for iTead Sonoff, Wemos and NodeMCU hardware Copyright (C) 2019 Theo Arends @@ -27,15 +27,15 @@ // Location specific includes #include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) -#include "sonoff_version.h" // Tasmota version information -#include "sonoff.h" // Enumeration used in my_user_config.h +#include "tasmota_version.h" // Tasmota version information +#include "tasmota.h" // Enumeration used in my_user_config.h #include "my_user_config.h" // Fixed user configurable options #ifdef USE_MQTT_TLS - #include // we need to include before "sonoff_post.h" to take precedence over the BearSSL version in Arduino + #include // we need to include before "tasmota_post.h" to take precedence over the BearSSL version in Arduino #endif // USE_MQTT_TLS -#include "sonoff_post.h" // Configuration overrides for all previous includes +#include "tasmota_post.h" // Configuration overrides for all previous includes #include "i18n.h" // Language support configured by my_user_config.h -#include "sonoff_template.h" // Hardware configuration +#include "tasmota_template.h" // Hardware configuration #ifdef ARDUINO_ESP8266_RELEASE_2_4_0 @@ -102,7 +102,7 @@ int baudrate = APP_BAUDRATE; // Serial interface baud rate int serial_in_byte_counter = 0; // Index in receive buffer int ota_state_flag = 0; // OTA state flag int ota_result = 0; // OTA result -int restart_flag = 0; // Sonoff restart flag +int restart_flag = 0; // Tasmota restart flag int wifi_state_flag = WIFI_RESTART; // Wifi state flag int tele_period = 1; // Tele period timer int blinks = 201; // Number of LED blinks diff --git a/sonoff/sonoff_ca.ino b/tasmota/tasmota_ca.ino similarity index 98% rename from sonoff/sonoff_ca.ino rename to tasmota/tasmota_ca.ino index f34b87dec..3df65c9b9 100644 --- a/sonoff/sonoff_ca.ino +++ b/tasmota/tasmota_ca.ino @@ -1,5 +1,5 @@ /* - sonoff_ca.ino - Certificate authorities for Tasmota, LetsEncrypt and AWS + tasmota_ca.ino - Certificate authorities for Tasmota, LetsEncrypt and AWS Copyright (C) 2019 Theo Arends diff --git a/sonoff/sonoff_post.h b/tasmota/tasmota_post.h similarity index 99% rename from sonoff/sonoff_post.h rename to tasmota/tasmota_post.h index 309cc4e32..09620c320 100644 --- a/sonoff/sonoff_post.h +++ b/tasmota/tasmota_post.h @@ -1,5 +1,5 @@ /* - sonoff_post.h - Post header file for Tasmota + tasmota_post.h - Post header file for Tasmota Copyright (C) 2019 Theo Arends @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef _SONOFF_POST_H_ -#define _SONOFF_POST_H_ +#ifndef _TASMOTA_POST_H_ +#define _TASMOTA_POST_H_ /*********************************************************************************************\ * Function declarations @@ -664,4 +664,4 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define DEBUG_SENSOR_LOG(...) #endif -#endif // _SONOFF_POST_H_ +#endif // _TASMOTA_POST_H_ diff --git a/sonoff/sonoff_template.h b/tasmota/tasmota_template.h similarity index 99% rename from sonoff/sonoff_template.h rename to tasmota/tasmota_template.h index a930dbd27..b63118bf3 100644 --- a/sonoff/sonoff_template.h +++ b/tasmota/tasmota_template.h @@ -1,5 +1,5 @@ /* - sonoff_template.h - template settings for Tasmota + tasmota_template.h - template settings for Tasmota Copyright (C) 2019 Theo Arends @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef _SONOFF_TEMPLATE_H_ -#define _SONOFF_TEMPLATE_H_ +#ifndef _TASMOTA_TEMPLATE_H_ +#define _TASMOTA_TEMPLATE_H_ // User selectable GPIO functionality // ATTENTION: Only add at the end of this list just before GPIO_SENSOR_END @@ -2163,4 +2163,4 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { } }; -#endif // _SONOFF_TEMPLATE_H_ +#endif // _TASMOTA_TEMPLATE_H_ diff --git a/sonoff/sonoff_version.h b/tasmota/tasmota_version.h similarity index 83% rename from sonoff/sonoff_version.h rename to tasmota/tasmota_version.h index 21ceb7cd4..695d14146 100644 --- a/sonoff/sonoff_version.h +++ b/tasmota/tasmota_version.h @@ -1,5 +1,5 @@ /* - sonoff_version.h - Version header file for Tasmota + tasmota_version.h - Version header file for Tasmota Copyright (C) 2019 Theo Arends @@ -17,9 +17,9 @@ along with this program. If not, see . */ -#ifndef _SONOFF_VERSION_H_ -#define _SONOFF_VERSION_H_ +#ifndef _TASMOTA_VERSION_H_ +#define _TASMOTA_VERSION_H_ const uint32_t VERSION = 0x06070101; -#endif // _SONOFF_VERSION_H_ +#endif // _TASMOTA_VERSION_H_ diff --git a/sonoff/user_config_override_sample.h b/tasmota/user_config_override_sample.h similarity index 100% rename from sonoff/user_config_override_sample.h rename to tasmota/user_config_override_sample.h diff --git a/sonoff/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino similarity index 100% rename from sonoff/xdrv_01_webserver.ino rename to tasmota/xdrv_01_webserver.ino diff --git a/sonoff/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino similarity index 100% rename from sonoff/xdrv_02_mqtt.ino rename to tasmota/xdrv_02_mqtt.ino diff --git a/sonoff/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino similarity index 100% rename from sonoff/xdrv_03_energy.ino rename to tasmota/xdrv_03_energy.ino diff --git a/sonoff/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino similarity index 100% rename from sonoff/xdrv_04_light.ino rename to tasmota/xdrv_04_light.ino diff --git a/sonoff/xdrv_05_irremote.ino b/tasmota/xdrv_05_irremote.ino similarity index 100% rename from sonoff/xdrv_05_irremote.ino rename to tasmota/xdrv_05_irremote.ino diff --git a/sonoff/xdrv_05_irremote_full.ino b/tasmota/xdrv_05_irremote_full.ino similarity index 100% rename from sonoff/xdrv_05_irremote_full.ino rename to tasmota/xdrv_05_irremote_full.ino diff --git a/sonoff/xdrv_06_snfbridge.ino b/tasmota/xdrv_06_snfbridge.ino similarity index 100% rename from sonoff/xdrv_06_snfbridge.ino rename to tasmota/xdrv_06_snfbridge.ino diff --git a/sonoff/xdrv_07_domoticz.ino b/tasmota/xdrv_07_domoticz.ino similarity index 100% rename from sonoff/xdrv_07_domoticz.ino rename to tasmota/xdrv_07_domoticz.ino diff --git a/sonoff/xdrv_08_serial_bridge.ino b/tasmota/xdrv_08_serial_bridge.ino similarity index 100% rename from sonoff/xdrv_08_serial_bridge.ino rename to tasmota/xdrv_08_serial_bridge.ino diff --git a/sonoff/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino similarity index 100% rename from sonoff/xdrv_09_timers.ino rename to tasmota/xdrv_09_timers.ino diff --git a/sonoff/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino similarity index 100% rename from sonoff/xdrv_10_rules.ino rename to tasmota/xdrv_10_rules.ino diff --git a/sonoff/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino similarity index 100% rename from sonoff/xdrv_10_scripter.ino rename to tasmota/xdrv_10_scripter.ino diff --git a/sonoff/xdrv_11_knx.ino b/tasmota/xdrv_11_knx.ino similarity index 100% rename from sonoff/xdrv_11_knx.ino rename to tasmota/xdrv_11_knx.ino diff --git a/sonoff/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino similarity index 100% rename from sonoff/xdrv_12_home_assistant.ino rename to tasmota/xdrv_12_home_assistant.ino diff --git a/sonoff/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino old mode 100755 new mode 100644 similarity index 100% rename from sonoff/xdrv_13_display.ino rename to tasmota/xdrv_13_display.ino diff --git a/sonoff/xdrv_14_mp3.ino b/tasmota/xdrv_14_mp3.ino similarity index 100% rename from sonoff/xdrv_14_mp3.ino rename to tasmota/xdrv_14_mp3.ino diff --git a/sonoff/xdrv_15_pca9685.ino b/tasmota/xdrv_15_pca9685.ino similarity index 100% rename from sonoff/xdrv_15_pca9685.ino rename to tasmota/xdrv_15_pca9685.ino diff --git a/sonoff/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino similarity index 100% rename from sonoff/xdrv_16_tuyamcu.ino rename to tasmota/xdrv_16_tuyamcu.ino diff --git a/sonoff/xdrv_17_rcswitch.ino b/tasmota/xdrv_17_rcswitch.ino similarity index 100% rename from sonoff/xdrv_17_rcswitch.ino rename to tasmota/xdrv_17_rcswitch.ino diff --git a/sonoff/xdrv_18_armtronix_dimmers.ino b/tasmota/xdrv_18_armtronix_dimmers.ino similarity index 100% rename from sonoff/xdrv_18_armtronix_dimmers.ino rename to tasmota/xdrv_18_armtronix_dimmers.ino diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/tasmota/xdrv_19_ps16dz_dimmer.ino similarity index 100% rename from sonoff/xdrv_19_ps16dz_dimmer.ino rename to tasmota/xdrv_19_ps16dz_dimmer.ino diff --git a/sonoff/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino similarity index 100% rename from sonoff/xdrv_20_hue.ino rename to tasmota/xdrv_20_hue.ino diff --git a/sonoff/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino similarity index 100% rename from sonoff/xdrv_21_wemo.ino rename to tasmota/xdrv_21_wemo.ino diff --git a/sonoff/xdrv_22_sonoff_ifan.ino b/tasmota/xdrv_22_sonoff_ifan.ino similarity index 100% rename from sonoff/xdrv_22_sonoff_ifan.ino rename to tasmota/xdrv_22_sonoff_ifan.ino diff --git a/sonoff/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino similarity index 100% rename from sonoff/xdrv_23_zigbee_0_constants.ino rename to tasmota/xdrv_23_zigbee_0_constants.ino diff --git a/sonoff/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino similarity index 100% rename from sonoff/xdrv_23_zigbee_3_devices.ino rename to tasmota/xdrv_23_zigbee_3_devices.ino diff --git a/sonoff/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino similarity index 100% rename from sonoff/xdrv_23_zigbee_5_converters.ino rename to tasmota/xdrv_23_zigbee_5_converters.ino diff --git a/sonoff/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino similarity index 100% rename from sonoff/xdrv_23_zigbee_6_commands.ino rename to tasmota/xdrv_23_zigbee_6_commands.ino diff --git a/sonoff/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino similarity index 100% rename from sonoff/xdrv_23_zigbee_7_statemachine.ino rename to tasmota/xdrv_23_zigbee_7_statemachine.ino diff --git a/sonoff/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino similarity index 100% rename from sonoff/xdrv_23_zigbee_8_parsers.ino rename to tasmota/xdrv_23_zigbee_8_parsers.ino diff --git a/sonoff/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino similarity index 100% rename from sonoff/xdrv_23_zigbee_9_impl.ino rename to tasmota/xdrv_23_zigbee_9_impl.ino diff --git a/sonoff/xdrv_24_buzzer.ino b/tasmota/xdrv_24_buzzer.ino similarity index 100% rename from sonoff/xdrv_24_buzzer.ino rename to tasmota/xdrv_24_buzzer.ino diff --git a/sonoff/xdrv_25_A4988_Stepper.ino b/tasmota/xdrv_25_A4988_Stepper.ino similarity index 100% rename from sonoff/xdrv_25_A4988_Stepper.ino rename to tasmota/xdrv_25_A4988_Stepper.ino diff --git a/sonoff/xdrv_26_ariluxrf.ino b/tasmota/xdrv_26_ariluxrf.ino similarity index 100% rename from sonoff/xdrv_26_ariluxrf.ino rename to tasmota/xdrv_26_ariluxrf.ino diff --git a/sonoff/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino similarity index 100% rename from sonoff/xdrv_27_shutter.ino rename to tasmota/xdrv_27_shutter.ino diff --git a/sonoff/xdrv_28_pcf8574.ino b/tasmota/xdrv_28_pcf8574.ino similarity index 100% rename from sonoff/xdrv_28_pcf8574.ino rename to tasmota/xdrv_28_pcf8574.ino diff --git a/sonoff/xdrv_29_deepsleep.ino b/tasmota/xdrv_29_deepsleep.ino similarity index 100% rename from sonoff/xdrv_29_deepsleep.ino rename to tasmota/xdrv_29_deepsleep.ino diff --git a/sonoff/xdrv_30_exs_dimmer.ino b/tasmota/xdrv_30_exs_dimmer.ino similarity index 100% rename from sonoff/xdrv_30_exs_dimmer.ino rename to tasmota/xdrv_30_exs_dimmer.ino diff --git a/sonoff/xdrv_31_tasmota_slave.ino b/tasmota/xdrv_31_tasmota_slave.ino similarity index 100% rename from sonoff/xdrv_31_tasmota_slave.ino rename to tasmota/xdrv_31_tasmota_slave.ino diff --git a/sonoff/xdrv_99_debug.ino b/tasmota/xdrv_99_debug.ino similarity index 100% rename from sonoff/xdrv_99_debug.ino rename to tasmota/xdrv_99_debug.ino diff --git a/sonoff/xdrv_interface.ino b/tasmota/xdrv_interface.ino similarity index 100% rename from sonoff/xdrv_interface.ino rename to tasmota/xdrv_interface.ino diff --git a/sonoff/xdsp_01_lcd.ino b/tasmota/xdsp_01_lcd.ino similarity index 100% rename from sonoff/xdsp_01_lcd.ino rename to tasmota/xdsp_01_lcd.ino diff --git a/sonoff/xdsp_02_ssd1306.ino b/tasmota/xdsp_02_ssd1306.ino old mode 100755 new mode 100644 similarity index 100% rename from sonoff/xdsp_02_ssd1306.ino rename to tasmota/xdsp_02_ssd1306.ino diff --git a/sonoff/xdsp_03_matrix.ino b/tasmota/xdsp_03_matrix.ino similarity index 100% rename from sonoff/xdsp_03_matrix.ino rename to tasmota/xdsp_03_matrix.ino diff --git a/sonoff/xdsp_04_ili9341.ino b/tasmota/xdsp_04_ili9341.ino similarity index 100% rename from sonoff/xdsp_04_ili9341.ino rename to tasmota/xdsp_04_ili9341.ino diff --git a/sonoff/xdsp_05_epaper_29.ino b/tasmota/xdsp_05_epaper_29.ino similarity index 100% rename from sonoff/xdsp_05_epaper_29.ino rename to tasmota/xdsp_05_epaper_29.ino diff --git a/sonoff/xdsp_06_epaper_42.ino b/tasmota/xdsp_06_epaper_42.ino similarity index 100% rename from sonoff/xdsp_06_epaper_42.ino rename to tasmota/xdsp_06_epaper_42.ino diff --git a/sonoff/xdsp_07_sh1106.ino b/tasmota/xdsp_07_sh1106.ino similarity index 100% rename from sonoff/xdsp_07_sh1106.ino rename to tasmota/xdsp_07_sh1106.ino diff --git a/sonoff/xdsp_08_ILI9488.ino b/tasmota/xdsp_08_ILI9488.ino similarity index 100% rename from sonoff/xdsp_08_ILI9488.ino rename to tasmota/xdsp_08_ILI9488.ino diff --git a/sonoff/xdsp_09_SSD1351.ino b/tasmota/xdsp_09_SSD1351.ino similarity index 100% rename from sonoff/xdsp_09_SSD1351.ino rename to tasmota/xdsp_09_SSD1351.ino diff --git a/sonoff/xdsp_10_RA8876.ino b/tasmota/xdsp_10_RA8876.ino similarity index 100% rename from sonoff/xdsp_10_RA8876.ino rename to tasmota/xdsp_10_RA8876.ino diff --git a/sonoff/xdsp_interface.ino b/tasmota/xdsp_interface.ino similarity index 100% rename from sonoff/xdsp_interface.ino rename to tasmota/xdsp_interface.ino diff --git a/sonoff/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino similarity index 100% rename from sonoff/xlgt_01_ws2812.ino rename to tasmota/xlgt_01_ws2812.ino diff --git a/sonoff/xlgt_02_my92x1.ino b/tasmota/xlgt_02_my92x1.ino similarity index 100% rename from sonoff/xlgt_02_my92x1.ino rename to tasmota/xlgt_02_my92x1.ino diff --git a/sonoff/xlgt_03_sm16716.ino b/tasmota/xlgt_03_sm16716.ino similarity index 100% rename from sonoff/xlgt_03_sm16716.ino rename to tasmota/xlgt_03_sm16716.ino diff --git a/sonoff/xlgt_04_sm2135.ino b/tasmota/xlgt_04_sm2135.ino similarity index 100% rename from sonoff/xlgt_04_sm2135.ino rename to tasmota/xlgt_04_sm2135.ino diff --git a/sonoff/xlgt_05_sonoff_l1.ino b/tasmota/xlgt_05_sonoff_l1.ino similarity index 100% rename from sonoff/xlgt_05_sonoff_l1.ino rename to tasmota/xlgt_05_sonoff_l1.ino diff --git a/sonoff/xlgt_interface.ino b/tasmota/xlgt_interface.ino similarity index 100% rename from sonoff/xlgt_interface.ino rename to tasmota/xlgt_interface.ino diff --git a/sonoff/xnrg_01_hlw8012.ino b/tasmota/xnrg_01_hlw8012.ino similarity index 100% rename from sonoff/xnrg_01_hlw8012.ino rename to tasmota/xnrg_01_hlw8012.ino diff --git a/sonoff/xnrg_02_cse7766.ino b/tasmota/xnrg_02_cse7766.ino similarity index 100% rename from sonoff/xnrg_02_cse7766.ino rename to tasmota/xnrg_02_cse7766.ino diff --git a/sonoff/xnrg_03_pzem004t.ino b/tasmota/xnrg_03_pzem004t.ino similarity index 100% rename from sonoff/xnrg_03_pzem004t.ino rename to tasmota/xnrg_03_pzem004t.ino diff --git a/sonoff/xnrg_04_mcp39f501.ino b/tasmota/xnrg_04_mcp39f501.ino similarity index 100% rename from sonoff/xnrg_04_mcp39f501.ino rename to tasmota/xnrg_04_mcp39f501.ino diff --git a/sonoff/xnrg_05_pzem_ac.ino b/tasmota/xnrg_05_pzem_ac.ino similarity index 100% rename from sonoff/xnrg_05_pzem_ac.ino rename to tasmota/xnrg_05_pzem_ac.ino diff --git a/sonoff/xnrg_06_pzem_dc.ino b/tasmota/xnrg_06_pzem_dc.ino similarity index 100% rename from sonoff/xnrg_06_pzem_dc.ino rename to tasmota/xnrg_06_pzem_dc.ino diff --git a/sonoff/xnrg_07_ade7953.ino b/tasmota/xnrg_07_ade7953.ino similarity index 100% rename from sonoff/xnrg_07_ade7953.ino rename to tasmota/xnrg_07_ade7953.ino diff --git a/sonoff/xnrg_08_sdm120.ino b/tasmota/xnrg_08_sdm120.ino similarity index 100% rename from sonoff/xnrg_08_sdm120.ino rename to tasmota/xnrg_08_sdm120.ino diff --git a/sonoff/xnrg_09_dds2382.ino b/tasmota/xnrg_09_dds2382.ino similarity index 100% rename from sonoff/xnrg_09_dds2382.ino rename to tasmota/xnrg_09_dds2382.ino diff --git a/sonoff/xnrg_10_sdm630.ino b/tasmota/xnrg_10_sdm630.ino similarity index 100% rename from sonoff/xnrg_10_sdm630.ino rename to tasmota/xnrg_10_sdm630.ino diff --git a/sonoff/xnrg_11_ddsu666.ino b/tasmota/xnrg_11_ddsu666.ino similarity index 100% rename from sonoff/xnrg_11_ddsu666.ino rename to tasmota/xnrg_11_ddsu666.ino diff --git a/sonoff/xnrg_12_solaxX1.ino b/tasmota/xnrg_12_solaxX1.ino similarity index 100% rename from sonoff/xnrg_12_solaxX1.ino rename to tasmota/xnrg_12_solaxX1.ino diff --git a/sonoff/xnrg_interface.ino b/tasmota/xnrg_interface.ino similarity index 100% rename from sonoff/xnrg_interface.ino rename to tasmota/xnrg_interface.ino diff --git a/sonoff/xsns_01_counter.ino b/tasmota/xsns_01_counter.ino similarity index 100% rename from sonoff/xsns_01_counter.ino rename to tasmota/xsns_01_counter.ino diff --git a/sonoff/xsns_02_analog.ino b/tasmota/xsns_02_analog.ino similarity index 100% rename from sonoff/xsns_02_analog.ino rename to tasmota/xsns_02_analog.ino diff --git a/sonoff/xsns_04_snfsc.ino b/tasmota/xsns_04_snfsc.ino similarity index 100% rename from sonoff/xsns_04_snfsc.ino rename to tasmota/xsns_04_snfsc.ino diff --git a/sonoff/xsns_05_ds18x20.ino b/tasmota/xsns_05_ds18x20.ino similarity index 100% rename from sonoff/xsns_05_ds18x20.ino rename to tasmota/xsns_05_ds18x20.ino diff --git a/sonoff/xsns_06_dht.ino b/tasmota/xsns_06_dht.ino similarity index 100% rename from sonoff/xsns_06_dht.ino rename to tasmota/xsns_06_dht.ino diff --git a/sonoff/xsns_07_sht1x.ino b/tasmota/xsns_07_sht1x.ino similarity index 100% rename from sonoff/xsns_07_sht1x.ino rename to tasmota/xsns_07_sht1x.ino diff --git a/sonoff/xsns_08_htu21.ino b/tasmota/xsns_08_htu21.ino similarity index 100% rename from sonoff/xsns_08_htu21.ino rename to tasmota/xsns_08_htu21.ino diff --git a/sonoff/xsns_09_bmp.ino b/tasmota/xsns_09_bmp.ino old mode 100755 new mode 100644 similarity index 100% rename from sonoff/xsns_09_bmp.ino rename to tasmota/xsns_09_bmp.ino diff --git a/sonoff/xsns_10_bh1750.ino b/tasmota/xsns_10_bh1750.ino similarity index 100% rename from sonoff/xsns_10_bh1750.ino rename to tasmota/xsns_10_bh1750.ino diff --git a/sonoff/xsns_11_veml6070.ino b/tasmota/xsns_11_veml6070.ino similarity index 100% rename from sonoff/xsns_11_veml6070.ino rename to tasmota/xsns_11_veml6070.ino diff --git a/sonoff/xsns_12_ads1115.ino b/tasmota/xsns_12_ads1115.ino similarity index 100% rename from sonoff/xsns_12_ads1115.ino rename to tasmota/xsns_12_ads1115.ino diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/tasmota/xsns_12_ads1115_i2cdev.ino similarity index 100% rename from sonoff/xsns_12_ads1115_i2cdev.ino rename to tasmota/xsns_12_ads1115_i2cdev.ino diff --git a/sonoff/xsns_13_ina219.ino b/tasmota/xsns_13_ina219.ino similarity index 100% rename from sonoff/xsns_13_ina219.ino rename to tasmota/xsns_13_ina219.ino diff --git a/sonoff/xsns_14_sht3x.ino b/tasmota/xsns_14_sht3x.ino old mode 100755 new mode 100644 similarity index 100% rename from sonoff/xsns_14_sht3x.ino rename to tasmota/xsns_14_sht3x.ino diff --git a/sonoff/xsns_15_mhz19.ino b/tasmota/xsns_15_mhz19.ino similarity index 100% rename from sonoff/xsns_15_mhz19.ino rename to tasmota/xsns_15_mhz19.ino diff --git a/sonoff/xsns_16_tsl2561.ino b/tasmota/xsns_16_tsl2561.ino similarity index 100% rename from sonoff/xsns_16_tsl2561.ino rename to tasmota/xsns_16_tsl2561.ino diff --git a/sonoff/xsns_17_senseair.ino b/tasmota/xsns_17_senseair.ino similarity index 100% rename from sonoff/xsns_17_senseair.ino rename to tasmota/xsns_17_senseair.ino diff --git a/sonoff/xsns_18_pms5003.ino b/tasmota/xsns_18_pms5003.ino similarity index 100% rename from sonoff/xsns_18_pms5003.ino rename to tasmota/xsns_18_pms5003.ino diff --git a/sonoff/xsns_19_mgs.ino b/tasmota/xsns_19_mgs.ino similarity index 100% rename from sonoff/xsns_19_mgs.ino rename to tasmota/xsns_19_mgs.ino diff --git a/sonoff/xsns_20_novasds.ino b/tasmota/xsns_20_novasds.ino similarity index 100% rename from sonoff/xsns_20_novasds.ino rename to tasmota/xsns_20_novasds.ino diff --git a/sonoff/xsns_21_sgp30.ino b/tasmota/xsns_21_sgp30.ino similarity index 100% rename from sonoff/xsns_21_sgp30.ino rename to tasmota/xsns_21_sgp30.ino diff --git a/sonoff/xsns_22_sr04.ino b/tasmota/xsns_22_sr04.ino similarity index 100% rename from sonoff/xsns_22_sr04.ino rename to tasmota/xsns_22_sr04.ino diff --git a/sonoff/xsns_24_si1145.ino b/tasmota/xsns_24_si1145.ino similarity index 100% rename from sonoff/xsns_24_si1145.ino rename to tasmota/xsns_24_si1145.ino diff --git a/sonoff/xsns_26_lm75ad.ino b/tasmota/xsns_26_lm75ad.ino similarity index 100% rename from sonoff/xsns_26_lm75ad.ino rename to tasmota/xsns_26_lm75ad.ino diff --git a/sonoff/xsns_27_apds9960.ino b/tasmota/xsns_27_apds9960.ino similarity index 100% rename from sonoff/xsns_27_apds9960.ino rename to tasmota/xsns_27_apds9960.ino diff --git a/sonoff/xsns_28_tm1638.ino b/tasmota/xsns_28_tm1638.ino similarity index 100% rename from sonoff/xsns_28_tm1638.ino rename to tasmota/xsns_28_tm1638.ino diff --git a/sonoff/xsns_29_mcp230xx.ino b/tasmota/xsns_29_mcp230xx.ino similarity index 100% rename from sonoff/xsns_29_mcp230xx.ino rename to tasmota/xsns_29_mcp230xx.ino diff --git a/sonoff/xsns_30_mpr121.ino b/tasmota/xsns_30_mpr121.ino similarity index 100% rename from sonoff/xsns_30_mpr121.ino rename to tasmota/xsns_30_mpr121.ino diff --git a/sonoff/xsns_31_ccs811.ino b/tasmota/xsns_31_ccs811.ino similarity index 100% rename from sonoff/xsns_31_ccs811.ino rename to tasmota/xsns_31_ccs811.ino diff --git a/sonoff/xsns_32_mpu6050.ino b/tasmota/xsns_32_mpu6050.ino similarity index 100% rename from sonoff/xsns_32_mpu6050.ino rename to tasmota/xsns_32_mpu6050.ino diff --git a/sonoff/xsns_33_ds3231.ino b/tasmota/xsns_33_ds3231.ino similarity index 100% rename from sonoff/xsns_33_ds3231.ino rename to tasmota/xsns_33_ds3231.ino diff --git a/sonoff/xsns_34_hx711.ino b/tasmota/xsns_34_hx711.ino similarity index 100% rename from sonoff/xsns_34_hx711.ino rename to tasmota/xsns_34_hx711.ino diff --git a/sonoff/xsns_35_tx20.ino b/tasmota/xsns_35_tx20.ino similarity index 100% rename from sonoff/xsns_35_tx20.ino rename to tasmota/xsns_35_tx20.ino diff --git a/sonoff/xsns_36_mgc3130.ino b/tasmota/xsns_36_mgc3130.ino similarity index 100% rename from sonoff/xsns_36_mgc3130.ino rename to tasmota/xsns_36_mgc3130.ino diff --git a/sonoff/xsns_37_rfsensor.ino b/tasmota/xsns_37_rfsensor.ino similarity index 100% rename from sonoff/xsns_37_rfsensor.ino rename to tasmota/xsns_37_rfsensor.ino diff --git a/sonoff/xsns_38_az7798.ino b/tasmota/xsns_38_az7798.ino similarity index 100% rename from sonoff/xsns_38_az7798.ino rename to tasmota/xsns_38_az7798.ino diff --git a/sonoff/xsns_39_max31855.ino b/tasmota/xsns_39_max31855.ino similarity index 100% rename from sonoff/xsns_39_max31855.ino rename to tasmota/xsns_39_max31855.ino diff --git a/sonoff/xsns_40_pn532.ino b/tasmota/xsns_40_pn532.ino similarity index 100% rename from sonoff/xsns_40_pn532.ino rename to tasmota/xsns_40_pn532.ino diff --git a/sonoff/xsns_41_max44009.ino b/tasmota/xsns_41_max44009.ino similarity index 100% rename from sonoff/xsns_41_max44009.ino rename to tasmota/xsns_41_max44009.ino diff --git a/sonoff/xsns_42_scd30.ino b/tasmota/xsns_42_scd30.ino similarity index 100% rename from sonoff/xsns_42_scd30.ino rename to tasmota/xsns_42_scd30.ino diff --git a/sonoff/xsns_43_hre.ino b/tasmota/xsns_43_hre.ino similarity index 100% rename from sonoff/xsns_43_hre.ino rename to tasmota/xsns_43_hre.ino diff --git a/sonoff/xsns_44_sps30.ino b/tasmota/xsns_44_sps30.ino similarity index 100% rename from sonoff/xsns_44_sps30.ino rename to tasmota/xsns_44_sps30.ino diff --git a/sonoff/xsns_45_vl53l0x.ino b/tasmota/xsns_45_vl53l0x.ino old mode 100755 new mode 100644 similarity index 100% rename from sonoff/xsns_45_vl53l0x.ino rename to tasmota/xsns_45_vl53l0x.ino diff --git a/sonoff/xsns_46_MLX90614.ino b/tasmota/xsns_46_MLX90614.ino similarity index 100% rename from sonoff/xsns_46_MLX90614.ino rename to tasmota/xsns_46_MLX90614.ino diff --git a/sonoff/xsns_47_max31865.ino b/tasmota/xsns_47_max31865.ino similarity index 100% rename from sonoff/xsns_47_max31865.ino rename to tasmota/xsns_47_max31865.ino diff --git a/sonoff/xsns_48_chirp.ino b/tasmota/xsns_48_chirp.ino similarity index 100% rename from sonoff/xsns_48_chirp.ino rename to tasmota/xsns_48_chirp.ino diff --git a/sonoff/xsns_50_paj7620.ino b/tasmota/xsns_50_paj7620.ino similarity index 100% rename from sonoff/xsns_50_paj7620.ino rename to tasmota/xsns_50_paj7620.ino diff --git a/sonoff/xsns_51_rdm6300.ino b/tasmota/xsns_51_rdm6300.ino similarity index 100% rename from sonoff/xsns_51_rdm6300.ino rename to tasmota/xsns_51_rdm6300.ino diff --git a/sonoff/xsns_52_ibeacon.ino b/tasmota/xsns_52_ibeacon.ino similarity index 100% rename from sonoff/xsns_52_ibeacon.ino rename to tasmota/xsns_52_ibeacon.ino diff --git a/sonoff/xsns_53_sml.ino b/tasmota/xsns_53_sml.ino similarity index 100% rename from sonoff/xsns_53_sml.ino rename to tasmota/xsns_53_sml.ino diff --git a/sonoff/xsns_54_ina226.ino b/tasmota/xsns_54_ina226.ino similarity index 100% rename from sonoff/xsns_54_ina226.ino rename to tasmota/xsns_54_ina226.ino diff --git a/sonoff/xsns_interface.ino b/tasmota/xsns_interface.ino similarity index 100% rename from sonoff/xsns_interface.ino rename to tasmota/xsns_interface.ino diff --git a/tools/decode-config.html b/tools/decode-config.html index d5cff4c3a..ccd05b514 100644 --- a/tools/decode-config.html +++ b/tools/decode-config.html @@ -1,5 +1,5 @@

decode-config.py

-

decode-config.py is able to backup and restore Sonoff-Tasmota configuration.

+

decode-config.py is able to backup and restore Tasmota configuration.

In comparison with the Tasmota build-in "Backup/Restore Configuration" function decode-config.py

  • uses human readable and editable JSON-format for backup/restore,
  • @@ -12,7 +12,7 @@   decode-config.py
    *.json file -Sonoff-Tasmota
    *.dmp file +Tasmota
    *.dmp file @@ -77,9 +77,9 @@
    • Python)
      This program is written in Python) so you need to install a working python environment (for details see Python Setup and Usage)

    • -
    • Sonoff-Tasmota Firmware with Web-Server enabled:

      +
    • Tasmota Firmware with Web-Server enabled:

        -
      • To backup or restore configurations from or to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command WebServer 2). This is the Tasmota default.
      • +
      • To backup or restore configurations from or to a Tasmota device you need a firmare with enabled web-server in admin mode (command WebServer 2). This is the Tasmota default.
      • If using your own compiled firmware be aware to enable the web-server (#define USE_WEBSERVER and #define WEB_SERVER 2).
    • @@ -91,7 +91,7 @@

      .json Format

      Configuration data in JSON-format.
      This format is decrypted, human readable and editable and can also be used for the --restore-file parameter.
      This file will be created by decode-config.py using the --backup-file with --backup-type json parameter, this is the default.

      .bin Format

      -

      Configuration data in binary format.
      This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for --restore-file command.
      It will be created by decode-config.py using --backup-file with --backup-type bin.
      Note:
      The .bin file contains the same information as the original .dmp file from Tasmota "Backup/Restore Configuration" but it is decrpted and 4 byte longer than an original (it is a prefix header at the beginning). .bin file data starting at address 4 contains the same as the struct SYSCFG from Tasmota settings.h in decrypted format.

      +

      Configuration data in binary format.
      This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for --restore-file command.
      It will be created by decode-config.py using --backup-file with --backup-type bin.
      Note:
      The .bin file contains the same information as the original .dmp file from Tasmota "Backup/Restore Configuration" but it is decrpted and 4 byte longer than an original (it is a prefix header at the beginning). .bin file data starting at address 4 contains the same as the struct SYSCFG from Tasmota settings.h in decrypted format.

      File extensions

      You don't need to append exensions for your file name as decode-config.py uses auto extension as default. The extension will be choose based on file contents and --backup-type parameter. If you do not want using auto extensions use the --no-extension parameter.

      @@ -108,14 +108,14 @@ If you do not want using auto extensions use the --no-extension par
      decode-config.py -d sonoff-4281
       

      will output a human readable configuration in JSON-format:

      {
      -  "altitude": 112, 
      -  "baudrate": 115200, 
      -  "blinkcount": 10, 
      -  "blinktime": 10, 
      +  "altitude": 112,
      +  "baudrate": 115200,
      +  "blinkcount": 10,
      +  "blinktime": 10,
       ...
         "ws_width": [
      -    1, 
      -    3, 
      +    1,
      +    3,
           5
         ]
       }
      @@ -141,29 +141,29 @@ If you do not want using auto extensions use the --no-extension par
       
       {
         ...
      -  "hostname": "%s-%04d", 
      +  "hostname": "%s-%04d",
         "ip_address": [
      -    "0.0.0.0", 
      -    "192.168.12.1", 
      -    "255.255.255.0", 
      +    "0.0.0.0",
      +    "192.168.12.1",
      +    "255.255.255.0",
           "192.168.12.1"
      -  ], 
      +  ],
         "ntp_server": [
      -    "ntp.localnet.home", 
      -    "ntp2.localnet.home", 
      +    "ntp.localnet.home",
      +    "ntp2.localnet.home",
           "192.168.12.1"
      -  ], 
      -  "sta_active": 0, 
      -  "sta_config": 5, 
      +  ],
      +  "sta_active": 0,
      +  "sta_config": 5,
         "sta_pwd": [
      -    "myWlAnPaszxwo!z", 
      +    "myWlAnPaszxwo!z",
           "myWlAnPaszxwo!z2"
      -  ], 
      +  ],
         "sta_ssid": [
      -    "wlan.1", 
      +    "wlan.1",
           "my-wlan"
      -  ], 
      -  "web_password": "myPaszxwo!z", 
      +  ],
      +  "web_password": "myPaszxwo!z",
         "webserver": 2
         ...
       }
      @@ -194,7 +194,7 @@ If you do not want using auto extensions use the --no-extension par
       

      Filter data

      The huge number of Tasmota configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories.

      With decode-config.py the following categories are available: Display, Domoticz, Internal, KNX, Led, Logging, MCP230xx, MQTT, Main, Management, Pow, Sensor, Serial, SetOption, SonoffRF, System, Timers, Wifi

      -

      These are similary to the categories on https://github.com/arendst/Sonoff-Tasmota/wiki/Commands.

      +

      These are similary to the categories on https://github.com/arendst/Tasmota/wiki/Commands.

      To filter outputs to a subset of groups use the -g or --group arg concatenating the grooup you want, e. g.

      decode-config.py -d sonoff-4281 -c my.conf --output-format cmnd --group Main MQTT Management Wifi
       

      Configuration file

      @@ -222,7 +222,7 @@ If you do not want using auto extensions use the --no-extension par [-g {Control,Devices,Display,Domoticz,Internal,KNX,Light,MQTT,Management,Power,Rules,Sensor,Serial,SetOption,SonoffRF,System,Timer,Wifi} [{Control,Devices,Display,Domoticz,Internal,KNX,Light,MQTT,Management,Power,Rules,Sensor,Serial,SetOption,SonoffRF,System,Timer,Wifi} ...]] [--ignore-warnings] [-h] [-H] [-v] [-V] -Backup/Restore Sonoff-Tasmota configuration data. Args that start with '--' +Backup/Restore Tasmota configuration data. Args that start with '--' (eg. -f) can also be set in a config file (specified via -c). Config file syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at https://goo.gl/R74nmi). If an arg is specified in more than one place, then diff --git a/tools/decode-config.md b/tools/decode-config.md index 883467dfa..2b0f8c62e 100644 --- a/tools/decode-config.md +++ b/tools/decode-config.md @@ -1,14 +1,14 @@ # decode-config.py -_decode-config.py_ is able to backup and restore Sonoff-Tasmota configuration. +_decode-config.py_ is able to backup and restore Tasmota configuration. In comparison with the Tasmota build-in "Backup/Restore Configuration" function _decode-config.py_ * uses human readable and editable [JSON](http://www.json.org/)-format for backup/restore, * can restore previously backup and changed [JSON](http://www.json.org/)-format files, * is able to create Tasmota compatible command list with related config parameter -Comparing backup files created by *decode-config.py* and *.dmp files created by Tasmota "Backup/Restore Configuration": +Comparing backup files created by *decode-config.py* and *.dmp files created by Tasmota "Backup/Restore Configuration": -|   | decode-config.py
      *.json file | Sonoff-Tasmota
      *.dmp file | +|   | decode-config.py
      *.json file | Tasmota
      *.dmp file | |-------------------------|:-------------------------------:|:-----------------------------------:| | Encrypted | No | Yes | | Readable | Yes | No | @@ -41,28 +41,28 @@ _decode-config.py_ is compatible with Tasmota version from v5.10.0 up to now. * [Notes](decode-config.md#notes) ## Prerequisite -* [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) +* [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) This program is written in [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) so you need to install a working python environment (for details see [Python Setup and Usage](https://docs.python.org/2.7/using/index.html)) -* [Sonoff-Tasmota](https://github.com/arendst/Sonoff-Tasmota) [Firmware](https://github.com/arendst/Sonoff-Tasmota/releases) with Web-Server enabled: - * To backup or restore configurations from or to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command [WebServer 2](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands#wifi)). This is the Tasmota default. +* [Tasmota](https://github.com/arendst/Tasmota) [Firmware](https://github.com/arendst/Tasmota/releases) with Web-Server enabled: + * To backup or restore configurations from or to a Tasmota device you need a firmare with enabled web-server in admin mode (command [WebServer 2](https://github.com/arendst/Tasmota/wiki/Commands#wifi)). This is the Tasmota default. * If using your own compiled firmware be aware to enable the web-server (`#define USE_WEBSERVER` and `#define WEB_SERVER 2`). ## File Types -_decode-config.py_ can handle the following backup file types: +_decode-config.py_ can handle the following backup file types: ### .dmp Format -Configuration data as used by Tasmota "Backup/Restore Configuration" web interface. +Configuration data as used by Tasmota "Backup/Restore Configuration" web interface. This format is binary and encrypted. ### .json Format -Configuration data in [JSON](http://www.json.org/)-format. -This format is decrypted, human readable and editable and can also be used for the `--restore-file` parameter. +Configuration data in [JSON](http://www.json.org/)-format. +This format is decrypted, human readable and editable and can also be used for the `--restore-file` parameter. This file will be created by _decode-config.py_ using the `--backup-file` with `--backup-type json` parameter, this is the default. ### .bin Format -Configuration data in binary format. -This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for `--restore-file` command. -It will be created by _decode-config.py_ using `--backup-file` with `--backup-type bin`. -Note: -The .bin file contains the same information as the original .dmp file from Tasmota "Backup/Restore Configuration" but it is decrpted and 4 byte longer than an original (it is a prefix header at the beginning). .bin file data starting at address 4 contains the same as the **struct SYSCFG** from Tasmota [settings.h](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/settings.h) in decrypted format. +Configuration data in binary format. +This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for `--restore-file` command. +It will be created by _decode-config.py_ using `--backup-file` with `--backup-type bin`. +Note: +The .bin file contains the same information as the original .dmp file from Tasmota "Backup/Restore Configuration" but it is decrpted and 4 byte longer than an original (it is a prefix header at the beginning). .bin file data starting at address 4 contains the same as the **struct SYSCFG** from Tasmota [settings.h](https://github.com/arendst/Tasmota/blob/master/sonoff/settings.h) in decrypted format. #### File extensions You don't need to append exensions for your file name as _decode-config.py_ uses auto extension as default. The extension will be choose based on file contents and `--backup-type` parameter. @@ -74,35 +74,35 @@ After download don't forget to set the executable flag under linux with `chmod + ### Basics At least pass a source where you want to read the configuration data from using `-f ` or `-d `: -The source can be either +The source can be either * a Tasmota device hostname or IP using the `-d ` parameter * a Tasmota `*.dmp` configuration file using `-f ` parameter -Example: +Example: decode-config.py -d sonoff-4281 will output a human readable configuration in [JSON](http://www.json.org/)-format: { - "altitude": 112, - "baudrate": 115200, - "blinkcount": 10, - "blinktime": 10, + "altitude": 112, + "baudrate": 115200, + "blinkcount": 10, + "blinktime": 10, ... "ws_width": [ - 1, - 3, + 1, + 3, 5 ] } ### Save backup file -To save the output as backup file use `--backup-file `, you can use placeholder for Version, Friendlyname and Hostname: +To save the output as backup file use `--backup-file `, you can use placeholder for Version, Friendlyname and Hostname: decode-config.py -d sonoff-4281 --backup-file Config_@f_@v - + If you have setup a WebPassword within Tasmota, use decode-config.py -d sonoff-4281 -p --backup-file Config_@f_@v @@ -112,10 +112,10 @@ will create a file like `Config_Sonoff_6.4.0.json` (the part `Sonoff` and `6.4.0 ### Restore backup file Reading back a saved (and possible changed) backup file use the `--restore-file ` parameter. This will read the (changed) configuration data from this file and send it back to the source device or filename. -To restore the previously save backup file `Config_Sonoff_6.2.1.json` to device `sonoff-4281` use: +To restore the previously save backup file `Config_Sonoff_6.2.1.json` to device `sonoff-4281` use: decode-config.py -d sonoff-4281 --restore-file Config_Sonoff_6.2.1.json - + with password set by WebPassword: decode-config.py -d sonoff-4281 -p --restore-file Config_Sonoff_6.2.1.json @@ -134,29 +134,29 @@ Example: { ... - "hostname": "%s-%04d", + "hostname": "%s-%04d", "ip_address": [ - "0.0.0.0", - "192.168.12.1", - "255.255.255.0", + "0.0.0.0", + "192.168.12.1", + "255.255.255.0", "192.168.12.1" - ], + ], "ntp_server": [ - "ntp.localnet.home", - "ntp2.localnet.home", + "ntp.localnet.home", + "ntp2.localnet.home", "192.168.12.1" - ], - "sta_active": 0, - "sta_config": 5, + ], + "sta_active": 0, + "sta_config": 5, "sta_pwd": [ - "myWlAnPaszxwo!z", + "myWlAnPaszxwo!z", "myWlAnPaszxwo!z2" - ], + ], "sta_ssid": [ - "wlan.1", + "wlan.1", "my-wlan" - ], - "web_password": "myPaszxwo!z", + ], + "web_password": "myPaszxwo!z", "webserver": 2 ... } @@ -192,11 +192,11 @@ Example: Note: A few very specific module commands like MPC230xx, KNX and some Display commands are not supported. These are still available by JSON output. ### Filter data -The huge number of Tasmota configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories. +The huge number of Tasmota configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories. With _decode-config.py_ the following categories are available: `Display`, `Domoticz`, `Internal`, `KNX`, `Led`, `Logging`, `MCP230xx`, `MQTT`, `Main`, `Management`, `Pow`, `Sensor`, `Serial`, `SetOption`, `SonoffRF`, `System`, `Timers`, `Wifi` -These are similary to the categories on [https://github.com/arendst/Sonoff-Tasmota/wiki/Commands](Tasmota Command Wiki). +These are similary to the categories on [https://github.com/arendst/Tasmota/wiki/Commands](Tasmota Command Wiki). To filter outputs to a subset of groups use the `-g` or `--group` arg concatenating the grooup you want, e. g. @@ -240,7 +240,7 @@ For advanced help use `-H` or `--full-help`: [-g {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi} [{Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi} ...]] [--ignore-warnings] [-h] [-H] [-v] [-V] - Backup/Restore Sonoff-Tasmota configuration data. Args that start with '--' + Backup/Restore Tasmota configuration data. Args that start with '--' (eg. -f) can also be set in a config file (specified via -c). Config file syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at https://goo.gl/R74nmi). If an arg is specified in more than one place, then @@ -383,8 +383,8 @@ will produce JSON configuration files for host sonoff1, sonoff2 and sonoff3 usin ## Notes Some general notes: * Filename replacement macros **@h** and **@H**: - * **@h** -The **@h** replacement macro uses the hostname configured with the Tasomta Wifi `Hostname ` command (defaults to `%s-%04d`). It will not use the network hostname of your device because this is not available when working with files only (e.g. `--file ` as source). + * **@h** +The **@h** replacement macro uses the hostname configured with the Tasomta Wifi `Hostname ` command (defaults to `%s-%04d`). It will not use the network hostname of your device because this is not available when working with files only (e.g. `--file ` as source). To prevent having a useless % in your filename, **@h** will not replaced by configuration data hostname if this contains '%' characters. - * **@H** + * **@H** If you want to use the network hostname within your filename, use the **@H** replacement macro instead - but be aware this will only replaced if you are using a network device as source (`-d`, `--device`, `--host`); it will not work when using a file as source (`-f`, `--file`) diff --git a/tools/decode-config.py b/tools/decode-config.py index 12ce09baa..450c1d1cb 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -3,7 +3,7 @@ VER = '2.3.0036' """ - decode-config.py - Backup/Restore Sonoff-Tasmota configuration data + decode-config.py - Backup/Restore Tasmota configuration data Copyright (C) 2019 Norbert Richter @@ -29,7 +29,7 @@ Requirements: Instructions: Execute command with option -d to retrieve config data from a host or use -f to read a configuration file saved using Tasmota Web-UI - + For further information read 'decode-config.md' For help execute command with argument -h (or -H for advanced help) @@ -46,7 +46,7 @@ Usage: decode-config.py [-f ] [-d ] [-P ] [-g {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi} [{Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi} ...]] [--ignore-warnings] [-h] [-H] [-v] [-V] - Backup/Restore Sonoff-Tasmota configuration data. Args that start with '--' + Backup/Restore Tasmota configuration data. Args that start with '--' (eg. -f) can also be set in a config file (specified via -c). Config file syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at https://goo.gl/R74nmi). If an arg is specified in more than one place, then @@ -263,7 +263,7 @@ exitcode = 0 Settings dictionary describes the config file fields definition: = { : } - + : "string" a python valid dictionary key (string) @@ -333,12 +333,12 @@ Settings dictionary describes the config file fields definition: to convert value from JSON back to binary object Common definitions - + : | | None function to be called or string to evaluate: : A function name will be called with one or two parameter: - The value to be processed + The value to be processed (optional) the current array index (1,n) A string will be evaluate as is. The following @@ -358,7 +358,7 @@ Settings dictionary describes the config file fields definition: numbers in the range -2147483648 through 2147483647 : unsigned integer numbers in the range 0 through 4294967295 - + """ # ---------------------------------------------------------------------- # Settings helper @@ -370,16 +370,16 @@ def passwordwrite(value): def bitsRead(x, n=0, c=1): """ Reads bit(s) of a number - + @param x: the number from which to read - + @param n: which bit position to read - + @param c: how many bits to read (1 if omitted) - + @return: the bit value(s) """ @@ -396,7 +396,7 @@ def bitsRead(x, n=0, c=1): x &= (1<= 2: print >> sys.stderr, "SetFieldValue(): fielddef {}, addr 0x{:04x} value {} formatcnt {} singletype {} bitsize {} ".format(fielddef,addr,value,formatcnt,singletype,bitsize) if not format_[-1:].lower() in ['s','p']: @@ -2309,10 +2309,10 @@ def SetFieldValue(fielddef, dobj, addr, value): try: struct.pack_into(singletype, dobj, addr, val) except struct.error as e: - exit(ExitCode.RESTORE_DATA_ERROR, - "Single type {} [fielddef={}, addr=0x{:04x}, value={}] - skipped!".format(e,fielddef,addr,val), - type_=LogType.WARNING, - doexit=not args.ignorewarning, + exit(ExitCode.RESTORE_DATA_ERROR, + "Single type {} [fielddef={}, addr=0x{:04x}, value={}] - skipped!".format(e,fielddef,addr,val), + type_=LogType.WARNING, + doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) value >>= bitsize else: @@ -2321,10 +2321,10 @@ def SetFieldValue(fielddef, dobj, addr, value): try: struct.pack_into(format_, dobj, addr, value) except struct.error as e: - exit(ExitCode.RESTORE_DATA_ERROR, - "String type {} [fielddef={}, addr=0x{:04x}, value={}} - skipped!".format(e,fielddef,addr,value), - type_=LogType.WARNING, - doexit=not args.ignorewarning, + exit(ExitCode.RESTORE_DATA_ERROR, + "String type {} [fielddef={}, addr=0x{:04x}, value={}} - skipped!".format(e,fielddef,addr,value), + type_=LogType.WARNING, + doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) return dobj @@ -2372,7 +2372,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): value = GetField(dobj, fieldname, subfielddef, raw=raw, addroffset=addroffset+offset) valuemapping.append(value) offset += length - + # contains a dict elif isinstance(format_, dict): mapping_value = {} @@ -2567,7 +2567,7 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""): curvalue = GetFieldValue(fielddef, dobj, baseaddr+addroffset) if prevvalue != curvalue and args.verbose: message("Value for '{}' changed from {} to {}".format(fieldname, prevvalue, curvalue), type_=LogType.INFO) - else: + else: if args.debug >= 2: print >> sys.stderr, "SetField(): Special field '{}' using '{}'/{}{} @{} skipped".format(fieldname, format_, arraydef, bits, hex(baseaddr+addroffset)) else: @@ -2757,14 +2757,14 @@ def Mapping2Bin(decode_cfg, jsonconfig, filename=""): restore data mapping @param filename: name of the restore file (for error output only) - + @return: changed binary config data (decrypted) or None on error """ if isinstance(decode_cfg, str): decode_cfg = bytearray(decode_cfg) - + # get binary header data to use the correct version template from device version, size, setting = GetTemplateSetting(decode_cfg) @@ -2807,13 +2807,13 @@ def Mapping2Cmnd(decode_cfg, valuemapping, filename=""): data mapping @param filename: name of the restore file (for error output only) - + @return: Tasmota command mapping {group: [cmnd <,cmnd <,...>>]} """ if isinstance(decode_cfg, str): decode_cfg = bytearray(decode_cfg) - + # get binary header data to use the correct version template from device version, size, setting = GetTemplateSetting(decode_cfg) @@ -2984,7 +2984,7 @@ def Restore(restorefile, backupfileformat, encode_cfg, decode_cfg, configmapping version, size, setting = GetTemplateSetting(new_decode_cfg) # get config file version cfg_version = GetField(new_decode_cfg, 'version', setting['version'], raw=True) - message("Config file contains data of Sonoff-Tasmota {}".format(GetVersionStr(cfg_version)), type_=LogType.INFO) + message("Config file contains data of Tasmota {}".format(GetVersionStr(cfg_version)), type_=LogType.INFO) if args.forcerestore or new_encode_cfg != encode_cfg: # write config direct to device via http if args.device is not None: @@ -3040,7 +3040,7 @@ def OutputTasmotaCmnds(tasmotacmnds): print print "# {}:".format(group) OutputTasmotaSubCmnds(cmnds) - + else: cmnds = [] for group in groups: @@ -3051,12 +3051,12 @@ def OutputTasmotaCmnds(tasmotacmnds): def ParseArgs(): """ Program argument parser - + @return: configargparse.parse_args() result """ global parser - parser = configargparse.ArgumentParser(description='Backup/Restore Sonoff-Tasmota configuration data.', + parser = configargparse.ArgumentParser(description='Backup/Restore Tasmota configuration data.', epilog='Either argument -d or -f must be given.', add_help=False, formatter_class=lambda prog: CustomHelpFormatter(prog)) @@ -3293,7 +3293,7 @@ if __name__ == "__main__": # decode into mappings dictionary configmapping = Bin2Mapping(decode_cfg) if args.verbose and 'version' in configmapping: - message("{} '{}' is using Sonoff-Tasmota {}".format('File' if args.tasmotafile is not None else 'Device', + message("{} '{}' is using Tasmota {}".format('File' if args.tasmotafile is not None else 'Device', args.tasmotafile if args.tasmotafile is not None else args.device, GetVersionStr(configmapping['version'])), type_=LogType.INFO) @@ -3314,5 +3314,5 @@ if __name__ == "__main__": if args.outputformat == 'cmnd' or args.outputformat == 'command': tasmotacmnds = Mapping2Cmnd(decode_cfg, configmapping) OutputTasmotaCmnds(tasmotacmnds) - + sys.exit(exitcode) diff --git a/tools/decode-status.py b/tools/decode-status.py index 10deefede..fcf65c7db 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -1,7 +1,7 @@ #!/usr/bin/env python """ - decode-status.py - decode status for Sonoff-Tasmota + decode-status.py - decode status for Tasmota Copyright (C) 2019 Theo Arends diff --git a/tools/fw_server/fw-server.py b/tools/fw_server/fw-server.py index 4d70f0f5e..df246f5b9 100644 --- a/tools/fw_server/fw-server.py +++ b/tools/fw_server/fw-server.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # coding=utf-8 """ -fw-server.py - firmware server for Sonoff-Tasmota OTA upgrade +fw-server.py - firmware server for Tasmota OTA upgrade Copyright (C) 2019 Gennaro Tortone @@ -24,12 +24,12 @@ Requirements: - pip install netifaces flask Instructions: - Copy Sonoff-Tasmota firmware binary files in 'fw' directory or + Copy Tasmota firmware binary files in 'fw' directory or specify a different directory with -f parameter. - A set of prebuilt files can be downloaded by Sonoff-Tasmota release page: - https://github.com/arendst/Sonoff-Tasmota/releases + A set of prebuilt files can be downloaded by Tasmota release page: + https://github.com/arendst/Tasmota/releases - Configure your Sonoff-Tasmota device with your fw-server URL: + Configure your Tasmota device with your fw-server URL: Firmware Upgrade -> Upgrade by web server http://:5000/sonoff-minimal.bin diff --git a/tools/fw_server/fw/README b/tools/fw_server/fw/README index c29367442..62274f362 100644 --- a/tools/fw_server/fw/README +++ b/tools/fw_server/fw/README @@ -1,3 +1,3 @@ -Copy Sonoff-Tasmota firmware binary files in this directory. -A set of prebuilt files can be downloaded by Sonoff-Tasmota release page: -https://github.com/arendst/Sonoff-Tasmota/releases \ No newline at end of file +Copy Tasmota firmware binary files in this directory. +A set of prebuilt files can be downloaded by Tasmota release page: +https://github.com/arendst/Tasmota/releases \ No newline at end of file From 1f084b8ec93fffde4788b02b38591d9655038ac0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Oct 2019 12:18:47 +0100 Subject: [PATCH 042/196] Prep for 7.x --- README.md | 5 +++-- RELEASENOTES.md | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e3435a83c..28d5592f3 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota) -See [sonoff/_changelog.ino](https://github.com/arendst/Tasmota/blob/development/sonoff/_changelog.ino) for detailed change information. +See [tasmota/_changelog.ino](https://github.com/arendst/Tasmota/blob/development/tasmota/_changelog.ino) for detailed change information. Unless your Tasmota powered device exhibits a problem or you need to make use of a feature that is not available in the Tasmota version currently installed on your device, leave your device alone - it works so don't make unnecessary changes! If the release version (i.e., the master branch) exhibits unexpected behaviour for your device and configuration, you should upgrade to the latest development version instead to see if your problem is resolved as some bugs in previous releases or development builds may already have been resolved. @@ -60,7 +60,8 @@ See [wiki migration path](https://github.com/arendst/Tasmota/wiki/Upgrade#migrat 1. Migrate to **Sonoff-Tasmota 3.9.x** 2. Migrate to **Sonoff-Tasmota 4.x** 3. Migrate to **Sonoff-Tasmota 5.14** -4. Migrate to **Sonoff-Tasmota 6.x** +4. Migrate to **Sonoff-Tasmota 6.7.1** +5. Migrate to **Tasmota 7.x** ## Support Information diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 86abd9678..70689d60b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -8,7 +8,8 @@ See [wiki migration path](https://github.com/arendst/Tasmota/wiki/Upgrade#migrat 1. Migrate to **Sonoff-Tasmota 3.9.x** 2. Migrate to **Sonoff-Tasmota 4.x** 3. Migrate to **Sonoff-Tasmota 5.14** -4. Migrate to **Sonoff-Tasmota 6.x** +4. Migrate to **Sonoff-Tasmota 6.7.1** +5. Migrate to **Tasmota 7.x** ## Supported Core versions This release will be supported from ESP8266/Arduino library Core version **pre-2.6.0** due to reported security and stability issues on previous Core version. @@ -104,8 +105,8 @@ Over 500 additional devices are supported using [templates](TEMPLATES.md). ## Provided Binary Downloads The following binary downloads have been compiled with ESP8266/Arduino library core version **pre-2.6.0**. -- **sonoff.bin** = The Sonoff version with sensors. **RECOMMENDED RELEASE BINARY** -- **sonoff-BG.bin** to **sonoff-TW.bin** = The Sonoff version in different languages. +- **sonoff.bin** = The Tasmota version with sensors. **RECOMMENDED RELEASE BINARY** +- **sonoff-BG.bin** to **sonoff-TW.bin** = The Tasmota version in different languages. - **sonoff-basic.bin** = The Basic version without most sensors. - **sonoff-knx.bin** = The Knx version without some features but adds KNX support. - **sonoff-sensors.bin** = The Sensors version adds more useful sensors. @@ -368,7 +369,7 @@ Version 6.7.1 20191026 * Add Tuya Energy monitoring by Shantur Rathore * Add Domoticz P1 Smart Meter support using energy sensors handled by xdrv_03_energy.ino based on an idea by pablozg * Add debug compile features using defines **DEBUG_TASMOTA_CORE**, **DEBUG_TASMOTA_DRIVER** and **DEBUG_TASMOTA_SENSOR**. - See **DEBUG_CORE_LOG** example in sonoff.ino and **DEBUG_DRIVER_LOG** example in xdrv_09_timers.ino + See **DEBUG_CORE_LOG** example in tasmota.ino and **DEBUG_DRIVER_LOG** example in xdrv_09_timers.ino * Add option 0 to ``Width1`` (Marker), ``Width2`` (Second), ``Width3`` (Minute) and ``Width4`` (Hour) disabling display (#6152) * Add MqttCount metric to STATE (#6155) * Add allow repeat/longpress for IRSend raw, introduced ``IRSend`` option (#6074) From 200edd46fbe080319d4bfa8e1fcb1f382489ac01 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Oct 2019 12:44:37 +0100 Subject: [PATCH 043/196] Change binary names from sonoff to tasmota --- .gitpod.yml | 2 +- .travis.yml | 56 +++++++-------- Doxyfile | 4 +- RELEASENOTES.md | 149 +++++---------------------------------- platformio.ini | 116 +++++++++++++++--------------- tasmota/_changelog.ino | 1 + tasmota/my_user_config.h | 22 +++--- tasmota/tasmota.ino | 2 +- tasmota/tasmota_post.h | 12 ++-- 9 files changed, 126 insertions(+), 238 deletions(-) diff --git a/.gitpod.yml b/.gitpod.yml index 38e7d7bfa..ee7750c54 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,3 +1,3 @@ tasks: - before: pip install -U platformio - command: platformio run -e sonoff + command: platformio run -e tasmota diff --git a/.travis.yml b/.travis.yml index 3f4121386..ee82b6f06 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,34 +13,34 @@ cache: - $HOME/.platformio env: - - ENV=sonoff - - ENV=sonoff-minimal - - ENV=sonoff-basic - - ENV=sonoff-knx - - ENV=sonoff-sensors - - ENV=sonoff-display - - ENV=sonoff-ir - - ENV=sonoff-BG - - ENV=sonoff-BR - - ENV=sonoff-CN - - ENV=sonoff-CZ - - ENV=sonoff-DE - - ENV=sonoff-ES - - ENV=sonoff-FR - - ENV=sonoff-GR - - ENV=sonoff-HE - - ENV=sonoff-HU - - ENV=sonoff-IT - - ENV=sonoff-KO - - ENV=sonoff-NL - - ENV=sonoff-PL - - ENV=sonoff-PT - - ENV=sonoff-RU - - ENV=sonoff-SE - - ENV=sonoff-SK - - ENV=sonoff-TR - - ENV=sonoff-TW - - ENV=sonoff-UK + - ENV=tasmota + - ENV=tasmota-minimal + - ENV=tasmota-basic + - ENV=tasmota-knx + - ENV=tasmota-sensors + - ENV=tasmota-display + - ENV=tasmota-ir + - ENV=tasmota-BG + - ENV=tasmota-BR + - ENV=tasmota-CN + - ENV=tasmota-CZ + - ENV=tasmota-DE + - ENV=tasmota-ES + - ENV=tasmota-FR + - ENV=tasmota-GR + - ENV=tasmota-HE + - ENV=tasmota-HU + - ENV=tasmota-IT + - ENV=tasmota-KO + - ENV=tasmota-NL + - ENV=tasmota-PL + - ENV=tasmota-PT + - ENV=tasmota-RU + - ENV=tasmota-SE + - ENV=tasmota-SK + - ENV=tasmota-TR + - ENV=tasmota-TW + - ENV=tasmota-UK script: - platformio run -e $ENV diff --git a/Doxyfile b/Doxyfile index 0d2d7031d..b563c8c3a 100644 --- a/Doxyfile +++ b/Doxyfile @@ -44,7 +44,7 @@ PROJECT_NUMBER = # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "Provide ESP8266 based itead Sonoff with Web, MQTT and OTA firmware using Arduino IDE or PlatformIO" +PROJECT_BRIEF = "Provide ESP8266 based devices with Web, MQTT and OTA firmware using Arduino IDE or PlatformIO" # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 @@ -796,7 +796,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = sonoff \ +INPUT = tasmota \ lib # This tag can be used to specify the character encoding of the source files diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 70689d60b..ea4651445 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -105,18 +105,18 @@ Over 500 additional devices are supported using [templates](TEMPLATES.md). ## Provided Binary Downloads The following binary downloads have been compiled with ESP8266/Arduino library core version **pre-2.6.0**. -- **sonoff.bin** = The Tasmota version with sensors. **RECOMMENDED RELEASE BINARY** -- **sonoff-BG.bin** to **sonoff-TW.bin** = The Tasmota version in different languages. -- **sonoff-basic.bin** = The Basic version without most sensors. -- **sonoff-knx.bin** = The Knx version without some features but adds KNX support. -- **sonoff-sensors.bin** = The Sensors version adds more useful sensors. -- **sonoff-ir** = The InfraRed Receiver and transmitter version allowing all available protocols provided by library IRremoteESP8266 but without most other features. -- **sonoff-display.bin** = The Display version without Energy Monitoring but adds display support. -- **sonoff-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. +- **tasmota.bin** = The Tasmota version with sensors. **RECOMMENDED RELEASE BINARY** +- **tasmota-BG.bin** to **tasmota-TW.bin** = The Tasmota version in different languages. +- **tasmota-basic.bin** = The Basic version without most sensors. +- **tasmota-knx.bin** = The Knx version without some features but adds KNX support. +- **tasmota-sensors.bin** = The Sensors version adds more useful sensors. +- **tasmota-ir** = The InfraRed Receiver and transmitter version allowing all available protocols provided by library IRremoteESP8266 but without most other features. +- **tasmota-display.bin** = The Display version without Energy Monitoring but adds display support. +- **tasmota-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. ## Available Features and Sensors -| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks |-----------------------|---------|-------|--------|-----|---------|----|---------|-------- | MY_LANGUAGE en-GB | x | x | x | x | x | x | x | | USE_ARDUINO_OTA | - | - | - | - | - | - | - | @@ -142,7 +142,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_EXPRESSION | - | - | - | - | - | - | - | | SUPPORT_IF_STATEMENT | - | - | - | - | - | - | - | | | | | | | | | | -| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks | ROTARY_V1 | - | - | - | - | - | - | - | | USE_SONOFF_RF | - | - | x | x | x | - | - | | USE_RF_FLASH | - | - | x | x | x | - | - | @@ -157,7 +157,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_DEEPSLEEP | - | - | - | - | - | - | - | | USE_EXS_DIMMER | - | - | x | x | - | - | - | | | | | | | | | | -| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks | USE_LIGHT | - | x | x | x | x | x | x | | USE_WS2812 | - | - | x | x | x | - | x | | USE_WS2812_DMA | - | - | - | - | - | - | - | @@ -184,7 +184,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_MAX31855 | - | - | - | - | x | - | - | | USE_MAX31865 | - | - | - | - | - | - | - | | | | | | | | | | -| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks | USE_I2C | - | - | x | x | x | - | x | | USE_SHT | - | - | x | x | x | - | x | | USE_HTU | - | - | x | x | x | - | x | @@ -220,7 +220,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_PAJ7620 | - | - | - | - | - | - | - | | USE_PCF8574 | - | - | - | - | - | - | - | | | | | | | | | | -| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks | USE_SPI | - | - | - | - | - | - | x | | USE_MHZ19 | - | - | x | x | x | - | x | | USE_SENSEAIR | - | - | x | x | x | - | x | @@ -246,7 +246,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_A4988_STEPPER | - | - | - | - | - | - | - | | USE_ARDUINO_SLAVE | - | - | - | - | - | - | - | Experimental | | | | | | | | | -| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks | USE_DISPLAY | - | - | - | - | - | - | x | | USE_DISPLAY_LCD | - | - | - | - | - | - | x | | USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x | @@ -260,120 +260,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | ## Changelog -Version 6.7.1 20191026 - * Remove support for WPS and SmartConfig in favour of Web server (!) based WifiManager (#6680) - * Remove binary sonoff-classic (#6680) - * Remove command ``SetOption2`` - * Remove default DS18B20 driver and only support define **USE_DS18x20** (#6647) - * Remove support for define **USE_DS18x20_LEGACY** and legacy DS18x20 driver (#6486) - * Replace xsns_23_sdm120 with xnrg_08_sdm120 - * Replace xsns_25_sdm630 with xnrg_10_sdm630 - * Replace xsns_49_solaxX1 with xnrg_12_solaxX1 (#6677) - * Change Sonoff L1 support by adding define **USE_SONOFF_L1** - * Change light drivers internals to ease management - * Change command ``PulseTime`` JSON message format and allow display of all pulsetimer information (#6519) - * Change command ``SetOption43`` to make it more general. Now supports PS_16_DZ driver too (#6544) - * Change command handling by moving buffers up in chain solving ``MQTTlog`` support (#6529) - * Change commands ``Var`` and ``Mem`` to show all parameters when no index is given (#6107) - * Change detection of non-MQTT commands by allowing non-space characters as delimiter (#6540) - * Change rename "Data" to "Hash" and limit to 32 bits when receiving UNKNOWN IR protocol (see DECODE_HASH from IRremoteESP8266) - * Change JSON output format for commands ``Adc``, ``Adcs``, ``Modules``, ``Gpio`` and ``Gpios`` from list to dictionary (#6407) - * Change energy sensors for three phase/channel support - * Change Settings crc calculation allowing short term backward compatibility - * Change Improve reliability of TasmotaSerial at 115200 bauds and reduce IRAM usage - * Change Tuya support by Shantur Rathore removing tuya related commands ``SetOption34, 41, 44, 45, 46, 65, 66 and 69`` (#6353) - * Change theoretical baudrate range to 300..19660500 bps in 300 increments (#6294) - * Change Settings area to 4k for future use - * Change some table locations from RAM to Flash - * Change filename of configuration backup from using FriendlyName1 to Hostname solving diacritic issues (#2422) - * Change Store AWS IoT Private Key and Certificate in SPI Flash avoiding device-specific compilations - * Change defines **USE_TX20_WIND_SENSOR** and **USE_RC_SWITCH** in my_user_config.h to disable to lower iram usage enabling latest core compilation (#6060, #6062) - * Fix PowerDelta related exception0: epc1:0x4000dce5 (#6750) - * Fix handling of ligth channels when pwm_multichannel (``SetOption68``) is enabled - * Fix better handling of PWM White Temperature mode for Module 48 (#6534) - * Fix TasmotaSerial: move serial send to IRAM for high speed baud rates - * Fix Domoticz battery level set to 100 if define **USE_ADC_VCC** is not used (#6033) - * Fix Force Elliptic Curve for Letsencrypt TLS #6042 - * Fix WeMo emulation for 1G echo and 2G echo dot (#6086) - * Fix Xiaomi Philips brightness (#6091) - * Add support for EX-Store WiFi Dimmer V4 (#5856) - * Add support for Arduino serial connection (EXPERIMENTAL) - * Add support for Zigbee devices Xiaomi lumi.weather air quality sensor, Osram mini-switch - * Add support for Zigbee device cc2530 initialization and basic ZCL decoding - * Add support for PMS3003 dust particle sensor - * Add support for Chint DDSU666 Modbus energy meter by Pablo Zerón - * Add support for SM2135 as used in Action LSC Smart Led E14 (#6495) - * Add support for Shelly 2.5 dual energy (#6160) - * Add support for shutters by Stefan Bode (#288) - * Add support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode - * Add support for up to three PZEM-014/-016 on one serial modbus connection with addresses 1 (default), 2 and 3 (#2315) - * Add support for up to three PZEM-004T on one serial connection with addresses 192.168.1.1 (default), 2 and 3 (#2315) - * Add support for up to three PZEM-003/-017 on one serial modbus connection with addresses 1 (default), 2 and 3 (#2315) - * Add support for up to 4 INA226 Voltage and Current sensors by Steve Rogers (#6342) - * Add support for A4988 stepper-motor-driver-circuit by Tim Leuschner (#6370) - * Add support for Hiking DDS238-2 Modbus energy meter by Matteo Campanella (#6384) - * Add support for HM17 bluetooth LE passive scan of ibeacon devices by Gerhard Mutz - * Add support for Solax X1 inverter by Pablo Zerón - * Add support for PAJ7620 gesture sensor by Christian Baars - * Add support for MAX31865 Thermocouple sensor by Alberto Lopez Siemens - * Add support for RDM6300 125kHz RFID Reader by Gerhard Mutz - * Add support for CHIRP soil moisture sensor by Christian Baars - * Add support for Sonoff iFan03 as module 71 (#5988) - * Add support for a buzzer - * Add support for IRSend long press ('repeat' feature from IRRemoteESP8266) (#6074) - * Add support for IRHVAC Midea/Komeco protocol (#3227) - * Add support for more IRSend protocols enabled in my_user_config.h - * Add support for IRSend Pioneer protocol (#6100) - * Add support for up to 4 INA219 sensors (#6046) - * Add support for I2C display driver SH1106 oled by Gerhard Mutz - * Add support for SPI display drivers epaper 4.2 inch, ILI9488 TFT, SSD1351 Color oled and RA8876 TFT by Gerhard Mutz - * Add command ``Buzzer`` with optional parameters ,, enabled when a buzzer is configured (#5988) - * Add command ``DimmerRange`` in Light module to support 2 byte dimming ranges from Tuya - * Add command ``DisplayHeight`` to set pixel height on supported devices - * Add command ``DisplayWidth`` to set pixel width on supported devices - * Add command ``EnergyReset4 x,x`` to initialize total usage for two tarrifs - * Add command ``EnergyReset5 x,x`` to initialize total export (or production) for two tarrifs - * Add command ``Gpio 255/All`` to show physical GPIO configuration of all non-flash pins (#6407) - * Add command ``Gpios 255/All`` to show all available GPIO components (#6407) - * Add command ``ModuleAddress 1/2/3`` to set Pzem module address when a single module is connected (#2315) - * Add command ``MqttLog `` for support of MQTT logging (#6498) - * Add command ``Power0 0/1/2/Off/On/Toggle`` to control all power outputs at once (#6340) - * Add command ``PowerDelta 101..32000`` for absolute power delta where 101 = 101-100 = 1W, 202 = 202-100 = 102W (#5901) - * Add command ``Reset 99`` to reset bootcount to zero (#684, #6351) - * Add command ``Sensor29 pin,0/1/2`` for OFF/ON/TOGGLE - * Add command ``Sensor34 8,0`` and ``Sensor34 8,1`` to disable/enable JSON message on weight change over 4 gram - * Add command ``SetOption34 0..255`` to set backlog delay. Default value is 200 (mSeconds) (#6562) - * Add command ``SetOption42 0..255`` to set overtemperature (Celsius only) threshold resulting in power off all on energy monitoring devices. Default setting is 90 (#6036) - * Add command ``SetOption65 0/1`` to disable (1) fast power cycle detection fixing unwanted brownout trigger - * Add command ``SetOption67 0/1`` to disable or enable a buzzer as used in iFan03 - * Add command ``SetOption68 0/1`` to enable multi-channel PWM instead of a single light (#6134) - * Add command ``SetOption71 0/1`` to switch between different Modbus Active Energy registers on DDS238-2 energy meters (#6531) - * Add command ``SetOption72 0/1`` to switch between software (0) or hardware (1) energy total counter (#6561) - * Add command ``Time`` to disable NTP and set UTC time as Epoch value if above 1451602800 (=20160101). ``Time 0`` re-enables NTP (#5279) - * Add command ``Time 1/2/3`` to select JSON time format ISO + Epoch, ISO or Epoch - * Add command ``Tariff`` to default to 0 (=disabled) and allowing to set both Standard Time (ST) and Daylight Savings Time (DST) start hour - ex. ``Tariff1 22,23`` = Tariff1 (Off-Peak) ST,DST ``Tariff2 6,7`` = Tariff2 (Standard) ST,DST ``Tariff9 0/1`` = Weekend toggle (1 = Off-Peak during weekend) - * Add command ``WebSensor 0/1`` to control display of sensor data in web GUI (#6085) - * Add command ``ZigbeeRead`` (#6095) - * Add define **USE_DEEPSLEEP** and command ``DeepSleepTime 0 or 10..86400`` (seconds) to enter deepsleep mode (#6638) - * Add define **USE_ENERGY_MARGIN_DETECTION** to disable Energy Margin and Power Limit detection - * Add define **USE_ENERGY_POWER_LIMIT** to disable Energy Power Limit detection while Energy Margin detection is active - * Add define **USE_SONOFF_RF** to enable/disable Sonoff Rf support (#6648) - * Add define **USE_WS2812_HARDWARE** to select hardware type WS2812, WS2812X, WS2813, SK6812, LC8812 or APA106 (DMA mode only) - * Add incremental beeps to Ifan03 remote control fan speed buttons (#6636) - * Add rule support after every command execution like Fanspeed#Data=2 (#6636) - * Add WebUI for multiple, independent PWM channels - * Add JSON array index support to rules evaluation allowing trigger on ENERGY#POWER[2]>0.60 from JSON ..,"Power":[0.00,0.68],.. (#6160) - * Add Full support of all protocols in IRremoteESP8266, to be used on dedicated-IR Tasmota version. Warning: +81k Flash when compiling with **USE_IR_REMOTE_FULL** - * Add 'sonoff-ir' pre-packaged IR-dedicated firmware and 'sonoff-ircustom' to customize firmware with IR Full protocol support - * Add Tuya Energy monitoring by Shantur Rathore - * Add Domoticz P1 Smart Meter support using energy sensors handled by xdrv_03_energy.ino based on an idea by pablozg - * Add debug compile features using defines **DEBUG_TASMOTA_CORE**, **DEBUG_TASMOTA_DRIVER** and **DEBUG_TASMOTA_SENSOR**. - See **DEBUG_CORE_LOG** example in tasmota.ino and **DEBUG_DRIVER_LOG** example in xdrv_09_timers.ino - * Add option 0 to ``Width1`` (Marker), ``Width2`` (Second), ``Width3`` (Minute) and ``Width4`` (Hour) disabling display (#6152) - * Add MqttCount metric to STATE (#6155) - * Add allow repeat/longpress for IRSend raw, introduced ``IRSend`` option (#6074) - * Add Oled reset GPIO option "OLED reset" - * Add blend RGB leds with White leds for better whites (#5895, #5704) - * Add AZ7798 automatic setting of clock display (#6034) - * Add Epoch and UptimeSec to JSON messages (#6068) +Version 7.1.0 Betty + * Change ArduinoSlave to TasmotaSlave (Experimental) + * Change repository name from Sonoff-Tasmota to Tasmota and all code references from Sonoff to Tasmota + * Add support for Tuya battery powered devices (#6735) diff --git a/platformio.ini b/platformio.ini index 4ea6d30d6..53983cb41 100755 --- a/platformio.ini +++ b/platformio.ini @@ -13,35 +13,35 @@ build_dir = .pioenvs build_cache_dir = .cache ; *** Uncomment one of the lines below to build/upload only one environment -;default_envs = sonoff -;default_envs = sonoff-ircustom ; alternative to 'sonoff' with full IR protocols activated, you will need to disable some features to keep code not too big -;default_envs = sonoff-minimal -;default_envs = sonoff-basic -;default_envs = sonoff-knx -;default_envs = sonoff-sensors -;default_envs = sonoff-display -;default_envs = sonoff-ir -;default_envs = sonoff-BG -;default_envs = sonoff-BR -;default_envs = sonoff-CN -;default_envs = sonoff-CZ -;default_envs = sonoff-DE -;default_envs = sonoff-ES -;default_envs = sonoff-FR -;default_envs = sonoff-GR -;default_envs = sonoff-HE -;default_envs = sonoff-HU -;default_envs = sonoff-IT -;default_envs = sonoff-KO -;default_envs = sonoff-NL -;default_envs = sonoff-PL -;default_envs = sonoff-PT -;default_envs = sonoff-RU -;default_envs = sonoff-SE -;default_envs = sonoff-SK -;default_envs = sonoff-TR -;default_envs = sonoff-TW -;default_envs = sonoff-UK +;default_envs = tasmota +;default_envs = tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big +;default_envs = tasmota-minimal +;default_envs = tasmota-basic +;default_envs = tasmota-knx +;default_envs = tasmota-sensors +;default_envs = tasmota-display +;default_envs = tasmota-ir +;default_envs = tasmota-BG +;default_envs = tasmota-BR +;default_envs = tasmota-CN +;default_envs = tasmota-CZ +;default_envs = tasmota-DE +;default_envs = tasmota-ES +;default_envs = tasmota-FR +;default_envs = tasmota-GR +;default_envs = tasmota-HE +;default_envs = tasmota-HU +;default_envs = tasmota-IT +;default_envs = tasmota-KO +;default_envs = tasmota-NL +;default_envs = tasmota-PL +;default_envs = tasmota-PT +;default_envs = tasmota-RU +;default_envs = tasmota-SE +;default_envs = tasmota-SK +;default_envs = tasmota-TR +;default_envs = tasmota-TW +;default_envs = tasmota-UK [esp82xx_defaults] build_flags = -D NDEBUG @@ -246,7 +246,7 @@ extra_scripts = pio/strip-floats.py ; ********************************************************************* -[env:sonoff] +[env:tasmota] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -260,7 +260,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-minimal] +[env:tasmota-minimal] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -274,7 +274,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-basic] +[env:tasmota-basic] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -288,7 +288,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-knx] +[env:tasmota-knx] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -302,7 +302,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-sensors] +[env:tasmota-sensors] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -316,7 +316,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-display] +[env:tasmota-display] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -330,7 +330,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-ir] +[env:tasmota-ir] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -344,7 +344,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-ircustom] +[env:tasmota-ircustom] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -358,7 +358,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-BG] +[env:tasmota-BG] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -372,7 +372,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-BR] +[env:tasmota-BR] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -386,7 +386,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-CN] +[env:tasmota-CN] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -400,7 +400,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-CZ] +[env:tasmota-CZ] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -414,7 +414,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-DE] +[env:tasmota-DE] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -428,7 +428,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-ES] +[env:tasmota-ES] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -442,7 +442,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-FR] +[env:tasmota-FR] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -456,7 +456,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-GR] +[env:tasmota-GR] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -470,7 +470,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-HE] +[env:tasmota-HE] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -484,7 +484,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-HU] +[env:tasmota-HU] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -498,7 +498,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-IT] +[env:tasmota-IT] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -512,7 +512,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-KO] +[env:tasmota-KO] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -526,7 +526,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-NL] +[env:tasmota-NL] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -540,7 +540,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-PL] +[env:tasmota-PL] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -554,7 +554,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-PT] +[env:tasmota-PT] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -568,7 +568,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-RU] +[env:tasmota-RU] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -582,7 +582,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-SE] +[env:tasmota-SE] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -596,7 +596,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-SK] +[env:tasmota-SK] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -610,7 +610,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-TR] +[env:tasmota-TR] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -624,7 +624,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-TW] +[env:tasmota-TW] platform = ${common.platform} framework = ${common.framework} board = ${common.board} @@ -638,7 +638,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-UK] +[env:tasmota-UK] platform = ${common.platform} framework = ${common.framework} board = ${common.board} diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 33d77decc..5819dd2d4 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -3,6 +3,7 @@ * Change ArduinoSlave to TasmotaSlave (Experimental) * Add support for Tuya battery powered devices (#6735) * Change repository name from Sonoff-Tasmota to Tasmota + * Change all code references from Sonoff to Tasmota * * 6.7.1 20191026 * Release diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 6a46a15bb..4cb42f130 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -79,7 +79,7 @@ #define MQTT_LOG_LEVEL LOG_LEVEL_NONE // [MqttLog] (LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE) // -- Ota ----------------------------------------- -#define OTA_URL "http://thehackbox.org/tasmota/release/sonoff.bin" // [OtaUrl] +#define OTA_URL "http://thehackbox.org/tasmota/release/tasmota.bin" // [OtaUrl] // -- MQTT ---------------------------------------- #define MQTT_USE 1 // [SetOption3] Select default MQTT use (0 = Off, 1 = On) @@ -468,9 +468,9 @@ // -- IR Remote features - all protocols from IRremoteESP8266 -------------------------- // IR Full Protocols mode is activated through platform.io only. -// Either use 'default_envs = sonoff-ircustom' and disable some features here to keep code not too big -// or use 'default_envs = sonoff-ir' for a pre-packaged IR-dedicated firmware -// When using 'sonoff-ircustom' or 'sonoff-ir', parameters below +// Either use 'default_envs = tasmota-ircustom' and disable some features here to keep code not too big +// or use 'default_envs = tasmota-ir' for a pre-packaged IR-dedicated firmware +// When using 'tasmota-ircustom' or 'tasmota-ir', parameters below // (USE_IR_REMOTE, USE_IR_RECEIVE, USE_IR_HVAC...) are IGNORED. // // Code impact of IR full protocols is +81k code, 3k mem @@ -555,13 +555,13 @@ * See RELEASENOTES.md for selected features \*********************************************************************************************/ -//#define FIRMWARE_BASIC // Create sonoff-basic with no sensors -//#define FIRMWARE_SENSORS // Create sonoff-sensors with useful sensors enabled -//#define FIRMWARE_KNX_NO_EMULATION // Create sonoff-knx with KNX but without Emulation -//#define FIRMWARE_DISPLAYS // Create sonoff-display with display drivers enabled -//#define FIRMWARE_IR // Create sonoff-ir with IR full protocols activated, and many sensors disabled -//#define FIRMWARE_IR_CUSTOM // Create sonoff customizable with special marker to add all IR protocols -//#define FIRMWARE_MINIMAL // Create sonoff-minimal as intermediate firmware for OTA-MAGIC +//#define FIRMWARE_BASIC // Create tasmota-basic with no sensors +//#define FIRMWARE_SENSORS // Create tasmota-sensors with useful sensors enabled +//#define FIRMWARE_KNX_NO_EMULATION // Create tasmota-knx with KNX but without Emulation +//#define FIRMWARE_DISPLAYS // Create tasmota-display with display drivers enabled +//#define FIRMWARE_IR // Create tasmota-ir with IR full protocols activated, and many sensors disabled +//#define FIRMWARE_IR_CUSTOM // Create tasmota customizable with special marker to add all IR protocols +//#define FIRMWARE_MINIMAL // Create tasmota-minimal as intermediate firmware for OTA-MAGIC /*********************************************************************************************\ * No user configurable items below diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index c4526a808..263888558 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -71,7 +71,7 @@ const char kSleepMode[] PROGMEM = "Dynamic|Normal"; const char kPrefixes[] PROGMEM = D_CMND "|" D_STAT "|" D_TELE; -const char kCodeImage[] PROGMEM = "sonoff|minimal|sensors|knx|basic|display|ir"; +const char kCodeImage[] PROGMEM = "tasmota|minimal|sensors|knx|basic|display|ir"; // Global variables SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 09620c320..ff5513481 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -70,7 +70,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif /*********************************************************************************************\ - * [sonoff-sensors.bin] + * [tasmota-sensors.bin] * Provide an image with useful supported sensors enabled \*********************************************************************************************/ @@ -214,7 +214,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif // FIRMWARE_SENSORS /*********************************************************************************************\ - * [sonoff-knx.bin] + * [tasmota-knx.bin] * Provide a dedicated KNX image allowing enough code and memory space \*********************************************************************************************/ @@ -234,7 +234,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif // FIRMWARE_KNX_NO_EMULATION /*********************************************************************************************\ - * [sonoff-display.bin] + * [tasmota-display.bin] * Provide an image with display drivers enabled \*********************************************************************************************/ @@ -298,7 +298,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif // FIRMWARE_DISPLAYS /*********************************************************************************************\ - * [sonoff-ir.bin] + * [tasmota-ir.bin] * Provide a dedicated image with IR full protocol support, with limited additional features \*********************************************************************************************/ @@ -388,7 +388,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif // FIRMWARE_IR /*********************************************************************************************\ - * [sonoff-basic.bin] + * [tasmota-basic.bin] * Provide an image without sensors \*********************************************************************************************/ @@ -490,7 +490,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif // FIRMWARE_BASIC /*********************************************************************************************\ - * [sonoff-minimal.bin] + * [tasmota-minimal.bin] * Provide the smallest image possible while still enabling a webserver for intermediate image load \*********************************************************************************************/ From 1d57dee15776937707308d2c87a2177836f36666 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sun, 27 Oct 2019 13:46:11 +0200 Subject: [PATCH 044/196] Remove ArduinoHexParser --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 28d5592f3..7aa801978 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,6 @@ Libraries used with Tasmota are: - [Adafruit SSD1306](https://github.com/adafruit/Adafruit_SSD1306) - Adafruit based SSD1351 - [Adafruit GFX](https://github.com/adafruit/Adafruit-GFX-Library) -- Arduino Hex Parser - [ArduinoJson](https://arduinojson.org/) - AT24C256 I2C eeprom - [Base64](https://github.com/Densaugeo/base64_arduino) From 1a148311e19d50aa22524846a824c3c39f1c7150 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Oct 2019 13:55:04 +0100 Subject: [PATCH 045/196] Change tuya receive from stat to tele (#6758) --- tasmota/xdrv_16_tuyamcu.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 6cab4bb4d..608303efc 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -681,7 +681,7 @@ void TuyaSerialInput(void) ResponseAppend_P(PSTR("}}")); if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_TUYA_MCU_RECEIVED)); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); } else { AddLog_P(LOG_LEVEL_DEBUG, mqtt_data); } From 51a6aceaa80a1367436c45f26252d514699bcb79 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Oct 2019 14:04:07 +0100 Subject: [PATCH 046/196] Bump version 7.0.0.1 Remove references to versions before 6.x --- tasmota/_changelog.ino | 3 ++ tasmota/settings.ino | 99 --------------------------------------- tasmota/tasmota_version.h | 2 +- 3 files changed, 4 insertions(+), 100 deletions(-) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 5819dd2d4..75afc236a 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -1,4 +1,7 @@ /*********************************************************************************************\ + * 7.0.0.1 20191027 + * Remove references to versions before 6.x + * * 6.7.1.1 20191026 * Change ArduinoSlave to TasmotaSlave (Experimental) * Add support for Tuya battery powered devices (#6735) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 75d1726c0..31ece2364 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -938,105 +938,6 @@ void SettingsDefaultWebColor(void) void SettingsDelta(void) { if (Settings.version != VERSION) { // Fix version dependent changes - - if (Settings.version < 0x05050000) { - for (uint32_t i = 0; i < 17; i++) { Settings.rf_code[i][0] = 0; } - memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); - } - if (Settings.version < 0x05080000) { - Settings.light_pixels = WS2812_LEDS; - Settings.light_width = 1; - Settings.light_color[0] = 255; - Settings.light_color[1] = 0; - Settings.light_color[2] = 0; - Settings.light_dimmer = 10; - Settings.light_correction = 1; - Settings.light_fade = 0; - Settings.light_speed = 1; - Settings.light_scheme = 0; - Settings.light_width = 1; - Settings.light_wakeup = 0; - } - if (Settings.version < 0x0508000A) { - Settings.power = 0; - Settings.altitude = 0; - } - if (Settings.version < 0x0508000B) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { // Move GPIO_LEDs - if ((Settings.my_gp.io[i] >= 25) && (Settings.my_gp.io[i] <= 32)) { // Was GPIO_LED1 - Settings.my_gp.io[i] += 23; // Move GPIO_LED1 - } - } - for (uint32_t i = 0; i < MAX_PWMS; i++) { // Move pwm_value and reset additional pulse_timerrs - Settings.pwm_value[i] = Settings.pulse_timer[4 +i]; - Settings.pulse_timer[4 +i] = 0; - } - } - if (Settings.version < 0x0508000D) { - Settings.pwm_frequency = PWM_FREQ; - Settings.pwm_range = PWM_RANGE; - } - if (Settings.version < 0x0508000E) { - SettingsDefaultSet_5_8_1(); - } - if (Settings.version < 0x05090102) { - Settings.flag2.data = Settings.flag.data; - Settings.flag2.data &= 0xFFE80000; - Settings.flag2.voltage_resolution = Settings.flag.not_power_linked; - Settings.flag2.current_resolution = 3; - Settings.ina219_mode = 0; - } - if (Settings.version < 0x050A0009) { - SettingsDefaultSet_5_10_1(); - } - if (Settings.version < 0x050B0107) { - Settings.flag.not_power_linked = 0; - } - if (Settings.version < 0x050C0005) { - Settings.light_rotation = 0; - Settings.energy_power_delta = 0; - char fingerprint[60]; - memcpy(fingerprint, Settings.mqtt_fingerprint, sizeof(fingerprint)); - char *p = fingerprint; - for (uint32_t i = 0; i < 20; i++) { - Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16); - Settings.mqtt_fingerprint[1][i] = Settings.mqtt_fingerprint[0][i]; - } - } - if (Settings.version < 0x050C0007) { - Settings.baudrate = APP_BAUDRATE / 300; - } - if (Settings.version < 0x050C0008) { - Settings.sbaudrate = SOFT_BAUDRATE / 300; - Settings.serial_delimiter = 0xff; - } - if (Settings.version < 0x050C000A) { - Settings.latitude = (int)((double)LATITUDE * 1000000); - Settings.longitude = (int)((double)LONGITUDE * 1000000); - } - if (Settings.version < 0x050C000B) { - Settings.rules[0][0] = '\0'; - } - if (Settings.version < 0x050C000D) { - memmove(Settings.rules, Settings.rules -256, sizeof(Settings.rules)); // move rules up by 256 bytes - memset(&Settings.timer, 0x00, sizeof(Timer) * MAX_TIMERS); // Reset timers as layout has changed from v5.12.0i - Settings.knx_GA_registered = 0; - Settings.knx_CB_registered = 0; - memset(&Settings.knx_physsical_addr, 0x00, 0x800 - 0x6b8); // Reset until 0x800 for future use - } - if (Settings.version < 0x050C000F) { - Settings.energy_kWhtoday /= 1000; - Settings.energy_kWhyesterday /= 1000; - RtcSettings.energy_kWhtoday /= 1000; - } - if (Settings.version < 0x050D0103) { - SettingsDefaultSet_5_13_1c(); - } - if (Settings.version < 0x050E0002) { - for (uint32_t i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; } - Settings.rule_enabled = Settings.flag.mqtt_serial_raw; // Was rules_enabled until 5.14.0b - Settings.rule_once = Settings.flag.pressure_conversion; // Was rules_once until 5.14.0b - } if (Settings.version < 0x06000000) { Settings.cfg_size = sizeof(SYSCFG); Settings.cfg_crc = GetSettingsCrc(); diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 695d14146..12fa83147 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x06070101; +const uint32_t VERSION = 0x07000001; #endif // _TASMOTA_VERSION_H_ From fef6d0c7c59997ee7e99ba966dd0704934edec8e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Oct 2019 14:23:03 +0100 Subject: [PATCH 047/196] Version update --- README.md | 2 +- REFERENCE.md | 20 -------------------- 2 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 REFERENCE.md diff --git a/README.md b/README.md index 7aa801978..652ce9588 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ See [RELEASENOTES.md](https://github.com/arendst/Tasmota/blob/development/RELEAS In addition to the [release webpage](https://github.com/arendst/Tasmota/releases/latest) the binaries can also be downloaded from http://thehackbox.org/tasmota/release/ ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v6.7.1.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v7.0.0.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota) diff --git a/REFERENCE.md b/REFERENCE.md deleted file mode 100644 index 6d2c08747..000000000 --- a/REFERENCE.md +++ /dev/null @@ -1,20 +0,0 @@ -Logo - -# Reference - -Tasmota backgound information. - -## Supported Smart Switch with Energy Monitoring GPIO usage -Module | GPIO00 | GPIO01 | GPIO02 | GPIO03 | GPIO04 | GPIO05 | GPIO12 | GPIO13 | GPIO14 | GPIO15 --------|--------|--------|--------|--------|--------|--------|--------|--------|--------|-------- -Sonoff Pow | KEY1 | - | - | - | - | NRG_SEL | REL1 | NRG_CF1 | HLW_CF | LED1 -Sonoff Pow R2 | KEY1 | RXD | - | TXD | - | - | REL1 | LED1_INV | - | - -Shelly 2 | - | RXD | - | TXD | REL1 | REL2 | SWT1 | - | SWT2 | - -Huafan SS | LED1_INV | - | - | LED2_INV | KEY1 | REL1_INV | NRG_CF1 | NRG_SEL | HLW_CF | - -KMC 70011 | KEY1 | - | - | - | HLW_CF | NRG_CF1 | NRG_SEL | LED1_INV | REL1 | - -Teckin | - | KEY1 | - | LED2_INV | HJL_CF | NRG_CF1 | NRG_SEL_INV | LED1_INV | REL1 | - -AplicWDP303075 | - | - | - | KEY1 | HLW_CF | NRG_CF1 | NRG_SEL_INV | LED1_INV | REL1 | - -Gosund SP1 v23 | - | LED1_INV | - | KEY1 | HJL_CF | NRG_CF1 | NRG_SEL_INV | LED2_INV | REL1 | - -SK03 Outdoor | KEY1 | - | - | - | HLW_CF | NRG_CF1 | NRG_SEL_INV | LED2_INV | LED1_INV | REL1 -BlitzWolf SHP | LED2_INV | - | LED1_INV | - | - | HJL_CF | NRG_SEL_INV | KEY1 | NRG_CF1 | REL1 -Teckin US | LED2_INV | - | LED1_INV | - | REL1 | HJL_CF | NRG_SEL_INV | KEY1 | NRG_CF1 | - From 26584975266286ef7376e5e4b0e20eeba82335f8 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 27 Oct 2019 20:10:25 +0200 Subject: [PATCH 048/196] TasmotaSlave: Revert removal of RSTi --- tasmota/tasmota_template.h | 16 +++++++++------- tasmota/xdrv_31_tasmota_slave.ino | 17 +++++++++++++---- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index b63118bf3..bf361ca0f 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -208,9 +208,10 @@ enum UserSelectablePins { GPIO_SM2135_DAT, // SM2135 Dat GPIO_DEEPSLEEP, // Kill switch for deepsleep GPIO_EXS_ENABLE, // EXS MCU Enable - GPIO_TASMOTASLAVE_TXD, // Arduino Slave TX - GPIO_TASMOTASLAVE_RXD, // Arduino Slave RX - GPIO_TASMOTASLAVE_RST, // Arduino Reset Pin + GPIO_TASMOTASLAVE_TXD, // Slave TX + GPIO_TASMOTASLAVE_RXD, // Slave RX + GPIO_TASMOTASLAVE_RST, // Slave Reset Pin + GPIO_TASMOTASLAVE_RST_INV, // Slave Reset Inverted GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -289,7 +290,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|" D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" - D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" + D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" D_SENSOR_SLAVE_RESET "i|" ; const char kSensorNamesFixed[] PROGMEM = @@ -703,9 +704,10 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_PN532_RXD, // PN532 HSU Rx #endif #ifdef USE_TASMOTA_SLAVE - GPIO_TASMOTASLAVE_TXD, // Tasmota Slave TX - GPIO_TASMOTASLAVE_RXD, // Tasmota Slave RX - GPIO_TASMOTASLAVE_RST, // Tasmota Reset Pin + GPIO_TASMOTASLAVE_TXD, // Tasmota Slave TX + GPIO_TASMOTASLAVE_RXD, // Tasmota Slave RX + GPIO_TASMOTASLAVE_RST, // Tasmota Slave Reset + GPIO_TASMOTASLAVE_RST_INV, // Tasmota Slave Reset Inverted #endif #ifdef USE_RDM6300 GPIO_RDM6300_RX, diff --git a/tasmota/xdrv_31_tasmota_slave.ino b/tasmota/xdrv_31_tasmota_slave.ino index dff94182b..2a413516f 100644 --- a/tasmota/xdrv_31_tasmota_slave.ino +++ b/tasmota/xdrv_31_tasmota_slave.ino @@ -134,6 +134,7 @@ struct TSLAVE { uint32_t spi_hex_size = 0; uint32_t spi_sector_counter = 0; uint8_t spi_sector_cursor = 0; + uint8_t inverted = LOW; bool type = false; bool flashing = false; bool SerialEnabled = false; @@ -198,9 +199,11 @@ uint8_t TasmotaSlave_UpdateInit(void) void TasmotaSlave_Reset(void) { if (TSlave.SerialEnabled) { - digitalWrite(pin[GPIO_TASMOTASLAVE_RST], LOW); + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], !TSlave.inverted); delay(1); - digitalWrite(pin[GPIO_TASMOTASLAVE_RST], HIGH); + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], TSlave.inverted); + delay(1); + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], !TSlave.inverted); delay(5); } } @@ -408,15 +411,21 @@ void TasmotaSlave_Init(void) return; } if (!TSlave.SerialEnabled) { - if ((pin[GPIO_TASMOTASLAVE_RXD] < 99) && (pin[GPIO_TASMOTASLAVE_TXD] < 99) && (pin[GPIO_TASMOTASLAVE_RST] < 99)) { + if ((pin[GPIO_TASMOTASLAVE_RXD] < 99) && (pin[GPIO_TASMOTASLAVE_TXD] < 99) && + ((pin[GPIO_TASMOTASLAVE_RST] < 99) || (pin[GPIO_TASMOTASLAVE_RST_INV] < 99))) { TasmotaSlave_Serial = new TasmotaSerial(pin[GPIO_TASMOTASLAVE_RXD], pin[GPIO_TASMOTASLAVE_TXD], 1, 0, 200); if (TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_SERIAL_SPEED)) { if (TasmotaSlave_Serial->hardwareSerial()) { ClaimSerial(); } + if (pin[GPIO_TASMOTASLAVE_RST_INV] < 99) { + pin[GPIO_TASMOTASLAVE_RST] = pin[GPIO_TASMOTASLAVE_RST_INV]; + pin[GPIO_TASMOTASLAVE_RST_INV] = 99; + TSlave.inverted = HIGH; + } pinMode(pin[GPIO_TASMOTASLAVE_RST], OUTPUT); - TasmotaSlave_Reset(); TSlave.SerialEnabled = true; + TasmotaSlave_Reset(); AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Enabled")); } } From c1d3bb41ddd977a68c1210246fcddc1a0d4c0d15 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 27 Oct 2019 23:07:20 +0200 Subject: [PATCH 049/196] TasmotaSlave Tuning --- tasmota/xdrv_31_tasmota_slave.ino | 40 ++++++++++++++++++------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/tasmota/xdrv_31_tasmota_slave.ino b/tasmota/xdrv_31_tasmota_slave.ino index 2a413516f..782ac7514 100644 --- a/tasmota/xdrv_31_tasmota_slave.ino +++ b/tasmota/xdrv_31_tasmota_slave.ino @@ -224,7 +224,7 @@ uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout) uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count) { TasmotaSlave_Serial->write(bytes, count); - TasmotaSlave_waitForSerialData(2, 1000); + TasmotaSlave_waitForSerialData(2, 250); uint8_t sync = TasmotaSlave_Serial->read(); uint8_t ok = TasmotaSlave_Serial->read(); if ((sync == 0x14) && (ok == 0x10)) { @@ -257,7 +257,7 @@ uint8_t TasmotaSlave_exitProgMode(void) return TasmotaSlave_execCmd(CMND_STK_LEAVE_PROGMODE); // Exit programming mode } -void TasmotaSlave_SetupFlash(void) +uint8_t TasmotaSlave_SetupFlash(void) { uint8_t ProgParams[] = {0x86, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; uint8_t ExtProgParams[] = {0x05, 0x04, 0xd7, 0xc2, 0x00}; @@ -265,48 +265,47 @@ void TasmotaSlave_SetupFlash(void) if (TasmotaSlave_Serial->hardwareSerial()) { ClaimSerial(); } + TasmotaSlave_Reset(); - uint8_t timer = 0; - bool no_error = false; - while (200 > timer) { + uint8_t timeout = 0; + uint8_t no_error = 0; + while (50 > timeout) { if (TasmotaSlave_execCmd(CMND_STK_GET_SYNC)) { - timer = 200; - no_error = true; + timeout = 200; + no_error = 1; } + timeout++; delay(1); } - if (no_error) { AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Found bootloader")); } else { + no_error = 0; AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Bootloader could not be found")); } - if (no_error) { if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) { } else { - no_error = true; + no_error = 0; AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (1)")); } } - if (no_error) { if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) { } else { - no_error = true; + no_error = 0; AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (2)")); } } - if (no_error) { if (TasmotaSlave_execCmd(CMND_STK_ENTER_PROGMODE)) { } else { - no_error = true; + no_error = 0; AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Failed to put bootloader into programming mode")); } } - + return no_error; } uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo) @@ -324,7 +323,7 @@ void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) TasmotaSlave_Serial->write(data[i]); } TasmotaSlave_Serial->write(CONST_STK_CRC_EOP); - TasmotaSlave_waitForSerialData(2, 1000); + TasmotaSlave_waitForSerialData(2, 250); TasmotaSlave_Serial->read(); TasmotaSlave_Serial->read(); } @@ -337,9 +336,15 @@ void TasmotaSlave_Flash(void) char thishexline[50]; uint8_t position = 0; char* flash_buffer; + SimpleHexParse hexParse = SimpleHexParse(); - TasmotaSlave_SetupFlash(); + if (!TasmotaSlave_SetupFlash()) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flashing aborted!")); + TSlave.flashing = false; + restart_flag = 2; + return; + } flash_buffer = new char[SPI_FLASH_SEC_SIZE]; uint32_t flash_start = TasmotaSlave_FlashStart() * SPI_FLASH_SEC_SIZE; @@ -418,6 +423,7 @@ void TasmotaSlave_Init(void) if (TasmotaSlave_Serial->hardwareSerial()) { ClaimSerial(); } + TasmotaSlave_Serial->setTimeout(50); if (pin[GPIO_TASMOTASLAVE_RST_INV] < 99) { pin[GPIO_TASMOTASLAVE_RST] = pin[GPIO_TASMOTASLAVE_RST_INV]; pin[GPIO_TASMOTASLAVE_RST_INV] = 99; From 6c1ff9eb06411685ed9991ee4d2d1bfa279459c5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 28 Oct 2019 09:54:23 +0100 Subject: [PATCH 050/196] Change default GUI to dark theme --- tasmota/_changelog.ino | 1 + tasmota/my_user_config.h | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 75afc236a..ed3f1607f 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -1,6 +1,7 @@ /*********************************************************************************************\ * 7.0.0.1 20191027 * Remove references to versions before 6.x + * Change default GUI to dark theme * * 6.7.1.1 20191026 * Change ArduinoSlave to TasmotaSlave (Experimental) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 4cb42f130..e159bdbe9 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -132,7 +132,12 @@ #define WEB_PASSWORD "" // [WebPassword] Web server Admin mode Password for WEB_USERNAME (empty string = Disable) #define FRIENDLY_NAME "Tasmota" // [FriendlyName] Friendlyname up to 32 characters used by webpages and Alexa #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) + +// -- 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 +// webcolor {"webcolor":["#000","#fff","#f2f2f2","#000","#fff","#000","#fff"]} +/* #define COLOR_TEXT "#000" // [WebColor1] Global text color - Black #define COLOR_BACKGROUND "#fff" // [WebColor2] Global background color - White #define COLOR_FORM "#f2f2f2" // [WebColor3] Form background color - Greyish @@ -140,6 +145,18 @@ #define COLOR_INPUT "#fff" // [WebColor5] Input background color - White #define COLOR_CONSOLE_TEXT "#000" // [WebColor6] Console text color - Black #define COLOR_CONSOLE "#fff" // [WebColor7] Console background color - White +*/ +// Dark theme +// webcolor {"webcolor":["#eee","#181818","#4f4f4f","#000","#ddd","#6a9955","#1e1e1e"]} +#define COLOR_TEXT "#eee" // [WebColor1] Global text color - Whiteish +#define COLOR_BACKGROUND "#181818" // [WebColor2] Global background color - Blackish +#define COLOR_FORM "#4f4f4f" // [WebColor3] Form background color - Greyish +#define COLOR_INPUT_TEXT "#000" // [WebColor4] Input text color - Black +#define COLOR_INPUT "#ddd" // [WebColor5] Input background color - Darker white +#define COLOR_CONSOLE_TEXT "#6a9955" // [WebColor6] Console text color - Greenish +#define COLOR_CONSOLE "#1e1e1e" // [WebColor7] Console background color - Blackish + +// Other colors #define COLOR_TEXT_WARNING "#f00" // [WebColor8] Warning text color - Red #define COLOR_TEXT_SUCCESS "#008000" // [WebColor9] Success text color - Green #define COLOR_BUTTON_TEXT "#fff" // [WebColor10] Button text color - White From fb757dabf2e3f47126a77d6dd7410b66a095e9ef Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Mon, 28 Oct 2019 10:24:35 +0100 Subject: [PATCH 051/196] Core Stage added NONOSDK22x_191024... and enabled by default for core stage. Updated NONO SDK22x from191024. See https://github.com/esp8266/Arduino/commit/ba50bd57b81cf4106fe44ab831d5a061facd4be9 --- platformio.ini | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/platformio.ini b/platformio.ini index 53983cb41..eaf820194 100755 --- a/platformio.ini +++ b/platformio.ini @@ -154,11 +154,15 @@ build_flags = ${esp82xx_defaults.build_flags} ; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473 -O2 -DBEARSSL_SSL_BASIC -; nonos-sdk 22y - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22y -; nonos-sdk 22x -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x -; nonos-sdk-pre-v3 +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 (Tasmota default) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK3V0 (known issues) ; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 ; lwIP 1.4 ; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH @@ -170,7 +174,7 @@ build_flags = ${esp82xx_defaults.build_flags} ; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH ; lwIP 2 - Higher Bandwidth no Features (Tasmota default) -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; VTABLES in Flash (default) +; VTABLES in Flash (Tasmota default) -DVTABLES_IN_FLASH ; VTABLES in Heap ; -DVTABLES_IN_DRAM From 2dabaa3d20d76df8b52dc4b307987fef9fc17a38 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 28 Oct 2019 13:36:04 +0100 Subject: [PATCH 052/196] Add command SetOption73 0/1 to re-enable CORS Add command SetOption73 0/1 to re-enable HTTP Cross-Origin Resource Sharing (CORS) now default disabled (#6767) --- tasmota/_changelog.ino | 1 + tasmota/settings.h | 6 +++--- tasmota/xdrv_01_webserver.ino | 13 +++++++++---- tools/decode-status.py | 5 +++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index ed3f1607f..dce497fdf 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -2,6 +2,7 @@ * 7.0.0.1 20191027 * Remove references to versions before 6.x * Change default GUI to dark theme + * Add command SetOption73 0/1 to re-enable HTTP Cross-Origin Resource Sharing (CORS) now default disabled (#6767) * * 6.7.1.1 20191026 * Change ArduinoSlave to TasmotaSlave (Experimental) diff --git a/tasmota/settings.h b/tasmota/settings.h index 02674b6bc..96bd2e6df 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -79,14 +79,14 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t no_power_feedback : 1; // bit 13 (v6.5.0.9) - SetOption63 - Don't scan relay power state at restart uint32_t use_underscore : 1; // bit 14 (v6.5.0.12) - SetOption64 - Enable "_" instead of "-" as sensor index separator uint32_t fast_power_cycle_disable : 1; // bit 15 (v6.6.0.20) - SetOption65 - Disable fast power cycle detection for device reset - uint32_t tuya_serial_mqtt_publish : 1; // bit 16 (v6.6.0.21) - SetOption66 - Enable or Disable TuyaMcuReceived messages over Mqtt + uint32_t tuya_serial_mqtt_publish : 1; // bit 16 (v6.6.0.21) - SetOption66 - Enable TuyaMcuReceived messages over Mqtt uint32_t buzzer_enable : 1; // bit 17 (v6.6.0.1) - SetOption67 - Enable buzzer when available uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM - uint32_t ex_tuya_dimmer_min_limit : 1; // bit 19 (v6.6.0.5) - SetOption69 - Limits Tuya dimmers to minimum of 10% (25) when enabled. + uint32_t ex_tuya_dimmer_min_limit : 1; // bit 19 (v6.6.0.5) - SetOption69 - Limits Tuya dimmers to minimum of 10% (25) when enabled. uint32_t energy_weekend : 1; // bit 20 (v6.6.0.8) - CMND_TARIFF uint32_t dds2382_model : 1; // bit 21 (v6.6.0.14) - SetOption71 - Select different Modbus registers for Active Energy (#6531) uint32_t hardware_energy_total : 1; // bit 22 (v6.6.0.15) - SetOption72 - Enable / Disable hardware energy total counter as reference (#6561) - uint32_t spare23 : 1; + uint32_t cors_enabled : 1; // bit 23 (v7.0.0.1) - SetOption73 - Enable HTTP CORS uint32_t spare24 : 1; uint32_t spare25 : 1; uint32_t spare26 : 1; diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index cab654c91..648dca783 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -667,14 +667,19 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true) return true; } +void HttpHeaderCors(void) +{ + if (Settings.flag3.cors_enabled) { + WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); + } +} + void WSHeaderSend(void) { WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate")); WebServer->sendHeader(F("Pragma"), F("no-cache")); WebServer->sendHeader(F("Expires"), F("-1")); -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 - WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); -#endif + HttpHeaderCors(); } /********************************************************************************************** @@ -2273,7 +2278,7 @@ void HandleUploadLoop(void) void HandlePreflightRequest(void) { - WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); + HttpHeaderCors(); WebServer->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST")); WebServer->sendHeader(F("Access-Control-Allow-Headers"), F("authorization")); WSSend(200, CT_HTML, ""); diff --git a/tools/decode-status.py b/tools/decode-status.py index fcf65c7db..f360de701 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -119,13 +119,14 @@ a_setoption = [[ "Do not scan relay power state at restart", "Use _ instead of - as sensor index separator", "Disable fast power cycle detection for device reset", - "(not used) Disable Dimmer range 255 slider control", + "Enable TuyaMcuReceived messages over Mqtt", "Enable buzzer when available", "Enable multi-channels PWM instead of Color PWM", "(not used) Limits Tuya MCU dimmers to minimum of 10% (25) when enabled", "Enable Weekend Energy Tariff", "Select different Modbus registers for Active Energy", - "","", + "Enable HTTP CORS", + "", "","","","", "","", "Enable shutter support", From abc99da9f17bdb4a87b11b73b439e999c11cbc4a Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 28 Oct 2019 21:19:52 +0200 Subject: [PATCH 053/196] TasmotaSlave: Add support for FUNC_EVERY_SECOND --- tasmota/xdrv_31_tasmota_slave.ino | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_31_tasmota_slave.ino b/tasmota/xdrv_31_tasmota_slave.ino index 782ac7514..3c73d61db 100644 --- a/tasmota/xdrv_31_tasmota_slave.ino +++ b/tasmota/xdrv_31_tasmota_slave.ino @@ -43,6 +43,7 @@ #define CMND_FEATURES 0x01 #define CMND_JSON 0x02 +#define CMND_SECOND_TICK 0x03 #define PARAM_DATA_START 0xFE #define PARAM_DATA_END 0xFF @@ -144,8 +145,8 @@ struct TSLAVE { typedef union { uint16_t data; struct { - uint16_t json : 1; - uint16_t spare1 : 1; + uint16_t json : 1; // Slave supports providing a JSON for TELEPERIOD + uint16_t second_tick : 1; // Slave supports receiving a FUNC_EVERY_SECOND callback with no response uint16_t spare2 : 1; uint16_t spare3 : 1; uint16_t spare4 : 1; @@ -378,6 +379,7 @@ void TasmotaSlave_Flash(void) } } TasmotaSlave_exitProgMode(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flash done!")); TSlave.flashing = false; restart_flag = 2; } @@ -485,6 +487,11 @@ bool Xdrv31(uint8_t function) switch (function) { case FUNC_EVERY_SECOND: TasmotaSlave_Init(); + if (TSlave.type) { + if (TSlaveSettings.features.second_tick) { + TasmotaSlave_sendCmnd(CMND_SECOND_TICK, 0); + } + } break; case FUNC_JSON_APPEND: TasmotaSlave_Show(); From f89921712ca201881c57974e6768bcb85df226fa Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 29 Oct 2019 10:50:15 +0100 Subject: [PATCH 054/196] Missing " Added missing ``"`` in line 502 Found with PlatformIO Home 3.0 Beta Project Inspection --- tasmota/language/pt-PT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 46d0bc3a4..44201b135 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -499,7 +499,7 @@ #define D_CALIBRATION "Calibração" //xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Direção do vento +#define D_TX20_WIND_DIRECTION "Direção do vento" #define D_TX20_WIND_SPEED "Velocidade do vento" #define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" #define D_TX20_WIND_SPEED_MAX "Velocidade máxima do vento" From 89c058ee99cc3b2e4c84365536d71240e7e0db0a Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 29 Oct 2019 11:15:30 +0100 Subject: [PATCH 055/196] Added env:tasmota-debug for... PlatformIO Home Project Inspection --- platformio.ini | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/platformio.ini b/platformio.ini index eaf820194..a6e94f13d 100755 --- a/platformio.ini +++ b/platformio.ini @@ -264,6 +264,22 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} +; *** Debug version used for PlatformIO Home Project Inspection +[env:tasmota-debug] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board} +board_build.flash_mode = ${common.board_build.flash_mode} +board_build.f_cpu = ${common.board_build.f_cpu} +build_type = debug +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_resetmethod = ${common.upload_resetmethod} +upload_speed = ${common.upload_speed} +extra_scripts = ${common.extra_scripts} + [env:tasmota-minimal] platform = ${common.platform} framework = ${common.framework} From 8a46e78e4a081cf1e651de3a43b308ef50ff9eeb Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 29 Oct 2019 11:27:04 +0100 Subject: [PATCH 056/196] Removed non-ASCII or non-UTF8 characters --- lib/ArduinoJson-5.13.4/library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ArduinoJson-5.13.4/library.properties b/lib/ArduinoJson-5.13.4/library.properties index 67ccbb95e..0829de12e 100644 --- a/lib/ArduinoJson-5.13.4/library.properties +++ b/lib/ArduinoJson-5.13.4/library.properties @@ -3,7 +3,7 @@ version=5.13.4 author=Benoit Blanchon maintainer=Benoit Blanchon sentence=An efficient and elegant JSON library for Arduino. -paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ fixed allocation, ✔ zero-copy, ✔ streams, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation. +paragraph=ArduinoJson supports serialization, deserialization, fixed allocation, zero-copy, streams, and more. It is the most popular Arduino library on GitHub. Check out arduinojson.org for a comprehensive documentation. category=Data Processing url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties architectures=* From 94fcff6794f348a6e7b37de360adae844c0914c4 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Tue, 29 Oct 2019 10:50:56 +0000 Subject: [PATCH 057/196] TuyaMCU: Change dimmer scale before comparing with dimmer ranges. Fixes #6780 --- tasmota/xdrv_16_tuyamcu.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 608303efc..f2a4c9400 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -377,8 +377,8 @@ void LightSerialDuty(uint16_t duty) { uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { - if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); + if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself if (Tuya.new_dim != duty) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); TuyaSendValue(dpid, duty); From ae216b99292e03b776655cb51b86b818ea4aee25 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 29 Oct 2019 09:59:56 -0300 Subject: [PATCH 058/196] PT-BR language update --- tasmota/language/pt-BR.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 30cab1498..d1287efd7 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -28,10 +28,10 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v5.14.0b + * Updated until v7.0.0.1 \*********************************************************************/ -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) #define LANGUAGE_LCID 1046 // HTML (ISO 639-1) Language Code From 52959c042b2b2f9790168c9b8f5d8b84a05e81f9 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 29 Oct 2019 10:01:30 -0300 Subject: [PATCH 059/196] PT-PT language update --- tasmota/language/pt-PT.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 44201b135..eba4fbb0d 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -28,10 +28,10 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v5.12.0 + * Updated until v7.0.0.1 \*********************************************************************/ -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) #define LANGUAGE_LCID 2070 // HTML (ISO 639-1) Language Code From 562a564ff978c66122ce0785c06818f6dc7de478 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Wed, 30 Oct 2019 09:20:55 +0100 Subject: [PATCH 060/196] Added motordelay to enhance calibration Some electronic shutters have up to 1sec before the motor starts. this can cause calibration issues --- tasmota/xdrv_27_shutter.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index f7ba5c911..d15a0f344 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -36,7 +36,7 @@ #define D_CMND_SHUTTER_SETCLOSE "SetClose" #define D_CMND_SHUTTER_INVERT "Invert" #define D_CMND_SHUTTER_CLIBRATION "Calibration" - +#define D_CMND_SHUTTER_MOTORDELAY "MotorDelay" #define D_SHUTTER "SHUTTER" const uint16_t MOTOR_STOP_TIME = 500; // in mS @@ -49,12 +49,13 @@ enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_O 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_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" + D_CMND_SHUTTER_MOTORDELAY; void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition, &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, - &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration }; + &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration ,CmndShutterMotorDelay}; const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"direction\":%d}"; From c67de901f1d6c24c5a17bc961153dfe5c9e97bcb Mon Sep 17 00:00:00 2001 From: stefanbode Date: Wed, 30 Oct 2019 09:28:46 +0100 Subject: [PATCH 061/196] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index d15a0f344..83aac40ae 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -37,6 +37,7 @@ #define D_CMND_SHUTTER_INVERT "Invert" #define D_CMND_SHUTTER_CLIBRATION "Calibration" #define D_CMND_SHUTTER_MOTORDELAY "MotorDelay" + #define D_SHUTTER "SHUTTER" const uint16_t MOTOR_STOP_TIME = 500; // in mS @@ -55,7 +56,7 @@ const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition, &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, - &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration ,CmndShutterMotorDelay}; + &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay}; const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"direction\":%d}"; @@ -78,6 +79,7 @@ struct SHUTTER { uint16_t operations[MAX_SHUTTERS]; int8_t direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE + uint8_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec. } Shutter; void ShutterRtc50mS(void) @@ -212,15 +214,16 @@ 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.motordelay[i] = Settings.shutter_motordelay[i]; char shutter_open_chr[10]; 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], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %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], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d,motordelay %d"), i, 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.mask, Settings.shutter_invert[i], Shutter.mode, Shutter.motordelay[i]); } else { // terminate loop at first INVALID shutter. @@ -238,7 +241,7 @@ void ShutterUpdatePosition(void) for (uint32_t i = 0; i < shutters_present; i++) { if (Shutter.direction[i] != 0) { //char stemp1[20]; - Shutter.real_position[i] = Shutter.start_position[i] + ( Shutter.time[i] * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); + Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); // avoid real position leaving the boundaries. Shutter.real_position[i] = Shutter.real_position[i] < 0 ? 0 : (Shutter.real_position[i] > Shutter.open_max[i] ? Shutter.open_max[i] : Shutter.real_position[i]) ; @@ -534,6 +537,19 @@ void CmndShutterCloseTime(void) } } +void CmndShutterMotorDelay(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(20 * CharToFloat(XdrvMailbox.data)); + ShutterInit(); + } + char time_chr[10]; + dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / 20, 1, time_chr); + ResponseCmndIdxChar(time_chr); + } +} + void CmndShutterRelay(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { @@ -596,8 +612,9 @@ void CmndShutterCalibration(void) // ???? // 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 0-255. - if ((field < 0) || (field > 255)) { + // The fields in a version string can only range from 1-255. + // and following value must be higher than previous one + if ((field <= 0) || (field > 255) || ( (i>0) && (field <= messwerte[i-1]) ) ) { free(version_dup); break; } @@ -605,7 +622,7 @@ void CmndShutterCalibration(void) // ???? } for (i=0 ; i < 5 ; i++) { Settings.shuttercoeff[i][XdrvMailbox.index-1] = 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]); + 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); From fecf323678bcaf3436cccca30ed6cb7821172868 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Wed, 30 Oct 2019 09:32:06 +0100 Subject: [PATCH 062/196] Update settings.h --- tasmota/settings.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 96bd2e6df..efcdadcaa 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -388,8 +388,8 @@ struct SYSCFG { uint16_t dimmer_hw_max; // E92 uint32_t deepsleep; // E94 uint16_t energy_power_delta; // E98 - - uint8_t free_e9a[350]; // E9A + uint8_t shutter_motordelay[MAX_SHUTTERS]; // E9A + uint8_t free_e9e[346]; // E9E uint32_t cfg_timestamp; // FF8 uint32_t cfg_crc32; // FFC From 3cd8bc2545145bbe07eddbffa214a7f57c309eb3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Oct 2019 10:14:16 +0100 Subject: [PATCH 063/196] Add SSD1306 64x48 pixel support Add SSD1306 64x48 pixel support (#6740) --- lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp | 7 +++++++ tasmota/xdsp_02_ssd1306.ino | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp index 9015c6e83..9827f7584 100644 --- a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp +++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp @@ -563,6 +563,13 @@ boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset, SSD1306_SETCONTRAST }; // 0x81 ssd1306_commandList(init4c, sizeof(init4c)); ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0xAF); + } else if((WIDTH == 64) && (HEIGHT == 48)) { + static const uint8_t PROGMEM init4d[] = { + SSD1306_SETCOMPINS, // 0xDA + 0x12, + SSD1306_SETCONTRAST }; // 0x81 + ssd1306_commandList(init4d, sizeof(init4d)); + ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF); } else { // Other screen varieties -- TBD } diff --git a/tasmota/xdsp_02_ssd1306.ino b/tasmota/xdsp_02_ssd1306.ino index 4b49c2329..060d54fa1 100644 --- a/tasmota/xdsp_02_ssd1306.ino +++ b/tasmota/xdsp_02_ssd1306.ino @@ -61,10 +61,10 @@ void SSD1306InitDriver() if (XDSP_02 == Settings.display_model) { - if ((Settings.display_width != 96) && (Settings.display_width != 128)) { + if ((Settings.display_width != 64) && (Settings.display_width != 96) && (Settings.display_width != 128)) { Settings.display_width = 128; } - if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 64)) { + if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 48) && (Settings.display_height != 64)) { Settings.display_height = 64; } From 9dfdd3e15d9179d0c05178695564d59c6845beee Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Oct 2019 10:57:14 +0100 Subject: [PATCH 064/196] Clean up pre 6.0 settings code --- tasmota/settings.ino | 80 ++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 48 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 31ece2364..d29ea206a 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -814,13 +814,41 @@ void SettingsDefaultSet2(void) // Settings.light_wakeup = 0; Settings.light_pixels = WS2812_LEDS; // Settings.light_rotation = 0; - SettingsDefaultSet_5_8_1(); // Clock color + Settings.ws_width[WS_SECOND] = 1; + Settings.ws_color[WS_SECOND][WS_RED] = 255; +// Settings.ws_color[WS_SECOND][WS_GREEN] = 0; + Settings.ws_color[WS_SECOND][WS_BLUE] = 255; + Settings.ws_width[WS_MINUTE] = 3; +// Settings.ws_color[WS_MINUTE][WS_RED] = 0; + Settings.ws_color[WS_MINUTE][WS_GREEN] = 255; +// Settings.ws_color[WS_MINUTE][WS_BLUE] = 0; + Settings.ws_width[WS_HOUR] = 5; + Settings.ws_color[WS_HOUR][WS_RED] = 255; +// Settings.ws_color[WS_HOUR][WS_GREEN] = 0; +// Settings.ws_color[WS_HOUR][WS_BLUE] = 0; Settings.dimmer_hw_max = DEFAULT_DIMMER_MAX; Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; // Display - SettingsDefaultSet_5_10_1(); // Display settings +// Settings.display_model = 0; + Settings.display_mode = 1; + Settings.display_refresh = 2; + Settings.display_rows = 2; + Settings.display_cols[0] = 16; + Settings.display_cols[1] = 8; + Settings.display_dimmer = 1; + Settings.display_size = 1; + Settings.display_font = 1; +// Settings.display_rotate = 0; + Settings.display_address[0] = MTX_ADDRESS1; + Settings.display_address[1] = MTX_ADDRESS2; + Settings.display_address[2] = MTX_ADDRESS3; + Settings.display_address[3] = MTX_ADDRESS4; + Settings.display_address[4] = MTX_ADDRESS5; + Settings.display_address[5] = MTX_ADDRESS6; + Settings.display_address[6] = MTX_ADDRESS7; + Settings.display_address[7] = MTX_ADDRESS8; // Time if (((APP_TIMEZONE > -14) && (APP_TIMEZONE < 15)) || (99 == APP_TIMEZONE)) { @@ -842,7 +870,8 @@ void SettingsDefaultSet2(void) } Settings.latitude = (int)((double)LATITUDE * 1000000); Settings.longitude = (int)((double)LONGITUDE * 1000000); - SettingsDefaultSet_5_13_1c(); // Time STD/DST settings + SettingsResetStd(); + SettingsResetDst(); Settings.button_debounce = KEY_DEBOUNCE_TIME; Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; @@ -860,45 +889,6 @@ void SettingsDefaultSet2(void) /********************************************************************************************/ -void SettingsDefaultSet_5_8_1(void) -{ -// Settings.flag.ws_clock_reverse = 0; - Settings.ws_width[WS_SECOND] = 1; - Settings.ws_color[WS_SECOND][WS_RED] = 255; - Settings.ws_color[WS_SECOND][WS_GREEN] = 0; - Settings.ws_color[WS_SECOND][WS_BLUE] = 255; - Settings.ws_width[WS_MINUTE] = 3; - Settings.ws_color[WS_MINUTE][WS_RED] = 0; - Settings.ws_color[WS_MINUTE][WS_GREEN] = 255; - Settings.ws_color[WS_MINUTE][WS_BLUE] = 0; - Settings.ws_width[WS_HOUR] = 5; - Settings.ws_color[WS_HOUR][WS_RED] = 255; - Settings.ws_color[WS_HOUR][WS_GREEN] = 0; - Settings.ws_color[WS_HOUR][WS_BLUE] = 0; -} - -void SettingsDefaultSet_5_10_1(void) -{ - Settings.display_model = 0; - Settings.display_mode = 1; - Settings.display_refresh = 2; - Settings.display_rows = 2; - Settings.display_cols[0] = 16; - Settings.display_cols[1] = 8; - Settings.display_dimmer = 1; - Settings.display_size = 1; - Settings.display_font = 1; - Settings.display_rotate = 0; - Settings.display_address[0] = MTX_ADDRESS1; - Settings.display_address[1] = MTX_ADDRESS2; - Settings.display_address[2] = MTX_ADDRESS3; - Settings.display_address[3] = MTX_ADDRESS4; - Settings.display_address[4] = MTX_ADDRESS5; - Settings.display_address[5] = MTX_ADDRESS6; - Settings.display_address[6] = MTX_ADDRESS7; - Settings.display_address[7] = MTX_ADDRESS8; -} - void SettingsResetStd(void) { Settings.tflag[0].hemis = TIME_STD_HEMISPHERE; @@ -919,12 +909,6 @@ void SettingsResetDst(void) Settings.toffset[1] = TIME_DST_OFFSET; } -void SettingsDefaultSet_5_13_1c(void) -{ - SettingsResetStd(); - SettingsResetDst(); -} - void SettingsDefaultWebColor(void) { char scolor[10]; From 6fc9dccfe83158f5900c0ec68a2e1e060cd79538 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Oct 2019 14:08:43 +0100 Subject: [PATCH 065/196] Some CppCheck optimizations --- tasmota/settings.ino | 4 +--- tasmota/support.ino | 10 ++++------ tasmota/support_button.ino | 6 ++---- tasmota/support_command.ino | 5 ++--- tasmota/support_float.ino | 3 +-- tasmota/support_rtc.ino | 3 --- tasmota/support_switch.ino | 6 ++---- 7 files changed, 12 insertions(+), 25 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index d29ea206a..c05935208 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -522,8 +522,6 @@ void SettingsErase(uint8_t type) */ #ifndef FIRMWARE_MINIMAL - bool result; - uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; if (1 == type) { @@ -540,7 +538,7 @@ void SettingsErase(uint8_t type) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " %d " D_UNIT_SECTORS), _sectorEnd - _sectorStart); for (uint32_t _sector = _sectorStart; _sector < _sectorEnd; _sector++) { - result = ESP.flashEraseSector(_sector); + bool result = ESP.flashEraseSector(_sector); if (_serialoutput) { Serial.print(F(D_LOG_APPLICATION D_ERASED_SECTOR " ")); Serial.print(_sector); diff --git a/tasmota/support.ino b/tasmota/support.ino index 6588f523e..a2895e9a1 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -74,8 +74,8 @@ void OsWatchLoop(void) String GetResetReason(void) { - char buff[32]; if (oswatch_blocked_loop) { + char buff[32]; strncpy_P(buff, PSTR(D_JSON_BLOCKED_LOOP), sizeof(buff)); return String(buff); } else { @@ -288,12 +288,11 @@ char* ulltoa(unsigned long long value, char *str, int radix) char digits[64]; char *dst = str; int i = 0; - int n = 0; // if (radix < 2 || radix > 36) { radix = 10; } do { - n = value % radix; + int n = value % radix; digits[i++] = (n < 10) ? (char)n+'0' : (char)n-10+'A'; value /= radix; } while (value != 0); @@ -599,10 +598,9 @@ bool NewerVersion(char* version_str) char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option) { - char sidx[8]; - strncpy_P(dest, S_RSLT_POWER, size); // POWER if ((devices_present + option) > 1) { + char sidx[8]; snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); // x strncat(dest, sidx, size - strlen(dest) -1); // POWERx } @@ -1545,7 +1543,6 @@ void GetLog(uint32_t idx, char** entry_pp, size_t* len_p) void Syslog(void) { // Destroys log_data - char syslog_preamble[64]; // Hostname + Id uint32_t current_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); if (syslog_host_hash != current_hash) { @@ -1553,6 +1550,7 @@ void Syslog(void) WiFi.hostByName(Settings.syslog_host, syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash } if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { + char syslog_preamble[64]; // Hostname + Id snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), my_hostname); memmove(log_data + strlen(syslog_preamble), log_data, sizeof(log_data) - strlen(syslog_preamble)); log_data[sizeof(log_data) -1] = '\0'; diff --git a/tasmota/support_button.ino b/tasmota/support_button.ino index d4a269017..d1367eca7 100644 --- a/tasmota/support_button.ino +++ b/tasmota/support_button.ino @@ -109,8 +109,6 @@ void ButtonHandler(void) { if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit - uint8_t button = NOT_PRESSED; - uint8_t button_present = 0; uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; // Extent hold time factor in case of iminnent Reset command uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50) char scmnd[20]; @@ -118,8 +116,8 @@ void ButtonHandler(void) // uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present; // for (uint32_t button_index = 0; button_index < maxdev; button_index++) { for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { - button = NOT_PRESSED; - button_present = 0; + uint8_t button = NOT_PRESSED; + uint8_t button_present = 0; if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { button_present = 1; diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 3915e9ea7..3b657c375 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -148,11 +148,11 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) char *type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) - uint32_t i = 0; uint32_t index = 1; bool user_index = false; if (type != nullptr) { type++; + uint32_t i; for (i = 0; i < strlen(type); i++) { type[i] = toupper(type[i]); } @@ -902,11 +902,10 @@ void CmndGpios(void) { myio cmodule; ModuleGpios(&cmodule); - uint32_t midx; uint32_t lines = 1; bool jsflg = false; for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { - midx = pgm_read_byte(kGpioNiceList + i); + uint32_t midx = pgm_read_byte(kGpioNiceList + i); if ((XdrvMailbox.payload != 255) && GetUsedInModule(midx, cmodule.io)) { continue; } if (!jsflg) { Response_P(PSTR("{\"" D_CMND_GPIOS "%d\":{"), lines); diff --git a/tasmota/support_float.ino b/tasmota/support_float.ino index 9ad556354..e6e788f3a 100644 --- a/tasmota/support_float.ino +++ b/tasmota/support_float.ino @@ -124,10 +124,9 @@ double TaylorLog(double x) double step = ((x - 1) * (x - 1)) / ((x + 1) * (x + 1)); // Store step to not have to calculate it each time double totalValue = 0; double powe = 1; - double y; for (uint32_t count = 0; count < 10; count++) { // Experimental number of 10 iterations z *= step; - y = (1 / powe) * z; + double y = (1 / powe) * z; totalValue = totalValue + y; powe = powe + 2; } diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index 94ea9bebe..62f2581c8 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -283,9 +283,6 @@ void BreakTime(uint32_t time_input, TIME_T &tm) time -= days; // now it is days in this year, starting at 0 tm.day_of_year = time; - days = 0; - month = 0; - month_length = 0; for (month = 0; month < 12; month++) { if (1 == month) { // february if (LEAP_YEAR(year)) { diff --git a/tasmota/support_switch.ino b/tasmota/support_switch.ino index 5415c1210..af085468a 100644 --- a/tasmota/support_switch.ino +++ b/tasmota/support_switch.ino @@ -133,8 +133,6 @@ void SwitchHandler(uint8_t mode) { if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit - uint8_t button = NOT_PRESSED; - uint8_t switchflag; uint16_t loops_per_second = 1000 / Settings.switch_debounce; for (uint32_t i = 0; i < MAX_SWITCHES; i++) { @@ -147,12 +145,12 @@ void SwitchHandler(uint8_t mode) } } - button = Switch.virtual_state[i]; + uint8_t button = Switch.virtual_state[i]; // enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION}; if (button != Switch.last_state[i]) { - switchflag = POWER_TOGGLE +1; + uint8_t switchflag = POWER_TOGGLE +1; switch (Settings.switchmode[i]) { case TOGGLE: switchflag = POWER_TOGGLE; // Toggle From 8ca843f9ab3668eee6470d96e8f516bc006a09fb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Oct 2019 16:06:53 +0100 Subject: [PATCH 066/196] Add frequency to ADE7953 energy monitor Add frequency to ADE7953 energy monitor as used in Shelly 2.5 by ljakob (#6778) --- tasmota/_changelog.ino | 1 + tasmota/xdrv_03_energy.ino | 6 ++--- tasmota/xnrg_07_ade7953.ino | 46 ++++++++++++++++++++++--------------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index dce497fdf..a18d6d4bf 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -3,6 +3,7 @@ * Remove references to versions before 6.x * Change default GUI to dark theme * Add command SetOption73 0/1 to re-enable HTTP Cross-Origin Resource Sharing (CORS) now default disabled (#6767) + * Add frequency to ADE7953 energy monitor as used in Shelly 2.5 by ljakob (#6778) * * 6.7.1.1 20191026 * Change ArduinoSlave to TasmotaSlave (Experimental) diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index 13bb8948a..e68b8215e 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -95,7 +95,7 @@ struct ENERGY { uint8_t data_valid[3] = { 0, 0, 0 }; uint8_t phase_count = 1; // Number of phases active - bool voltage_common = false; // Use single voltage + bool voltage_common = false; // Use single voltage and frequency bool voltage_available = true; // Enable if voltage is measured bool current_available = true; // Enable if current is measured @@ -1014,7 +1014,7 @@ void EnergyShow(bool json) } if (!isnan(Energy.frequency[0])) { ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), - EnergyFormat(value_chr, frequency_chr[0], json)); + EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); } } if (Energy.voltage_available) { @@ -1084,7 +1084,7 @@ void EnergyShow(bool json) } if (!isnan(Energy.frequency[0])) { WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), - EnergyFormat(value_chr, frequency_chr[0], json)); + EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); } } WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr[0]); diff --git a/tasmota/xnrg_07_ade7953.ino b/tasmota/xnrg_07_ade7953.ino index 5f789e3c8..fd11da99e 100644 --- a/tasmota/xnrg_07_ade7953.ino +++ b/tasmota/xnrg_07_ade7953.ino @@ -36,20 +36,22 @@ #define ADE7953_ADDR 0x38 -const uint8_t Ade7953Registers[] { - 0x1B, // RMS current channel B (Relay 1) - 0x13, // Active power channel B - 0x11, // Apparent power channel B - 0x15, // Reactive power channel B - 0x1A, // RMS current channel A (Relay 2) - 0x12, // Active power channel A - 0x10, // Apparent power channel A - 0x14, // Reactive power channel A - 0x1C // RMS voltage (Both relays) +const uint16_t Ade7953Registers[] { + 0x31B, // RMS current channel B (Relay 1) + 0x313, // Active power channel B + 0x311, // Apparent power channel B + 0x315, // Reactive power channel B + 0x31A, // RMS current channel A (Relay 2) + 0x312, // Active power channel A + 0x310, // Apparent power channel A + 0x314, // Reactive power channel A + 0x31C, // RMS voltage (Both relays) + 0x10E // 16-bit unsigned period register }; struct Ade7953 { uint32_t voltage_rms = 0; + uint32_t period = 0; uint32_t current_rms[2] = { 0, 0 }; uint32_t active_power[2] = { 0, 0 }; uint8_t init_step = 0; @@ -118,17 +120,20 @@ void Ade7953Init(void) void Ade7953GetData(void) { int32_t reg[2][4]; - for (uint32_t i = 0; i < sizeof(Ade7953Registers); i++) { - int32_t value = Ade7953Read(0x300 + Ade7953Registers[i]); + for (uint32_t i = 0; i < sizeof(Ade7953Registers)/sizeof(uint16_t); i++) { + int32_t value = Ade7953Read(Ade7953Registers[i]); if (8 == i) { Ade7953.voltage_rms = value; // RMS voltage (Both relays) + } else if (9 == i) { + Ade7953.period = value; // period } else { reg[i >> 2][i &3] = value; } } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: %d, [%d, %d, %d, %d], [%d, %d, %d, %d]"), - Ade7953.voltage_rms, reg[0][0], reg[0][1], reg[0][2], reg[0][3], - reg[1][0], reg[1][1], reg[1][2], reg[1][3]); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: %d, %d, [%d, %d, %d, %d], [%d, %d, %d, %d]"), + Ade7953.voltage_rms, Ade7953.period, + reg[0][0], reg[0][1], reg[0][2], reg[0][3], + reg[1][0], reg[1][1], reg[1][2], reg[1][3]); uint32_t apparent_power[2] = { 0, 0 }; uint32_t reactive_power[2] = { 0, 0 }; @@ -148,11 +153,14 @@ void Ade7953GetData(void) uint32_t current_rms_sum = Ade7953.current_rms[0] + Ade7953.current_rms[1]; uint32_t active_power_sum = Ade7953.active_power[0] + Ade7953.active_power[1]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ADE: U %d, I %d + %d = %d, P %d + %d = %d"), - Ade7953.voltage_rms, Ade7953.current_rms[0], Ade7953.current_rms[1], current_rms_sum, Ade7953.active_power[0], Ade7953.active_power[1], active_power_sum); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ADE: U %d, C %d, I %d + %d = %d, P %d + %d = %d"), + Ade7953.voltage_rms, Ade7953.period, + Ade7953.current_rms[0], Ade7953.current_rms[1], current_rms_sum, + Ade7953.active_power[0], Ade7953.active_power[1], active_power_sum); if (Energy.power_on) { // Powered on Energy.voltage[0] = (float)Ade7953.voltage_rms / Settings.energy_voltage_calibration; + Energy.frequency[0] = 223750.0f / ( (float)Ade7953.period + 1); for (uint32_t channel = 0; channel < 2; channel++) { Energy.data_valid[channel] = 0; @@ -202,7 +210,7 @@ void Ade7953DrvInit(void) Ade7953.init_step = 2; Energy.phase_count = 2; // Handle two channels as two phases - Energy.voltage_common = true; // Use common voltage + Energy.voltage_common = true; // Use common voltage and frequency energy_flg = XNRG_07; } @@ -278,4 +286,4 @@ bool Xnrg07(uint8_t function) #endif // USE_ADE7953 #endif // USE_ENERGY_SENSOR -#endif // USE_I2C +#endif // USE_I2C \ No newline at end of file From aaa420e52becf0aaaed91efc2f47a25e19a6a578 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Oct 2019 16:51:13 +0100 Subject: [PATCH 067/196] Prep for core AUTOFLASHSIZE --- tasmota/settings.ino | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index c05935208..311d3108e 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -256,11 +256,22 @@ const uint32_t SPIFFS_END = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SE #else // Core > 2.5.2 and STAGE +#if AUTOFLASHSIZE + +#include "flash_hal.h" + +// From libraries/EEPROM/EEPROM.cpp EEPROMClass +const uint32_t SPIFFS_END = (FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; + +#else + extern "C" uint32_t _FS_end; // From libraries/EEPROM/EEPROM.cpp EEPROMClass const uint32_t SPIFFS_END = ((uint32_t)&_FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; -#endif +#endif // AUTOFLASHSIZE + +#endif // All cores < pre-2.6.0 // Version 4.2 config = eeprom area const uint32_t SETTINGS_LOCATION = SPIFFS_END; // No need for SPIFFS as it uses EEPROM area From 9d6be8166b4d88a602bc4c2a26a0cd5a90c14f7e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Oct 2019 17:28:25 +0100 Subject: [PATCH 068/196] CppCheck optimization --- tasmota/settings.ino | 2 -- 1 file changed, 2 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 311d3108e..87fb7c845 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1030,7 +1030,6 @@ void SettingsDelta(void) Settings.baudrate = Settings.ex_baudrate * 4; Settings.sbaudrate = Settings.ex_sbaudrate * 4; } - if (Settings.version < 0x0606000A) { uint8_t tuyaindex = 0; if (Settings.param[P_BACKLOG_DELAY] > 0) { // ex SetOption34 @@ -1062,7 +1061,6 @@ void SettingsDelta(void) if (Settings.param[P_ex_TUYA_CURRENT_ID] > 0) { // ex SetOption45 Settings.tuya_fnid_map[tuyaindex].fnid = 32; // TUYA_MCU_FUNC_CURRENT - Move Tuya Current Id to Map Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_CURRENT_ID]; - tuyaindex++; } } if (Settings.version < 0x0606000C) { From 393f56827696297da734b01ffd37439c3306467c Mon Sep 17 00:00:00 2001 From: Bohdan Kmit Date: Wed, 30 Oct 2019 21:58:38 +0200 Subject: [PATCH 069/196] Add Setoption74 to runtime configuration of internal pullup resistor usage for single DS18x20 sensor --- tasmota/settings.h | 2 +- tasmota/xsns_05_ds18x20.ino | 18 +++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index efcdadcaa..c64820103 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -87,7 +87,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t dds2382_model : 1; // bit 21 (v6.6.0.14) - SetOption71 - Select different Modbus registers for Active Energy (#6531) uint32_t hardware_energy_total : 1; // bit 22 (v6.6.0.15) - SetOption72 - Enable / Disable hardware energy total counter as reference (#6561) uint32_t cors_enabled : 1; // bit 23 (v7.0.0.1) - SetOption73 - Enable HTTP CORS - uint32_t spare24 : 1; + uint32_t ds18x20_internal_pullup : 1; // bit 24 (v7.0.0.1) - SetOption74 - Enable internal pullup for single DS18x20 sensor uint32_t spare25 : 1; uint32_t spare26 : 1; uint32_t spare27 : 1; diff --git a/tasmota/xsns_05_ds18x20.ino b/tasmota/xsns_05_ds18x20.ino index ca052c2f2..bb3362042 100644 --- a/tasmota/xsns_05_ds18x20.ino +++ b/tasmota/xsns_05_ds18x20.ino @@ -74,11 +74,7 @@ uint8_t OneWireReset(void) uint8_t retries = 125; //noInterrupts(); -#ifdef DS18B20_INTERNAL_PULLUP - pinMode(ds18x20_pin, INPUT_PULLUP); -#else - pinMode(ds18x20_pin, INPUT); -#endif + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); do { if (--retries == 0) { return 0; @@ -88,11 +84,7 @@ uint8_t OneWireReset(void) pinMode(ds18x20_pin, OUTPUT); digitalWrite(ds18x20_pin, LOW); delayMicroseconds(480); -#ifdef DS18B20_INTERNAL_PULLUP - pinMode(ds18x20_pin, INPUT_PULLUP); -#else - pinMode(ds18x20_pin, INPUT); -#endif + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); delayMicroseconds(70); uint8_t r = !digitalRead(ds18x20_pin); //interrupts(); @@ -121,11 +113,7 @@ uint8_t OneWireReadBit(void) pinMode(ds18x20_pin, OUTPUT); digitalWrite(ds18x20_pin, LOW); delayMicroseconds(3); -#ifdef DS18B20_INTERNAL_PULLUP - pinMode(ds18x20_pin, INPUT_PULLUP); -#else - pinMode(ds18x20_pin, INPUT); -#endif + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); delayMicroseconds(10); uint8_t r = digitalRead(ds18x20_pin); //interrupts(); From dccf6fb7cd324128d1f79b23ce5289b1b627f40f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Oct 2019 22:22:18 +0100 Subject: [PATCH 070/196] Add command SetOption74 0/1 Add command SetOption74 0/1 to enable DS18x20 internal pull-up and remove define DS18B20_INTERNAL_PULLUP (#6795) --- tasmota/_changelog.ino | 1 + tasmota/my_user_config.h | 1 - tools/decode-status.py | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index a18d6d4bf..76b314a72 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -4,6 +4,7 @@ * Change default GUI to dark theme * Add command SetOption73 0/1 to re-enable HTTP Cross-Origin Resource Sharing (CORS) now default disabled (#6767) * Add frequency to ADE7953 energy monitor as used in Shelly 2.5 by ljakob (#6778) + * Add command SetOption74 0/1 to enable DS18x20 internal pull-up and remove define DS18B20_INTERNAL_PULLUP (#6795) * * 6.7.1.1 20191026 * Change ArduinoSlave to TasmotaSlave (Experimental) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index e159bdbe9..33f00ca4f 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -353,7 +353,6 @@ // -- One wire sensors ---------------------------- #define USE_DS18x20 // Add support for DS18x20 sensors with id sort, single scan and read retry (+2k6 code) // #define W1_PARASITE_POWER // Optimize for parasite powered sensors -// #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistor // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) diff --git a/tools/decode-status.py b/tools/decode-status.py index f360de701..b50d920db 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -126,7 +126,7 @@ a_setoption = [[ "Enable Weekend Energy Tariff", "Select different Modbus registers for Active Energy", "Enable HTTP CORS", - "", + "Enable internal pullup for single DS18x20 sensor", "","","","", "","", "Enable shutter support", From d36d38adeaf6f7d1f21216368e9d1a6a3d1486ed Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 31 Oct 2019 10:41:50 +0100 Subject: [PATCH 071/196] Add hide Alexa objects with friendlyname starting with '$' --- tasmota/_changelog.ino | 1 + tasmota/xdrv_20_hue.ino | 44 ++++++++++++++++++++++++++--------------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 76b314a72..8d6245a1e 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -5,6 +5,7 @@ * Add command SetOption73 0/1 to re-enable HTTP Cross-Origin Resource Sharing (CORS) now default disabled (#6767) * Add frequency to ADE7953 energy monitor as used in Shelly 2.5 by ljakob (#6778) * Add command SetOption74 0/1 to enable DS18x20 internal pull-up and remove define DS18B20_INTERNAL_PULLUP (#6795) + * Add hide Alexa objects with friendlyname starting with '$' (#6722, #6762) * * 6.7.1.1 20191026 * Change ArduinoSlave to TasmotaSlave (Experimental) diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 9289822fc..3b439ea2f 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -361,6 +361,13 @@ void HueLightStatus1(uint8_t device, String *response) response->replace("{light_status}", light_status); } +// Check whether this device should be reported to Alexa or considered hidden. +// Any device whose friendly name start with "$" is considered hidden +bool HueActive(uint8_t device) { + if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; } + return '$' != Settings.friendlyname[device-1][0]; +} + void HueLightStatus2(uint8_t device, String *response) { *response += FPSTR(HUE_LIGHTS_STATUS_JSON2); @@ -442,20 +449,22 @@ uint32_t findEchoGeneration(void) { return gen; } -void HueGlobalConfig(String *path) -{ +void HueGlobalConfig(String *path) { String response; uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; path->remove(0,1); // cut leading / to get - response = F("{\"lights\":{\""); + response = F("{\"lights\":{"); + bool appending = false; // do we need to add a comma to append for (uint32_t i = 1; i <= maxhue; i++) { - response += EncodeLightId(i); - response += F("\":{\"state\":"); - HueLightStatus1(i, &response); - HueLightStatus2(i, &response); - if (i < maxhue) { - response += ",\""; + if (HueActive(i)) { + if (appending) { response += ","; } + response += "\""; + response += EncodeLightId(i); + response += F("\":{\"state\":"); + HueLightStatus1(i, &response); + HueLightStatus2(i, &response); + appending = true; } } response += F("},\"groups\":{},\"schedules\":{},\"config\":"); @@ -493,14 +502,17 @@ void HueLights(String *path) path->remove(0,path->indexOf("/lights")); // Remove until /lights if (path->endsWith("/lights")) { // Got /lights - response = "{\""; + response = "{"; + bool appending = false; for (uint32_t i = 1; i <= maxhue; i++) { - response += EncodeLightId(i); - response += F("\":{\"state\":"); - HueLightStatus1(i, &response); - HueLightStatus2(i, &response); - if (i < maxhue) { - response += ",\""; + if (HueActive(i)) { + if (appending) { response += ","; } + response += "\""; + response += EncodeLightId(i); + response += F("\":{\"state\":"); + HueLightStatus1(i, &response); + HueLightStatus2(i, &response); + appending = true; } } #ifdef USE_SCRIPT_HUE From a8d0d8a67febdd558ec43a94b06d6e55c6865cc0 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 31 Oct 2019 11:12:00 +0100 Subject: [PATCH 072/196] Fix better control of RGB/White when SetOption37 >128, added Dimmer1 and Dimmer2 commands --- tasmota/_changelog.ino | 1 + tasmota/support_command.ino | 3 + tasmota/xdrv_04_light.ino | 164 ++++++++++++++++++++++++++++++------ 3 files changed, 141 insertions(+), 27 deletions(-) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 76b314a72..ec19b471a 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -5,6 +5,7 @@ * Add command SetOption73 0/1 to re-enable HTTP Cross-Origin Resource Sharing (CORS) now default disabled (#6767) * Add frequency to ADE7953 energy monitor as used in Shelly 2.5 by ljakob (#6778) * Add command SetOption74 0/1 to enable DS18x20 internal pull-up and remove define DS18B20_INTERNAL_PULLUP (#6795) + * Fix better control of RGB/White when SetOption37 >128, added Dimmer1 and Dimmer2 commands (#6714) * * 6.7.1.1 20191026 * Change ArduinoSlave to TasmotaSlave (Experimental) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 3b657c375..d17307264 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -699,6 +699,9 @@ void CmndSetoption(void) param_low = 1; param_high = 250; break; + case P_RGB_REMAP: + restart_flag = 2; // SetOption37 needs a reboot in most cases + break; } if ((XdrvMailbox.payload >= param_low) && (XdrvMailbox.payload <= param_high)) { Settings.param[pindex] = XdrvMailbox.payload; diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 67359634e..f4fb6dbab 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -455,8 +455,20 @@ class LightStateClass { return dimmer; } - uint8_t getDimmer() { - return BriToDimmer(getBri()); + uint8_t getDimmer(uint32_t mode = 0) { + uint8_t bri; + switch (mode) { + case 1: + bri = getBriRGB(); + break; + case 2: + bri = getBriCT(); + break; + default: + bri = getBri(); + break; + } + return BriToDimmer(bri); } inline uint16_t getCT() { @@ -893,9 +905,19 @@ public: //debugLogs(); } - void changeDimmer(uint8_t dimmer) { + void changeDimmer(uint8_t dimmer, uint32_t mode = 0) { uint8_t bri = changeUIntScale(dimmer, 0, 100, 0, 255); - changeBri(bri); + switch (mode) { + case 1: + changeBriRGB(bri); + break; + case 2: + changeBriCT(bri); + break; + default: + changeBri(bri); + break; + } } void changeBri(uint8_t bri) { @@ -904,6 +926,18 @@ public: calcLevels(); } + void changeBriRGB(uint8_t bri) { + _state->setBriRGB(bri); + saveSettings(); + calcLevels(); + } + + void changeBriCT(uint8_t bri) { + _state->setBriCT(bri); + saveSettings(); + calcLevels(); + } + void changeRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { _state->setRGB(r, g, b, keep_bri); if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } // try to force RGB @@ -971,7 +1005,7 @@ public: } else { uint8_t cm = _state->getColorMode(); - memset(&Settings.light_color[0], 0, sizeof(Settings.light_color)); + memset(&Settings.light_color[0], 0, sizeof(Settings.light_color)); // clear all channels if (LCM_RGB & cm) { // can be either LCM_RGB or LCM_BOTH _state->getRGB(&Settings.light_color[0], &Settings.light_color[1], &Settings.light_color[2]); Settings.light_dimmer = _state->BriToDimmer(_state->getBriRGB()); @@ -1097,6 +1131,9 @@ bool LightModuleInit(void) uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); if (0 == pwm_channels) { pwm_channels = 1; } devices_present += pwm_channels - 1; // add the pwm channels controls at the end + } else if ((Settings.param[P_RGB_REMAP] & 128) && (LST_RGBW <= (light_type & 7))) { + // if RGBW or RGBCW, and SetOption37 >= 128, we manage RGB and W separately, hence adding a device + devices_present++; } return (light_type > LT_BASIC); @@ -1108,10 +1145,20 @@ void LightInit(void) Light.subtype = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); // Always 0 - LST_MAX (5) Light.pwm_multi_channels = Settings.flag3.pwm_multi_channels; + if (LST_RGBW <= Light.subtype) { + // only change if RGBW or RGBCW + // do not allow independant RGB and WC colors + bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); + light_controller.setCTRGBLinked(ct_rgb_linked); + } + if ((LST_SINGLE < Light.subtype) && Light.pwm_multi_channels) { // we treat each PWM channel as an independant one, hence we switch to light_controller.setPWMMultiChannel(true); Light.device = devices_present - Light.subtype + 1; // adjust if we also have relays + } else if (!light_controller.isCTRGBLinked()) { + // if RGBW or RGBCW, and SetOption37 >= 128, we manage RGB and W separately + Light.device--; // we take the last two devices as lights } #ifdef DEBUG_LIGHT AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d devices_present=%d", @@ -1177,10 +1224,6 @@ void LightUpdateColorMapping(void) Light.color_remap[3] = tmp[param]; Light.color_remap[4] = tmp[1-param]; - // do not allow independant RGV and WC colors - bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); - light_controller.setCTRGBLinked(ct_rgb_linked); - Light.update = true; //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]); } @@ -1196,22 +1239,37 @@ uint8_t LightGetBri(uint8_t device) { if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { bri = Light.current_color[device - Light.device]; } - } else if (device == Light.device) { - bri = light_state.getBri(); + } else if (light_controller.isCTRGBLinked()) { // standard behavior + if (device == Light.device) { + bri = light_state.getBri(); + } + } else { // unlinked + if (device == Light.device) { + bri = light_state.getBriRGB(); + } else if (device == Light.device + 1) { + bri = light_state.getBriCT(); + } } return bri; } -// If SetOption68 is set, get the brightness for a specific device - +// If SetOption68 is set, set the brightness for a specific device void LightSetBri(uint8_t device, uint8_t bri) { if (Light.pwm_multi_channels) { if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { Light.current_color[device - Light.device] = bri; light_controller.changeChannels(Light.current_color); } - } else if (device == Light.device) { - light_controller.changeBri(bri); + } else if (light_controller.isCTRGBLinked()) { // standard + if (device == Light.device) { + light_controller.changeBri(bri); + } + } else { // unlinked + if (device == Light.device) { + light_controller.changeBriRGB(bri); + } else if (device == Light.device + 1) { + light_controller.changeBriCT(bri); + } } } @@ -1369,13 +1427,31 @@ void LightPreparePower(void) // #endif // USE_DOMOTICZ // } } else { - if (light_state.getBri() && !(Light.power)) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + if (light_controller.isCTRGBLinked()) { // linked, standard + if (light_state.getBri() && !(Light.power)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBri() && Light.power) { + ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } else { + // RGB + if (light_state.getBriRGB() && !(Light.power & 1)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBri() && (Light.power & 1)) { + ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); + } + // White CT + if (light_state.getBriCT() && !(Light.power & 2)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBri() && (Light.power & 2)) { + ExecuteCommandPower(Light.device + 1, POWER_OFF_NO_STATE, SRC_LIGHT); } - } - else if (!light_state.getBri() && Light.power) { - ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); } #ifdef USE_DOMOTICZ DomoticzUpdatePowerState(Light.device); @@ -1387,7 +1463,7 @@ void LightPreparePower(void) #ifdef DEBUG_LIGHT AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", power, Light.power); #endif - Light.power = power >> (Light.device - 1); // reset next state + Light.power = power >> (Light.device - 1); // reset next state, works also with unlinked RGB/CT LightState(0); } @@ -1478,6 +1554,8 @@ void LightSetPower(void) uint32_t mask = 1; // default mask if (Light.pwm_multi_channels) { mask = (1 << Light.subtype) - 1; // wider mask + } else if (!light_controller.isCTRGBLinked()) { + mask = 3; // we got 2 devices, for RGB and White } uint32_t shift = Light.device - 1; // If PWM multi_channels @@ -1596,6 +1674,16 @@ void LightAnimate(void) // #endif } + if (!light_controller.isCTRGBLinked()) { + // we have 2 power bits for RGB and White + if (0 == (Light.power & 1)) { + Light.new_color[0] = Light.new_color[1] = Light.new_color[2] = 0; + } + if (0 == (Light.power & 2)) { + Light.new_color[3] = Light.new_color[4] = 0; + } + } + if (memcmp(Light.last_color, Light.new_color, Light.subtype)) { Light.update = true; } @@ -1928,6 +2016,17 @@ void CmndChannel(void) { if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { bool coldim = false; + + // Handle +/- special command + if (1 == XdrvMailbox.data_len) { + uint8_t channel = changeUIntScale(Light.current_color[XdrvMailbox.index - Light.device],0,255,0,100); + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (channel > 89) ? 100 : channel + 10; + } else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (channel < 11) ? 1 : channel - 10; + } + } + // Set "Channel" directly - this allows Color and Direct PWM control to coexist if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { Light.current_color[XdrvMailbox.index - Light.device] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); @@ -2063,21 +2162,32 @@ void CmndColorTemperature(void) void CmndDimmer(void) { - uint32_t dimmer = light_state.getDimmer(); + uint32_t dimmer; + + if ((1 == XdrvMailbox.index) || (2 == XdrvMailbox.index)) { // Dimmer1 is RGB, Dimmer 2 iw white + dimmer = light_state.getDimmer(XdrvMailbox.index); + } else { + dimmer = light_state.getDimmer(); + } + // Handle +/- special command if (1 == XdrvMailbox.data_len) { if ('+' == XdrvMailbox.data[0]) { XdrvMailbox.payload = (dimmer > 89) ? 100 : dimmer + 10; - } - else if ('-' == XdrvMailbox.data[0]) { + } else if ('-' == XdrvMailbox.data[0]) { XdrvMailbox.payload = (dimmer < 11) ? 1 : dimmer - 10; } } + // If value is ok, change it, otherwise report old value if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - light_controller.changeDimmer(XdrvMailbox.payload); + if ((1 == XdrvMailbox.index) || (2 == XdrvMailbox.index)) { + light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); + } else { + light_controller.changeDimmer(XdrvMailbox.payload); + } Light.update = true; LightPreparePower(); } else { - ResponseCmndNumber(Settings.light_dimmer); + ResponseCmndNumber(dimmer); } } From 50e1038c054eea197648ff34467304d79558e93b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 31 Oct 2019 12:12:48 +0100 Subject: [PATCH 073/196] Add support for SetOption82-113 --- tasmota/settings.h | 47 ++++++++++++++++++++++++++++++++++++- tasmota/settings.ino | 2 +- tasmota/support_command.ino | 34 +++++++++++++++++++++------ tasmota/tasmota.h | 5 ---- tools/decode-status.py | 17 ++++++++++---- 5 files changed, 87 insertions(+), 18 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index c64820103..8cd575cf1 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -98,6 +98,44 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu }; } SysBitfield3; +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 spare00 : 1; + uint32_t spare01 : 1; + uint32_t spare02 : 1; + uint32_t spare03 : 1; + uint32_t spare04 : 1; + uint32_t spare05 : 1; + uint32_t spare06 : 1; + uint32_t spare07 : 1; + uint32_t spare08 : 1; + uint32_t spare09 : 1; + uint32_t spare10 : 1; + uint32_t spare11 : 1; + uint32_t spare12 : 1; + uint32_t spare13 : 1; + uint32_t spare14 : 1; + uint32_t spare15 : 1; + uint32_t spare16 : 1; + uint32_t spare17 : 1; + uint32_t spare18 : 1; + uint32_t spare19 : 1; + uint32_t spare20 : 1; + uint32_t spare21 : 1; + uint32_t spare22 : 1; + uint32_t spare23 : 1; + uint32_t spare24 : 1; + uint32_t spare25 : 1; + uint32_t spare26 : 1; + uint32_t spare27 : 1; + uint32_t spare28 : 1; + uint32_t spare29 : 1; + uint32_t spare30 : 1; + uint32_t spare31 : 1; + }; +} SysBitfield4; + typedef union { uint32_t data; // Allow bit manipulation struct { @@ -227,7 +265,13 @@ struct SYSCFG { uint8_t weblog_level; // 1AC uint8_t mqtt_fingerprint[2][20]; // 1AD uint8_t adc_param_type; // 1D5 - uint8_t register8[16]; // 1D6 - 16 x 8-bit registers indexed by enum SettingsRegister8 + + uint8_t free_1d6[10]; // 1D6 + + SysBitfield4 flag4; // 1E0 + + uint8_t free_1e4[2]; // 1E4 + uint8_t shutter_accuracy; // 1E6 uint8_t mqttlog_level; // 1E7 uint8_t sps30_inuse_hours; // 1E8 @@ -389,6 +433,7 @@ struct SYSCFG { uint32_t deepsleep; // E94 uint16_t energy_power_delta; // E98 uint8_t shutter_motordelay[MAX_SHUTTERS]; // E9A + uint8_t free_e9e[346]; // E9E uint32_t cfg_timestamp; // FF8 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 87fb7c845..c5f4371bc 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1064,7 +1064,7 @@ void SettingsDelta(void) } } if (Settings.version < 0x0606000C) { - memset(&Settings.register8, 0x00, sizeof(Settings.register8)); + memset((char*)&Settings +0x1D6, 0x00, 16); } if (Settings.version < 0x0606000F) { Settings.shutter_accuracy = 0; diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 3b657c375..533aef8c8 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -372,10 +372,11 @@ void CmndStatus(void) if ((0 == payload) || (3 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_MQTTLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" - D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\"]}}"), + D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\",\"%08X\"]}}"), Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.tele_period, - Settings.flag2.data, Settings.flag.data, ToHex_P((unsigned char*)Settings.param, PARAM8_SIZE, stemp2, sizeof(stemp2)), Settings.flag3.data); + Settings.flag2.data, Settings.flag.data, ToHex_P((unsigned char*)Settings.param, PARAM8_SIZE, stemp2, sizeof(stemp2)), + Settings.flag3.data, Settings.flag4.data); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3")); } @@ -627,7 +628,7 @@ void CmndSavedata(void) void CmndSetoption(void) { - if (XdrvMailbox.index < 82) { + if (XdrvMailbox.index < 114) { uint32_t ptype; uint32_t pindex; if (XdrvMailbox.index <= 31) { // SetOption0 .. 31 = Settings.flag @@ -638,10 +639,15 @@ void CmndSetoption(void) ptype = 2; pindex = XdrvMailbox.index -32; // 0 .. 17 (= PARAM8_SIZE -1) } - else { // SetOption50 .. 81 = Settings.flag3 + + else if (XdrvMailbox.index <= 81) { // SetOption50 .. 81 = Settings.flag3 ptype = 1; pindex = XdrvMailbox.index -50; // 0 .. 31 } + else { // SetOption82 .. 113 = Settings.flag4 + ptype = 3; + pindex = XdrvMailbox.index -82; // 0 .. 31 + } if (XdrvMailbox.payload >= 0) { if (0 == ptype) { // SetOption0 .. 31 if (XdrvMailbox.payload <= 1) { @@ -690,6 +696,11 @@ void CmndSetoption(void) } } } + else if (3 == ptype) { // SetOption82 .. 113 + if (XdrvMailbox.payload <= 1) { + bitWrite(Settings.flag4.data, pindex, XdrvMailbox.payload); + } + } else { // SetOption32 .. 49 uint32_t param_low = 0; uint32_t param_high = 255; @@ -716,9 +727,18 @@ void CmndSetoption(void) } } if (ptype < 99) { - char stemp1[TOPSZ]; - if (2 == ptype) { snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), Settings.param[pindex]); } - ResponseCmndIdxChar((2 == ptype) ? stemp1 : (1 == ptype) ? GetStateText(bitRead(Settings.flag3.data, pindex)) : GetStateText(bitRead(Settings.flag.data, pindex))); + if (2 == ptype) { + ResponseCmndIdxNumber(Settings.param[pindex]); + } else { + uint32_t flag = Settings.flag.data; + if (1 == ptype) { + flag = Settings.flag3.data; + } + else if (3 == ptype) { + flag = Settings.flag4.data; + } + ResponseCmndIdxChar(GetStateText(bitRead(flag, pindex))); + } } } } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 73fc192a8..9520a3613 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -250,11 +250,6 @@ enum SettingsParamIndex { P_HOLD_TIME, P_MAX_POWER_RETRY, P_BACKLOG_DELAY, P_MDN P_ex_ENERGY_TARIFF1, P_ex_ENERGY_TARIFF2, // SetOption47 .. SetOption48 P_MAX_PARAM8 }; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 -enum SettingsRegister8 { R8_SPARE00, R8_SPARE01, R8_SPARE02, R8_SPARE03, - R8_SPARE04, R8_SPARE05, R8_SPARE06, R8_SPARE07, - R8_SPARE08, R8_SPARE09, R8_SPARE10, R8_SPARE11, - R8_SPARE12, R8_SPARE13, R8_SPARE14, R8_SPARE15 }; // Max size is 16 (Settings.register8[]) - enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_P1_SMART_METER, DZ_SHUTTER, DZ_MAX_SENSORS}; diff --git a/tools/decode-status.py b/tools/decode-status.py index b50d920db..2b67a3fd1 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -86,7 +86,7 @@ a_setoption = [[ ],[ "Key hold time (ms)", "Sonoff POW Max_Power_Retry", - "(not used) Tuya MCU device id", + "Backlog delay (ms)", "(not used) mDNS delayed start (Sec)", "Boot loop retry offset (0 = disable)", "RGBWW remap", @@ -99,8 +99,8 @@ a_setoption = [[ "(not used) Tuya MCU voltage Id", "(not used) Tuya MCU current Id", "(not used) Tuya MCU power Id", - "Energy Tariff1 start hour", - "Energy Tariff2 start hour", + "(not used) Energy Tariff1 start hour", + "(not used) Energy Tariff2 start hour", "", ],[ "Timers enabled", @@ -131,6 +131,15 @@ a_setoption = [[ "","", "Enable shutter support", "Invert PCF8574 ports" + ],[ + "","","","", + "","","","", + "","","","", + "","","","", + "","","","", + "","","","", + "","","","", + "","","","" ]] a_features = [[ @@ -246,7 +255,7 @@ def StartDecode(): options.append(str("{0:2d} ({1:3d}) {2}".format(i, split_register[opt_idx], option))) i += 1 - if r in (0, 2): #registers 1 and 3 hold binary values + if r in (0, 2, 3): #registers 1 and 3 hold binary values for opt_idx, option in enumerate(opt_group): i_register = int(register,16) state = (i_register >> opt_idx) & 1 From 23cef04b9e435f82cbd2b1e6ee4039e54bb0e069 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 31 Oct 2019 13:18:00 +0100 Subject: [PATCH 074/196] Refactor command SetOption --- tasmota/support_command.ino | 130 ++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index e127707c6..1dbbbdc2d 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -632,76 +632,24 @@ void CmndSetoption(void) uint32_t ptype; uint32_t pindex; if (XdrvMailbox.index <= 31) { // SetOption0 .. 31 = Settings.flag - ptype = 0; + ptype = 2; pindex = XdrvMailbox.index; // 0 .. 31 } else if (XdrvMailbox.index <= 49) { // SetOption32 .. 49 = Settings.param - ptype = 2; + ptype = 1; pindex = XdrvMailbox.index -32; // 0 .. 17 (= PARAM8_SIZE -1) } - else if (XdrvMailbox.index <= 81) { // SetOption50 .. 81 = Settings.flag3 - ptype = 1; + ptype = 3; pindex = XdrvMailbox.index -50; // 0 .. 31 } else { // SetOption82 .. 113 = Settings.flag4 - ptype = 3; + ptype = 4; pindex = XdrvMailbox.index -82; // 0 .. 31 } + if (XdrvMailbox.payload >= 0) { - if (0 == ptype) { // SetOption0 .. 31 - if (XdrvMailbox.payload <= 1) { - switch (pindex) { - case 5: // mqtt_power_retain (CMND_POWERRETAIN) - case 6: // mqtt_button_retain (CMND_BUTTONRETAIN) - case 7: // mqtt_switch_retain (CMND_SWITCHRETAIN) - case 9: // mqtt_sensor_retain (CMND_SENSORRETAIN) - case 14: // interlock (CMND_INTERLOCK) - case 22: // mqtt_serial (SerialSend and SerialLog) - case 23: // mqtt_serial_raw (SerialSend) - case 25: // knx_enabled (Web config) - case 27: // knx_enable_enhancement (Web config) - ptype = 99; // Command Error - break; // Ignore command SetOption - case 3: // mqtt - case 15: // pwm_control - restart_flag = 2; - default: - bitWrite(Settings.flag.data, pindex, XdrvMailbox.payload); - } - if (12 == pindex) { // stop_flash_rotate - stop_flash_rotate = XdrvMailbox.payload; - SettingsSave(2); - } -#ifdef USE_HOME_ASSISTANT - if ((19 == pindex) || (30 == pindex)) { - HAssDiscover(); // Delayed execution to provide enough resources during hass_discovery or hass_light - } -#endif // USE_HOME_ASSISTANT - } - } - else if (1 == ptype) { // SetOption50 .. 81 - if (XdrvMailbox.payload <= 1) { - bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload); - if (5 == pindex) { // SetOption55 - if (0 == XdrvMailbox.payload) { - restart_flag = 2; // Disable mDNS needs restart - } - } - if (10 == pindex) { // SetOption60 enable or disable traditional sleep - WiFiSetSleepMode(); // Update WiFi sleep mode accordingly - } - if (18 == pindex) { // SetOption68 for multi-channel PWM, requires a reboot - restart_flag = 2; - } - } - } - else if (3 == ptype) { // SetOption82 .. 113 - if (XdrvMailbox.payload <= 1) { - bitWrite(Settings.flag4.data, pindex, XdrvMailbox.payload); - } - } - else { // SetOption32 .. 49 + if (1 == ptype) { // SetOption32 .. 49 uint32_t param_low = 0; uint32_t param_high = 255; switch (pindex) { @@ -710,15 +658,13 @@ void CmndSetoption(void) param_low = 1; param_high = 250; break; - case P_RGB_REMAP: - restart_flag = 2; // SetOption37 needs a reboot in most cases - break; } if ((XdrvMailbox.payload >= param_low) && (XdrvMailbox.payload <= param_high)) { Settings.param[pindex] = XdrvMailbox.payload; #ifdef USE_LIGHT if (P_RGB_REMAP == pindex) { LightUpdateColorMapping(); + restart_flag = 2; // SetOption37 needs a reboot in most cases } #endif #if (defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE)) || defined(USE_IR_REMOTE_FULL) @@ -726,18 +672,74 @@ void CmndSetoption(void) IrReceiveUpdateThreshold(); } #endif + } else { + ptype = 99; // Command Error + } + } else { + if (XdrvMailbox.payload <= 1) { + if (2 == ptype) { // SetOption0 .. 31 + switch (pindex) { + case 5: // mqtt_power_retain (CMND_POWERRETAIN) + case 6: // mqtt_button_retain (CMND_BUTTONRETAIN) + case 7: // mqtt_switch_retain (CMND_SWITCHRETAIN) + case 9: // mqtt_sensor_retain (CMND_SENSORRETAIN) + case 14: // interlock (CMND_INTERLOCK) + case 22: // mqtt_serial (SerialSend and SerialLog) + case 23: // mqtt_serial_raw (SerialSend) + case 25: // knx_enabled (Web config) + case 27: // knx_enable_enhancement (Web config) + ptype = 99; // Command Error + break; // Ignore command SetOption + case 3: // mqtt + case 15: // pwm_control + restart_flag = 2; + default: + bitWrite(Settings.flag.data, pindex, XdrvMailbox.payload); + } + if (12 == pindex) { // stop_flash_rotate + stop_flash_rotate = XdrvMailbox.payload; + SettingsSave(2); + } + #ifdef USE_HOME_ASSISTANT + if ((19 == pindex) || (30 == pindex)) { + HAssDiscover(); // Delayed execution to provide enough resources during hass_discovery or hass_light + } + #endif // USE_HOME_ASSISTANT + } + else if (3 == ptype) { // SetOption50 .. 81 + bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload); + switch (pindex) { + case 5: // SetOption55 + if (0 == XdrvMailbox.payload) { + restart_flag = 2; // Disable mDNS needs restart + } + break; + case 10: // SetOption60 enable or disable traditional sleep + WiFiSetSleepMode(); // Update WiFi sleep mode accordingly + break; + case 18: // SetOption68 for multi-channel PWM, requires a reboot + restart_flag = 2; + break; + } + } + else if (4 == ptype) { // SetOption82 .. 113 + bitWrite(Settings.flag4.data, pindex, XdrvMailbox.payload); + } + } else { + ptype = 99; // Command Error } } } + if (ptype < 99) { - if (2 == ptype) { + if (1 == ptype) { ResponseCmndIdxNumber(Settings.param[pindex]); } else { uint32_t flag = Settings.flag.data; - if (1 == ptype) { + if (3 == ptype) { flag = Settings.flag3.data; } - else if (3 == ptype) { + else if (4 == ptype) { flag = Settings.flag4.data; } ResponseCmndIdxChar(GetStateText(bitRead(flag, pindex))); From e497421ace372fc5b4f2898e118b20dd710704d4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 31 Oct 2019 17:24:06 +0100 Subject: [PATCH 075/196] Add command SetOption75 0/1 to switch between grouptopic Add command SetOption75 0/1 to switch between grouptopic (0) using fulltopic replacing %topic% or (1) is cmnd/ (#6779) --- tasmota/_changelog.ino | 3 ++- tasmota/settings.h | 2 +- tasmota/support_command.ino | 3 ++- tasmota/tasmota.ino | 23 +++++++++++++++++++---- tasmota/xdrv_01_webserver.ino | 5 +++-- tasmota/xdrv_02_mqtt.ino | 7 ++++--- 6 files changed, 31 insertions(+), 12 deletions(-) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index b98b89210..055d01a52 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -1,12 +1,13 @@ /*********************************************************************************************\ * 7.0.0.1 20191027 - * Remove references to versions before 6.x + * Remove references to versions before 6.0 * Change default GUI to dark theme * Add command SetOption73 0/1 to re-enable HTTP Cross-Origin Resource Sharing (CORS) now default disabled (#6767) * Add frequency to ADE7953 energy monitor as used in Shelly 2.5 by ljakob (#6778) * Add command SetOption74 0/1 to enable DS18x20 internal pull-up and remove define DS18B20_INTERNAL_PULLUP (#6795) * Fix better control of RGB/White when SetOption37 >128, added Dimmer1 and Dimmer2 commands (#6714) * Add hide Alexa objects with friendlyname starting with '$' (#6722, #6762) + * Add command SetOption75 0/1 to switch between grouptopic (0) using fulltopic replacing %topic% or (1) is cmnd/ (#6779) * * 6.7.1.1 20191026 * Change ArduinoSlave to TasmotaSlave (Experimental) diff --git a/tasmota/settings.h b/tasmota/settings.h index 8cd575cf1..332782162 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -88,7 +88,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t hardware_energy_total : 1; // bit 22 (v6.6.0.15) - SetOption72 - Enable / Disable hardware energy total counter as reference (#6561) uint32_t cors_enabled : 1; // bit 23 (v7.0.0.1) - SetOption73 - Enable HTTP CORS uint32_t ds18x20_internal_pullup : 1; // bit 24 (v7.0.0.1) - SetOption74 - Enable internal pullup for single DS18x20 sensor - uint32_t spare25 : 1; + uint32_t grouptopic_mode : 1; // bit 25 (v7.0.0.1) - SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) uint32_t spare26 : 1; uint32_t spare27 : 1; uint32_t spare28 : 1; diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 1dbbbdc2d..47908e2d0 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -143,7 +143,7 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) bool grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr); char stemp1[TOPSZ]; - GetFallbackTopic_P(stemp1, CMND, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/ + GetFallbackTopic_P(stemp1, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/ fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); char *type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) @@ -718,6 +718,7 @@ void CmndSetoption(void) WiFiSetSleepMode(); // Update WiFi sleep mode accordingly break; case 18: // SetOption68 for multi-channel PWM, requires a reboot + case 25: // SetOption75 grouptopic change restart_flag = 2; break; } diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 263888558..1240a60de 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -243,18 +243,26 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi prefix 4 = Cmnd fallback prefix 5 = Stat fallback prefix 6 = Tele fallback + prefix 8 = Cmnd topic + prefix 9 = Stat topic + prefix 10 = Tele topic */ char romram[CMDSZ]; String fulltopic; snprintf_P(romram, sizeof(romram), subtopic); if (fallback_topic_flag || (prefix > 3)) { + bool fallback = (prefix < 8); prefix &= 3; char stemp[11]; fulltopic = GetTextIndexed(stemp, sizeof(stemp), prefix, kPrefixes); fulltopic += F("/"); - fulltopic += mqtt_client; - fulltopic += F("_fb"); // cmnd/_fb + if (fallback) { + fulltopic += mqtt_client; + fulltopic += F("_fb"); // cmnd/_fb + } else { + fulltopic += topic; // cmnd/ + } } else { fulltopic = Settings.mqtt_fulltopic; if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) { @@ -282,9 +290,16 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi return stopic; } -char* GetFallbackTopic_P(char *stopic, uint32_t prefix, const char* subtopic) +char* GetGroupTopic_P(char *stopic, const char* subtopic) { - return GetTopic_P(stopic, prefix +4, nullptr, subtopic); + // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# + // SetOption75 1: cmnd/ + return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, Settings.mqtt_grptopic, subtopic); +} + +char* GetFallbackTopic_P(char *stopic, const char* subtopic) +{ + return GetTopic_P(stopic, CMND +4, nullptr, subtopic); } char* GetStateText(uint32_t state) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 648dca783..634759fe0 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1910,9 +1910,10 @@ void HandleInformation(void) #endif WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), Settings.mqtt_topic); - WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), Settings.mqtt_grptopic); +// WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), Settings.mqtt_grptopic); + WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), GetGroupTopic_P(stopic, "")); WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, mqtt_topic, "")); - WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, CMND, "")); + WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, "")); } else { WSContentSend_P(PSTR("}1" D_MQTT "}2" D_DISABLED)); } diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index cafdc80da..450c12d90 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -528,9 +528,9 @@ void MqttConnected(void) GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); MqttSubscribe(stopic); if (strstr_P(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) { - GetTopic_P(stopic, CMND, Settings.mqtt_grptopic, PSTR("#")); + GetGroupTopic_P(stopic, PSTR("#")); // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# or SetOption75 1: cmnd/ MqttSubscribe(stopic); - GetFallbackTopic_P(stopic, CMND, PSTR("#")); + GetFallbackTopic_P(stopic, PSTR("#")); MqttSubscribe(stopic); } @@ -538,8 +538,9 @@ void MqttConnected(void) } if (Mqtt.initial_connection_state) { + char stopic2[TOPSZ]; Response_P(PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), - ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, CMND, ""), Settings.mqtt_grptopic); + ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, ""), GetGroupTopic_P(stopic2, "")); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER if (Settings.webserver) { From 20370820b85acf282fbf7ebec38ef2a484921a16 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 31 Oct 2019 17:41:54 +0100 Subject: [PATCH 076/196] Update decode-status.py --- tools/decode-status.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/decode-status.py b/tools/decode-status.py index 2b67a3fd1..2edc469db 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -125,9 +125,11 @@ a_setoption = [[ "(not used) Limits Tuya MCU dimmers to minimum of 10% (25) when enabled", "Enable Weekend Energy Tariff", "Select different Modbus registers for Active Energy", + "Enable hardware energy total counter as reference", "Enable HTTP CORS", "Enable internal pullup for single DS18x20 sensor", - "","","","", + "GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)", + "","", "","", "Enable shutter support", "Invert PCF8574 ports" From 8e07f0de26d0722015bea0bbfff3ee0cf92be385 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 31 Oct 2019 21:36:37 +0100 Subject: [PATCH 077/196] Delete outdated info --- tasmota/user_config_override_sample.h | 1 - 1 file changed, 1 deletion(-) diff --git a/tasmota/user_config_override_sample.h b/tasmota/user_config_override_sample.h index ef97e43cf..c70ec849f 100644 --- a/tasmota/user_config_override_sample.h +++ b/tasmota/user_config_override_sample.h @@ -31,7 +31,6 @@ * (3) for platformio: * define USE_CONFIG_OVERRIDE as a build flags. * ie1 : export PLATFORMIO_BUILD_FLAGS='-DUSE_CONFIG_OVERRIDE' - * ie2 : enable in file platformio.ini "build_flags = -Wl,-Tesp8266.flash.1m0.ld -DUSE_CONFIG_OVERRIDE" * for Arduino IDE: * enable define USE_CONFIG_OVERRIDE in my_user_config.h ****************************************************************************************************** From c3b5c3638b7bd124290ff518f5073cfda20ce681 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 1 Nov 2019 11:03:10 +0100 Subject: [PATCH 078/196] Bring setting -DUSE_CONFIG_OVERRIDE more to top... to make it easier to find. Core Selection is moved too. --- platformio.ini | 128 +++++++++++++++++++++++++------------------------ 1 file changed, 66 insertions(+), 62 deletions(-) diff --git a/platformio.ini b/platformio.ini index a6e94f13d..f7837adbf 100755 --- a/platformio.ini +++ b/platformio.ini @@ -43,6 +43,72 @@ build_cache_dir = .cache ;default_envs = tasmota-TW ;default_envs = tasmota-UK +[common] +framework = arduino +board = esp01_1m +board_build.flash_mode = dout + +platform = ${core_active.platform} +build_flags = ${core_active.build_flags} + +; ********************************************************************* +; *** Uncomment to use custom settings from file user_config_override.h +; -DUSE_CONFIG_OVERRIDE +; ********************************************************************* + +; *** Optional Debug messages +; -DDEBUG_TASMOTA_CORE +; -DDEBUG_TASMOTA_DRIVER +; -DDEBUG_TASMOTA_SENSOR + +; *** Optional Firmware configurations +; -DFIRMWARE_MINIMAL +; -DFIRMWARE_SENSORS +; -DFIRMWARE_BASIC +; -DFIRMWARE_KNX_NO_EMULATION +; -DFIRMWARE_DISPLAYS +; -DFIRMWARE_IR +; -DFIRMWARE_IR_CUSTOM + +; *** Fix espressif8266@1.7.0 induced undesired all warnings +build_unflags = -Wall + +; set CPU frequency to 80MHz (default) or 160MHz +board_build.f_cpu = 80000000L +;board_build.f_cpu = 160000000L + +monitor_speed = 115200 +upload_speed = 115200 +upload_resetmethod = nodemcu + +; *** Upload Serial reset method for Wemos and NodeMCU +upload_port = COM5 +extra_scripts = pio/strip-floats.py + pio/obj-dump.py + +; *** Upload file to OTA server using SCP +;upload_port = user@host:/path +;extra_scripts = pio/strip-floats.py, pio/sftp-uploader.py + +; *** Upload file to OTA server in folder api/arduino using HTTP +;upload_port = domus1:80/api/upload-arduino.php +;extra_scripts = pio/strip-floats.py, pio/http-uploader.py + +[core_active] +; Select one core set for platform and build_flags +;platform = ${core_2_3_0.platform} +;build_flags = ${core_2_3_0.build_flags} +;platform = ${core_2_4_2.platform} +;build_flags = ${core_2_4_2.build_flags} +platform = ${core_pre.platform} +build_flags = ${core_pre.build_flags} +;platform = ${core_pre_ipv6.platform} +;build_flags = ${core_pre_ipv6.build_flags} +;platform = ${core_stage.platform} +;build_flags = ${core_stage.build_flags} + +; ********************************************************************* + [esp82xx_defaults] build_flags = -D NDEBUG -mtarget-align @@ -188,68 +254,6 @@ build_flags = ${esp82xx_defaults.build_flags} ; -fexceptions ; -lstdc++-exc -[core_active] -; Select one core set for platform and build_flags -;platform = ${core_2_3_0.platform} -;build_flags = ${core_2_3_0.build_flags} -;platform = ${core_2_4_2.platform} -;build_flags = ${core_2_4_2.build_flags} -platform = ${core_pre.platform} -build_flags = ${core_pre.build_flags} -;platform = ${core_pre_ipv6.platform} -;build_flags = ${core_pre_ipv6.build_flags} -;platform = ${core_stage.platform} -;build_flags = ${core_stage.build_flags} - -[common] -framework = arduino -board = esp01_1m -board_build.flash_mode = dout - -platform = ${core_active.platform} -build_flags = ${core_active.build_flags} - -; *** Optional Debug messages -; -DDEBUG_TASMOTA_CORE -; -DDEBUG_TASMOTA_DRIVER -; -DDEBUG_TASMOTA_SENSOR - -; *** Optional Firmware configurations -; -DFIRMWARE_MINIMAL -; -DFIRMWARE_SENSORS -; -DFIRMWARE_BASIC -; -DFIRMWARE_KNX_NO_EMULATION -; -DFIRMWARE_DISPLAYS -; -DFIRMWARE_IR -; -DFIRMWARE_IR_CUSTOM -; -DUSE_CONFIG_OVERRIDE - -; *** Fix espressif8266@1.7.0 induced undesired all warnings -build_unflags = -Wall - -; set CPU frequency to 80MHz (default) or 160MHz -board_build.f_cpu = 80000000L -;board_build.f_cpu = 160000000L - -monitor_speed = 115200 -upload_speed = 115200 -upload_resetmethod = nodemcu - -; *** Upload Serial reset method for Wemos and NodeMCU -upload_port = COM5 -extra_scripts = pio/strip-floats.py - pio/obj-dump.py - -; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = pio/strip-floats.py, pio/sftp-uploader.py - -; *** Upload file to OTA server in folder api/arduino using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = pio/strip-floats.py, pio/http-uploader.py - -; ********************************************************************* - [env:tasmota] platform = ${common.platform} framework = ${common.framework} From 6a6d829c27c05edc43d00c7da1541a848b06494e Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 1 Nov 2019 11:25:08 +0100 Subject: [PATCH 079/196] Update platformio.ini --- platformio.ini | 62 ++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/platformio.ini b/platformio.ini index f7837adbf..cae9f6b78 100755 --- a/platformio.ini +++ b/platformio.ini @@ -12,36 +12,38 @@ src_dir = tasmota build_dir = .pioenvs build_cache_dir = .cache -; *** Uncomment one of the lines below to build/upload only one environment -;default_envs = tasmota -;default_envs = tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big -;default_envs = tasmota-minimal -;default_envs = tasmota-basic -;default_envs = tasmota-knx -;default_envs = tasmota-sensors -;default_envs = tasmota-display -;default_envs = tasmota-ir -;default_envs = tasmota-BG -;default_envs = tasmota-BR -;default_envs = tasmota-CN -;default_envs = tasmota-CZ -;default_envs = tasmota-DE -;default_envs = tasmota-ES -;default_envs = tasmota-FR -;default_envs = tasmota-GR -;default_envs = tasmota-HE -;default_envs = tasmota-HU -;default_envs = tasmota-IT -;default_envs = tasmota-KO -;default_envs = tasmota-NL -;default_envs = tasmota-PL -;default_envs = tasmota-PT -;default_envs = tasmota-RU -;default_envs = tasmota-SE -;default_envs = tasmota-SK -;default_envs = tasmota-TR -;default_envs = tasmota-TW -;default_envs = tasmota-UK +; *** Build/upload environment +default_envs = +; *** Uncomment the line(s) below to select version(s) +; tasmota +; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big +; tasmota-minimal +; tasmota-basic +; tasmota-knx +; tasmota-sensors +; tasmota-display +; tasmota-ir +; tasmota-BG +; tasmota-BR +; tasmota-CN +; tasmota-CZ +; tasmota-DE +; tasmota-ES +; tasmota-FR +; tasmota-GR +; tasmota-HE +; tasmota-HU +; tasmota-IT +; tasmota-KO +; tasmota-NL +; tasmota-PL +; tasmota-PT +; tasmota-RU +; tasmota-SE +; tasmota-SK +; tasmota-TR +; tasmota-TW +; tasmota-UK [common] framework = arduino From fa854b7bfbfab508f9a9567499e89f2ef61ff997 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 1 Nov 2019 11:44:18 +0100 Subject: [PATCH 080/196] Update platformio.ini --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index cae9f6b78..2ed7415c3 100755 --- a/platformio.ini +++ b/platformio.ini @@ -14,7 +14,7 @@ build_cache_dir = .cache ; *** Build/upload environment default_envs = -; *** Uncomment the line(s) below to select version(s) +; *** Uncomment by deleting ";" in the line(s) below to select version(s) ; tasmota ; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big ; tasmota-minimal @@ -54,7 +54,7 @@ platform = ${core_active.platform} build_flags = ${core_active.build_flags} ; ********************************************************************* -; *** Uncomment to use custom settings from file user_config_override.h +; *** Uncomment by deleting ";" to use custom settings from file user_config_override.h ; -DUSE_CONFIG_OVERRIDE ; ********************************************************************* From 66d0ee34a3921b3c411bb90629debf1ba8281bf2 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 1 Nov 2019 11:48:11 +0100 Subject: [PATCH 081/196] Update platformio.ini --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 2ed7415c3..3d2ef5aea 100755 --- a/platformio.ini +++ b/platformio.ini @@ -54,7 +54,7 @@ platform = ${core_active.platform} build_flags = ${core_active.build_flags} ; ********************************************************************* -; *** Uncomment by deleting ";" to use custom settings from file user_config_override.h +; *** Uncomment, by deleting ";" in line below, to use custom settings from file user_config_override.h ; -DUSE_CONFIG_OVERRIDE ; ********************************************************************* From 49e8f52a43b282144a230952b1f44d7943edda06 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 1 Nov 2019 16:05:07 +0100 Subject: [PATCH 082/196] Fix case insensitive rule variable substitution Fix case insensitive rule variable substitution (#6802) --- tasmota/xdrv_10_rules.ino | 50 +++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 1a1f3c2c2..d1f8ca49a 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -365,6 +365,29 @@ int8_t parseCompareExpression(String &expr, String &leftExpr, String &rightExpr) return compare; } +void RulesVarReplace(String &commands, const String &sfind, const String &replace) +{ +// String ufind = sfind; +// ufind.toUpperCase(); +// char *find = (char*)ufind.c_str(); + char *find = (char*)sfind.c_str(); + uint32_t flen = strlen(find); + + String ucommand = commands; + ucommand.toUpperCase(); + char *read_from = (char*)ucommand.c_str(); + char *write_to = (char*)commands.c_str(); + char *found_at; + while ((found_at = strstr(read_from, find)) != nullptr) { + write_to += (found_at - read_from); + memmove_P(write_to, find, flen); // Make variable Uppercase + write_to += flen; + read_from = found_at + flen; + } + + commands.replace(find, replace); +} + /*******************************************************************************************/ bool RuleSetProcess(uint8_t rule_set, String &event_saved) @@ -402,7 +425,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) if (plen == -1) { plen = 9999; } if (plen2 == -1) { plen2 = 9999; } plen = tmin(plen, plen2); - if (plen == plen2) { stop_all_rules = true; } // If BREAK was used, Stop execution of this rule set + if (plen == plen2) { stop_all_rules = true; } // If BREAK was used, Stop execution of this rule set String commands = rules.substring(pevt +4, plen); // "Backlog Dimmer 10;Color 100000" plen += 6; @@ -417,21 +440,22 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) ucommand.toUpperCase(); // if (!ucommand.startsWith("BACKLOG")) { commands = "backlog " + commands; } // Always use Backlog to prevent power race exception if (ucommand.indexOf("EVENT ") != -1) { commands = "backlog " + commands; } // Always use Backlog with event to prevent rule event loop exception - commands.replace(F("%value%"), Rules.event_value); + + RulesVarReplace(commands, F("%VALUE%"), Rules.event_value); for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%%var%d%%"), i +1); - commands.replace(stemp, rules_vars[i]); + snprintf_P(stemp, sizeof(stemp), PSTR("%%VAR%d%%"), i +1); + RulesVarReplace(commands, stemp, rules_vars[i]); } for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%%mem%d%%"), i +1); - commands.replace(stemp, Settings.mems[i]); + snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1); + RulesVarReplace(commands, stemp, Settings.mems[i]); } - commands.replace(F("%time%"), String(MinutesPastMidnight())); - commands.replace(F("%uptime%"), String(MinutesUptime())); - commands.replace(F("%timestamp%"), GetDateAndTime(DT_LOCAL).c_str()); + RulesVarReplace(commands, F("%TIME%"), String(MinutesPastMidnight())); + RulesVarReplace(commands, F("%UPTIME%"), String(MinutesUptime())); + RulesVarReplace(commands, F("%TIMESTAMP%"), GetDateAndTime(DT_LOCAL)); #if defined(USE_TIMERS) && defined(USE_SUNRISE) - commands.replace(F("%sunrise%"), String(SunMinutes(0))); - commands.replace(F("%sunset%"), String(SunMinutes(1))); + RulesVarReplace(commands, F("%SUNRISE%"), String(SunMinutes(0))); + RulesVarReplace(commands, F("%SUNSET%"), String(SunMinutes(1))); #endif // USE_TIMERS and USE_SUNRISE char command[commands.length() +1]; @@ -443,11 +467,11 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) // MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RULE)); #ifdef SUPPORT_IF_STATEMENT char *pCmd = command; - RulesPreprocessCommand(pCmd); //Do pre-process for IF statement + RulesPreprocessCommand(pCmd); // Do pre-process for IF statement #endif ExecuteCommand(command, SRC_RULE); serviced = true; - if (stop_all_rules) { return serviced; } // If BREAK was used, Stop execution of this rule set + if (stop_all_rules) { return serviced; } // If BREAK was used, Stop execution of this rule set } Rules.trigger_count[rule_set]++; } From d6115b7dd1312e537e3123d22c4fc13f5cfcc4c2 Mon Sep 17 00:00:00 2001 From: localhost61 Date: Sat, 2 Nov 2019 05:33:40 +0100 Subject: [PATCH 083/196] Add COLOR_TITLE as WebColor19 --- tasmota/my_user_config.h | 1 + tasmota/settings.h | 5 +++-- tasmota/settings.ino | 7 +++++-- tasmota/support.ino | 18 +++++++++++++----- tasmota/xdrv_01_webserver.ino | 3 ++- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 33f00ca4f..69773b3d0 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -168,6 +168,7 @@ #define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" // [WebColor16] Save button color when hovered over - Darker greenish #define COLOR_TIMER_TAB_TEXT "#fff" // [WebColor17] Config timer tab text color - White #define COLOR_TIMER_TAB_BACKGROUND "#999" // [WebColor18] Config timer tab background color - Light grey +#define COLOR_TITLE_TEXT COLOR_TEXT // [WebColor19] Title text color - Whiteish // -- mDNS ---------------------------------------- #define MDNS_ENABLED 0 // [SetOption55] Use mDNS (0 = Disable, 1 = Enable) diff --git a/tasmota/settings.h b/tasmota/settings.h index 332782162..4f95e62b9 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -433,8 +433,9 @@ struct SYSCFG { uint32_t deepsleep; // E94 uint16_t energy_power_delta; // E98 uint8_t shutter_motordelay[MAX_SHUTTERS]; // E9A - - uint8_t free_e9e[346]; // E9E + uint8_t free_e9e[342]; // E9E + uint8_t web_color2[1][3]; // FF4 + uint8_t free_ff7 ; // FF7 uint32_t cfg_timestamp; // FF8 uint32_t cfg_crc32; // FFC diff --git a/tasmota/settings.ino b/tasmota/settings.ino index c5f4371bc..a9f686e50 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -119,6 +119,9 @@ #ifndef COLOR_TIMER_TAB_BACKGROUND #define COLOR_TIMER_TAB_BACKGROUND "#999" // Config timer tab background color - Light grey #endif +#ifndef COLOR_TITLE_TEXT +#define COLOR_TITLE_TEXT COLOR_TEXT // Title text color defaults to global text color either dark or light +#endif #ifndef IR_RCV_MIN_UNKNOWN_SIZE #define IR_RCV_MIN_UNKNOWN_SIZE 6 // Set the smallest sized "UNKNOWN" message packets we actually care about (default 6, max 255) #endif @@ -137,7 +140,7 @@ enum WebColors { COL_INPUT_TEXT, COL_INPUT, COL_CONSOLE_TEXT, COL_CONSOLE, COL_TEXT_WARNING, COL_TEXT_SUCCESS, COL_BUTTON_TEXT, COL_BUTTON, COL_BUTTON_HOVER, COL_BUTTON_RESET, COL_BUTTON_RESET_HOVER, COL_BUTTON_SAVE, COL_BUTTON_SAVE_HOVER, - COL_TIMER_TAB_TEXT, COL_TIMER_TAB_BACKGROUND, + COL_TIMER_TAB_TEXT, COL_TIMER_TAB_BACKGROUND, COL_TITLE, COL_LAST }; const char kWebColors[] PROGMEM = @@ -145,7 +148,7 @@ const char kWebColors[] PROGMEM = COLOR_INPUT_TEXT "|" COLOR_INPUT "|" COLOR_CONSOLE_TEXT "|" COLOR_CONSOLE "|" COLOR_TEXT_WARNING "|" COLOR_TEXT_SUCCESS "|" COLOR_BUTTON_TEXT "|" COLOR_BUTTON "|" COLOR_BUTTON_HOVER "|" COLOR_BUTTON_RESET "|" COLOR_BUTTON_RESET_HOVER "|" COLOR_BUTTON_SAVE "|" COLOR_BUTTON_SAVE_HOVER "|" - COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND; + COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND "|" COLOR_TITLE_TEXT; /*********************************************************************************************\ * RTC memory diff --git a/tasmota/support.ino b/tasmota/support.ino index a2895e9a1..51147f502 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -883,15 +883,23 @@ void WebHexCode(uint32_t i, const char* code) color = w | (w << 4); // 00112233 } */ - - Settings.web_color[i][0] = (color >> 16) & 0xFF; // Red - Settings.web_color[i][1] = (color >> 8) & 0xFF; // Green - Settings.web_color[i][2] = color & 0xFF; // Blue + uint32_t j = sizeof(Settings.web_color)/3; // First area contains j=18 colors + if (i < j) { + Settings.web_color[i][0] = (color >> 16) & 0xFF; // Red + Settings.web_color[i][1] = (color >> 8) & 0xFF; // Green + Settings.web_color[i][2] = color & 0xFF; // Blue + } else { + Settings.web_color2[i-j][0] = (color >> 16) & 0xFF; // Red + Settings.web_color2[i-j][1] = (color >> 8) & 0xFF; // Green + Settings.web_color2[i-j][2] = color & 0xFF; // Blue + } } uint32_t WebColor(uint32_t i) { - uint32_t tcolor = (Settings.web_color[i][0] << 16) | (Settings.web_color[i][1] << 8) | Settings.web_color[i][2]; + uint32_t j = sizeof(Settings.web_color)/3; // First area contains j=18 colors + uint32_t tcolor = (i

      " D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "

      " // COLOR_TEXT_WARNING #endif - "
      " + "
      " // COLOR_TITLE #ifdef LANGUAGE_MODULE_NAME "

      " D_MODULE " %s

      " #else @@ -832,6 +832,7 @@ void WSContentSendStyle_P(const char* formatP, ...) #ifdef FIRMWARE_MINIMAL WebColor(COL_TEXT_WARNING), #endif + WebColor(COL_TITLE), ModuleName().c_str(), Settings.friendlyname[0]); if (Settings.flag3.gui_hostname_ip) { bool lip = (static_cast(WiFi.localIP()) != 0); From 05ca07271774486703af657d2751b423aa3296ca Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 2 Nov 2019 13:14:38 +0200 Subject: [PATCH 084/196] TasmotaSlave: Add functionality --- tasmota/xdrv_31_tasmota_slave.ino | 176 ++++++++++++++++++++++++------ 1 file changed, 140 insertions(+), 36 deletions(-) diff --git a/tasmota/xdrv_31_tasmota_slave.ino b/tasmota/xdrv_31_tasmota_slave.ino index 3c73d61db..175fb78e1 100644 --- a/tasmota/xdrv_31_tasmota_slave.ino +++ b/tasmota/xdrv_31_tasmota_slave.ino @@ -43,12 +43,14 @@ #define CMND_FEATURES 0x01 #define CMND_JSON 0x02 -#define CMND_SECOND_TICK 0x03 +#define CMND_FUNC_EVERY_SECOND 0x03 +#define CMND_FUNC_EVERY_100_MSECOND 0x04 +#define CMND_SLAVE_SEND 0x05 +#define CMND_PUBLISH_TELE 0x06 #define PARAM_DATA_START 0xFE #define PARAM_DATA_END 0xFF - #include /* @@ -143,24 +145,40 @@ struct TSLAVE { } TSlave; typedef union { - uint16_t data; + uint32_t data; struct { - uint16_t json : 1; // Slave supports providing a JSON for TELEPERIOD - uint16_t second_tick : 1; // Slave supports receiving a FUNC_EVERY_SECOND callback with no response - uint16_t spare2 : 1; - uint16_t spare3 : 1; - uint16_t spare4 : 1; - uint16_t spare5 : 1; - uint16_t spare6 : 1; - uint16_t spare7 : 1; - uint16_t spare8 : 1; - uint16_t spare9 : 1; - uint16_t spare10 : 1; - uint16_t spare11 : 1; - uint16_t spare12 : 1; - uint16_t spare13 : 1; - uint16_t spare14 : 1; - uint16_t spare15 : 1; + uint32_t func_json_append : 1; // Slave supports providing a JSON for TELEPERIOD + uint32_t func_every_second : 1; // Slave supports receiving a FUNC_EVERY_SECOND callback with no response + uint32_t func_every_100_msecond : 1; // Slave supports receiving a FUNC_EVERY_100_MSECOND callback with no response + uint32_t func_slave_send : 1; // Slave supports receiving commands with "slave send xxx" + uint32_t spare4 : 1; + uint32_t spare5 : 1; + uint32_t spare6 : 1; + uint32_t spare7 : 1; + uint32_t spare8 : 1; + uint32_t spare9 : 1; + uint32_t spare10 : 1; + uint32_t spare11 : 1; + uint32_t spare12 : 1; + uint32_t spare13 : 1; + uint32_t spare14 : 1; + uint32_t spare15 : 1; + uint32_t spare16 : 1; + uint32_t spare17 : 1; + uint32_t spare18 : 1; + uint32_t spare19 : 1; + uint32_t spare20 : 1; + uint32_t spare21 : 1; + uint32_t spare22 : 1; + uint32_t spare23 : 1; + uint32_t spare24 : 1; + uint32_t spare25 : 1; + uint32_t spare26 : 1; + uint32_t spare27 : 1; + uint32_t spare28 : 1; + uint32_t spare29 : 1; + uint32_t spare30 : 1; + uint32_t spare31 : 1; }; } TSlaveFeatureCfg; @@ -169,18 +187,17 @@ typedef union { * Tasmota as master */ -struct FEATURES { +struct TSLAVE_FEATURES { uint32_t features_version; TSlaveFeatureCfg features; - uint16_t spare4; } TSlaveSettings; -struct COMMAND { +struct TSLAVE_COMMAND { uint8_t command; uint8_t parameter; uint8_t unused2; uint8_t unused3; -} Command; +} TSlaveCommand; TasmotaSerial *TasmotaSlave_Serial; @@ -444,7 +461,7 @@ void TasmotaSlave_Init(void) TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)); uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)); memcpy(&TSlaveSettings, &buffer, sizeof(TSlaveSettings)); - if (20191026 <= TSlaveSettings.features_version) { + if (20191101 <= TSlaveSettings.features_version) { TSlave.type = true; AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u"), TSlaveSettings.features_version); } @@ -453,7 +470,7 @@ void TasmotaSlave_Init(void) void TasmotaSlave_Show(void) { - if ((TSlave.type) && (TSlaveSettings.features.json)) { + if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) { char buffer[100]; TasmotaSlave_sendCmnd(CMND_JSON, 0); TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1); @@ -465,17 +482,94 @@ void TasmotaSlave_Show(void) void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param) { - Command.command = cmnd; - Command.parameter = param; - char buffer[sizeof(Command)+2]; + TSlaveCommand.command = cmnd; + TSlaveCommand.parameter = param; + char buffer[sizeof(TSlaveCommand)+2]; buffer[0] = CMND_START; - memcpy(&buffer[1], &Command, sizeof(Command)); - buffer[sizeof(Command)+1] = CMND_END; + memcpy(&buffer[1], &TSlaveCommand, sizeof(TSlaveCommand)); + buffer[sizeof(TSlaveCommand)+1] = CMND_END; for (uint8_t ca = 0; ca < sizeof(buffer); ca++) { TasmotaSlave_Serial->write(buffer[ca]); } } +const char kTasmotaSlaveCommands[] PROGMEM = "|" // No prefix + "Slave" ; + +void (* const TasmotaSlaveCommand[])(void) PROGMEM = { + &CmndTasmotaSlave }; + +void CmndTasmotaSlave(void) +{ + if (XdrvMailbox.data_len > 0) { + uint8_t paramcount = 1; + for (uint8_t idx = 0; idx < strlen(XdrvMailbox.data); idx++) { + if ((' ' == XdrvMailbox.data[idx]) || (',' == XdrvMailbox.data[idx])) { + XdrvMailbox.data[idx] = ','; // Make it a comma irrespective whether its a space or a comma + paramcount++; + } + UpperCase(XdrvMailbox.data,XdrvMailbox.data); + + char sub_string[XdrvMailbox.data_len]; + + if (1 == paramcount) { // Single parameter commands + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1), "RESET")) { + TasmotaSlave_Reset(); + TSlave.type = false; // Force redetection + TSlave.waitstate = 7; // give it at least 3 seconds to restart from bootloader + } + } + if (2 == paramcount) { // Double parameter commands + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1), "SEND")) && (TSlaveSettings.features.func_slave_send)) { + char tmp[XdrvMailbox.data_len]; + sprintf(tmp, "%s", subStr(sub_string, XdrvMailbox.data, ",", 2)); + TasmotaSlave_sendCmnd(CMND_SLAVE_SEND, strlen(tmp)); + TasmotaSlave_Serial->write(char(PARAM_DATA_START)); + for (uint8_t ci = 0; ci < strlen(tmp); ci++) { + TasmotaSlave_Serial->write(tmp[ci]); + } + TasmotaSlave_Serial->write(char(PARAM_DATA_END)); + } + } + } + } + ResponseCmndDone(); +} + +void TasmotaSlave_ProcessIn(void) +{ + uint8_t cmnd = TasmotaSlave_Serial->read(); + switch (cmnd) { + case CMND_START: + TasmotaSlave_waitForSerialData(sizeof(TSlaveCommand),50); + uint8_t buffer[sizeof(TSlaveCommand)]; + for (uint8_t idx = 0; idx < sizeof(TSlaveCommand); idx++) { + buffer[idx] = TasmotaSlave_Serial->read(); + } + TasmotaSlave_Serial->read(); // read trailing byte of command + memcpy(&TSlaveCommand, &buffer, sizeof(TSlaveCommand)); + if (CMND_PUBLISH_TELE == TSlaveCommand.command) { // We need to publish stat/ with incoming stream as content + char inbuf[sizeof(TSlaveCommand.parameter)+1]; + TasmotaSlave_waitForSerialData(TSlaveCommand.parameter, 50); + TasmotaSlave_Serial->read(); // Read leading byte + for (uint8_t idx = 0; idx < TSlaveCommand.parameter; idx++) { + inbuf[idx] = TasmotaSlave_Serial->read(); + } + TasmotaSlave_Serial->read(); // Read trailing byte + inbuf[TSlaveCommand.parameter] = '\0'; + Response_P(PSTR("{\"TasmotaSlave\":")); + ResponseAppend_P("%s", inbuf); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + XdrvRulesProcess(); + } + break; + default: + break; + } +} + + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -485,16 +579,26 @@ bool Xdrv31(uint8_t function) bool result = false; switch (function) { - case FUNC_EVERY_SECOND: - TasmotaSlave_Init(); - if (TSlave.type) { - if (TSlaveSettings.features.second_tick) { - TasmotaSlave_sendCmnd(CMND_SECOND_TICK, 0); + case FUNC_EVERY_100_MSECOND: + if ((TSlave.type) && (TSlaveSettings.features.func_every_100_msecond)) { + if (TasmotaSlave_Serial->available()) { + TasmotaSlave_ProcessIn(); + } } + break; + case FUNC_EVERY_SECOND: + if ((TSlave.type) && (TSlaveSettings.features.func_every_second)) { + TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_SECOND, 0); } + TasmotaSlave_Init(); break; case FUNC_JSON_APPEND: - TasmotaSlave_Show(); + if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) { + TasmotaSlave_Show(); + } + break; + case FUNC_COMMAND: + result = DecodeCommand(kTasmotaSlaveCommands, TasmotaSlaveCommand); break; } return result; From ea5c8492a12870427e8ee7e300415e6438bffdf5 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sat, 2 Nov 2019 13:17:39 +0200 Subject: [PATCH 085/196] TasmotaSlave: Add functionality --- tasmota/xdrv_31_tasmota_slave.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_31_tasmota_slave.ino b/tasmota/xdrv_31_tasmota_slave.ino index 175fb78e1..a19f9384f 100644 --- a/tasmota/xdrv_31_tasmota_slave.ino +++ b/tasmota/xdrv_31_tasmota_slave.ino @@ -583,8 +583,8 @@ bool Xdrv31(uint8_t function) if ((TSlave.type) && (TSlaveSettings.features.func_every_100_msecond)) { if (TasmotaSlave_Serial->available()) { TasmotaSlave_ProcessIn(); - } } + } break; case FUNC_EVERY_SECOND: if ((TSlave.type) && (TSlaveSettings.features.func_every_second)) { @@ -604,4 +604,4 @@ bool Xdrv31(uint8_t function) return result; } -#endif // USE_TASMOTA_SLAVE \ No newline at end of file +#endif // USE_TASMOTA_SLAVE From b33886224f606adbb75a22706d6280438b02240f Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 2 Nov 2019 12:21:18 +0100 Subject: [PATCH 086/196] Update IRremoteESP8266 to v2.7.0 --- .../.github/CONTRIBUTING.md | 82 - .../.github/Contributors.md | 20 - .../.github/issue_template.md | 42 - lib/IRremoteESP8266-2.6.5/.gitignore | 53 - lib/IRremoteESP8266-2.6.5/.gitmodules | 4 - lib/IRremoteESP8266-2.6.5/.style.yapf | 3 - lib/IRremoteESP8266-2.6.5/.travis.yml | 74 - .../CommonAcControl/CommonAcControl.ino | 81 - .../examples/IRGCTCPServer/platformio.ini | 18 - .../examples/IRServer/platformio.ini | 18 - .../examples/IRrecvDemo/platformio.ini | 18 - .../examples/IRrecvDump/platformio.ini | 18 - .../examples/IRrecvDumpV2/platformio.ini | 18 - .../examples/IRsendDemo/platformio.ini | 18 - .../examples/IRsendProntoDemo/platformio.ini | 18 - .../JVCPanasonicSendDemo/platformio.ini | 18 - .../examples/LGACSend/platformio.ini | 18 - .../examples/SmartIRRepeater/platformio.ini | 18 - .../examples/TurnOnArgoAC/platformio.ini | 18 - .../examples/TurnOnDaikinAC/platformio.ini | 18 - .../examples/TurnOnFujitsuAC/platformio.ini | 18 - .../TurnOnKelvinatorAC/platformio.ini | 18 - .../TurnOnMitsubishiAC/platformio.ini | 18 - .../TurnOnMitsubishiHeavyAc/platformio.ini | 18 - .../examples/TurnOnPanasonicAC/platformio.ini | 18 - .../examples/TurnOnToshibaAC/platformio.ini | 18 - .../examples/TurnOnTrotecAC/platformio.ini | 18 - lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.cpp | 442 ----- .../src/ir_Mitsubishi.cpp | 811 --------- lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.h | 121 -- .../tools/auto_analyse_raw_data.py | 432 ----- .../tools/auto_analyse_raw_data_test.py | 492 ----- .../CPPLINT.cfg | 0 .../LICENSE.txt | 0 .../README.md | 16 +- lib/IRremoteESP8266-2.7.0/README_fr.md | 83 + .../ReleaseNotes.md | 71 + .../SupportedProtocols.md | 30 +- .../CommonAcControl/CommonAcControl.ino | 72 + .../examples/CommonAcControl/platformio.ini | 5 +- .../ControlSamsungAC/ControlSamsungAC.ino | 0 .../examples/ControlSamsungAC/platformio.ini | 5 +- .../DumbIRRepeater/DumbIRRepeater.ino | 0 .../examples/DumbIRRepeater/platformio.ini | 5 +- .../examples/IRGCSendDemo/IRGCSendDemo.ino | 0 .../examples/IRGCSendDemo/platformio.ini | 5 +- .../examples/IRGCTCPServer/IRGCTCPServer.ino | 0 .../examples/IRGCTCPServer/platformio.ini | 17 + .../examples/IRMQTTServer/IRMQTTServer.h | 51 +- .../examples/IRMQTTServer/IRMQTTServer.ino | 662 ++++--- .../examples/IRMQTTServer/platformio.ini | 15 +- .../examples/IRServer/IRServer.ino | 0 .../examples/IRServer/platformio.ini | 17 + .../examples/IRrecvDemo/IRrecvDemo.ino | 0 .../examples/IRrecvDemo/platformio.ini | 17 + .../examples/IRrecvDump/IRrecvDump.ino | 0 .../examples/IRrecvDump/platformio.ini | 17 + .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 32 +- .../examples/IRrecvDumpV2/platformio.ini | 46 + .../examples/IRsendDemo/IRsendDemo.ino | 0 .../examples/IRsendDemo/platformio.ini | 17 + .../IRsendProntoDemo/IRsendProntoDemo.ino | 6 +- .../examples/IRsendProntoDemo/platformio.ini | 17 + .../JVCPanasonicSendDemo.ino | 0 .../JVCPanasonicSendDemo/platformio.ini | 17 + .../examples/LGACSend/LGACSend.ino | 0 .../examples/LGACSend/platformio.ini | 17 + .../SmartIRRepeater/SmartIRRepeater.ino | 0 .../examples/SmartIRRepeater/platformio.ini | 17 + .../examples/TurnOnArgoAC/TurnOnArgoAC.ino | 0 .../examples/TurnOnArgoAC/platformio.ini | 17 + .../TurnOnDaikinAC/TurnOnDaikinAC.ino | 0 .../examples/TurnOnDaikinAC/platformio.ini | 17 + .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 0 .../examples/TurnOnFujitsuAC/platformio.ini | 17 + .../TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino | 0 .../TurnOnKelvinatorAC/platformio.ini | 17 + .../TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino | 0 .../TurnOnMitsubishiAC/platformio.ini | 17 + .../TurnOnMitsubishiHeavyAc.ino | 0 .../TurnOnMitsubishiHeavyAc/platformio.ini | 17 + .../TurnOnPanasonicAC/TurnOnPanasonicAC.ino | 0 .../examples/TurnOnPanasonicAC/platformio.ini | 17 + .../TurnOnToshibaAC/TurnOnToshibaAC.ino | 0 .../examples/TurnOnToshibaAC/platformio.ini | 17 + .../TurnOnTrotecAC/TurnOnTrotecAC.ino | 0 .../examples/TurnOnTrotecAC/platformio.ini | 17 + .../examples/Web-AC-control/README.md | 43 + .../Web-AC-control/Web-AC-control.ino | 300 ++++ .../examples/Web-AC-control/platformio.ini | 36 + .../examples/Web-AC-control/printscreen.png | Bin 0 -> 25768 bytes .../Web-AC-control/upload/favicon.ico | Bin 0 -> 16446 bytes .../Web-AC-control/upload/level_1_off.svg | 49 + .../Web-AC-control/upload/level_1_on.svg | 49 + .../Web-AC-control/upload/level_2_off.svg | 49 + .../Web-AC-control/upload/level_2_on.svg | 49 + .../Web-AC-control/upload/level_3_off.svg | 49 + .../Web-AC-control/upload/level_3_on.svg | 49 + .../Web-AC-control/upload/level_4_off.svg | 49 + .../Web-AC-control/upload/level_4_on.svg | 49 + .../examples/Web-AC-control/upload/ui.html | 109 ++ .../examples/Web-AC-control/upload/ui.js | 132 ++ .../keywords.txt | 705 ++++++-- .../library.json | 2 +- .../library.properties | 2 +- .../pylintrc | 0 .../src/CPPLINT.cfg | 0 .../src/IRac.cpp | 1140 ++++++++---- .../src/IRac.h | 52 +- .../src/IRrecv.cpp | 21 +- .../src/IRrecv.h | 20 +- .../src/IRremoteESP8266.h | 43 +- .../src/IRsend.cpp | 21 + .../src/IRsend.h | 49 +- lib/IRremoteESP8266-2.7.0/src/IRtext.cpp | 149 ++ lib/IRremoteESP8266-2.7.0/src/IRtext.h | 146 ++ .../src/IRtimer.cpp | 0 .../src/IRtimer.h | 0 .../src/IRutils.cpp | 320 +++- .../src/IRutils.h | 43 + lib/IRremoteESP8266-2.7.0/src/i18n.h | 25 + .../src/ir_Aiwa.cpp | 0 .../src/ir_Amcor.cpp | 71 +- .../src/ir_Amcor.h | 26 +- .../src/ir_Argo.cpp | 151 +- .../src/ir_Argo.h | 80 +- .../src/ir_Carrier.cpp | 0 .../src/ir_Coolix.cpp | 266 +-- .../src/ir_Coolix.h | 51 +- .../src/ir_Daikin.cpp | 1572 ++++++++-------- .../src/ir_Daikin.h | 213 ++- .../src/ir_Denon.cpp | 0 .../src/ir_Dish.cpp | 0 .../src/ir_Electra.cpp | 92 +- .../src/ir_Electra.h | 25 +- .../src/ir_Fujitsu.cpp | 242 ++- .../src/ir_Fujitsu.h | 24 +- .../src/ir_GICable.cpp | 0 .../src/ir_GlobalCache.cpp | 0 .../src/ir_Goodweather.cpp | 183 +- .../src/ir_Goodweather.h | 30 +- .../src/ir_Gree.cpp | 264 ++- .../src/ir_Gree.h | 62 +- .../src/ir_Haier.cpp | 464 +++-- .../src/ir_Haier.h | 89 +- lib/IRremoteESP8266-2.7.0/src/ir_Hitachi.cpp | 753 ++++++++ .../src/ir_Hitachi.h | 77 +- .../src/ir_Inax.cpp | 0 .../src/ir_JVC.cpp | 0 .../src/ir_Kelvinator.cpp | 163 +- .../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 | 133 +- .../src/ir_Midea.h | 32 +- .../src/ir_Mitsubishi.cpp | 1594 +++++++++++++++++ lib/IRremoteESP8266-2.7.0/src/ir_Mitsubishi.h | 312 ++++ .../src/ir_MitsubishiHeavy.cpp | 561 +++--- .../src/ir_MitsubishiHeavy.h | 74 +- .../src/ir_NEC.cpp | 0 .../src/ir_NEC.h | 0 .../src/ir_Neoclima.cpp | 221 +-- .../src/ir_Neoclima.h | 38 +- .../src/ir_Nikai.cpp | 0 .../src/ir_Panasonic.cpp | 410 ++--- .../src/ir_Panasonic.h | 72 +- .../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 | 231 ++- .../src/ir_Samsung.h | 34 +- .../src/ir_Sanyo.cpp | 0 .../src/ir_Sharp.cpp | 118 +- .../src/ir_Sharp.h | 13 +- .../src/ir_Sherwood.cpp | 0 .../src/ir_Sony.cpp | 0 .../src/ir_Tcl.cpp | 197 +- .../src/ir_Tcl.h | 35 +- .../src/ir_Teco.cpp | 185 +- .../src/ir_Teco.h | 51 +- .../src/ir_Toshiba.cpp | 112 +- .../src/ir_Toshiba.h | 16 +- .../src/ir_Trotec.cpp | 97 +- .../src/ir_Trotec.h | 13 +- .../src/ir_Vestel.cpp | 255 ++- .../src/ir_Vestel.h | 15 +- .../src/ir_Whirlpool.cpp | 210 +-- .../src/ir_Whirlpool.h | 31 +- .../src/ir_Whynter.cpp | 0 .../src/locale/README.md | 97 + lib/IRremoteESP8266-2.7.0/src/locale/de-CH.h | 158 ++ lib/IRremoteESP8266-2.7.0/src/locale/de-DE.h | 126 ++ .../src/locale/defaults.h | 440 +++++ lib/IRremoteESP8266-2.7.0/src/locale/en-AU.h | 8 + lib/IRremoteESP8266-2.7.0/src/locale/en-IE.h | 8 + lib/IRremoteESP8266-2.7.0/src/locale/en-UK.h | 8 + lib/IRremoteESP8266-2.7.0/src/locale/en-US.h | 13 + lib/IRremoteESP8266-2.7.0/src/locale/es-ES.h | 134 ++ lib/IRremoteESP8266-2.7.0/src/locale/fr-FR.h | 115 ++ .../test/IRac_test.cpp | 281 ++- .../test/IRrecv_test.cpp | 0 .../test/IRrecv_test.h | 0 .../test/IRsend_test.cpp | 0 .../test/IRsend_test.h | 0 .../test/IRutils_test.cpp | 187 +- .../test/Makefile | 21 +- .../test/ir_Aiwa_test.cpp | 0 .../test/ir_Amcor_test.cpp | 6 +- .../test/ir_Argo_test.cpp | 12 +- .../test/ir_Carrier_test.cpp | 0 .../test/ir_Coolix_test.cpp | 57 +- .../test/ir_Daikin_test.cpp | 574 +++++- .../test/ir_Denon_test.cpp | 0 .../test/ir_Dish_test.cpp | 0 .../test/ir_Electra_test.cpp | 8 +- .../test/ir_Fujitsu_test.cpp | 198 +- .../test/ir_GICable_test.cpp | 0 .../test/ir_GlobalCache_test.cpp | 0 .../test/ir_Goodweather_test.cpp | 40 +- .../test/ir_Gree_test.cpp | 16 +- .../test/ir_Haier_test.cpp | 98 +- .../test/ir_Hitachi_test.cpp | 314 +++- .../test/ir_Inax_test.cpp | 0 .../test/ir_JVC_test.cpp | 0 .../test/ir_Kelvinator_test.cpp | 12 +- .../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 | 49 +- .../test/ir_MitsubishiHeavy_test.cpp | 74 +- .../test/ir_Mitsubishi_test.cpp | 565 +++++- .../test/ir_NEC_test.cpp | 0 .../test/ir_Neoclima_test.cpp | 2 +- .../test/ir_Nikai_test.cpp | 0 .../test/ir_Panasonic_test.cpp | 81 +- .../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 | 70 +- .../test/ir_Sanyo_test.cpp | 0 .../test/ir_Sharp_test.cpp | 26 +- .../test/ir_Sherwood_test.cpp | 0 .../test/ir_Sony_test.cpp | 0 .../test/ir_Tcl_test.cpp | 44 +- .../test/ir_Teco_test.cpp | 74 +- .../test/ir_Toshiba_test.cpp | 6 +- .../test/ir_Trotec_test.cpp | 4 +- .../test/ir_Vestel_test.cpp | 30 +- .../test/ir_Whirlpool_test.cpp | 20 +- .../test/ir_Whynter_test.cpp | 0 .../tools/Makefile | 12 +- .../tools/RawToGlobalCache.sh | 0 .../tools/auto_analyse_raw_data.py | 729 ++++++++ .../tools/auto_analyse_raw_data_test.py | 1170 ++++++++++++ .../tools/gc_decode.cpp | 50 +- .../tools/generate_irtext_h.sh | 36 + .../tools/mkkeywords | 0 .../tools/mode2_decode.cpp | 0 .../tools/scrape_supported_devices.py | 0 tasmota/_changelog.ino | 1 + 271 files changed, 15901 insertions(+), 8190 deletions(-) delete mode 100755 lib/IRremoteESP8266-2.6.5/.github/CONTRIBUTING.md delete mode 100755 lib/IRremoteESP8266-2.6.5/.github/Contributors.md delete mode 100755 lib/IRremoteESP8266-2.6.5/.github/issue_template.md delete mode 100755 lib/IRremoteESP8266-2.6.5/.gitignore delete mode 100755 lib/IRremoteESP8266-2.6.5/.gitmodules delete mode 100755 lib/IRremoteESP8266-2.6.5/.style.yapf delete mode 100755 lib/IRremoteESP8266-2.6.5/.travis.yml delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/CommonAcControl.ino delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/IRServer/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/LGACSend/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/platformio.ini delete mode 100755 lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.cpp delete mode 100755 lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.cpp delete mode 100755 lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.h delete mode 100755 lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data.py delete mode 100755 lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data_test.py rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/CPPLINT.cfg (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/LICENSE.txt (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/README.md (90%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/README_fr.md rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/ReleaseNotes.md (86%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/SupportedProtocols.md (89%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/CommonAcControl/CommonAcControl.ino rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/CommonAcControl/platformio.ini (86%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/ControlSamsungAC/ControlSamsungAC.ino (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/ControlSamsungAC/platformio.ini (86%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/DumbIRRepeater/DumbIRRepeater.ino (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/DumbIRRepeater/platformio.ini (86%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRGCSendDemo/IRGCSendDemo.ino (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRGCSendDemo/platformio.ini (86%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRGCTCPServer/IRGCTCPServer.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/IRGCTCPServer/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRMQTTServer/IRMQTTServer.h (88%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRMQTTServer/IRMQTTServer.ino (84%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRMQTTServer/platformio.ini (82%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRServer/IRServer.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/IRServer/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRrecvDemo/IRrecvDemo.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/IRrecvDemo/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRrecvDump/IRrecvDump.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/IRrecvDump/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRrecvDumpV2/IRrecvDumpV2.ino (87%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/IRrecvDumpV2/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRsendDemo/IRsendDemo.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/IRsendDemo/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/IRsendProntoDemo/IRsendProntoDemo.ino (96%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/IRsendProntoDemo/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/JVCPanasonicSendDemo/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/LGACSend/LGACSend.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/LGACSend/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/SmartIRRepeater/SmartIRRepeater.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/SmartIRRepeater/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/TurnOnArgoAC/TurnOnArgoAC.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/TurnOnArgoAC/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/TurnOnDaikinAC/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/TurnOnFujitsuAC/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/TurnOnKelvinatorAC/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiAC/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/TurnOnPanasonicAC/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/TurnOnToshibaAC/platformio.ini rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/examples/TurnOnTrotecAC/platformio.ini create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/README.md create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/Web-AC-control.ino create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/platformio.ini create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/printscreen.png create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/favicon.ico create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_1_off.svg create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_1_on.svg create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_2_off.svg create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_2_on.svg create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_3_off.svg create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_3_on.svg create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_4_off.svg create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_4_on.svg create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/ui.html create mode 100644 lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/ui.js rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/keywords.txt (80%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/library.json (97%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/library.properties (97%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/pylintrc (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/CPPLINT.cfg (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRac.cpp (75%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRac.h (84%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRrecv.cpp (98%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRrecv.h (96%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRremoteESP8266.h (95%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRsend.cpp (98%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRsend.h (92%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/src/IRtext.cpp create mode 100644 lib/IRremoteESP8266-2.7.0/src/IRtext.h rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRtimer.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRtimer.h (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRutils.cpp (70%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/IRutils.h (57%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/src/i18n.h rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Aiwa.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Amcor.cpp (82%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Amcor.h (83%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Argo.cpp (76%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Argo.h (70%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Carrier.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Coolix.cpp (73%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Coolix.h (68%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Daikin.cpp (70%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Daikin.h (76%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Denon.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Dish.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Electra.cpp (79%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Electra.h (78%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Fujitsu.cpp (76%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Fujitsu.h (88%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_GICable.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_GlobalCache.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Goodweather.cpp (72%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Goodweather.h (81%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Gree.cpp (71%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Gree.h (72%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Haier.cpp (67%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Haier.h (80%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/src/ir_Hitachi.cpp rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Hitachi.h (51%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Inax.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_JVC.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Kelvinator.cpp (77%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Kelvinator.h (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_LG.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_LG.h (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Lasertag.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Lego.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Lutron.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_MWM.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Magiquest.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Magiquest.h (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Midea.cpp (82%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Midea.h (84%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/src/ir_Mitsubishi.cpp create mode 100644 lib/IRremoteESP8266-2.7.0/src/ir_Mitsubishi.h rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_MitsubishiHeavy.cpp (63%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_MitsubishiHeavy.h (77%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_NEC.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_NEC.h (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Neoclima.cpp (69%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Neoclima.h (83%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Nikai.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Panasonic.cpp (72%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Panasonic.h (70%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Pioneer.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Pronto.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_RC5_RC6.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_RCMM.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Samsung.cpp (80%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Samsung.h (77%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Sanyo.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Sharp.cpp (85%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Sharp.h (87%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Sherwood.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Sony.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Tcl.cpp (59%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Tcl.h (73%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Teco.cpp (60%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Teco.h (70%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Toshiba.cpp (80%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Toshiba.h (84%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Trotec.cpp (78%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Trotec.h (87%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Vestel.cpp (64%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Vestel.h (89%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Whirlpool.cpp (76%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Whirlpool.h (87%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/src/ir_Whynter.cpp (100%) mode change 100755 => 100644 create mode 100644 lib/IRremoteESP8266-2.7.0/src/locale/README.md create mode 100644 lib/IRremoteESP8266-2.7.0/src/locale/de-CH.h create mode 100644 lib/IRremoteESP8266-2.7.0/src/locale/de-DE.h create mode 100644 lib/IRremoteESP8266-2.7.0/src/locale/defaults.h create mode 100644 lib/IRremoteESP8266-2.7.0/src/locale/en-AU.h create mode 100644 lib/IRremoteESP8266-2.7.0/src/locale/en-IE.h create mode 100644 lib/IRremoteESP8266-2.7.0/src/locale/en-UK.h create mode 100644 lib/IRremoteESP8266-2.7.0/src/locale/en-US.h create mode 100644 lib/IRremoteESP8266-2.7.0/src/locale/es-ES.h create mode 100644 lib/IRremoteESP8266-2.7.0/src/locale/fr-FR.h rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/IRac_test.cpp (83%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/IRrecv_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/IRrecv_test.h (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/IRsend_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/IRsend_test.h (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/IRutils_test.cpp (77%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/Makefile (96%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Aiwa_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Amcor_test.cpp (98%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Argo_test.cpp (95%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Carrier_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Coolix_test.cpp (96%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Daikin_test.cpp (85%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Denon_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Dish_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Electra_test.cpp (97%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Fujitsu_test.cpp (81%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_GICable_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_GlobalCache_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Goodweather_test.cpp (93%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Gree_test.cpp (97%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Haier_test.cpp (92%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Hitachi_test.cpp (74%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Inax_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_JVC_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Kelvinator_test.cpp (98%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_LG_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Lasertag_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Lego_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Lutron_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_MWM_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Magiquest_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Midea_test.cpp (94%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_MitsubishiHeavy_test.cpp (91%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Mitsubishi_test.cpp (72%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_NEC_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Neoclima_test.cpp (99%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Nikai_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Panasonic_test.cpp (94%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Pioneer_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Pronto_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_RC5_RC6_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_RCMM_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Samsung_test.cpp (96%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Sanyo_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Sharp_test.cpp (96%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Sherwood_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Sony_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Tcl_test.cpp (89%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Teco_test.cpp (82%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Toshiba_test.cpp (99%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Trotec_test.cpp (97%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Vestel_test.cpp (93%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Whirlpool_test.cpp (97%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/test/ir_Whynter_test.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/tools/Makefile (94%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/tools/RawToGlobalCache.sh (100%) create mode 100755 lib/IRremoteESP8266-2.7.0/tools/auto_analyse_raw_data.py create mode 100755 lib/IRremoteESP8266-2.7.0/tools/auto_analyse_raw_data_test.py rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/tools/gc_decode.cpp (65%) mode change 100755 => 100644 create mode 100755 lib/IRremoteESP8266-2.7.0/tools/generate_irtext_h.sh rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/tools/mkkeywords (100%) rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/tools/mode2_decode.cpp (100%) mode change 100755 => 100644 rename lib/{IRremoteESP8266-2.6.5 => IRremoteESP8266-2.7.0}/tools/scrape_supported_devices.py (100%) diff --git a/lib/IRremoteESP8266-2.6.5/.github/CONTRIBUTING.md b/lib/IRremoteESP8266-2.6.5/.github/CONTRIBUTING.md deleted file mode 100755 index 20bb97d94..000000000 --- a/lib/IRremoteESP8266-2.6.5/.github/CONTRIBUTING.md +++ /dev/null @@ -1,82 +0,0 @@ -# Contributing to the IRremoteESP8266 library - -:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: - -The following is a set of guidelines for contributing to the IRremoteESP8266 library, hosted on GitHub. These are guidelines, [not rules](http://imgur.com/mSHi8). Use your best judgment, and feel free to propose changes to this document in a pull request. - -#### Table Of Contents - -[Code of Conduct](#code-of-conduct) - -[How Can I Contribute?](#how-can-i-contribute) - * [Reporting Bugs](#reporting-bugs) - * [Pull Requests](#pull-requests) - -[Styleguides](#styleguides) - * [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) - * [Git Commit Messages](#git-commit-messages) - - -## Code of Conduct - -This project and everyone participating in it is governed by the principle of ["Be excellent to each other"](http://www.imdb.com/title/tt0096928/quotes). That's it. TL;DR: _Don't be a jerk._ - -## How Can I Contribute? - -### Reporting Bugs - -This section guides you through submitting a bug report for the library. Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior :computer: :computer:, and find related reports :mag_right:. - -Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as much detail as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](issue_template.md), the information it asks for helps us resolve issues faster. - -> **Note:** If you find a **Closed** issue that seems like it's the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. - -#### Before Submitting A Bug Report - -* **Check the [Troubleshooting Guide](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide).** You might be able to find the cause of the problem and fix it yourself. Most importantly, check if you can reproduce the problem in the latest version (a.k.a. 'master') of the library. -* **Perform a [cursory search](https://github.com/issues?q=+is%3Aissue+repo%3Acrankyoldgit/IRremoteESP8266)** to see if the problem is already reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one. - -#### How Do I Submit A (Good) Bug Report? - -Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Create an issue and provide the following information by filling in [the template](issue_template.md). - -Explain the problem and include any additional details to help maintainers reproduce the problem: - -* **Use a clear and descriptive title** for the issue to identify the problem. -* **Describe the exact steps which reproduce the problem** in as much detail as possible. -* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). -* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. -* **Explain which behavior you expected to see instead and why.** -* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below. - -Provide more context by answering these questions: - -* **Can you reproduce the problem in one of the code examples?** -* **Did the problem start happening recently** (e.g. after updating to a new version of Arduino or the library) or was this always a problem? -* If the problem started happening recently, **can you reproduce the problem in an older version of the library?** What's the most recent version in which the problem doesn't happen? You can download older versions of the library from [the releases page](https://github.com/crankyoldgit/IRremoteESP8266/releases). -* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens. - -Include details about your configuration, circuit and environment: - -* **Which version of the library are you using?** You can get the exact version by inspecting the `library.json` file in the root directory of the library. -* **What board are you running this on?** - -### Pull Requests - -* Do not include issue numbers in the PR title -* Include as much data and comments as practicle. -* Follow the [C++ style guide](https://google.github.io/styleguide/cppguide.html). -* Please write or ensure Unit Tests cover the change you are making, if you can. -* End all files with a newline -* Avoid platform-dependent code. -* Use c98 types where possible for better portablity. -* In almost all cases, code & documentation should be peer-reviewed by at least one other contributor. -* The code should pass all the existing testing infrastructure in Travis. e.g. Unit tests, cpplint, and basic compilation. -* State if you have tested this under real conditions if you have, and what other tests you may have carried out. - -### Git Commit Messages - -* Limit the first line to 72 characters or less -* Reference issues and pull requests liberally after the first line -* Humour is always acceptable. Be liberal with it. ;-) -* While not required, a comprehensive description of all the changes in the PR is best. diff --git a/lib/IRremoteESP8266-2.6.5/.github/Contributors.md b/lib/IRremoteESP8266-2.6.5/.github/Contributors.md deleted file mode 100755 index a4958fe70..000000000 --- a/lib/IRremoteESP8266-2.6.5/.github/Contributors.md +++ /dev/null @@ -1,20 +0,0 @@ -## Contributors of this project -### Main contributors & maintainers -- [Mark Szabo](https://github.com/markszabo/) : Initial IR sending on ESP8266 -- [Sébastien Warin](https://github.com/sebastienwarin/) (http://sebastien.warin.fr) : Initial IR receiving on ESP8266 -- [David Conran](https://github.com/crankyoldgit/) : ESP32 support and pretty much everything else. -- [Roi Dayan](https://github.com/roidayan/) -- [Marcos de Alcântara Marinho](https://github.com/marcosamarinho/) -- [Massimiliano Pinto](https://github.com/pintomax/) -- [Darsh Patel](https://github.com/darshkpatel/) -- [Jonny Graham](https://github.com/jonnygraham/) -- [Stu Fisher](https://github.com/stufisher/) -- [Jorge Cisneros](https://github.com/jorgecis/) -- [Denes Varga](https://github.com/denxhun/) -- [Brett T. Warden](https://github.com/bwarden/) -- [Fabien Valthier](https://github.com/hcoohb) -- [Ajay Pala](https://github.com/ajaypala/) - -All contributors can be found on the [contributors site](https://github.com/crankyoldgit/IRremoteESP8266/graphs/contributors). - -### Contributors of the [original project](https://github.com/z3t0/Arduino-IRremote) can be found on the [original project's contributors page](https://github.com/z3t0/Arduino-IRremote/blob/master/Contributors.md) diff --git a/lib/IRremoteESP8266-2.6.5/.github/issue_template.md b/lib/IRremoteESP8266-2.6.5/.github/issue_template.md deleted file mode 100755 index d9b80dab6..000000000 --- a/lib/IRremoteESP8266-2.6.5/.github/issue_template.md +++ /dev/null @@ -1,42 +0,0 @@ -_(Please use this template for reporting issues. You can delete what ever is not relevant. Giving us this information will help us help you faster. Please also read the [FAQ](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions) & [Troubleshooting Guide](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide). Your problem may already have an answer there.)_ - -### Version/revision of the library used -_Typically located in the `library.json` & `src/IRremoteESP8266.h` files in the root directory of the library. -e.g. v2.0.0, or 'master' as at 1st of June, 2017. etc._ - -### Expected behavior -_What steps did you do and what should it have done?_ - -e.g. -1. Initialise the IRsend class. -2. IRsend.sendFoobar(0xdeadbeef); -3. Foobar branded BBQ turns on and cooks me some ribs. - -### Actual behavior -_What steps did you do, and what did or didn't actually happen?_ - -e.g. -1. Initialise the IRsend class. -2. IRsend.sendFoobar(0xdeadbeef); -3. Foobar BBQ went into Cow(er)-saving mode and fried me a couple of eggs instead. - -#### Output of raw data from IRrecvDumpV2.ino (if applicable) -_Include some raw dumps of what the device saw._ - -### Steps to reproduce the behavior -_What can we do to (pref. reliably) repeat what is happening?_ - -#### Example code used -_Include all relevant code snippets or links to the actual code files. Tip: [How to quote your code so it is still readable](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code)._ - -#### Circuit diagram and hardware used (if applicable) -_Link to an image of the circuit diagram used. Part number of the IR receiver module etc. ESP8266 or ESP32 board type._ - -### I have followed the steps in the [Troubleshooting Guide](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide) & read the [FAQ](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions) -_Yes/No._ - -### Has this library/code previously worked as expected for you? -_Yes/No. If "Yes", which version last worked for you?_ - -### Other useful information -_More information is always welcome. Be verbose._ diff --git a/lib/IRremoteESP8266-2.6.5/.gitignore b/lib/IRremoteESP8266-2.6.5/.gitignore deleted file mode 100755 index c02171953..000000000 --- a/lib/IRremoteESP8266-2.6.5/.gitignore +++ /dev/null @@ -1,53 +0,0 @@ -#----------------------------------------# -# .gitingore for IRremoteESP8266 library # -#----------------------------------------# - -### Files to ignore. - -## Editors -# vi/vim -**/*.swp - -# vscode -.vscode - -## Build environments -# Platformio -**/.pio/ -**/.pioenvs/ -**/.piolibdeps/ -**/.clang_complete -**/.gcc-flags.json -examples/**/lib -examples/**/.travis.yml -examples/**/.gitignore -lib/readme.txt -lib/googletest/**/* - -# GCC pre-compiled headers. -**/*.gch - -# Python compiled files -**/*.pyc - -# Unit Test builds -test/*.o -test/*.a -test/*_test - -# Tools builds -tools/*.o -tools/*.a -tools/gc_decode -tools/mode2_decode - -.pioenvs -.piolibdeps -.clang_complete -.gcc-flags.json - -#Cygwin builds -*.exe - -# Mac extended attributes -.DS_Store diff --git a/lib/IRremoteESP8266-2.6.5/.gitmodules b/lib/IRremoteESP8266-2.6.5/.gitmodules deleted file mode 100755 index c28fe0509..000000000 --- a/lib/IRremoteESP8266-2.6.5/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "lib/googletest"] - path = lib/googletest - url = https://github.com/google/googletest.git - branch = v1.8.x diff --git a/lib/IRremoteESP8266-2.6.5/.style.yapf b/lib/IRremoteESP8266-2.6.5/.style.yapf deleted file mode 100755 index 65fa0ee33..000000000 --- a/lib/IRremoteESP8266-2.6.5/.style.yapf +++ /dev/null @@ -1,3 +0,0 @@ -[style] -based_on_style: google -indent_width: 2 diff --git a/lib/IRremoteESP8266-2.6.5/.travis.yml b/lib/IRremoteESP8266-2.6.5/.travis.yml deleted file mode 100755 index e8bf3d832..000000000 --- a/lib/IRremoteESP8266-2.6.5/.travis.yml +++ /dev/null @@ -1,74 +0,0 @@ -language: c -env: - - BD=esp8266:esp8266:nodemcuv2:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled - # - BD=esp8266:esp8266:d1_mini:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled -before_install: - - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" - - sleep 3 - - export DISPLAY=:1.0 - - wget http://downloads.arduino.cc/arduino-1.8.8-linux64.tar.xz - - tar xf arduino-1.8.8-linux64.tar.xz - - sudo mv arduino-1.8.8 /usr/local/share/arduino - - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino - - wget https://raw.githubusercontent.com/google/styleguide/gh-pages/cpplint/cpplint.py -install: - - ln -s $PWD /usr/local/share/arduino/libraries/ - - git clone https://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WiFiManager - - git clone https://github.com/knolleary/pubsubclient.git /usr/local/share/arduino/libraries/PubSubClient - - git clone https://github.com/bblanchon/ArduinoJson.git --branch 5.x /usr/local/share/arduino/libraries/ArduinoJson - - arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs - - arduino --install-boards esp8266:esp8266 - - arduino --board $BD --save-prefs - - arduino --pref "compiler.warning_level=all" --save-prefs - - sudo apt-get install jq - - sudo apt-get purge python-enum34 - - sudo apt-get install pylint3 -script: echo Running checks -notifications: - email: - on_success: change - on_failure: change -jobs: - include: - - script: - # Check that everything compiles. (Part 1) - - arduino --verify --board $BD $PWD/examples/IRrecvDemo/IRrecvDemo.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/IRGCSendDemo/IRGCSendDemo.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/IRGCTCPServer/IRGCTCPServer.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/IRServer/IRServer.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/IRrecvDumpV2/IRrecvDumpV2.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/IRsendDemo/IRsendDemo.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino 2> /dev/null - - script: - # Check that everything compiles. (Part 2) - - arduino --verify --board $BD $PWD/examples/IRsendProntoDemo/IRsendProntoDemo.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/LGACSend/LGACSend.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/TurnOnArgoAC/TurnOnArgoAC.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/IRMQTTServer/IRMQTTServer.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/ControlSamsungAC/ControlSamsungAC.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/DumbIRRepeater/DumbIRRepeater.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/SmartIRRepeater/SmartIRRepeater.ino 2> /dev/null - - arduino --verify --board $BD $PWD/examples/CommonAcControl/CommonAcControl.ino 2> /dev/null - - script: - # Check the version numbers match. - - LIB_VERSION=$(egrep "^#define\s+_IRREMOTEESP8266_VERSION_\s+" src/IRremoteESP8266.h | cut -d\" -f2) - - test ${LIB_VERSION} == "$(jq -r .version library.json)" - - grep -q "^version=${LIB_VERSION}$" library.properties - # Check the tools programs compile. - - (cd tools; make all) - # Check for lint issues. - - shopt -s nullglob - - python cpplint.py --extensions=c,cc,cpp,ino --headers=h,hpp {src,test,tools}/*.{h,c,cc,cpp,hpp,ino} examples/*/*.{h,c,cc,cpp,hpp,ino} - - pylint3 -d F0001 {src,test,tools}/*.py - - shopt -u nullglob - # Build and run the unit tests. - - (cd test; make run) - - (cd tools; make run_tests) diff --git a/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/CommonAcControl.ino b/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/CommonAcControl.ino deleted file mode 100755 index 6f0416b51..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/CommonAcControl.ino +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright 2019 David Conran -* -* This example code demonstrates how to use the "Common" IRac class to control -* various air conditions. The IRac class does not support all the features -* for every protocol. Some have more detailed support that what the "Common" -* interface offers, and some only have a limited subset of the "Common" options. -* -* This example code will: -* o Try to turn on, then off every fully supported A/C protocol we know of. -* o It will try to put the A/C unit into Cooling mode at 25C, with a medium -* fan speed, and no fan swinging. -* Note: Some protocols support multiple models, only the first model is tried. -* -*/ -#include -#include -#include -#include - -const uint16_t kIrLed = 4; // The ESP GPIO pin to use that controls the IR LED. -IRac ac(kIrLed); // Create a A/C object using GPIO to sending messages with. -stdAc::state_t state; // Where we will store the desired state of the A/C. -stdAc::state_t prev; // Where we will store the previous state of the A/C. - -void setup() { - Serial.begin(115200); - delay(200); - - // Set up what we want to send. - // See state_t, opmode_t, fanspeed_t, swingv_t, & swingh_t in IRsend.h for - // all the various options. - state.protocol = decode_type_t::DAIKIN; // Set a protocol to use. - state.model = 1; // Some A/C's have different models. Let's try using just 1. - state.mode = stdAc::opmode_t::kCool; // Run in cool mode initially. - state.celsius = true; // Use Celsius for units of temp. False = Fahrenheit - state.degrees = 25; // 25 degrees. - state.fanspeed = stdAc::fanspeed_t::kMedium; // Start with the fan at medium. - state.swingv = stdAc::swingv_t::kOff; // Don't swing the fan up or down. - state.swingh = stdAc::swingh_t::kOff; // Don't swing the fan left or right. - state.light = false; // Turn off any LED/Lights/Display that we can. - state.beep = false; // Turn off any beep from the A/C if we can. - state.econo = false; // Turn off any economy modes if we can. - state.filter = false; // Turn off any Ion/Mold/Health filters if we can. - state.turbo = false; // Don't use any turbo/powerful/etc modes. - state.quiet = false; // Don't use any quiet/silent/etc modes. - state.sleep = -1; // Don't set any sleep time or modes. - state.clean = false; // Turn off any Cleaning options if we can. - state.clock = -1; // Don't set any current time if we can avoid it. - state.power = false; // Initially start with the unit off. - - prev = state; // Make sure we have a valid previous state. -} - -void loop() { - // For every protocol the library has ... - for (int i = 1; i < kLastDecodeType; i++) { - decode_type_t protocol = (decode_type_t)i; - // If the protocol is supported by the IRac class ... - if (ac.isProtocolSupported(protocol)) { - state.protocol = protocol; // Change the protocol used. - - Serial.println("Protocol " + String(protocol) + " / " + - typeToString(protocol)); - state.power = true; // We want to turn on the A/C unit. - // Have the IRac class create and send a message. - // We need a `prev` state as some A/Cs use toggle messages. - // e.g. On & Off are the same message. When given the previous state, - // it will try to do the correct thing for you. - ac.sendAc(state, &prev); // Construct and send the message. - Serial.println("Sent a message to turn ON the A/C unit."); - prev = state; // Copy new state over the previous one. - delay(5000); // Wait 5 seconds. - state.power = false; // Now we want to turn the A/C off. - ac.sendAc(state, &prev); // Construct and send the message. - Serial.println("Sent a message to turn OFF the A/C unit."); - prev = state; // Copy new state over the previous one. - delay(1000); // Wait 1 second. - } - } - Serial.println("Starting from the begining again ..."); -} diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRServer/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRServer/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/IRServer/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/LGACSend/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/LGACSend/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/LGACSend/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/platformio.ini deleted file mode 100755 index 1aba0afcc..000000000 --- a/lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -[platformio] -src_dir = . - -[env] -lib_extra_dirs = ../../ -lib_ldf_mode = deep+ -lib_ignore = examples -build_flags = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 - -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.cpp deleted file mode 100755 index 0550816a9..000000000 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.cpp +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2018 David Conran -// -// Code to emulate Hitachi protocol compatible devices. -// Should be compatible with: -// * Hitachi RAS-35THA6 remote -// - -#include "ir_Hitachi.h" -#include -#ifndef ARDUINO -#include -#endif -#include "IRrecv.h" -#include "IRremoteESP8266.h" -#include "IRsend.h" -#include "IRutils.h" - -// Constants -// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/417 -const uint16_t kHitachiAcHdrMark = 3300; -const uint16_t kHitachiAcHdrSpace = 1700; -const uint16_t kHitachiAc1HdrMark = 3400; -const uint16_t kHitachiAc1HdrSpace = 3400; -const uint16_t kHitachiAcBitMark = 400; -const uint16_t kHitachiAcOneSpace = 1250; -const uint16_t kHitachiAcZeroSpace = 500; -const uint32_t kHitachiAcMinGap = kDefaultMessageGap; // Just a guess. - -using irutils::addBoolToString; -using irutils::addIntToString; -using irutils::addLabeledString; -using irutils::addModeToString; -using irutils::addFanToString; -using irutils::addTempToString; - -#if (SEND_HITACHI_AC || SEND_HITACHI_AC2) -// Send a Hitachi A/C message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=kHitachiAcStateLength) -// repeat: Nr. of times the message is to be repeated. (Default = 0). -// -// Status: ALPHA / Untested. -// -// Ref: -// https://github.com/crankyoldgit/IRremoteESP8266/issues/417 -void IRsend::sendHitachiAC(const unsigned char data[], const uint16_t nbytes, - const uint16_t repeat) { - if (nbytes < kHitachiAcStateLength) - return; // Not enough bytes to send a proper message. - sendGeneric(kHitachiAcHdrMark, kHitachiAcHdrSpace, kHitachiAcBitMark, - kHitachiAcOneSpace, kHitachiAcBitMark, kHitachiAcZeroSpace, - kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, 38, true, - repeat, 50); -} -#endif // (SEND_HITACHI_AC || SEND_HITACHI_AC2) - -#if SEND_HITACHI_AC1 -// Send a Hitachi A/C 13-byte message. -// -// For devices: -// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=kHitachiAc1StateLength) -// repeat: Nr. of times the message is to be repeated. (Default = 0). -// -// Status: BETA / Appears to work. -// -// Ref: -// https://github.com/crankyoldgit/IRremoteESP8266/issues/453 -// Basically the same as sendHitatchiAC() except different size and header. -void IRsend::sendHitachiAC1(const unsigned char data[], const uint16_t nbytes, - const uint16_t repeat) { - if (nbytes < kHitachiAc1StateLength) - return; // Not enough bytes to send a proper message. - sendGeneric(kHitachiAc1HdrMark, kHitachiAc1HdrSpace, kHitachiAcBitMark, - kHitachiAcOneSpace, kHitachiAcBitMark, kHitachiAcZeroSpace, - kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, 38, true, - repeat, 50); -} -#endif // SEND_HITACHI_AC1 - -#if SEND_HITACHI_AC2 -// Send a Hitachi A/C 53-byte message. -// -// For devices: -// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=kHitachiAc2StateLength) -// repeat: Nr. of times the message is to be repeated. (Default = 0). -// -// Status: BETA / Appears to work. -// -// Ref: -// https://github.com/crankyoldgit/IRremoteESP8266/issues/417 -// Basically the same as sendHitatchiAC() except different size. -void IRsend::sendHitachiAC2(const unsigned char data[], const uint16_t nbytes, - const uint16_t repeat) { - if (nbytes < kHitachiAc2StateLength) - return; // Not enough bytes to send a proper message. - sendHitachiAC(data, nbytes, repeat); -} -#endif // SEND_HITACHI_AC2 - -// Class for handling the remote control on a Hitachi 28 byte A/C message. -// Inspired by: -// https://github.com/ToniA/arduino-heatpumpir/blob/master/HitachiHeatpumpIR.cpp - -IRHitachiAc::IRHitachiAc(const uint16_t pin, const bool inverted, - const bool use_modulation) - : _irsend(pin, inverted, use_modulation) { stateReset(); } - -void IRHitachiAc::stateReset(void) { - remote_state[0] = 0x80; - remote_state[1] = 0x08; - remote_state[2] = 0x0C; - remote_state[3] = 0x02; - remote_state[4] = 0xFD; - remote_state[5] = 0x80; - remote_state[6] = 0x7F; - remote_state[7] = 0x88; - remote_state[8] = 0x48; - remote_state[9] = 0x10; - for (uint8_t i = 10; i < kHitachiAcStateLength; i++) remote_state[i] = 0x00; - remote_state[14] = 0x60; - remote_state[15] = 0x60; - remote_state[24] = 0x80; - setTemp(23); -} - -void IRHitachiAc::begin(void) { _irsend.begin(); } - -uint8_t IRHitachiAc::calcChecksum(const uint8_t state[], - const uint16_t length) { - int8_t sum = 62; - for (uint16_t i = 0; i < length - 1; i++) sum -= reverseBits(state[i], 8); - return reverseBits((uint8_t)sum, 8); -} - -void IRHitachiAc::checksum(const uint16_t length) { - remote_state[length - 1] = calcChecksum(remote_state, length); -} - -bool IRHitachiAc::validChecksum(const uint8_t state[], const uint16_t length) { - if (length < 2) return true; // Assume true for lengths that are too short. - return (state[length - 1] == calcChecksum(state, length)); -} - -uint8_t *IRHitachiAc::getRaw(void) { - checksum(); - return remote_state; -} - -void IRHitachiAc::setRaw(const uint8_t new_code[], const uint16_t length) { - for (uint8_t i = 0; i < length && i < kHitachiAcStateLength; i++) - remote_state[i] = new_code[i]; -} - -#if SEND_HITACHI_AC -void IRHitachiAc::send(const uint16_t repeat) { - checksum(); - _irsend.sendHitachiAC(remote_state, kHitachiAcStateLength, repeat); -} -#endif // SEND_HITACHI_AC - -bool IRHitachiAc::getPower(void) { return (remote_state[17] & 0x01); } - -void IRHitachiAc::setPower(const bool on) { - if (on) - remote_state[17] |= 0x01; - else - remote_state[17] &= 0xFE; -} - -void IRHitachiAc::on(void) { setPower(true); } - -void IRHitachiAc::off(void) { setPower(false); } - -uint8_t IRHitachiAc::getMode(void) { return reverseBits(remote_state[10], 8); } - -void IRHitachiAc::setMode(const uint8_t mode) { - uint8_t newmode = mode; - switch (mode) { - case kHitachiAcFan: - // Fan mode sets a special temp. - setTemp(64); - break; - case kHitachiAcAuto: - case kHitachiAcHeat: - case kHitachiAcCool: - case kHitachiAcDry: - break; - default: - newmode = kHitachiAcAuto; - } - remote_state[10] = reverseBits(newmode, 8); - if (mode != kHitachiAcFan) setTemp(_previoustemp); - setFan(getFan()); // Reset the fan speed after the mode change. -} - -uint8_t IRHitachiAc::getTemp(void) { - return reverseBits(remote_state[11], 8) >> 1; -} - -void IRHitachiAc::setTemp(const uint8_t celsius) { - uint8_t temp; - if (celsius != 64) _previoustemp = celsius; - switch (celsius) { - case 64: - temp = celsius; - break; - default: - temp = std::min(celsius, kHitachiAcMaxTemp); - temp = std::max(temp, kHitachiAcMinTemp); - } - remote_state[11] = reverseBits(temp << 1, 8); - if (temp == kHitachiAcMinTemp) - remote_state[9] = 0x90; - else - remote_state[9] = 0x10; -} - -uint8_t IRHitachiAc::getFan(void) { return reverseBits(remote_state[13], 8); } - -void IRHitachiAc::setFan(const uint8_t speed) { - uint8_t fanmin = kHitachiAcFanAuto; - uint8_t fanmax = kHitachiAcFanHigh; - switch (getMode()) { - case kHitachiAcDry: // Only 2 x low speeds in Dry mode. - fanmin = kHitachiAcFanLow; - fanmax = kHitachiAcFanLow + 1; - break; - case kHitachiAcFan: - fanmin = kHitachiAcFanLow; // No Auto in Fan mode. - break; - } - uint8_t newspeed = std::max(speed, fanmin); - newspeed = std::min(newspeed, fanmax); - remote_state[13] = reverseBits(newspeed, 8); -} - -bool IRHitachiAc::getSwingVertical(void) { return remote_state[14] & 0x80; } - -void IRHitachiAc::setSwingVertical(const bool on) { - if (on) - remote_state[14] |= 0x80; - else - remote_state[14] &= 0x7F; -} - -bool IRHitachiAc::getSwingHorizontal(void) { return remote_state[15] & 0x80; } - -void IRHitachiAc::setSwingHorizontal(const bool on) { - if (on) - remote_state[15] |= 0x80; - else - remote_state[15] &= 0x7F; -} - - -// Convert a standard A/C mode into its native mode. -uint8_t IRHitachiAc::convertMode(const stdAc::opmode_t mode) { - switch (mode) { - case stdAc::opmode_t::kCool: - return kHitachiAcCool; - case stdAc::opmode_t::kHeat: - return kHitachiAcHeat; - case stdAc::opmode_t::kDry: - return kHitachiAcDry; - case stdAc::opmode_t::kFan: - return kHitachiAcFan; - default: - return kHitachiAcAuto; - } -} - -// Convert a standard A/C Fan speed into its native fan speed. -uint8_t IRHitachiAc::convertFan(const stdAc::fanspeed_t speed) { - switch (speed) { - case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kHitachiAcFanLow; - case stdAc::fanspeed_t::kMedium: - return kHitachiAcFanLow + 1; - case stdAc::fanspeed_t::kHigh: - return kHitachiAcFanHigh - 1; - case stdAc::fanspeed_t::kMax: - return kHitachiAcFanHigh; - default: - return kHitachiAcFanAuto; - } -} - -// Convert a native mode to it's common equivalent. -stdAc::opmode_t IRHitachiAc::toCommonMode(const uint8_t mode) { - switch (mode) { - case kHitachiAcCool: return stdAc::opmode_t::kCool; - case kHitachiAcHeat: return stdAc::opmode_t::kHeat; - case kHitachiAcDry: return stdAc::opmode_t::kDry; - case kHitachiAcFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; - } -} - -// Convert a native fan speed to it's common equivalent. -stdAc::fanspeed_t IRHitachiAc::toCommonFanSpeed(const uint8_t speed) { - switch (speed) { - case kHitachiAcFanHigh: return stdAc::fanspeed_t::kMax; - case kHitachiAcFanHigh - 1: return stdAc::fanspeed_t::kHigh; - case kHitachiAcFanLow + 1: return stdAc::fanspeed_t::kMedium; - case kHitachiAcFanLow: return stdAc::fanspeed_t::kLow; - default: return stdAc::fanspeed_t::kAuto; - } -} - -// Convert the A/C state to it's common equivalent. -stdAc::state_t IRHitachiAc::toCommon(void) { - stdAc::state_t result; - result.protocol = decode_type_t::HITACHI_AC; - result.model = -1; // No models used. - result.power = this->getPower(); - result.mode = this->toCommonMode(this->getMode()); - result.celsius = true; - result.degrees = this->getTemp(); - result.fanspeed = this->toCommonFanSpeed(this->getFan()); - result.swingv = this->getSwingVertical() ? stdAc::swingv_t::kAuto : - stdAc::swingv_t::kOff; - result.swingh = this->getSwingHorizontal() ? stdAc::swingh_t::kAuto : - stdAc::swingh_t::kOff; - // Not supported. - result.quiet = false; - result.turbo = false; - result.clean = false; - result.econo = false; - result.filter = false; - result.light = false; - result.beep = false; - result.sleep = -1; - result.clock = -1; - return result; -} - -// Convert the internal state into a human readable string. -String IRHitachiAc::toString(void) { - String result = ""; - result.reserve(110); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); - result += addModeToString(getMode(), kHitachiAcAuto, kHitachiAcCool, - kHitachiAcHeat, kHitachiAcDry, kHitachiAcFan); - result += addTempToString(getTemp()); - result += addFanToString(getFan(), kHitachiAcFanHigh, kHitachiAcFanLow, - kHitachiAcFanAuto, kHitachiAcFanAuto, - kHitachiAcFanMed); - result += addBoolToString(getSwingVertical(), F("Swing (Vertical)")); - result += addBoolToString(getSwingHorizontal(), F("Swing (Horizontal)")); - return result; -} - -#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2) -// Decode the supplied Hitachi A/C message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: The number of data bits to expect. -// Typically kHitachiAcBits, kHitachiAc1Bits, kHitachiAc2Bits -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: ALPHA / Untested. -// -// Supported devices: -// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA -// -// Ref: -// https://github.com/crankyoldgit/IRremoteESP8266/issues/417 -// https://github.com/crankyoldgit/IRremoteESP8266/issues/453 -bool IRrecv::decodeHitachiAC(decode_results *results, const uint16_t nbits, - const bool strict) { - const uint8_t k_tolerance = _tolerance + 5; - if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) - return false; // Can't possibly be a valid HitachiAC message. - if (strict) { - switch (nbits) { - case kHitachiAcBits: - case kHitachiAc1Bits: - case kHitachiAc2Bits: - break; // Okay to continue. - default: - return false; // Not strictly a Hitachi message. - } - } - uint16_t offset = kStartOffset; - uint16_t hmark; - uint32_t hspace; - if (nbits == kHitachiAc1Bits) { - hmark = kHitachiAc1HdrMark; - hspace = kHitachiAc1HdrSpace; - } else { - hmark = kHitachiAcHdrMark; - hspace = kHitachiAcHdrSpace; - } - // Match Header + Data + Footer - if (!matchGeneric(results->rawbuf + offset, results->state, - results->rawlen - offset, nbits, - hmark, hspace, - kHitachiAcBitMark, kHitachiAcOneSpace, - kHitachiAcBitMark, kHitachiAcZeroSpace, - kHitachiAcBitMark, kHitachiAcMinGap, true, - k_tolerance)) return false; - - // Compliance - if (strict) { - if (nbits / 8 == kHitachiAcStateLength && - !IRHitachiAc::validChecksum(results->state, kHitachiAcStateLength)) - return false; - } - - // Success - switch (nbits) { - case kHitachiAc1Bits: - results->decode_type = HITACHI_AC1; - break; - case kHitachiAc2Bits: - results->decode_type = HITACHI_AC2; - break; - case kHitachiAcBits: - default: - results->decode_type = HITACHI_AC; - } - results->bits = nbits; - // No need to record the state as we stored it as we decoded it. - // As we use result->state, we don't record value, address, or command as it - // is a union data type. - return true; -} -#endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2) diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.cpp deleted file mode 100755 index c78b1d21a..000000000 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.cpp +++ /dev/null @@ -1,811 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017-2018 David Conran -// Copyright 2018 Denes Varga - -// Mitsubishi - -#include "ir_Mitsubishi.h" -#include -#ifndef ARDUINO -#include -#endif -#include "IRrecv.h" -#include "IRsend.h" -#include "IRutils.h" - -// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote -// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran - -// Constants -// Mitsubishi TV -// period time is 1/33000Hz = 30.303 uSeconds (T) -// Ref: -// GlobalCache's Control Tower's Mitsubishi TV data. -// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp -const uint16_t kMitsubishiTick = 30; -const uint16_t kMitsubishiBitMarkTicks = 10; -const uint16_t kMitsubishiBitMark = kMitsubishiBitMarkTicks * kMitsubishiTick; -const uint16_t kMitsubishiOneSpaceTicks = 70; -const uint16_t kMitsubishiOneSpace = kMitsubishiOneSpaceTicks * kMitsubishiTick; -const uint16_t kMitsubishiZeroSpaceTicks = 30; -const uint16_t kMitsubishiZeroSpace = - kMitsubishiZeroSpaceTicks * kMitsubishiTick; -const uint16_t kMitsubishiMinCommandLengthTicks = 1786; -const uint16_t kMitsubishiMinCommandLength = - kMitsubishiMinCommandLengthTicks * kMitsubishiTick; -const uint16_t kMitsubishiMinGapTicks = 936; -const uint16_t kMitsubishiMinGap = kMitsubishiMinGapTicks * kMitsubishiTick; - -// Mitsubishi Projector (HC3000) -// Ref: -// https://github.com/crankyoldgit/IRremoteESP8266/issues/441 - -const uint16_t kMitsubishi2HdrMark = 8400; -const uint16_t kMitsubishi2HdrSpace = kMitsubishi2HdrMark / 2; -const uint16_t kMitsubishi2BitMark = 560; -const uint16_t kMitsubishi2ZeroSpace = 520; -const uint16_t kMitsubishi2OneSpace = kMitsubishi2ZeroSpace * 3; -const uint16_t kMitsubishi2MinGap = 28500; - -// Mitsubishi A/C -// Ref: -// https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L84 - -const uint16_t kMitsubishiAcHdrMark = 3400; -const uint16_t kMitsubishiAcHdrSpace = 1750; -const uint16_t kMitsubishiAcBitMark = 450; -const uint16_t kMitsubishiAcOneSpace = 1300; -const uint16_t kMitsubishiAcZeroSpace = 420; -const uint16_t kMitsubishiAcRptMark = 440; -const uint16_t kMitsubishiAcRptSpace = 17100; - -using irutils::addBoolToString; -using irutils::addFanToString; -using irutils::addIntToString; -using irutils::addLabeledString; -using irutils::addModeToString; -using irutils::addTempToString; -using irutils::minsToString; - -#if SEND_MITSUBISHI -// Send a Mitsubishi message -// -// Args: -// data: Contents of the message to be sent. -// nbits: Nr. of bits of data to be sent. Typically kMitsubishiBits. -// repeat: Nr. of additional times the message is to be sent. -// -// Status: ALPHA / untested. -// -// Notes: -// This protocol appears to have no header. -// Ref: -// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp -// GlobalCache's Control Tower's Mitsubishi TV data. -void IRsend::sendMitsubishi(uint64_t data, uint16_t nbits, uint16_t repeat) { - sendGeneric(0, 0, // No Header - kMitsubishiBitMark, kMitsubishiOneSpace, kMitsubishiBitMark, - kMitsubishiZeroSpace, kMitsubishiBitMark, kMitsubishiMinGap, - kMitsubishiMinCommandLength, data, nbits, 33, true, repeat, 50); -} -#endif // SEND_MITSUBISHI - -#if DECODE_MITSUBISHI -// Decode the supplied Mitsubishi message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / previously working. -// -// Notes: -// This protocol appears to have no header. -// -// Ref: -// GlobalCache's Control Tower's Mitsubishi TV data. -bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits, - bool strict) { - if (strict && nbits != kMitsubishiBits) - return false; // Request is out of spec. - - uint16_t offset = kStartOffset; - uint64_t data = 0; - - // Match Data + Footer - if (!matchGeneric(results->rawbuf + offset, &data, - results->rawlen - offset, nbits, - 0, 0, // No header - kMitsubishiBitMark, kMitsubishiOneSpace, - kMitsubishiBitMark, kMitsubishiZeroSpace, - kMitsubishiBitMark, kMitsubishiMinGap, - true, 30)) return false; - // Success - results->decode_type = MITSUBISHI; - results->bits = nbits; - results->value = data; - results->address = 0; - results->command = 0; - return true; -} -#endif // DECODE_MITSUBISHI - -#if SEND_MITSUBISHI2 -// Send a Mitsubishi2 message -// -// Args: -// data: Contents of the message to be sent. -// nbits: Nr. of bits of data to be sent. Typically kMitsubishiBits. -// repeat: Nr. of additional times the message is to be sent. -// -// Status: ALPHA / untested. -// -// Notes: -// Based on a Mitsubishi HC3000 projector's remote. -// This protocol appears to have a manditory in-protocol repeat. -// That is in *addition* to the entire message needing to be sent twice -// for the device to accept the command. That is separate from the repeat. -// i.e. Allegedly, the real remote requires the "Off" button pressed twice. -// You will need to add a suitable gap yourself. -// Ref: -// https://github.com/crankyoldgit/IRremoteESP8266/issues/441 -void IRsend::sendMitsubishi2(uint64_t data, uint16_t nbits, uint16_t repeat) { - for (uint16_t i = 0; i <= repeat; i++) { - // First half of the data. - sendGeneric(kMitsubishi2HdrMark, kMitsubishi2HdrSpace, kMitsubishi2BitMark, - kMitsubishi2OneSpace, kMitsubishi2BitMark, - kMitsubishi2ZeroSpace, kMitsubishi2BitMark, - kMitsubishi2HdrSpace, data >> (nbits / 2), nbits / 2, 33, true, - 0, 50); - // Second half of the data. - sendGeneric(0, 0, // No header for the second data block - kMitsubishi2BitMark, kMitsubishi2OneSpace, kMitsubishi2BitMark, - kMitsubishi2ZeroSpace, kMitsubishi2BitMark, kMitsubishi2MinGap, - data & ((1 << (nbits / 2)) - 1), nbits / 2, 33, true, 0, 50); - } -} -#endif // SEND_MITSUBISHI2 - -#if DECODE_MITSUBISHI2 -// Decode the supplied Mitsubishi2 message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / Works with simulated data. -// -// Notes: -// Hardware supported: -// * Mitsubishi HC3000 projector's remote. -// -// Ref: -// https://github.com/crankyoldgit/IRremoteESP8266/issues/441 -bool IRrecv::decodeMitsubishi2(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + kHeader + (kFooter * 2) - 1) - return false; // Shorter than shortest possibly expected. - if (strict && nbits != kMitsubishiBits) - return false; // Request is out of spec. - - uint16_t offset = kStartOffset; - results->value = 0; - - // Header - if (!matchMark(results->rawbuf[offset++], kMitsubishi2HdrMark)) return false; - if (!matchSpace(results->rawbuf[offset++], kMitsubishi2HdrSpace)) - return false; - for (uint8_t i = 0; i < 2; i++) { - // Match Data + Footer - uint16_t used; - uint64_t data = 0; - used = matchGeneric(results->rawbuf + offset, &data, - results->rawlen - offset, nbits / 2, - 0, 0, // No header - kMitsubishi2BitMark, kMitsubishi2OneSpace, - kMitsubishi2BitMark, kMitsubishi2ZeroSpace, - kMitsubishi2BitMark, kMitsubishi2HdrSpace, - i % 2); - if (!used) return false; - offset += used; - results->value <<= (nbits / 2); - results->value += data; - } - - // Success - results->decode_type = MITSUBISHI2; - results->bits = nbits; - results->address = results->value >> (nbits / 2); - results->command = results->value & ((1 << (nbits / 2)) - 1); - return true; -} -#endif // DECODE_MITSUBISHI2 - -#if SEND_MITSUBISHI_AC -// Send a Mitsubishi A/C message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=kMitsubishiACStateLength) -// repeat: Nr. of times the message is to be repeated. -// (Default = kMitsubishiACMinRepeat). -// -// Status: BETA / Appears to be working. -// -void IRsend::sendMitsubishiAC(const unsigned char data[], const uint16_t nbytes, - const uint16_t repeat) { - if (nbytes < kMitsubishiACStateLength) - return; // Not enough bytes to send a proper message. - - sendGeneric(kMitsubishiAcHdrMark, kMitsubishiAcHdrSpace, kMitsubishiAcBitMark, - kMitsubishiAcOneSpace, kMitsubishiAcBitMark, - kMitsubishiAcZeroSpace, kMitsubishiAcRptMark, - kMitsubishiAcRptSpace, data, nbytes, 38, false, repeat, 50); -} -#endif // SEND_MITSUBISHI_AC - -#if DECODE_MITSUBISHI_AC -// Decode the supplied Mitsubishi message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: ALPHA / Under development -// -// Ref: -// https://www.analysir.com/blog/2015/01/06/reverse-engineering-mitsubishi-ac-infrared-protocol/ -bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < ((kMitsubishiACBits * 2) + 2)) { - DPRINTLN("Shorter than shortest possibly expected."); - return false; // Shorter than shortest possibly expected. - } - if (strict && nbits != kMitsubishiACBits) { - DPRINTLN("Request is out of spec."); - return false; // Request is out of spec. - } - uint16_t offset = kStartOffset; - for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) { - results->state[i] = 0; - } - bool failure = false; - uint8_t rep = 0; - do { - failure = false; - // Header: - // Sometime happens that junk signals arrives before the real message - bool headerFound = false; - while (!headerFound && - offset < (results->rawlen - (kMitsubishiACBits * 2 + 2))) { - headerFound = - matchMark(results->rawbuf[offset++], kMitsubishiAcHdrMark) && - matchSpace(results->rawbuf[offset++], kMitsubishiAcHdrSpace); - } - if (!headerFound) { - DPRINTLN("Header mark not found."); - failure = true; - } - // Decode byte-by-byte: - match_result_t data_result; - for (uint8_t i = 0; i < kMitsubishiACStateLength && !failure; i++) { - results->state[i] = 0; - data_result = - matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark, - kMitsubishiAcOneSpace, kMitsubishiAcBitMark, - kMitsubishiAcZeroSpace, _tolerance, kMarkExcess, false); - if (data_result.success == false) { - failure = true; - DPRINT("Byte decode failed at #"); - DPRINTLN((uint16_t)i); - } else { - results->state[i] = data_result.data; - offset += data_result.used; - DPRINT((uint16_t)results->state[i]); - DPRINT(","); - } - DPRINTLN(""); - } - // HEADER validation: - if (failure || results->state[0] != 0x23 || results->state[1] != 0xCB || - results->state[2] != 0x26 || results->state[3] != 0x01 || - results->state[4] != 0x00) { - DPRINTLN("Header mismatch."); - failure = true; - } else { - // DATA part: - - // FOOTER checksum: - if (IRMitsubishiAC::calculateChecksum(results->state) != - results->state[kMitsubishiACStateLength - 1]) { - DPRINTLN("Checksum error."); - failure = true; - } - } - if (rep != kMitsubishiACMinRepeat && failure) { - bool repeatMarkFound = false; - while (!repeatMarkFound && - offset < (results->rawlen - (kMitsubishiACBits * 2 + 4))) { - repeatMarkFound = - matchMark(results->rawbuf[offset++], kMitsubishiAcRptMark) && - matchSpace(results->rawbuf[offset++], kMitsubishiAcRptSpace); - } - if (!repeatMarkFound) { - DPRINTLN("First attempt failure and repeat mark not found."); - return false; - } - } - rep++; - // Check if the repeat is correct if we need strict decode: - if (strict && !failure) { - DPRINTLN("Strict repeat check enabled."); - // Repeat mark and space: - if (!matchMark(results->rawbuf[offset++], kMitsubishiAcRptMark) || - !matchSpace(results->rawbuf[offset++], kMitsubishiAcRptSpace)) { - DPRINTLN("Repeat mark error."); - return false; - } - // Header mark and space: - if (!matchMark(results->rawbuf[offset++], kMitsubishiAcHdrMark) || - !matchSpace(results->rawbuf[offset++], kMitsubishiAcHdrSpace)) { - DPRINTLN("Repeat header error."); - return false; - } - // Payload: - for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) { - data_result = - matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark, - kMitsubishiAcOneSpace, kMitsubishiAcBitMark, - kMitsubishiAcZeroSpace, _tolerance, kMarkExcess, false); - if (data_result.success == false || - data_result.data != results->state[i]) { - DPRINTLN("Repeat payload error."); - return false; - } - offset += data_result.used; - } - } // strict repeat check - } while (failure && rep <= kMitsubishiACMinRepeat); - results->decode_type = MITSUBISHI_AC; - results->bits = kMitsubishiACStateLength * 8; - return true; -} -#endif // DECODE_MITSUBISHI_AC - -// Code to emulate Mitsubishi A/C IR remote control unit. -// Inspired and derived from the work done at: -// https://github.com/r45635/HVAC-IR-Control -// -// Warning: Consider this very alpha code. Seems to work, but not validated. -// -// Equipment it seems compatible with: -// * -// Initialise the object. -IRMitsubishiAC::IRMitsubishiAC(const uint16_t pin, const bool inverted, - const bool use_modulation) - : _irsend(pin, inverted, use_modulation) { this->stateReset(); } - -// Reset the state of the remote to a known good state/sequence. -void IRMitsubishiAC::stateReset(void) { - // The state of the IR remote in IR code form. - // Known good state obtained from: - // https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L108 - // Note: Can't use the following because it requires -std=c++11 - // uint8_t known_good_state[kMitsubishiACStateLength] = { - // 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, - // 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; - remote_state[0] = 0x23; - remote_state[1] = 0xCB; - remote_state[2] = 0x26; - remote_state[3] = 0x01; - remote_state[4] = 0x00; - remote_state[5] = 0x20; - remote_state[6] = 0x08; - remote_state[7] = 0x06; - remote_state[8] = 0x30; - remote_state[9] = 0x45; - remote_state[10] = 0x67; - for (uint8_t i = 11; i < kMitsubishiACStateLength - 1; i++) - remote_state[i] = 0; - remote_state[kMitsubishiACStateLength - 1] = 0x1F; - this->checksum(); // Calculate the checksum -} - -// Configure the pin for output. -void IRMitsubishiAC::begin(void) { _irsend.begin(); } - -#if SEND_MITSUBISHI_AC -// Send the current desired state to the IR LED. -void IRMitsubishiAC::send(const uint16_t repeat) { - this->checksum(); // Ensure correct checksum before sending. - _irsend.sendMitsubishiAC(remote_state, kMitsubishiACStateLength, repeat); -} -#endif // SEND_MITSUBISHI_AC - -// Return a pointer to the internal state date of the remote. -uint8_t *IRMitsubishiAC::getRaw(void) { - this->checksum(); - return remote_state; -} - -void IRMitsubishiAC::setRaw(const uint8_t *data) { - for (uint8_t i = 0; i < (kMitsubishiACStateLength - 1); i++) { - remote_state[i] = data[i]; - } - this->checksum(); -} - -// Calculate the checksum for the current internal state of the remote. -void IRMitsubishiAC::checksum(void) { - remote_state[17] = this->calculateChecksum(remote_state); -} - -uint8_t IRMitsubishiAC::calculateChecksum(const uint8_t *data) { - uint8_t sum = 0; - // Checksum is simple addition of all previous bytes stored - // as an 8 bit value. - for (uint8_t i = 0; i < 17; i++) sum += data[i]; - return sum & 0xFFU; -} - -// Set the requested power state of the A/C to off. -void IRMitsubishiAC::on(void) { - // state = ON; - remote_state[5] |= kMitsubishiAcPower; -} - -// Set the requested power state of the A/C to off. -void IRMitsubishiAC::off(void) { - // state = OFF; - remote_state[5] &= ~kMitsubishiAcPower; -} - -// Set the requested power state of the A/C. -void IRMitsubishiAC::setPower(bool on) { - if (on) - this->on(); - else - this->off(); -} - -// Return the requested power state of the A/C. -bool IRMitsubishiAC::getPower(void) { - return ((remote_state[5] & kMitsubishiAcPower) != 0); -} - -// Set the temp. in deg C -void IRMitsubishiAC::setTemp(const uint8_t degrees) { - uint8_t temp = std::max((uint8_t)kMitsubishiAcMinTemp, degrees); - temp = std::min((uint8_t)kMitsubishiAcMaxTemp, temp); - remote_state[7] = temp - kMitsubishiAcMinTemp; -} - -// Return the set temp. in deg C -uint8_t IRMitsubishiAC::getTemp(void) { - return (remote_state[7] + kMitsubishiAcMinTemp); -} - -// Set the speed of the fan, 0-6. -// 0 is auto, 1-5 is the speed, 6 is silent. -void IRMitsubishiAC::setFan(const uint8_t speed) { - uint8_t fan = speed; - // Bounds check - if (fan > kMitsubishiAcFanSilent) - fan = kMitsubishiAcFanMax; // Set the fan to maximum if out of range. - if (fan == kMitsubishiAcFanAuto) { // Automatic is a special case. - remote_state[9] = 0b10000000 | (remote_state[9] & 0b01111000); - return; - } else if (fan >= kMitsubishiAcFanMax) { - fan--; // There is no spoon^H^H^Heed 5 (max), pretend it doesn't exist. - } - remote_state[9] &= 0b01111000; // Clear the previous state - remote_state[9] |= fan; -} - -// Return the requested state of the unit's fan. -uint8_t IRMitsubishiAC::getFan(void) { - uint8_t fan = remote_state[9] & 0b111; - if (fan == kMitsubishiAcFanMax) return kMitsubishiAcFanSilent; - return fan; -} - -// Return the requested climate operation mode of the a/c unit. -uint8_t IRMitsubishiAC::getMode(void) { return (remote_state[6]); } - -// Set the requested climate operation mode of the a/c unit. -void IRMitsubishiAC::setMode(const uint8_t mode) { - // If we get an unexpected mode, default to AUTO. - switch (mode) { - case kMitsubishiAcAuto: - remote_state[8] = 0b00110000; - break; - case kMitsubishiAcCool: - remote_state[8] = 0b00110110; - break; - case kMitsubishiAcDry: - remote_state[8] = 0b00110010; - break; - case kMitsubishiAcHeat: - remote_state[8] = 0b00110000; - break; - default: - this->setMode(kMitsubishiAcAuto); - return; - } - remote_state[6] = mode; -} - -// Set the requested vane operation mode of the a/c unit. -void IRMitsubishiAC::setVane(const uint8_t position) { - uint8_t pos = std::min(position, (uint8_t)0b111); // bounds check - pos |= 0b1000; - pos <<= 3; - remote_state[9] &= 0b11000111; // Clear the previous setting. - remote_state[9] |= pos; -} - -// Set the requested wide-vane operation mode of the a/c unit. -void IRMitsubishiAC::setWideVane(const uint8_t position) { - uint8_t pos = std::min(position, kMitsubishiAcWideVaneAuto); // bounds check - pos <<= 4; - remote_state[8] &= 0b00001111; // Clear the previous setting. - remote_state[8] |= pos; -} - -// Return the requested vane operation mode of the a/c unit. -uint8_t IRMitsubishiAC::getVane(void) { - return ((remote_state[9] & 0b00111000) >> 3); -} - -// Return the requested wide vane operation mode of the a/c unit. -uint8_t IRMitsubishiAC::getWideVane(void) { - return (remote_state[8] >> 4); -} - -// Return the clock setting of the message. 1=1/6 hour. e.g. 4pm = 48 -uint8_t IRMitsubishiAC::getClock(void) { return remote_state[10]; } - -// Set the current time. 1 = 1/6 hour. e.g. 6am = 36. -void IRMitsubishiAC::setClock(const uint8_t clock) { - remote_state[10] = clock; -} - -// Return the desired start time. 1 = 1/6 hour. e.g. 1am = 6 -uint8_t IRMitsubishiAC::getStartClock(void) { return remote_state[12]; } - -// Set the desired start time of the AC. 1 = 1/6 hour. e.g. 8pm = 120 -void IRMitsubishiAC::setStartClock(const uint8_t clock) { - remote_state[12] = clock; -} - -// Return the desired stop time of the AC. 1 = 1/6 hour. e.g 10pm = 132 -uint8_t IRMitsubishiAC::getStopClock(void) { return remote_state[11]; } - -// Set the desired stop time of the AC. 1 = 1/6 hour. e.g 10pm = 132 -void IRMitsubishiAC::setStopClock(const uint8_t clock) { - remote_state[11] = clock; -} - -// Return the timer setting. Possible values: kMitsubishiAcNoTimer, -// kMitsubishiAcStartTimer, kMitsubishiAcStopTimer, -// kMitsubishiAcStartStopTimer -uint8_t IRMitsubishiAC::getTimer(void) { return remote_state[13] & 0b111; } - -// Set the timer setting. Possible values: kMitsubishiAcNoTimer, -// kMitsubishiAcStartTimer, kMitsubishiAcStopTimer, -// kMitsubishiAcStartStopTimer -void IRMitsubishiAC::setTimer(uint8_t timer) { - remote_state[13] = timer & 0b111; -} - -// Convert a standard A/C mode into its native mode. -uint8_t IRMitsubishiAC::convertMode(const stdAc::opmode_t mode) { - switch (mode) { - case stdAc::opmode_t::kCool: - return kMitsubishiAcCool; - case stdAc::opmode_t::kHeat: - return kMitsubishiAcHeat; - case stdAc::opmode_t::kDry: - return kMitsubishiAcDry; - default: - return kMitsubishiAcAuto; - } -} - -// Convert a standard A/C Fan speed into its native fan speed. -uint8_t IRMitsubishiAC::convertFan(const stdAc::fanspeed_t speed) { - switch (speed) { - case stdAc::fanspeed_t::kMin: - return kMitsubishiAcFanSilent; - case stdAc::fanspeed_t::kLow: - return kMitsubishiAcFanRealMax - 3; - case stdAc::fanspeed_t::kMedium: - return kMitsubishiAcFanRealMax - 2; - case stdAc::fanspeed_t::kHigh: - return kMitsubishiAcFanRealMax - 1; - case stdAc::fanspeed_t::kMax: - return kMitsubishiAcFanRealMax; - default: - return kMitsubishiAcFanAuto; - } -} - -// Convert a standard A/C vertical swing into its native setting. -uint8_t IRMitsubishiAC::convertSwingV(const stdAc::swingv_t position) { - switch (position) { - case stdAc::swingv_t::kHighest: - return kMitsubishiAcVaneAutoMove - 6; - case stdAc::swingv_t::kHigh: - return kMitsubishiAcVaneAutoMove - 5; - case stdAc::swingv_t::kMiddle: - return kMitsubishiAcVaneAutoMove - 4; - case stdAc::swingv_t::kLow: - return kMitsubishiAcVaneAutoMove - 3; - case stdAc::swingv_t::kLowest: - return kMitsubishiAcVaneAutoMove - 2; - case stdAc::swingv_t::kAuto: - return kMitsubishiAcVaneAutoMove; - default: - return kMitsubishiAcVaneAuto; - } -} - -// Convert a standard A/C wide wane swing into its native setting. -uint8_t IRMitsubishiAC::convertSwingH(const stdAc::swingh_t position) { - switch (position) { - case stdAc::swingh_t::kLeftMax: - return kMitsubishiAcWideVaneAuto - 7; - case stdAc::swingh_t::kLeft: - return kMitsubishiAcWideVaneAuto - 6; - case stdAc::swingh_t::kMiddle: - return kMitsubishiAcWideVaneAuto - 5; - case stdAc::swingh_t::kRight: - return kMitsubishiAcWideVaneAuto - 4; - case stdAc::swingh_t::kRightMax: - return kMitsubishiAcWideVaneAuto - 3; - case stdAc::swingh_t::kWide: - return kMitsubishiAcWideVaneAuto - 2; - case stdAc::swingh_t::kAuto: - return kMitsubishiAcWideVaneAuto; - default: - return kMitsubishiAcWideVaneAuto - 5; - } -} - -// Convert a native mode to it's common equivalent. -stdAc::opmode_t IRMitsubishiAC::toCommonMode(const uint8_t mode) { - switch (mode) { - case kMitsubishiAcCool: return stdAc::opmode_t::kCool; - case kMitsubishiAcHeat: return stdAc::opmode_t::kHeat; - case kMitsubishiAcDry: return stdAc::opmode_t::kDry; - default: return stdAc::opmode_t::kAuto; - } -} - -// Convert a native fan speed to it's common equivalent. -stdAc::fanspeed_t IRMitsubishiAC::toCommonFanSpeed(const uint8_t speed) { - switch (speed) { - case kMitsubishiAcFanRealMax: return stdAc::fanspeed_t::kMax; - case kMitsubishiAcFanRealMax - 1: return stdAc::fanspeed_t::kHigh; - case kMitsubishiAcFanRealMax - 2: return stdAc::fanspeed_t::kMedium; - case kMitsubishiAcFanRealMax - 3: return stdAc::fanspeed_t::kLow; - case kMitsubishiAcFanSilent: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; - } -} - -// Convert a native vertical swing to it's common equivalent. -stdAc::swingv_t IRMitsubishiAC::toCommonSwingV(const uint8_t pos) { - switch (pos) { - case 1: return stdAc::swingv_t::kHighest; - case 2: return stdAc::swingv_t::kHigh; - case 3: return stdAc::swingv_t::kMiddle; - case 4: return stdAc::swingv_t::kLow; - case 5: return stdAc::swingv_t::kLowest; - default: return stdAc::swingv_t::kAuto; - } -} - -// Convert a native horizontal swing to it's common equivalent. -stdAc::swingh_t IRMitsubishiAC::toCommonSwingH(const uint8_t pos) { - switch (pos) { - case 1: return stdAc::swingh_t::kLeftMax; - case 2: return stdAc::swingh_t::kLeft; - case 3: return stdAc::swingh_t::kMiddle; - case 4: return stdAc::swingh_t::kRight; - case 5: return stdAc::swingh_t::kRightMax; - case 6: return stdAc::swingh_t::kWide; - default: return stdAc::swingh_t::kAuto; - } -} - -// Convert the A/C state to it's common equivalent. -stdAc::state_t IRMitsubishiAC::toCommon(void) { - stdAc::state_t result; - result.protocol = decode_type_t::MITSUBISHI_AC; - result.model = -1; // No models used. - result.power = this->getPower(); - result.mode = this->toCommonMode(this->getMode()); - result.celsius = true; - result.degrees = this->getTemp(); - result.fanspeed = this->toCommonFanSpeed(this->getFan()); - result.swingv = this->toCommonSwingV(this->getVane()); - result.swingh = this->toCommonSwingH(this->getWideVane()); - result.quiet = this->getFan() == kMitsubishiAcFanSilent; - // Not supported. - result.turbo = false; - result.clean = false; - result.econo = false; - result.filter = false; - result.light = false; - result.beep = false; - result.sleep = -1; - result.clock = -1; - return result; -} - -// Convert the internal state into a human readable string. -String IRMitsubishiAC::toString(void) { - String result = ""; - result.reserve(110); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); - result += addModeToString(getMode(), kMitsubishiAcAuto, kMitsubishiAcCool, - kMitsubishiAcHeat, kMitsubishiAcDry, - kMitsubishiAcAuto); - result += addTempToString(getTemp()); - result += addFanToString(getFan(), kMitsubishiAcFanRealMax, - kMitsubishiAcFanRealMax - 3, - kMitsubishiAcFanAuto, kMitsubishiAcFanQuiet, - kMitsubishiAcFanRealMax - 2); - result += F(", Vane: "); - switch (this->getVane()) { - case MITSUBISHI_AC_VANE_AUTO: - result += F("AUTO"); - break; - case MITSUBISHI_AC_VANE_AUTO_MOVE: - result += F("AUTO MOVE"); - break; - default: - result += uint64ToString(this->getVane()); - } - result += F(", Wide Vane: "); - switch (this->getWideVane()) { - case kMitsubishiAcWideVaneAuto: - result += F("AUTO"); - break; - default: - result += uint64ToString(this->getWideVane()); - } - result += addLabeledString(minsToString(getClock() * 10), F("Time")); - result += addLabeledString(minsToString(getStartClock() * 10), F("On timer")); - result += addLabeledString(minsToString(getStopClock() * 10), F("Off timer")); - result += F(", Timer: "); - switch (this->getTimer()) { - case kMitsubishiAcNoTimer: - result += '-'; - break; - case kMitsubishiAcStartTimer: - result += F("Start"); - break; - case kMitsubishiAcStopTimer: - result += F("Stop"); - break; - case kMitsubishiAcStartStopTimer: - result += F("Start+Stop"); - break; - default: - result += F("? ("); - result += this->getTimer(); - result += F(")\n"); - } - return result; -} diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.h b/lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.h deleted file mode 100755 index ac67082dc..000000000 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Mitsubishi.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran - -// Mitsubishi - -// Supports: -// Brand: Mitsubishi, Model: TV -// Brand: Mitsubishi, Model: HC3000 Projector - -#ifndef IR_MITSUBISHI_H_ -#define IR_MITSUBISHI_H_ - -#define __STDC_LIMIT_MACROS -#include -#ifndef UNIT_TEST -#include -#endif -#include "IRremoteESP8266.h" -#include "IRsend.h" -#ifdef UNIT_TEST -#include "IRsend_test.h" -#endif - -// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote -// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran - -// Constants -const uint8_t kMitsubishiAcAuto = 0x20; -const uint8_t kMitsubishiAcCool = 0x18; -const uint8_t kMitsubishiAcDry = 0x10; -const uint8_t kMitsubishiAcHeat = 0x08; -const uint8_t kMitsubishiAcPower = 0x20; -const uint8_t kMitsubishiAcFanAuto = 0; -const uint8_t kMitsubishiAcFanMax = 5; -const uint8_t kMitsubishiAcFanRealMax = 4; -const uint8_t kMitsubishiAcFanSilent = 6; -const uint8_t kMitsubishiAcFanQuiet = kMitsubishiAcFanSilent; -const uint8_t kMitsubishiAcMinTemp = 16; // 16C -const uint8_t kMitsubishiAcMaxTemp = 31; // 31C -const uint8_t kMitsubishiAcVaneAuto = 0; -const uint8_t kMitsubishiAcVaneAutoMove = 7; -const uint8_t kMitsubishiAcNoTimer = 0; -const uint8_t kMitsubishiAcStartTimer = 5; -const uint8_t kMitsubishiAcStopTimer = 3; -const uint8_t kMitsubishiAcStartStopTimer = 7; -const uint8_t kMitsubishiAcWideVaneAuto = 8; - -// Legacy defines (Deprecated) -#define MITSUBISHI_AC_VANE_AUTO_MOVE kMitsubishiAcVaneAutoMove -#define MITSUBISHI_AC_VANE_AUTO kMitsubishiAcVaneAuto -#define MITSUBISHI_AC_POWER kMitsubishiAcPower -#define MITSUBISHI_AC_MIN_TEMP kMitsubishiAcMinTemp -#define MITSUBISHI_AC_MAX_TEMP kMitsubishiAcMaxTemp -#define MITSUBISHI_AC_HEAT kMitsubishiAcHeat -#define MITSUBISHI_AC_FAN_SILENT kMitsubishiAcFanSilent -#define MITSUBISHI_AC_FAN_REAL_MAX kMitsubishiAcFanRealMax -#define MITSUBISHI_AC_FAN_MAX kMitsubishiAcFanMax -#define MITSUBISHI_AC_FAN_AUTO kMitsubishiAcFanAuto -#define MITSUBISHI_AC_DRY kMitsubishiAcDry -#define MITSUBISHI_AC_COOL kMitsubishiAcCool -#define MITSUBISHI_AC_AUTO kMitsubishiAcAuto - -class IRMitsubishiAC { - public: - explicit IRMitsubishiAC(const uint16_t pin, const bool inverted = false, - const bool use_modulation = true); - - static uint8_t calculateChecksum(const uint8_t* data); - - void stateReset(void); -#if SEND_MITSUBISHI_AC - void send(const uint16_t repeat = kMitsubishiACMinRepeat); - uint8_t calibrate(void) { return _irsend.calibrate(); } -#endif // SEND_MITSUBISHI_AC - void begin(void); - void on(void); - void off(void); - void setPower(const bool on); - bool getPower(void); - void setTemp(const uint8_t degrees); - uint8_t getTemp(void); - void setFan(const uint8_t speed); - uint8_t getFan(void); - void setMode(const uint8_t mode); - uint8_t getMode(void); - void setVane(const uint8_t position); - void setWideVane(const uint8_t position); - uint8_t getVane(void); - uint8_t getWideVane(void); - uint8_t* getRaw(void); - void setRaw(const uint8_t* data); - uint8_t getClock(void); - void setClock(const uint8_t clock); - uint8_t getStartClock(void); - void setStartClock(const uint8_t clock); - uint8_t getStopClock(void); - void setStopClock(const uint8_t clock); - uint8_t getTimer(void); - void setTimer(const uint8_t timer); - uint8_t convertMode(const stdAc::opmode_t mode); - uint8_t convertFan(const stdAc::fanspeed_t speed); - uint8_t convertSwingV(const stdAc::swingv_t position); - uint8_t convertSwingH(const stdAc::swingh_t position); - static stdAc::opmode_t toCommonMode(const uint8_t mode); - static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); - static stdAc::swingv_t toCommonSwingV(const uint8_t pos); - static stdAc::swingh_t toCommonSwingH(const uint8_t pos); - stdAc::state_t toCommon(void); - String toString(void); -#ifndef UNIT_TEST - - private: - IRsend _irsend; -#else - IRsendTest _irsend; -#endif - uint8_t remote_state[kMitsubishiACStateLength]; - void checksum(void); -}; - -#endif // IR_MITSUBISHI_H_ diff --git a/lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data.py b/lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data.py deleted file mode 100755 index 8a2e45794..000000000 --- a/lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data.py +++ /dev/null @@ -1,432 +0,0 @@ -#!/usr/bin/python -"""Attempt an automatic analysis of IRremoteESP8266's Raw data output. - Makes suggestions on key values and tried to break down the message - into likely chunks.""" -# -# Copyright 2018 David Conran -import argparse -import sys - - -class RawIRMessage(): - """Basic analyse functions & structure for raw IR messages.""" - - # pylint: disable=too-many-instance-attributes - - def __init__(self, margin, timings, output=sys.stdout, verbose=True): - self.hdr_mark = None - self.hdr_space = None - self.bit_mark = None - self.zero_space = None - self.one_space = None - self.gaps = [] - self.margin = margin - self.marks = [] - self.mark_buckets = {} - self.spaces = [] - self.space_buckets = {} - self.output = output - self.verbose = verbose - if len(timings) <= 3: - raise ValueError("Too few message timings supplied.") - self.timings = timings - self._generate_timing_candidates() - self._calc_values() - - def _generate_timing_candidates(self): - """Determine the likely values from the given data.""" - count = 0 - for usecs in self.timings: - count = count + 1 - if count % 2: - self.marks.append(usecs) - else: - self.spaces.append(usecs) - self.marks, self.mark_buckets = self.reduce_list(self.marks) - self.spaces, self.space_buckets = self.reduce_list(self.spaces) - - def reduce_list(self, items): - """Reduce a list of numbers into buckets that are at least margin apart.""" - result = [] - last = -1 - buckets = {} - for item in sorted(items, reverse=True): - if last == -1 or item < last - self.margin: - result.append(item) - last = item - buckets[last] = [item] - else: - buckets[last].append(item) - return result, buckets - - def _usec_compare(self, seen, expected): - """Compare two usec values and see if they match within a - subtractive margin.""" - return expected - self.margin < seen <= expected - - def _usec_compares(self, usecs, expecteds): - """Compare a usec value to a list of values and return True - if they are within a subtractive margin.""" - for expected in expecteds: - if self._usec_compare(usecs, expected): - return True - return False - - def display_binary(self, binary_str): - """Display common representations of the suppied binary string.""" - num = int(binary_str, 2) - bits = len(binary_str) - rev_binary_str = binary_str[::-1] - rev_num = int(rev_binary_str, 2) - self.output.write("\n Bits: %d\n" - " Hex: %s (MSB first)\n" - " %s (LSB first)\n" - " Dec: %s (MSB first)\n" - " %s (LSB first)\n" - " Bin: 0b%s (MSB first)\n" - " 0b%s (LSB first)\n" % - (bits, ("0x{0:0%dX}" % (bits / 4)).format(num), - ("0x{0:0%dX}" % (bits / 4)).format(rev_num), num, - rev_num, binary_str, rev_binary_str)) - - def add_data_code(self, bin_str, footer=True): - """Add the common "data" sequence of code to send the bulk of a message.""" - # pylint: disable=no-self-use - code = [] - code.append(" // Data") - code.append(" // e.g. data = 0x%X, nbits = %d" % (int(bin_str, 2), - len(bin_str))) - code.append(" sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, " - "nbits, true);") - if footer: - code.append(" // Footer") - code.append(" mark(kBitMark);") - return code - - def _calc_values(self): - """Calculate the values which describe the standard timings - for the protocol.""" - if self.verbose: - self.output.write("Potential Mark Candidates:\n" - "%s\n" - "Potential Space Candidates:\n" - "%s\n" % (str(self.marks), str(self.spaces))) - # Largest mark is likely the kHdrMark - self.hdr_mark = self.marks[0] - # The bit mark is likely to be the smallest mark. - self.bit_mark = self.marks[-1] - - if self.is_space_encoded() and len(self.spaces) >= 3: - if self.verbose and len(self.marks) > 2: - self.output.write("DANGER: Unexpected and unused 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() - # Rest are probably message gaps - self.gaps = spaces - - def is_space_encoded(self): - """Make an educated guess if the message is space encoded.""" - return len(self.spaces) > len(self.marks) - - def is_hdr_mark(self, usec): - """Is usec the header mark?""" - return self._usec_compare(usec, self.hdr_mark) - - def is_hdr_space(self, usec): - """Is usec the header space?""" - return self._usec_compare(usec, self.hdr_space) - - def is_bit_mark(self, usec): - """Is usec the bit mark?""" - return self._usec_compare(usec, self.bit_mark) - - def is_one_space(self, usec): - """Is usec the one space?""" - return self._usec_compare(usec, self.one_space) - - def is_zero_space(self, usec): - """Is usec the zero_space?""" - return self._usec_compare(usec, self.zero_space) - - def is_gap(self, usec): - """Is usec the a space gap?""" - return self._usec_compares(usec, self.gaps) - - -def avg_list(items): - """Return the average of a list of numbers.""" - if items: - return int(sum(items) / len(items)) - return 0 - - -def add_bit(so_far, bit, output=sys.stdout): - """Add a bit to the end of the bits collected so far.""" - if bit == "reset": - return "" - output.write(str(bit)) # This effectively displays in LSB first order. - return so_far + str(bit) # Storing it in MSB first order. - - -def convert_rawdata(data_str): - """Parse a C++ rawdata declaration into a list of values.""" - start = data_str.find('{') - end = data_str.find('}') - if end == -1: - end = len(data_str) - if start > end: - raise ValueError("Raw Data not parsible due to parentheses placement.") - data_str = data_str[start + 1:end] - results = [] - for timing in [x.strip() for x in data_str.split(',')]: - try: - results.append(int(timing)) - except ValueError: - raise ValueError( - "Raw Data contains a non-numeric value of '%s'." % timing) - return results - - -def dump_constants(message, defines, output=sys.stdout): - """Dump the key constants and generate the C++ #defines.""" - 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]) - one_space = avg_list(message.space_buckets[message.one_space]) - zero_space = avg_list(message.space_buckets[message.zero_space]) - - output.write("Guessing key value:\n" - "kHdrMark = %d\n" - "kHdrSpace = %d\n" - "kBitMark = %d\n" - "kOneSpace = %d\n" - "kZeroSpace = %d\n" % (hdr_mark, hdr_space, bit_mark, one_space, - zero_space)) - defines.append("const uint16_t kHdrMark = %d;" % hdr_mark) - defines.append("const uint16_t kBitMark = %d;" % bit_mark) - defines.append("const uint16_t kHdrSpace = %d;" % hdr_space) - defines.append("const uint16_t kOneSpace = %d;" % one_space) - defines.append("const uint16_t kZeroSpace = %d;" % zero_space) - - avg_gaps = [avg_list(message.space_buckets[x]) for x in message.gaps] - if len(message.gaps) == 1: - output.write("kSpaceGap = %d\n" % avg_gaps[0]) - defines.append("const uint16_t kSpaceGap = %d;" % avg_gaps[0]) - else: - count = 0 - for gap in avg_gaps: - # We probably (still) have a gap in the protocol. - count = count + 1 - output.write("kSpaceGap%d = %d\n" % (count, gap)) - defines.append("const uint16_t kSpaceGap%d = %d;" % (count, gap)) - - -def parse_and_report(rawdata_str, margin, gen_code=False, output=sys.stdout): - """Analyse the rawdata c++ definition of a IR message.""" - defines = [] - function_code = [] - - # Parse the input. - rawdata = convert_rawdata(rawdata_str) - - output.write("Found %d timing entries.\n" % len(rawdata)) - - message = RawIRMessage(margin, rawdata, output) - output.write("\nGuessing encoding type:\n") - if message.is_space_encoded(): - output.write("Looks like it uses space encoding. Yay!\n\n") - dump_constants(message, defines, output) - else: - output.write("Sorry, it looks like it is Mark encoded. " - "I can't do that yet. Exiting.\n") - sys.exit(1) - total_bits = decode_data(message, defines, function_code, output) - if gen_code: - generate_irsend_code(defines, function_code, total_bits, output) - - -def decode_data(message, defines, function_code, output=sys.stdout): - """Decode the data sequence with the given values in mind.""" - # pylint: disable=too-many-branches,too-many-statements - - # Now we have likely candidates for the key values, go through the original - # sequence and break it up and indicate accordingly. - - output.write("\nDecoding protocol based on analysis so far:\n\n") - state = "" - count = 1 - total_bits = "" - binary_value = add_bit("", "reset") - - function_code.extend([ - "// Function should be safe up to 64 bits.", - "void IRsend::sendXyz(const uint64_t data, const uint16_t" - " nbits, const uint16_t repeat) {", - " enableIROut(38); // A guess. Most common frequency.", - " for (uint16_t r = 0; r <= repeat; r++) {" - ]) - - for usec in message.timings: - if (message.is_hdr_mark(usec) and count % 2 and - not message.is_bit_mark(usec)): - state = "HM" - if binary_value: - message.display_binary(binary_value) - function_code.extend(message.add_data_code(binary_value, False)) - total_bits = total_bits + binary_value - binary_value = add_bit(binary_value, "reset") - output.write("kHdrMark+") - function_code.extend([" // Header", " mark(kHdrMark);"]) - elif message.is_hdr_space(usec) and not message.is_one_space(usec): - if state != "HM": - if binary_value: - message.display_binary(binary_value) - total_bits = total_bits + binary_value - function_code.extend(message.add_data_code(binary_value)) - binary_value = add_bit(binary_value, "reset") - output.write("UNEXPECTED->") - state = "HS" - output.write("kHdrSpace+") - function_code.append(" space(kHdrSpace);") - elif message.is_bit_mark(usec) and count % 2: - if state not in ("HS", "BS"): - output.write("kBitMark(UNEXPECTED)") - state = "BM" - elif message.is_zero_space(usec): - if state != "BM": - output.write("kZeroSpace(UNEXPECTED)") - state = "BS" - binary_value = add_bit(binary_value, 0, output) - elif message.is_one_space(usec): - if state != "BM": - output.write("kOneSpace(UNEXPECTED)") - state = "BS" - binary_value = add_bit(binary_value, 1, output) - elif message.is_gap(usec): - if state != "BM": - output.write("UNEXPECTED->") - state = "GS" - output.write("GAP(%d)" % usec) - if binary_value: - message.display_binary(binary_value) - function_code.extend(message.add_data_code(binary_value)) - else: - function_code.extend([" // Gap", " mark(kBitMark);"]) - function_code.append(" space(kSpaceGap);") - total_bits = total_bits + binary_value - binary_value = add_bit(binary_value, "reset") - else: - output.write("UNKNOWN(%d)" % usec) - state = "UNK" - count = count + 1 - if binary_value: - message.display_binary(binary_value) - function_code.extend(message.add_data_code(binary_value)) - function_code.extend([ - " space(100000); // A 100% made up guess of the gap" - " between messages.", " }", "}" - ]) - - total_bits = total_bits + binary_value - output.write("\nTotal Nr. of suspected bits: %d\n" % len(total_bits)) - defines.append("const uint16_t kXyzBits = %d;" % len(total_bits)) - if len(total_bits) > 64: - defines.append("const uint16_t kXyzStateLength = %d;" % - (len(total_bits) / 8)) - return total_bits - - -def generate_irsend_code(defines, normal, bits_str, output=sys.stdout): - """Output the estimated C++ code to reproduce the IR message.""" - output.write("\nGenerating a VERY rough code outline:\n\n" - "// WARNING: This probably isn't directly usable." - " It's a guide only.\n") - for line in defines: - output.write("%s\n" % line) - - if len(bits_str) > 64: # Will it fit in a uint64_t? - output.write("// DANGER: More than 64 bits detected. A uint64_t for " - "'data' won't work!\n") - # Display the "normal" version's code incase there are some - # oddities in it. - for line in normal: - output.write("%s\n" % line) - - if len(bits_str) > 64: # Will it fit in a uint64_t? - output.write("\n\n// Alternative >64 bit Function\n" - "void IRsend::sendXyz(uint8_t data[], uint16_t nbytes," - " uint16_t repeat) {\n" - " // nbytes should typically be kXyzStateLength\n" - " // data should typically be:\n" - " // uint8_t data[kXyzStateLength] = {0x%s};\n" - " // data[] is assumed to be in MSB order for this code.\n" - " for (uint16_t r = 0; r <= repeat; r++) {\n" - " sendGeneric(kHdrMark, kHdrSpace,\n" - " kBitMark, kOneSpace,\n" - " kBitMark, kZeroSpace,\n" - " kBitMark,\n" - " 100000, // 100%% made-up guess at the" - " message gap.\n" - " data, nbytes,\n" - " 38000, // Complete guess of the modulation" - " frequency.\n" - " true, 0, 50);\n" - " }\n" - "}\n" % ", 0x".join("%02X" % int(bits_str[i:i + 8], 2) - for i in range(0, len(bits_str), 8))) - - -def main(): - """Parse the commandline arguments and call the method.""" - arg_parser = argparse.ArgumentParser( - description="Read an IRremoteESP8266 rawData declaration and tries to " - "analyse it.", - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - arg_parser.add_argument( - "-g", - "--code", - action="store_true", - default=False, - dest="gen_code", - help="Generate a C++ code outline to aid making an IRsend function.") - arg_group = arg_parser.add_mutually_exclusive_group(required=True) - arg_group.add_argument( - "rawdata", - help="A rawData line from IRrecvDumpV2. e.g. 'uint16_t rawbuf[37] = {" - "7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, " - "520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, " - "494, 520, 520, 520, 494, 520, 494, 520, 494, 520, 494};'", - nargs="?") - arg_group.add_argument( - "-f", "--file", help="Read in a rawData line from the file.") - arg_parser.add_argument( - "-r", - "--range", - type=int, - help="Max number of micro-seconds difference between values to consider" - " it the same value.", - dest="margin", - default=200) - arg_group.add_argument( - "--stdin", - help="Read in a rawData line from STDIN.", - action="store_true", - default=False) - arg_options = arg_parser.parse_args() - - if arg_options.stdin: - data = sys.stdin.read() - elif arg_options.file: - with open(arg_options.file) as input_file: - data = input_file.read() - else: - data = arg_options.rawdata - parse_and_report(data, arg_options.margin, arg_options.gen_code) - - -if __name__ == '__main__': - main() diff --git a/lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data_test.py b/lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data_test.py deleted file mode 100755 index 5d5504ffc..000000000 --- a/lib/IRremoteESP8266-2.6.5/tools/auto_analyse_raw_data_test.py +++ /dev/null @@ -1,492 +0,0 @@ -#!/usr/bin/python3 -"""Unit tests for auto_analyse_raw_data.py""" -from io import StringIO -import unittest -import auto_analyse_raw_data as analyse - - -class TestRawIRMessage(unittest.TestCase): - """Unit tests for the RawIRMessage class.""" - - # pylint: disable=too-many-public-methods - - def test_display_binary(self): - """Test the display_binary() method.""" - output = StringIO() - message = analyse.RawIRMessage(100, [8000, 4000, 500, 500, 500], output, - False) - self.assertEqual(output.getvalue(), '') - message.display_binary("10101010") - message.display_binary("0000000000000000") - message.display_binary("00010010001101000101011001111000") - self.assertEqual(output.getvalue(), '\n' - ' Bits: 8\n' - ' Hex: 0xAA (MSB first)\n' - ' 0x55 (LSB first)\n' - ' Dec: 170 (MSB first)\n' - ' 85 (LSB first)\n' - ' Bin: 0b10101010 (MSB first)\n' - ' 0b01010101 (LSB first)\n' - '\n' - ' Bits: 16\n' - ' Hex: 0x0000 (MSB first)\n' - ' 0x0000 (LSB first)\n' - ' Dec: 0 (MSB first)\n' - ' 0 (LSB first)\n' - ' Bin: 0b0000000000000000 (MSB first)\n' - ' 0b0000000000000000 (LSB first)\n' - '\n' - ' Bits: 32\n' - ' Hex: 0x12345678 (MSB first)\n' - ' 0x1E6A2C48 (LSB first)\n' - ' Dec: 305419896 (MSB first)\n' - ' 510274632 (LSB first)\n' - ' Bin: 0b00010010001101000101011001111000 (MSB first)\n' - ' 0b00011110011010100010110001001000 (LSB first)\n') - - -class TestAutoAnalyseRawData(unittest.TestCase): - """Unit tests for the functions in AutoAnalyseRawData.""" - - # pylint: disable=too-many-public-methods - - def test_dump_constants_simple(self): - """Simple tests for the dump_constants() function.""" - ignore = StringIO() - output = StringIO() - defs = [] - message = analyse.RawIRMessage(200, [ - 7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, - 520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494, - 520, 520, 520, 494, 520, 494, 520, 494, 1482, 494 - ], ignore) - analyse.dump_constants(message, defs, output) - self.assertEqual(defs, [ - 'const uint16_t kHdrMark = 7930;', 'const uint16_t kBitMark = 496;', - 'const uint16_t kHdrSpace = 3965;', 'const uint16_t kOneSpace = 1485;', - 'const uint16_t kZeroSpace = 520;' - ]) - self.assertEqual(output.getvalue(), 'Guessing key value:\n' - 'kHdrMark = 7930\n' - 'kHdrSpace = 3965\n' - 'kBitMark = 496\n' - 'kOneSpace = 1485\n' - 'kZeroSpace = 520\n') - - def test_dump_constants_aircon(self): - """More complex tests for the dump_constants() function.""" - ignore = StringIO() - output = StringIO() - defs = [] - message = analyse.RawIRMessage(200, [ - 9008, 4496, 644, 1660, 676, 530, 648, 558, 672, 1636, 646, 1660, 644, - 556, 650, 584, 626, 560, 644, 580, 628, 1680, 624, 560, 648, 1662, 644, - 582, 648, 536, 674, 530, 646, 580, 628, 560, 670, 532, 646, 562, 644, - 556, 672, 536, 648, 1662, 646, 1660, 652, 554, 644, 558, 672, 538, 644, - 560, 668, 560, 648, 1638, 668, 536, 644, 1660, 668, 532, 648, 560, 648, - 1660, 674, 554, 622, 19990, 646, 580, 624, 1660, 648, 556, 648, 558, - 674, 556, 622, 560, 644, 564, 668, 536, 646, 1662, 646, 1658, 672, 534, - 648, 558, 644, 562, 648, 1662, 644, 584, 622, 558, 648, 562, 668, 534, - 670, 536, 670, 532, 672, 536, 646, 560, 646, 558, 648, 558, 670, 534, - 650, 558, 646, 560, 646, 560, 668, 1638, 646, 1662, 646, 1660, 646, - 1660, 648 - ], ignore) - analyse.dump_constants(message, defs, output) - self.assertEqual(defs, [ - 'const uint16_t kHdrMark = 9008;', 'const uint16_t kBitMark = 650;', - 'const uint16_t kHdrSpace = 4496;', 'const uint16_t kOneSpace = 1657;', - 'const uint16_t kZeroSpace = 554;', 'const uint16_t kSpaceGap = 19990;' - ]) - self.assertEqual(output.getvalue(), 'Guessing key value:\n' - 'kHdrMark = 9008\n' - 'kHdrSpace = 4496\n' - 'kBitMark = 650\n' - 'kOneSpace = 1657\n' - 'kZeroSpace = 554\n' - 'kSpaceGap = 19990\n') - - def test_convert_rawdata(self): - """Tests for the convert_rawdata() function.""" - # trivial cases - self.assertEqual(analyse.convert_rawdata("0"), [0]) - with self.assertRaises(ValueError) as context: - analyse.convert_rawdata("") - self.assertEqual(str(context.exception), - "Raw Data contains a non-numeric value of ''.") - - # Single parenthesis - self.assertEqual(analyse.convert_rawdata("foo {10"), [10]) - self.assertEqual(analyse.convert_rawdata("20} bar"), [20]) - - # No parentheses - self.assertEqual(analyse.convert_rawdata("10,20 , 30"), [10, 20, 30]) - - # Dual parentheses - self.assertEqual(analyse.convert_rawdata("{10,20 , 30}"), [10, 20, 30]) - self.assertEqual(analyse.convert_rawdata("foo{10,20}bar"), [10, 20]) - - # Many parentheses - self.assertEqual(analyse.convert_rawdata("foo{10,20}{bar}"), [10, 20]) - self.assertEqual(analyse.convert_rawdata("foo{10,20}{bar}}{"), [10, 20]) - - # Bad parentheses - with self.assertRaises(ValueError) as context: - analyse.convert_rawdata("}10{") - self.assertEqual(str(context.exception), - "Raw Data not parsible due to parentheses placement.") - - # Non base-10 values - with self.assertRaises(ValueError) as context: - analyse.convert_rawdata("10, 20, foo, bar, 30") - self.assertEqual(str(context.exception), - "Raw Data contains a non-numeric value of 'foo'.") - - # A messy usual "good" case. - input_str = """uint16_t rawbuf[6] = { - 9008, 4496, 644, - 1660, 676, - - 530} - ;""" - self.assertEqual( - analyse.convert_rawdata(input_str), [9008, 4496, 644, 1660, 676, 530]) - - def test_parse_and_report(self): - """Tests for the parse_and_report() function.""" - - # Without code generation. - output = StringIO() - input_str = """ - uint16_t rawbuf[139] = {9008, 4496, 644, 1660, 676, 530, 648, 558, 672, - 1636, 646, 1660, 644, 556, 650, 584, 626, 560, 644, 580, 628, 1680, - 624, 560, 648, 1662, 644, 582, 648, 536, 674, 530, 646, 580, 628, - 560, 670, 532, 646, 562, 644, 556, 672, 536, 648, 1662, 646, 1660, - 652, 554, 644, 558, 672, 538, 644, 560, 668, 560, 648, 1638, 668, - 536, 644, 1660, 668, 532, 648, 560, 648, 1660, 674, 554, 622, 19990, - 646, 580, 624, 1660, 648, 556, 648, 558, 674, 556, 622, 560, 644, - 564, 668, 536, 646, 1662, 646, 1658, 672, 534, 648, 558, 644, 562, - 648, 1662, 644, 584, 622, 558, 648, 562, 668, 534, 670, 536, 670, - 532, 672, 536, 646, 560, 646, 558, 648, 558, 670, 534, 650, 558, - 646, 560, 646, 560, 668, 1638, 646, 1662, 646, 1660, 646, 1660, - 648};""" - analyse.parse_and_report(input_str, 200, False, output) - self.assertEqual( - output.getvalue(), 'Found 139 timing entries.\n' - 'Potential Mark Candidates:\n' - '[9008, 676]\n' - 'Potential Space Candidates:\n' - '[19990, 4496, 1680, 584]\n' - '\n' - 'Guessing encoding type:\n' - 'Looks like it uses space encoding. Yay!\n' - '\n' - 'Guessing key value:\n' - 'kHdrMark = 9008\n' - 'kHdrSpace = 4496\n' - 'kBitMark = 650\n' - 'kOneSpace = 1657\n' - 'kZeroSpace = 554\n' - 'kSpaceGap = 19990\n' - '\n' - 'Decoding protocol based on analysis so far:\n' - '\n' - 'kHdrMark+kHdrSpace+10011000010100000000011000001010010GAP(19990)\n' - ' Bits: 35\n' - ' Hex: 0x4C2803052 (MSB first)\n' - ' 0x250600A19 (LSB first)\n' - ' Dec: 20443050066 (MSB first)\n' - ' 9938405913 (LSB first)\n' - ' Bin: 0b10011000010100000000011000001010010 (MSB first)\n' - ' 0b01001010000011000000000101000011001 (LSB first)\n' - 'kBitMark(UNEXPECTED)01000000110001000000000000001111\n' - ' Bits: 32\n' - ' Hex: 0x40C4000F (MSB first)\n' - ' 0xF0002302 (LSB first)\n' - ' Dec: 1086586895 (MSB first)\n' - ' 4026540802 (LSB first)\n' - ' Bin: 0b01000000110001000000000000001111 (MSB first)\n' - ' 0b11110000000000000010001100000010 (LSB first)\n' - '\n' - 'Total Nr. of suspected bits: 67\n') - - # With code generation. - output = StringIO() - input_str = """ - uint16_t rawbuf[37] = {7930, 3952, 494, 1482, 520, 1482, 494, - 1508, 494, 520, 494, 1482, 494, 520, 494, 1482, 494, 1482, 494, - 3978, 494, 520, 494, 520, 494, 520, 494, 520, 520, 520, 494, 520, - 494, 520, 494, 1482, 494};""" - analyse.parse_and_report(input_str, 200, True, output) - self.assertEqual( - output.getvalue(), 'Found 37 timing entries.\n' - 'Potential Mark Candidates:\n' - '[7930, 520]\n' - 'Potential Space Candidates:\n' - '[3978, 1508, 520]\n' - '\n' - 'Guessing encoding type:\n' - 'Looks like it uses space encoding. Yay!\n' - '\n' - 'Guessing key value:\n' - 'kHdrMark = 7930\n' - 'kHdrSpace = 3965\n' - 'kBitMark = 496\n' - 'kOneSpace = 1485\n' - 'kZeroSpace = 520\n' - '\n' - 'Decoding protocol based on analysis so far:\n' - '\n' - 'kHdrMark+kHdrSpace+11101011\n' - ' Bits: 8\n' - ' Hex: 0xEB (MSB first)\n' - ' 0xD7 (LSB first)\n' - ' Dec: 235 (MSB first)\n' - ' 215 (LSB first)\n' - ' Bin: 0b11101011 (MSB first)\n' - ' 0b11010111 (LSB first)\n' - 'UNEXPECTED->kHdrSpace+00000001\n' - ' Bits: 8\n' - ' Hex: 0x01 (MSB first)\n' - ' 0x80 (LSB first)\n' - ' Dec: 1 (MSB first)\n' - ' 128 (LSB first)\n' - ' Bin: 0b00000001 (MSB first)\n' - ' 0b10000000 (LSB first)\n' - '\n' - 'Total Nr. of suspected bits: 16\n' - '\n' - 'Generating a VERY rough code outline:\n' - '\n' - "// WARNING: This probably isn't directly usable. It's a guide only.\n" - 'const uint16_t kHdrMark = 7930;\n' - 'const uint16_t kBitMark = 496;\n' - 'const uint16_t kHdrSpace = 3965;\n' - 'const uint16_t kOneSpace = 1485;\n' - 'const uint16_t kZeroSpace = 520;\n' - 'const uint16_t kXyzBits = 16;\n' - '// Function should be safe up to 64 bits.\n' - 'void IRsend::sendXyz(const uint64_t data, const uint16_t nbits,' - ' const uint16_t repeat) {\n' - ' enableIROut(38); // A guess. Most common frequency.\n' - ' for (uint16_t r = 0; r <= repeat; r++) {\n' - ' // Header\n' - ' mark(kHdrMark);\n' - ' space(kHdrSpace);\n' - ' // Data\n' - ' // e.g. data = 0xEB, nbits = 8\n' - ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' - ' true);\n' - ' // Footer\n' - ' mark(kBitMark);\n' - ' space(kHdrSpace);\n' - ' // Data\n' - ' // e.g. data = 0x1, nbits = 8\n' - ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' - ' true);\n' - ' // Footer\n' - ' mark(kBitMark);\n' - ' space(100000); // A 100% made up guess of the gap between' - ' messages.\n' - ' }\n' - '}\n') - - def test_unusual_gaps(self): - """Tests for unusual Space Gaps in parse_and_report() function.""" - - # Tests for unusual Gaps. (Issue #482) - output = StringIO() - input_str = """ - uint16_t rawbuf[272] = {3485, 3512, 864, 864, 864, 2620, 864, 864, - 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, - 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, - 864, 2620, 864, 864, 864, 2620, 864, 864, 864, 864, 864, 864, - 864, 864, 864, 864, 864, 864, 864, 864, 864, 2620, 864, 864, - 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, - 3485, 3512, 864, 864, 864, 2620, 864, 864, 864, 2620, 864, 2620, - 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 864, - 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, - 864, 2620, 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, - 864, 864, 864, 864, 2620, 864, 864, 864, 864, 864, 864, 864, 864, - 864, 864, 864, 864, - 3485, 3512, 864, 13996, - 3485, 3512, 864, 864, 864, 864, 864, 2620, 864, 864, 864, 2620, - 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 864, 864, 2620, - 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, - 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 864, - 864, 864, 864, 864, 864, 2620, 864, 2620, 864, 864, 864, 2620, - 864, 2620, 864, 864, 864, 864, - 3485, 3512, 864, 864, 864, 864, 864, 2620, 864, 864, 864, 2620, - 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 864, 864, 2620, - 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, - 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 864, - 864, 864, 864, 864, 864, 2620, 864, 2620, 864, 864, 864, 2620, - 864, 2620, 864, 864, 864, 864, 3485, 3512, 864, 13996};""" - analyse.parse_and_report(input_str, 200, True, output) - self.assertEqual( - output.getvalue(), 'Found 272 timing entries.\n' - 'Potential Mark Candidates:\n' - '[3485, 864]\n' - 'Potential Space Candidates:\n' - '[13996, 3512, 2620, 864]\n' - '\n' - 'Guessing encoding type:\n' - 'Looks like it uses space encoding. Yay!\n' - '\n' - 'Guessing key value:\n' - 'kHdrMark = 3485\n' - 'kHdrSpace = 3512\n' - 'kBitMark = 864\n' - 'kOneSpace = 2620\n' - 'kZeroSpace = 864\n' - 'kSpaceGap = 13996\n' - '\n' - 'Decoding protocol based on analysis so far:\n' - '\n' - 'kHdrMark+kHdrSpace+01011111010111110100000001000000\n' - ' Bits: 32\n' - ' Hex: 0x5F5F4040 (MSB first)\n' - ' 0x0202FAFA (LSB first)\n' - ' Dec: 1600077888 (MSB first)\n' - ' 33749754 (LSB first)\n' - ' Bin: 0b01011111010111110100000001000000 (MSB first)\n' - ' 0b00000010000000101111101011111010 (LSB first)\n' - 'kHdrMark+kHdrSpace+01011111010111110100000001000000\n' - ' Bits: 32\n' - ' Hex: 0x5F5F4040 (MSB first)\n' - ' 0x0202FAFA (LSB first)\n' - ' Dec: 1600077888 (MSB first)\n' - ' 33749754 (LSB first)\n' - ' Bin: 0b01011111010111110100000001000000 (MSB first)\n' - ' 0b00000010000000101111101011111010 (LSB first)\n' - 'kHdrMark+kHdrSpace+GAP(13996)' - 'kHdrMark+kHdrSpace+00101111001011110110110001101100\n' - ' Bits: 32\n' - ' Hex: 0x2F2F6C6C (MSB first)\n' - ' 0x3636F4F4 (LSB first)\n' - ' Dec: 791637100 (MSB first)\n' - ' 909571316 (LSB first)\n' - ' Bin: 0b00101111001011110110110001101100 (MSB first)\n' - ' 0b00110110001101101111010011110100 (LSB first)\n' - 'kHdrMark+kHdrSpace+00101111001011110110110001101100\n' - ' Bits: 32\n' - ' Hex: 0x2F2F6C6C (MSB first)\n' - ' 0x3636F4F4 (LSB first)\n' - ' Dec: 791637100 (MSB first)\n' - ' 909571316 (LSB first)\n' - ' Bin: 0b00101111001011110110110001101100 (MSB first)\n' - ' 0b00110110001101101111010011110100 (LSB first)\n' - 'kHdrMark+kHdrSpace+GAP(13996)\n' - 'Total Nr. of suspected bits: 128\n' - '\n' - 'Generating a VERY rough code outline:\n' - '\n' - "// WARNING: This probably isn't directly usable. It's a guide only.\n" - 'const uint16_t kHdrMark = 3485;\n' - 'const uint16_t kBitMark = 864;\n' - 'const uint16_t kHdrSpace = 3512;\n' - 'const uint16_t kOneSpace = 2620;\n' - 'const uint16_t kZeroSpace = 864;\n' - 'const uint16_t kSpaceGap = 13996;\n' - 'const uint16_t kXyzBits = 128;\n' - 'const uint16_t kXyzStateLength = 16;\n' - "// DANGER: More than 64 bits detected. A uint64_t for 'data' won't" - ' work!\n' - '// Function should be safe up to 64 bits.\n' - 'void IRsend::sendXyz(const uint64_t data, const uint16_t nbits,' - ' const uint16_t repeat) {\n' - ' enableIROut(38); // A guess. Most common frequency.\n' - ' for (uint16_t r = 0; r <= repeat; r++) {\n' - ' // Header\n' - ' mark(kHdrMark);\n' - ' space(kHdrSpace);\n' - ' // Data\n' - ' // e.g. data = 0x5F5F4040, nbits = 32\n' - ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' - ' true);\n' - ' // Header\n' - ' mark(kHdrMark);\n' - ' space(kHdrSpace);\n' - ' // Data\n' - ' // e.g. data = 0x5F5F4040, nbits = 32\n' - ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' - ' true);\n' - ' // Header\n' - ' mark(kHdrMark);\n' - ' space(kHdrSpace);\n' - ' // Gap\n' - ' mark(kBitMark);\n' - ' space(kSpaceGap);\n' - ' // Header\n' - ' mark(kHdrMark);\n' - ' space(kHdrSpace);\n' - ' // Data\n' - ' // e.g. data = 0x2F2F6C6C, nbits = 32\n' - ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' - ' true);\n' - ' // Header\n' - ' mark(kHdrMark);\n' - ' space(kHdrSpace);\n' - ' // Data\n' - ' // e.g. data = 0x2F2F6C6C, nbits = 32\n' - ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' - ' true);\n' - ' // Header\n' - ' mark(kHdrMark);\n' - ' space(kHdrSpace);\n' - ' // Gap\n' - ' mark(kBitMark);\n' - ' space(kSpaceGap);\n' - ' space(100000); // A 100% made up guess of the gap between' - ' messages.\n' - ' }\n' - '}\n' - '\n' - '\n' - '// Alternative >64 bit Function\n' - 'void IRsend::sendXyz(uint8_t data[], uint16_t nbytes, uint16_t repeat)' - ' {\n' - ' // nbytes should typically be kXyzStateLength\n' - ' // data should typically be:\n' - ' // uint8_t data[kXyzStateLength] = {0x5F, 0x5F, 0x40, 0x40, 0x5F,' - ' 0x5F, 0x40, 0x40, 0x2F, 0x2F, 0x6C, 0x6C, 0x2F, 0x2F, 0x6C, 0x6C};\n' - ' // data[] is assumed to be in MSB order for this code.\n' - ' for (uint16_t r = 0; r <= repeat; r++) {\n' - ' sendGeneric(kHdrMark, kHdrSpace,\n' - ' kBitMark, kOneSpace,\n' - ' kBitMark, kZeroSpace,\n' - ' kBitMark,\n' - ' 100000, // 100% made-up guess at the message gap.\n' - ' data, nbytes,\n' - ' 38000, // Complete guess of the modulation' - ' frequency.\n' - ' true, 0, 50);\n' - ' }\n' - '}\n') - - def test_reduce_list(self): - """Tests for the reduce_list method.""" - - ignore = StringIO() - message = analyse.RawIRMessage(200, [ - 7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, - 520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494, - 520, 520, 520, 494, 520, 494, 520, 494, 1482, 494 - ], ignore) - test_space_data = [4496, 1660, 530, 558, 1636, 1660, 556] - result_list, result_dict = message.reduce_list(test_space_data) - self.assertEqual([4496, 1660, 558], result_list) - self.assertEqual({ - 558: [558, 556, 530], - 1660: [1660, 1660, 1636], - 4496: [4496] - }, result_dict) - - def test_avg_list(self): - """Tests for the avg_list method.""" - - self.assertEqual(0, analyse.avg_list([])) - self.assertEqual(23, analyse.avg_list([10, 20, 40])) - - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/lib/IRremoteESP8266-2.6.5/CPPLINT.cfg b/lib/IRremoteESP8266-2.7.0/CPPLINT.cfg old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/CPPLINT.cfg rename to lib/IRremoteESP8266-2.7.0/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.6.5/LICENSE.txt b/lib/IRremoteESP8266-2.7.0/LICENSE.txt old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/LICENSE.txt rename to lib/IRremoteESP8266-2.7.0/LICENSE.txt diff --git a/lib/IRremoteESP8266-2.6.5/README.md b/lib/IRremoteESP8266-2.7.0/README.md old mode 100755 new mode 100644 similarity index 90% rename from lib/IRremoteESP8266-2.6.5/README.md rename to lib/IRremoteESP8266-2.7.0/README.md index c4cb31515..c609eb632 --- a/lib/IRremoteESP8266-2.6.5/README.md +++ b/lib/IRremoteESP8266-2.7.0/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.6.5 Now Available -Version 2.6.4 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.0 Now Available +Version 2.7.0 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. @@ -25,12 +25,12 @@ The most likely externally used `#define`s have been _aliased_ for limited backward compatibility for projects using the old style. Going forward, only the new `kConstantName` style will be supported for new protocol additions. -In the unlikely case it does break your code, then you may have been referencing +In the unlikely case, it does break your code, then you may have been referencing something you likely should not have. You should be able to quickly determine the new name from the old. e.g. `CONSTANT_NAME` to `kConstantName`. Use common sense or examining the library's code if this does affect code. -## Supported protocols +## Supported Protocols You can find the details of which protocols & devices are supported [here](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md). @@ -55,22 +55,22 @@ Some common answers to common questions and problems are on our [F.A.Q. wiki pag 1. Restart your Arduino IDE. 1. Check out the examples. -##### Using Git to install library ( Linux ) +##### Using Git to install the library ( Linux ) ``` cd ~/Arduino/libraries git clone https://github.com/crankyoldgit/IRremoteESP8266.git ``` -###### To Update to the latest version of the library +###### To update to the latest version of the library ``` cd ~/Arduino/libraries/IRremoteESP8266 && git pull ``` ## Contributing If you want to [contribute](.github/CONTRIBUTING.md#how-can-i-contribute) to this project, consider: -- [Report](.github/CONTRIBUTING.md#reporting-bugs) bugs and errors +- [Reporting](.github/CONTRIBUTING.md#reporting-bugs) bugs and errors - Ask for enhancements - Improve our documentation -- [Create issues](.github/CONTRIBUTING.md#reporting-bugs) and [pull requests](.github/CONTRIBUTING.md#pull-requests) +- [Creating issues](.github/CONTRIBUTING.md#reporting-bugs) and [pull requests](.github/CONTRIBUTING.md#pull-requests) - Tell other people about this library ## Contributors diff --git a/lib/IRremoteESP8266-2.7.0/README_fr.md b/lib/IRremoteESP8266-2.7.0/README_fr.md new file mode 100644 index 000000000..38581eeb0 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/README_fr.md @@ -0,0 +1,83 @@ +# IRremote ESP8266 Library + +[![Build Status](https://travis-ci.org/crankyoldgit/IRremoteESP8266.svg?branch=master)](https://travis-ci.org/crankyoldgit/IRremoteESP8266) +[![arduino-library-badge](https://www.ardu-badge.com/badge/IRremoteESP8266.svg?)](https://www.ardu-badge.com/IRremoteESP8266) +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/crankyoldgit/IRremoteESP8266.svg)](http://isitmaintained.com/project/crankyoldgit/IRremoteESP8266 "Average time to resolve an issue") +[![Percentage of issues still open](http://isitmaintained.com/badge/open/crankyoldgit/IRremoteESP8266.svg)](http://isitmaintained.com/project/crankyoldgit/IRremoteESP8266 "Percentage of issues still open") +[![GitLicense](https://gitlicense.com/badge/crankyoldgit/IRremoteESP8266)](https://gitlicense.com/license/crankyoldgit/IRremoteESP8266) + +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.0 disponible +Version 2.7.0 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. + +#### Mise à jour depuis pre-v2.5 +La librairie à changer, elle n'utilise plus les constantes déclarées comme `#define` mais comme : +[const](https://google.github.io/styleguide/cppguide.html#Constant_Names) avec le nom approprié par le langage +[C++ style guide](https://google.github.io/styleguide/cppguide.html). +Il se peut que d'ancien programme ne compile pas. +Le cas le plus utilisé de `#define`s à été remplacé par _aliased_ pour limiter +la compatibilité de revenir en arrière pour les vieux projet. En revenant en arrière seulement la +nouvelle `kConstantName` style est supporté. + +Dans le cas peu probable, votre code serait cassé, alors vous avez peut-être fait référence à +quelque chose que vous ne devriez probablement pas avoir.Vous devez être capable de determiner le nouveau nom +qui remplacera l'ancien. exemple : `CONSTANT_NAME` par `kConstantName`. +Si vous avez un problème examinez le code pour trouver le problème. + +## Protocoles supportés +Vous pouvez trouver le détails des protocoles et machines supportés +[here](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md). + +## Dépannage +Avant de reporter un probème ou de demander de l'aide, essayez de suivre notre [guide de dépannage](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide) first. + +## Questions fréquentes +Les questions les plus fréquentes sont ici, avec des réponses [F.A.Q. wiki page](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions). + +## Installation +##### Officiel releases avec l'Arduino IDE v1.8+ (Windows & Linux) +1. Cliquez sur _"Sketch"_ -> _"Include Library"_ -> _"Manage Libraries..."_ Menu items. +1. Entrez `IRremoteESP8266` dans le _"Filter your search..."_ barre de recherche en haut à droite. +1. Cliquez sur le IRremoteESP8266 pour avoir les résultats de la recherche. +1. Selectionnez la version que vous voulez installer et cliquez sur _"Install"_. + +##### Installation manuelle pour Windows +1. cliquez le boutton sur _"Clone or Download"_ , et _"[Download ZIP](https://github.com/crankyoldgit/IRremoteESP8266/archive->master.zip)"_ on the page. +1. Extraire l'archive. +1. renommez le fichier par _"IRremoteESP8266"_. +1. déplacer le fichier dans votre fichier de bibliothèques. (Pour windows : `C:\Users\VOTRE_NOM\Documents\Arduino\libraries\`) +1. Redemarrez arduino IDE. +1. Regardez les exemples. + +##### En utilisant GIT ( Linux ) +``` +cd ~/Arduino/libraries +git clone https://github.com/crankyoldgit/IRremoteESP8266.git +``` +###### Pour se mettre à jour +``` +cd ~/Arduino/libraries/IRremoteESP8266 && git pull +``` + +## Contribution +Si vous voulez [contribuer](.github/CONTRIBUTING.md#how-can-i-contribute) au projet, pour les erreurs: +- [Reporting](.github/CONTRIBUTING.md#reporting-bugs) bug et erreurs +- Demander des améliorations +- Améliorer notre documentation +- [Création d'issues](.github/CONTRIBUTING.md#reporting-bugs) et [pull requests](.github/CONTRIBUTING.md#pull-requests) +- Parlez de cettre librairie à d'autres personnes + +## Contributeurs +disponible [ici](.github/Contributors.md) + +## Historique de la bibliothèque +Elle est basée sur le travail de Shirriff (https://github.com/shirriff/Arduino-IRremote/) + +[Mark Szabo](https://github.com/crankyoldgit/IRremoteESP8266) à mis a jour la IRsend class pour qu'elle soit fonctionnelle sur ESP8266 et [Sebastien Warin](https://github.com/sebastienwarin/IRremoteESP8266) s'est occupé de la partie réception et décodage (IRrecv class). + +Comme pour la version 2.0, la bibliothèque à été completement réécrite avec les ressources sur ESP8266. diff --git a/lib/IRremoteESP8266-2.6.5/ReleaseNotes.md b/lib/IRremoteESP8266-2.7.0/ReleaseNotes.md old mode 100755 new mode 100644 similarity index 86% rename from lib/IRremoteESP8266-2.6.5/ReleaseNotes.md rename to lib/IRremoteESP8266-2.7.0/ReleaseNotes.md index 5672d2483..cdc5ad4a2 --- a/lib/IRremoteESP8266-2.6.5/ReleaseNotes.md +++ b/lib/IRremoteESP8266-2.7.0/ReleaseNotes.md @@ -1,5 +1,76 @@ # Release Notes +## _v2.7.0 (20191030)_ + +**[Bug Fixes]** +- auto_analyse: Fix > 64 bit send code generation. (#976) +- auto_analyse: Fix missing arguments in generated code for send64+ (#972) +- IRsendProntoDemo: Fix compile issue on ESP32 platform. (#938) +- IRMQTTServer: Fix compile error when `MQTT_ENABLE` is false. (#933) + +**[Features]** +- Add Hitachi 424 bit A/C support. (#975, #980, #981) +- Experimental detailed support for `DAIKIN152` (#971) +- Mitsubishi 112bit A/C support (#947, #968) +- gc_decode: Adding Support for Decoding codes in raw code format (#963) +- Refactor to use common routines/macros to handle bit manipulation. (#934) +- Use centralised common strings. Saves ~1.5k of program space. (#946) +- Add Internationalisation (i18n) / Locale support. (#946, #955, #966) + - `de-CH`: Swiss German. (#949, #954) + - `de-DE`: German. (#946, #950, #952) + - `en-AU`: English/Australia (Default locale) (#946) + - `en-IE`: English/Ireland (#946) + - `en-UK`: English/United Kingdom (#946) + - `en-US`: English/United States (#946) + - `es-ES`: Spanish. (#953) + - `fr-FR`: French. (#962) +- Port CI pipeline to PlatformIO (#936) + +**[Misc]** +- Add DAIKIN128 & DAIKIN152 to `decodeToState()` (#982) +- auto_analyse: Produce better code when leader is detected. (#977) +- Coolix A/C improvements (#944) +- A/C setRaw/getRaw/stateReset() cleanup. (#967) +- Add documentation on how to use & support the i18n aspects of the library. +- Make travis checks faster. (#957) +- Translate README.md to french (#959) +- Fixed Coolix kCoolixDefaultState (#941) +- Improve generation of list of pio projects. (#940) + + +## _v2.6.6 (20190923)_ + +**[Bug Fixes]** +- Ensure `begin()` is called for every supported common a/c. (#905, #899) +- IRMQTTServer: Fix JSON state parsing. (#896) +- IRMQTTServer: Fix compilation error when `MQTT_CLIMATE_JSON` is `true`. (#893) + +**[Features]** +- Mitsubishi136: Full A/C support. (#898, #890) +- Fujitsu: Add support for ARRY4 remote. (#895) +- Web-AC-control: Add new WebUI example sketch. (#880, #886) +- Improve Common A/C API (#913) +- IRMQTTServer: Support for multiple climates. (#903) +- IRMQTTServer: Add TX channel support for HTTP interface. (#929) +- IRMQTTServer: Add option to clear retained settings. (#917) +- auto_analyse_raw_data.py: Add decode code generation. (#909) +- auto_analyse_raw_data.py: General improvements (#906) + +**[Misc]** +- IRMQTTServer: Use latest API for common A/C. (#928) +- IRMQTTServer: Add flag & documentation for Home Assistant mode. (#919) +- IRMQTTServer: Move from ArduinoJson v5 to v6. (#878) +- IRMQTTServer: Use retain for discovery message. (#881) +- Goodweather: Adjust timings & minor fixes. (#924) +- PanasonicAc: Add better SwingV support for common a/c framework. (#923) +- Daikin2: Corrections for common A/C interface. (#910) +- MitsubishiAC: Improve decoding. (#914) +- Fujitsu: Disable horiz swing for ARRY4. (#907) +- SamsungAc: Only send power on/off code if it's needed. (#884) +- Teco: Add timer support. (#883) +- More consistent A/C `::toString()` output. (#920) + + ## _v2.6.5 (20190828)_ **[Bug Fixes]** diff --git a/lib/IRremoteESP8266-2.6.5/SupportedProtocols.md b/lib/IRremoteESP8266-2.7.0/SupportedProtocols.md old mode 100755 new mode 100644 similarity index 89% rename from lib/IRremoteESP8266-2.6.5/SupportedProtocols.md rename to lib/IRremoteESP8266-2.7.0/SupportedProtocols.md index c9d286973..afd31587e --- a/lib/IRremoteESP8266-2.6.5/SupportedProtocols.md +++ b/lib/IRremoteESP8266-2.7.0/SupportedProtocols.md @@ -1,6 +1,6 @@ + Last generated: Wed Oct 30 13:41:10 2019 ---> # IR Protocols supported by this library | Protocol | Brand | Model | A/C Model | Detailed A/C Support | @@ -11,21 +11,22 @@ | [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 | | [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)** | AR-DB1 remote
      AR-RAE1E remote
      AR-RAH2E remote
      AR-REB1E remote
      AST9RSGCW A/C
      ASYG30LFCA A/C
      ASYG7LMCA A/C | ARDB1
      ARJW2
      ARRAH2E
      ARREB1E | 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 | 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 | | [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 | 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 | +| [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 | | [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
      RAS-35THA6 remote
      Series VI A/C (Circa 2007) | | 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 | | - | | [JVC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_JVC.cpp) | **Unknown** | | | - | | [Kelvinator](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.cpp) | **[Green](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.h)** | YAPOF3 remote | | Yes | @@ -39,12 +40,13 @@ | [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Comfee](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | MPD1-12CRN7 A/C | | Yes | | [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Keystone](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG57H4(B)BGEF remote | | Yes | | [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Pioneer System](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RUBO18GMFILCAD A/C (18K BTU)
      RYBO12GMFILCAD A/C (12K BTU) | | Yes | -| [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | HC3000 Projector
      TV | | Yes | +| [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | HC3000 Projector
      KM14A 0179213 remote
      MS-GK24VA A/C
      TV | | Yes | +| [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) | **[Yamaha](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | RAV561 remote
      RXV585B A/V Receiver | | Yes | | [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 | CKP
      DKE
      JKE
      LKE
      NKE
      RKR | 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)
      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 | | [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** | | | - | @@ -59,16 +61,18 @@ | [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 | DG11J13A
      DG11J191 | 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 | | [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 ## Send & decodable protocols: @@ -97,6 +101,7 @@ - HITACHI_AC - HITACHI_AC1 - HITACHI_AC2 +- HITACHI_AC424 - INAX - JVC - KELVINATOR @@ -108,6 +113,7 @@ - MAGIQUEST - MIDEA - MITSUBISHI +- MITSUBISHI136 - MITSUBISHI2 - MITSUBISHI_AC - MITSUBISHI_HEAVY_152 @@ -132,10 +138,10 @@ - SHARP - SHARP_AC - SONY -- TCL112AC - TECO - TOSHIBA_AC - TROTEC - VESTEL_AC - WHIRLPOOL_AC - WHYNTER +- typeguess diff --git a/lib/IRremoteESP8266-2.7.0/examples/CommonAcControl/CommonAcControl.ino b/lib/IRremoteESP8266-2.7.0/examples/CommonAcControl/CommonAcControl.ino new file mode 100644 index 000000000..4e11e631d --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/CommonAcControl/CommonAcControl.ino @@ -0,0 +1,72 @@ +/* Copyright 2019 David Conran +* +* This example code demonstrates how to use the "Common" IRac class to control +* various air conditions. The IRac class does not support all the features +* for every protocol. Some have more detailed support that what the "Common" +* interface offers, and some only have a limited subset of the "Common" options. +* +* This example code will: +* o Try to turn on, then off every fully supported A/C protocol we know of. +* o It will try to put the A/C unit into Cooling mode at 25C, with a medium +* fan speed, and no fan swinging. +* Note: Some protocols support multiple models, only the first model is tried. +* +*/ +#include +#include +#include +#include + +const uint16_t kIrLed = 4; // The ESP GPIO pin to use that controls the IR LED. +IRac ac(kIrLed); // Create a A/C object using GPIO to sending messages with. + +void setup() { + Serial.begin(115200); + delay(200); + + // Set up what we want to send. + // See state_t, opmode_t, fanspeed_t, swingv_t, & swingh_t in IRsend.h for + // all the various options. + ac.next.protocol = decode_type_t::DAIKIN; // Set a protocol to use. + ac.next.model = 1; // Some A/Cs have different models. Try just the first. + ac.next.mode = stdAc::opmode_t::kCool; // Run in cool mode initially. + ac.next.celsius = true; // Use Celsius for temp units. False = Fahrenheit + ac.next.degrees = 25; // 25 degrees. + ac.next.fanspeed = stdAc::fanspeed_t::kMedium; // Start the fan at medium. + ac.next.swingv = stdAc::swingv_t::kOff; // Don't swing the fan up or down. + ac.next.swingh = stdAc::swingh_t::kOff; // Don't swing the fan left or right. + ac.next.light = false; // Turn off any LED/Lights/Display that we can. + ac.next.beep = false; // Turn off any beep from the A/C if we can. + ac.next.econo = false; // Turn off any economy modes if we can. + ac.next.filter = false; // Turn off any Ion/Mold/Health filters if we can. + ac.next.turbo = false; // Don't use any turbo/powerful/etc modes. + ac.next.quiet = false; // Don't use any quiet/silent/etc modes. + ac.next.sleep = -1; // Don't set any sleep time or modes. + ac.next.clean = false; // Turn off any Cleaning options if we can. + ac.next.clock = -1; // Don't set any current time if we can avoid it. + ac.next.power = false; // Initially start with the unit off. + + Serial.println("Try to turn on & off every supported A/C type ..."); +} + +void loop() { + // For every protocol the library has ... + for (int i = 1; i < kLastDecodeType; i++) { + decode_type_t protocol = (decode_type_t)i; + // If the protocol is supported by the IRac class ... + if (ac.isProtocolSupported(protocol)) { + Serial.println("Protocol " + String(protocol) + " / " + + typeToString(protocol) + " is supported."); + ac.next.protocol = protocol; // Change the protocol used. + ac.next.power = true; // We want to turn on the A/C unit. + Serial.println("Sending a message to turn ON the A/C unit."); + ac.sendAc(); // Have the IRac class create and send a message. + delay(5000); // Wait 5 seconds. + ac.next.power = false; // Now we want to turn the A/C off. + Serial.println("Send a message to turn OFF the A/C unit."); + ac.sendAc(); // Send the message. + delay(1000); // Wait 1 second. + } + } + Serial.println("Starting from the begining again ..."); +} diff --git a/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/CommonAcControl/platformio.ini old mode 100755 new mode 100644 similarity index 86% rename from lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/platformio.ini rename to lib/IRremoteESP8266-2.7.0/examples/CommonAcControl/platformio.ini index 1aba0afcc..e6f6320da --- a/lib/IRremoteESP8266-2.6.5/examples/CommonAcControl/platformio.ini +++ b/lib/IRremoteESP8266-2.7.0/examples/CommonAcControl/platformio.ini @@ -5,14 +5,13 @@ src_dir = . lib_extra_dirs = ../../ lib_ldf_mode = deep+ lib_ignore = examples -build_flags = +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU [env:nodemcuv2] platform = espressif8266 -framework = arduino board = nodemcuv2 [env:esp32dev] platform = espressif32 -framework = arduino board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/ControlSamsungAC.ino b/lib/IRremoteESP8266-2.7.0/examples/ControlSamsungAC/ControlSamsungAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/ControlSamsungAC.ino rename to lib/IRremoteESP8266-2.7.0/examples/ControlSamsungAC/ControlSamsungAC.ino diff --git a/lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/ControlSamsungAC/platformio.ini old mode 100755 new mode 100644 similarity index 86% rename from lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/platformio.ini rename to lib/IRremoteESP8266-2.7.0/examples/ControlSamsungAC/platformio.ini index 1aba0afcc..e6f6320da --- a/lib/IRremoteESP8266-2.6.5/examples/ControlSamsungAC/platformio.ini +++ b/lib/IRremoteESP8266-2.7.0/examples/ControlSamsungAC/platformio.ini @@ -5,14 +5,13 @@ src_dir = . lib_extra_dirs = ../../ lib_ldf_mode = deep+ lib_ignore = examples -build_flags = +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU [env:nodemcuv2] platform = espressif8266 -framework = arduino board = nodemcuv2 [env:esp32dev] platform = espressif32 -framework = arduino board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/DumbIRRepeater.ino b/lib/IRremoteESP8266-2.7.0/examples/DumbIRRepeater/DumbIRRepeater.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/DumbIRRepeater.ino rename to lib/IRremoteESP8266-2.7.0/examples/DumbIRRepeater/DumbIRRepeater.ino diff --git a/lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/DumbIRRepeater/platformio.ini old mode 100755 new mode 100644 similarity index 86% rename from lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/platformio.ini rename to lib/IRremoteESP8266-2.7.0/examples/DumbIRRepeater/platformio.ini index 1aba0afcc..e6f6320da --- a/lib/IRremoteESP8266-2.6.5/examples/DumbIRRepeater/platformio.ini +++ b/lib/IRremoteESP8266-2.7.0/examples/DumbIRRepeater/platformio.ini @@ -5,14 +5,13 @@ src_dir = . lib_extra_dirs = ../../ lib_ldf_mode = deep+ lib_ignore = examples -build_flags = +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU [env:nodemcuv2] platform = espressif8266 -framework = arduino board = nodemcuv2 [env:esp32dev] platform = espressif32 -framework = arduino board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/IRGCSendDemo.ino b/lib/IRremoteESP8266-2.7.0/examples/IRGCSendDemo/IRGCSendDemo.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/IRGCSendDemo.ino rename to lib/IRremoteESP8266-2.7.0/examples/IRGCSendDemo/IRGCSendDemo.ino diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/IRGCSendDemo/platformio.ini old mode 100755 new mode 100644 similarity index 86% rename from lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.0/examples/IRGCSendDemo/platformio.ini index 1aba0afcc..e6f6320da --- a/lib/IRremoteESP8266-2.6.5/examples/IRGCSendDemo/platformio.ini +++ b/lib/IRremoteESP8266-2.7.0/examples/IRGCSendDemo/platformio.ini @@ -5,14 +5,13 @@ src_dir = . lib_extra_dirs = ../../ lib_ldf_mode = deep+ lib_ignore = examples -build_flags = +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU [env:nodemcuv2] platform = espressif8266 -framework = arduino board = nodemcuv2 [env:esp32dev] platform = espressif32 -framework = arduino board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/IRGCTCPServer.ino b/lib/IRremoteESP8266-2.7.0/examples/IRGCTCPServer/IRGCTCPServer.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/IRGCTCPServer/IRGCTCPServer.ino rename to lib/IRremoteESP8266-2.7.0/examples/IRGCTCPServer/IRGCTCPServer.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/IRGCTCPServer/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/IRGCTCPServer/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/IRGCTCPServer/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.h b/lib/IRremoteESP8266-2.7.0/examples/IRMQTTServer/IRMQTTServer.h old mode 100755 new mode 100644 similarity index 88% rename from lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.h rename to lib/IRremoteESP8266-2.7.0/examples/IRMQTTServer/IRMQTTServer.h index 73821dc05..eb5a4e37f --- a/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.h +++ b/lib/IRremoteESP8266-2.7.0/examples/IRMQTTServer/IRMQTTServer.h @@ -68,7 +68,7 @@ const IPAddress kSubnetMask = IPAddress(255, 255, 255, 0); #endif // USE_STATIC_IP // See: https://github.com/tzapu/WiFiManager#filter-networks for these settings. -#define HIDE_DUPLIATE_NETWORKS false // Should WifiManager hide duplicate SSIDs +#define HIDE_DUPLICATE_NETWORKS false // Make WifiManager hide duplicate SSIDs // #define MIN_SIGNAL_STRENGTH 20 // Minimum WiFi signal stength (percentage) // before we will connect. // The unset default is 8%. @@ -100,6 +100,11 @@ const uint32_t kMqttReconnectTime = 5000; // Delay(ms) between reconnect tries. #define MQTT_CLIMATE_STAT "stat" // Sub-topic for the climate stat topics. // Enable sending/receiving climate via JSON. `true` cost ~5k of program space. #define MQTT_CLIMATE_JSON false +// Use Home Assistant-style operation modes. +// i.e. Change the climate mode to "off" when turning the power "off". +// See: https://www.home-assistant.io/components/climate.mqtt/#modes +// Change to false, if your home automation system doesn't like this. +#define MQTT_CLIMATE_HA_MODE true // Do we send an IR message when we reboot and recover the existing A/C state? // If set to `false` you may miss requested state changes while the ESP was // down. If set to `true`, it will resend the previous desired state sent to the @@ -109,9 +114,15 @@ const uint32_t kMqttReconnectTime = 5000; // Delay(ms) between reconnect tries. #define QOS 1 // MQTT broker should queue up any unreceived messages for us // #define QOS 0 // MQTT broker WON'T queue up messages for us. Fire & Forget. + // Enable(true)/Disable(false) the option to send a MQTT Discovery message for -// the AirCon/Climate system to Home Assistant. `false` saves ~1.5k. +// the AirCon/Climate system to Home Assistant. Note: `false` saves ~1.5k. #define MQTT_DISCOVERY_ENABLE true +// Enable(true)/Disable(false) the option to clear any settings stored in MQTT +// for this device's current config. e.g. Climate states using MQTT retain. +// In theory, you shouldn't need this as you can always clean up by hand, hence +// it is disabled by default. Note: `false` saves ~1.2k. +#define MQTT_CLEAR_ENABLE false #endif // MQTT_ENABLE // ------------------------ IR Capture Settings -------------------------------- @@ -195,6 +206,7 @@ const uint16_t kMinUnknownSize = 2 * 10; #define KEY_CODE "code" #define KEY_BITS "bits" #define KEY_REPEAT "repeats" +#define KEY_CHANNEL "channel" // Which IR TX channel to send on. // GPIO html/config keys #define KEY_TX_GPIO "tx" @@ -209,6 +221,11 @@ const uint8_t kPortLength = 5; // Largest value of uint16_t is "65535". const uint8_t kUsernameLength = 15; const uint8_t kPasswordLength = 20; +// -------------------------- Json Settings ------------------------------------ + +const uint16_t kJsonConfigMaxSize = 512; // Bytes +const uint16_t kJsonAcStateMaxSize = 1024; // Bytes + // -------------------------- Debug Settings ----------------------------------- // Debug output is disabled if any of the IR pins are on the TX (D1) pin. // See `isSerialGpioUsedByIr()`. @@ -220,7 +237,7 @@ const uint8_t kPasswordLength = 20; // ----------------- End of User Configuration Section ------------------------- // Constants -#define _MY_VERSION_ "v1.3.4" +#define _MY_VERSION_ "v1.4.4" const uint8_t kRebootTime = 15; // Seconds const uint8_t kQuickDisplayTime = 2; // Seconds @@ -267,10 +284,13 @@ const char* kUrlGpioSet = "/gpio/set"; const char* kUrlInfo = "/info"; const char* kUrlReboot = "/quitquitquit"; const char* kUrlWipe = "/reset"; +const char* kUrlClearMqtt = "/clear_retained"; #if MQTT_ENABLE const uint32_t kBroadcastPeriodMs = MQTTbroadcastInterval * 1000; // mSeconds. -const uint32_t kStatListenPeriodMs = 5 * 1000; // mSeconds +// How long should we listen to recover for previous states? +// Default is 5 seconds per IR TX GPIOs (channels) used. +const uint32_t kStatListenPeriodMs = 5 * 1000 * kNrOfIrTxGpios; // mSeconds const int32_t kMaxPauseMs = 10000; // 10 Seconds. const char* kSequenceDelimiter = ";"; const char kPauseChar = 'P'; @@ -290,6 +310,12 @@ const char* kClimateTopics = "|" KEY_JSON #endif // MQTT_CLIMATE_JSON ")
      "; +const char* kMqttTopics[] = { + KEY_PROTOCOL, KEY_MODEL, KEY_POWER, KEY_MODE, KEY_TEMP, KEY_FANSPEED, + KEY_SWINGV, KEY_SWINGH, KEY_QUIET, KEY_TURBO, KEY_LIGHT, KEY_BEEP, + KEY_ECONO, KEY_SLEEP, KEY_FILTER, KEY_CLEAN, KEY_CELSIUS, KEY_RESEND, + KEY_JSON}; // KEY_JSON needs to be the last one. + void mqttCallback(char* topic, byte* payload, unsigned int length); String listOfCommandTopics(void); @@ -303,12 +329,13 @@ void receivingMQTT(String const topic_name, String const callback_str); void callback(char* topic, byte* payload, unsigned int length); void sendMQTTDiscovery(const char *topic); void doBroadcast(TimerMs *timer, const uint32_t interval, - const stdAc::state_t state, const bool retain, + IRac *climates[], const bool retain, const bool force); #if MQTT_CLIMATE_JSON -stdAc::state_t jsonToState(const stdAc::state_t current, const String str); +stdAc::state_t jsonToState(const stdAc::state_t current, const char *str); void sendJsonState(const stdAc::state_t state, const String topic, - const bool retain = false, const bool ha_mode = true); + const bool retain = false, + const bool ha_mode = MQTT_CLIMATE_HA_MODE); #endif // MQTT_CLIMATE_JSON #endif // MQTT_ENABLE #if REPORT_VCC @@ -327,6 +354,7 @@ String gpioToString(const int16_t gpio); uint8_t getDefaultIrSendIdx(void); IRsend* getDefaultIrSendPtr(void); int8_t getDefaultTxGpio(void); +String genStatTopic(const uint16_t channel = 0); String listOfTxGpios(void); bool hasUnsafeHTMLChars(String input); String htmlHeader(const String title, const String h1_text = ""); @@ -382,12 +410,11 @@ bool sendInt(const String topic, const int32_t num, const bool retain); bool sendBool(const String topic, const bool on, const bool retain); bool sendString(const String topic, const String str, const bool retain); bool sendFloat(const String topic, const float_t temp, const bool retain); -stdAc::state_t updateClimate(stdAc::state_t current, const String str, - const String prefix, const String payload); +void updateClimate(stdAc::state_t *current, const String str, + const String prefix, const String payload); bool cmpClimate(const stdAc::state_t a, const stdAc::state_t b); -bool sendClimate(const stdAc::state_t prev, const stdAc::state_t next, - const String topic_prefix, const bool retain, +bool sendClimate(const String topic_prefix, const bool retain, const bool forceMQTT, const bool forceIR, - const bool enableIR = true); + const bool enableIR = true, IRac *ac = NULL); bool decodeCommonAc(const decode_results *decode); #endif // EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_ diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.ino b/lib/IRremoteESP8266-2.7.0/examples/IRMQTTServer/IRMQTTServer.ino old mode 100755 new mode 100644 similarity index 84% rename from lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.ino rename to lib/IRremoteESP8266-2.7.0/examples/IRMQTTServer/IRMQTTServer.ino index 730a8965f..6373181a0 --- a/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/IRMQTTServer.ino +++ b/lib/IRremoteESP8266-2.7.0/examples/IRMQTTServer/IRMQTTServer.ino @@ -31,7 +31,7 @@ * * - Arduino IDE: * o Install the following libraries via Library Manager - * - ArduinoJson (https://arduinojson.org/) (Version >= 5.0 and < 6.0) + * - ArduinoJson (https://arduinojson.org/) (Version >= 6.0) * - PubSubClient (https://pubsubclient.knolleary.net/) * - WiFiManager (https://github.com/tzapu/WiFiManager) * (ESP8266: Version >= 0.14, ESP32: 'development' branch.) @@ -72,10 +72,14 @@ * http:///ir?type=31&code=40000,1,1,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1058 * http:///ir?type=18&code=190B8050000000E0190B8070000010f0 * http:///ir?repeats=1&type=25&code=0000,006E,0022,0002,0155,00AA,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0040,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0040,0015,0040,0015,0040,0015,0640,0155,0055,0015,0E40 + * If you have enabled more than 1 TX GPIO, you can use the "channel" argument: + * http:///ir?channel=0&type=7&code=E0E09966 + * http:///ir?channel=1&type=7&code=E0E09966 * * or * - * Send a MQTT message to the topic 'ir_server/send' (or 'ir_server/send_0' etc) + * Send a MQTT message to the topic 'ir_server/send' + * (or 'ir_server/send_1' etc if you have enabled more than 1 TX GPIO) * using the following format (Order is important): * protocol_num,hexcode * e.g. 7,E0E09966 @@ -177,10 +181,13 @@ * * ### via MQTT: * The code listen for commands (via wildcard) on the MQTT topics at the - * `ir_server/ac/cmnd/+` level, such as: + * `ir_server/ac/cmnd/+` level (or ir_server/ac_1/cmnd/+` if multiple TX GPIOs) + * such as: * i.e. protocol, model, power, mode, temp, fanspeed, swingv, swingh, quiet, * turbo, light, beep, econo, sleep, filter, clean, use_celsius - * e.g. ir_server/ac/cmnd/power, ir_server/ac/cmnd/temp, etc. + * e.g. ir_server/ac/cmnd/power, ir_server/ac/cmnd/temp, + * ir_server/ac_0/cmnd/mode, ir_server/ac_2/cmnd/fanspeed, etc. + * It will process them, and if successful and it caused a change, it will * acknowledge this via the relevant state topic for that command. * e.g. If the aircon/climate changes from power off to power on, it will @@ -262,14 +269,30 @@ * temp_step: 1 * retain: false * + * #### 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 + * 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. + * + * If you no longer want it, manually remove it from your MQTT broker. + * e.g. + * `mosquitto_pub -t homeassistant/climate/ir_server/config -n -r -d` + * + * NOTE: If you have multiple TX GPIOs configured, it *ONLY* works for the + * first TX GPIO climate. You will need to manually configure the others. + * * ### via HTTP: * Use the "http:///aircon/set" URL and pass on * the arguments as needed to control your device. See the `KEY_*` #defines * in the code for all the parameters. * i.e. protocol, model, power, mode, temp, fanspeed, swingv, swingh, quiet, - * turbo, light, beep, econo, sleep, filter, clean, use_celsius + * turbo, light, beep, econo, sleep, filter, clean, use_celsius, channel * Example: - * http:///aircon/set?protocol=PANASONIC_AC&model=LKE&power=on&mode=auto&fanspeed=min&temp=23 + * http:///aircon/set?channel=0&protocol=PANASONIC_AC&model=LKE&power=on&mode=auto&fanspeed=min&temp=23 + * + * NOTE: If you don't set the channel, the first GPIO (Channel 0) is used. * * ## Debugging & Logging * If DEBUG is turned on, there is additional information printed on the Serial @@ -388,9 +411,9 @@ uint32_t irRecvCounter = 0; #endif // IR_RX // Climate stuff -stdAc::state_t climate; -stdAc::state_t climate_prev; -IRac *commonAc = NULL; +IRac *climate[kNrOfIrTxGpios]; +String channel_re = "("; // Will be built later. +uint16_t chan = 0; // The channel to use for the aircon HTML page. TimerMs lastClimateIr = TimerMs(); // When we last sent the IR Climate mesg. uint32_t irClimateCounter = 0; // How many have we sent? @@ -423,7 +446,6 @@ String MqttLog; // Topic we send log messages to. String MqttLwt; // Topic for the Last Will & Testament. String MqttClimate; // Sub-topic for the climate topics. String MqttClimateCmnd; // Sub-topic for the climate command topics. -String MqttClimateStat; // Sub-topic for the climate stat topics. #if MQTT_DISCOVERY_ENABLE String MqttDiscovery; #endif // MQTT_DISCOVERY_ENABLE @@ -434,8 +456,10 @@ String MqttClientId; bool lockMqttBroadcast = true; TimerMs lastBroadcast = TimerMs(); // When we last sent a broadcast. bool hasBroadcastBeenSent = false; +#if MQTT_DISCOVERY_ENABLE TimerMs lastDiscovery = TimerMs(); // When we last sent a Discovery. bool hasDiscoveryBeenSent = false; +#endif // MQTT_DISCOVERY_ENABLE TimerMs statListenTime = TimerMs(); // How long we've been listening for. #endif // MQTT_ENABLE @@ -455,7 +479,7 @@ bool isSerialGpioUsedByIr(void) { return true; // Serial port is in use by IR capture. Abort. } #endif // IR_RX - for (uint8_t i = 0; i < kNrOfIrTxGpios; i++) + for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) switch (txGpioTable[i]) { #if defined(ESP32) case kSerialRxGpio: @@ -467,6 +491,8 @@ bool isSerialGpioUsedByIr(void) { } // Debug messages get sent to the serial port. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" void debug(const char *str) { #if DEBUG if (isSerialGpioUsedByIr()) return; // Abort. @@ -474,6 +500,7 @@ void debug(const char *str) { Serial.printf("%07u.%03u: %s\n", now / 1000, now % 1000, str); #endif // DEBUG } +#pragma GCC diagnostic pop // callback notifying us of the need to save the wifi config void saveWifiConfigCallback(void) { @@ -502,8 +529,7 @@ bool mountSpiffs(void) { bool saveConfig(void) { debug("Saving the config."); bool success = false; - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); + DynamicJsonDocument json(kJsonConfigMaxSize); #if MQTT_ENABLE json[kMqttServerKey] = MqttServer; json[kMqttPortKey] = MqttPort; @@ -528,7 +554,7 @@ bool saveConfig(void) { debug("Failed to open config file for writing."); } else { debug("Writing out the config file."); - json.printTo(configFile); + serializeJson(json, configFile); configFile.close(); debug("Finished writing config file."); success = true; @@ -553,9 +579,8 @@ bool loadConfigFile(void) { std::unique_ptr buf(new char[size]); configFile.readBytes(buf.get(), size); - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.parseObject(buf.get()); - if (json.success()) { + DynamicJsonDocument json(kJsonConfigMaxSize); + if (!deserializeJson(json, buf.get(), kJsonConfigMaxSize)) { debug("Json config file parsed ok."); #if MQTT_ENABLE strncpy(MqttServer, json[kMqttServerKey] | "", kHostnameLength); @@ -621,7 +646,7 @@ String gpioToString(const int16_t gpio) { } int8_t getDefaultTxGpio(void) { - for (int8_t i = 0; i < kNrOfIrTxGpios; i++) + for (int16_t i = 0; i < kNrOfIrTxGpios; i++) if (txGpioTable[i] != kGpioUnused) return txGpioTable[i]; return kGpioUnused; } @@ -630,7 +655,7 @@ int8_t getDefaultTxGpio(void) { String listOfTxGpios(void) { bool found = false; String result = ""; - for (uint8_t i = 0; i < kNrOfIrTxGpios; i++) { + for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) { if (i) result += ", "; result += gpioToString(txGpioTable[i]); if (!found && txGpioTable[i] == getDefaultTxGpio()) { @@ -902,6 +927,17 @@ String htmlSelectModel(const String name, const int16_t def) { return html; } +String htmlSelectUint(const String name, const uint16_t max, + const uint16_t def) { + String html = ""); + return html; +} + String htmlSelectGpio(const String name, const int16_t def, const int8_t list[], const int16_t length) { String html = ": " - "" - "Fan Speed" + - htmlSelectFanspeed(KEY_FANSPEED, climate.fanspeed) + "" - "Swing (V)" + - htmlSelectSwingv(KEY_SWINGV, climate.swingv) + "" - "Swing (H)" + - htmlSelectSwingh(KEY_SWINGH, climate.swingh) + "" - "Quiet" + htmlSelectBool(KEY_QUIET, climate.quiet) + - "" - "Turbo" + htmlSelectBool(KEY_TURBO, climate.turbo) + - "" - "Econo" + htmlSelectBool(KEY_ECONO, climate.econo) + - "" - "Light" + htmlSelectBool(KEY_LIGHT, climate.light) + - "" - "Filter" + htmlSelectBool(KEY_FILTER, climate.filter) + - "" - "Clean" + htmlSelectBool(KEY_CLEAN, climate.clean) + - "" - "Beep" + htmlSelectBool(KEY_BEEP, climate.beep) + - "" - "Force resend" + htmlSelectBool(KEY_RESEND, false) + - "" - "" - "" - ""; + if (kNrOfIrTxGpios > 1) { + html += "
      " + "" + "" + "
      Climate #" + + htmlSelectUint(KEY_CHANNEL, kNrOfIrTxGpios, chan) + + "" + "
      " + "
      " + "
      "; + } + if (climate[chan] != NULL) { + html += "

      Current Settings

      " + "
      " + "" + + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
      Protocol" + + htmlSelectClimateProtocol(KEY_PROTOCOL, + climate[chan]->next.protocol) + + "
      Model" + + htmlSelectModel(KEY_MODEL, climate[chan]->next.model) + + "
      Power" + + htmlSelectBool(KEY_POWER, climate[chan]->next.power) + + "
      Mode" + + htmlSelectMode(KEY_MODE, climate[chan]->next.mode) + + "
      Temp" + "" + "
      Fan Speed" + + htmlSelectFanspeed(KEY_FANSPEED, climate[chan]->next.fanspeed) + + "
      Swing (V)" + + htmlSelectSwingv(KEY_SWINGV, climate[chan]->next.swingv) + + "
      Swing (H)" + + htmlSelectSwingh(KEY_SWINGH, climate[chan]->next.swingh) + + "
      Quiet" + + htmlSelectBool(KEY_QUIET, climate[chan]->next.quiet) + + "
      Turbo" + + htmlSelectBool(KEY_TURBO, climate[chan]->next.turbo) + + "
      Econo" + + htmlSelectBool(KEY_ECONO, climate[chan]->next.econo) + + "
      Light" + + htmlSelectBool(KEY_LIGHT, climate[chan]->next.light) + + "
      Filter" + + htmlSelectBool(KEY_FILTER, climate[chan]->next.filter) + + "
      Clean" + + htmlSelectBool(KEY_CLEAN, climate[chan]->next.clean) + + "
      Beep" + + htmlSelectBool(KEY_BEEP, climate[chan]->next.beep) + + "
      Force resend" + + htmlSelectBool(KEY_RESEND, false) + + "
      " + "" + "
      "; + } html += htmlEnd(); server.send(200, "text/html", html); } @@ -1043,26 +1113,40 @@ void handleAirConSet(void) { return server.requestAuthentication(); } #endif - stdAc::state_t result = climate; debug("New common a/c received via HTTP"); - bool force_resend = false; - for (uint16_t i = 0; i < server.args(); i++) { - if (server.argName(i).equals(KEY_RESEND)) - force_resend = IRac::strToBool(server.arg(i).c_str()); - else - result = updateClimate(result, server.argName(i), "", server.arg(i)); + uint16_t channel = chan; + if (kNrOfIrTxGpios > 1) { + // Scan for the channel number if needed. + for (uint16_t i = 0; i < server.args(); i++) { + if (server.argName(i).equals(KEY_CHANNEL)) { + channel = server.arg(i).toInt(); + } + } } + // Change the HTML channel for the climate if it is within the correct range. + if (channel < kNrOfIrTxGpios) chan = channel; -#if MQTT_ENABLE - sendClimate(climate, result, MqttClimateStat, true, false, force_resend); -#else // MQTT_ENABLE - sendClimate(climate, result, "", false, false, force_resend); -#endif // MQTT_ENABLE - lastClimateSource = F("HTTP"); - // Update the old climate state with the new one. - climate = result; - // Redirect back to the aircon page. + IRac *ac_ptr = climate[chan]; String html = htmlHeader(F("Aircon updated!")); + if (ac_ptr != NULL) { + bool force_resend = false; + for (uint16_t i = 0; i < server.args(); i++) { + if (server.argName(i).equals(KEY_RESEND)) + force_resend = IRac::strToBool(server.arg(i).c_str()); + else + updateClimate(&(ac_ptr->next), server.argName(i), "", server.arg(i)); + } +#if MQTT_ENABLE + sendClimate(genStatTopic(chan), true, false, force_resend, true, ac_ptr); +#else // MQTT_ENABLE + sendClimate("", false, false, force_resend, true, ac_ptr); +#endif // MQTT_ENABLE + lastClimateSource = F("HTTP"); + } else { // ac_ptr == NULL + debug("No climate setup for the given channel. Aborting!"); + html = htmlHeader(F("Aircon update FAILED!")); + } + // Redirect back to the aircon page. html += addJsReloadUrl(kUrlAircon, kQuickDisplayTime, false); html += htmlEnd(); server.send(200, "text/html", html); @@ -1088,6 +1172,12 @@ void handleAdmin(void) { kUrlSendDiscovery, F("Send MQTT Discovery"), F("Send a Climate MQTT discovery message to Home Assistant.

      ")); #endif // MQTT_DISCOVERY_ENABLE +#if MQTT_CLEAR_ENABLE + html += htmlButton( + kUrlClearMqtt, F("Clear data saved to MQTT"), + F("Clear all saved climate & discovery messages for this device & " + "reboot.

      ")); +#endif // MQTT_CLEAR_ENABLE #endif // MQTT_ENABLE html += htmlButton( kUrlReboot, F("Reboot"), @@ -1168,7 +1258,7 @@ void handleInfo(void) { " (" + timeSince(lastIrReceivedTime) + ")
      " #endif // IR_RX "Duplicate Wifi networks: " + - String(HIDE_DUPLIATE_NETWORKS ? "Hide" : "Show") + "
      " + String(HIDE_DUPLICATE_NETWORKS ? "Hide" : "Show") + "
      " "Min Wifi signal required: " #ifdef MIN_SIGNAL_STRENGTH + String(static_cast(MIN_SIGNAL_STRENGTH)) + @@ -1230,14 +1320,18 @@ void handleInfo(void) { "Last state broadcast: " + (hasBroadcastBeenSent ? timeElapsed(lastBroadcast.elapsed()) : String("Never")) + "
      " +#if MQTT_DISCOVERY_ENABLE "Last discovery sent: " + (lockMqttBroadcast ? String("Locked") : (hasDiscoveryBeenSent ? timeElapsed(lastDiscovery.elapsed()) : String("Never"))) + "
      " - "Command topics: " + MqttClimateCmnd + kClimateTopics + - "State topics: " + MqttClimateStat + kClimateTopics + +#endif // MQTT_DISCOVERY_ENABLE + "Command topics: " + MqttClimate + channel_re + '/' + MQTT_CLIMATE_CMND + + '/' + kClimateTopics + + "State topics: " + MqttClimate + channel_re + '/' + MQTT_CLIMATE_STAT + + '/' + kClimateTopics + #endif // MQTT_ENABLE "

      " // Page footer @@ -1261,6 +1355,59 @@ void doRestart(const char* str, const bool serial_only) { delay(5000); // Enough time to ensure we don't return. } +#if MQTT_ENABLE && MQTT_CLEAR_ENABLE +// Clear any MQTT message that we might have set retain on. +bool clearMqttSavedStates(const String topic_base) { + String channelStr = ""; + bool success = true; + // Clear the Last Will & Testament. + success &= mqtt_client.publish(MqttLwt.c_str(), "", true); +#if MQTT_DISCOVERY_ENABLE + // Clear the HA climate discovery message. + success &= mqtt_client.publish(MqttDiscovery.c_str(), "", true); +#endif // MQTT_DISCOVERY_ENABLE + for (size_t channel = 0; + channel <= kNrOfIrTxGpios; + channelStr = '_' + String(channel++)) { + for (size_t i = 0; i < sizeof(kMqttTopics) / sizeof(char*); i++) { + // Sending a retained "" message to the topic should clear previous values + // in theory. + String topic = topic_base + channelStr + '/' + F(MQTT_CLIMATE_STAT) + + '/' + String(kMqttTopics[i]); + success &= mqtt_client.publish(topic.c_str(), "", true); + } + channelStr = '_' + String(channel); + } + String logmesg = "Removing all possible settings saved in MQTT for '" + + topic_base + "' "; + logmesg += success ? F("succeeded") : F("failed"); + mqttLog(logmesg.c_str()); + return success; +} + +// Clear settings from MQTT web page +void handleClearMqtt(void) { +#if HTML_PASSWORD_ENABLE + if (!server.authenticate(HttpUsername, HttpPassword)) { + debug(("Basic HTTP authentication failure for " + + String(kUrlClearMqtt)).c_str()); + return server.requestAuthentication(); + } +#endif + server.send(200, "text/html", + htmlHeader(F("Clearing saved info from MQTT"), + F("Removing all saved settings for this device from " + "MQTT.")) + + "

      Device restarting. Try connecting in a few seconds.

      " + + addJsReloadUrl(kUrlRoot, 10, true) + + htmlEnd()); + // Do the clearing. + mqttLog("Clearing all saved settings from MQTT."); + clearMqttSavedStates(MqttClimate); + doRestart("Rebooting..."); +} +#endif // MQTT_ENABLE && MQTT_CLEAR_ENABLE + // Reset web page void handleReset(void) { #if HTML_PASSWORD_ENABLE @@ -1278,6 +1425,10 @@ void handleReset(void) { htmlEnd()); // Do the reset. #if MQTT_ENABLE +#if MQTT_CLEAR_ENABLE + mqttLog("Clearing all saved climate settings from MQTT."); + clearMqttSavedStates(MqttClimate); +#endif // MQTT_CLEAR_ENABLE mqttLog("Wiping all saved config settings."); #endif // MQTT_ENABLE if (mountSpiffs()) { @@ -1648,6 +1799,7 @@ void handleIr(void) { decode_type_t ir_type = decode_type_t::NEC; // Default to NEC codes. uint16_t nbits = 0; uint16_t repeat = 0; + int16_t channel = -1; for (uint16_t i = 0; i < server.args(); i++) { if (server.argName(i).equals(KEY_TYPE) || @@ -1660,11 +1812,16 @@ void handleIr(void) { nbits = server.arg(i).toInt(); } else if (server.argName(i).equals(KEY_REPEAT)) { repeat = server.arg(i).toInt(); + } else if (server.argName(i).equals(KEY_CHANNEL)) { + channel = server.arg(i).toInt(); } } debug("New code received via HTTP"); - lastSendSucceeded = sendIRCode(getDefaultIrSendPtr(), ir_type, data, - data_str.c_str(), nbits, repeat); + IRsend *tx_ptr = getDefaultIrSendPtr(); + if (channel >= 0 && channel < kNrOfIrTxGpios && IrSendTable[channel] != NULL) + tx_ptr = IrSendTable[channel]; + lastSendSucceeded = sendIRCode(tx_ptr, ir_type, data, data_str.c_str(), nbits, + repeat); String html = htmlHeader(F("IR command sent!")); html += addJsReloadUrl(kUrlRoot, kQuickDisplayTime, true); html += htmlEnd(); @@ -1831,7 +1988,7 @@ void setup_wifi(void) { #if MIN_SIGNAL_STRENGTH wifiManager.setMinimumSignalQuality(MIN_SIGNAL_STRENGTH); #endif // MIN_SIGNAL_STRENGTH - wifiManager.setRemoveDuplicateAPs(HIDE_DUPLIATE_NETWORKS); + wifiManager.setRemoveDuplicateAPs(HIDE_DUPLICATE_NETWORKS); if (!wifiManager.autoConnect()) // Reboot. A.k.a. "Have you tried turning it Off and On again?" @@ -1873,7 +2030,6 @@ void init_vars(void) { // Sub-topic for the climate command topics. MqttClimateCmnd = MqttClimate + '/' + MQTT_CLIMATE_CMND + '/'; // Sub-topic for the climate stat topics. - MqttClimateStat = MqttClimate + '/' + MQTT_CLIMATE_STAT + '/'; #if MQTT_DISCOVERY_ENABLE MqttDiscovery = "homeassistant/climate/" + String(Hostname) + "/config"; #endif // MQTT_DISCOVERY_ENABLE @@ -1884,28 +2040,6 @@ void init_vars(void) { } void setup(void) { - // Set the default climate settings. - climate.protocol = decode_type_t::UNKNOWN; - climate.model = -1; // Unknown. - climate.power = false; - climate.mode = stdAc::opmode_t::kAuto; - climate.celsius = true; - climate.degrees = 25; // 25C - climate.fanspeed = stdAc::fanspeed_t::kAuto; - climate.swingv = stdAc::swingv_t::kAuto; - climate.swingh = stdAc::swingh_t::kAuto; - climate.quiet = false; - climate.turbo = false; - climate.econo = false; - climate.light = false; - climate.filter = false; - climate.clean = false; - climate.beep = false; - climate.sleep = -1; // Off - climate.clock = -1; // Don't set. - climate_prev = climate; - lastClimateSource = F("None"); - #if DEBUG if (!isSerialGpioUsedByIr()) { #if defined(ESP8266) @@ -1928,17 +2062,29 @@ void setup(void) { if (isSerialGpioUsedByIr()) Serial.end(); #endif // DEBUG + channel_re.reserve(kNrOfIrTxGpios * 3); // Initialise all the IR transmitters. for (uint8_t i = 0; i < kNrOfIrTxGpios; i++) { if (txGpioTable[i] == kGpioUnused) { IrSendTable[i] = NULL; + climate[i] = NULL; } else { IrSendTable[i] = new IRsend(txGpioTable[i], kInvertTxOutput); - if (IrSendTable[i] == NULL) break; - IrSendTable[i]->begin(); - offset = IrSendTable[i]->calibrate(); + if (IrSendTable[i] != NULL) { + IrSendTable[i]->begin(); + offset = IrSendTable[i]->calibrate(); + } + climate[i] = new IRac(txGpioTable[i], kInvertTxOutput); + if (climate[i] != NULL && i > 0) channel_re += '_' + String(i) + '|'; } } + lastClimateSource = F("None"); + if (channel_re.length() == 1) { + channel_re = ""; + } else { + channel_re.remove(channel_re.length() - 1, 1); // Remove the last char. + channel_re += F(")?"); + } #if IR_RX if (rx_gpio != kGpioUnused) irrecv = new IRrecv(rx_gpio, kCaptureBufferSize, kCaptureTimeout, true); @@ -1950,8 +2096,6 @@ void setup(void) { irrecv->enableIRIn(IR_RX_PULLUP); // Start the receiver } #endif // IR_RX - commonAc = new IRac(txGpioTable[0], kInvertTxOutput); - // Wait a bit for things to settle. delay(500); @@ -1992,6 +2136,10 @@ void setup(void) { // Parse and update the new gpios. server.on(kUrlGpioSet, handleGpioSetting); #if MQTT_ENABLE +#if MQTT_CLEAR_ENABLE + // Clear settings saved to MQTT as retained messages. + server.on(kUrlClearMqtt, handleClearMqtt); +#endif // MQTT_CLEAR_ENABLE #if MQTT_DISCOVERY_ENABLE // MQTT Discovery url server.on(kUrlSendDiscovery, handleSendMqttDiscovery); @@ -2070,6 +2218,13 @@ void setup(void) { } #if MQTT_ENABLE +String genStatTopic(const uint16_t channel) { + if (channel) // Never use the '*_0' state channel. + return MqttClimate + "_" + String(channel) + '/' + MQTT_CLIMATE_STAT + '/'; + else + return MqttClimate + '/' + MQTT_CLIMATE_STAT + '/'; +} + // MQTT subscribing to topic void subscribing(const String topic_name) { // subscription to topic for receiving data with QoS. @@ -2125,12 +2280,18 @@ bool reconnect(void) { mqttSentCounter++; // Subscribing to topic(s) - subscribing(MqttSend); - for (uint8_t i = 0; i < kNrOfIrTxGpios; i++) { - subscribing(MqttSend + '_' + String(static_cast(i))); + subscribing(MqttSend); // General base topic. + subscribing(MqttClimateCmnd + '+'); // Base climate command topics + // Per channel topics + for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) { + // General + if (IrSendTable[i] != NULL) + subscribing(MqttSend + '_' + String(i)); + // Climate + if (climate[i] != NULL) + subscribing(MqttClimate + '_' + String(i) + '/' + MQTT_CLIMATE_CMND + + '/' + '+'); } - // Climate command topics. - subscribing(MqttClimateCmnd + '+'); } else { debug(("failed, rc=" + String(mqtt_client.state()) + " Try again in a bit.").c_str()); @@ -2176,18 +2337,20 @@ void handleSendMqttDiscovery(void) { #endif // MQTT_DISCOVERY_ENABLE void doBroadcast(TimerMs *timer, const uint32_t interval, - const stdAc::state_t state, const bool retain, + IRac *climate[], const bool retain, const bool force) { if (force || (!lockMqttBroadcast && timer->elapsed() > interval)) { debug("Sending MQTT stat update broadcast."); - sendClimate(state, state, MqttClimateStat, - retain, true, false); + for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) { + String stat_topic = genStatTopic(i); + sendClimate(stat_topic, retain, true, false, true, climate[i]); #if REPORT_VCC - sendString(MqttClimateStat + KEY_VCC, vccToString(), false); + sendString(stat_topic + KEY_VCC, vccToString(), false); #endif // REPORT_VCC #if MQTT_CLIMATE_JSON - sendJsonState(state, MqttClimateStat + KEY_JSON); + sendJsonState(climate[i]->next, stat_topic + KEY_JSON); #endif // MQTT_CLIMATE_JSON + } timer->reset(); // It's been sent, so reset the timer. hasBroadcastBeenSent = true; } @@ -2209,38 +2372,46 @@ void receivingMQTT(String const topic_name, String const callback_str) { lastMqttCmdTime = millis(); mqttRecvCounter++; + // Check if a specific channel was requested by looking for a "*_[0-9]" suffix + // Or is for a specific ac/climate channel. e.g. "*/ac_[1-9]" + debug(("Checking for channel number in " + topic_name).c_str()); + for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) { + if (topic_name.endsWith("_" + String(i)) || + (i > 0 && topic_name.startsWith(MqttClimate + "_" + String(i)))) { + channel = i; + break; + } + } + debug(("Channel = " + String(channel)).c_str()); + // Is it a climate topic? if (topic_name.startsWith(MqttClimate)) { - if (topic_name.startsWith(MqttClimateCmnd)) { + String alt_cmnd_topic = MqttClimate + "_" + String(channel) + '/' + + MQTT_CLIMATE_CMND + '/'; + // Also accept climate commands on the '*_0' channel. + String cmnd_topic = topic_name.startsWith(alt_cmnd_topic) ? alt_cmnd_topic + : MqttClimateCmnd; + String stat_topic = genStatTopic(channel); + if (topic_name.startsWith(cmnd_topic)) { debug("It's a climate command topic"); - stdAc::state_t updated = updateClimate( - climate, topic_name, MqttClimateCmnd, callback_str); + updateClimate(&(climate[channel]->next), topic_name, cmnd_topic, + callback_str); // Handle the special command for forcing a resend of the state via IR. bool force_resend = false; - if (topic_name.equals(MqttClimateCmnd + KEY_RESEND) && + if (topic_name.equals(cmnd_topic + KEY_RESEND) && callback_str.equalsIgnoreCase(KEY_RESEND)) { force_resend = true; mqttLog("Climate resend requested."); } - if (sendClimate(climate, updated, MqttClimateStat, - true, false, force_resend) && !force_resend) + if (sendClimate(stat_topic, true, false, force_resend, true, + climate[channel]) && !force_resend) lastClimateSource = F("MQTT"); - climate = updated; - } else if (topic_name.startsWith(MqttClimateStat)) { + } else if (topic_name.startsWith(stat_topic)) { debug("It's a climate state topic. Update internal state and DON'T send"); - climate = updateClimate( - climate, topic_name, MqttClimateStat, callback_str); + updateClimate(&(climate[channel]->next), topic_name, stat_topic, + callback_str); } return; // We are done for now. } - // Check if a specific channel was requested by looking for a "*_[0-9]" suffix - for (uint8_t i = 0; i < kNrOfIrTxGpios; i++) { - debug(("Checking if " + topic_name + " ends with _" + String(i)).c_str()); - if (topic_name.endsWith("_" + String(i))) { - channel = i; - debug("It does!"); - break; - } - } debug(("Using transmit channel " + String(static_cast(channel)) + " / GPIO " + String(static_cast(txGpioTable[channel]))).c_str()); @@ -2356,7 +2527,7 @@ void sendMQTTDiscovery(const char *topic) { "\"swing_mode_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_SWINGV "\"," "\"swing_modes\":[" "\"off\",\"auto\",\"highest\",\"high\",\"middle\",\"low\",\"lowest\"]" - "}").c_str())) { + "}").c_str(), true)) { mqttLog("MQTT climate discovery successful sent."); hasDiscoveryBeenSent = true; lastDiscovery.reset(); @@ -2402,8 +2573,8 @@ void loop(void) { // Attempt to fetch back any Climate state stored in MQTT retained // messages on the MQTT broker. mqttLog("Started listening for previous state."); - climate_prev = climate; // Make a copy so we can compare afterwards. - subscribing(MqttClimateStat + '+'); + for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) + subscribing(genStatTopic(i) + '+'); statListenTime.reset(); } } @@ -2413,14 +2584,18 @@ void loop(void) { lastConnectedTime = now; mqtt_client.loop(); if (lockMqttBroadcast && statListenTime.elapsed() > kStatListenPeriodMs) { - unsubscribing(MqttClimateStat + '+'); - mqttLog("Finished listening for previous state."); - if (IRac::cmpStates(climate, climate_prev)) { // Something changed. - mqttLog("The state was recovered from MQTT broker. Updating."); - sendClimate(climate_prev, climate, MqttClimateStat, - true, false, false, MQTT_CLIMATE_IR_SEND_ON_RESTART); - lastClimateSource = F("MQTT (via retain)"); + for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) { + String stat_topic = genStatTopic(i); + unsubscribing(stat_topic + '+'); + // Did something change? + if (climate[i] != NULL && climate[i]->hasStateChanged()) { + sendClimate(stat_topic, true, false, false, + MQTT_CLIMATE_IR_SEND_ON_RESTART, climate[i]); + lastClimateSource = F("MQTT (via retain)"); + mqttLog("The state was recovered from MQTT broker."); + } } + mqttLog("Finished listening for previous state."); lockMqttBroadcast = false; // Release the lock so we can broadcast again. } // Periodically send all of the climate state via MQTT. @@ -2477,17 +2652,16 @@ uint64_t getUInt64fromHex(char const *str) { uint64_t result = 0; uint16_t offset = 0; // Skip any leading '0x' or '0X' prefix. - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) - offset = 2; + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) offset = 2; for (; isxdigit((unsigned char)str[offset]); offset++) { char c = str[offset]; result *= 16; - if (isdigit(c)) /* '0' .. '9' */ - result += c - '0'; - else if (isupper(c)) /* 'A' .. 'F' */ - result += c - 'A' + 10; - else /* 'a' .. 'f'*/ - result += c - 'a' + 10; + if (isdigit(c)) + result += c - '0'; // '0' .. '9' + else if (isupper(c)) + result += c - 'A' + 10; // 'A' .. 'F' + else + result += c - 'a' + 10; // 'a' .. 'f' } return result; } @@ -2641,8 +2815,7 @@ bool sendFloat(const String topic, const float_t temp, const bool retain) { #if MQTT_CLIMATE_JSON void sendJsonState(const stdAc::state_t state, const String topic, const bool retain, const bool ha_mode) { - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); + DynamicJsonDocument json(kJsonAcStateMaxSize); json[KEY_PROTOCOL] = typeToString(state.protocol); json[KEY_MODEL] = state.model; json[KEY_POWER] = IRac::boolToString(state.power); @@ -2668,108 +2841,117 @@ void sendJsonState(const stdAc::state_t state, const String topic, String payload = ""; payload.reserve(200); - json.printTo(payload); + serializeJson(json, payload); sendString(topic, payload, retain); } -stdAc::state_t jsonToState(const stdAc::state_t current, const String str) { - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.parseObject(str); - if (!json.success()) { +bool validJsonStr(DynamicJsonDocument doc, const char* key) { + return doc.containsKey(key) && doc[key].is(); +} + +bool validJsonInt(DynamicJsonDocument doc, const char* key) { + return doc.containsKey(key) && doc[key].is(); +} + +stdAc::state_t jsonToState(const stdAc::state_t current, const char *str) { + DynamicJsonDocument json(kJsonAcStateMaxSize); + if (deserializeJson(json, str, kJsonAcStateMaxSize)) { debug("json MQTT message did not parse. Skipping!"); return current; } stdAc::state_t result = current; - if (json.containsKey(KEY_PROTOCOL)) + if (validJsonStr(json, KEY_PROTOCOL)) result.protocol = strToDecodeType(json[KEY_PROTOCOL]); - if (json.containsKey(KEY_MODEL)) - result.model = IRac::strToModel(json[KEY_MODEL]); - if (json.containsKey(KEY_MODE)) + else if (validJsonInt(json, KEY_PROTOCOL)) + result.protocol = (decode_type_t)json[KEY_PROTOCOL].as(); + if (validJsonStr(json, KEY_MODEL)) + result.model = IRac::strToModel(json[KEY_MODEL].as()); + else if (validJsonInt(json, KEY_MODEL)) + result.model = json[KEY_MODEL]; + if (validJsonStr(json, KEY_MODE)) result.mode = IRac::strToOpmode(json[KEY_MODE]); - if (json.containsKey(KEY_FANSPEED)) + if (validJsonStr(json, KEY_FANSPEED)) result.fanspeed = IRac::strToFanspeed(json[KEY_FANSPEED]); - if (json.containsKey(KEY_SWINGV)) + if (validJsonStr(json, KEY_SWINGV)) result.swingv = IRac::strToSwingV(json[KEY_SWINGV]); - if (json.containsKey(KEY_SWINGH)) + if (validJsonStr(json, KEY_SWINGH)) result.swingh = IRac::strToSwingH(json[KEY_SWINGH]); if (json.containsKey(KEY_TEMP)) result.degrees = json[KEY_TEMP]; - if (json.containsKey(KEY_SLEEP)) + if (validJsonInt(json, KEY_SLEEP)) result.sleep = json[KEY_SLEEP]; - if (json.containsKey(KEY_POWER)) + if (validJsonStr(json, KEY_POWER)) result.power = IRac::strToBool(json[KEY_POWER]); - if (json.containsKey(KEY_QUIET)) + if (validJsonStr(json, KEY_QUIET)) result.quiet = IRac::strToBool(json[KEY_QUIET]); - if (json.containsKey(KEY_TURBO)) + if (validJsonStr(json, KEY_TURBO)) result.turbo = IRac::strToBool(json[KEY_TURBO]); - if (json.containsKey(KEY_ECONO)) + if (validJsonStr(json, KEY_ECONO)) result.econo = IRac::strToBool(json[KEY_ECONO]); - if (json.containsKey(KEY_LIGHT)) + if (validJsonStr(json, KEY_LIGHT)) result.light = IRac::strToBool(json[KEY_LIGHT]); - if (json.containsKey(KEY_CLEAN)) + if (validJsonStr(json, KEY_CLEAN)) result.clean = IRac::strToBool(json[KEY_CLEAN]); - if (json.containsKey(KEY_FILTER)) + if (validJsonStr(json, KEY_FILTER)) result.filter = IRac::strToBool(json[KEY_FILTER]); - if (json.containsKey(KEY_BEEP)) + if (validJsonStr(json, KEY_BEEP)) result.beep = IRac::strToBool(json[KEY_BEEP]); - if (json.containsKey(KEY_CELSIUS)) + if (validJsonStr(json, KEY_CELSIUS)) result.celsius = IRac::strToBool(json[KEY_CELSIUS]); return result; } #endif // MQTT_CLIMATE_JSON -stdAc::state_t updateClimate(stdAc::state_t current, const String str, - const String prefix, const String payload) { - stdAc::state_t result = current; +void updateClimate(stdAc::state_t *state, const String str, + const String prefix, const String payload) { #if MQTT_CLIMATE_JSON if (str.equals(prefix + KEY_JSON)) - result = jsonToState(result, payload.c_str()); + *state = jsonToState(*state, payload.c_str()); else #endif // MQTT_CLIMATE_JSON if (str.equals(prefix + KEY_PROTOCOL)) - result.protocol = strToDecodeType(payload.c_str()); + state->protocol = strToDecodeType(payload.c_str()); else if (str.equals(prefix + KEY_MODEL)) - result.model = IRac::strToModel(payload.c_str()); + state->model = IRac::strToModel(payload.c_str()); else if (str.equals(prefix + KEY_POWER)) - result.power = IRac::strToBool(payload.c_str()); + state->power = IRac::strToBool(payload.c_str()); else if (str.equals(prefix + KEY_MODE)) - result.mode = IRac::strToOpmode(payload.c_str()); + state->mode = IRac::strToOpmode(payload.c_str()); else if (str.equals(prefix + KEY_TEMP)) - result.degrees = payload.toFloat(); + state->degrees = payload.toFloat(); else if (str.equals(prefix + KEY_FANSPEED)) - result.fanspeed = IRac::strToFanspeed(payload.c_str()); + state->fanspeed = IRac::strToFanspeed(payload.c_str()); else if (str.equals(prefix + KEY_SWINGV)) - result.swingv = IRac::strToSwingV(payload.c_str()); + state->swingv = IRac::strToSwingV(payload.c_str()); else if (str.equals(prefix + KEY_SWINGH)) - result.swingh = IRac::strToSwingH(payload.c_str()); + state->swingh = IRac::strToSwingH(payload.c_str()); else if (str.equals(prefix + KEY_QUIET)) - result.quiet = IRac::strToBool(payload.c_str()); + state->quiet = IRac::strToBool(payload.c_str()); else if (str.equals(prefix + KEY_TURBO)) - result.turbo = IRac::strToBool(payload.c_str()); + state->turbo = IRac::strToBool(payload.c_str()); else if (str.equals(prefix + KEY_ECONO)) - result.econo = IRac::strToBool(payload.c_str()); + state->econo = IRac::strToBool(payload.c_str()); else if (str.equals(prefix + KEY_LIGHT)) - result.light = IRac::strToBool(payload.c_str()); + state->light = IRac::strToBool(payload.c_str()); else if (str.equals(prefix + KEY_BEEP)) - result.beep = IRac::strToBool(payload.c_str()); + state->beep = IRac::strToBool(payload.c_str()); else if (str.equals(prefix + KEY_FILTER)) - result.filter = IRac::strToBool(payload.c_str()); + state->filter = IRac::strToBool(payload.c_str()); else if (str.equals(prefix + KEY_CLEAN)) - result.clean = IRac::strToBool(payload.c_str()); + state->clean = IRac::strToBool(payload.c_str()); else if (str.equals(prefix + KEY_CELSIUS)) - result.celsius = IRac::strToBool(payload.c_str()); + state->celsius = IRac::strToBool(payload.c_str()); else if (str.equals(prefix + KEY_SLEEP)) - result.sleep = payload.toInt(); - return result; + state->sleep = payload.toInt(); } -bool sendClimate(const stdAc::state_t prev, const stdAc::state_t next, - const String topic_prefix, const bool retain, +bool sendClimate(const String topic_prefix, const bool retain, const bool forceMQTT, const bool forceIR, - const bool enableIR) { + const bool enableIR, IRac *ac) { bool diff = false; bool success = true; - + const stdAc::state_t next = ac->getState(); + const stdAc::state_t prev = ac->getStatePrev(); if (prev.protocol != next.protocol || forceMQTT) { diff = true; success &= sendString(topic_prefix + KEY_PROTOCOL, @@ -2779,6 +2961,8 @@ bool sendClimate(const stdAc::state_t prev, const stdAc::state_t next, diff = true; success &= sendInt(topic_prefix + KEY_MODEL, next.model, retain); } +#if MQTT_CLIMATE_HA_MODE + // Home Assistant want's these two bound together. if (prev.power != next.power || prev.mode != next.mode || forceMQTT) { diff = true; success &= sendBool(topic_prefix + KEY_POWER, next.power, retain); @@ -2787,6 +2971,18 @@ bool sendClimate(const stdAc::state_t prev, const stdAc::state_t next, : F("off")), retain); } +#else // MQTT_CLIMATE_HA_MODE + // In non-Home Assistant mode, power and mode are not bound together. + if (prev.power != next.power || forceMQTT) { + diff = true; + success &= sendBool(topic_prefix + KEY_POWER, next.power, retain); + } + if (prev.mode != next.mode || forceMQTT) { + diff = true; + success &= sendString(topic_prefix + KEY_MODE, + IRac::opmodeToString(next.mode), retain); + } +#endif // MQTT_CLIMATE_HA_MODE if (prev.degrees != next.degrees || forceMQTT) { diff = true; success &= sendFloat(topic_prefix + KEY_TEMP, next.degrees, retain); @@ -2845,19 +3041,24 @@ bool sendClimate(const stdAc::state_t prev, const stdAc::state_t next, if (diff && !forceMQTT) { debug("Difference in common A/C state detected."); #if MQTT_CLIMATE_JSON - sendJsonState(next, MqttClimateStat + KEY_JSON); + sendJsonState(next, topic_prefix + KEY_JSON); #endif // MQTT_CLIMATE_JSON } else { debug("NO difference in common A/C state detected."); } // Only send an IR message if we need to. if (enableIR && ((diff && !forceMQTT) || forceIR)) { + sendReqCounter++; + if (ac == NULL) { // No climate object is available. + debug("Can't send climate state as common A/C object doesn't exist!"); + return false; + } debug("Sending common A/C state via IR."); #if IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING // Turn IR capture off if we need to. if (irrecv != NULL) irrecv->disableIRIn(); // Stop the IR receiver #endif // IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING - lastClimateSucceeded = commonAc->sendAc(next, &prev); + lastClimateSucceeded = ac->sendAc(); #if IR_RX && DISABLE_CAPTURE_WHILE_TRANSMITTING // Turn IR capture back on if we need to. if (irrecv != NULL) irrecv->enableIRIn(); // Restart the receiver @@ -2866,7 +3067,6 @@ bool sendClimate(const stdAc::state_t prev, const stdAc::state_t next, success &= lastClimateSucceeded; lastClimateIr.reset(); irClimateCounter++; - sendReqCounter++; } return success; } @@ -2883,35 +3083,39 @@ bool decodeCommonAc(const decode_results *decode) { debug("Inbound IR messages isn't a supported common A/C protocol"); return false; } - stdAc::state_t state = climate; + if (climate[0] == NULL) { + debug("No common A/C object allocated for channel 0. Skipping."); + return false; + } + stdAc::state_t state = climate[0]->next; debug("Converting inbound IR A/C message to common A/C"); - if (!IRAcUtils::decodeToState(decode, &state, &climate)) { + if (!IRAcUtils::decodeToState(decode, &state, &(climate[0]->next))) { debug("Failed to convert to common A/C."); // This shouldn't happen! return false; } #if IGNORE_DECODED_AC_PROTOCOL - if (climate.protocol != decode_type_t::UNKNOWN) { + if (climate[0]->next.protocol != decode_type_t::UNKNOWN) { // Use the previous protcol/model if set. - state.protocol = climate.protocol; - state.model = climate.model; + state.protocol = climate[0]->next.protocol; + state.model = climate[0]->next.model; } #endif // IGNORE_DECODED_AC_PROTOCOL // Continue to use the previously prefered temperature units. // i.e. Keep using Celsius or Fahrenheit. -if (climate.celsius != state.celsius) { +if (climate[0]->next.celsius != state.celsius) { // We've got a mismatch, so we need to convert. - state.degrees = climate.celsius ? fahrenheitToCelsius(state.degrees) - : celsiusToFahrenheit(state.degrees); - state.celsius = climate.celsius; + state.degrees = climate[0]->next.celsius ? fahrenheitToCelsius(state.degrees) + : celsiusToFahrenheit(state.degrees); + state.celsius = climate[0]->next.celsius; } +climate[0]->next = state; // Copy over the new climate state. #if MQTT_ENABLE - sendClimate(climate, state, MqttClimateStat, true, false, - REPLAY_DECODED_AC_MESSAGE, REPLAY_DECODED_AC_MESSAGE); + sendClimate(genStatTopic(0), true, false, REPLAY_DECODED_AC_MESSAGE, + REPLAY_DECODED_AC_MESSAGE, climate[0]); #else // MQTT_ENABLE - sendClimate(climate, state, "", false, false, REPLAY_DECODED_AC_MESSAGE, - REPLAY_DECODED_AC_MESSAGE); + sendClimate("", false, false, REPLAY_DECODED_AC_MESSAGE, + REPLAY_DECODED_AC_MESSAGE, climate[0]); #endif // MQTT_ENABLE - climate = state; // Copy over the new climate state. return true; } #endif // USE_DECODED_AC_SETTINGS && IR_RX diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/IRMQTTServer/platformio.ini old mode 100755 new mode 100644 similarity index 82% rename from lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/platformio.ini rename to lib/IRremoteESP8266-2.7.0/examples/IRMQTTServer/platformio.ini index 2d82260ad..1a22b09af --- a/lib/IRremoteESP8266-2.6.5/examples/IRMQTTServer/platformio.ini +++ b/lib/IRremoteESP8266-2.7.0/examples/IRMQTTServer/platformio.ini @@ -5,13 +5,15 @@ src_dir = . lib_extra_dirs = ../../ lib_ldf_mode = deep+ lib_ignore = examples -build_flags = -DMQTT_MAX_PACKET_SIZE=768 +build_flags = -DMQTT_MAX_PACKET_SIZE=768 ; -D_IR_LOCALE_=en-AU +framework = arduino +platform = espressif8266 [common] lib_deps_builtin = lib_deps_external = PubSubClient - ArduinoJson@<6.0 + ArduinoJson@>=6.0 [common_esp8266] lib_deps_external = @@ -26,20 +28,14 @@ lib_deps_external = https://github.com/tzapu/WiFiManager.git#development [env:nodemcuv2] -platform = espressif8266 -framework = arduino board = nodemcuv2 lib_deps = ${common_esp8266.lib_deps_external} [env:d1_mini] -platform = espressif8266 -framework = arduino board = d1_mini lib_deps = ${common_esp8266.lib_deps_external} [env:d1_mini_no_mqtt] -platform = espressif8266 -framework = arduino board = d1_mini build_flags = ${env.build_flags} @@ -48,13 +44,10 @@ lib_deps = ${common_esp8266.lib_deps_external} [env:esp32dev] platform = espressif32 -framework = arduino board = esp32dev lib_deps = ${common_esp32.lib_deps_external} [env:esp01_1m] -platform = espressif8266 -framework = arduino board = esp01_1m build_flags = ${env.build_flags} diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRServer/IRServer.ino b/lib/IRremoteESP8266-2.7.0/examples/IRServer/IRServer.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/IRServer/IRServer.ino rename to lib/IRremoteESP8266-2.7.0/examples/IRServer/IRServer.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/IRServer/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/IRServer/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/IRServer/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/IRrecvDemo.ino b/lib/IRremoteESP8266-2.7.0/examples/IRrecvDemo/IRrecvDemo.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/IRrecvDemo/IRrecvDemo.ino rename to lib/IRremoteESP8266-2.7.0/examples/IRrecvDemo/IRrecvDemo.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/IRrecvDemo/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/IRrecvDemo/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/IRrecvDump.ino b/lib/IRremoteESP8266-2.7.0/examples/IRrecvDump/IRrecvDump.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/IRrecvDump/IRrecvDump.ino rename to lib/IRremoteESP8266-2.7.0/examples/IRrecvDump/IRrecvDump.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/IRrecvDump/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/IRrecvDump/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/IRremoteESP8266-2.7.0/examples/IRrecvDumpV2/IRrecvDumpV2.ino old mode 100755 new mode 100644 similarity index 87% rename from lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/IRrecvDumpV2.ino rename to lib/IRremoteESP8266-2.7.0/examples/IRrecvDumpV2/IRrecvDumpV2.ino index f69c14aed..fc61f9b84 --- a/lib/IRremoteESP8266-2.6.5/examples/IRrecvDumpV2/IRrecvDumpV2.ino +++ b/lib/IRremoteESP8266-2.7.0/examples/IRrecvDumpV2/IRrecvDumpV2.ino @@ -9,6 +9,9 @@ * https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-receiving * * Changes: + * Version 1.0 October, 2019 + * - Internationalisation (i18n) support. + * - Stop displaying the legacy raw timing info. * Version 0.5 June, 2019 * - Move A/C description to IRac.cpp. * Version 0.4 July, 2018 @@ -25,6 +28,7 @@ #include #include #include +#include #include // ==================== start of TUNEABLE PARAMETERS ==================== @@ -92,6 +96,11 @@ const uint8_t kTimeout = 15; // from your device. (e.g. Other IR remotes work.) // NOTE: Set this value very high to effectively turn off UNKNOWN detection. const uint16_t kMinUnknownSize = 12; + +// Legacy (No longer supported!) +// +// Change to `true` if you miss/need the old "Raw Timing[]" display. +#define LEGACY_TIMING_INFO false // ==================== end of TUNEABLE PARAMETERS ==================== // Use turn on the save buffer feature for more complete capture coverage. @@ -107,12 +116,11 @@ void setup() { #endif // ESP8266 while (!Serial) // Wait for the serial connection to be establised. delay(50); - Serial.printf("\nIRrecvDumpV2 is now running and waiting for IR input on Pin " - "%d\n", kRecvPin); + Serial.printf("\n" D_STR_IRRECVDUMP_STARTUP "\n", kRecvPin); #if DECODE_HASH // Ignore messages with less than minimum on or off pulses. irrecv.setUnknownThreshold(kMinUnknownSize); -#endif // DECODE_HASH +#endif // DECODE_HASH irrecv.enableIRIn(); // Start the receiver } @@ -122,25 +130,23 @@ void loop() { if (irrecv.decode(&results)) { // Display a crude timestamp. uint32_t now = millis(); - Serial.printf("Timestamp : %06u.%03u\n", now / 1000, now % 1000); - // Check if we got an IR message tha was to big for our capture buffer. + Serial.printf(D_STR_TIMESTAMP " : %06u.%03u\n", now / 1000, now % 1000); + // Check if we got an IR message that was to big for our capture buffer. if (results.overflow) - Serial.printf( - "WARNING: IR code is too big for buffer (>= %d). " - "This result shouldn't be trusted until this is resolved. " - "Edit & increase kCaptureBufferSize.\n", - kCaptureBufferSize); + Serial.printf(D_WARN_BUFFERFULL "\n", kCaptureBufferSize); // Display the library version the message was captured with. - Serial.println("Library : v" _IRREMOTEESP8266_VERSION_ "\n"); + Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_ "\n"); // Display the basic output of what we found. Serial.print(resultToHumanReadableBasic(&results)); // Display any extra A/C info if we have it. String description = IRAcUtils::resultAcToString(&results); - if (description.length()) Serial.println("Mesg Desc.: " + description); + if (description.length()) Serial.println(D_STR_MESGDESC ": " + description); yield(); // Feed the WDT as the text output can take a while to print. - // Output RAW timing info of the result. +#if LEGACY_TIMING_INFO + // Output legacy RAW timing info of the result. Serial.println(resultToTimingInfo(&results)); yield(); // Feed the WDT (again) +#endif // LEGACY_TIMING_INFO // Output the results as source code Serial.println(resultToSourceCode(&results)); Serial.println(); // Blank line between entries diff --git a/lib/IRremoteESP8266-2.7.0/examples/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/IRrecvDumpV2/platformio.ini new file mode 100644 index 000000000..d3c660df9 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/IRrecvDumpV2/platformio.ini @@ -0,0 +1,46 @@ +[platformio] +src_dir = . + +[env] +; Default platform +platform = espressif8266 +; Default board +board = nodemcuv2 +framework = arduino +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +board = nodemcuv2 +; build_flags = -D_IR_LOCALE_=en-AU + +[env:esp32dev] +platform = espressif32 +board = esp32dev +; build_flags = -D_IR_LOCALE_=en-AU + +[env:de-CH] +build_flags = -D_IR_LOCALE_=de-CH + +[env:de-DE] +build_flags = -D_IR_LOCALE_=de-DE + +[env:en-AU] +build_flags = -D_IR_LOCALE_=en-AU + +[env:en-IE] +build_flags = -D_IR_LOCALE_=en-IE + +[env:en-UK] +build_flags = -D_IR_LOCALE_=en-UK + +[env:en-US] +build_flags = -D_IR_LOCALE_=en-US + +[env:es-ES] +build_flags = -D_IR_LOCALE_=es-ES + +[env:fr-FR] +build_flags = -D_IR_LOCALE_=fr-FR diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/IRsendDemo.ino b/lib/IRremoteESP8266-2.7.0/examples/IRsendDemo/IRsendDemo.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/IRsendDemo/IRsendDemo.ino rename to lib/IRremoteESP8266-2.7.0/examples/IRsendDemo/IRsendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/IRsendDemo/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/IRsendDemo/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/IRsendProntoDemo.ino b/lib/IRremoteESP8266-2.7.0/examples/IRsendProntoDemo/IRsendProntoDemo.ino old mode 100755 new mode 100644 similarity index 96% rename from lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/IRsendProntoDemo.ino rename to lib/IRremoteESP8266-2.7.0/examples/IRsendProntoDemo/IRsendProntoDemo.ino index 09101c9dc..330ad5051 --- a/lib/IRremoteESP8266-2.6.5/examples/IRsendProntoDemo/IRsendProntoDemo.ino +++ b/lib/IRremoteESP8266-2.7.0/examples/IRsendProntoDemo/IRsendProntoDemo.ino @@ -92,7 +92,11 @@ uint16_t panasonicProntoCode[104] = { void setup() { irsend.begin(); - Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY); + #if defined(ESP8266) + Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY); + #else // ESP8266 + Serial.begin(115200, SERIAL_8N1); + #endif // ESP8266 } void loop() { diff --git a/lib/IRremoteESP8266-2.7.0/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/IRsendProntoDemo/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/IRsendProntoDemo/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib/IRremoteESP8266-2.7.0/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino rename to lib/IRremoteESP8266-2.7.0/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/JVCPanasonicSendDemo/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/JVCPanasonicSendDemo/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/LGACSend/LGACSend.ino b/lib/IRremoteESP8266-2.7.0/examples/LGACSend/LGACSend.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/LGACSend/LGACSend.ino rename to lib/IRremoteESP8266-2.7.0/examples/LGACSend/LGACSend.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/LGACSend/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/LGACSend/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/LGACSend/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/SmartIRRepeater.ino b/lib/IRremoteESP8266-2.7.0/examples/SmartIRRepeater/SmartIRRepeater.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/SmartIRRepeater/SmartIRRepeater.ino rename to lib/IRremoteESP8266-2.7.0/examples/SmartIRRepeater/SmartIRRepeater.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/SmartIRRepeater/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/SmartIRRepeater/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/SmartIRRepeater/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/TurnOnArgoAC.ino b/lib/IRremoteESP8266-2.7.0/examples/TurnOnArgoAC/TurnOnArgoAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/TurnOnArgoAC/TurnOnArgoAC.ino rename to lib/IRremoteESP8266-2.7.0/examples/TurnOnArgoAC/TurnOnArgoAC.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/TurnOnArgoAC/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/TurnOnArgoAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib/IRremoteESP8266-2.7.0/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino rename to lib/IRremoteESP8266-2.7.0/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/TurnOnDaikinAC/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/TurnOnDaikinAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/IRremoteESP8266-2.7.0/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino rename to lib/IRremoteESP8266-2.7.0/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/TurnOnFujitsuAC/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/TurnOnFujitsuAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib/IRremoteESP8266-2.7.0/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino rename to lib/IRremoteESP8266-2.7.0/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/TurnOnKelvinatorAC/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/TurnOnKelvinatorAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino rename to lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiAC/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino b/lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino rename to lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino b/lib/IRremoteESP8266-2.7.0/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino rename to lib/IRremoteESP8266-2.7.0/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/TurnOnPanasonicAC/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/TurnOnPanasonicAC/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/TurnOnPanasonicAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino b/lib/IRremoteESP8266-2.7.0/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino rename to lib/IRremoteESP8266-2.7.0/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/TurnOnToshibaAC/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/TurnOnToshibaAC/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/TurnOnToshibaAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino b/lib/IRremoteESP8266-2.7.0/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino rename to lib/IRremoteESP8266-2.7.0/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino diff --git a/lib/IRremoteESP8266-2.7.0/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/TurnOnTrotecAC/platformio.ini new file mode 100644 index 000000000..e6f6320da --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/TurnOnTrotecAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 + +[env:esp32dev] +platform = espressif32 +board = esp32dev diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/README.md b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/README.md new file mode 100644 index 000000000..fa8a441cb --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/README.md @@ -0,0 +1,43 @@ +# esp8266-AC-control + +This is just a web interface for the IRremoteESP8266 library. + +![Web Gui Preview](https://github.com/mariusmotea/esp8266-AC-control/raw/master/printscreen.png) + + +## Instructions: + + - Connect IR led to one GPIO pin (recommended pin is GPIO4) + + - Edit esp8266-AC-control.ino header marked as "User space". You will need to import the library dedicated for your AC model. Every library has its own commands for AC mode and fan speed that will need to be replace according to commands available in .h file of the library. + + - Flash the firmware in ESP board using 1M or 2M of SPIFFS storage. + + - Connect the board to your wifi network (look for "AC Remote Control" SSID and follow WiFi Manager wizard) + + - Upload web application files in SPIFFS storage using build in web form located at /file-upload path. + + +## REST API: + +Browser console will show the ajax calls to ESP8266 board. Running configuration can be displayed with GET request to /state path, any value can be changed with http PUT request to same path. + +Ex: + +``` +➜ ~ curl 192.168.0.71/state +{"mode":2,"fan":0,"temp":27,"power":true}% +➜ ~ curl -X PUT -d '{"temp":22}' 192.168.0.71/state +{"temp":22}% +➜ ~ curl 192.168.0.71/state +{"mode":2,"fan":0,"temp":22,"power":true}% +``` + +## DEBUG: + +Use mobile phone camera to see if the led is sending any IR signals when buttons are pressed. This will show if the circuit was properly made and the selected GPIO pin is the correct one. + + +## Credits: + +Interface: https://github.com/ael-code/daikin-control diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/Web-AC-control.ino b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/Web-AC-control.ino new file mode 100644 index 000000000..ac02bdc59 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/Web-AC-control.ino @@ -0,0 +1,300 @@ +/* Copyright 2019 Motea Marius + + This example code will create a webserver that will provide basic control to AC units using the web application + build with javascript/css. User config zone need to be updated if a different class than Collix need to be used. + Javasctipt file may also require minor changes as in current version it will not allow to set fan speed if Auto mode + is selected (required for Coolix). + +*/ +#include +#if defined(ESP8266) +#include +#include +#include +#include +#endif // ESP8266 +#if defined(ESP32) +#include +#include +#include +#include +#include +#endif // ESP32 +#include +#include +#include +#include +#include + +//// ###### User configuration space for AC library classes ########## + +#include // replace library based on your AC unit model, check https://github.com/crankyoldgit/IRremoteESP8266 + +#define AUTO_MODE kCoolixAuto +#define COOL_MODE kCoolixCool +#define DRY_MODE kCoolixDry +#define HEAT_MODE kCoolixHeat +#define FAN_MODE kCoolixFan + +#define FAN_AUTO kCoolixFanAuto +#define FAN_MIN kCoolixFanMin +#define FAN_MED kCoolixFanMed +#define FAN_HI kCoolixFanMax + +// ESP8266 GPIO pin to use for IR blaster. +const uint16_t kIrLed = 4; +// Library initialization, change it according to the imported library file. +IRCoolixAC ac(kIrLed); + +/// ##### End user configuration ###### + + +struct state { + uint8_t temperature = 22, fan = 0, operation = 0; + bool powerStatus; +}; + +File fsUploadFile; + +// core + +state acState; + +// settings +char deviceName[] = "AC Remote Control"; + +#if defined(ESP8266) +ESP8266WebServer server(80); +ESP8266HTTPUpdateServer httpUpdateServer; +#endif // ESP8266 +#if defined(ESP32) +WebServer server(80); +#endif // ESP32 + +bool handleFileRead(String path) { + // send the right file to the client (if it exists) + // Serial.println("handleFileRead: " + path); + if (path.endsWith("/")) path += "index.html"; + // If a folder is requested, send the index file + String contentType = getContentType(path); + // Get the MIME type + String pathWithGz = path + ".gz"; + if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) { + // If the file exists, either as a compressed archive, or normal + if (SPIFFS.exists(pathWithGz)) // If there's a compressed version available + path += ".gz"; // Use the compressed verion + File file = SPIFFS.open(path, "r"); + // Open the file + server.streamFile(file, contentType); + // Send it to the client + file.close(); + // Close the file again + // Serial.println(String("\tSent file: ") + path); + return true; + } + // Serial.println(String("\tFile Not Found: ") + path); + // If the file doesn't exist, return false + return false; +} + +String getContentType(String filename) { + // convert the file extension to the MIME type + if (filename.endsWith(".html")) return "text/html"; + else if (filename.endsWith(".css")) return "text/css"; + else if (filename.endsWith(".js")) return "application/javascript"; + else if (filename.endsWith(".ico")) return "image/x-icon"; + else if (filename.endsWith(".gz")) return "application/x-gzip"; + return "text/plain"; +} + +void handleFileUpload() { // upload a new file to the SPIFFS + HTTPUpload& upload = server.upload(); + if (upload.status == UPLOAD_FILE_START) { + String filename = upload.filename; + if (!filename.startsWith("/")) filename = "/" + filename; + // Serial.print("handleFileUpload Name: "); //Serial.println(filename); + fsUploadFile = SPIFFS.open(filename, "w"); + // Open the file for writing in SPIFFS (create if it doesn't exist) + filename = String(); + } else if (upload.status == UPLOAD_FILE_WRITE) { + if (fsUploadFile) + fsUploadFile.write(upload.buf, upload.currentSize); + // Write the received bytes to the file + } else if (upload.status == UPLOAD_FILE_END) { + if (fsUploadFile) { + // If the file was successfully created + fsUploadFile.close(); + // Close the file again + // Serial.print("handleFileUpload Size: "); + // Serial.println(upload.totalSize); + server.sendHeader("Location", "/success.html"); + // Redirect the client to the success page + server.send(303); + } else { + server.send(500, "text/plain", "500: couldn't create file"); + } + } +} + + +void handleNotFound() { + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + for (uint8_t i = 0; i < server.args(); i++) { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + server.send(404, "text/plain", message); +} + +void setup() { + // Serial.begin(115200); + // Serial.println(); + ac.begin(); + + + delay(1000); + + // Serial.println("mounting FS..."); + + if (!SPIFFS.begin()) { + // Serial.println("Failed to mount file system"); + return; + } + + WiFiManager wifiManager; + + + if (!wifiManager.autoConnect(deviceName)) { + delay(3000); + ESP.restart(); + delay(5000); + } + + +#if defined(ESP8266) + httpUpdateServer.setup(&server); +#endif // ESP8266 + + + + server.on("/state", HTTP_PUT, []() { + DynamicJsonDocument root(1024); + DeserializationError error = deserializeJson(root, server.arg("plain")); + if (error) { + server.send(404, "text/plain", "FAIL. " + server.arg("plain")); + } else { + if (root.containsKey("temp")) { + acState.temperature = (uint8_t) root["temp"]; + } + + if (root.containsKey("fan")) { + acState.fan = (uint8_t) root["fan"]; + } + + if (root.containsKey("power")) { + acState.powerStatus = root["power"]; + } + + if (root.containsKey("mode")) { + acState.operation = root["mode"]; + } + + String output; + serializeJson(root, output); + server.send(200, "text/plain", output); + + delay(200); + + if (acState.powerStatus) { + ac.on(); + ac.setTemp(acState.temperature); + if (acState.operation == 0) { + ac.setMode(AUTO_MODE); + ac.setFan(FAN_AUTO); + acState.fan = 0; + } else if (acState.operation == 1) { + ac.setMode(COOL_MODE); + } else if (acState.operation == 2) { + ac.setMode(DRY_MODE); + } else if (acState.operation == 3) { + ac.setMode(HEAT_MODE); + } else if (acState.operation == 4) { + ac.setMode(FAN_MODE); + } + + if (acState.operation != 0) { + if (acState.fan == 0) { + ac.setFan(FAN_AUTO); + } else if (acState.fan == 1) { + ac.setFan(FAN_MIN); + } else if (acState.fan == 2) { + ac.setFan(FAN_MED); + } else if (acState.fan == 3) { + ac.setFan(FAN_HI); + } + } + } else { + ac.off(); + } + ac.send(); + } + }); + + server.on("/file-upload", HTTP_POST, + // if the client posts to the upload page + []() { + // Send status 200 (OK) to tell the client we are ready to receive + server.send(200); + }, + handleFileUpload); // Receive and save the file + + server.on("/file-upload", HTTP_GET, []() { + // if the client requests the upload page + + String html = "
      "; + html += ""; + html += ""; + html += "
      "; + server.send(200, "text/html", html); + }); + + server.on("/", []() { + server.sendHeader("Location", String("ui.html"), true); + server.send(302, "text/plain", ""); + }); + + server.on("/state", HTTP_GET, []() { + DynamicJsonDocument root(1024); + root["mode"] = acState.operation; + root["fan"] = acState.fan; + root["temp"] = acState.temperature; + root["power"] = acState.powerStatus; + String output; + serializeJson(root, output); + server.send(200, "text/plain", output); + }); + + + server.on("/reset", []() { + server.send(200, "text/html", "reset"); + delay(100); + ESP.restart(); + }); + + server.serveStatic("/", SPIFFS, "/", "max-age=86400"); + + server.onNotFound(handleNotFound); + + server.begin(); +} + + +void loop() { + server.handleClient(); +} diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/platformio.ini b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/platformio.ini new file mode 100644 index 000000000..731442831 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/platformio.ini @@ -0,0 +1,36 @@ +[platformio] +src_dir = . + +[env] +lib_extra_dirs = ../../ +lib_ldf_mode = deep+ +lib_ignore = examples +framework = arduino +build_flags = ; -D_IR_LOCALE_=en-AU + +[common] +lib_deps_builtin = +lib_deps_external = + ArduinoJson@>=6.0 + +[common_esp8266] +lib_deps_external = + ${common.lib_deps_builtin} + ${common.lib_deps_external} + WifiManager@>=0.14 + +[common_esp32] +lib_deps_external = + ${common.lib_deps_builtin} + ${common.lib_deps_external} + https://github.com/tzapu/WiFiManager.git#development + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 +lib_deps = ${common_esp8266.lib_deps_external} + +[env:esp32dev] +platform = espressif32 +board = esp32dev +lib_deps = ${common_esp32.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/printscreen.png b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/printscreen.png new file mode 100644 index 0000000000000000000000000000000000000000..9fc7dbf3cf0587c1a9ed322ae05e6a24cf6faa7a GIT binary patch literal 25768 zcmeFZWn5I<8wENb2!e!4C`gzn2&i@h4_oGg}(8Nr#+pZuEfBmnhiv+XxQBbhzo0O8#N}~Rc+~rIVy8ogM^xFvpijApO7Jg~{URm=A+t{f8dZ(nVkoAS1=qs9hy1n2`nr`Di89q8j7sNd7@ZpQyyu^Hd z@O8W1{l}Z{ZSUh2Bq;m} zlAYpV_?SJ0-ZZQHXY*Y~qwe^c-GWvNWUbWBvRxma)8+88hDXlN`lnv>ZIlZ(Q}!Ez zY0(p|jBbQ%MBOi^xS-7;6OB1rT`Bfw5ySB-xDXP4*~`1(n$^YjCZbV7{`EIQ`Ka#< z?;p95j`wUWZdUEyf9bK`GdKLhK68fMtB6l1rfO`(p-)u&AOm6=H(P;t;&Qf2=)-Z(EycK2z;tS5PW<@;?gjDNlYx*~o&2ZzDPa%ced& zjZ)l;(Ev-v>;=Im{_l_95fG8;9mlFtt)pu&uMiSfyBsKj7|6lxOei|vx z4!NUK(&4f9M+Q1nm_|)YtNrz1ki|r1H2(1vF^7p8;BA*JWEZSdV%m!4YDhT?OD>u4iH(R*cKRag@ zBY8#R;Pba#CxiGh3k$iI9o%;}^282y+WRV8)=QQKbu=qp=I!sTxA$f1mfOKH;G%>( z>uo}u>|5!5t=PZsh}laVcIM4<;vXpMD&1vtCAv>LZ{_^!7cqj4&&Pbs4SUm7o$9F7 z2iS5do)Z!hCRdmD>$z&Kj3To<_IEdbvcwG-N9dZ!hI6FlnRsG%W}Lvo3>{#%sxo7Y z_IJ^m8G&z)){J*N0saEsrhYDdF8=f9UqoCH`)kdd0a01T&EZZg2yOW7RQZdh!*79v+B%6qcLdZNY0@k*3a6nKs5&qndW zA|028c$S~A$VdL}L%LURMzCv}sOvh0!Sd>85C>R{YZUC)kATeyKc=#d%-H@c#1QLL z+=1slTHSRv!Ec!I9W|Sph95bDWwjSxUzO*9hAv6^g`0A@&Z9034wa4zeVR&2@0Y;) zLo{=g|Jan(`7Gp|jl?XMXV386+q2O3**tgc;Xt&2y=7;jw5?y&)~KshOJ8LT8`qNIH3heFz zuifuQd{jomCAPe7+cwT3Impe(a>RPO*qFQMTI024(OEc;uu-=>pQ99y3Jc-ULTjY< zu0FL2R?;|rZcVlrgw4id^*d2tiLKE>Use>VK}sJ9FKUew8>8Yy+HH+Eqhy%ef4`c1 zNDq5KQc6-AAYDsduft!jmaSt>Z&i{|WHmBm(iUw_A-WxpLV!h7F2(4vZAj}u{Y_Qh z&@e$hPIM$lrth^Soo96V-fAs{)q1$L)usORg)#Mhhs{A#4Br=c5VeXb@90Y-?E;e^ zp)t<`jJ|TNsV-Aid^1ODOt*}4naidJ^d zC<@=!>p|tvb+r16n<#_VWSRCeZEX)G4l;5o?O-7;(E0=$_?a)yK1m$U?1U@vGW zX204)hMQ{yNLIjI zi6|HsHmnzAtJ*q=k&H!8AyCs;f+}pi4&(->B2*;loT`G!sC#u8IEKVvx5aG z80qnXcG2#e>Qqm80^g|j7-dde(!*3NO}Y1FY4-<x^@zbPMCVp~aqguiTF=w#rxG0-}PZh$I+~mc~wU6?6w7Wj|85E6caa<4!si}nEC;6(U_Ny+%2|A`Pm@juF$qp~;VUPw4TgE)< zdxq*WYJcDj`>Ga?>Hr3ir>LLvczV3#bSR1C(>pWIkeI+--e7+(Be}0Kyb!5KN;Lnz zCz3?sIBH3>tA}RmVVz}tv)c?-nu$?EaM7i1(~|M@74GiW{iiY@k--2BW`q-Qq6BQges?gdJ-;wDkaw}O+m)gfPh)uz* zx(%8;z1%Bzj*cj^Ul`h^*E*8nh_-^#_#t4ZGTVB=hchbeMblE1>(`y=pI^!mn-5$dJeVGyGYvYo>WQ6(f&{dV*G+P~5!8=77=2 zUJVIq-ci+N6uywP1mJ@c=5{FSW$0oCJS@%=>#~(QVB5ej6RaHCt5Y^b9c13OVNS=F znW$$b@;haak;=m{CV*nXTF|7)dRkpeCK5!Nq^;^3BsfRUFNt zOtd<3Nk!a}pK1--rt3>x==y^9wZdM_xjb7FPk%B=S>%)Y2wZ^tDBlqWinkGt=T>)- zA1w)pw+#saFTvI5%Y`IIzY=He2LQCx!>?5IJa>D|kUJH+&~KM85!8Ws_2R+3%CvyPsU!7N208 zpIq%|N8u6J>3Tt;7o0yYNF86>{{l0l!8Z5R5sqdKT>xk4RMqM*om@K_g2x~Hn)+lI zI<(A?nO%nI-IHto0@&L2a^`V-A^u$k&gx&e+wXULZAun#Nbsb=aSX&w(R^DJA7_8g z`+uHEocZQcQ+LgPti0nn0Rs#sy-RSl!TN5*KiA^~*V{56JDHXSFy#UsuSMB`*y8g0Q@!D9v-|4g|anDUkHbSKjijGOYk)AlYW z*Zu=0?Ej*ICI%_51NYpMJr1$> zG%vR&{B%i0cW19f0pL`f^>e@bf|vaPqrK1JqM@|&24%nxtrEALwSoJjJlCq5GobZh zT8D##cz?p@8*%uk>ojO=)mV!IH1bir@}+UU(sG~ge#h?iR}B^Q>qXhcHSvO-)Gmry zlT7Tw@ky((6DQQzVFl3d;+ggrje-?EwOS1|CMWJR0 zqew;0)jy9R!9QS$?++g?loUTg51tm|*r&P7ZpLNOVuQCe{+dFetZ=Zv6gA>JwuA^_ z5bE>5?wI0AnoNZl!N-{7p z$`|uxn-(nkvtwYDJJWe9j4r>=^+PYCo_?>1(DyK}^(8ALvQH72;~8Qsu%6hpX=@+v@gYNK}0*e5zu-%|4+=TM?Z$K|~?E>cwN$QSF{(NY=0G ztedWDgkp4CmB3&zD@F@azGw4j_1!wD91hmw4oY@8%4QP>wzMvCnaB;pe>F9Qu`Rt? z=X^ALdCn2v=9@KBkj&p@?0t)P*uGsP&t!9Pusf(d2$pJK*e6tC4m4prC`T!^e(jU4(`5Q zDjpL}i@_$4!-fh2FdnPp-}4;Fyl+`Ya-(}JEOXSk>p^u2A7ijg1UOH~L6I+I-3zc@A@s zcq(CqZH2{)biF~PuMbO!`jSs&C=LFSEb)Ttbr*+2<8mZe>6m6wCtqXQ~dc|qs2nISTZ zzMVRUk;6mA6kT~iRh$lhYq09}WAeBNF5LOr8ry|* zbw02d&W8tbmW;m|;6-XG6lgstrS$shwq+)C7zQ6m8g#@< z4I%HC7X0|*%{qj6deM*3$$^MUpKe955$+-_4k~;bj$!F+yu*DW$!Rm@zV&4b5~XL6 zFvt)rFnv)w|HWe+lzNWd65OB1vc`2iYV@o#U?EiL#L>S3vHO^Y`R-=Ejk2i(DZjE( zPuH#GrO~@HOYuY#ZT#zJt&3_Dee_$^-jn)3qDh_KLl2{~cL(XL#C`N0YfJiUQDgD2 zU0{(#Zxgzj_1orrZ!;3BQ6PEiy6aSj6h)Ey)=0m0*6KPa!4Tf3i0YTVGH2$MV-weL zKv-=!d7!GaW@>+HY-|_3pgtk0wEY2c*{A#g{n2`1AyD9-AaGs#$ueSddgT?>8_(?t zqOGRq$h)-%`Df4<^7KPN$H(d*b**aNoC)VoE{Ts{ zGkXbGuZE(8+}yiXA|z~%eGy@|xIgh;J<3#ulpWie2U4(J^X^}DflISrLlCBM?tLEn z=>Bi4^Zhw1a4qnnmP>9oesGdAdOdnM#UP7us?`;ym&7>6ou0GFF=&&y{BuEVOFZ}l zucXF$!3~+BDq8Lv$N|8>i@ z1yy_-y)h3C#>2PzimGGP8`Nlh`vil*ZbHser$pA|-z@x-bMNj$><6=z_q(+XL}frz_Mo85JQ=_vDrN}F+uY#etRLD9 z&Wf%?>Rdj#b|QdIN^cyGK?=V2t5^7J?CeufL12sX1e- z3i4xt?Lq(>z?->%ZXN1*Eo?n1ywH^th+Y{R>+Q}ptQ}a!!LcZ-vY!s*XzpU`u~86{ z#JV?CrT`c&09tcH<=&bsbhsoBhD7%{?fq%cPEm+?w$#RZw80_X#AgT?z5K}NO#m{A z-Ur}pb1o%rh(_CTV!JTgAmi84q?*S;JD?4%>B`IPrkVz(b1HY6HgH*B2&Wy?WK;@I zeNwgr@i}kbq&*hK2l!^okt&-NK7R0o zdG!h<0P{rv+t(%R_(=%wZ**HlRd$PF6Jt>TzV-WzS&ftpf?{bF4z(_sI9(hCcgd;3 z!izKS{m|PU@jTcc`TVP0>|pp|@a4IjF81~>Tr4ym)RDcX_5fzm0;pO}Vu0!0M{<)> zCjsF)0X{|bvmuZeE{FTxdRcqEhi&noEo%=O2Y^WnnQ_N_n7ZDa?@cNinxW7uQi}sd zA&#zTL>f~7_c_I7X%*SwAyQKt=X*0uLGhQry@UD2vgJTF(q)Kq zTMHnqv+_CkXT;BNBYuW*nTgT8sLHt@v{GSIS68oHy(mn$qh5|5Y z!v|p*vbFRo{U2_~T7oFLjKMo~8WfqHI@yxBa3>(UPzmYHsO(HfSr1>F7@(~rB=dVD zoU#I?Imrf+9IG-{&*mn~2LM!;8g)jpmU##PThRIn3qTg`*3fTd5cQl7^gNhqjzEDC zjc}0BaX%X7nM*)`3aW1NHamL|J2U|x3ab&O#7U=rsf+XY3B=VOy6zJDjDZ^I_U39N zANN(IX9XguseDe@y`AIiqJ>gR!;uWSCk71tTLb;c#dquN2|xWtv%+uP&ewj z0;|IAW)y!>{AV+eyh$d~pok`85*-F>N3ow$`V8cd$1jh8q9=dW8RZZ^r%S zKZsE_wPYWIjs97S4mg#L1v_GcXhEy(WTs4a(hfqnlcMw1>g!ASIBY@->6N3mcGSMp?#YG3xbLC zBxH3`r7H8f8Mt#tVP!ISXf&)}DbMzDn@&-a<#cF_18JeW_Cfdiu{mtgcigh-cLy=y`)^U&8SW`t32QWp-;l$|J?DmID~u(mY{TU zL!KLembk4se}blnlK`6eRP6Kcgd6(5`%sS1^j}T$>>#4wuzzB?G*pCenCohCqFCB8 z4dKUHc~yJyxBA1NZi-Y;t2b-lR=x<+h2 zF=W#6c>>Fq4ZTX>>Ky*xLiNriCb&BhMTPsjwW(&lTukB%n;i^S%|bl7mN{ z{s31y69s9=w!J#hS755R_0<>_D0!(bD+xA~nSi$Jt1i5ZxDV~S;|dBy z%c-XA2yQtbiE@C1tYKf23Bx8DIb_bq6R@oUs;2A!wy`{d0>JWur4j#OS%^pcTL*$u z_hIurY4@J6L$wEF4J8=pM-wzNzi9O#?uMnr!kch43(Bf|X%SaP0G)A|hF$9g_`4!Y zBkyXT3Of{+s)p1XW;J>x&Zrpx9w!?Q+6M}wl}e$3dK;&|!3CePvGfWhc6Gred1%_5 zHoQG+h(U zq4=OAjBy9WPu{u+C@h^oC8Z4%eXCG%vQp5P0ZHVHx|`-R#5*-} z1L5J`rJgX@@l}SRzZ{jK$b_=U$kHhn#cms6fP}FKl20+nse;_Fq$?(L*m2JJBz0oZ z?eW+9QJR0>H**T%)k|InTU7^xAhKGqYa9vDOl_C-wc@nCZp9(WXt{v0&j@0`w3I zge5Kazp|M*g77NeX$=bX+Ya(y?$_zT=Wbw7V_1_0MpsKM3iUa>J4+e3HStt8fWoqO znk+|M!$1bsS2nCXFSK;QHy@6+=zk~AH_{X9zNu-du37#&!`<=STXh-ZhTe@WlGnS% z@v#>BW`nM2ciTcK%f@lA2A2m~+Le3&cTJ;nVM zYj?7IL7q{=5H45Y=+Cs7t$KRv!XVzETT3_1^%=ezsrt=7i%Azsy$?()7_iWvr}XC| z(iV%yJn~`biGuqH{Jo+)d0Dc}4|x-zQ{6Gopqug zS`gfs$C@td2uCmI6lrqbky@u=p@DTfvjXWqatYMg0p$;zkT0wPFk`_rInGRbv|s(` ziYWf7AKq@1{wfePFId;N$9*e-^LIEeo9@4;QcpD`OW82j-)stO3f%0hEE1qfln$h^ zqT}*h;C^?d_p|x7iim)P) zkL$u4<5E`s4PJPshAHC#AOAyDT}#ViD;UGR*Wi969tqr{OoI&P8cLPVr)Okp7KlwZ zw{FCya`dK^K?~m9qDP_fY@gFN+9D)FW>#H(l0gckQ zbiRy-sM?$2R4cYZv*dN;rAtxNrnL>-k*Dt~*cVbo_A57Vvk4&(O>IIemIqs&2ed*l z$%4&=+Y3)e1Z7}hID#$t3ll3FSXR?d0LFA4mP*`}HfjvLvYbyYvhh^*GO4g9)@=(> zsZ(l|ed@n}>%B&BmDbDg%6t(6m&v=RDhGh3*jI*{MzW2#x6(2#o6XRu zX#{DWc4&#!&0vhaprD`B%hkqTi{w=&a#`O~OMCSu1}V6aZqch7mBcE=o}OOpJqje|=kXe7V)^kcH!)d>9& z1dPuzdLzcOmWG`kC50uslfr)2YPh7tow{aU+Q{8LE0s^1q9pA)xhp8zPCXwhWoW{F zO~d06k^v4Dq`cc-jv~|^|NSDK9&l#G0Ol8GNkRbvQDZ9VzYOtIw@6oz*F4mr$+a@p zbT=*2A+@GtqG|rg3`Ult^oIyRvOC(hST0cAuO@juxhK=B9zEaN3lM?5Jp@{*k4&8e z6kgGB;>#BW3j6>JsOGN4-i{D(7^xghQmrqAR zpJ4?`lC4(f9X(s5GVO)$8NF}SDXfW6XvR2O=q;yR2w`__xa0O`2%7WdK=Bvc@XeNQ z@x0oKr)=arBfpJ7R`988tMdH@29NEDDTRiV{XLOp_$+6mcp4;g4cL{+2bqSS+&JhA zlvNPh-_Y{BTlm4`56|EE*1Uk*cZ%VoU1671DLFzuVyS$msjQ+L_)g`&%}>eR7oM+<9HPG#ok_ zbE2c$xj+;BElK?LvHSK8~-t&@5& z8F!OtrB$3c3>Y#5_oQb!N)xHPc*It{i5NBJ-kq10mbT(BJV5tN=Wnf|vdfn(fRheZ zn!+ex_ic`o4Z8*c=6SDu<~#q9Nxwgd*O{}uh|o&0q#-yE&c{yQu4Z)XQNqgGHt%Lv zgk}h;I>W*q7to+s$L{*SM-FNDnUIZygg3JZK5XcFIQZhDJgx{{o&lv|(eg-ndAFWB zy4UJSRyxA4FH_U1(wHHoOeICVs*O6StJL0<_7+>Duj1Hk2a7T0x4zrL2Yc(wJ=Y$- zOU*qKd7eE_E=I67h+1K|?J$v)GJ^nhXBB|@hW*F=wdyvi6cIImar|1*`Z#V^0b{1` zInW#Dr)mld*ALG^L{;rhdKXt3a|sRS8qscjomzVf0yPNG^wnorqQ`x2?=9#b%Br)Hq=HQ?^KNg#6^e8&OD;0AMJr>m1_tM7ddc{_W;zyay-w#Lmee)io-9d_ zgcCZtRB^*$-8wBmzT8qXiUa;9Ps=Zaf6{y_3yc8Kw;m^Ui>a9rWzHyoC5#Bxi*U~nj&*PglaiGJ zOJbHx2xGE~1NajLG+(}z2~iQtWS9g^>-M-j1;5+&YGGue;d#C>H~Zm?P;^Hc+&e^I z`g7sD0n6WsOT0??6LOh)*kLFwc3g3qy-0$dr(oH5(#w?_1JhG$-Haz1<(@7^_=$Y$ zwgN&IH9O~T8mc!KinEcY)NAjjYjNAZs+VMg(9+P9Rj~qMpL*X%0`-d3B5GP)5AfDd z$ujFg=tx-+tm02S@Nd2=NoHGIAf$t9y#MQc5YNVeVzu^Y$uCuA+MfgQmnX;e?%m{X zfvKXnb%z1HWG&@K{vTJv&1v;ZyN5emZGEf~*s^$Se?0&waBGU;UcGsT+?7DM-u!;%F8Ezts8YGH6MA~L!c@Qzi$vgIYqN7Yv1|X(t;akfw&Q?XX-)G`HD|xJj2MBfc z?Gi_wDKl1zXf7KKZd#F9$OFssuT+>*W{ElYP~ElpQY{&prBzj zNNf1~j0>O6Ubi<9tSp}7zep_98ef3cYkldo?-ZP8-FqvUA9?-Nu@~iyDsWu%30?T^ zr0dwLdd`wZ{;&Y^cDq2lWwg8F#8>i9`Ai2K68-%5SdP_qO5%^843=|#jX2?;dP+cj zr?H;=j8dF=i!hSg`~!yeC-r~n@__;<3^VzRcUTreqUp#ULcE_4ZagQmR+xC=Y(n&R znOZ1;-{=e@252}mKCiVZ7rk7H296(#N8(lE99kuf8&!^n9FF0I)Pl-Pg3i zr~G&#D?37;@ybk!x6Q@m@w%mo@>fS4or=_l3n^=hB;1xA9ctNHUq+rl^LWW@yYyYC zJOWXm_J1F%{9g_K?KY(bM4`Za@x(UbC9Xz@e+mD6FI)WmzfbpHGD&9!Yydt@`LRqv z{6HVf+&@eN>J>8$e8!8;*4 zsDXJxwfedG@nF1XNqflV&*MDmIEc?Gybsu2D6W&p2eW$P_(TZ4>N#RZiq%LSXu2Ky zV&L)PdWk3Dd!r$)?6{h55%9K~YLlYcg=Xi9|6$r7_+Ll>5lqi(X$B&C&Z;1ewFQ(J z61mpIhA{Y!Uu?a#JhBAb;Dv^@zNKi+%Iz9ZYd?qfriU@ux7>4T<>@cELK8&Khlp_= z9efx>XAB6;j8$Q`fa3=V#o&7rjW_uNYmEG)PZi+pN_545Q$uLy_s1+y^afo}yBjO) zl8>4JCI~Jcldv#0^&t>&VZhk!R7=KJ0^1`xA_&BpJqhud{xZCAqV69&>Vp{;mYY7^ zR(?L=4BYI=v3fpZz(icS!Xo!M)M2YfD3fSWWeZ2dZE;rZXnVsP|MVq;03J&QLn6l9cQun6omt-hiy1j>00q3dSf?4Y^7rTc`XCTJj}R8fZ_hC zmV>&tC@PGz@iBiP&fJb8m_2v9<1AY~-+R1B*PMY%`p~X#0V06lc51qvG5~U>wbcq{~KdS`=w zCt}*~9Px3A@2U^Q?5E|50~syXYgPa)VDa&$ydA1POIux&+AZYxeR_$@F>i=e19y#6 zca-_r)!|b6EMOwo1f|Kq-p=}nv>Rw5Z~`SrB>w#qw;RN}31>|16RxBV0|LS*AUIZ> zI`=AZ$_LH^g2j0}V387%$nTDTm`SCpJkc=4tIzak>Z>Ih+yh!-cgQFm!1+S7FVSm( z=H1Df;2*fo2Bng-L;lAPNtrAD0^g=uA^J#!1tCv{fR)iR^cw9^Dg56)9tR|&$QjWS zj&V&A&|9>{UjqN5#Qu93t6*=&62$$b&~S0Y4o>%VyIk1R*v(yzjw1t} zVtjV-Q&e1toc@c+DokB?mX?uhcuv|#3e41f#^Z|%N$oq);x_Cz5knT@g4#YiSJ=i`j$&86MPm1g?w9tf{ybq zaFpiuceRY$a@%P8N`ZAlblSy z8+b)brvp!3V<~6oN4%1;hpmfqNWOwUt}qLEI;v@`?(ct2>Y{1<38|3rGa--nkYGS1 zDK{718#s3okG2TyI3UHAI%9~zT-(LAB~+RZbx+y_ZPO!92Y7{5xZkW4{;@_@jly8M zyadk|oTNut|6NcVp~`p~3`keUcNEoSRTyW(iw|NCgl5)`p5FVjxB}sLs}>)~kn?pM zZQ9$)fe-rvHx;X)~UXEya5?KlV7twdV>pKr*HhAb{h@>>ql=V1DJ zi1(h)7*sUwqXVb&SZW$iwmzS^5dA;2uPn1E{;F3{q_*K8^LYQvog!xsoficWIRWJ# z(M^@8v`K4`AGZ4cdS}(~1-fsPZLLgfPBGD`R_Bod^ zC7c=opQ>BFa4mtRk9-j7)rOXV{b&eqttJdYPMHq+PKN=|dyld)05V)^d~IR)TV+_L zhSAtwe#=N{v4@sfgJs_k-6!PPS~eJcZ-HJ`;Np6zEGYdS${B#JBU~#Fv?JcTH%Gs! zt1m|nIn*YyrBe>NX<)M*31Q3asCz@ zICVb!<%pu@*rs)}qou)MF40(lO<$s==s2ti9y}HoCj8)PzVrP+vI9UZ4oexqz3#*$ z`gLv?MAlCOJb7rn%O!mv2v)i+*Njl!oyO5WKij9YA~r_`oXodS{D#&k?#-iTWgwf} zzr+sygm?~Ad!NdZkJ>i>{cCI22nISwl8ut(zN|Go3_reND9Hm}2<<1wt>qm|Mu>jo zxr0^hM6^8@&2_@@(N_A%dXjd%XFEFi0qCjS-5MWK*y2E*YFP_t#8Wf(bUGF-UY++} zl(Ip-jT-PZ&Jn{J4q8N&no0Y3jA8SKO+JZSkI?XS*n{mB{#eTVCoN`+zc{tJ%-}(f zU40fg`7-Wtr)))ky}W#Ps?yN|0)<3|`NLe!W6ky)MoVRvszqbkxlhGS(*$}M&et(b zr;WQ)mR2!$Nybe6k!I~Qm_HbK$!y#~NXqX#Ra48nEx)jNM_<=sj8hjT63Oe2I_OxY zA1XKI?9kBMoGuw+1(G$w9Z31Aq9bbBFk?`}rLEasK7pdEejwqkh8uT>J6iX3>_(vX ztbUQ^@ts}P+H9IM=5?QAb;UGDBj8I+5^9%R7V;t3yp<$D7)^h?v|A0Oorh#)bkuunf1eM90gO_y_5On~=EClo)p1f-_UR6Sixd-xJedQJ;dv>0Tg z9Fdu?YK-U7x^nFb-6whS;S$S>4<_M02qVp0#$iMw_8BSO0F>#UKv~2|`317qPg|Lm zAM7h~d1J3%RW$fi4ck-T*p5ujVwJ`$@E;4w%-)Rz23G1zX8^NX4>)Nd6kuz*1k*Nq z?-eQeQZQL<4cmuMQ&Vd;hqJSZOuZr`9mWa_aD6Vpz}8#-`-5zk=onz`mx5(65T`>7;T=uG3?Z^{ zZ3v>Lt=8-on*wGFtKBn3Y5G-_BY;;ow4{Sc9&RCj;=6b6U*&sia)K>h$N)&fAY*aT z72)p>D!G!m)99-;Qe5kr@sB@_jq-kOKdo~pa+Tr|tyNdN-XQ%j_NAdTM~$6)Ck^mr z`1WQsQ|_3JNo)NDbmA7?;`poHQI=+ejtc{Jk~Z_@HGSfQxE91f8jk#5h&pe?>yL+9 zLcEn2hr=wA=ifrzU({cvKUm^KSQ@9XYyN3Kp;$#(-Ny8EDsH(2y?qo&$7^QBrk-_H z70Od(11NCPsyY~PbwZf{_vydn^PMvUG+qTg9_c5e5|4j^?|s%g^%?1jBnYJ8J3tyP z@PDj&l*J(U6Ck`R`Qy5u)y;@QTJizm zEME4nAlJFNh(#bK6)P(UBz0ZO$hS@kn`$Kg{JSye_x-<#*gsdCS)}^oX!HxHY=8X# z&Jd>!q@TIdaAo{Z~+FVpGQN`9w7=?tFpl;v9 zX|=d)un7o#)O#65TwjI#LQ+zal{+Y;oPZXO8pt!k$(INqGym6_UtrQ|7Y9_h17J!B z>jNGjA)se3Mnbb~8^#>_b#ZD)v9SBDLpdN#TT#w{iT+PWcN(^p*+K?Kfyk_l1-1MV z;70E)*$M)^O3?!Vh3}Pe?SMsAkf+jP?iNjMKDw!uC1bf6ZrH8fgrjFwEtk;Vsect59A0C z3vnba1~|zw0m*AsbwN?MvqJxYLpDq7%bL@mX?nR^RbAH@bSfbL1u=+gEH9r77Fq<~ zB;X!Qovo<#qbT;=U(i?6(3l-o-oZ&;o5fZ8tqflmh8()(NAj^>p$CAx$C>Gh7@P*a zbCitZ_g8)m5gh_ngHx`*-^*kId($Qmyas_CVCgMeb}p{3dSna7a{!LlO6IcdgG^DH zBgln&bApQ`ULy% zb+QDSW7zr?`_ng5@938GWYo9=&{Dpfa|*~__6xf=#1BqWRiM8nLNyA_-ZQ)$_s(0* zS^|wLwqp7oJ4w18J5xgsjGk_RN7 zINLvIEr|%pJ78?g2OM@iFrq-q_cu`^r!29rai0T#s}!vOrb*{w_fAiDrX8q)N-2}a zcjFHB8eqzbMScGnGh?^o);8t0bg;V)9E8q3-$7GCc@C8an$*kpBN&m;G96m_`D!0e z+Kh^!R=)#ahsr0Zul8zZBUM$N{$g+NRULGFQ4OuR#RPHRgUZ(QLVe!c6 zE^wW42%@8-vxpyFlY%YG(Gx}Q@>=vX{(-)H@Vqk)L;c2S$eaadtVM#oWkpM-G~4;r zuQyG(fy}g{gV0kcClM~BN)-wG=fgV=(KRWOzd&Md4NXDAn9y+-^ zGdH^%ab#FY|0nGklFIKGtK`oNw}# zFBk565w@Ofik7$rD<%}T{dCK~8i*ZC+I_EH<=1Dx>qx7#6wfw{#tkABS3b{ssLkjA z`(aRwLe<5Wbz*9Lq*0@x^y-R2S zwA?(w9$(!Qg0?IYN{M@`BYC#R<5XM z;%!gbgd?ZRcynG#s8Y0~nU(n0QyqXd?_$tR2QL@!w0=m`dVhktDg9D#wScpUf&iZfmJOLNX|4ZPUOaqHKn={elx4Ip|mqI3)VX0HgNpPg_6 zXTB|Ko%Igldm|wd3cf%=*-K^08sIsvXqk_%2prPG)8KP6T@}0B8Qy%;y+S6SQ_&`n zWSC@BuQQW~jw2U%T5+a{S(sCtZ1|l3?HseZDr?6!Ri%+I_Y~;visu16N}h|$Y?Fw( zT?SdiTIST6JWd@n*9-dXO*SjnJ>gQfsXkCABiDd&%Qf(EoX3SA`M#%QVL%JzLges0 z6hI_I6OKSvmR`YcDSg*81}2MaQ?35cZDxG|)x0BKeNCLX@Gs$9aK`LxE}Rhbh%A{1 zJ++Q~%XqW9q6mAt=KM;;tEl>obXs+zhrLp1;;FewiaC}g6TVI@_ZkL(q1qDX<3$47 zUv@*s!fiETTv8rcw(xrkzqvI8<>afa(KL;jLfpWnRJeBwL?oYXRx1UIH#%nMt3IRx zx&?RTQOud{4*NLWs>-a^o>#A%aT$Cuhnjav(R24BMy~-ns-Fd|Ka-Q9sXy;6xPSFo zYye|&_r>R}T$%TN(%Iqmnfgn;gNVoxNs8^Xe$6duWXGAHRv6JmHgT4mg5 zBPE-o)?^dpyFUYVoSB#Gi)1wX^}eU5VucTUK;H8M6TeM7DN@iQ&V4fvnB@6w)w@ZV zfc`R7^C9`qvk^hRdIl)5FZ{OZ#(9z)T@wF!CH9<8#nyr|>9b``Li*`TBrB0;B)nA$ zp3g>ZP@=$hL@v9|`NOTyfe(SOqLZuc-&15h&;Up}I(pG(qZ%)CQ}~RdgV*(Z6I@g8 zHL{j@vQB+z99^hW)u#49uaU02Z2wxpdrLecLcKrPH4*xByO)vj82j7-UCqHVipjB|pPYqo3$gBfI$WQd5+^7w0G1gjX@?TG4fwR&gv3#q5fM)=@9 zh_w7v{xJeL*cxEn-~mWxs0lZ|y?ticG29rCgHp(&k2*v=%!-7POkP~2oVyn)e7VeS zo)YB=Q+3N`b+G`;> zYJ{)w@mEIh2(XmI`xnQ>BAd?tL#2Nqed9#q-@+M0cLcaV!Ttyk7%Wk_CwdOEAMR@d zZuX_zCpGvBpoZq3(LOoNP6H4ZwR{n>CtA+`(+e@@@_lCqpa{oIkkWD#0>x?SuI-Y( zmV|_N5$Hq{bXqh6&Yz+&NZYXr^hSd@l<)iPJr7`+?JI(+L%WlMdb8*?$SMA0rFnD% zRr=pv{U%DC`^7(=On({xf`t6mwZ$aRw7ER?*cSDi%}V+5=5&|n;ZTY5#F_E7!LG9r z`2=KBihJ@KQMfj@{@PJs7AOf++K%CJ4K6a<(dM)rj<}-t1)zI&Adn9stYwMG|F|cb z|IH?EbeTi%Rnu+8$Lc?6C27>?3y>D6YSrd;mb!kvigX3y{d0+aGc^^jtAMP$bR7AMdHo8rgc=P%(a=Lrw_m9B4 zPe2@_jq@}FifSIC2wVfRxin(;IUb1shMaDkQyP4iA-@%TIbpgz&Kmc@3qYG|MR4d^ zg8t_`Fvd2N2zMN4W_k=hvdBHHUdvb!JNDx=8$kvRv)byL^Z&SH8f{ptrSUT>~%I$5O-f-0D<1QQ(); zqkqbQyT0Zjuu&&q%Yv27CF8yg))4tj za~th+=l^K$-2b7@_c(5353%kI5f+=ly-eOpo&)oX2B-oyXVAd_VK~zCZ8F^YyY_L|SQQ z#1u#4uQl?Ze2dI84H@~ZM-A)FA|?nprH}`+Kr-|q3@ubaHyQ~4$`=l}6awst5|LP~ zgA`F90or$d4tF9dC<-jtPS-$Hdi;0QmI`D<1s(8D=0(bJu-M8e#wurFhEt@&sC=@J z%pbvJbc<;AtXl;0u|6o~(-qngmx4xld>PJ&-B^8jGOb&m{T3TA2x_EfEZPhV_Df&_ znz*+%!~Txzg=1iOC-E4mMZsJmEp5QVa0urZdo?PLA}?_N-}oM&@+4 zafu|$@;Qq66cpyCxCYCB1=41URrsOvoQ1j#YA$+fTG80++-9eT;gg_%BRO~%Qwp4! zZ^3^|V|RBqGa;4-w^;yf12S-2h<(bU^HyENdkxwWbCulj10=R)$UeV*DQ#N-F{^J| z7#cRs(()N4&{S`VwXeRI7o)n@XzYwWcM5=uh%G|R$}fc1Vus9bVOBr9Bc2M>issF8 z3NODWI*;PV0f8vWJDywJK00`^bmK2V=^&e2ZqvSdC{{)3p_9e}RPczk-&3DL_YtW6 z@k*|j+2<7%FUq@_9(zTL6dP3mi$OO>7UJ)hH|sD=;)hp&Vb&iU*D(G%G*1=wp=mde zd(VijkVw1~-$&RtiJlGnXZu}%>LvFR0V>N%vDYQJXz2u<-gctubIEheeV!T0N%}sI zs@A&z_5V_e9e?^H^Y0w9?4VHjbr%9(M|gw`G-g(X>FA7`fNF(0Os*Ntr1tmM`fYk` z$Afl9{LCI$i~>L#uzgFLHiY*W0lFbzGK#A~FHhxLlEc4yGjuh72RWbT3BL7E(fvS|6m`!xax|;%T$Q<_eG3TLv(_ z0*j%HND+TcA+OI90JnYyvaSfv4GUc-NsK=4Y4>DYaGQfAQ*G&*E-RzNwokL^oRoAH)Uea>ONJ z8RnjiJ}!b|Fk@W!){pf;rG4-dleDz7utYjrUa#syeAy>%>W(w!Hmc(F_Yxs~Y}OXy z#E{@wD<~U>O!ci?vuv(GjKc$TsX$a1YB_GXvDz7lWE?gQ9kNSm4tCVhy^FL*1k{!K zP}DpotFz|vWcD!2A=UGK$+c$uuS;Dvb!A!CR+g6s{%6MuPk}6y3wLBtr_|Uak1E&kN zk5+oX_v+rU?1XqJ)?)oN-g9T`FKEu!CPZ?jbtEy#HFKkpchc{mP{B46jHs5KC~pBq z^$Ssbr%NbnA$Z_Y&x6{y1iY!q2zlk7F?G0orYz3QQj>05>G%7gIf89aLwq<98&hWB zh@O{qX;8v<(Sa>{!&-W(%;R-Qz|%+eHY|39kHetaJzWJ53nOgaK+WYsTT5kgKOXun z(ZlXg`O(G$Yi$EFwe>J9%^fdjn>N*YS(Y&mIp$rDa=&J;H>F6QHP(3OMkV)7!8Et8 z$I$B_G^Sh0Bf)FgjZhdy4E`Lk(>zg0pC&Is)J-6J_n6k8?6x9(s8qiuB{DSEPa;s< z%dx>@j*i}Uoyhkjn8}A@zRSy;!dm`7nSM-ivHq34EqZ%>i|at%c;~d|e8;-LAR+wr zFYP6+SK4<(L$Z*hmL^~m#K8U)c&awpu8=nIT5#scTatGh`(ys;fx=)t42I?(ll-TJ zG%9hndK5!!LGkYz{ez}~NaoF+rxUw2XN>h3)=*BhIquxe!(BzE+CB~hkspHWvb_rH zY&#fN`MUY8B!DlQ+ye@SAoQ9T{hrc<|LH&1qOw)P(IF7$Js{SVf*OYn%P{%T^yPjn zhS+L0`UG66q!v`gu?wavivft-V#q#$BsLS}TqxYep(|2G6Zp%~l>?t*RQ~f-y%;tZ z94I=`1cmV96z9Tt=wKoeySfv6E-cJm77{!0fN6Zm<9}?b%wyB!!ga)%*F~j4Su)G) zh9$;?^=y@=lq~)|vK?B^VfQo)IA`g!lpnpYL!NYZYFTa{pVgAGU}FN@=pL zu=|dV2pF|4p(EcxkKJUZ-eCv}&R=sl!Wq@oJM%ma)N0Bb6Msgl`4nO`=o)NQ>-fYs zQ;f5^+%gf6tc!hBF?O@mFlLP)ImGm0PWYKks|RWqn9@~tKMVL2F&256G6;6FVfxIf z08W+Mw|%Cm3yyNrT!}}2of4Y>uDZ3U{Yy$bg>Occ0dH@%=x9=IJ_V_eTeL>61d~Fc zRQcyQimradhfugilyr8Zo`$}Nd`QCuqWfBK%9c9~!byyGeqyNkl!f&Eb3hnYOKviH zG0H1Y_*ryStZOC-HYZ*ijR$GIKr3>=@{31iJ8oZn`-4`Y8ZxrgCk?*?ZUZ2l{utRM zAR%Nl;FSoH0#3m9wm2f>GRz2IgmdpUN_d)U6GU|nW zxJZ!TdUa${5Cx*b%iDvw$n{iLw79>w5AR9il8Ke;a#5i1~#ZdHgEUre&Bg#D7^xvJz8Bdk4`v61u?)Q1!(Dp z%TeyK-`1%^7ECG*McqggAOs)c&D1T_{ny8N@y|z@8;S5^+0RnD1($(IzR*jVxP~?C z3?-7O1)HLKDYJa-nHCaOf_c1w$cGDp=;RI%W!5F8yYA}m1c-AaJOw|ZOjHC_qCLFg zKCsM_O4 literal 0 HcmV?d00001 diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/favicon.ico b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f206c7cc7241d6969ccd7c9ab8d12a56bbf09430 GIT binary patch literal 16446 zcmeHOJ&4pm6wcwlC>+SC+-Bz|ncOa0_``w!;v&dd*eNP1*w}~`R)U3MsaV*Z3WAE- zh^Sy^V<(EBAP8cig^HjeihswUoZq|M+)ZM#o6SYd?#>=_Nhb5nyzkAMmp7A%W%b~% zTD9wvg&F2DHl)3K%lZ)GzcLWtR-sP5`mI!~$t=xuq?R-be{$>K0)U9+~cxG$w#g0?^E z?fd5>my`o5;@YWN)#;G`wqHJcY^DP#OC@l97sk;w>45AauI;Sy(Z;i=_9ye)H*syj zZVpYBtJ!||x{)mdeFc(aRziO z#?A=k!?qU1VJW}TSD9CD`-qOmc)CjYzD-&`WbM_l#6KyP%1Q1X z)bWx#=Uc&NQP%J`{jb{~`L?8XW$fRKf8BPB|1NQpNvqXDAQRA7wS3QE8XhEggMK-AlHcg7wSZ(x!QZL>3?JY9qItg_&5H~`2TeNA7f`P=gwux)s;M_aT%G~6Xn9vj(^%)60jRR zUd-uv)IOB7{3Z0+Zv4S@XV?bP^2eT?-R;I7eYQO-{z8;Rc)wSk^+9{lR6*HU@uzxd ztsVQbwnDGl@|;Mp!i|6{GR5ARur#>Wt?qvSTJ zA=+CW<*(9?fAXiWo5(%C0ei|xEQn|I`>6NIY5C)svMY}~8_ASq{DZo>I{u~o6^(SA z$9wobV@=oxq_uz4(}Ov{0r0$;_xA!MW87Y(Dew=gvMsL-e-r-&e3gm+BH};qTw4zA z1VUr{?`Ycp+S(awL-H+5K3zu%5Y*zys$1bF-0 z@DAg;&%gFfsT}q1b@~x~KZ^GQOMU)yB;QEip>zTFk*K*L>A6=CR_LR8#zu%k9v + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_1_on.svg b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_1_on.svg new file mode 100644 index 000000000..32505f2a4 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_1_on.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_2_off.svg b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_2_off.svg new file mode 100644 index 000000000..20d54679c --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_2_off.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_2_on.svg b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_2_on.svg new file mode 100644 index 000000000..307370607 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_2_on.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_3_off.svg b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_3_off.svg new file mode 100644 index 000000000..2bbf5848e --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_3_off.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_3_on.svg b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_3_on.svg new file mode 100644 index 000000000..ca29839e2 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_3_on.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_4_off.svg b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_4_off.svg new file mode 100644 index 000000000..3ee1beced --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_4_off.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_4_on.svg b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_4_on.svg new file mode 100644 index 000000000..720d70148 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/level_4_on.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/ui.html b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/ui.html new file mode 100644 index 000000000..cfefc20d5 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/ui.html @@ -0,0 +1,109 @@ + + + + + + + Home Temperature + + + + + + + + + + + + + + + + +
      + + + +
      + +

      +
      + +
      +
      + + +
      + OFF +
      + +
      +
      +
      +
      + + +

      Mode

      +
      + + + + + +
      + +
      +
      + + +

      Fan

      +
      + + + + +
      + +
      +
      +
      +
      +
      +
      + + +

      Target temperature

      +
      + ~ C +
      + +
      + + +
      + + + +
      +
      +
      + +
      +
      + + + + diff --git a/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/ui.js b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/ui.js new file mode 100644 index 000000000..9bdb8c795 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/examples/Web-AC-control/upload/ui.js @@ -0,0 +1,132 @@ +var state = {} + +function updateStatus() { + $.ajax({ + type: 'GET', + url: "state", + dataType: "json", + data: [{ + name: "light", + value: "1" + }, ], + success: function(data) { + if (!data) { + return; + } + state = data; + if (state["power"] === true) { + $("#power").text(" ON"); + $("#power-btn").addClass("btn-info"); + $("#power-btn").removeClass("btn-default"); + } else { + $("#power").text(" OFF"); + $("#power-btn").addClass("btn-default"); + $("#power-btn").removeClass("btn-info"); + } + $("#target_temp").text(state["temp"] + " C"); + setModeColor(state["mode"]); + setFanColor(state["fan"]); + }, + error: function() { + console.log('error getting state'); + }, + timeout: 1000 + }); +} + +updateStatus(); + + + + +function postData(t) { + var e = new XMLHttpRequest; + e.timeout = 2000; + e.open("PUT", "state", !0); + e.setRequestHeader("Content-Type", "application/json"); + console.log(JSON.stringify(t)), e.send(JSON.stringify(t)); +} + +function mode_onclick(mode) { + state["mode"] = mode; + setModeColor(mode); + postData(state); +} + + +function setModeColor(mode) { + $(".mode-btn").addClass("btn-default"); + $(".mode-btn").removeClass("btn-info"); + + if (mode === 0) { + $("#mode_auto").removeClass("btn-default"); + $("#mode_auto").addClass("btn-info"); + setFanColor(0); + state["fan"] = 0; + } else if (mode === 1) { + $("#mode_cooling").removeClass("btn-default"); + $("#mode_cooling").addClass("btn-info"); + } else if (mode === 2) { + $("#mode_dehum").removeClass("btn-default"); + $("#mode_dehum").addClass("btn-info"); + } else if (mode === 3) { + $("#mode_heating").removeClass("btn-default"); + $("#mode_heating").addClass("btn-info"); + } else if (mode === 4) { + $("#mode_fan").removeClass("btn-default"); + $("#mode_fan").addClass("btn-info"); + } +} + +function setFanColor(fan) { + if (fan == 0) { + $("#fan_auto").removeClass("btn-default"); + $("#fan_auto").addClass("btn-info"); + } else { + $("#fan_auto").removeClass("btn-info"); + $("#fan_auto").addClass("btn-default"); + } + for (var i = 1; i <= 3; ++i) { + if (i <= fan) { + $("#fan_lvl_" + i).attr("src", "level_" + i + "_on.svg"); + } else { + $("#fan_lvl_" + i).attr("src", "level_" + i + "_off.svg"); + } + } +} + +function fan_onclick(fan) { + if (state["mode"] !== 0) { + state["fan"] = fan; + setFanColor(fan); + postData(state); + } +} + +function power_onclick(power) { + if (state["power"]) { + state["power"] = false; + $("#power").text(" OFF"); + $("#power-btn").removeClass("btn-info"); + $("#power-btn").addClass("btn-default"); + } else { + state["power"] = true; + $("#power").text(" ON"); + $("#power-btn").addClass("btn-info"); + $("#power-btn").removeClass("btn-default"); + } + postData(state); +} + + +function temp_onclick(temp) { + state["temp"] += temp; + if (state["temp"] < 17) { + state["temp"] = 17; + } + if (state["temp"] > 30) { + state["temp"] = 30; + } + $("#target_temp").text(state["temp"] + " C"); + postData(state); +} diff --git a/lib/IRremoteESP8266-2.6.5/keywords.txt b/lib/IRremoteESP8266-2.7.0/keywords.txt old mode 100755 new mode 100644 similarity index 80% rename from lib/IRremoteESP8266-2.6.5/keywords.txt rename to lib/IRremoteESP8266-2.7.0/keywords.txt index db2d398a1..33a48f5f2 --- a/lib/IRremoteESP8266-2.6.5/keywords.txt +++ b/lib/IRremoteESP8266-2.7.0/keywords.txt @@ -37,8 +37,11 @@ IRGreeAC KEYWORD1 IRHaierAC KEYWORD1 IRHaierACYRW02 KEYWORD1 IRHitachiAc KEYWORD1 +IRHitachiAc424 KEYWORD1 IRKelvinatorAC KEYWORD1 IRMideaAC KEYWORD1 +IRMitsubishi112 KEYWORD1 +IRMitsubishi136 KEYWORD1 IRMitsubishiAC KEYWORD1 IRMitsubishiHeavy152Ac KEYWORD1 IRMitsubishiHeavy88Ac KEYWORD1 @@ -76,16 +79,22 @@ whirlpool_ac_remote_model_t KEYWORD1 ####################################### _delayMicroseconds KEYWORD2 +_getTime KEYWORD2 +_getTimer KEYWORD2 _matchGeneric KEYWORD2 _setMode KEYWORD2 _setTemp KEYWORD2 +_setTime KEYWORD2 +_setTimer KEYWORD2 _validTolerance KEYWORD2 add KEYWORD2 addBoolToString KEYWORD2 +addDayToString KEYWORD2 addFanToString KEYWORD2 addIntToString KEYWORD2 addLabeledString KEYWORD2 addModeToString KEYWORD2 +addModelToString KEYWORD2 addTempToString KEYWORD2 amcor KEYWORD2 argo KEYWORD2 @@ -123,6 +132,7 @@ copyIrParams KEYWORD2 countBits KEYWORD2 daikin KEYWORD2 daikin128 KEYWORD2 +daikin152 KEYWORD2 daikin160 KEYWORD2 daikin176 KEYWORD2 daikin2 KEYWORD2 @@ -151,6 +161,7 @@ decodeHaierAC KEYWORD2 decodeHaierACYRW02 KEYWORD2 decodeHash KEYWORD2 decodeHitachiAC KEYWORD2 +decodeHitachiAc424 KEYWORD2 decodeInax KEYWORD2 decodeJVC KEYWORD2 decodeKelvinator KEYWORD2 @@ -162,6 +173,8 @@ decodeMWM KEYWORD2 decodeMagiQuest KEYWORD2 decodeMidea KEYWORD2 decodeMitsubishi KEYWORD2 +decodeMitsubishi112 KEYWORD2 +decodeMitsubishi136 KEYWORD2 decodeMitsubishi2 KEYWORD2 decodeMitsubishiAC KEYWORD2 decodeMitsubishiHeavy KEYWORD2 @@ -182,7 +195,6 @@ decodeSanyoLC7461 KEYWORD2 decodeSharp KEYWORD2 decodeSharpAc KEYWORD2 decodeSony KEYWORD2 -decodeTcl112Ac KEYWORD2 decodeTeco KEYWORD2 decodeToState KEYWORD2 decodeToshibaAC KEYWORD2 @@ -225,6 +237,7 @@ fujitsu KEYWORD2 get3D KEYWORD2 get8CHeat KEYWORD2 getBeep KEYWORD2 +getBit KEYWORD2 getBufSize KEYWORD2 getButton KEYWORD2 getClean KEYWORD2 @@ -260,7 +273,6 @@ getMax KEYWORD2 getMode KEYWORD2 getMold KEYWORD2 getNight KEYWORD2 -getNormalState KEYWORD2 getOffTime KEYWORD2 getOffTimer KEYWORD2 getOffTimerEnabled KEYWORD2 @@ -316,9 +328,13 @@ goodweather KEYWORD2 gree KEYWORD2 haier KEYWORD2 haierYrwo2 KEYWORD2 +handleSpecialState KEYWORD2 hasACState KEYWORD2 +hasStateChanged KEYWORD2 hitachi KEYWORD2 +hitachi424 KEYWORD2 htmlEscape KEYWORD2 +initState KEYWORD2 invertBits KEYWORD2 isOffTimerActive KEYWORD2 isOffTimerEnabled KEYWORD2 @@ -345,8 +361,11 @@ midea KEYWORD2 minRepeats KEYWORD2 minsToString KEYWORD2 mitsubishi KEYWORD2 +mitsubishi112 KEYWORD2 +mitsubishi136 KEYWORD2 mitsubishiHeavy152 KEYWORD2 mitsubishiHeavy88 KEYWORD2 +modelToStr KEYWORD2 msToString KEYWORD2 neoclima KEYWORD2 off KEYWORD2 @@ -394,6 +413,7 @@ sendHaierACYRW02 KEYWORD2 sendHitachiAC KEYWORD2 sendHitachiAC1 KEYWORD2 sendHitachiAC2 KEYWORD2 +sendHitachiAc424 KEYWORD2 sendInax KEYWORD2 sendJVC KEYWORD2 sendKelvinator KEYWORD2 @@ -406,6 +426,8 @@ sendMWM KEYWORD2 sendMagiQuest KEYWORD2 sendMidea KEYWORD2 sendMitsubishi KEYWORD2 +sendMitsubishi112 KEYWORD2 +sendMitsubishi136 KEYWORD2 sendMitsubishi2 KEYWORD2 sendMitsubishiAC KEYWORD2 sendMitsubishiHeavy152 KEYWORD2 @@ -445,6 +467,8 @@ set3D KEYWORD2 set8CHeat KEYWORD2 setAuto KEYWORD2 setBeep KEYWORD2 +setBit KEYWORD2 +setBits KEYWORD2 setButton KEYWORD2 setClean KEYWORD2 setClock KEYWORD2 @@ -469,6 +493,7 @@ setHealth KEYWORD2 setHold KEYWORD2 setHumid KEYWORD2 setIFeel KEYWORD2 +setInvertedStates KEYWORD2 setIon KEYWORD2 setIonFilter KEYWORD2 setLed KEYWORD2 @@ -594,6 +619,7 @@ ARGO_MIN_TEMP LITERAL1 ARJW2 LITERAL1 ARRAH2E LITERAL1 ARREB1E LITERAL1 +ARRY4 LITERAL1 CARRIER_AC LITERAL1 CARRIER_AC_BITS LITERAL1 COOLIX LITERAL1 @@ -644,6 +670,7 @@ DECODE_HASH LITERAL1 DECODE_HITACHI_AC LITERAL1 DECODE_HITACHI_AC1 LITERAL1 DECODE_HITACHI_AC2 LITERAL1 +DECODE_HITACHI_AC424 LITERAL1 DECODE_INAX LITERAL1 DECODE_JVC LITERAL1 DECODE_KELVINATOR LITERAL1 @@ -654,6 +681,8 @@ DECODE_LUTRON LITERAL1 DECODE_MAGIQUEST LITERAL1 DECODE_MIDEA LITERAL1 DECODE_MITSUBISHI LITERAL1 +DECODE_MITSUBISHI112 LITERAL1 +DECODE_MITSUBISHI136 LITERAL1 DECODE_MITSUBISHI2 LITERAL1 DECODE_MITSUBISHIHEAVY LITERAL1 DECODE_MITSUBISHI_AC LITERAL1 @@ -809,6 +838,7 @@ HITACHI_AC1_STATE_LENGTH LITERAL1 HITACHI_AC2 LITERAL1 HITACHI_AC2_BITS LITERAL1 HITACHI_AC2_STATE_LENGTH LITERAL1 +HITACHI_AC424 LITERAL1 HITACHI_AC_BITS LITERAL1 HITACHI_AC_STATE_LENGTH LITERAL1 ICACHE_RAM_ATTR LITERAL1 @@ -857,6 +887,8 @@ MIDEA_AC_POWER LITERAL1 MIDEA_AC_SLEEP LITERAL1 MIDEA_BITS LITERAL1 MITSUBISHI LITERAL1 +MITSUBISHI112 LITERAL1 +MITSUBISHI136 LITERAL1 MITSUBISHI2 LITERAL1 MITSUBISHI_AC LITERAL1 MITSUBISHI_AC_AUTO LITERAL1 @@ -933,6 +965,7 @@ SEND_HAIER_AC_YRW02 LITERAL1 SEND_HITACHI_AC LITERAL1 SEND_HITACHI_AC1 LITERAL1 SEND_HITACHI_AC2 LITERAL1 +SEND_HITACHI_AC424 LITERAL1 SEND_INAX LITERAL1 SEND_JVC LITERAL1 SEND_KELVINATOR LITERAL1 @@ -943,6 +976,8 @@ SEND_LUTRON LITERAL1 SEND_MAGIQUEST LITERAL1 SEND_MIDEA LITERAL1 SEND_MITSUBISHI LITERAL1 +SEND_MITSUBISHI112 LITERAL1 +SEND_MITSUBISHI136 LITERAL1 SEND_MITSUBISHI2 LITERAL1 SEND_MITSUBISHIHEAVY LITERAL1 SEND_MITSUBISHI_AC LITERAL1 @@ -1031,32 +1066,40 @@ kAmcorDefaultRepeat LITERAL1 kAmcorDry LITERAL1 kAmcorFan LITERAL1 kAmcorFanAuto LITERAL1 -kAmcorFanMask LITERAL1 kAmcorFanMax LITERAL1 kAmcorFanMed LITERAL1 kAmcorFanMin LITERAL1 +kAmcorFanOffset LITERAL1 +kAmcorFanSize LITERAL1 kAmcorFooterMark LITERAL1 kAmcorGap LITERAL1 kAmcorHdrMark LITERAL1 kAmcorHdrSpace LITERAL1 kAmcorHeat LITERAL1 -kAmcorMaxMask LITERAL1 +kAmcorMax LITERAL1 +kAmcorMaxOffset LITERAL1 +kAmcorMaxSize LITERAL1 kAmcorMaxTemp LITERAL1 kAmcorMinTemp LITERAL1 kAmcorModeFanByte LITERAL1 -kAmcorModeMask LITERAL1 +kAmcorModeOffset LITERAL1 +kAmcorModeSize LITERAL1 kAmcorOneMark LITERAL1 kAmcorOneSpace LITERAL1 kAmcorPowerByte LITERAL1 -kAmcorPowerMask LITERAL1 kAmcorPowerOff LITERAL1 +kAmcorPowerOffset LITERAL1 kAmcorPowerOn LITERAL1 +kAmcorPowerSize LITERAL1 kAmcorSpecialByte LITERAL1 kAmcorStateLength LITERAL1 kAmcorTempByte LITERAL1 -kAmcorTempMask LITERAL1 +kAmcorTempOffset LITERAL1 +kAmcorTempSize LITERAL1 kAmcorTolerance LITERAL1 -kAmcorVentMask LITERAL1 +kAmcorVentOffset LITERAL1 +kAmcorVentOn LITERAL1 +kAmcorVentSize LITERAL1 kAmcorZeroMark LITERAL1 kAmcorZeroSpace LITERAL1 kArgoAuto LITERAL1 @@ -1069,7 +1112,8 @@ kArgoFan1 LITERAL1 kArgoFan2 LITERAL1 kArgoFan3 LITERAL1 kArgoFanAuto LITERAL1 -kArgoFanMask LITERAL1 +kArgoFanOffset LITERAL1 +kArgoFanSize LITERAL1 kArgoFlap1 LITERAL1 kArgoFlap2 LITERAL1 kArgoFlap3 LITERAL1 @@ -1085,22 +1129,27 @@ kArgoHeat LITERAL1 kArgoHeatAuto LITERAL1 kArgoHeatBit LITERAL1 kArgoHeatBlink LITERAL1 -kArgoIFeelBit LITERAL1 -kArgoMaxBit LITERAL1 +kArgoIFeelBitOffset LITERAL1 +kArgoMaxBitOffset LITERAL1 kArgoMaxRoomTemp LITERAL1 kArgoMaxTemp LITERAL1 kArgoMinTemp LITERAL1 -kArgoModeMask LITERAL1 -kArgoNightBit LITERAL1 +kArgoModeOffset LITERAL1 +kArgoModeSize LITERAL1 +kArgoNightBitOffset LITERAL1 kArgoOff LITERAL1 kArgoOneSpace LITERAL1 -kArgoPowerBit LITERAL1 -kArgoRoomTempHighMask LITERAL1 -kArgoRoomTempLowMask LITERAL1 +kArgoPowerBitOffset LITERAL1 +kArgoRoomTempHighOffset LITERAL1 +kArgoRoomTempHighSize LITERAL1 +kArgoRoomTempLowOffset LITERAL1 +kArgoRoomTempLowSize LITERAL1 kArgoStateLength LITERAL1 -kArgoTempHighMask LITERAL1 -kArgoTempLowMask LITERAL1 -kArgoTempOffset LITERAL1 +kArgoTempDelta LITERAL1 +kArgoTempHighOffset LITERAL1 +kArgoTempHighSize LITERAL1 +kArgoTempLowOffset LITERAL1 +kArgoTempLowSize LITERAL1 kArgoZeroSpace LITERAL1 kAuto LITERAL1 kCarrierAcBitMark LITERAL1 @@ -1117,6 +1166,7 @@ kCoolixBitMark LITERAL1 kCoolixBitMarkTicks LITERAL1 kCoolixBits LITERAL1 kCoolixClean LITERAL1 +kCoolixCmdFan LITERAL1 kCoolixCool LITERAL1 kCoolixDefaultRepeat LITERAL1 kCoolixDefaultState LITERAL1 @@ -1125,10 +1175,11 @@ kCoolixFan LITERAL1 kCoolixFanAuto LITERAL1 kCoolixFanAuto0 LITERAL1 kCoolixFanFixed LITERAL1 -kCoolixFanMask LITERAL1 kCoolixFanMax LITERAL1 kCoolixFanMed LITERAL1 kCoolixFanMin LITERAL1 +kCoolixFanOffset LITERAL1 +kCoolixFanSize LITERAL1 kCoolixFanTempCode LITERAL1 kCoolixFanZoneFollow LITERAL1 kCoolixHdrMark LITERAL1 @@ -1139,37 +1190,47 @@ kCoolixHeat LITERAL1 kCoolixLed LITERAL1 kCoolixMinGap LITERAL1 kCoolixMinGapTicks LITERAL1 -kCoolixModeMask LITERAL1 +kCoolixModeOffset LITERAL1 +kCoolixModeSize LITERAL1 kCoolixOff LITERAL1 kCoolixOneSpace LITERAL1 kCoolixOneSpaceTicks LITERAL1 kCoolixPrefix LITERAL1 kCoolixSensorTempIgnoreCode LITERAL1 -kCoolixSensorTempMask LITERAL1 kCoolixSensorTempMax LITERAL1 kCoolixSensorTempMin LITERAL1 +kCoolixSensorTempOffset LITERAL1 +kCoolixSensorTempSize LITERAL1 kCoolixSleep LITERAL1 kCoolixSwing LITERAL1 +kCoolixSwingH LITERAL1 +kCoolixSwingV LITERAL1 kCoolixTempMap LITERAL1 -kCoolixTempMask LITERAL1 kCoolixTempMax LITERAL1 kCoolixTempMin LITERAL1 +kCoolixTempOffset LITERAL1 kCoolixTempRange LITERAL1 +kCoolixTempSize LITERAL1 kCoolixTick LITERAL1 kCoolixTurbo LITERAL1 kCoolixUnknown LITERAL1 kCoolixZeroSpace LITERAL1 kCoolixZeroSpaceTicks LITERAL1 -kCoolixZoneFollowMask LITERAL1 +kCoolixZoneFollowMaskOffset LITERAL1 kDaikin128Auto LITERAL1 kDaikin128BitCeiling LITERAL1 kDaikin128BitEcono LITERAL1 +kDaikin128BitEconoOffset LITERAL1 kDaikin128BitHalfHour LITERAL1 kDaikin128BitMark LITERAL1 kDaikin128BitPowerToggle LITERAL1 +kDaikin128BitPowerToggleOffset LITERAL1 kDaikin128BitSleep LITERAL1 +kDaikin128BitSleepOffset LITERAL1 kDaikin128BitSwing LITERAL1 +kDaikin128BitSwingOffset LITERAL1 kDaikin128BitTimerEnabled LITERAL1 +kDaikin128BitTimerEnabledOffset LITERAL1 kDaikin128BitWall LITERAL1 kDaikin128Bits LITERAL1 kDaikin128ByteClockHours LITERAL1 @@ -1193,32 +1254,51 @@ kDaikin128FanQuiet LITERAL1 kDaikin128FooterMark LITERAL1 kDaikin128Freq LITERAL1 kDaikin128Gap LITERAL1 +kDaikin128HalfHourOffset LITERAL1 kDaikin128HdrMark LITERAL1 kDaikin128HdrSpace LITERAL1 kDaikin128Heat LITERAL1 +kDaikin128HoursOffset LITERAL1 +kDaikin128HoursSize LITERAL1 kDaikin128LeaderMark LITERAL1 kDaikin128LeaderSpace LITERAL1 kDaikin128MaskFan LITERAL1 -kDaikin128MaskHours LITERAL1 kDaikin128MaskLight LITERAL1 -kDaikin128MaskMode LITERAL1 kDaikin128MaxTemp LITERAL1 kDaikin128MinTemp LITERAL1 +kDaikin128ModeSize LITERAL1 kDaikin128OneSpace LITERAL1 kDaikin128SectionLength LITERAL1 kDaikin128Sections LITERAL1 kDaikin128StateLength LITERAL1 +kDaikin128TimerOffset LITERAL1 +kDaikin128TimerSize LITERAL1 kDaikin128ZeroSpace LITERAL1 kDaikin152BitMark LITERAL1 kDaikin152Bits LITERAL1 +kDaikin152ComfortByte LITERAL1 +kDaikin152ComfortOffset LITERAL1 kDaikin152DefaultRepeat LITERAL1 +kDaikin152DryTemp LITERAL1 +kDaikin152EconoByte LITERAL1 +kDaikin152FanByte LITERAL1 +kDaikin152FanTemp LITERAL1 kDaikin152Freq LITERAL1 kDaikin152Gap LITERAL1 kDaikin152HdrMark LITERAL1 kDaikin152HdrSpace LITERAL1 kDaikin152LeaderBits LITERAL1 +kDaikin152ModeByte LITERAL1 kDaikin152OneSpace LITERAL1 +kDaikin152PowerByte LITERAL1 +kDaikin152PowerfulByte LITERAL1 +kDaikin152QuietByte LITERAL1 +kDaikin152SensorByte LITERAL1 +kDaikin152SensorOffset LITERAL1 kDaikin152StateLength LITERAL1 +kDaikin152SwingVByte LITERAL1 +kDaikin152TempByte LITERAL1 +kDaikin152TempSize LITERAL1 kDaikin152ZeroSpace LITERAL1 kDaikin160BitMark LITERAL1 kDaikin160Bits LITERAL1 @@ -1233,9 +1313,7 @@ kDaikin160Gap LITERAL1 kDaikin160HdrMark LITERAL1 kDaikin160HdrSpace LITERAL1 kDaikin160MaskFan LITERAL1 -kDaikin160MaskMode LITERAL1 kDaikin160MaskSwingV LITERAL1 -kDaikin160MaskTemp LITERAL1 kDaikin160OneSpace LITERAL1 kDaikin160Section1Length LITERAL1 kDaikin160Section2Length LITERAL1 @@ -1247,6 +1325,8 @@ kDaikin160SwingVHighest LITERAL1 kDaikin160SwingVLow LITERAL1 kDaikin160SwingVLowest LITERAL1 kDaikin160SwingVMiddle LITERAL1 +kDaikin160TempOffset LITERAL1 +kDaikin160TempSize LITERAL1 kDaikin160ZeroSpace LITERAL1 kDaikin176BitMark LITERAL1 kDaikin176Bits LITERAL1 @@ -1266,8 +1346,6 @@ kDaikin176HdrMark LITERAL1 kDaikin176HdrSpace LITERAL1 kDaikin176MaskFan LITERAL1 kDaikin176MaskMode LITERAL1 -kDaikin176MaskSwingH LITERAL1 -kDaikin176MaskTemp LITERAL1 kDaikin176ModeButton LITERAL1 kDaikin176OneSpace LITERAL1 kDaikin176Section1Length LITERAL1 @@ -1276,6 +1354,8 @@ kDaikin176Sections LITERAL1 kDaikin176StateLength LITERAL1 kDaikin176SwingHAuto LITERAL1 kDaikin176SwingHOff LITERAL1 +kDaikin176TempOffset LITERAL1 +kDaikin176TempSize LITERAL1 kDaikin176ZeroSpace LITERAL1 kDaikin216BitMark LITERAL1 kDaikin216Bits LITERAL1 @@ -1292,36 +1372,49 @@ kDaikin216Gap LITERAL1 kDaikin216HdrMark LITERAL1 kDaikin216HdrSpace LITERAL1 kDaikin216MaskFan LITERAL1 -kDaikin216MaskMode LITERAL1 -kDaikin216MaskSwingH LITERAL1 -kDaikin216MaskSwingV LITERAL1 -kDaikin216MaskTemp LITERAL1 kDaikin216OneSpace LITERAL1 kDaikin216Section1Length LITERAL1 kDaikin216Section2Length LITERAL1 kDaikin216Sections LITERAL1 kDaikin216StateLength LITERAL1 +kDaikin216SwingOff LITERAL1 +kDaikin216SwingOn LITERAL1 +kDaikin216SwingSize LITERAL1 +kDaikin216TempOffset LITERAL1 +kDaikin216TempSize LITERAL1 kDaikin216ZeroSpace LITERAL1 -kDaikin2BeepMask LITERAL1 +kDaikin2BeepOffset LITERAL1 +kDaikin2BeepSize LITERAL1 kDaikin2BitClean LITERAL1 +kDaikin2BitCleanOffset LITERAL1 kDaikin2BitEye LITERAL1 kDaikin2BitEyeAuto LITERAL1 +kDaikin2BitEyeAutoOffset LITERAL1 +kDaikin2BitEyeOffset LITERAL1 kDaikin2BitFreshAir LITERAL1 kDaikin2BitFreshAirHigh LITERAL1 +kDaikin2BitFreshAirHighOffset LITERAL1 +kDaikin2BitFreshAirOffset LITERAL1 kDaikin2BitMark LITERAL1 kDaikin2BitMold LITERAL1 +kDaikin2BitMoldOffset LITERAL1 kDaikin2BitPower LITERAL1 +kDaikin2BitPowerOffset LITERAL1 kDaikin2BitPurify LITERAL1 +kDaikin2BitPurifyOffset LITERAL1 kDaikin2BitSleepTimer LITERAL1 +kDaikin2BitSleepTimerOffset LITERAL1 kDaikin2Bits LITERAL1 kDaikin2DefaultRepeat LITERAL1 +kDaikin2FanByte LITERAL1 kDaikin2Freq LITERAL1 kDaikin2Gap LITERAL1 kDaikin2HdrMark LITERAL1 kDaikin2HdrSpace LITERAL1 kDaikin2LeaderMark LITERAL1 kDaikin2LeaderSpace LITERAL1 -kDaikin2LightMask LITERAL1 +kDaikin2LightOffset LITERAL1 +kDaikin2LightSize LITERAL1 kDaikin2MinCoolTemp LITERAL1 kDaikin2OneSpace LITERAL1 kDaikin2Section1Length LITERAL1 @@ -1329,12 +1422,19 @@ kDaikin2Section2Length LITERAL1 kDaikin2Sections LITERAL1 kDaikin2StateLength LITERAL1 kDaikin2SwingHAuto LITERAL1 +kDaikin2SwingHLeft LITERAL1 +kDaikin2SwingHLeftMax LITERAL1 +kDaikin2SwingHMiddle LITERAL1 +kDaikin2SwingHRight LITERAL1 +kDaikin2SwingHRightMax LITERAL1 kDaikin2SwingHSwing LITERAL1 +kDaikin2SwingHWide LITERAL1 kDaikin2SwingVAuto LITERAL1 kDaikin2SwingVBreeze LITERAL1 kDaikin2SwingVCirculate LITERAL1 kDaikin2SwingVHigh LITERAL1 kDaikin2SwingVLow LITERAL1 +kDaikin2SwingVSwing LITERAL1 kDaikin2Tolerance LITERAL1 kDaikin2ZeroSpace LITERAL1 kDaikinAuto LITERAL1 @@ -1342,17 +1442,27 @@ kDaikinBeepLoud LITERAL1 kDaikinBeepOff LITERAL1 kDaikinBeepQuiet LITERAL1 kDaikinBitComfort LITERAL1 +kDaikinBitComfortOffset LITERAL1 kDaikinBitEcono LITERAL1 +kDaikinBitEconoOffset LITERAL1 kDaikinBitEye LITERAL1 kDaikinBitMark LITERAL1 kDaikinBitMold LITERAL1 +kDaikinBitMoldOffset LITERAL1 kDaikinBitOffTimer LITERAL1 +kDaikinBitOffTimerOffset LITERAL1 kDaikinBitOnTimer LITERAL1 +kDaikinBitOnTimerOffset LITERAL1 kDaikinBitPower LITERAL1 +kDaikinBitPowerOffset LITERAL1 kDaikinBitPowerful LITERAL1 +kDaikinBitPowerfulOffset LITERAL1 kDaikinBitSensor LITERAL1 +kDaikinBitSensorOffset LITERAL1 kDaikinBitSilent LITERAL1 +kDaikinBitSilentOffset LITERAL1 kDaikinBitWeeklyTimer LITERAL1 +kDaikinBitWeeklyTimerOffset LITERAL1 kDaikinBits LITERAL1 kDaikinBitsShort LITERAL1 kDaikinByteChecksum1 LITERAL1 @@ -1378,17 +1488,23 @@ kDaikinByteSilent LITERAL1 kDaikinByteSwingH LITERAL1 kDaikinByteTemp LITERAL1 kDaikinByteWeeklyTimer LITERAL1 +kDaikinClockMinsHighOffset LITERAL1 +kDaikinClockMinsHighSize LITERAL1 kDaikinCool LITERAL1 kDaikinCurBit LITERAL1 kDaikinCurIndex LITERAL1 kDaikinDefaultRepeat LITERAL1 +kDaikinDoWOffset LITERAL1 +kDaikinDoWSize LITERAL1 kDaikinDry LITERAL1 kDaikinFan LITERAL1 kDaikinFanAuto LITERAL1 kDaikinFanMax LITERAL1 kDaikinFanMed LITERAL1 kDaikinFanMin LITERAL1 +kDaikinFanOffset LITERAL1 kDaikinFanQuiet LITERAL1 +kDaikinFanSize LITERAL1 kDaikinFirstHeader64 LITERAL1 kDaikinGap LITERAL1 kDaikinHdrMark LITERAL1 @@ -1401,6 +1517,10 @@ kDaikinLightOff LITERAL1 kDaikinMarkExcess LITERAL1 kDaikinMaxTemp LITERAL1 kDaikinMinTemp LITERAL1 +kDaikinModeOffset LITERAL1 +kDaikinModeSize LITERAL1 +kDaikinOnTimerMinsHighOffset LITERAL1 +kDaikinOnTimerMinsHighSize LITERAL1 kDaikinOneSpace LITERAL1 kDaikinSection1Length LITERAL1 kDaikinSection2Length LITERAL1 @@ -1408,6 +1528,12 @@ kDaikinSection3Length LITERAL1 kDaikinSections LITERAL1 kDaikinStateLength LITERAL1 kDaikinStateLengthShort LITERAL1 +kDaikinSwingOff LITERAL1 +kDaikinSwingOffset LITERAL1 +kDaikinSwingOn LITERAL1 +kDaikinSwingSize LITERAL1 +kDaikinTempOffset LITERAL1 +kDaikinTempSize LITERAL1 kDaikinTolerance LITERAL1 kDaikinUnusedTime LITERAL1 kDaikinZeroSpace LITERAL1 @@ -1458,8 +1584,9 @@ kElectraAcFan LITERAL1 kElectraAcFanAuto LITERAL1 kElectraAcFanHigh LITERAL1 kElectraAcFanLow LITERAL1 -kElectraAcFanMask LITERAL1 kElectraAcFanMed LITERAL1 +kElectraAcFanOffset LITERAL1 +kElectraAcFanSize LITERAL1 kElectraAcHdrMark LITERAL1 kElectraAcHdrSpace LITERAL1 kElectraAcHeat LITERAL1 @@ -1467,14 +1594,18 @@ kElectraAcMaxTemp LITERAL1 kElectraAcMessageGap LITERAL1 kElectraAcMinRepeat LITERAL1 kElectraAcMinTemp LITERAL1 -kElectraAcModeMask LITERAL1 -kElectraAcOffsetTemp LITERAL1 +kElectraAcModeOffset LITERAL1 kElectraAcOneSpace LITERAL1 -kElectraAcPowerMask LITERAL1 +kElectraAcPowerOffset LITERAL1 kElectraAcStateLength LITERAL1 -kElectraAcSwingHMask LITERAL1 -kElectraAcSwingVMask LITERAL1 -kElectraAcTempMask LITERAL1 +kElectraAcSwingHOffset LITERAL1 +kElectraAcSwingOff LITERAL1 +kElectraAcSwingOn LITERAL1 +kElectraAcSwingSize LITERAL1 +kElectraAcSwingVOffset LITERAL1 +kElectraAcTempDelta LITERAL1 +kElectraAcTempOffset LITERAL1 +kElectraAcTempSize LITERAL1 kElectraAcZeroSpace LITERAL1 kFan LITERAL1 kFnvBasis32 LITERAL1 @@ -1482,6 +1613,7 @@ kFnvPrime32 LITERAL1 kFooter LITERAL1 kFujitsuAcBitMark LITERAL1 kFujitsuAcBits LITERAL1 +kFujitsuAcCleanOffset LITERAL1 kFujitsuAcCmdEcono LITERAL1 kFujitsuAcCmdPowerful LITERAL1 kFujitsuAcCmdStayOn LITERAL1 @@ -1496,6 +1628,8 @@ kFujitsuAcFanHigh LITERAL1 kFujitsuAcFanLow LITERAL1 kFujitsuAcFanMed LITERAL1 kFujitsuAcFanQuiet LITERAL1 +kFujitsuAcFanSize LITERAL1 +kFujitsuAcFilterOffset LITERAL1 kFujitsuAcHdrMark LITERAL1 kFujitsuAcHdrSpace LITERAL1 kFujitsuAcMaxTemp LITERAL1 @@ -1509,11 +1643,13 @@ kFujitsuAcModeDry LITERAL1 kFujitsuAcModeFan LITERAL1 kFujitsuAcModeHeat LITERAL1 kFujitsuAcOneSpace LITERAL1 +kFujitsuAcOutsideQuietOffset LITERAL1 kFujitsuAcStateLength LITERAL1 kFujitsuAcStateLengthShort LITERAL1 kFujitsuAcSwingBoth LITERAL1 kFujitsuAcSwingHoriz LITERAL1 kFujitsuAcSwingOff LITERAL1 +kFujitsuAcSwingSize LITERAL1 kFujitsuAcSwingVert LITERAL1 kFujitsuAcZeroSpace LITERAL1 kGicableBitMark LITERAL1 @@ -1533,7 +1669,9 @@ kGlobalCacheRptIndex LITERAL1 kGlobalCacheRptStartIndex LITERAL1 kGlobalCacheStartIndex LITERAL1 kGoodweatherAuto LITERAL1 +kGoodweatherBitAirFlow LITERAL1 kGoodweatherBitCommand LITERAL1 +kGoodweatherBitEOF LITERAL1 kGoodweatherBitFan LITERAL1 kGoodweatherBitLight LITERAL1 kGoodweatherBitMark LITERAL1 @@ -1556,32 +1694,30 @@ kGoodweatherCmdSwing LITERAL1 kGoodweatherCmdTimer LITERAL1 kGoodweatherCmdTurbo LITERAL1 kGoodweatherCmdUpTemp LITERAL1 -kGoodweatherCommandMask LITERAL1 +kGoodweatherCommandSize LITERAL1 kGoodweatherCool LITERAL1 kGoodweatherDry LITERAL1 +kGoodweatherEOFMask LITERAL1 +kGoodweatherExtraTolerance LITERAL1 kGoodweatherFan LITERAL1 kGoodweatherFanAuto LITERAL1 kGoodweatherFanHigh LITERAL1 kGoodweatherFanLow LITERAL1 -kGoodweatherFanMask LITERAL1 kGoodweatherFanMed LITERAL1 +kGoodweatherFanSize LITERAL1 kGoodweatherHdrMark LITERAL1 kGoodweatherHdrSpace LITERAL1 kGoodweatherHeat LITERAL1 -kGoodweatherLightMask LITERAL1 kGoodweatherMinRepeat LITERAL1 -kGoodweatherModeMask LITERAL1 kGoodweatherOneSpace LITERAL1 -kGoodweatherPowerMask LITERAL1 -kGoodweatherSleepMask LITERAL1 +kGoodweatherStateInit LITERAL1 kGoodweatherSwingFast LITERAL1 -kGoodweatherSwingMask LITERAL1 kGoodweatherSwingOff LITERAL1 +kGoodweatherSwingSize LITERAL1 kGoodweatherSwingSlow LITERAL1 -kGoodweatherTempMask LITERAL1 kGoodweatherTempMax LITERAL1 kGoodweatherTempMin LITERAL1 -kGoodweatherTurboMask LITERAL1 +kGoodweatherTempSize LITERAL1 kGoodweatherZeroSpace LITERAL1 kGpioUnused LITERAL1 kGreeAuto LITERAL1 @@ -1594,26 +1730,26 @@ kGreeDefaultRepeat LITERAL1 kGreeDry LITERAL1 kGreeFan LITERAL1 kGreeFanAuto LITERAL1 -kGreeFanMask LITERAL1 kGreeFanMax LITERAL1 kGreeFanMed LITERAL1 kGreeFanMin LITERAL1 +kGreeFanOffset LITERAL1 +kGreeFanSize LITERAL1 kGreeHdrMark LITERAL1 kGreeHdrSpace LITERAL1 kGreeHeat LITERAL1 -kGreeIFeelMask LITERAL1 -kGreeLightMask LITERAL1 +kGreeIFeelOffset LITERAL1 +kGreeLightOffset LITERAL1 kGreeMaxTemp LITERAL1 kGreeMinTemp LITERAL1 -kGreeModeMask LITERAL1 kGreeMsgSpace LITERAL1 kGreeOneSpace LITERAL1 -kGreePower1Mask LITERAL1 -kGreePower2Mask LITERAL1 -kGreeSleepMask LITERAL1 +kGreePower1Offset LITERAL1 +kGreePower2Offset LITERAL1 +kGreeSleepOffset LITERAL1 kGreeStateLength LITERAL1 kGreeSwingAuto LITERAL1 -kGreeSwingAutoMask LITERAL1 +kGreeSwingAutoOffset LITERAL1 kGreeSwingDown LITERAL1 kGreeSwingDownAuto LITERAL1 kGreeSwingLastPos LITERAL1 @@ -1621,19 +1757,20 @@ kGreeSwingMiddle LITERAL1 kGreeSwingMiddleAuto LITERAL1 kGreeSwingMiddleDown LITERAL1 kGreeSwingMiddleUp LITERAL1 -kGreeSwingPosMask LITERAL1 +kGreeSwingSize LITERAL1 kGreeSwingUp LITERAL1 kGreeSwingUpAuto LITERAL1 -kGreeTempMask LITERAL1 -kGreeTimer1Mask LITERAL1 -kGreeTimerEnabledBit LITERAL1 -kGreeTimerHalfHrBit LITERAL1 -kGreeTimerHoursMask LITERAL1 +kGreeTempSize LITERAL1 +kGreeTimerEnabledOffset LITERAL1 +kGreeTimerHalfHrOffset LITERAL1 +kGreeTimerHoursOffset LITERAL1 +kGreeTimerHoursSize LITERAL1 kGreeTimerMax LITERAL1 -kGreeTimerTensHrMask LITERAL1 -kGreeTurboMask LITERAL1 -kGreeWiFiMask LITERAL1 -kGreeXfanMask LITERAL1 +kGreeTimerTensHrOffset LITERAL1 +kGreeTimerTensHrSize LITERAL1 +kGreeTurboOffset LITERAL1 +kGreeWiFiOffset LITERAL1 +kGreeXfanOffset LITERAL1 kGreeZeroSpace LITERAL1 kHaierACBits LITERAL1 kHaierACStateLength LITERAL1 @@ -1663,19 +1800,28 @@ kHaierAcFanLow LITERAL1 kHaierAcFanMed LITERAL1 kHaierAcHdr LITERAL1 kHaierAcHdrGap LITERAL1 +kHaierAcHealthBitOffset LITERAL1 kHaierAcHeat LITERAL1 +kHaierAcHoursSize LITERAL1 kHaierAcMaxTemp LITERAL1 kHaierAcMaxTime LITERAL1 kHaierAcMinGap LITERAL1 kHaierAcMinTemp LITERAL1 -kHaierAcModeMask LITERAL1 +kHaierAcMinsSize LITERAL1 +kHaierAcModeOffset LITERAL1 +kHaierAcOffTimerOffset LITERAL1 +kHaierAcOnTimerOffset LITERAL1 kHaierAcOneSpace LITERAL1 kHaierAcPrefix LITERAL1 kHaierAcSleepBit LITERAL1 +kHaierAcSleepBitOffset LITERAL1 kHaierAcSwingChg LITERAL1 kHaierAcSwingDown LITERAL1 kHaierAcSwingOff LITERAL1 +kHaierAcSwingOffset LITERAL1 +kHaierAcSwingSize LITERAL1 kHaierAcSwingUp LITERAL1 +kHaierAcTimeOffset LITERAL1 kHaierAcYrw02Auto LITERAL1 kHaierAcYrw02ButtonFan LITERAL1 kHaierAcYrw02ButtonHealth LITERAL1 @@ -1694,10 +1840,16 @@ kHaierAcYrw02FanAuto LITERAL1 kHaierAcYrw02FanHigh LITERAL1 kHaierAcYrw02FanLow LITERAL1 kHaierAcYrw02FanMed LITERAL1 +kHaierAcYrw02FanOffset LITERAL1 +kHaierAcYrw02FanSize LITERAL1 +kHaierAcYrw02HealthOffset LITERAL1 kHaierAcYrw02Heat LITERAL1 +kHaierAcYrw02ModeOffset LITERAL1 kHaierAcYrw02Power LITERAL1 +kHaierAcYrw02PowerOffset LITERAL1 kHaierAcYrw02Prefix LITERAL1 kHaierAcYrw02Sleep LITERAL1 +kHaierAcYrw02SleepOffset LITERAL1 kHaierAcYrw02SwingAuto LITERAL1 kHaierAcYrw02SwingBottom LITERAL1 kHaierAcYrw02SwingDown LITERAL1 @@ -1707,10 +1859,13 @@ kHaierAcYrw02SwingTop LITERAL1 kHaierAcYrw02TurboHigh LITERAL1 kHaierAcYrw02TurboLow LITERAL1 kHaierAcYrw02TurboOff LITERAL1 +kHaierAcYrw02TurboOffset LITERAL1 +kHaierAcYrw02TurboSize LITERAL1 kHaierAcZeroSpace LITERAL1 kHeader LITERAL1 kHeat LITERAL1 kHigh LITERAL1 +kHighNibble LITERAL1 kHighest LITERAL1 kHitachiAc1Bits LITERAL1 kHitachiAc1HdrMark LITERAL1 @@ -1718,6 +1873,36 @@ kHitachiAc1HdrSpace LITERAL1 kHitachiAc1StateLength LITERAL1 kHitachiAc2Bits LITERAL1 kHitachiAc2StateLength LITERAL1 +kHitachiAc424BitMark LITERAL1 +kHitachiAc424Bits LITERAL1 +kHitachiAc424Cool LITERAL1 +kHitachiAc424Dry LITERAL1 +kHitachiAc424Fan LITERAL1 +kHitachiAc424FanAuto LITERAL1 +kHitachiAc424FanByte LITERAL1 +kHitachiAc424FanHigh LITERAL1 +kHitachiAc424FanLow LITERAL1 +kHitachiAc424FanMax LITERAL1 +kHitachiAc424FanMaxDry LITERAL1 +kHitachiAc424FanMedium LITERAL1 +kHitachiAc424FanMin LITERAL1 +kHitachiAc424FanTemp LITERAL1 +kHitachiAc424HdrMark LITERAL1 +kHitachiAc424HdrSpace LITERAL1 +kHitachiAc424Heat LITERAL1 +kHitachiAc424LdrMark LITERAL1 +kHitachiAc424LdrSpace LITERAL1 +kHitachiAc424MaxTemp LITERAL1 +kHitachiAc424MinTemp LITERAL1 +kHitachiAc424ModeByte LITERAL1 +kHitachiAc424OneSpace LITERAL1 +kHitachiAc424PowerByte LITERAL1 +kHitachiAc424PowerOffset LITERAL1 +kHitachiAc424StateLength LITERAL1 +kHitachiAc424TempByte LITERAL1 +kHitachiAc424TempOffset LITERAL1 +kHitachiAc424TempSize LITERAL1 +kHitachiAc424ZeroSpace LITERAL1 kHitachiAcAuto LITERAL1 kHitachiAcAutoTemp LITERAL1 kHitachiAcBitMark LITERAL1 @@ -1730,6 +1915,7 @@ kHitachiAcFanAuto LITERAL1 kHitachiAcFanHigh LITERAL1 kHitachiAcFanLow LITERAL1 kHitachiAcFanMed LITERAL1 +kHitachiAcFreq LITERAL1 kHitachiAcHdrMark LITERAL1 kHitachiAcHdrSpace LITERAL1 kHitachiAcHeat LITERAL1 @@ -1737,7 +1923,9 @@ kHitachiAcMaxTemp LITERAL1 kHitachiAcMinGap LITERAL1 kHitachiAcMinTemp LITERAL1 kHitachiAcOneSpace LITERAL1 +kHitachiAcPowerOffset LITERAL1 kHitachiAcStateLength LITERAL1 +kHitachiAcSwingOffset LITERAL1 kHitachiAcZeroSpace LITERAL1 kIdleState LITERAL1 kInaxBitMark LITERAL1 @@ -1767,8 +1955,8 @@ kJvcZeroSpace LITERAL1 kJvcZeroSpaceTicks LITERAL1 kKelvinatorAuto LITERAL1 kKelvinatorAutoTemp LITERAL1 -kKelvinatorBasicFanMask LITERAL1 kKelvinatorBasicFanMax LITERAL1 +kKelvinatorBasicFanSize LITERAL1 kKelvinatorBitMark LITERAL1 kKelvinatorBitMarkTicks LITERAL1 kKelvinatorBits LITERAL1 @@ -1780,10 +1968,10 @@ kKelvinatorDefaultRepeat LITERAL1 kKelvinatorDry LITERAL1 kKelvinatorFan LITERAL1 kKelvinatorFanAuto LITERAL1 -kKelvinatorFanMask LITERAL1 kKelvinatorFanMax LITERAL1 kKelvinatorFanMin LITERAL1 kKelvinatorFanOffset LITERAL1 +kKelvinatorFanSize LITERAL1 kKelvinatorGapSpace LITERAL1 kKelvinatorGapSpaceTicks LITERAL1 kKelvinatorHdrMark LITERAL1 @@ -1791,28 +1979,21 @@ kKelvinatorHdrMarkTicks LITERAL1 kKelvinatorHdrSpace LITERAL1 kKelvinatorHdrSpaceTicks LITERAL1 kKelvinatorHeat LITERAL1 -kKelvinatorIonFilter LITERAL1 kKelvinatorIonFilterOffset LITERAL1 -kKelvinatorLight LITERAL1 kKelvinatorLightOffset LITERAL1 kKelvinatorMaxTemp LITERAL1 kKelvinatorMinTemp LITERAL1 -kKelvinatorModeMask LITERAL1 +kKelvinatorModeOffset LITERAL1 kKelvinatorOneSpace LITERAL1 kKelvinatorOneSpaceTicks LITERAL1 -kKelvinatorPower LITERAL1 -kKelvinatorQuiet LITERAL1 +kKelvinatorPowerOffset LITERAL1 kKelvinatorQuietOffset LITERAL1 -kKelvinatorSleep1And3 LITERAL1 kKelvinatorStateLength LITERAL1 kKelvinatorTick LITERAL1 -kKelvinatorTurbo LITERAL1 kKelvinatorTurboOffset LITERAL1 -kKelvinatorVentSwing LITERAL1 -kKelvinatorVentSwingH LITERAL1 +kKelvinatorVentSwingHOffset LITERAL1 kKelvinatorVentSwingOffset LITERAL1 -kKelvinatorVentSwingV LITERAL1 -kKelvinatorXfan LITERAL1 +kKelvinatorVentSwingVOffset LITERAL1 kKelvinatorXfanOffset LITERAL1 kKelvinatorZeroSpace LITERAL1 kKelvinatorZeroSpaceTicks LITERAL1 @@ -1870,6 +2051,7 @@ kLgTick LITERAL1 kLgZeroSpace LITERAL1 kLgZeroSpaceTicks LITERAL1 kLow LITERAL1 +kLowNibble LITERAL1 kLowest LITERAL1 kLutronBits LITERAL1 kLutronDelta LITERAL1 @@ -1900,26 +2082,26 @@ kMaxTimeoutMs LITERAL1 kMedium LITERAL1 kMiddle LITERAL1 kMideaACAuto LITERAL1 -kMideaACCelsiusBit LITERAL1 -kMideaACChecksumMask LITERAL1 +kMideaACCelsiusOffset LITERAL1 kMideaACCool LITERAL1 kMideaACDry LITERAL1 kMideaACFan LITERAL1 kMideaACFanAuto LITERAL1 kMideaACFanHigh LITERAL1 kMideaACFanLow LITERAL1 -kMideaACFanMask LITERAL1 kMideaACFanMed LITERAL1 +kMideaACFanOffset LITERAL1 +kMideaACFanSize LITERAL1 kMideaACHeat LITERAL1 kMideaACMaxTempC LITERAL1 kMideaACMaxTempF LITERAL1 kMideaACMinTempC LITERAL1 kMideaACMinTempF LITERAL1 -kMideaACModeMask LITERAL1 -kMideaACPower LITERAL1 -kMideaACSleep LITERAL1 -kMideaACStateMask LITERAL1 -kMideaACTempMask LITERAL1 +kMideaACModeOffset LITERAL1 +kMideaACPowerOffset LITERAL1 +kMideaACSleepOffset LITERAL1 +kMideaACTempOffset LITERAL1 +kMideaACTempSize LITERAL1 kMideaACToggleSwingV LITERAL1 kMideaBitMark LITERAL1 kMideaBitMarkTicks LITERAL1 @@ -1938,6 +2120,91 @@ kMideaTolerance LITERAL1 kMideaZeroSpace LITERAL1 kMideaZeroSpaceTicks LITERAL1 kMin LITERAL1 +kMitsubishi112Auto LITERAL1 +kMitsubishi112BitMark LITERAL1 +kMitsubishi112Bits LITERAL1 +kMitsubishi112Cool LITERAL1 +kMitsubishi112Dry LITERAL1 +kMitsubishi112FanByte LITERAL1 +kMitsubishi112FanLow LITERAL1 +kMitsubishi112FanMax LITERAL1 +kMitsubishi112FanMed LITERAL1 +kMitsubishi112FanMin LITERAL1 +kMitsubishi112FanOffset LITERAL1 +kMitsubishi112FanQuiet LITERAL1 +kMitsubishi112FanSize LITERAL1 +kMitsubishi112Gap LITERAL1 +kMitsubishi112HdrMark LITERAL1 +kMitsubishi112HdrMarkTolerance LITERAL1 +kMitsubishi112HdrSpace LITERAL1 +kMitsubishi112Heat LITERAL1 +kMitsubishi112MaxTemp LITERAL1 +kMitsubishi112MinRepeat LITERAL1 +kMitsubishi112MinTemp LITERAL1 +kMitsubishi112ModeByte LITERAL1 +kMitsubishi112ModeOffset LITERAL1 +kMitsubishi112OneSpace LITERAL1 +kMitsubishi112PowerByte LITERAL1 +kMitsubishi112PowerOffset LITERAL1 +kMitsubishi112StateLength LITERAL1 +kMitsubishi112SwingHAuto LITERAL1 +kMitsubishi112SwingHByte LITERAL1 +kMitsubishi112SwingHLeft LITERAL1 +kMitsubishi112SwingHLeftMax LITERAL1 +kMitsubishi112SwingHMiddle LITERAL1 +kMitsubishi112SwingHOffset LITERAL1 +kMitsubishi112SwingHRight LITERAL1 +kMitsubishi112SwingHRightMax LITERAL1 +kMitsubishi112SwingHSize LITERAL1 +kMitsubishi112SwingHWide LITERAL1 +kMitsubishi112SwingVAuto LITERAL1 +kMitsubishi112SwingVByte LITERAL1 +kMitsubishi112SwingVHigh LITERAL1 +kMitsubishi112SwingVHighest LITERAL1 +kMitsubishi112SwingVLow LITERAL1 +kMitsubishi112SwingVLowest LITERAL1 +kMitsubishi112SwingVMiddle LITERAL1 +kMitsubishi112SwingVOffset LITERAL1 +kMitsubishi112SwingVSize LITERAL1 +kMitsubishi112TempByte LITERAL1 +kMitsubishi112TempSize LITERAL1 +kMitsubishi112ZeroSpace LITERAL1 +kMitsubishi136Auto LITERAL1 +kMitsubishi136BitMark LITERAL1 +kMitsubishi136Bits LITERAL1 +kMitsubishi136Cool LITERAL1 +kMitsubishi136Dry LITERAL1 +kMitsubishi136Fan LITERAL1 +kMitsubishi136FanByte LITERAL1 +kMitsubishi136FanLow LITERAL1 +kMitsubishi136FanMax LITERAL1 +kMitsubishi136FanMed LITERAL1 +kMitsubishi136FanMin LITERAL1 +kMitsubishi136FanOffset LITERAL1 +kMitsubishi136FanQuiet LITERAL1 +kMitsubishi136FanSize LITERAL1 +kMitsubishi136Gap LITERAL1 +kMitsubishi136HdrMark LITERAL1 +kMitsubishi136HdrSpace LITERAL1 +kMitsubishi136Heat LITERAL1 +kMitsubishi136MaxTemp LITERAL1 +kMitsubishi136MinRepeat LITERAL1 +kMitsubishi136MinTemp LITERAL1 +kMitsubishi136ModeByte LITERAL1 +kMitsubishi136ModeOffset LITERAL1 +kMitsubishi136OneSpace LITERAL1 +kMitsubishi136PowerBit LITERAL1 +kMitsubishi136PowerByte LITERAL1 +kMitsubishi136PowerOffset LITERAL1 +kMitsubishi136StateLength LITERAL1 +kMitsubishi136SwingVAuto LITERAL1 +kMitsubishi136SwingVByte LITERAL1 +kMitsubishi136SwingVHigh LITERAL1 +kMitsubishi136SwingVHighest LITERAL1 +kMitsubishi136SwingVLow LITERAL1 +kMitsubishi136SwingVLowest LITERAL1 +kMitsubishi136TempByte LITERAL1 +kMitsubishi136ZeroSpace LITERAL1 kMitsubishi2BitMark LITERAL1 kMitsubishi2HdrMark LITERAL1 kMitsubishi2HdrSpace LITERAL1 @@ -1951,19 +2218,25 @@ kMitsubishiAcAuto LITERAL1 kMitsubishiAcBitMark LITERAL1 kMitsubishiAcCool LITERAL1 kMitsubishiAcDry LITERAL1 +kMitsubishiAcExtraTolerance LITERAL1 kMitsubishiAcFanAuto LITERAL1 +kMitsubishiAcFanAutoOffset LITERAL1 kMitsubishiAcFanMax LITERAL1 +kMitsubishiAcFanOffset LITERAL1 kMitsubishiAcFanQuiet LITERAL1 kMitsubishiAcFanRealMax LITERAL1 kMitsubishiAcFanSilent LITERAL1 +kMitsubishiAcFanSize LITERAL1 kMitsubishiAcHdrMark LITERAL1 kMitsubishiAcHdrSpace LITERAL1 kMitsubishiAcHeat LITERAL1 kMitsubishiAcMaxTemp LITERAL1 kMitsubishiAcMinTemp LITERAL1 +kMitsubishiAcModeOffset LITERAL1 kMitsubishiAcNoTimer LITERAL1 kMitsubishiAcOneSpace LITERAL1 kMitsubishiAcPower LITERAL1 +kMitsubishiAcPowerOffset LITERAL1 kMitsubishiAcRptMark LITERAL1 kMitsubishiAcRptSpace LITERAL1 kMitsubishiAcStartStopTimer LITERAL1 @@ -1971,6 +2244,9 @@ kMitsubishiAcStartTimer LITERAL1 kMitsubishiAcStopTimer LITERAL1 kMitsubishiAcVaneAuto LITERAL1 kMitsubishiAcVaneAutoMove LITERAL1 +kMitsubishiAcVaneBitOffset LITERAL1 +kMitsubishiAcVaneOffset LITERAL1 +kMitsubishiAcVaneSize LITERAL1 kMitsubishiAcWideVaneAuto LITERAL1 kMitsubishiAcZeroSpace LITERAL1 kMitsubishiBitMark LITERAL1 @@ -1990,7 +2266,6 @@ kMitsubishiHeavy152SwingHAuto LITERAL1 kMitsubishiHeavy152SwingHLeft LITERAL1 kMitsubishiHeavy152SwingHLeftMax LITERAL1 kMitsubishiHeavy152SwingHLeftRight LITERAL1 -kMitsubishiHeavy152SwingHMask LITERAL1 kMitsubishiHeavy152SwingHMiddle LITERAL1 kMitsubishiHeavy152SwingHOff LITERAL1 kMitsubishiHeavy152SwingHRight LITERAL1 @@ -2001,18 +2276,20 @@ kMitsubishiHeavy152SwingVHigh LITERAL1 kMitsubishiHeavy152SwingVHighest LITERAL1 kMitsubishiHeavy152SwingVLow LITERAL1 kMitsubishiHeavy152SwingVLowest LITERAL1 -kMitsubishiHeavy152SwingVMask LITERAL1 kMitsubishiHeavy152SwingVMiddle LITERAL1 kMitsubishiHeavy152SwingVOff LITERAL1 +kMitsubishiHeavy152SwingVOffset LITERAL1 +kMitsubishiHeavy152SwingVSize LITERAL1 kMitsubishiHeavy3DMask LITERAL1 kMitsubishiHeavy88Bits LITERAL1 -kMitsubishiHeavy88CleanBit LITERAL1 +kMitsubishiHeavy88CleanOffset LITERAL1 kMitsubishiHeavy88FanAuto LITERAL1 kMitsubishiHeavy88FanEcono LITERAL1 kMitsubishiHeavy88FanHigh LITERAL1 kMitsubishiHeavy88FanLow LITERAL1 -kMitsubishiHeavy88FanMask LITERAL1 kMitsubishiHeavy88FanMed LITERAL1 +kMitsubishiHeavy88FanOffset LITERAL1 +kMitsubishiHeavy88FanSize LITERAL1 kMitsubishiHeavy88FanTurbo LITERAL1 kMitsubishiHeavy88MinRepeat LITERAL1 kMitsubishiHeavy88StateLength LITERAL1 @@ -2021,43 +2298,44 @@ kMitsubishiHeavy88SwingHAuto LITERAL1 kMitsubishiHeavy88SwingHLeft LITERAL1 kMitsubishiHeavy88SwingHLeftMax LITERAL1 kMitsubishiHeavy88SwingHLeftRight LITERAL1 -kMitsubishiHeavy88SwingHMask LITERAL1 kMitsubishiHeavy88SwingHMiddle LITERAL1 kMitsubishiHeavy88SwingHOff LITERAL1 +kMitsubishiHeavy88SwingHOffset1 LITERAL1 +kMitsubishiHeavy88SwingHOffset2 LITERAL1 kMitsubishiHeavy88SwingHRight LITERAL1 kMitsubishiHeavy88SwingHRightLeft LITERAL1 kMitsubishiHeavy88SwingHRightMax LITERAL1 +kMitsubishiHeavy88SwingHSize LITERAL1 kMitsubishiHeavy88SwingVAuto LITERAL1 +kMitsubishiHeavy88SwingVByte5Offset LITERAL1 +kMitsubishiHeavy88SwingVByte5Size LITERAL1 +kMitsubishiHeavy88SwingVByte7Offset LITERAL1 +kMitsubishiHeavy88SwingVByte7Size LITERAL1 kMitsubishiHeavy88SwingVHigh LITERAL1 kMitsubishiHeavy88SwingVHighest LITERAL1 kMitsubishiHeavy88SwingVLow LITERAL1 kMitsubishiHeavy88SwingVLowest LITERAL1 -kMitsubishiHeavy88SwingVMask LITERAL1 -kMitsubishiHeavy88SwingVMaskByte5 LITERAL1 -kMitsubishiHeavy88SwingVMaskByte7 LITERAL1 kMitsubishiHeavy88SwingVMiddle LITERAL1 kMitsubishiHeavy88SwingVOff LITERAL1 kMitsubishiHeavyAuto LITERAL1 kMitsubishiHeavyBitMark LITERAL1 -kMitsubishiHeavyCleanBit LITERAL1 +kMitsubishiHeavyCleanOffset LITERAL1 kMitsubishiHeavyCool LITERAL1 kMitsubishiHeavyDry LITERAL1 kMitsubishiHeavyFan LITERAL1 -kMitsubishiHeavyFanMask LITERAL1 -kMitsubishiHeavyFilterBit LITERAL1 +kMitsubishiHeavyFilterOffset LITERAL1 kMitsubishiHeavyGap LITERAL1 kMitsubishiHeavyHdrMark LITERAL1 kMitsubishiHeavyHdrSpace LITERAL1 kMitsubishiHeavyHeat LITERAL1 kMitsubishiHeavyMaxTemp LITERAL1 kMitsubishiHeavyMinTemp LITERAL1 -kMitsubishiHeavyModeMask LITERAL1 -kMitsubishiHeavyNightBit LITERAL1 +kMitsubishiHeavyModeOffset LITERAL1 +kMitsubishiHeavyNightOffset LITERAL1 kMitsubishiHeavyOneSpace LITERAL1 -kMitsubishiHeavyPowerBit LITERAL1 +kMitsubishiHeavyPowerOffset LITERAL1 kMitsubishiHeavySigLength LITERAL1 -kMitsubishiHeavySilentBit LITERAL1 -kMitsubishiHeavyTempMask LITERAL1 +kMitsubishiHeavySilentOffset LITERAL1 kMitsubishiHeavyZeroSpace LITERAL1 kMitsubishiHeavyZjsSig LITERAL1 kMitsubishiHeavyZmsSig LITERAL1 @@ -2071,6 +2349,7 @@ kMitsubishiOneSpaceTicks LITERAL1 kMitsubishiTick LITERAL1 kMitsubishiZeroSpace LITERAL1 kMitsubishiZeroSpaceTicks LITERAL1 +kModeBitsSize LITERAL1 kNECBits LITERAL1 kNecBitMark LITERAL1 kNecBitMarkTicks LITERAL1 @@ -2090,7 +2369,7 @@ kNecRptSpaceTicks LITERAL1 kNecTick LITERAL1 kNecZeroSpace LITERAL1 kNecZeroSpaceTicks LITERAL1 -kNeoclima8CHeatMask LITERAL1 +kNeoclima8CHeatOffset LITERAL1 kNeoclimaAuto LITERAL1 kNeoclimaBitMark LITERAL1 kNeoclimaBits LITERAL1 @@ -2103,9 +2382,10 @@ kNeoclimaButtonFresh LITERAL1 kNeoclimaButtonHold LITERAL1 kNeoclimaButtonIon LITERAL1 kNeoclimaButtonLight LITERAL1 -kNeoclimaButtonMask LITERAL1 kNeoclimaButtonMode LITERAL1 +kNeoclimaButtonOffset LITERAL1 kNeoclimaButtonPower LITERAL1 +kNeoclimaButtonSize LITERAL1 kNeoclimaButtonSleep LITERAL1 kNeoclimaButtonSwing LITERAL1 kNeoclimaButtonTempDown LITERAL1 @@ -2113,37 +2393,41 @@ kNeoclimaButtonTempUp LITERAL1 kNeoclimaButtonTurbo LITERAL1 kNeoclimaCool LITERAL1 kNeoclimaDry LITERAL1 -kNeoclimaEyeMask LITERAL1 +kNeoclimaEyeOffset LITERAL1 kNeoclimaFan LITERAL1 kNeoclimaFanAuto LITERAL1 kNeoclimaFanHigh LITERAL1 kNeoclimaFanLow LITERAL1 -kNeoclimaFanMask LITERAL1 kNeoclimaFanMed LITERAL1 +kNeoclimaFanOffest LITERAL1 +kNeoclimaFanSize LITERAL1 kNeoclimaFollowMe LITERAL1 -kNeoclimaFreshMask LITERAL1 +kNeoclimaFreshOffset LITERAL1 kNeoclimaHdrMark LITERAL1 kNeoclimaHdrSpace LITERAL1 kNeoclimaHeat LITERAL1 -kNeoclimaHoldMask LITERAL1 -kNeoclimaIonMask LITERAL1 -kNeoclimaLightMask LITERAL1 +kNeoclimaHoldOffset LITERAL1 +kNeoclimaIonOffset LITERAL1 +kNeoclimaLightOffset LITERAL1 kNeoclimaMaxTemp LITERAL1 kNeoclimaMinGap LITERAL1 kNeoclimaMinRepeat LITERAL1 kNeoclimaMinTemp LITERAL1 -kNeoclimaModeMask LITERAL1 +kNeoclimaModeOffset LITERAL1 kNeoclimaOneSpace LITERAL1 -kNeoclimaPowerMask LITERAL1 -kNeoclimaSleepMask LITERAL1 +kNeoclimaPowerOffset LITERAL1 +kNeoclimaSleepOffset LITERAL1 kNeoclimaStateLength LITERAL1 -kNeoclimaSwingHMask LITERAL1 -kNeoclimaSwingVMask LITERAL1 +kNeoclimaSwingHOffset LITERAL1 kNeoclimaSwingVOff LITERAL1 +kNeoclimaSwingVOffset LITERAL1 kNeoclimaSwingVOn LITERAL1 -kNeoclimaTempMask LITERAL1 -kNeoclimaTurboMask LITERAL1 +kNeoclimaSwingVSize LITERAL1 +kNeoclimaTempOffset LITERAL1 +kNeoclimaTempSize LITERAL1 +kNeoclimaTurboOffset LITERAL1 kNeoclimaZeroSpace LITERAL1 +kNibbleSize LITERAL1 kNikaiBitMark LITERAL1 kNikaiBitMarkTicks LITERAL1 kNikaiBits LITERAL1 @@ -2169,22 +2453,22 @@ kPanasonicAcDry LITERAL1 kPanasonicAcExcess LITERAL1 kPanasonicAcFan LITERAL1 kPanasonicAcFanAuto LITERAL1 +kPanasonicAcFanDelta LITERAL1 kPanasonicAcFanMax LITERAL1 kPanasonicAcFanMed LITERAL1 kPanasonicAcFanMin LITERAL1 kPanasonicAcFanModeTemp LITERAL1 -kPanasonicAcFanOffset LITERAL1 kPanasonicAcHeat LITERAL1 kPanasonicAcMaxTemp LITERAL1 kPanasonicAcMessageGap LITERAL1 kPanasonicAcMinTemp LITERAL1 -kPanasonicAcOffTimer LITERAL1 -kPanasonicAcOnTimer LITERAL1 -kPanasonicAcPower LITERAL1 -kPanasonicAcPowerful LITERAL1 -kPanasonicAcPowerfulCkp LITERAL1 -kPanasonicAcQuiet LITERAL1 -kPanasonicAcQuietCkp LITERAL1 +kPanasonicAcOffTimerOffset LITERAL1 +kPanasonicAcOnTimerOffset LITERAL1 +kPanasonicAcPowerOffset LITERAL1 +kPanasonicAcPowerfulCkpOffset LITERAL1 +kPanasonicAcPowerfulOffset LITERAL1 +kPanasonicAcQuietCkpOffset LITERAL1 +kPanasonicAcQuietOffset LITERAL1 kPanasonicAcSection1Length LITERAL1 kPanasonicAcSectionGap LITERAL1 kPanasonicAcShortBits LITERAL1 @@ -2197,9 +2481,16 @@ kPanasonicAcSwingHLeft LITERAL1 kPanasonicAcSwingHMiddle LITERAL1 kPanasonicAcSwingHRight LITERAL1 kPanasonicAcSwingVAuto LITERAL1 -kPanasonicAcSwingVDown LITERAL1 -kPanasonicAcSwingVUp LITERAL1 +kPanasonicAcSwingVHigh LITERAL1 +kPanasonicAcSwingVHighest LITERAL1 +kPanasonicAcSwingVLow LITERAL1 +kPanasonicAcSwingVLowest LITERAL1 +kPanasonicAcSwingVMiddle LITERAL1 +kPanasonicAcTempOffset LITERAL1 +kPanasonicAcTempSize LITERAL1 kPanasonicAcTimeMax LITERAL1 +kPanasonicAcTimeOverflowSize LITERAL1 +kPanasonicAcTimeSize LITERAL1 kPanasonicAcTimeSpecial LITERAL1 kPanasonicAcTolerance LITERAL1 kPanasonicBitMark LITERAL1 @@ -2303,11 +2594,11 @@ kSamsung36Bits LITERAL1 kSamsungACSectionLength LITERAL1 kSamsungAcAuto LITERAL1 kSamsungAcAutoTemp LITERAL1 -kSamsungAcBeepMask LITERAL1 +kSamsungAcBeepOffset LITERAL1 kSamsungAcBitMark LITERAL1 kSamsungAcBits LITERAL1 -kSamsungAcCleanMask10 LITERAL1 -kSamsungAcCleanMask11 LITERAL1 +kSamsungAcClean10Offset LITERAL1 +kSamsungAcClean11Offset LITERAL1 kSamsungAcCool LITERAL1 kSamsungAcDefaultRepeat LITERAL1 kSamsungAcDry LITERAL1 @@ -2318,32 +2609,35 @@ kSamsungAcFanAuto LITERAL1 kSamsungAcFanAuto2 LITERAL1 kSamsungAcFanHigh LITERAL1 kSamsungAcFanLow LITERAL1 -kSamsungAcFanMask LITERAL1 kSamsungAcFanMed LITERAL1 +kSamsungAcFanOffest LITERAL1 +kSamsungAcFanSize LITERAL1 kSamsungAcFanTurbo LITERAL1 kSamsungAcHdrMark LITERAL1 kSamsungAcHdrSpace LITERAL1 kSamsungAcHeat LITERAL1 kSamsungAcMaxTemp LITERAL1 kSamsungAcMinTemp LITERAL1 -kSamsungAcModeMask LITERAL1 +kSamsungAcModeOffset LITERAL1 kSamsungAcOneSpace LITERAL1 -kSamsungAcPowerMask1 LITERAL1 -kSamsungAcPowerMask6 LITERAL1 +kSamsungAcPower1Offset LITERAL1 +kSamsungAcPower6Offset LITERAL1 +kSamsungAcPower6Size LITERAL1 kSamsungAcPowerSection LITERAL1 -kSamsungAcPowerfulMask10 LITERAL1 +kSamsungAcPowerful10Offset LITERAL1 +kSamsungAcPowerful10Size LITERAL1 kSamsungAcPowerfulMask8 LITERAL1 -kSamsungAcQuietMask1 LITERAL1 -kSamsungAcQuietMask5 LITERAL1 +kSamsungAcQuiet1Offset LITERAL1 +kSamsungAcQuiet5Offset LITERAL1 kSamsungAcSectionGap LITERAL1 kSamsungAcSectionMark LITERAL1 kSamsungAcSectionSpace LITERAL1 kSamsungAcSections LITERAL1 kSamsungAcStateLength LITERAL1 -kSamsungAcSwingMask LITERAL1 kSamsungAcSwingMove LITERAL1 +kSamsungAcSwingOffset LITERAL1 +kSamsungAcSwingSize LITERAL1 kSamsungAcSwingStop LITERAL1 -kSamsungAcTempMask LITERAL1 kSamsungAcZeroSpace LITERAL1 kSamsungBitMark LITERAL1 kSamsungBitMarkTicks LITERAL1 @@ -2383,10 +2677,11 @@ kSanyoSa8650bOneMark LITERAL1 kSanyoSa8650bRptLength LITERAL1 kSanyoSa8650bZeroMark LITERAL1 kSharpAcAuto LITERAL1 -kSharpAcBitFanManual LITERAL1 +kSharpAcBitFanManualOffset LITERAL1 kSharpAcBitMark LITERAL1 -kSharpAcBitPower LITERAL1 -kSharpAcBitTempManual LITERAL1 +kSharpAcBitModeNonAutoOffset LITERAL1 +kSharpAcBitPowerOffset LITERAL1 +kSharpAcBitTempManualOffset LITERAL1 kSharpAcBits LITERAL1 kSharpAcByteFan LITERAL1 kSharpAcByteManual LITERAL1 @@ -2401,15 +2696,15 @@ kSharpAcFanHigh LITERAL1 kSharpAcFanMax LITERAL1 kSharpAcFanMed LITERAL1 kSharpAcFanMin LITERAL1 +kSharpAcFanOffset LITERAL1 +kSharpAcFanSize LITERAL1 kSharpAcGap LITERAL1 kSharpAcHdrMark LITERAL1 kSharpAcHdrSpace LITERAL1 kSharpAcHeat LITERAL1 -kSharpAcMaskFan LITERAL1 -kSharpAcMaskMode LITERAL1 -kSharpAcMaskTemp LITERAL1 kSharpAcMaxTemp LITERAL1 kSharpAcMinTemp LITERAL1 +kSharpAcModeSize LITERAL1 kSharpAcOneSpace LITERAL1 kSharpAcStateLength LITERAL1 kSharpAcZeroSpace LITERAL1 @@ -2455,13 +2750,12 @@ kStartOffset LITERAL1 kStateSizeMax LITERAL1 kStopState LITERAL1 kTcl112AcAuto LITERAL1 -kTcl112AcBitEcono LITERAL1 -kTcl112AcBitHealth LITERAL1 -kTcl112AcBitLight LITERAL1 +kTcl112AcBitEconoOffset LITERAL1 +kTcl112AcBitHealthOffset LITERAL1 +kTcl112AcBitLightOffset LITERAL1 kTcl112AcBitMark LITERAL1 -kTcl112AcBitSwingH LITERAL1 -kTcl112AcBitSwingV LITERAL1 -kTcl112AcBitTurbo LITERAL1 +kTcl112AcBitSwingHOffset LITERAL1 +kTcl112AcBitTurboOffset LITERAL1 kTcl112AcBits LITERAL1 kTcl112AcCool LITERAL1 kTcl112AcDefaultRepeat LITERAL1 @@ -2470,16 +2764,22 @@ kTcl112AcFan LITERAL1 kTcl112AcFanAuto LITERAL1 kTcl112AcFanHigh LITERAL1 kTcl112AcFanLow LITERAL1 -kTcl112AcFanMask LITERAL1 kTcl112AcFanMed LITERAL1 +kTcl112AcFanSize LITERAL1 kTcl112AcGap LITERAL1 -kTcl112AcHalfDegree LITERAL1 +kTcl112AcHalfDegreeOffset LITERAL1 kTcl112AcHdrMark LITERAL1 +kTcl112AcHdrMarkTolerance LITERAL1 kTcl112AcHdrSpace LITERAL1 kTcl112AcHeat LITERAL1 +kTcl112AcModeSize LITERAL1 kTcl112AcOneSpace LITERAL1 -kTcl112AcPowerMask LITERAL1 +kTcl112AcPowerOffset LITERAL1 kTcl112AcStateLength LITERAL1 +kTcl112AcSwingVOff LITERAL1 +kTcl112AcSwingVOffset LITERAL1 +kTcl112AcSwingVOn LITERAL1 +kTcl112AcSwingVSize LITERAL1 kTcl112AcTempMax LITERAL1 kTcl112AcTempMin LITERAL1 kTcl112AcTolerance LITERAL1 @@ -2494,28 +2794,32 @@ kTecoFan LITERAL1 kTecoFanAuto LITERAL1 kTecoFanHigh LITERAL1 kTecoFanLow LITERAL1 -kTecoFanMask LITERAL1 kTecoFanMed LITERAL1 +kTecoFanOffset LITERAL1 +kTecoFanSize LITERAL1 kTecoGap LITERAL1 kTecoHdrMark LITERAL1 kTecoHdrSpace LITERAL1 kTecoHeat LITERAL1 -kTecoHumid LITERAL1 -kTecoLight LITERAL1 +kTecoHumidOffset LITERAL1 +kTecoLightOffset LITERAL1 kTecoMaxTemp LITERAL1 kTecoMinTemp LITERAL1 -kTecoModeMask LITERAL1 +kTecoModeOffset LITERAL1 kTecoOneSpace LITERAL1 -kTecoPower LITERAL1 +kTecoPowerOffset LITERAL1 kTecoReset LITERAL1 -kTecoSave LITERAL1 -kTecoSleep LITERAL1 -kTecoSwing LITERAL1 -kTecoTempMask LITERAL1 -kTecoTimerHalfH LITERAL1 -kTecoTimerOn LITERAL1 -kTecoTimerTenHr LITERAL1 -kTecoTimerUniHr LITERAL1 +kTecoSaveOffset LITERAL1 +kTecoSleepOffset LITERAL1 +kTecoSwingOffset LITERAL1 +kTecoTempOffset LITERAL1 +kTecoTempSize LITERAL1 +kTecoTimerHalfHourOffset LITERAL1 +kTecoTimerOnOffset LITERAL1 +kTecoTimerTensHoursOffset LITERAL1 +kTecoTimerTensHoursSize LITERAL1 +kTecoTimerUnitHoursOffset LITERAL1 +kTecoTimerUnitHoursSize LITERAL1 kTecoZeroSpace LITERAL1 kTimeoutMs LITERAL1 kTolerance LITERAL1 @@ -2530,14 +2834,20 @@ kToshibaAcFanAuto LITERAL1 kToshibaAcFanMax LITERAL1 kToshibaAcFanMed LITERAL1 kToshibaAcFanMin LITERAL1 +kToshibaAcFanOffset LITERAL1 +kToshibaAcFanSize LITERAL1 kToshibaAcHdrMark LITERAL1 kToshibaAcHdrSpace LITERAL1 kToshibaAcHeat LITERAL1 kToshibaAcMaxTemp LITERAL1 kToshibaAcMinGap LITERAL1 kToshibaAcMinTemp LITERAL1 +kToshibaAcModeOffset LITERAL1 +kToshibaAcModeSize LITERAL1 kToshibaAcOneSpace LITERAL1 -kToshibaAcPower LITERAL1 +kToshibaAcPowerOffset LITERAL1 +kToshibaAcTempOffset LITERAL1 +kToshibaAcTempSize LITERAL1 kToshibaAcZeroSpace LITERAL1 kTrotecAuto LITERAL1 kTrotecBitMark LITERAL1 @@ -2550,6 +2860,8 @@ kTrotecFan LITERAL1 kTrotecFanHigh LITERAL1 kTrotecFanLow LITERAL1 kTrotecFanMed LITERAL1 +kTrotecFanOffset LITERAL1 +kTrotecFanSize LITERAL1 kTrotecGap LITERAL1 kTrotecGapEnd LITERAL1 kTrotecHdrMark LITERAL1 @@ -2559,19 +2871,23 @@ kTrotecIntro2 LITERAL1 kTrotecMaxTemp LITERAL1 kTrotecMaxTimer LITERAL1 kTrotecMinTemp LITERAL1 +kTrotecModeOffset LITERAL1 +kTrotecModeSize LITERAL1 kTrotecOneSpace LITERAL1 -kTrotecPowerBit LITERAL1 -kTrotecSleepBit LITERAL1 +kTrotecPowerBitOffset LITERAL1 +kTrotecSleepBitOffset LITERAL1 kTrotecStateLength LITERAL1 -kTrotecTimerBit LITERAL1 +kTrotecTempOffset LITERAL1 +kTrotecTempSize LITERAL1 +kTrotecTimerBitOffset LITERAL1 kTrotecZeroSpace LITERAL1 kUnknownThreshold LITERAL1 kUseDefTol LITERAL1 kVestelAcAuto LITERAL1 kVestelAcBitMark LITERAL1 kVestelAcBits LITERAL1 -kVestelAcCRCMask LITERAL1 kVestelAcChecksumOffset LITERAL1 +kVestelAcChecksumSize LITERAL1 kVestelAcCool LITERAL1 kVestelAcDry LITERAL1 kVestelAcFan LITERAL1 @@ -2582,16 +2898,19 @@ kVestelAcFanHigh LITERAL1 kVestelAcFanLow LITERAL1 kVestelAcFanMed LITERAL1 kVestelAcFanOffset LITERAL1 +kVestelAcFanSize LITERAL1 kVestelAcHdrMark LITERAL1 kVestelAcHdrSpace LITERAL1 kVestelAcHeat LITERAL1 kVestelAcHourOffset LITERAL1 +kVestelAcHourSize LITERAL1 kVestelAcIon LITERAL1 kVestelAcIonOffset LITERAL1 kVestelAcMaxTemp LITERAL1 kVestelAcMinTempC LITERAL1 kVestelAcMinTempH LITERAL1 kVestelAcMinuteOffset LITERAL1 +kVestelAcMinuteSize LITERAL1 kVestelAcModeOffset LITERAL1 kVestelAcNormal LITERAL1 kVestelAcOffTimeOffset LITERAL1 @@ -2600,6 +2919,7 @@ kVestelAcOnTimeOffset LITERAL1 kVestelAcOnTimerFlagOffset LITERAL1 kVestelAcOneSpace LITERAL1 kVestelAcPowerOffset LITERAL1 +kVestelAcPowerSize LITERAL1 kVestelAcSleep LITERAL1 kVestelAcStateDefault LITERAL1 kVestelAcSwing LITERAL1 @@ -2607,11 +2927,14 @@ kVestelAcSwingOffset LITERAL1 kVestelAcTempOffset LITERAL1 kVestelAcTimeStateDefault LITERAL1 kVestelAcTimerFlagOffset LITERAL1 +kVestelAcTimerHourSize LITERAL1 +kVestelAcTimerMinsSize LITERAL1 +kVestelAcTimerSize LITERAL1 kVestelAcTolerance LITERAL1 kVestelAcTurbo LITERAL1 kVestelAcTurboSleepOffset LITERAL1 kVestelAcZeroSpace LITERAL1 -kWhirlpoolAcAltTempMask LITERAL1 +kWhirlpoolAcAltTempOffset LITERAL1 kWhirlpoolAcAltTempPos LITERAL1 kWhirlpoolAcAuto LITERAL1 kWhirlpoolAcAutoTemp LITERAL1 @@ -2640,37 +2963,39 @@ kWhirlpoolAcFan LITERAL1 kWhirlpoolAcFanAuto LITERAL1 kWhirlpoolAcFanHigh LITERAL1 kWhirlpoolAcFanLow LITERAL1 -kWhirlpoolAcFanMask LITERAL1 kWhirlpoolAcFanMedium LITERAL1 +kWhirlpoolAcFanOffset LITERAL1 kWhirlpoolAcFanPos LITERAL1 +kWhirlpoolAcFanSize LITERAL1 kWhirlpoolAcGap LITERAL1 kWhirlpoolAcHdrMark LITERAL1 kWhirlpoolAcHdrSpace LITERAL1 kWhirlpoolAcHeat LITERAL1 -kWhirlpoolAcHourMask LITERAL1 -kWhirlpoolAcLightMask LITERAL1 +kWhirlpoolAcHourOffset LITERAL1 +kWhirlpoolAcHourSize LITERAL1 +kWhirlpoolAcLightOffset LITERAL1 kWhirlpoolAcMaxTemp LITERAL1 kWhirlpoolAcMinGap LITERAL1 kWhirlpoolAcMinTemp LITERAL1 -kWhirlpoolAcMinuteMask LITERAL1 -kWhirlpoolAcModeMask LITERAL1 +kWhirlpoolAcMinuteOffset LITERAL1 +kWhirlpoolAcMinuteSize LITERAL1 +kWhirlpoolAcModeOffset LITERAL1 kWhirlpoolAcModePos LITERAL1 kWhirlpoolAcOffTimerPos LITERAL1 kWhirlpoolAcOnTimerPos LITERAL1 kWhirlpoolAcOneSpace LITERAL1 -kWhirlpoolAcPowerToggleMask LITERAL1 +kWhirlpoolAcPowerToggleOffset LITERAL1 kWhirlpoolAcPowerTogglePos LITERAL1 kWhirlpoolAcSections LITERAL1 -kWhirlpoolAcSleepMask LITERAL1 +kWhirlpoolAcSleepOffset LITERAL1 kWhirlpoolAcSleepPos LITERAL1 kWhirlpoolAcStateLength LITERAL1 kWhirlpoolAcSuperMask LITERAL1 kWhirlpoolAcSuperPos LITERAL1 -kWhirlpoolAcSwing1Mask LITERAL1 -kWhirlpoolAcSwing2Mask LITERAL1 -kWhirlpoolAcTempMask LITERAL1 +kWhirlpoolAcSwing1Offset LITERAL1 +kWhirlpoolAcSwing2Offset LITERAL1 kWhirlpoolAcTempPos LITERAL1 -kWhirlpoolAcTimerEnableMask LITERAL1 +kWhirlpoolAcTimerEnableOffset LITERAL1 kWhirlpoolAcZeroSpace LITERAL1 kWhynterBitMark LITERAL1 kWhynterBitMarkTicks LITERAL1 diff --git a/lib/IRremoteESP8266-2.6.5/library.json b/lib/IRremoteESP8266-2.7.0/library.json old mode 100755 new mode 100644 similarity index 97% rename from lib/IRremoteESP8266-2.6.5/library.json rename to lib/IRremoteESP8266-2.7.0/library.json index c5136f18e..361bbb0af --- a/lib/IRremoteESP8266-2.6.5/library.json +++ b/lib/IRremoteESP8266-2.7.0/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.6.5", + "version": "2.7.0", "keywords": "infrared, ir, remote, esp8266, esp32", "description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)", "repository": diff --git a/lib/IRremoteESP8266-2.6.5/library.properties b/lib/IRremoteESP8266-2.7.0/library.properties old mode 100755 new mode 100644 similarity index 97% rename from lib/IRremoteESP8266-2.6.5/library.properties rename to lib/IRremoteESP8266-2.7.0/library.properties index f83a80428..1f2c0770f --- a/lib/IRremoteESP8266-2.6.5/library.properties +++ b/lib/IRremoteESP8266-2.7.0/library.properties @@ -1,5 +1,5 @@ name=IRremoteESP8266 -version=2.6.5 +version=2.7.0 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.6.5/pylintrc b/lib/IRremoteESP8266-2.7.0/pylintrc old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/pylintrc rename to lib/IRremoteESP8266-2.7.0/pylintrc diff --git a/lib/IRremoteESP8266-2.6.5/src/CPPLINT.cfg b/lib/IRremoteESP8266-2.7.0/src/CPPLINT.cfg old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/CPPLINT.cfg rename to lib/IRremoteESP8266-2.7.0/src/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.6.5/src/IRac.cpp b/lib/IRremoteESP8266-2.7.0/src/IRac.cpp old mode 100755 new mode 100644 similarity index 75% rename from lib/IRremoteESP8266-2.6.5/src/IRac.cpp rename to lib/IRremoteESP8266-2.7.0/src/IRac.cpp index df668d836..bec5eb554 --- a/lib/IRremoteESP8266-2.6.5/src/IRac.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/IRac.cpp @@ -14,6 +14,7 @@ #endif #include "IRsend.h" #include "IRremoteESP8266.h" +#include "IRtext.h" #include "IRutils.h" #include "ir_Amcor.h" #include "ir_Argo.h" @@ -42,15 +43,59 @@ IRac::IRac(const uint16_t pin, const bool inverted, const bool use_modulation) { _pin = pin; _inverted = inverted; _modulation = use_modulation; + initState(&next); + _prev = next; } +void IRac::initState(stdAc::state_t *state, + const decode_type_t vendor, const int16_t model, + const bool power, const stdAc::opmode_t mode, + const float degrees, const bool celsius, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool econo, + const bool light, const bool filter, const bool clean, + const bool beep, const int16_t sleep, + const int16_t clock) { + state->protocol = vendor; + state->model = model; + state->power = power; + state->mode = mode; + state->degrees = degrees; + state->celsius = celsius; + state->fanspeed = fan; + state->swingv = swingv; + state->swingh = swingh; + state->quiet = quiet; + state->turbo = turbo; + state->econo = econo; + state->light = light; + state->filter = filter; + state->clean = clean; + state->beep = beep; + state->sleep = sleep; + state->clock = clock; +} + +void IRac::initState(stdAc::state_t *state) { + initState(state, decode_type_t::UNKNOWN, -1, false, stdAc::opmode_t::kOff, + 25, true, // 25 degrees Celsius + stdAc::fanspeed_t::kAuto, stdAc::swingv_t::kOff, + stdAc::swingh_t::kOff, false, false, false, false, false, false, + false, -1, -1); +} + +stdAc::state_t IRac::getState(void) { return next; } + +stdAc::state_t IRac::getStatePrev(void) { return _prev; } + // Is the given protocol supported by the IRac class? bool IRac::isProtocolSupported(const decode_type_t protocol) { switch (protocol) { #if SEND_AMCOR case decode_type_t::AMCOR: #endif -#if SEND_AMCOR +#if SEND_ARGO case decode_type_t::ARGO: #endif #if SEND_COOLIX @@ -62,6 +107,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #if SEND_DAIKIN128 case decode_type_t::DAIKIN128: #endif +#if SEND_DAIKIN152 + case decode_type_t::DAIKIN152: +#endif #if SEND_DAIKIN160 case decode_type_t::DAIKIN160: #endif @@ -95,6 +143,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #if SEND_HITACHI_AC case decode_type_t::HITACHI_AC: #endif +#if SEND_HITACHI_AC424 + case decode_type_t::HITACHI_AC424: +#endif #if SEND_KELVINATOR case decode_type_t::KELVINATOR: #endif @@ -104,6 +155,12 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #if SEND_MITSUBISHI_AC case decode_type_t::MITSUBISHI_AC: #endif +#if SEND_MITSUBISHI112 + case decode_type_t::MITSUBISHI112: +#endif +#if SEND_MITSUBISHI136 + case decode_type_t::MITSUBISHI136: +#endif #if SEND_MITSUBISHIHEAVY case decode_type_t::MITSUBISHI_HEAVY_88: case decode_type_t::MITSUBISHI_HEAVY_152: @@ -148,6 +205,7 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { void IRac::amcor(IRAmcorAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -170,6 +228,7 @@ void IRac::argo(IRArgoAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const int16_t sleep) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -194,6 +253,14 @@ void IRac::coolix(IRCoolixAC *ac, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool turbo, const bool light, const bool clean, const int16_t sleep) { + ac->begin(); + ac->setPower(on); + if (!on) { + // after turn off AC no more commands should + // be accepted + ac->send(); + return; + } ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); @@ -227,8 +294,6 @@ void IRac::coolix(IRCoolixAC *ac, ac->setClean(); ac->send(); } - // Power gets done last, as off has a special command. - ac->setPower(on); ac->send(); } #endif // SEND_COOLIX @@ -240,6 +305,7 @@ void IRac::daikin(IRDaikinESP *ac, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const bool econo, const bool clean) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -266,6 +332,7 @@ void IRac::daikin128(IRDaikin128 *ac, const stdAc::swingv_t swingv, const bool quiet, const bool turbo, const bool light, const bool econo, const int16_t sleep, const int16_t clock) { + ac->begin(); ac->setPowerToggle(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -285,11 +352,38 @@ void IRac::daikin128(IRDaikin128 *ac, } #endif // SEND_DAIKIN128 +#if SEND_DAIKIN152 +void IRac::daikin152(IRDaikin152 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const bool quiet, const bool turbo, const bool econo) { + ac->begin(); + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingV((int8_t)swingv >= 0); + // No Horizontal Swing setting avaliable. + ac->setQuiet(quiet); + // No Light setting available. + // No Filter setting available. + ac->setPowerful(turbo); + ac->setEcono(econo); + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + ac->send(); +} +#endif // SEND_DAIKIN152 + #if SEND_DAIKIN160 void IRac::daikin160(IRDaikin160 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -304,6 +398,7 @@ void IRac::daikin176(IRDaikin176 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingh_t swingh) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -321,19 +416,21 @@ void IRac::daikin2(IRDaikin2 *ac, const bool quiet, const bool turbo, const bool light, const bool econo, const bool filter, const bool clean, const bool beep, const int16_t sleep, const int16_t clock) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical(ac->convertSwingV(swingv)); - ac->setSwingHorizontal((int8_t)swingh >= 0); + ac->setSwingHorizontal(ac->convertSwingH(swingh)); ac->setQuiet(quiet); - ac->setLight(light); + ac->setLight(light ? 1 : 3); // On/High is 1, Off is 3. ac->setPowerful(turbo); ac->setEcono(econo); ac->setPurify(filter); ac->setMold(clean); - ac->setBeep(beep); + ac->setClean(true); // Hardwire auto clean to be on per request (@sheppy99) + ac->setBeep(beep ? 2 : 3); // On/Loud is 2, Off is 3. if (sleep > 0) ac->enableSleepTimer(sleep); if (clock >= 0) ac->setCurrentTime(clock); ac->send(); @@ -346,6 +443,7 @@ void IRac::daikin216(IRDaikin216 *ac, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -364,6 +462,7 @@ void IRac::electra(IRElectraAc *ac, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -388,7 +487,9 @@ void IRac::fujitsu(IRFujitsuAC *ac, const fujitsu_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 bool econo) { + const bool quiet, const bool turbo, const bool econo, + const bool filter, const bool clean) { + ac->begin(); ac->setModel(model); if (on) { // Do all special messages (except "Off") first, @@ -420,8 +521,8 @@ void IRac::fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model, ac->setSwing(swing); if (quiet) ac->setFanSpeed(kFujitsuAcFanQuiet); // No Light setting available. - // No Filter setting available. - // No Clean setting available. + ac->setFilter(filter); + ac->setClean(clean); // No Beep setting available. // No Sleep setting available. // No Clock setting available. @@ -442,6 +543,7 @@ void IRac::goodweather(IRGoodweatherAc *ac, const stdAc::swingv_t swingv, const bool turbo, const bool light, const int16_t sleep) { + ac->begin(); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); @@ -468,6 +570,7 @@ void IRac::gree(IRGreeAC *ac, const gree_ac_remote_model_t model, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const bool light, const bool clean, const int16_t sleep) { + ac->begin(); ac->setModel(model); ac->setPower(on); ac->setMode(ac->convertMode(mode)); @@ -494,6 +597,7 @@ void IRac::haier(IRHaierAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool filter, const int16_t sleep, const int16_t clock) { + ac->begin(); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); @@ -521,6 +625,7 @@ void IRac::haierYrwo2(IRHaierACYRW02 *ac, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const bool filter, const int16_t sleep) { + ac->begin(); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); @@ -543,6 +648,7 @@ void IRac::hitachi(IRHitachiAc *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) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -561,6 +667,29 @@ void IRac::hitachi(IRHitachiAc *ac, } #endif // SEND_HITACHI_AC +#if SEND_HITACHI_AC424 +void IRac::hitachi424(IRHitachiAc424 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan) { + ac->begin(); + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + // TODO(jamsinclair): Add Swing(V) support. + // No Swing(H) setting available. + // No Quiet setting available. + // No Turbo setting available. + // No Light setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + ac->send(); +} +#endif // SEND_HITACHI_AC424 + #if SEND_KELVINATOR void IRac::kelvinator(IRKelvinatorAC *ac, const bool on, const stdAc::opmode_t mode, @@ -569,6 +698,7 @@ void IRac::kelvinator(IRKelvinatorAC *ac, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const bool light, const bool filter, const bool clean) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -592,6 +722,7 @@ void IRac::midea(IRMideaAC *ac, const bool on, const stdAc::opmode_t mode, const bool celsius, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const int16_t sleep) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setUseCelsius(celsius); @@ -618,6 +749,7 @@ void IRac::mitsubishi(IRMitsubishiAC *ac, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const int16_t clock) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -636,6 +768,58 @@ void IRac::mitsubishi(IRMitsubishiAC *ac, } #endif // SEND_MITSUBISHI_AC +#if SEND_MITSUBISHI112 +void IRac::mitsubishi112(IRMitsubishi112 *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) { + ac->begin(); + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingV(ac->convertSwingV(swingv)); + ac->setSwingH(ac->convertSwingH(swingh)); + ac->setQuiet(quiet); + // FIXME - Econo + // ac->setEcono(econo); + // No Turbo setting available. + // No Light setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + ac->send(); +} +#endif // SEND_MITSUBISHI112 + +#if SEND_MITSUBISHI136 +void IRac::mitsubishi136(IRMitsubishi136 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const bool quiet) { + ac->begin(); + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingV(ac->convertSwingV(swingv)); + // No Horizontal Swing setting available. + ac->setQuiet(quiet); + // No Turbo setting available. + // No Light setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + ac->send(); +} +#endif // SEND_MITSUBISHI136 + #if SEND_MITSUBISHIHEAVY void IRac::mitsubishiHeavy88(IRMitsubishiHeavy88Ac *ac, const bool on, const stdAc::opmode_t mode, @@ -645,6 +829,7 @@ void IRac::mitsubishiHeavy88(IRMitsubishiHeavy88Ac *ac, const stdAc::swingh_t swingh, const bool turbo, const bool econo, const bool clean) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -672,6 +857,7 @@ void IRac::mitsubishiHeavy152(IRMitsubishiHeavy152Ac *ac, const bool quiet, const bool turbo, const bool econo, const bool filter, const bool clean, const int16_t sleep) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -698,6 +884,7 @@ void IRac::neoclima(IRNeoclimaAc *ac, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool turbo, const bool light, const bool filter, const int16_t sleep) { + ac->begin(); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); @@ -723,6 +910,7 @@ void IRac::panasonic(IRPanasonicAc *ac, const panasonic_ac_remote_model_t model, 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) { + ac->begin(); ac->setModel(model); ac->setPower(on); ac->setMode(ac->convertMode(mode)); @@ -749,9 +937,11 @@ void IRac::samsung(IRSamsungAc *ac, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool quiet, const bool turbo, const bool clean, - const bool beep, const bool dopower) { - // dopower is for unit testing only. It should only ever be false in tests. - if (dopower) ac->setPower(on); + const bool beep, const bool prevpower, + const bool forcepower) { + ac->begin(); + ac->stateReset(forcepower, prevpower); + ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); @@ -776,6 +966,7 @@ void IRac::samsung(IRSamsungAc *ac, void IRac::sharp(IRSharpAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -804,6 +995,7 @@ void IRac::tcl112(IRTcl112Ac *ac, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool turbo, const bool light, const bool econo, const bool filter) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -828,6 +1020,7 @@ void IRac::teco(IRTecoAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool light, const int16_t sleep) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -850,6 +1043,7 @@ void IRac::teco(IRTecoAc *ac, void IRac::toshiba(IRToshibaAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -873,6 +1067,7 @@ void IRac::trotec(IRTrotecESP *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const int16_t sleep) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -898,6 +1093,7 @@ void IRac::vestel(IRVestelAc *ac, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const bool filter, const int16_t sleep, const int16_t clock, const bool sendNormal) { + ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -926,6 +1122,7 @@ void IRac::whirlpool(IRWhirlpoolAc *ac, const whirlpool_ac_remote_model_t model, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const bool light, const int16_t sleep, const int16_t clock) { + ac->begin(); ac->setModel(model); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -1029,303 +1226,11 @@ bool IRac::sendAc(const decode_type_t vendor, const int16_t model, const bool quiet, const bool turbo, const bool econo, const bool light, const bool filter, const bool clean, const bool beep, const int16_t sleep, const int16_t clock) { - // Convert the temperature to Celsius. - float degC; - if (celsius) - degC = degrees; - else - degC = fahrenheitToCelsius(degrees); - bool on = power; - // A hack for Home Assistant, it appears to need/want an Off opmode. - if (mode == stdAc::opmode_t::kOff) on = false; - // Per vendor settings & setup. - switch (vendor) { -#if SEND_AMCOR - case AMCOR: - { - IRAmcorAc ac(_pin, _inverted, _modulation); - amcor(&ac, on, mode, degC, fan); - break; - } -#endif // SEND_AMCOR -#if SEND_ARGO - case ARGO: - { - IRArgoAC ac(_pin, _inverted, _modulation); - argo(&ac, on, mode, degC, fan, swingv, turbo, sleep); - break; - } -#endif // SEND_ARGO -#if SEND_COOLIX - case COOLIX: - { - IRCoolixAC ac(_pin, _inverted, _modulation); - coolix(&ac, on, mode, degC, fan, swingv, swingh, - turbo, light, clean, sleep); - break; - } -#endif // SEND_COOLIX -#if SEND_DAIKIN - case DAIKIN: - { - IRDaikinESP ac(_pin, _inverted, _modulation); - daikin(&ac, on, mode, degC, fan, swingv, swingh, - quiet, turbo, econo, clean); - break; - } -#endif // SEND_DAIKIN -#if SEND_DAIKIN128 - case DAIKIN128: - { - IRDaikin128 ac(_pin, _inverted, _modulation); - daikin128(&ac, on, mode, degC, fan, swingv, quiet, turbo, - light, econo, sleep, clock); - break; - } -#endif // SEND_DAIKIN2 -#if SEND_DAIKIN160 - case DAIKIN160: - { - IRDaikin160 ac(_pin, _inverted, _modulation); - daikin160(&ac, on, mode, degC, fan, swingv); - break; - } -#endif // SEND_DAIKIN160 -#if SEND_DAIKIN176 - case DAIKIN176: - { - IRDaikin176 ac(_pin, _inverted, _modulation); - daikin176(&ac, on, mode, degC, fan, swingh); - break; - } -#endif // SEND_DAIKIN176 -#if SEND_DAIKIN2 - case DAIKIN2: - { - IRDaikin2 ac(_pin, _inverted, _modulation); - daikin2(&ac, on, mode, degC, fan, swingv, swingh, quiet, turbo, - light, econo, filter, clean, beep, sleep, clock); - break; - } -#endif // SEND_DAIKIN2 -#if SEND_DAIKIN216 - case DAIKIN216: - { - IRDaikin216 ac(_pin, _inverted, _modulation); - daikin216(&ac, on, mode, degC, fan, swingv, swingh, quiet, turbo); - break; - } -#endif // SEND_DAIKIN216 -#if SEND_ELECTRA_AC - case ELECTRA_AC: - { - IRElectraAc ac(_pin, _inverted, _modulation); - ac.begin(); - electra(&ac, on, mode, degC, fan, swingv, swingh); - break; - } -#endif // SEND_ELECTRA_AC -#if SEND_FUJITSU_AC - case FUJITSU_AC: - { - IRFujitsuAC ac(_pin, (fujitsu_ac_remote_model_t)model, _inverted, - _modulation); - ac.begin(); - fujitsu(&ac, (fujitsu_ac_remote_model_t)model, on, mode, degC, fan, - swingv, swingh, quiet, turbo, econo); - break; - } -#endif // SEND_FUJITSU_AC -#if SEND_GOODWEATHER - case GOODWEATHER: - { - IRGoodweatherAc ac(_pin, _inverted, _modulation); - ac.begin(); - goodweather(&ac, on, mode, degC, fan, swingv, turbo, light, sleep); - break; - } -#endif // SEND_GOODWEATHER -#if SEND_GREE - case GREE: - { - IRGreeAC ac(_pin, (gree_ac_remote_model_t)model, _inverted, _modulation); - ac.begin(); - gree(&ac, (gree_ac_remote_model_t)model, on, mode, degC, fan, swingv, - turbo, light, clean, sleep); - break; - } -#endif // SEND_GREE -#if SEND_HAIER_AC - case HAIER_AC: - { - IRHaierAC ac(_pin, _inverted, _modulation); - ac.begin(); - haier(&ac, on, mode, degC, fan, swingv, filter, sleep, clock); - break; - } -#endif // SEND_HAIER_AC -#if SEND_HAIER_AC_YRW02 - case HAIER_AC_YRW02: - { - IRHaierACYRW02 ac(_pin, _inverted, _modulation); - ac.begin(); - haierYrwo2(&ac, on, mode, degC, fan, swingv, turbo, filter, sleep); - break; - } -#endif // SEND_HAIER_AC_YRW02 -#if SEND_HITACHI_AC - case HITACHI_AC: - { - IRHitachiAc ac(_pin, _inverted, _modulation); - ac.begin(); - hitachi(&ac, on, mode, degC, fan, swingv, swingh); - break; - } -#endif // SEND_HITACHI_AC -#if SEND_KELVINATOR - case KELVINATOR: - { - IRKelvinatorAC ac(_pin, _inverted, _modulation); - ac.begin(); - kelvinator(&ac, on, mode, degC, fan, swingv, swingh, quiet, turbo, - light, filter, clean); - break; - } -#endif // SEND_KELVINATOR -#if SEND_MIDEA - case MIDEA: - { - IRMideaAC ac(_pin, _inverted, _modulation); - ac.begin(); - midea(&ac, on, mode, celsius, degrees, fan, swingv, sleep); - break; - } -#endif // SEND_MIDEA -#if SEND_MITSUBISHI_AC - case MITSUBISHI_AC: - { - IRMitsubishiAC ac(_pin, _inverted, _modulation); - ac.begin(); - mitsubishi(&ac, on, mode, degC, fan, swingv, swingh, quiet, clock); - break; - } -#endif // SEND_MITSUBISHI_AC -#if SEND_MITSUBISHIHEAVY - case MITSUBISHI_HEAVY_88: - { - IRMitsubishiHeavy88Ac ac(_pin, _inverted, _modulation); - ac.begin(); - mitsubishiHeavy88(&ac, on, mode, degC, fan, swingv, swingh, - turbo, econo, clean); - break; - } - case MITSUBISHI_HEAVY_152: - { - IRMitsubishiHeavy152Ac ac(_pin, _inverted, _modulation); - ac.begin(); - mitsubishiHeavy152(&ac, on, mode, degC, fan, swingv, swingh, - quiet, turbo, econo, filter, clean, sleep); - break; - } -#endif // SEND_MITSUBISHIHEAVY -#if SEND_NEOCLIMA - case NEOCLIMA: - { - IRNeoclimaAc ac(_pin, _inverted, _modulation); - ac.begin(); - neoclima(&ac, on, mode, degC, fan, swingv, swingh, turbo, light, filter, - sleep); - break; - } -#endif // SEND_NEOCLIMA -#if SEND_PANASONIC_AC - case PANASONIC_AC: - { - IRPanasonicAc ac(_pin, _inverted, _modulation); - ac.begin(); - panasonic(&ac, (panasonic_ac_remote_model_t)model, on, mode, degC, fan, - swingv, swingh, quiet, turbo, clock); - break; - } -#endif // SEND_PANASONIC_AC -#if SEND_SAMSUNG_AC - case SAMSUNG_AC: - { - IRSamsungAc ac(_pin, _inverted, _modulation); - ac.begin(); - samsung(&ac, on, mode, degC, fan, swingv, quiet, turbo, clean, beep); - break; - } -#endif // SEND_SAMSUNG_AC -#if SEND_SHARP_AC - case SHARP_AC: - { - IRSharpAc ac(_pin, _inverted, _modulation); - ac.begin(); - sharp(&ac, on, mode, degC, fan); - break; - } -#endif // SEND_SHARP_AC -#if SEND_TCL112AC - case TCL112AC: - { - IRTcl112Ac ac(_pin, _inverted, _modulation); - ac.begin(); - tcl112(&ac, on, mode, degC, fan, swingv, swingh, turbo, light, econo, - filter); - break; - } -#endif // SEND_TCL112AC -#if SEND_TECO - case TECO: - { - IRTecoAc ac(_pin, _inverted, _modulation); - ac.begin(); - teco(&ac, on, mode, degC, fan, swingv, light, sleep); - break; - } -#endif // SEND_TECO -#if SEND_TOSHIBA_AC - case TOSHIBA_AC: - { - IRToshibaAC ac(_pin, _inverted, _modulation); - ac.begin(); - toshiba(&ac, on, mode, degC, fan); - break; - } -#endif // SEND_TOSHIBA_AC -#if SEND_TROTEC - case TROTEC: - { - IRTrotecESP ac(_pin, _inverted, _modulation); - ac.begin(); - trotec(&ac, on, mode, degC, fan, sleep); - break; - } -#endif // SEND_TROTEC -#if SEND_VESTEL_AC - case VESTEL_AC: - { - IRVestelAc ac(_pin, _inverted, _modulation); - ac.begin(); - vestel(&ac, on, mode, degC, fan, swingv, turbo, filter, sleep, clock); - break; - } -#endif // SEND_VESTEL_AC -#if SEND_WHIRLPOOL_AC - case WHIRLPOOL_AC: - { - IRWhirlpoolAc ac(_pin, _inverted, _modulation); - ac.begin(); - whirlpool(&ac, (whirlpool_ac_remote_model_t)model, on, mode, degC, fan, - swingv, turbo, light, sleep, clock); - break; - } -#endif // SEND_WHIRLPOOL_AC - default: - return false; // Fail, didn't match anything. - } - return true; // Success. + stdAc::state_t to_send; + initState(&to_send, vendor, model, power, mode, degrees, celsius, fan, swingv, + swingh, quiet, turbo, econo, light, filter, clean, beep, sleep, + clock); + return this->sendAc(to_send, &to_send); } // Send A/C message for a given device using state_t structures. @@ -1336,12 +1241,348 @@ bool IRac::sendAc(const decode_type_t vendor, const int16_t model, // Returns: // boolean: True, if accepted/converted/attempted. False, if unsupported. bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { - stdAc::state_t final = this->handleToggles(desired, prev); - return this->sendAc(final.protocol, final.model, final.power, final.mode, - final.degrees, final.celsius, final.fanspeed, - final.swingv, final.swingh, final.quiet, final.turbo, - final.econo, final.light, final.filter, final.clean, - final.beep, final.sleep, final.clock); + stdAc::state_t send = this->handleToggles(desired, prev); + // Convert the temperature to Celsius. + float degC; + if (desired.celsius) + degC = send.degrees; + else + degC = fahrenheitToCelsius(desired.degrees); + bool on = desired.power; + // A hack for Home Assistant, it appears to need/want an Off opmode. + if (desired.mode == stdAc::opmode_t::kOff) on = false; + // Per vendor settings & setup. + switch (send.protocol) { +#if SEND_AMCOR + case AMCOR: + { + IRAmcorAc ac(_pin, _inverted, _modulation); + amcor(&ac, on, send.mode, degC, send.fanspeed); + break; + } +#endif // SEND_AMCOR +#if SEND_ARGO + case ARGO: + { + IRArgoAC ac(_pin, _inverted, _modulation); + argo(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.turbo, + send.sleep); + break; + } +#endif // SEND_ARGO +#if SEND_COOLIX + case COOLIX: + { + IRCoolixAC ac(_pin, _inverted, _modulation); + coolix(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, + send.turbo, send.light, send.clean, send.sleep); + break; + } +#endif // SEND_COOLIX +#if SEND_DAIKIN + case DAIKIN: + { + IRDaikinESP ac(_pin, _inverted, _modulation); + daikin(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, + send.quiet, send.turbo, send.econo, send.clean); + break; + } +#endif // SEND_DAIKIN +#if SEND_DAIKIN128 + case DAIKIN128: + { + IRDaikin128 ac(_pin, _inverted, _modulation); + daikin128(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.quiet, send.turbo, send.light, send.econo, send.sleep, + send.clock); + break; + } +#endif // SEND_DAIKIN2 +#if SEND_DAIKIN152 + case DAIKIN152: + { + IRDaikin152 ac(_pin, _inverted, _modulation); + daikin152(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.quiet, send.turbo, send.econo); + break; + } +#endif // SEND_DAIKIN152 +#if SEND_DAIKIN160 + case DAIKIN160: + { + IRDaikin160 ac(_pin, _inverted, _modulation); + daikin160(&ac, on, send.mode, degC, send.fanspeed, send.swingv); + break; + } +#endif // SEND_DAIKIN160 +#if SEND_DAIKIN176 + case DAIKIN176: + { + IRDaikin176 ac(_pin, _inverted, _modulation); + daikin176(&ac, on, send.mode, degC, send.fanspeed, send.swingh); + break; + } +#endif // SEND_DAIKIN176 +#if SEND_DAIKIN2 + case DAIKIN2: + { + IRDaikin2 ac(_pin, _inverted, _modulation); + daikin2(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, + send.quiet, send.turbo, send.light, send.econo, send.filter, + send.clean, send.beep, send.sleep, send.clock); + break; + } +#endif // SEND_DAIKIN2 +#if SEND_DAIKIN216 + case DAIKIN216: + { + IRDaikin216 ac(_pin, _inverted, _modulation); + daikin216(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.swingh, send.quiet, send.turbo); + break; + } +#endif // SEND_DAIKIN216 +#if SEND_ELECTRA_AC + case ELECTRA_AC: + { + IRElectraAc ac(_pin, _inverted, _modulation); + electra(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.swingh); + break; + } +#endif // SEND_ELECTRA_AC +#if SEND_FUJITSU_AC + case FUJITSU_AC: + { + IRFujitsuAC ac(_pin, (fujitsu_ac_remote_model_t)send.model, _inverted, + _modulation); + fujitsu(&ac, (fujitsu_ac_remote_model_t)send.model, on, send.mode, degC, + send.fanspeed, send.swingv, send.swingh, send.quiet, send.turbo, + send.econo, send.filter, send.clean); + break; + } +#endif // SEND_FUJITSU_AC +#if SEND_GOODWEATHER + case GOODWEATHER: + { + IRGoodweatherAc ac(_pin, _inverted, _modulation); + goodweather(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.turbo, send.light, send.sleep); + break; + } +#endif // SEND_GOODWEATHER +#if SEND_GREE + case GREE: + { + IRGreeAC ac(_pin, (gree_ac_remote_model_t)send.model, _inverted, + _modulation); + gree(&ac, (gree_ac_remote_model_t)send.model, on, send.mode, degC, + send.fanspeed, send.swingv, send.turbo, send.light, send.clean, + send.sleep); + break; + } +#endif // SEND_GREE +#if SEND_HAIER_AC + case HAIER_AC: + { + IRHaierAC ac(_pin, _inverted, _modulation); + haier(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.filter, + send.sleep, send.clock); + break; + } +#endif // SEND_HAIER_AC +#if SEND_HAIER_AC_YRW02 + case HAIER_AC_YRW02: + { + IRHaierACYRW02 ac(_pin, _inverted, _modulation); + haierYrwo2(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.turbo, send.filter, send.sleep); + break; + } +#endif // SEND_HAIER_AC_YRW02 +#if SEND_HITACHI_AC + case HITACHI_AC: + { + IRHitachiAc ac(_pin, _inverted, _modulation); + hitachi(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.swingh); + break; + } +#endif // SEND_HITACHI_AC +#if SEND_HITACHI_AC424 + case HITACHI_AC424: + { + IRHitachiAc424 ac(_pin, _inverted, _modulation); + hitachi424(&ac, on, send.mode, degC, send.fanspeed); + break; + } +#endif // SEND_HITACHI_AC424 +#if SEND_KELVINATOR + case KELVINATOR: + { + IRKelvinatorAC ac(_pin, _inverted, _modulation); + kelvinator(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.swingh, send.quiet, send.turbo, send.light, send.filter, + send.clean); + break; + } +#endif // SEND_KELVINATOR +#if SEND_MIDEA + case MIDEA: + { + IRMideaAC ac(_pin, _inverted, _modulation); + midea(&ac, on, send.mode, send.celsius, send.degrees, send.fanspeed, + send.swingv, send.sleep); + break; + } +#endif // SEND_MIDEA +#if SEND_MITSUBISHI_AC + case MITSUBISHI_AC: + { + IRMitsubishiAC ac(_pin, _inverted, _modulation); + mitsubishi(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.swingh, send.quiet, send.clock); + break; + } +#endif // SEND_MITSUBISHI_AC +#if SEND_MITSUBISHI112 + case MITSUBISHI112: + { + IRMitsubishi112 ac(_pin, _inverted, _modulation); + mitsubishi112(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.swingh, send.quiet); + break; + } +#endif // SEND_MITSUBISHI112 +#if SEND_MITSUBISHI136 + case MITSUBISHI136: + { + IRMitsubishi136 ac(_pin, _inverted, _modulation); + mitsubishi136(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.quiet); + break; + } +#endif // SEND_MITSUBISHI136 +#if SEND_MITSUBISHIHEAVY + case MITSUBISHI_HEAVY_88: + { + IRMitsubishiHeavy88Ac ac(_pin, _inverted, _modulation); + mitsubishiHeavy88(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.swingh, send.turbo, send.econo, send.clean); + break; + } + case MITSUBISHI_HEAVY_152: + { + IRMitsubishiHeavy152Ac ac(_pin, _inverted, _modulation); + mitsubishiHeavy152(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.swingh, send.quiet, send.turbo, send.econo, + send.filter, send.clean, send.sleep); + break; + } +#endif // SEND_MITSUBISHIHEAVY +#if SEND_NEOCLIMA + case NEOCLIMA: + { + IRNeoclimaAc ac(_pin, _inverted, _modulation); + neoclima(&ac, on, send.mode, degC, send.fanspeed, send.swingv, + send.swingh, send.turbo, send.light, send.filter, send.sleep); + break; + } +#endif // SEND_NEOCLIMA +#if SEND_PANASONIC_AC + case PANASONIC_AC: + { + IRPanasonicAc ac(_pin, _inverted, _modulation); + panasonic(&ac, (panasonic_ac_remote_model_t)send.model, on, send.mode, + degC, send.fanspeed, send.swingv, send.swingh, send.quiet, + send.turbo, send.clock); + break; + } +#endif // SEND_PANASONIC_AC +#if SEND_SAMSUNG_AC + case SAMSUNG_AC: + { + IRSamsungAc ac(_pin, _inverted, _modulation); + samsung(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.quiet, + send.turbo, send.clean, send.beep, prev->power); + break; + } +#endif // SEND_SAMSUNG_AC +#if SEND_SHARP_AC + case SHARP_AC: + { + IRSharpAc ac(_pin, _inverted, _modulation); + sharp(&ac, on, send.mode, degC, send.fanspeed); + break; + } +#endif // SEND_SHARP_AC +#if SEND_TCL112AC + case TCL112AC: + { + IRTcl112Ac ac(_pin, _inverted, _modulation); + tcl112(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, + send.turbo, send.light, send.econo, send.filter); + break; + } +#endif // SEND_TCL112AC +#if SEND_TECO + case TECO: + { + IRTecoAc ac(_pin, _inverted, _modulation); + teco(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.light, + send.sleep); + break; + } +#endif // SEND_TECO +#if SEND_TOSHIBA_AC + case TOSHIBA_AC: + { + IRToshibaAC ac(_pin, _inverted, _modulation); + toshiba(&ac, on, send.mode, degC, send.fanspeed); + break; + } +#endif // SEND_TOSHIBA_AC +#if SEND_TROTEC + case TROTEC: + { + IRTrotecESP ac(_pin, _inverted, _modulation); + trotec(&ac, on, send.mode, degC, send.fanspeed, send.sleep); + break; + } +#endif // SEND_TROTEC +#if SEND_VESTEL_AC + case VESTEL_AC: + { + IRVestelAc ac(_pin, _inverted, _modulation); + vestel(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.turbo, + send.filter, send.sleep, send.clock); + break; + } +#endif // SEND_VESTEL_AC +#if SEND_WHIRLPOOL_AC + case WHIRLPOOL_AC: + { + IRWhirlpoolAc ac(_pin, _inverted, _modulation); + whirlpool(&ac, (whirlpool_ac_remote_model_t)send.model, on, send.mode, + degC, send.fanspeed, send.swingv, send.turbo, send.light, + send.sleep, send.clock); + break; + } +#endif // SEND_WHIRLPOOL_AC + default: + return false; // Fail, didn't match anything. + } + return true; // Success. +} + +// Send an A/C message based soley on our internal state. +// +// Returns: +// boolean: True, if accepted/converted/attempted. False, if unsupported. +bool IRac::sendAc(void) { + bool success = this->sendAc(next, &_prev); + _prev = next; + return success; } // Compare two AirCon states. @@ -1356,21 +1597,29 @@ bool IRac::cmpStates(const stdAc::state_t a, const stdAc::state_t b) { a.clean != b.clean || a.beep != b.beep || a.sleep != b.sleep; } +bool IRac::hasStateChanged(void) { return cmpStates(next, _prev); } + stdAc::opmode_t IRac::strToOpmode(const char *str, const stdAc::opmode_t def) { - if (!strcasecmp(str, "AUTO") || !strcasecmp(str, "AUTOMATIC")) + if (!strcasecmp(str, kAutoStr.c_str()) || + !strcasecmp(str, kAutomaticStr.c_str())) return stdAc::opmode_t::kAuto; - else if (!strcasecmp(str, "OFF") || !strcasecmp(str, "STOP")) + else if (!strcasecmp(str, kOffStr.c_str()) || + !strcasecmp(str, kStopStr.c_str())) return stdAc::opmode_t::kOff; - else if (!strcasecmp(str, "COOL") || !strcasecmp(str, "COOLING")) + else if (!strcasecmp(str, kCoolStr.c_str()) || + !strcasecmp(str, "COOLING")) return stdAc::opmode_t::kCool; - else if (!strcasecmp(str, "HEAT") || !strcasecmp(str, "HEATING")) + else if (!strcasecmp(str, kHeatStr.c_str()) || + !strcasecmp(str, "HEATING")) return stdAc::opmode_t::kHeat; - else if (!strcasecmp(str, "DRY") || !strcasecmp(str, "DRYING") || + else if (!strcasecmp(str, kDryStr.c_str()) || + !strcasecmp(str, "DRYING") || !strcasecmp(str, "DEHUMIDIFY")) return stdAc::opmode_t::kDry; - else if (!strcasecmp(str, "FAN") || !strcasecmp(str, "FANONLY") || - !strcasecmp(str, "FAN_ONLY")) + else if (!strcasecmp(str, kFanStr.c_str()) || + !strcasecmp(str, "FANONLY") || + !strcasecmp(str, kFanOnlyStr.c_str())) return stdAc::opmode_t::kFan; else return def; @@ -1378,20 +1627,26 @@ stdAc::opmode_t IRac::strToOpmode(const char *str, stdAc::fanspeed_t IRac::strToFanspeed(const char *str, const stdAc::fanspeed_t def) { - if (!strcasecmp(str, "AUTO") || !strcasecmp(str, "AUTOMATIC")) + if (!strcasecmp(str, kAutoStr.c_str()) || + !strcasecmp(str, kAutomaticStr.c_str())) return stdAc::fanspeed_t::kAuto; - else if (!strcasecmp(str, "MIN") || !strcasecmp(str, "MINIMUM") || - !strcasecmp(str, "LOWEST")) + else if (!strcasecmp(str, kMinStr.c_str()) || + !strcasecmp(str, kMinimumStr.c_str()) || + !strcasecmp(str, kLowestStr.c_str())) return stdAc::fanspeed_t::kMin; - else if (!strcasecmp(str, "LOW")) + else if (!strcasecmp(str, kLowStr.c_str()) || + !strcasecmp(str, kLoStr.c_str())) return stdAc::fanspeed_t::kLow; - else if (!strcasecmp(str, "MED") || !strcasecmp(str, "MEDIUM") || - !strcasecmp(str, "MID")) + else if (!strcasecmp(str, kMedStr.c_str()) || + !strcasecmp(str, kMediumStr.c_str()) || + !strcasecmp(str, kMidStr.c_str())) return stdAc::fanspeed_t::kMedium; - else if (!strcasecmp(str, "HIGH") || !strcasecmp(str, "HI")) + else if (!strcasecmp(str, kHighStr.c_str()) || + !strcasecmp(str, kHiStr.c_str())) return stdAc::fanspeed_t::kHigh; - else if (!strcasecmp(str, "MAX") || !strcasecmp(str, "MAXIMUM") || - !strcasecmp(str, "HIGHEST")) + else if (!strcasecmp(str, kMaxStr.c_str()) || + !strcasecmp(str, kMaximumStr.c_str()) || + !strcasecmp(str, kHighestStr.c_str())) return stdAc::fanspeed_t::kMax; else return def; @@ -1399,26 +1654,36 @@ stdAc::fanspeed_t IRac::strToFanspeed(const char *str, stdAc::swingv_t IRac::strToSwingV(const char *str, const stdAc::swingv_t def) { - if (!strcasecmp(str, "AUTO") || !strcasecmp(str, "AUTOMATIC") || - !strcasecmp(str, "ON") || !strcasecmp(str, "SWING")) + if (!strcasecmp(str, kAutoStr.c_str()) || + !strcasecmp(str, kAutomaticStr.c_str()) || + !strcasecmp(str, kOnStr.c_str()) || + !strcasecmp(str, kSwingStr.c_str())) return stdAc::swingv_t::kAuto; - else if (!strcasecmp(str, "OFF") || !strcasecmp(str, "STOP")) + else if (!strcasecmp(str, kOffStr.c_str()) || + !strcasecmp(str, kStopStr.c_str())) return stdAc::swingv_t::kOff; - else if (!strcasecmp(str, "MIN") || !strcasecmp(str, "MINIMUM") || - !strcasecmp(str, "LOWEST") || !strcasecmp(str, "BOTTOM") || - !strcasecmp(str, "DOWN")) + else if (!strcasecmp(str, kMinStr.c_str()) || + !strcasecmp(str, kMinimumStr.c_str()) || + !strcasecmp(str, kLowestStr.c_str()) || + !strcasecmp(str, kBottomStr.c_str()) || + !strcasecmp(str, kDownStr.c_str())) return stdAc::swingv_t::kLowest; - else if (!strcasecmp(str, "LOW")) + else if (!strcasecmp(str, kLowStr.c_str())) return stdAc::swingv_t::kLow; - else if (!strcasecmp(str, "MID") || !strcasecmp(str, "MIDDLE") || - !strcasecmp(str, "MED") || !strcasecmp(str, "MEDIUM") || - !strcasecmp(str, "CENTRE") || !strcasecmp(str, "CENTER")) + else if (!strcasecmp(str, kMidStr.c_str()) || + !strcasecmp(str, kMiddleStr.c_str()) || + !strcasecmp(str, kMedStr.c_str()) || + !strcasecmp(str, kMediumStr.c_str()) || + !strcasecmp(str, kCentreStr.c_str())) return stdAc::swingv_t::kMiddle; - else if (!strcasecmp(str, "HIGH") || !strcasecmp(str, "HI")) + else if (!strcasecmp(str, kHighStr.c_str()) || + !strcasecmp(str, kHiStr.c_str())) return stdAc::swingv_t::kHigh; - else if (!strcasecmp(str, "HIGHEST") || !strcasecmp(str, "MAX") || - !strcasecmp(str, "MAXIMUM") || !strcasecmp(str, "TOP") || - !strcasecmp(str, "UP")) + else if (!strcasecmp(str, kHighestStr.c_str()) || + !strcasecmp(str, kMaxStr.c_str()) || + !strcasecmp(str, kMaximumStr.c_str()) || + !strcasecmp(str, kTopStr.c_str()) || + !strcasecmp(str, kUpStr.c_str())) return stdAc::swingv_t::kHighest; else return def; @@ -1426,34 +1691,40 @@ stdAc::swingv_t IRac::strToSwingV(const char *str, stdAc::swingh_t IRac::strToSwingH(const char *str, const stdAc::swingh_t def) { - if (!strcasecmp(str, "AUTO") || !strcasecmp(str, "AUTOMATIC") || - !strcasecmp(str, "ON") || !strcasecmp(str, "SWING")) + if (!strcasecmp(str, kAutoStr.c_str()) || + !strcasecmp(str, kAutomaticStr.c_str()) || + !strcasecmp(str, kOnStr.c_str()) || !strcasecmp(str, kSwingStr.c_str())) return stdAc::swingh_t::kAuto; - else if (!strcasecmp(str, "OFF") || !strcasecmp(str, "STOP")) + else if (!strcasecmp(str, kOffStr.c_str()) || + !strcasecmp(str, kStopStr.c_str())) return stdAc::swingh_t::kOff; - else if (!strcasecmp(str, "LEFTMAX") || !strcasecmp(str, "LEFT MAX") || - !strcasecmp(str, "MAXLEFT") || !strcasecmp(str, "MAX LEFT") || - !strcasecmp(str, "FARLEFT") || !strcasecmp(str, "FAR LEFT")) + else if (!strcasecmp(str, kLeftMaxStr.c_str()) || + !strcasecmp(str, D_STR_LEFT " " D_STR_MAX) || + !strcasecmp(str, D_STR_MAX D_STR_LEFT) || + !strcasecmp(str, kMaxLeftStr.c_str())) return stdAc::swingh_t::kLeftMax; - else if (!strcasecmp(str, "LEFT")) + else if (!strcasecmp(str, kLeftStr.c_str())) return stdAc::swingh_t::kLeft; - else if (!strcasecmp(str, "MID") || !strcasecmp(str, "MIDDLE") || - !strcasecmp(str, "MED") || !strcasecmp(str, "MEDIUM") || - !strcasecmp(str, "CENTRE") || !strcasecmp(str, "CENTER")) + else if (!strcasecmp(str, kMidStr.c_str()) || + !strcasecmp(str, kMiddleStr.c_str()) || + !strcasecmp(str, kMedStr.c_str()) || + !strcasecmp(str, kMediumStr.c_str()) || + !strcasecmp(str, kCentreStr.c_str())) return stdAc::swingh_t::kMiddle; - else if (!strcasecmp(str, "RIGHT")) + else if (!strcasecmp(str, kRightStr.c_str())) return stdAc::swingh_t::kRight; - else if (!strcasecmp(str, "RIGHTMAX") || !strcasecmp(str, "RIGHT MAX") || - !strcasecmp(str, "MAXRIGHT") || !strcasecmp(str, "MAX RIGHT") || - !strcasecmp(str, "FARRIGHT") || !strcasecmp(str, "FAR RIGHT")) + else if (!strcasecmp(str, kRightMaxStr.c_str()) || + !strcasecmp(str, D_STR_MAX " " D_STR_RIGHT) || + !strcasecmp(str, D_STR_MAX D_STR_RIGHT) || + !strcasecmp(str, kMaxRightStr.c_str())) return stdAc::swingh_t::kRightMax; - else if (!strcasecmp(str, "WIDE")) + else if (!strcasecmp(str, kWideStr.c_str())) return stdAc::swingh_t::kWide; else return def; } -// Assumes str is the model or an integer >= 1. +// Assumes str is the model code or an integer >= 1. int16_t IRac::strToModel(const char *str, const int16_t def) { // Gree if (!strcasecmp(str, "YAW1F")) { @@ -1469,6 +1740,8 @@ int16_t IRac::strToModel(const char *str, const int16_t def) { return fujitsu_ac_remote_model_t::ARREB1E; } else if (!strcasecmp(str, "ARJW2")) { return fujitsu_ac_remote_model_t::ARJW2; + } else if (!strcasecmp(str, "ARRY4")) { + return fujitsu_ac_remote_model_t::ARRY4; // Panasonic A/C families } else if (!strcasecmp(str, "LKE") || !strcasecmp(str, "PANASONICLKE")) { return panasonic_ac_remote_model_t::kPanasonicLke; @@ -1498,99 +1771,103 @@ int16_t IRac::strToModel(const char *str, const int16_t def) { } bool IRac::strToBool(const char *str, const bool def) { - if (!strcasecmp(str, "ON") || !strcasecmp(str, "1") || - !strcasecmp(str, "YES") || !strcasecmp(str, "TRUE")) + if (!strcasecmp(str, kOnStr.c_str()) || + !strcasecmp(str, "1") || + !strcasecmp(str, kYesStr.c_str()) || + !strcasecmp(str, kTrueStr.c_str())) return true; - else if (!strcasecmp(str, "OFF") || !strcasecmp(str, "0") || - !strcasecmp(str, "NO") || !strcasecmp(str, "FALSE")) + else if (!strcasecmp(str, kOffStr.c_str()) || + !strcasecmp(str, "0") || + !strcasecmp(str, kNoStr.c_str()) || + !strcasecmp(str, kFalseStr.c_str())) return false; else return def; } String IRac::boolToString(const bool value) { - return value ? F("on") : F("off"); + return value ? kOnStr : kOffStr; } String IRac::opmodeToString(const stdAc::opmode_t mode) { switch (mode) { case stdAc::opmode_t::kOff: - return F("off"); + return kOffStr; case stdAc::opmode_t::kAuto: - return F("auto"); + return kAutoStr; case stdAc::opmode_t::kCool: - return F("cool"); + return kCoolStr; case stdAc::opmode_t::kHeat: - return F("heat"); + return kHeatStr; case stdAc::opmode_t::kDry: - return F("dry"); + return kDryStr; case stdAc::opmode_t::kFan: - return F("fan_only"); + return kFanOnlyStr; default: - return F("unknown"); + return kUnknownStr; } } String IRac::fanspeedToString(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kAuto: - return F("auto"); + return kAutoStr; case stdAc::fanspeed_t::kMax: - return F("max"); + return kMaxStr; case stdAc::fanspeed_t::kHigh: - return F("high"); + return kHighStr; case stdAc::fanspeed_t::kMedium: - return F("medium"); + return kMediumStr; case stdAc::fanspeed_t::kLow: - return F("low"); + return kLowStr; case stdAc::fanspeed_t::kMin: - return F("min"); + return kMinStr; default: - return F("unknown"); + return kUnknownStr; } } String IRac::swingvToString(const stdAc::swingv_t swingv) { switch (swingv) { case stdAc::swingv_t::kOff: - return F("off"); + return kOffStr; case stdAc::swingv_t::kAuto: - return F("auto"); + return kAutoStr; case stdAc::swingv_t::kHighest: - return F("highest"); + return kHighestStr; case stdAc::swingv_t::kHigh: - return F("high"); + return kHighStr; case stdAc::swingv_t::kMiddle: - return F("middle"); + return kMiddleStr; case stdAc::swingv_t::kLow: - return F("low"); + return kLowStr; case stdAc::swingv_t::kLowest: - return F("lowest"); + return kLowestStr; default: - return F("unknown"); + return kUnknownStr; } } String IRac::swinghToString(const stdAc::swingh_t swingh) { switch (swingh) { case stdAc::swingh_t::kOff: - return F("off"); + return kOffStr; case stdAc::swingh_t::kAuto: - return F("auto"); + return kAutoStr; case stdAc::swingh_t::kLeftMax: - return F("leftmax"); + return kLeftMaxStr; case stdAc::swingh_t::kLeft: - return F("left"); + return kLeftStr; case stdAc::swingh_t::kMiddle: - return F("middle"); + return kMiddleStr; case stdAc::swingh_t::kRight: - return F("right"); + return kRightStr; case stdAc::swingh_t::kRightMax: - return F("rightmax"); + return kRightMaxStr; case stdAc::swingh_t::kWide: - return F("wide"); + return kWideStr; default: - return F("unknown"); + return kUnknownStr; } } @@ -1630,6 +1907,13 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_DAIKIN128 +#if DECODE_DAIKIN152 + case decode_type_t::DAIKIN152: { + IRDaikin152 ac(0); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_DAIKIN152 #if DECODE_DAIKIN160 case decode_type_t::DAIKIN160: { IRDaikin160 ac(0); @@ -1686,6 +1970,20 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_MITSUBISHI_AC +#if DECODE_MITSUBISHI112 + case decode_type_t::MITSUBISHI112: { + IRMitsubishi112 ac(0); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_MITSUBISHI112 +#if DECODE_MITSUBISHI136 + case decode_type_t::MITSUBISHI136: { + IRMitsubishi136 ac(0); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_MITSUBISHI136 #if DECODE_MITSUBISHIHEAVY case decode_type_t::MITSUBISHI_HEAVY_88: { IRMitsubishiHeavy88Ac ac(0); @@ -1771,6 +2069,7 @@ namespace IRAcUtils { #if DECODE_COOLIX case decode_type_t::COOLIX: { IRCoolixAC ac(0); + ac.on(); ac.setRaw(result->value); // Coolix uses value instead of state. return ac.toString(); } @@ -1792,6 +2091,13 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_HITACHI_AC +#if DECODE_HITACHI_AC424 + case decode_type_t::HITACHI_AC424: { + IRHitachiAc424 ac(0); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_HITACHI_AC424 #if DECODE_WHIRLPOOL_AC case decode_type_t::WHIRLPOOL_AC: { IRWhirlpoolAc ac(0); @@ -1870,6 +2176,22 @@ namespace IRAcUtils { break; } #endif // DECODE_DAIKIN +#if DECODE_DAIKIN128 + case decode_type_t::DAIKIN128: { + IRDaikin128 ac(0); + ac.setRaw(decode->state); + *result = ac.toCommon(); + break; + } +#endif // DECODE_DAIKIN128 +#if DECODE_DAIKIN152 + case decode_type_t::DAIKIN152: { + IRDaikin152 ac(0); + ac.setRaw(decode->state); + *result = ac.toCommon(); + break; + } +#endif // DECODE_DAIKIN152 #if DECODE_DAIKIN160 case decode_type_t::DAIKIN160: { IRDaikin160 ac(kGpioUnused); @@ -1958,6 +2280,14 @@ namespace IRAcUtils { break; } #endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC2) +#if DECODE_HITACHI_AC424 + case decode_type_t::HITACHI_AC424: { + IRHitachiAc424 ac(kGpioUnused); + ac.setRaw(decode->state); + *result = ac.toCommon(); + break; + } +#endif // DECODE_HITACHI_AC424 #if DECODE_KELVINATOR case decode_type_t::KELVINATOR: { IRKelvinatorAC ac(kGpioUnused); @@ -1982,6 +2312,22 @@ namespace IRAcUtils { break; } #endif // DECODE_MITSUBISHI_AC +#if DECODE_MITSUBISHI112 + case decode_type_t::MITSUBISHI112: { + IRMitsubishi112 ac(kGpioUnused); + ac.setRaw(decode->state); + *result = ac.toCommon(); + break; + } +#endif // DECODE_MITSUBISHI112 +#if DECODE_MITSUBISHI136 + case decode_type_t::MITSUBISHI136: { + IRMitsubishi136 ac(kGpioUnused); + ac.setRaw(decode->state); + *result = ac.toCommon(); + break; + } +#endif // DECODE_MITSUBISHI136 #if DECODE_MITSUBISHIHEAVY case decode_type_t::MITSUBISHI_HEAVY_88: { IRMitsubishiHeavy88Ac ac(kGpioUnused); diff --git a/lib/IRremoteESP8266-2.6.5/src/IRac.h b/lib/IRremoteESP8266-2.7.0/src/IRac.h old mode 100755 new mode 100644 similarity index 84% rename from lib/IRremoteESP8266-2.6.5/src/IRac.h rename to lib/IRremoteESP8266-2.7.0/src/IRac.h index 73ee4b2a3..2fae0084a --- a/lib/IRremoteESP8266-2.6.5/src/IRac.h +++ b/lib/IRremoteESP8266-2.7.0/src/IRac.h @@ -41,6 +41,20 @@ class IRac { explicit IRac(const uint16_t pin, const bool inverted = false, const bool use_modulation = true); static bool isProtocolSupported(const decode_type_t protocol); + static void initState(stdAc::state_t *state, + const decode_type_t vendor, const int16_t model, + const bool power, const stdAc::opmode_t mode, + const float degrees, const bool celsius, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool econo, + const bool light, const bool filter, const bool clean, + const bool beep, const int16_t sleep, + const int16_t clock); + static void initState(stdAc::state_t *state); + bool sendAc(void); + bool sendAc(const stdAc::state_t desired, const stdAc::state_t *prev = NULL); bool sendAc(const decode_type_t vendor, const int16_t model, const bool power, const stdAc::opmode_t mode, const float degrees, const bool celsius, const stdAc::fanspeed_t fan, @@ -49,7 +63,6 @@ class IRac { const bool light, const bool filter, const bool clean, const bool beep, const int16_t sleep = -1, const int16_t clock = -1); - bool sendAc(const stdAc::state_t desired, const stdAc::state_t *prev = NULL); static bool cmpStates(const stdAc::state_t a, const stdAc::state_t b); static bool strToBool(const char *str, const bool def = false); static int16_t strToModel(const char *str, const int16_t def = -1); @@ -67,6 +80,10 @@ class IRac { static String fanspeedToString(const stdAc::fanspeed_t speed); static String swingvToString(const stdAc::swingv_t swingv); static String swinghToString(const stdAc::swingh_t swingh); + stdAc::state_t getState(void); + stdAc::state_t getStatePrev(void); + bool hasStateChanged(void); + stdAc::state_t next; // The state we want the device to be in after we send. #ifndef UNIT_TEST private: @@ -74,6 +91,7 @@ class IRac { uint16_t _pin; bool _inverted; bool _modulation; + stdAc::state_t _prev; // The state we expect the device to currently be in. #if SEND_AMCOR void amcor(IRAmcorAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, @@ -110,6 +128,13 @@ class IRac { const bool econo, const int16_t sleep = -1, const int16_t clock = -1); #endif // SEND_DAIKIN128 +#if SEND_DAIKIN152 + void daikin152(IRDaikin152 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const bool quiet, const bool turbo, const bool econo); +#endif // SEND_DAIKIN152 #if SEND_DAIKIN160 void daikin160(IRDaikin160 *ac, const bool on, const stdAc::opmode_t mode, @@ -151,7 +176,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 bool econo); + const bool quiet, const bool turbo, const bool econo, + const bool filter, const bool clean); #endif // SEND_FUJITSU_AC #if SEND_GOODWEATHER void goodweather(IRGoodweatherAc *ac, @@ -190,6 +216,11 @@ void electra(IRElectraAc *ac, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh); #endif // SEND_HITACHI_AC +#if SEND_HITACHI_AC424 + void hitachi424(IRHitachiAc424 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan); +#endif // SEND_HITACHI_AC424 #if SEND_KELVINATOR void kelvinator(IRKelvinatorAC *ac, const bool on, const stdAc::opmode_t mode, @@ -212,6 +243,20 @@ void electra(IRElectraAc *ac, const stdAc::swingh_t swingh, const bool quiet, const int16_t clock = -1); #endif // SEND_MITSUBISHI_AC +#if SEND_MITSUBISHI112 + void mitsubishi112(IRMitsubishi112 *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); +#endif // SEND_MITSUBISHI112 +#if SEND_MITSUBISHI136 + void mitsubishi136(IRMitsubishi136 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const bool quiet); +#endif // SEND_MITSUBISHI136 #if SEND_MITSUBISHIHEAVY void mitsubishiHeavy88(IRMitsubishiHeavy88Ac *ac, const bool on, const stdAc::opmode_t mode, @@ -247,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 bool quiet, const bool turbo, const bool clean, - const bool beep, const bool dopower = true); + const bool beep, const bool prevpower = true, + const bool forcepower = true); #endif // SEND_SAMSUNG_AC #if SEND_SHARP_AC void sharp(IRSharpAc *ac, diff --git a/lib/IRremoteESP8266-2.6.5/src/IRrecv.cpp b/lib/IRremoteESP8266-2.7.0/src/IRrecv.cpp old mode 100755 new mode 100644 similarity index 98% rename from lib/IRremoteESP8266-2.6.5/src/IRrecv.cpp rename to lib/IRremoteESP8266-2.7.0/src/IRrecv.cpp index 739ced38f..c2c1b5394 --- a/lib/IRremoteESP8266-2.6.5/src/IRrecv.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/IRrecv.cpp @@ -560,11 +560,16 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { DPRINTLN("Attempting Haier AC YR-W02 decode"); if (decodeHaierACYRW02(results)) return true; #endif +#if DECODE_HITACHI_AC424 + // HitachiAc424 should be checked before HitachiAC & HitachiAC2 + DPRINTLN("Attempting Hitachi AC 424 decode"); + if (decodeHitachiAc424(results, kHitachiAc424Bits)) return true; +#endif // DECODE_HITACHI_AC2 #if DECODE_HITACHI_AC2 // HitachiAC2 should be checked before HitachiAC DPRINTLN("Attempting Hitachi AC2 decode"); if (decodeHitachiAC(results, kHitachiAc2Bits)) return true; -#endif +#endif // DECODE_HITACHI_AC2 #if DECODE_HITACHI_AC DPRINTLN("Attempting Hitachi AC decode"); if (decodeHitachiAC(results, kHitachiAcBits)) return true; @@ -607,10 +612,11 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { DPRINTLN("Attempting Vestel AC decode"); if (decodeVestelAc(results)) return true; #endif -#if DECODE_TCL112AC - DPRINTLN("Attempting TCL112AC decode"); - if (decodeTcl112Ac(results)) return true; -#endif +#if DECODE_MITSUBISHI112 || DECODE_TCL112AC + // Mitsubish112 and Tcl112 share the same decoder. + DPRINTLN("Attempting Mitsubishi112/TCL112AC decode"); + if (decodeMitsubishi112(results)) return true; +#endif // DECODE_MITSUBISHI112 || DECODE_TCL112AC #if DECODE_TECO DPRINTLN("Attempting Teco decode"); if (decodeTeco(results)) return true; @@ -669,6 +675,11 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { DPRINTLN("Attempting Daikin152 decode"); if (decodeDaikin152(results)) return true; #endif // DECODE_DAIKIN152 +#if DECODE_MITSUBISHI136 + DPRINTLN("Attempting Mitsubishi136 decode"); + if (decodeMitsubishi136(results)) return true; +#endif // DECODE_MITSUBISHI136 + // Typically new protocols are added above this line. #if DECODE_HASH // decodeHash returns a hash on any input. // Thus, it needs to be last in the list. diff --git a/lib/IRremoteESP8266-2.6.5/src/IRrecv.h b/lib/IRremoteESP8266-2.7.0/src/IRrecv.h old mode 100755 new mode 100644 similarity index 96% rename from lib/IRremoteESP8266-2.6.5/src/IRrecv.h rename to lib/IRremoteESP8266-2.7.0/src/IRrecv.h index 72c168269..2424f0463 --- a/lib/IRremoteESP8266-2.6.5/src/IRrecv.h +++ b/lib/IRremoteESP8266-2.7.0/src/IRrecv.h @@ -254,6 +254,16 @@ class IRrecv { uint16_t nbits = kMitsubishiACBits, bool strict = false); #endif +#if DECODE_MITSUBISHI136 + bool decodeMitsubishi136(decode_results *results, + const uint16_t nbits = kMitsubishi136Bits, + const bool strict = true); +#endif +#if DECODE_MITSUBISHI112 + bool decodeMitsubishi112(decode_results *results, + const uint16_t nbits = kMitsubishi112Bits, + const bool strict = true); +#endif #if DECODE_MITSUBISHIHEAVY bool decodeMitsubishiHeavy(decode_results *results, const uint16_t nbits, const bool strict = true); @@ -436,6 +446,11 @@ class IRrecv { const uint16_t nbits = kHitachiAc1Bits, const bool strict = true); #endif +#if DECODE_HITACHI_AC424 + bool decodeHitachiAc424(decode_results *results, + const uint16_t nbits = kHitachiAc424Bits, + const bool strict = true); +#endif // DECODE_HITACHI_AC424 #if DECODE_GICABLE bool decodeGICable(decode_results *results, uint16_t nbits = kGicableBits, bool strict = true); @@ -472,11 +487,6 @@ class IRrecv { const uint16_t nbits = kVestelAcBits, const bool strict = true); #endif -#if DECODE_TCL112AC - bool decodeTcl112Ac(decode_results *results, - const uint16_t nbits = kTcl112AcBits, - const bool strict = true); -#endif #if DECODE_TECO bool decodeTeco(decode_results *results, const uint16_t nbits = kTecoBits, const bool strict = false); diff --git a/lib/IRremoteESP8266-2.6.5/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.7.0/src/IRremoteESP8266.h old mode 100755 new mode 100644 similarity index 95% rename from lib/IRremoteESP8266-2.6.5/src/IRremoteESP8266.h rename to lib/IRremoteESP8266-2.7.0/src/IRremoteESP8266.h index 0e1f00fa3..19e44d2fd --- a/lib/IRremoteESP8266-2.6.5/src/IRremoteESP8266.h +++ b/lib/IRremoteESP8266-2.7.0/src/IRremoteESP8266.h @@ -36,6 +36,7 @@ * Carrier & Haier AC code by crankyoldgit * Vestel AC code by Erdem U. Altınyurt * Teco AC code by Fabien Valthier (hcoohb) + * Mitsubishi 112 AC Code by kuchel77 * * GPL license, all text above must be included in any redistribution ****************************************************/ @@ -51,7 +52,13 @@ #endif // UNIT_TEST // Library Version -#define _IRREMOTEESP8266_VERSION_ "2.6.5" +#define _IRREMOTEESP8266_VERSION_ "2.7.0" + +// Set the language & locale for the library. See the `locale` dir for options. +#ifndef _IR_LOCALE_ +#define _IR_LOCALE_ en-AU +#endif // _IR_LOCALE_ + // 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! @@ -132,6 +139,12 @@ #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 @@ -255,6 +268,9 @@ #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) @@ -448,6 +464,15 @@ #define DECODE_DAIKIN128 false #define SEND_DAIKIN128 true +#define DECODE_AMCOR false +#define SEND_AMCOR true + +#define DECODE_DAIKIN152 false +#define SEND_DAIKIN152 true + +#define DECODE_HITACHI_AC424 false +#define SEND_HITACHI_AC424 true + #endif // defined(FIRMWARE_IR) || defined(FIRMWARE_IR_CUSTOM) // full IR protocols #if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \ @@ -459,7 +484,8 @@ DECODE_VESTEL_AC || DECODE_TCL112AC || DECODE_MITSUBISHIHEAVY || \ DECODE_DAIKIN216 || DECODE_SHARP_AC || DECODE_DAIKIN160 || \ DECODE_NEOCLIMA || DECODE_DAIKIN176 || DECODE_DAIKIN128 || \ - DECODE_AMCOR || DECODE_DAIKIN152) + DECODE_AMCOR || DECODE_DAIKIN152 || DECODE_MITSUBISHI136 || \ + DECODE_MITSUBISHI112 || DECODE_HITACHI_AC424) #define DECODE_AC true // We need some common infrastructure for decoding A/Cs. #else #define DECODE_AC false // We don't need that infrastructure. @@ -549,8 +575,11 @@ enum decode_type_t { DAIKIN128, AMCOR, DAIKIN152, // 70 + MITSUBISHI136, + MITSUBISHI112, + HITACHI_AC424, // Add new entries before this one, and update it to point to the last entry. - kLastDecodeType = DAIKIN152, + kLastDecodeType = HITACHI_AC424, }; // Message lengths & required repeat values @@ -625,6 +654,8 @@ const uint16_t kHitachiAc1StateLength = 13; const uint16_t kHitachiAc1Bits = kHitachiAc1StateLength * 8; const uint16_t kHitachiAc2StateLength = 53; const uint16_t kHitachiAc2Bits = kHitachiAc2StateLength * 8; +const uint16_t kHitachiAc424StateLength = 53; +const uint16_t kHitachiAc424Bits = kHitachiAc424StateLength * 8; const uint16_t kInaxBits = 24; const uint16_t kInaxMinRepeat = kSingleRepeat; const uint16_t kJvcBits = 16; @@ -648,6 +679,12 @@ const uint16_t kMitsubishiMinRepeat = kSingleRepeat; const uint16_t kMitsubishiACStateLength = 18; const uint16_t kMitsubishiACBits = kMitsubishiACStateLength * 8; const uint16_t kMitsubishiACMinRepeat = kSingleRepeat; +const uint16_t kMitsubishi136StateLength = 17; +const uint16_t kMitsubishi136Bits = kMitsubishi136StateLength * 8; +const uint16_t kMitsubishi136MinRepeat = kNoRepeat; +const uint16_t kMitsubishi112StateLength = 14; +const uint16_t kMitsubishi112Bits = kMitsubishi112StateLength * 8; +const uint16_t kMitsubishi112MinRepeat = kNoRepeat; const uint16_t kMitsubishiHeavy88StateLength = 11; const uint16_t kMitsubishiHeavy88Bits = kMitsubishiHeavy88StateLength * 8; const uint16_t kMitsubishiHeavy88MinRepeat = kNoRepeat; diff --git a/lib/IRremoteESP8266-2.6.5/src/IRsend.cpp b/lib/IRremoteESP8266-2.7.0/src/IRsend.cpp old mode 100755 new mode 100644 similarity index 98% rename from lib/IRremoteESP8266-2.6.5/src/IRsend.cpp rename to lib/IRremoteESP8266-2.7.0/src/IRsend.cpp index b094fdff5..18e2eb559 --- a/lib/IRremoteESP8266-2.6.5/src/IRsend.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/IRsend.cpp @@ -608,10 +608,16 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { return kHitachiAc1Bits; case HITACHI_AC2: return kHitachiAc2Bits; + case HITACHI_AC424: + return kHitachiAc424Bits; case KELVINATOR: return kKelvinatorBits; case MITSUBISHI_AC: return kMitsubishiACBits; + case MITSUBISHI136: + return kMitsubishi136Bits; + case MITSUBISHI112: + return kMitsubishi112Bits; case MITSUBISHI_HEAVY_152: return kMitsubishiHeavy152Bits; case MITSUBISHI_HEAVY_88: @@ -930,6 +936,11 @@ bool IRsend::send(const decode_type_t type, const unsigned char *state, sendHitachiAC2(state, nbytes); break; #endif // SEND_HITACHI_AC2 +#if SEND_HITACHI_AC424 + case HITACHI_AC424: + sendHitachiAc424(state, nbytes); + break; +#endif // SEND_HITACHI_AC424 #if SEND_KELVINATOR case KELVINATOR: sendKelvinator(state, nbytes); @@ -940,6 +951,16 @@ bool IRsend::send(const decode_type_t type, const unsigned char *state, sendMitsubishiAC(state, nbytes); break; #endif // SEND_MITSUBISHI_AC +#if SEND_MITSUBISHI136 + case MITSUBISHI136: + sendMitsubishi136(state, nbytes); + break; +#endif // SEND_MITSUBISHI136 +#if SEND_MITSUBISHI112 + case MITSUBISHI112: + sendMitsubishi112(state, nbytes); + break; +#endif // SEND_MITSUBISHI112 #if SEND_MITSUBISHIHEAVY case MITSUBISHI_HEAVY_88: sendMitsubishiHeavy88(state, nbytes); diff --git a/lib/IRremoteESP8266-2.6.5/src/IRsend.h b/lib/IRremoteESP8266-2.7.0/src/IRsend.h old mode 100755 new mode 100644 similarity index 92% rename from lib/IRremoteESP8266-2.6.5/src/IRsend.h rename to lib/IRremoteESP8266-2.7.0/src/IRsend.h index cbccee479..b0956e77c --- a/lib/IRremoteESP8266-2.6.5/src/IRsend.h +++ b/lib/IRremoteESP8266-2.7.0/src/IRsend.h @@ -112,6 +112,36 @@ namespace stdAc { } state_t; }; // namespace stdAc + +enum fujitsu_ac_remote_model_t { + ARRAH2E = 1, // (1) AR-RAH2E, AR-RAC1E, AR-RAE1E (Default) + ARDB1, // (2) AR-DB1, AR-DL10 (AR-DL10 swing doesn't work) + ARREB1E, // (3) AR-REB1E + ARJW2, // (4) AR-JW2 (Same as ARDB1 but with horiz control) + ARRY4, // (5) AR-RY4 (Same as AR-RAH2E but with clean & filter) +}; + +enum gree_ac_remote_model_t { + YAW1F = 1, // (1) Ultimate, EKOKAI, RusClimate (Default) + YBOFB, // (2) Green, YBOFB2, YAPOF3 +}; + +enum panasonic_ac_remote_model_t { + kPanasonicUnknown = 0, + kPanasonicLke = 1, + kPanasonicNke = 2, + kPanasonicDke = 3, + kPanasonicJke = 4, + kPanasonicCkp = 5, + kPanasonicRkr = 6, +}; + +enum whirlpool_ac_remote_model_t { + DG11J13A = 1, // DG11J1-04 too + DG11J191, +}; + + // Classes class IRsend { public: @@ -275,6 +305,16 @@ class IRsend { void sendMitsubishi(uint64_t data, uint16_t nbits = kMitsubishiBits, uint16_t repeat = kMitsubishiMinRepeat); #endif +#if SEND_MITSUBISHI136 + void sendMitsubishi136(const unsigned char data[], + const uint16_t nbytes = kMitsubishi136StateLength, + const uint16_t repeat = kMitsubishi136MinRepeat); +#endif +#if SEND_MITSUBISHI112 + void sendMitsubishi112(const unsigned char data[], + const uint16_t nbytes = kMitsubishi112StateLength, + const uint16_t repeat = kMitsubishi112MinRepeat); +#endif #if SEND_MITSUBISHI2 void sendMitsubishi2(uint64_t data, uint16_t nbits = kMitsubishiBits, uint16_t repeat = kMitsubishiMinRepeat); @@ -417,13 +457,18 @@ class IRsend { #if SEND_HITACHI_AC1 void sendHitachiAC1(const unsigned char data[], const uint16_t nbytes = kHitachiAc1StateLength, - const uint16_t repeat = kNoRepeat); + const uint16_t repeat = kHitachiAcDefaultRepeat); #endif #if SEND_HITACHI_AC2 void sendHitachiAC2(const unsigned char data[], const uint16_t nbytes = kHitachiAc2StateLength, - const uint16_t repeat = kNoRepeat); + const uint16_t repeat = kHitachiAcDefaultRepeat); #endif +#if SEND_HITACHI_AC424 + void sendHitachiAc424(const unsigned char data[], + const uint16_t nbytes = kHitachiAc424StateLength, + const uint16_t repeat = kHitachiAcDefaultRepeat); +#endif // SEND_HITACHI_AC424 #if SEND_GICABLE void sendGICable(uint64_t data, uint16_t nbits = kGicableBits, uint16_t repeat = kGicableMinRepeat); diff --git a/lib/IRremoteESP8266-2.7.0/src/IRtext.cpp b/lib/IRremoteESP8266-2.7.0/src/IRtext.cpp new file mode 100644 index 000000000..f7702db9b --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/IRtext.cpp @@ -0,0 +1,149 @@ +// Copyright 2019 - David Conran (@crankyoldgit) + +#ifndef UNIT_TEST +#include +#endif // UNIT_TEST +#include "IRremoteESP8266.h" +#include "i18n.h" + +// Common + +String kUnknownStr = D_STR_UNKNOWN; +String kProtocolStr = D_STR_PROTOCOL; +String kPowerStr = D_STR_POWER; +String kOnStr = D_STR_ON; +String kOffStr = D_STR_OFF; +String kModeStr = D_STR_MODE; +String kToggleStr = D_STR_TOGGLE; +String kTurboStr = D_STR_TURBO; +String kSuperStr = D_STR_SUPER; +String kSleepStr = D_STR_SLEEP; +String kLightStr = D_STR_LIGHT; +String kPowerfulStr = D_STR_POWERFUL; +String kQuietStr = D_STR_QUIET; +String kEconoStr = D_STR_ECONO; +String kSwingStr = D_STR_SWING; +String kSwingHStr = D_STR_SWINGH; +String kSwingVStr = D_STR_SWINGV; +String kBeepStr = D_STR_BEEP; +String kZoneFollowStr = D_STR_ZONEFOLLOW; +String kFixedStr = D_STR_FIXED; +String kMouldStr = D_STR_MOULD; +String kCleanStr = D_STR_CLEAN; +String kPurifyStr = D_STR_PURIFY; +String kTimerStr = D_STR_TIMER; +String kOnTimerStr = D_STR_ONTIMER; +String kOffTimerStr = D_STR_OFFTIMER; +String kClockStr = D_STR_CLOCK; +String kCommandStr = D_STR_COMMAND; +String kXFanStr = D_STR_XFAN; +String kHealthStr = D_STR_HEALTH; +String kModelStr = D_STR_MODEL; +String kTempStr = D_STR_TEMP; +String kIFeelStr = D_STR_IFEEL; +String kHumidStr = D_STR_HUMID; +String kSaveStr = D_STR_SAVE; +String kEyeStr = D_STR_EYE; +String kFollowStr = D_STR_FOLLOW; +String kIonStr = D_STR_ION; +String kFreshStr = D_STR_FRESH; +String kHoldStr = D_STR_HOLD; +String kButtonStr = D_STR_BUTTON; +String k8CHeatStr = D_STR_8C_HEAT; +String kNightStr = D_STR_NIGHT; +String kSilentStr = D_STR_SILENT; +String kFilterStr = D_STR_FILTER; +String k3DStr = D_STR_3D; +String kCelsiusStr = D_STR_CELSIUS; +String kTempUpStr = D_STR_TEMPUP; +String kTempDownStr = D_STR_TEMPDOWN; +String kStartStr = D_STR_START; +String kStopStr = D_STR_STOP; +String kMoveStr = D_STR_MOVE; +String kSetStr = D_STR_SET; +String kCancelStr = D_STR_CANCEL; +String kUpStr = D_STR_UP; +String kDownStr = D_STR_DOWN; +String kChangeStr = D_STR_CHANGE; +String kComfortStr = D_STR_COMFORT; +String kSensorStr = D_STR_SENSOR; +String kWeeklyTimerStr = D_STR_WEEKLYTIMER; +String kWifiStr = D_STR_WIFI; +String kLastStr = D_STR_LAST; +String kFastStr = D_STR_FAST; +String kSlowStr = D_STR_SLOW; +String kAirFlowStr = D_STR_AIRFLOW; +String kStepStr = D_STR_STEP; +String kNAStr = D_STR_NA; +String kOutsideStr = D_STR_OUTSIDE; +String kLoudStr = D_STR_LOUD; +String kLowerStr = D_STR_LOWER; +String kUpperStr = D_STR_UPPER; +String kBreezeStr = D_STR_BREEZE; +String kCirculateStr = D_STR_CIRCULATE; +String kCeilingStr = D_STR_CEILING; +String kWallStr = D_STR_WALL; +String kRoomStr = D_STR_ROOM; +String k6thSenseStr = D_STR_6THSENSE; + +String kAutoStr = D_STR_AUTO; +String kAutomaticStr = D_STR_AUTOMATIC; +String kManualStr = D_STR_MANUAL; +String kCoolStr = D_STR_COOL; +String kHeatStr = D_STR_HEAT; +String kFanStr = D_STR_FAN; +String kDryStr = D_STR_DRY; +String kFanOnlyStr = D_STR_FANONLY; + +String kMaxStr = D_STR_MAX; +String kMaximumStr = D_STR_MAXIMUM; +String kMinStr = D_STR_MIN; +String kMinimumStr = D_STR_MINIMUM; +String kMedStr = D_STR_MED; +String kMediumStr = D_STR_MEDIUM; + +String kHighestStr = D_STR_HIGHEST; +String kHighStr = D_STR_HIGH; +String kHiStr = D_STR_HI; +String kMidStr = D_STR_MID; +String kMiddleStr = D_STR_MIDDLE; +String kLowStr = D_STR_LOW; +String kLoStr = D_STR_LO; +String kLowestStr = D_STR_LOWEST; +String kMaxRightStr = D_STR_MAXRIGHT; +String kRightMaxStr = D_STR_RIGHTMAX_NOSPACE; +String kRightStr = D_STR_RIGHT; +String kLeftStr = D_STR_LEFT; +String kMaxLeftStr = D_STR_MAXLEFT; +String kLeftMaxStr = D_STR_LEFTMAX_NOSPACE; +String kWideStr = D_STR_WIDE; +String kCentreStr = D_STR_CENTRE; +String kTopStr = D_STR_TOP; +String kBottomStr = D_STR_BOTTOM; + +String kSpaceLBraceStr = D_STR_SPACELBRACE; +String kCommaSpaceStr = D_STR_COMMASPACE; +String kColonSpaceStr = D_STR_COLONSPACE; + +// IRutils +// - Time +char kTimeSep = D_CHR_TIME_SEP; +String kDayStr = D_STR_DAY; +String kDaysStr = D_STR_DAYS; +String kHourStr = D_STR_HOUR; +String kHoursStr = D_STR_HOURS; +String kMinuteStr = D_STR_MINUTE; +String kMinutesStr = D_STR_MINUTES; +String kSecondStr = D_STR_SECOND; +String kSecondsStr = D_STR_SECONDS; +String kNowStr = D_STR_NOW; +String kThreeLetterDayOfWeekStr = D_STR_THREELETTERDAYS; + +String kYesStr = D_STR_YES; +String kNoStr = D_STR_NO; +String kTrueStr = D_STR_TRUE; +String kFalseStr = D_STR_FALSE; + +String kRepeatStr = D_STR_REPEAT; +String kCodeStr = D_STR_CODE; +String kBitsStr = D_STR_BITS; diff --git a/lib/IRremoteESP8266-2.7.0/src/IRtext.h b/lib/IRremoteESP8266-2.7.0/src/IRtext.h new file mode 100644 index 000000000..526290c1c --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/IRtext.h @@ -0,0 +1,146 @@ +// Copyright 2019 - David Conran (@crankyoldgit) +// This header file is to be included in files **other than** 'IRtext.cpp'. +// +// WARNING: Do not edit this file! This file is automatically generated by +// 'tools/generate_irtext_h.sh'. + +#ifndef IRTEXT_H_ +#define IRTEXT_H_ + +#include "i18n.h" + +// Constant text to be shared across all object files. +// This means there is only one copy of the character/string/text etc. + +extern const char kTimeSep; +extern const String k3DStr; +extern const String k6thSenseStr; +extern const String k8CHeatStr; +extern const String kAirFlowStr; +extern const String kAutomaticStr; +extern const String kAutoStr; +extern const String kBeepStr; +extern const String kBitsStr; +extern const String kBottomStr; +extern const String kBreezeStr; +extern const String kButtonStr; +extern const String kCancelStr; +extern const String kCeilingStr; +extern const String kCelsiusStr; +extern const String kCentreStr; +extern const String kChangeStr; +extern const String kCirculateStr; +extern const String kCleanStr; +extern const String kClockStr; +extern const String kCodeStr; +extern const String kColonSpaceStr; +extern const String kComfortStr; +extern const String kCommandStr; +extern const String kCommaSpaceStr; +extern const String kCoolStr; +extern const String kDaysStr; +extern const String kDayStr; +extern const String kDownStr; +extern const String kDryStr; +extern const String kEconoStr; +extern const String kEyeStr; +extern const String kFalseStr; +extern const String kFanOnlyStr; +extern const String kFanStr; +extern const String kFastStr; +extern const String kFilterStr; +extern const String kFixedStr; +extern const String kFollowStr; +extern const String kFreshStr; +extern const String kHealthStr; +extern const String kHeatStr; +extern const String kHighestStr; +extern const String kHighStr; +extern const String kHiStr; +extern const String kHoldStr; +extern const String kHoursStr; +extern const String kHourStr; +extern const String kHumidStr; +extern const String kIFeelStr; +extern const String kIonStr; +extern const String kLastStr; +extern const String kLeftMaxStr; +extern const String kLeftStr; +extern const String kLightStr; +extern const String kLoStr; +extern const String kLoudStr; +extern const String kLowerStr; +extern const String kLowestStr; +extern const String kLowStr; +extern const String kManualStr; +extern const String kMaximumStr; +extern const String kMaxLeftStr; +extern const String kMaxRightStr; +extern const String kMaxStr; +extern const String kMediumStr; +extern const String kMedStr; +extern const String kMiddleStr; +extern const String kMidStr; +extern const String kMinimumStr; +extern const String kMinStr; +extern const String kMinutesStr; +extern const String kMinuteStr; +extern const String kModelStr; +extern const String kModeStr; +extern const String kMouldStr; +extern const String kMoveStr; +extern const String kNAStr; +extern const String kNightStr; +extern const String kNoStr; +extern const String kNowStr; +extern const String kOffStr; +extern const String kOffTimerStr; +extern const String kOnStr; +extern const String kOnTimerStr; +extern const String kOutsideStr; +extern const String kPowerfulStr; +extern const String kPowerStr; +extern const String kProtocolStr; +extern const String kPurifyStr; +extern const String kQuietStr; +extern const String kRepeatStr; +extern const String kRightMaxStr; +extern const String kRightStr; +extern const String kRoomStr; +extern const String kSaveStr; +extern const String kSecondsStr; +extern const String kSecondStr; +extern const String kSensorStr; +extern const String kSetStr; +extern const String kSilentStr; +extern const String kSleepStr; +extern const String kSlowStr; +extern const String kSpaceLBraceStr; +extern const String kStartStr; +extern const String kStepStr; +extern const String kStopStr; +extern const String kSuperStr; +extern const String kSwingHStr; +extern const String kSwingStr; +extern const String kSwingVStr; +extern const String kTempDownStr; +extern const String kTempStr; +extern const String kTempUpStr; +extern const String kThreeLetterDayOfWeekStr; +extern const String kTimerStr; +extern const String kToggleStr; +extern const String kTopStr; +extern const String kTrueStr; +extern const String kTurboStr; +extern const String kUnknownStr; +extern const String kUpperStr; +extern const String kUpStr; +extern const String kWallStr; +extern const String kWeeklyTimerStr; +extern const String kWideStr; +extern const String kWifiStr; +extern const String kXFanStr; +extern const String kYesStr; +extern const String kZoneFollowStr; + +#endif // IRTEXT_H_ diff --git a/lib/IRremoteESP8266-2.6.5/src/IRtimer.cpp b/lib/IRremoteESP8266-2.7.0/src/IRtimer.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/IRtimer.cpp rename to lib/IRremoteESP8266-2.7.0/src/IRtimer.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/IRtimer.h b/lib/IRremoteESP8266-2.7.0/src/IRtimer.h old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/IRtimer.h rename to lib/IRremoteESP8266-2.7.0/src/IRtimer.h diff --git a/lib/IRremoteESP8266-2.6.5/src/IRutils.cpp b/lib/IRremoteESP8266-2.7.0/src/IRutils.cpp old mode 100755 new mode 100644 similarity index 70% rename from lib/IRremoteESP8266-2.6.5/src/IRutils.cpp rename to lib/IRremoteESP8266-2.7.0/src/IRutils.cpp index 6f589aa3d..76a3db307 --- a/lib/IRremoteESP8266-2.6.5/src/IRutils.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/IRutils.cpp @@ -14,6 +14,8 @@ #endif #include "IRrecv.h" #include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRtext.h" // Reverse the order of the requested least significant nr. of bits. // Args: @@ -89,7 +91,7 @@ void serialPrintUint64(uint64_t input, uint8_t base) { // Returns: // A decode_type_t enum. decode_type_t strToDecodeType(const char * const str) { - if (!strcasecmp(str, "UNKNOWN")) + if (!strcasecmp(str, kUnknownStr.c_str())) return decode_type_t::UNKNOWN; else if (!strcasecmp(str, "UNUSED")) return decode_type_t::UNUSED; @@ -143,6 +145,8 @@ decode_type_t strToDecodeType(const char * const str) { return decode_type_t::HITACHI_AC1; else if (!strcasecmp(str, "HITACHI_AC2")) return decode_type_t::HITACHI_AC2; + else if (!strcasecmp(str, "HITACHI_AC424")) + return decode_type_t::HITACHI_AC424; else if (!strcasecmp(str, "INAX")) return decode_type_t::INAX; else if (!strcasecmp(str, "JVC")) @@ -169,6 +173,10 @@ decode_type_t strToDecodeType(const char * const str) { return decode_type_t::MITSUBISHI2; else if (!strcasecmp(str, "MITSUBISHI_AC")) return decode_type_t::MITSUBISHI_AC; + else if (!strcasecmp(str, "MITSUBISHI136")) + return decode_type_t::MITSUBISHI136; + else if (!strcasecmp(str, "MITSUBISHI112")) + return decode_type_t::MITSUBISHI112; else if (!strcasecmp(str, "MITSUBISHI_HEAVY_88")) return decode_type_t::MITSUBISHI_HEAVY_88; else if (!strcasecmp(str, "MITSUBISHI_HEAVY_152")) @@ -330,6 +338,9 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) { case HITACHI_AC2: result = F("HITACHI_AC2"); break; + case HITACHI_AC424: + result = F("HITACHI_AC424"); + break; case INAX: result = F("INAX"); break; @@ -369,6 +380,12 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) { case MITSUBISHI_AC: result = F("MITSUBISHI_AC"); break; + case MITSUBISHI136: + result = F("MITSUBISHI136"); + break; + case MITSUBISHI112: + result = F("MITSUBISHI112"); + break; case MITSUBISHI_HEAVY_88: result = F("MITSUBISHI_HEAVY_88"); break; @@ -467,10 +484,10 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) { break; case UNKNOWN: default: - result = F("UNKNOWN"); + result = kUnknownStr; break; } - if (isRepeat) result += F(" (Repeat)"); + if (isRepeat) result += kSpaceLBraceStr + kRepeatStr + ')'; return result; } @@ -494,7 +511,10 @@ bool hasACState(const decode_type_t protocol) { case HITACHI_AC: case HITACHI_AC1: case HITACHI_AC2: + case HITACHI_AC424: case KELVINATOR: + case MITSUBISHI136: + case MITSUBISHI112: case MITSUBISHI_AC: case MITSUBISHI_HEAVY_88: case MITSUBISHI_HEAVY_152: @@ -555,7 +575,7 @@ String resultToSourceCode(const decode_results * const results) { } output += uint64ToString(usecs, 10); if (i < results->rawlen - 1) - output += F(", "); // ',' not needed on the last one + output += kCommaSpaceStr; // ',' not needed on the last one if (i % 2 == 0) output += ' '; // Extra if it was even. } @@ -582,7 +602,7 @@ String resultToSourceCode(const decode_results * const results) { output += F("0x"); if (results->state[i] < 0x10) output += '0'; output += uint64ToString(results->state[i], 16); - if (i < nbytes - 1) output += F(", "); + if (i < nbytes - 1) output += kCommaSpaceStr; } output += F("};\n"); #endif // DECODE_AC @@ -630,7 +650,7 @@ String resultToTimingInfo(const decode_results * const results) { while (value.length() < 6) value = ' ' + value; output += value; if (i < results->rawlen - 1) - output += F(", "); // ',' not needed for last one + output += kCommaSpaceStr; // ',' not needed for last one if (!(i % 8)) output += '\n'; // Newline every 8 entries. } output += '\n'; @@ -640,9 +660,9 @@ String resultToTimingInfo(const decode_results * const results) { // Convert the decode_results structure's value/state to simple hexadecimal. // String resultToHexidecimal(const decode_results * const result) { - String output = ""; + String output = F("0x"); // Reserve some space for the string to reduce heap fragmentation. - output.reserve(2 * kStateSizeMax); // Should cover worst cases. + output.reserve(2 * kStateSizeMax + 2); // Should cover worst cases. if (hasACState(result->decode_type)) { #if DECODE_AC for (uint16_t i = 0; result->bits > i * 8; i++) { @@ -663,16 +683,16 @@ String resultToHumanReadableBasic(const decode_results * const results) { // Reserve some space for the string to reduce heap fragmentation. output.reserve(2 * kStateSizeMax + 50); // Should cover most cases. // Show Encoding standard - output += F("Encoding : "); + output += kProtocolStr + F(" : "); output += typeToString(results->decode_type, results->repeat); output += '\n'; // Show Code & length - output += F("Code : "); + output += kCodeStr + F(" : "); output += resultToHexidecimal(results); - output += F(" ("); + output += kSpaceLBraceStr; output += uint64ToString(results->bits); - output += F(" bits)\n"); + output += ' ' + kBitsStr + F(")\n"); return output; } @@ -778,15 +798,15 @@ namespace irutils { String addLabeledString(const String value, const String label, const bool precomma) { String result = ""; - if (precomma) result += F(", "); + if (precomma) result += kCommaSpaceStr; result += label; - result += F(": "); + result += kColonSpaceStr; return result + value; } String addBoolToString(const bool value, const String label, const bool precomma) { - return addLabeledString((value ? F("On") : F("Off")), label, precomma); + return addLabeledString((value ? kOnStr : kOffStr), label, precomma); } String addIntToString(const uint16_t value, const String label, @@ -794,9 +814,58 @@ namespace irutils { return addLabeledString(uint64ToString(value), label, precomma); } + String modelToStr(const decode_type_t protocol, const int16_t model) { + switch (protocol) { + case decode_type_t::GREE: + switch (model) { + case gree_ac_remote_model_t::YAW1F: return F("YAW1F"); + case gree_ac_remote_model_t::YBOFB: return F("YBOFB"); + default: return kUnknownStr; + } + break; + case decode_type_t::FUJITSU_AC: + switch (model) { + case fujitsu_ac_remote_model_t::ARRAH2E: return F("ARRAH2E"); + case fujitsu_ac_remote_model_t::ARDB1: return F("ARDB1"); + case fujitsu_ac_remote_model_t::ARREB1E: return F("ARREB1E"); + case fujitsu_ac_remote_model_t::ARJW2: return F("ARJW2"); + case fujitsu_ac_remote_model_t::ARRY4: return F("ARRY4"); + default: return kUnknownStr; + } + break; + case decode_type_t::PANASONIC_AC: + switch (model) { + case panasonic_ac_remote_model_t::kPanasonicLke: return F("LKE"); + case panasonic_ac_remote_model_t::kPanasonicNke: return F("NKE"); + case panasonic_ac_remote_model_t::kPanasonicDke: return F("DKE"); + case panasonic_ac_remote_model_t::kPanasonicJke: return F("JKE"); + case panasonic_ac_remote_model_t::kPanasonicCkp: return F("CKP"); + case panasonic_ac_remote_model_t::kPanasonicRkr: return F("RKR"); + default: return kUnknownStr; + } + break; + case decode_type_t::WHIRLPOOL_AC: + switch (model) { + case whirlpool_ac_remote_model_t::DG11J13A: return F("DG11J13A"); + case whirlpool_ac_remote_model_t::DG11J191: return F("DG11J191"); + default: return kUnknownStr; + } + break; + default: return kUnknownStr; + } + } + + String addModelToString(const decode_type_t protocol, const int16_t model, + const bool precomma) { + String result = addIntToString(model, kModelStr, precomma); + result += kSpaceLBraceStr; + result += modelToStr(protocol, model); + return result + ')'; + } + String addTempToString(const uint16_t degrees, const bool celsius, const bool precomma) { - String result = addIntToString(degrees, F("Temp"), precomma); + String result = addIntToString(degrees, kTempStr, precomma); result += celsius ? 'C' : 'F'; return result; } @@ -804,30 +873,47 @@ namespace irutils { String addModeToString(const uint8_t mode, const uint8_t automatic, const uint8_t cool, const uint8_t heat, const uint8_t dry, const uint8_t fan) { - String result = addIntToString(mode, F("Mode")); - result += F(" ("); - if (mode == automatic) result += F("AUTO"); - else if (mode == cool) result += F("COOL"); - else if (mode == heat) result += F("HEAT"); - else if (mode == dry) result += F("DRY"); - else if (mode == fan) result += F("FAN"); + String result = addIntToString(mode, kModeStr); + result += kSpaceLBraceStr; + if (mode == automatic) result += kAutoStr; + else if (mode == cool) result += kCoolStr; + else if (mode == heat) result += kHeatStr; + else if (mode == dry) result += kDryStr; + else if (mode == fan) result += kFanStr; else - result += F("UNKNOWN"); + result += kUnknownStr; + return result + ')'; + } + + String addDayToString(const uint8_t day_of_week, const int8_t offset, + const bool precomma) { + String result = addIntToString(day_of_week, kDayStr, precomma); + result += kSpaceLBraceStr; + if ((uint8_t)(day_of_week + offset) < 7) +#if UNIT_TEST + result += kThreeLetterDayOfWeekStr.substr( + (day_of_week + offset) * 3, 3); +#else // UNIT_TEST + result += kThreeLetterDayOfWeekStr.substring( + (day_of_week + offset) * 3, (day_of_week + offset) * 3 + 3); +#endif // UNIT_TEST + else + result += kUnknownStr; return result + ')'; } String addFanToString(const uint8_t speed, const uint8_t high, const uint8_t low, const uint8_t automatic, const uint8_t quiet, const uint8_t medium) { - String result = addIntToString(speed, F("Fan")); - result += F(" ("); - if (speed == high) result += F("High"); - else if (speed == low) result += F("Low"); - else if (speed == automatic) result += F("Auto"); - else if (speed == quiet) result += F("Quiet"); - else if (speed == medium) result += F("Medium"); + String result = addIntToString(speed, kFanStr); + result += kSpaceLBraceStr; + if (speed == high) result += kHighStr; + else if (speed == low) result += kLowStr; + else if (speed == automatic) result += kAutoStr; + else if (speed == quiet) result += kQuietStr; + else if (speed == medium) result += kMediumStr; else - result += F("UNKNOWN"); + result += kUnknownStr; return result + ')'; } @@ -895,7 +981,7 @@ namespace irutils { String msToString(uint32_t const msecs) { uint32_t totalseconds = msecs / 1000; - if (totalseconds == 0) return F("Now"); + if (totalseconds == 0) return kNowStr; // Note: uint32_t can only hold up to 45 days, so uint8_t is safe. uint8_t days = totalseconds / (60 * 60 * 24); @@ -904,24 +990,22 @@ namespace irutils { uint8_t seconds = totalseconds % 60; String result = ""; - if (days) { - result += uint64ToString(days) + F(" day"); - if (days > 1) result += 's'; - } + if (days) + result += uint64ToString(days) + ' ' + ((days > 1) ? kDaysStr : kDayStr); if (hours) { if (result.length()) result += ' '; - result += uint64ToString(hours) + F(" hour"); - if (hours > 1) result += 's'; + result += uint64ToString(hours) + ' ' + ((hours > 1) ? kHoursStr + : kHourStr); } if (minutes) { if (result.length()) result += ' '; - result += uint64ToString(minutes) + F(" minute"); - if (minutes > 1) result += 's'; + result += uint64ToString(minutes) + ' ' + ((minutes > 1) ? kMinutesStr + : kMinuteStr); } if (seconds) { if (result.length()) result += ' '; - result += uint64ToString(seconds) + F(" second"); - if (seconds > 1) result += 's'; + result += uint64ToString(seconds) + ' ' + ((seconds > 1) ? kSecondsStr + : kSecondStr); } return result; } @@ -930,7 +1014,7 @@ namespace irutils { String result = ""; result.reserve(5); // 23:59 is the typical worst case. if (mins / 60 < 10) result += '0'; // Zero pad the hours - result += uint64ToString(mins / 60) + ':'; + result += uint64ToString(mins / 60) + kTimeSep; if (mins % 60 < 10) result += '0'; // Zero pad the minutes. result += uint64ToString(mins % 60); return result; @@ -961,4 +1045,152 @@ namespace irutils { if (integer > 99) return 255; // Too big. return ((integer / 10) << 4) + (integer % 10); } + + // Return the value of `position`th bit of `data`. + // Args: + // data: Value to be examined. + // position: Nr. of the nth bit to be examined. `0` is the LSB. + // size: Nr. of bits in data. + bool getBit(const uint64_t data, const uint8_t position, const uint8_t size) { + if (position >= size) return false; // Outside of range. + return data & (1ULL << position); + } + + // Return the value of `position`th bit of `data`. + // Args: + // data: Value to be examined. + // position: Nr. of the nth bit to be examined. `0` is the LSB. + bool getBit(const uint8_t data, const uint8_t position) { + if (position >= 8) return false; // Outside of range. + return data & (1 << position); + } + + // Return the value of `data` with the `position`th bit changed to `on` + // Args: + // data: Value to be changed. + // position: Nr. of the bit to be changed. `0` is the LSB. + // on: Value to set the position'th bit to. + // size: Nr. of bits in data. + uint64_t setBit(const uint64_t data, const uint8_t position, const bool on, + const uint8_t size) { + if (position >= size) return data; // Outside of range. + uint64_t mask = 1ULL << position; + if (on) + return data | mask; + else + return data & ~mask; + } + + // Return the value of `data` with the `position`th bit changed to `on` + // Args: + // data: Value to be changed. + // position: Nr. of the bit to be changed. `0` is the LSB. + // on: Value to set the position'th bit to. + uint8_t setBit(const uint8_t data, const uint8_t position, const bool on) { + if (position >= 8) return data; // Outside of range. + uint8_t mask = 1 << position; + if (on) + return data | mask; + else + return data & ~mask; + } + + // Change the value at the location `data_ptr` with the `position`th bit + // changed to `on` + // Args: + // data: Ptr to the data to be changed. + // position: Nr. of the bit to be changed. `0` is the LSB. + // on: Value to set the position'th bit to. + void setBit(uint8_t * const data, const uint8_t position, const bool on) { + uint8_t mask = 1 << position; + if (on) + *data |= mask; + else + *data &= ~mask; + } + + // Change the value at the location `data_ptr` with the `position`th bit + // changed to `on` + // Args: + // data: Ptr to the data to be changed. + // position: Nr. of the bit to be changed. `0` is the LSB. + // on: Value to set the position'th bit to. + void setBit(uint32_t * const data, const uint8_t position, const bool on) { + uint32_t mask = (uint32_t)1 << position; + if (on) + *data |= mask; + else + *data &= ~mask; + } + + // Change the value at the location `data_ptr` with the `position`th bit + // changed to `on` + // Args: + // data: Ptr to the data to be changed. + // position: Nr. of the bit to be changed. `0` is the LSB. + // on: Value to set the position'th bit to. + void setBit(uint64_t * const data, const uint8_t position, const bool on) { + uint64_t mask = (uint64_t)1 << position; + if (on) + *data |= mask; + else + *data &= ~mask; + } + + // Change the uint8_t pointed to by `dst` starting at the `offset`th bit + // and for `nbits` bits, with the contents of `data`. + // Args: + // dst: Ptr to the uint8_t to be changed. + // offset: Nr. of bits from the Least Significant Bit to be ignored. + // nbits: Nr of bits of `data` to be placed into the destination uint8_t. + // data: Value to be placed into dst. + void setBits(uint8_t * const dst, const uint8_t offset, const uint8_t nbits, + const uint8_t data) { + if (offset >= 8 || !nbits) return; // Short circuit as it won't change. + // Calculate the mask for the supplied value. + uint8_t mask = UINT8_MAX >> (8 - ((nbits > 8) ? 8 : nbits)); + // Calculate the mask & clear the space for the data. + // Clear the destination bits. + *dst &= ~(uint8_t)(mask << offset); + // Merge in the data. + *dst |= ((data & mask) << offset); + } + + // Change the uint32_t pointed to by `dst` starting at the `offset`th bit + // and for `nbits` bits, with the contents of `data`. + // Args: + // dst: Ptr to the uint32_t to be changed. + // offset: Nr. of bits from the Least Significant Bit to be ignored. + // nbits: Nr of bits of `data` to be placed into the destination uint32_t. + // data: Value to be placed into dst. + void setBits(uint32_t * const dst, const uint8_t offset, const uint8_t nbits, + const uint32_t data) { + if (offset >= 32 || !nbits) return; // Short circuit as it won't change. + // Calculate the mask for the supplied value. + uint32_t mask = UINT32_MAX >> (32 - ((nbits > 32) ? 32 : nbits)); + // Calculate the mask & clear the space for the data. + // Clear the destination bits. + *dst &= ~(mask << offset); + // Merge in the data. + *dst |= ((data & mask) << offset); + } + + // Change the uint64_t pointed to by `dst` starting at the `offset`th bit + // and for `nbits` bits, with the contents of `data`. + // Args: + // dst: Ptr to the uint64_t to be changed. + // offset: Nr. of bits from the Least Significant Bit to be ignored. + // nbits: Nr of bits of `data` to be placed into the destination uint64_t. + // data: Value to be placed into dst. + void setBits(uint64_t * const dst, const uint8_t offset, const uint8_t nbits, + const uint64_t data) { + if (offset >= 64 || !nbits) return; // Short circuit as it won't change. + // Calculate the mask for the supplied value. + uint64_t mask = UINT64_MAX >> (64 - ((nbits > 64) ? 64 : nbits)); + // Calculate the mask & clear the space for the data. + // Clear the destination bits. + *dst &= ~(mask << offset); + // Merge in the data. + *dst |= ((data & mask) << offset); + } } // namespace irutils diff --git a/lib/IRremoteESP8266-2.6.5/src/IRutils.h b/lib/IRremoteESP8266-2.7.0/src/IRutils.h old mode 100755 new mode 100644 similarity index 57% rename from lib/IRremoteESP8266-2.6.5/src/IRutils.h rename to lib/IRremoteESP8266-2.7.0/src/IRutils.h index 8d4226577..34319134a --- a/lib/IRremoteESP8266-2.6.5/src/IRutils.h +++ b/lib/IRremoteESP8266-2.7.0/src/IRutils.h @@ -14,6 +14,10 @@ #include "IRremoteESP8266.h" #include "IRrecv.h" +const uint8_t kNibbleSize = 4; +const uint8_t kLowNibble = 0; +const uint8_t kHighNibble = 4; +const uint8_t kModeBitsSize = 3; uint64_t reverseBits(uint64_t input, uint16_t nbits); String uint64ToString(uint64_t input, uint8_t base = 10); String typeToString(const decode_type_t protocol, @@ -43,6 +47,9 @@ namespace irutils { const bool precomma = true); String addIntToString(const uint16_t value, const String label, const bool precomma = true); + String modelToStr(const decode_type_t protocol, const int16_t model); + String addModelToString(const decode_type_t protocol, const int16_t model, + const bool precomma = true); String addLabeledString(const String value, const String label, const bool precomma = true); String addTempToString(const uint16_t degrees, const bool celsius = true, @@ -53,6 +60,8 @@ namespace irutils { String addFanToString(const uint8_t speed, const uint8_t high, const uint8_t low, const uint8_t automatic, const uint8_t quiet, const uint8_t medium); + String addDayToString(const uint8_t day_of_week, const int8_t offset = 0, + const bool precomma = true); String htmlEscape(const String unescaped); String msToString(uint32_t const msecs); String minsToString(const uint16_t mins); @@ -60,5 +69,39 @@ namespace irutils { const uint8_t init = 0); uint8_t bcdToUint8(const uint8_t bcd); uint8_t uint8ToBcd(const uint8_t integer); + bool getBit(const uint64_t data, const uint8_t position, + const uint8_t size = 64); + bool getBit(const uint8_t data, const uint8_t position); +#define GETBIT8(a, b) (a & ((uint8_t)1 << b)) +#define GETBIT16(a, b) (a & ((uint16_t)1 << b)) +#define GETBIT32(a, b) (a & ((uint32_t)1 << b)) +#define GETBIT64(a, b) (a & ((uint64_t)1 << b)) +#define GETBITS8(data, offset, size) \ + (((data) & (((uint8_t)UINT8_MAX >> (8 - (size))) << (offset))) >> (offset)) +#define GETBITS16(data, offset, size) \ + (((data) & (((uint16_t)UINT16_MAX >> (16 - (size))) << (offset))) >> \ + (offset)) +#define GETBITS32(data, offset, size) \ + (((data) & (((uint32_t)UINT32_MAX >> (32 - (size))) << (offset))) >> \ + (offset)) +#define GETBITS64(data, offset, size) \ + (((data) & (((uint64_t)UINT64_MAX >> (64 - (size))) << (offset))) >> \ + (offset)) + uint64_t setBit(const uint64_t data, const uint8_t position, + const bool on = true, const uint8_t size = 64); + uint8_t setBit(const uint8_t data, const uint8_t position, + const bool on = true); + void setBit(uint8_t * const data, const uint8_t position, + const bool on = true); + void setBit(uint32_t * const data, const uint8_t position, + const bool on = true); + void setBit(uint64_t * const data, const uint8_t position, + const bool on = true); + void setBits(uint8_t * const dst, const uint8_t offset, const uint8_t nbits, + const uint8_t data); + void setBits(uint32_t * const dst, const uint8_t offset, const uint8_t nbits, + const uint32_t data); + void setBits(uint64_t * const dst, const uint8_t offset, const uint8_t nbits, + const uint64_t data); } // namespace irutils #endif // IRUTILS_H_ diff --git a/lib/IRremoteESP8266-2.7.0/src/i18n.h b/lib/IRremoteESP8266-2.7.0/src/i18n.h new file mode 100644 index 000000000..27ac4d714 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/i18n.h @@ -0,0 +1,25 @@ +// Copyright 2019 - David Conran (@crankyoldgit) + +#ifndef I18N_H_ +#define I18N_H_ + +#include "IRremoteESP8266.h" + +// Load the appropriate locale header file. +#ifndef _IR_LOCALE_ +#define _IR_LOCALE_ en-AU +#endif // _IR_LOCALE_ + +#define ENQUOTE_(x) #x +#define ENQUOTE(x) ENQUOTE_(x) + +// Load the desired/requested locale. +#ifdef _IR_LOCALE_ +#include ENQUOTE(locale/_IR_LOCALE_.h) +#endif // _IR_LOCALE_ + +// Now that any specific locale has been loaded, we can safely load the defaults +// as the defaults should not override anything that has now set. +#include "locale/defaults.h" + +#endif // I18N_H_ diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Aiwa.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Aiwa.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Aiwa.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Aiwa.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Amcor.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Amcor.cpp old mode 100755 new mode 100644 similarity index 82% rename from lib/IRremoteESP8266-2.6.5/src/ir_Amcor.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Amcor.cpp index 8c0b73c8c..b36c6d15a --- a/lib/IRremoteESP8266-2.6.5/src/ir_Amcor.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Amcor.cpp @@ -7,8 +7,10 @@ #include "ir_Amcor.h" #include +#include #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Constants @@ -28,6 +30,7 @@ using irutils::addBoolToString; using irutils::addModeToString; using irutils::addFanToString; using irutils::addTempToString; +using irutils::setBits; #if SEND_AMCOR // Send a Amcor HVAC formatted message. @@ -104,8 +107,7 @@ void IRAmcorAc::begin(void) { _irsend.begin(); } #if SEND_AMCOR void IRAmcorAc::send(const uint16_t repeat) { - this->checksum(); // Create valid checksum before sending - _irsend.sendAmcor(remote_state, kAmcorStateLength, repeat); + _irsend.sendAmcor(getRaw(), kAmcorStateLength, repeat); } #endif // SEND_AMCOR @@ -136,7 +138,7 @@ uint8_t* IRAmcorAc::getRaw(void) { } void IRAmcorAc::setRaw(const uint8_t state[]) { - for (uint8_t i = 0; i < kAmcorStateLength; i++) remote_state[i] = state[i]; + memcpy(remote_state, state, kAmcorStateLength); } void IRAmcorAc::on(void) { setPower(true); } @@ -144,49 +146,45 @@ void IRAmcorAc::on(void) { setPower(true); } void IRAmcorAc::off(void) { setPower(false); } void IRAmcorAc::setPower(const bool on) { - remote_state[kAmcorPowerByte] &= ~kAmcorPowerMask; - remote_state[kAmcorPowerByte] |= (on ? kAmcorPowerOn : kAmcorPowerOff); + setBits(&remote_state[kAmcorPowerByte], kAmcorPowerOffset, kAmcorPowerSize, + on ? kAmcorPowerOn : kAmcorPowerOff); } bool IRAmcorAc::getPower(void) { - return ((remote_state[kAmcorPowerByte] & kAmcorPowerMask) == kAmcorPowerOn); + return GETBITS8(remote_state[kAmcorPowerByte], kAmcorPowerOffset, + kAmcorPowerSize) == kAmcorPowerOn; } // Set the temp in deg C void IRAmcorAc::setTemp(const uint8_t degrees) { uint8_t temp = std::max(kAmcorMinTemp, degrees); temp = std::min(kAmcorMaxTemp, temp); - - temp <<= 1; - remote_state[kAmcorTempByte] &= ~kAmcorTempMask; - remote_state[kAmcorTempByte] |= temp; + setBits(&remote_state[kAmcorTempByte], kAmcorTempOffset, kAmcorTempSize, + temp); } uint8_t IRAmcorAc::getTemp(void) { - return (remote_state[kAmcorTempByte] & kAmcorTempMask) >> 1; + return GETBITS8(remote_state[kAmcorTempByte], kAmcorTempOffset, + kAmcorTempSize); } // Maximum Cooling or Hearing void IRAmcorAc::setMax(const bool on) { if (on) { switch (getMode()) { - case kAmcorCool: - setTemp(kAmcorMinTemp); - break; - case kAmcorHeat: - setTemp(kAmcorMaxTemp); - break; - default: // Not allowed in all other operating modes. - return; + case kAmcorCool: setTemp(kAmcorMinTemp); break; + case kAmcorHeat: setTemp(kAmcorMaxTemp); break; + // Not allowed in all other operating modes. + default: return; } - remote_state[kAmcorSpecialByte] |= kAmcorMaxMask; - } else { - remote_state[kAmcorSpecialByte] &= ~kAmcorMaxMask; } + setBits(&remote_state[kAmcorSpecialByte], kAmcorMaxOffset, kAmcorMaxSize, + on ? kAmcorMax : 0); } bool IRAmcorAc::getMax(void) { - return ((remote_state[kAmcorSpecialByte] & kAmcorMaxMask) == kAmcorMaxMask); + return GETBITS8(remote_state[kAmcorSpecialByte], kAmcorMaxOffset, + kAmcorMaxSize) == kAmcorMax; } // Set the speed of the fan @@ -196,8 +194,8 @@ void IRAmcorAc::setFan(const uint8_t speed) { case kAmcorFanMin: case kAmcorFanMed: case kAmcorFanMax: - remote_state[kAmcorModeFanByte] &= ~kAmcorFanMask; - remote_state[kAmcorModeFanByte] |= speed << 4; + setBits(&remote_state[kAmcorModeFanByte], kAmcorFanOffset, kAmcorFanSize, + speed); break; default: setFan(kAmcorFanAuto); @@ -205,27 +203,26 @@ void IRAmcorAc::setFan(const uint8_t speed) { } uint8_t IRAmcorAc::getFan(void) { - return (remote_state[kAmcorModeFanByte] & kAmcorFanMask) >> 4; + return GETBITS8(remote_state[kAmcorModeFanByte], kAmcorFanOffset, + kAmcorFanSize); } uint8_t IRAmcorAc::getMode(void) { - return remote_state[kAmcorModeFanByte] & kAmcorModeMask; + return GETBITS8(remote_state[kAmcorModeFanByte], kAmcorModeOffset, + kAmcorModeSize); } void IRAmcorAc::setMode(const uint8_t mode) { - remote_state[kAmcorSpecialByte] &= ~kAmcorVentMask; // Clear the vent setting switch (mode) { case kAmcorFan: - remote_state[kAmcorSpecialByte] |= kAmcorVentMask; // Set the vent option - // FALL-THRU case kAmcorCool: case kAmcorHeat: case kAmcorDry: case kAmcorAuto: - // Mask out bits - remote_state[kAmcorModeFanByte] &= ~kAmcorModeMask; - // Set the mode at bit positions - remote_state[kAmcorModeFanByte] |= mode; + setBits(&remote_state[kAmcorSpecialByte], kAmcorVentOffset, + kAmcorVentSize, (mode == kAmcorFan) ? kAmcorVentOn : 0); + setBits(&remote_state[kAmcorModeFanByte], kAmcorModeOffset, + kAmcorModeSize, mode); return; default: this->setMode(kAmcorAuto); @@ -311,16 +308,16 @@ stdAc::state_t IRAmcorAc::toCommon(void) { } // Convert the internal state into a human readable string. -String IRAmcorAc::toString() { +String IRAmcorAc::toString(void) { String result = ""; result.reserve(70); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kAmcorAuto, kAmcorCool, kAmcorHeat, kAmcorDry, kAmcorFan); result += addFanToString(getFan(), kAmcorFanMax, kAmcorFanMin, kAmcorFanAuto, kAmcorFanAuto, kAmcorFanMed); result += addTempToString(getTemp()); - result += addBoolToString(getMax(), F("Max")); + result += addBoolToString(getMax(), kMaxStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Amcor.h b/lib/IRremoteESP8266-2.7.0/src/ir_Amcor.h old mode 100755 new mode 100644 similarity index 83% rename from lib/IRremoteESP8266-2.6.5/src/ir_Amcor.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Amcor.h index 73beb27a7..fa8aa1edd --- a/lib/IRremoteESP8266-2.6.5/src/ir_Amcor.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Amcor.h @@ -35,36 +35,44 @@ const uint8_t kAmcorFanMin = 0b001; const uint8_t kAmcorFanMed = 0b010; const uint8_t kAmcorFanMax = 0b011; const uint8_t kAmcorFanAuto = 0b100; -const uint8_t kAmcorFanMask = 0b01110000; +const uint8_t kAmcorFanOffset = 4; +const uint8_t kAmcorFanSize = 3; // Modes const uint8_t kAmcorCool = 0b001; const uint8_t kAmcorHeat = 0b010; const uint8_t kAmcorFan = 0b011; // Aka "Vent" const uint8_t kAmcorDry = 0b100; const uint8_t kAmcorAuto = 0b101; -const uint8_t kAmcorModeMask = 0b00000111; +const uint8_t kAmcorModeOffset = 0; +const uint8_t kAmcorModeSize = 3; // state[2] const uint8_t kAmcorTempByte = 2; // Temperature const uint8_t kAmcorMinTemp = 12; // Celsius const uint8_t kAmcorMaxTemp = 32; // Celsius -const uint8_t kAmcorTempMask = 0b01111110; +const uint8_t kAmcorTempOffset = 1; +const uint8_t kAmcorTempSize = 6; // Bits // state[5] // Power const uint8_t kAmcorPowerByte = 5; -const uint8_t kAmcorPowerMask = 0b11110000; -const uint8_t kAmcorPowerOn = 0b00110000; // 0x30 -const uint8_t kAmcorPowerOff = 0b11000000; // 0xC0 +const uint8_t kAmcorPowerOffset = 4; +const uint8_t kAmcorPowerSize = 4; +const uint8_t kAmcorPowerOn = 0b0011; // 0x3 +const uint8_t kAmcorPowerOff = 0b1100; // 0xC // state[6] const uint8_t kAmcorSpecialByte = 6; // Max Mode (aka "Lo" in Cool and "Hi" in Heat) -const uint8_t kAmcorMaxMask = 0b00000011; // 0x03 -// "Vent" Mode -const uint8_t kAmcorVentMask = 0b11000000; // 0xC0 +const uint8_t kAmcorMax = 0b11; +const uint8_t kAmcorMaxOffset = 0; +const uint8_t kAmcorMaxSize = 2; +// "Vent" Mode +const uint8_t kAmcorVentOn = 0b11; +const uint8_t kAmcorVentOffset = 6; +const uint8_t kAmcorVentSize = 2; // state[7] // Checksum byte. const uint8_t kAmcorChecksumByte = kAmcorStateLength - 1; diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Argo.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Argo.cpp old mode 100755 new mode 100644 similarity index 76% rename from lib/IRremoteESP8266-2.6.5/src/ir_Argo.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Argo.cpp index 522ede7e6..2721d3dc5 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Argo.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Argo.cpp @@ -7,10 +7,12 @@ Copyright 2019 crankyoldgit #include "ir_Argo.h" #include +#include #ifndef UNIT_TEST #include #endif // UNIT_TEST #include "IRremoteESP8266.h" +#include "IRtext.h" #include "IRutils.h" // Constants @@ -27,6 +29,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_ARGO // Send an Argo A/C message. @@ -55,8 +59,7 @@ void IRArgoAC::begin(void) { _irsend.begin(); } #if SEND_ARGO void IRArgoAC::send(const uint16_t repeat) { - this->checksum(); // Create valid checksum before sending - _irsend.sendArgo(argo, kArgoStateLength, repeat); + _irsend.sendArgo(getRaw(), kArgoStateLength, repeat); } #endif // SEND_ARGO @@ -105,73 +108,54 @@ uint8_t* IRArgoAC::getRaw(void) { } void IRArgoAC::setRaw(const uint8_t state[]) { - for (uint8_t i = 0; i < kArgoStateLength; i++) argo[i] = state[i]; + memcpy(argo, state, kArgoStateLength); } -void IRArgoAC::on(void) { - // Bit 5 of byte 9 is on/off - // in MSB first - argo[9]|= kArgoPowerBit; // Set ON/OFF bit to 1 -} +void IRArgoAC::on(void) { setPower(true); } -void IRArgoAC::off(void) { - // in MSB first - // bit 5 of byte 9 to off - argo[9] &= ~kArgoPowerBit; // Set on/off bit to 0 -} +void IRArgoAC::off(void) { setPower(false); } void IRArgoAC::setPower(const bool on) { - if (on) - this->on(); - else - this->off(); + setBit(&argo[9], kArgoPowerBitOffset, on); } -bool IRArgoAC::getPower(void) { return argo[9] & kArgoPowerBit; } +bool IRArgoAC::getPower(void) { return GETBIT8(argo[9], kArgoPowerBitOffset); } void IRArgoAC::setMax(const bool on) { - if (on) - argo[9] |= kArgoMaxBit; - else - argo[9] &= ~kArgoMaxBit; + setBit(&argo[9], kArgoMaxBitOffset, on); } -bool IRArgoAC::getMax(void) { return argo[9] & kArgoMaxBit; } +bool IRArgoAC::getMax(void) { return GETBIT8(argo[9], kArgoMaxBitOffset); } // Set the temp in deg C // Sending 0 equals +4 void IRArgoAC::setTemp(const uint8_t degrees) { uint8_t temp = std::max(kArgoMinTemp, degrees); - temp = std::min(kArgoMaxTemp, temp); - - // offset 4 degrees. "If I want 12 degrees, I need to send 8" - temp -= kArgoTempOffset; + // delta 4 degrees. "If I want 12 degrees, I need to send 8" + temp = std::min(kArgoMaxTemp, temp) - kArgoTempDelta; // Settemp = Bit 6,7 of byte 2, and bit 0-2 of byte 3 // mask out bits // argo[13] & 0x00000100; // mask out ON/OFF Bit - argo[2] &= ~kArgoTempLowMask; - argo[3] &= ~kArgoTempHighMask; - - // append to bit 6,7 - argo[2] += temp << 6; - // remove lowest to bits and append in 0-2 - argo[3] += ((temp >> 2) & kArgoTempHighMask); + setBits(&argo[2], kArgoTempLowOffset, kArgoTempLowSize, temp); + setBits(&argo[3], kArgoTempHighOffset, kArgoTempHighSize, + temp >> kArgoTempLowSize); } uint8_t IRArgoAC::getTemp(void) { - return (((argo[3] & kArgoTempHighMask) << 2 ) | (argo[2] >> 6)) + - kArgoTempOffset; + return ((GETBITS8(argo[3], kArgoTempHighOffset, + kArgoTempHighSize) << kArgoTempLowSize) | + GETBITS8(argo[2], kArgoTempLowOffset, kArgoTempLowSize)) + + kArgoTempDelta; } // Set the speed of the fan void IRArgoAC::setFan(const uint8_t fan) { - // Mask out bits - argo[3] &= ~kArgoFanMask; - // Set fan mode at bit positions - argo[3] |= (std::min(fan, kArgoFan3) << 3); + setBits(&argo[3], kArgoFanOffset, kArgoFanSize, std::min(fan, kArgoFan3)); } -uint8_t IRArgoAC::getFan(void) { return (argo[3] & kArgoFanMask) >> 3; } +uint8_t IRArgoAC::getFan(void) { + return GETBITS8(argo[3], kArgoFanOffset, kArgoFanSize); +} void IRArgoAC::setFlap(const uint8_t flap) { flap_mode = flap; @@ -181,7 +165,7 @@ void IRArgoAC::setFlap(const uint8_t flap) { uint8_t IRArgoAC::getFlap(void) { return flap_mode; } uint8_t IRArgoAC::getMode(void) { - return (argo[2] & kArgoModeMask) >> 3; + return GETBITS8(argo[2], kArgoModeOffset, kArgoModeSize); } void IRArgoAC::setMode(const uint8_t mode) { @@ -192,10 +176,7 @@ void IRArgoAC::setMode(const uint8_t mode) { case kArgoOff: case kArgoHeat: case kArgoHeatAuto: - // Mask out bits - argo[2] &= ~kArgoModeMask; - // Set the mode at bit positions - argo[2] |= ((mode << 3) & kArgoModeMask); + setBits(&argo[2], kArgoModeOffset, kArgoModeSize, mode); return; default: this->setMode(kArgoAuto); @@ -203,24 +184,16 @@ void IRArgoAC::setMode(const uint8_t mode) { } void IRArgoAC::setNight(const bool on) { - if (on) - // Set bit at night position: bit 2 - argo[9] |= kArgoNightBit; - else - argo[9] &= ~kArgoNightBit; + setBit(&argo[9], kArgoNightBitOffset, on); } -bool IRArgoAC::getNight(void) { return argo[9] & kArgoNightBit; } +bool IRArgoAC::getNight(void) { return GETBIT8(argo[9], kArgoNightBitOffset); } void IRArgoAC::setiFeel(const bool on) { - if (on) - // Set bit at iFeel position: bit 7 - argo[9] |= kArgoIFeelBit; - else - argo[9] &= ~kArgoIFeelBit; + setBit(&argo[9], kArgoIFeelBitOffset, on); } -bool IRArgoAC::getiFeel(void) { return argo[9] & kArgoIFeelBit; } +bool IRArgoAC::getiFeel(void) { return GETBIT8(argo[9], kArgoIFeelBitOffset); } void IRArgoAC::setTime(void) { // TODO(kaschmo): use function call from checksum to set time first @@ -228,19 +201,17 @@ void IRArgoAC::setTime(void) { void IRArgoAC::setRoomTemp(const uint8_t degrees) { uint8_t temp = std::min(degrees, kArgoMaxRoomTemp); - temp = std::max(temp, kArgoTempOffset); - temp -= kArgoTempOffset;; - // Mask out bits - argo[3] &= ~kArgoRoomTempLowMask; - argo[4] &= ~kArgoRoomTempHighMask; - - argo[3] += temp << 5; // Append to bit 5,6,7 - argo[4] += temp >> 3; // Remove lowest 3 bits and append in 0,1 + temp = std::max(temp, kArgoTempDelta) - kArgoTempDelta; + setBits(&argo[3], kArgoRoomTempLowOffset, kArgoRoomTempLowSize, temp); + setBits(&argo[4], kArgoRoomTempHighOffset, kArgoRoomTempHighSize, + temp >> kArgoRoomTempLowSize); } uint8_t IRArgoAC::getRoomTemp(void) { - return ((argo[4] & kArgoRoomTempHighMask) << 3 | (argo[3] >> 5)) + - kArgoTempOffset; + return ((GETBITS8(argo[4], kArgoRoomTempHighOffset, + kArgoRoomTempHighSize) << kArgoRoomTempLowSize) | + GETBITS8(argo[3], kArgoRoomTempLowOffset, kArgoRoomTempLowSize)) + + kArgoTempDelta; } // Convert a standard A/C mode into its native mode. @@ -341,56 +312,60 @@ stdAc::state_t IRArgoAC::toCommon(void) { } // Convert the internal state into a human readable string. -String IRArgoAC::toString() { +String IRArgoAC::toString(void) { String result = ""; result.reserve(100); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); - result += addIntToString(getMode(), F("Mode")); + result += addBoolToString(getPower(), kPowerStr, false); + result += addIntToString(getMode(), kModeStr); + result += kSpaceLBraceStr; switch (getMode()) { case kArgoAuto: - result += F(" (AUTO)"); + result += kAutoStr; break; case kArgoCool: - result += F(" (COOL)"); + result += kCoolStr; break; case kArgoHeat: - result += F(" (HEAT)"); + result += kHeatStr; break; case kArgoDry: - result += F(" (DRY)"); + result += kDryStr; break; case kArgoHeatAuto: - result += F(" (HEATAUTO)"); + result += kHeatStr + ' ' + kAutoStr; break; case kArgoOff: - result += F(" (OFF)"); + result += kOffStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } - result += addIntToString(getFan(), F("Fan")); + result += ')'; + result += addIntToString(getFan(), kFanStr); + result += kSpaceLBraceStr; switch (getFan()) { case kArgoFanAuto: - result += F(" (AUTO)"); + result += kAutoStr; break; case kArgoFan3: - result += F(" (MAX)"); + result += kMaxStr; break; case kArgoFan1: - result += F(" (MIN)"); + result += kMinStr; break; case kArgoFan2: - result += F(" (MED)"); + result += kMedStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } + result += ')'; result += addTempToString(getTemp()); - result += F(", Room "); + result += kCommaSpaceStr + kRoomStr + ' '; result += addTempToString(getRoomTemp(), true, false); - result += addBoolToString(getMax(), F("Max")); - result += addBoolToString(getiFeel(), F("iFeel")); - result += addBoolToString(getNight(), F("Night")); + result += addBoolToString(getMax(), kMaxStr); + result += addBoolToString(getiFeel(), kIFeelStr); + result += addBoolToString(getNight(), kNightStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Argo.h b/lib/IRremoteESP8266-2.7.0/src/ir_Argo.h old mode 100755 new mode 100644 similarity index 70% rename from lib/IRremoteESP8266-2.6.5/src/ir_Argo.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Argo.h index 49c8c42e5..3c1281ea3 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Argo.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Argo.h @@ -41,48 +41,64 @@ // byte[2] const uint8_t kArgoHeatBit = 0b00100000; -const uint8_t kArgoModeMask = 0b00111000; -const uint8_t kArgoTempLowMask = 0b11000000; -const uint8_t kArgoCool = 0b000; // 0b000 (LSB) 0 -const uint8_t kArgoDry = 0b001; // 0b100 (LSB) 1 -const uint8_t kArgoAuto = 0b010; // 0b010 (LSB) 2 -const uint8_t kArgoOff = 0b011; // 0b110 (LSB) 3 -const uint8_t kArgoHeat = 0b100; // 0b001 (LSB) 4 -const uint8_t kArgoHeatAuto = 0b101; // 0b101 (LSB) 5 +// kArgoTempLowMask = 0b11000000; +const uint8_t kArgoTempLowOffset = 5; +const uint8_t kArgoTempLowSize = 2; + +// Mode 0b00111000 +const uint8_t kArgoModeOffset = 3; +const uint8_t kArgoModeSize = 3; +const uint8_t kArgoCool = 0b000; +const uint8_t kArgoDry = 0b001; +const uint8_t kArgoAuto = 0b010; +const uint8_t kArgoOff = 0b011; +const uint8_t kArgoHeat = 0b100; +const uint8_t kArgoHeatAuto = 0b101; // ?no idea what mode that is -const uint8_t kArgoHeatBlink = 0b110; // 0b011 (LSB) 6 +const uint8_t kArgoHeatBlink = 0b110; // byte[3] -const uint8_t kArgoTempHighMask = 0b00000111; -const uint8_t kArgoFanMask = 0b00011000; -const uint8_t kArgoRoomTempLowMask = 0b11100000; -const uint8_t kArgoFanAuto = 0; // 0b00 -const uint8_t kArgoFan3 = 3; // 0b11 -const uint8_t kArgoFan2 = 2; // 0b01 -const uint8_t kArgoFan1 = 1; // 0b10 +// kArgoTempHighMask = 0b00000111; +const uint8_t kArgoTempHighOffset = 0; +const uint8_t kArgoTempHighSize = 3; +// Fan 0b00011000 +const uint8_t kArgoFanOffset = 3; +const uint8_t kArgoFanSize = 2; +const uint8_t kArgoFanAuto = 0; // 0b00 +const uint8_t kArgoFan1 = 1; // 0b01 +const uint8_t kArgoFan2 = 2; // 0b10 +const uint8_t kArgoFan3 = 3; // 0b11 +// kArgoRoomTempLowMask = 0b11100000; +const uint8_t kArgoRoomTempLowOffset = 5; +const uint8_t kArgoRoomTempLowSize = 3; // byte[4] -const uint8_t kArgoRoomTempHighMask = 0b00000011; -const uint8_t kArgoTempOffset = 4; -const uint8_t kArgoMaxRoomTemp = ((1 << 5) - 1) + kArgoTempOffset; // 35C +// kArgoRoomTempHighMask = 0b00000011; +const uint8_t kArgoRoomTempHighOffset = 0; +const uint8_t kArgoRoomTempHighSize = 2; + +const uint8_t kArgoTempDelta = 4; +const uint8_t kArgoMaxRoomTemp = + ((1 << (kArgoRoomTempHighSize + kArgoRoomTempLowSize)) - 1) + + kArgoTempDelta; // 35C // byte[9] -const uint8_t kArgoPowerBit = 0b00100000; -const uint8_t kArgoMaxBit = 0b00001000; -const uint8_t kArgoNightBit = 0b00000100; -const uint8_t kArgoIFeelBit = 0b10000000; +const uint8_t kArgoNightBitOffset = 2; +const uint8_t kArgoMaxBitOffset = 3; +const uint8_t kArgoPowerBitOffset = 5; +const uint8_t kArgoIFeelBitOffset = 7; -const uint8_t kArgoMinTemp = 10; // Celsius offset +4 +const uint8_t kArgoMinTemp = 10; // Celsius delta +4 const uint8_t kArgoMaxTemp = 32; // Celsius -const uint8_t kArgoFlapAuto = 0; // 0b000 -const uint8_t kArgoFlap1 = 1; // 0b100 -const uint8_t kArgoFlap2 = 2; // 0b010 -const uint8_t kArgoFlap3 = 3; // 0b110 -const uint8_t kArgoFlap4 = 4; // 0b001 -const uint8_t kArgoFlap5 = 5; // 0b101 -const uint8_t kArgoFlap6 = 6; // 0b011 -const uint8_t kArgoFlapFull = 7; // 0b111 +const uint8_t kArgoFlapAuto = 0; +const uint8_t kArgoFlap1 = 1; +const uint8_t kArgoFlap2 = 2; +const uint8_t kArgoFlap3 = 3; +const uint8_t kArgoFlap4 = 4; +const uint8_t kArgoFlap5 = 5; +const uint8_t kArgoFlap6 = 6; +const uint8_t kArgoFlapFull = 7; // Legacy defines. (Deperecated) #define ARGO_COOL_ON kArgoCoolOn diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Carrier.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Carrier.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Carrier.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Carrier.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Coolix.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Coolix.cpp old mode 100755 new mode 100644 similarity index 73% rename from lib/IRremoteESP8266-2.6.5/src/ir_Coolix.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Coolix.cpp index 616b417ce..2c840fe47 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Coolix.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Coolix.cpp @@ -8,6 +8,7 @@ #endif #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Coolix A/C / heatpump added by (send) bakrus & (decode) crankyoldgit @@ -18,6 +19,7 @@ // Brand: Midea, Model: RG52D/BGE Remote // Brand: Midea, Model: MS12FU-10HRDN1-QRD0GW(B) A/C // Brand: Midea, Model: MSABAU-07HRFN1-QRD0GW A/C (circa 2016) +// Brand: Tokio, Model: AATOEMF17-12CHR1SW split-type RG51|50/BGE Remote // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/484 @@ -44,6 +46,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_COOLIX // Send a Coolix message @@ -100,21 +104,43 @@ IRCoolixAC::IRCoolixAC(const uint16_t pin, const bool inverted, const bool use_modulation) : _irsend(pin, inverted, use_modulation) { stateReset(); } -void IRCoolixAC::stateReset() { setRaw(kCoolixDefaultState); } +void IRCoolixAC::stateReset() { + setRaw(kCoolixDefaultState); + clearSensorTemp(); + powerFlag = false; + turboFlag = false; + ledFlag = false; + cleanFlag = false; + sleepFlag = false; + swingFlag = false; + swingHFlag = false; + swingVFlag = false; +} void IRCoolixAC::begin() { _irsend.begin(); } #if SEND_COOLIX void IRCoolixAC::send(const uint16_t repeat) { _irsend.sendCOOLIX(remote_state, kCoolixBits, repeat); + // make sure to remove special state from remote_state + // after command has being transmitted. + recoverSavedState(); } #endif // SEND_COOLIX uint32_t IRCoolixAC::getRaw() { return remote_state; } void IRCoolixAC::setRaw(const uint32_t new_code) { - remote_state = new_code; - saved_state = new_code; + if (!handleSpecialState(new_code)) { + // it isn`t special so might afect Temp|mode|Fan + if (new_code == kCoolixCmdFan) { + setMode(kCoolixFan); + } else { + // must be a command changing Temp|Mode|Fan + // it is safe to just copy to remote var + remote_state = new_code; + } + } } // Return true if the current state is a special state. @@ -125,13 +151,41 @@ bool IRCoolixAC::isSpecialState(void) { case kCoolixOff: case kCoolixSwing: case kCoolixSleep: - case kCoolixTurbo: - return true; - default: - return false; + case kCoolixTurbo: return true; + default: return false; } } +// Special state means commands that are not +// affecting Temperature/Mode/Fan +bool IRCoolixAC::handleSpecialState(const uint32_t data) { + switch (data) { + case kCoolixClean: + cleanFlag = !cleanFlag; + break; + case kCoolixLed: + ledFlag = !ledFlag; + break; + case kCoolixOff: + powerFlag = false; + break; + case kCoolixSwing: + swingFlag = !swingFlag; + break; + case kCoolixSleep: + sleepFlag = !sleepFlag; + break; + case kCoolixTurbo: + turboFlag = !turboFlag; + break; + default: + return false; + } + return true; +} + +// must be called before every special state +// to make sure the remote_state is safe void IRCoolixAC::updateSavedState(void) { if (!isSpecialState()) saved_state = remote_state; } @@ -144,18 +198,12 @@ void IRCoolixAC::recoverSavedState(void) { if (isSpecialState()) stateReset(); } -uint32_t IRCoolixAC::getNormalState(void) { - return isSpecialState() ? saved_state : remote_state; -} - void IRCoolixAC::setTempRaw(const uint8_t code) { - recoverSavedState(); - remote_state &= ~kCoolixTempMask; // Clear the old temp. - remote_state |= (code << 4); + setBits(&remote_state, kCoolixTempOffset, kCoolixTempSize, code); } uint8_t IRCoolixAC::getTempRaw() { - return (getNormalState() & kCoolixTempMask) >> 4; + return GETBITS32(remote_state, kCoolixTempOffset, kCoolixTempSize); } void IRCoolixAC::setTemp(const uint8_t desired) { @@ -166,17 +214,14 @@ void IRCoolixAC::setTemp(const uint8_t desired) { } uint8_t IRCoolixAC::getTemp() { - uint8_t code = getTempRaw(); - uint8_t i; - for (i = 0; i < kCoolixTempRange; i++) + const uint8_t code = getTempRaw(); + for (uint8_t i = 0; i < kCoolixTempRange; i++) if (kCoolixTempMap[i] == code) return kCoolixTempMin + i; - return kCoolixUnknown; // Not a temp we expected. + return kCoolixTempMax; // Not a temp we expected. } void IRCoolixAC::setSensorTempRaw(const uint8_t code) { - recoverSavedState(); - remote_state &= ~kCoolixSensorTempMask; // Clear previous sensor temp. - remote_state |= ((code & 0xF) << 8); + setBits(&remote_state, kCoolixSensorTempOffset, kCoolixSensorTempSize, code); } void IRCoolixAC::setSensorTemp(const uint8_t desired) { @@ -188,87 +233,89 @@ void IRCoolixAC::setSensorTemp(const uint8_t desired) { } uint8_t IRCoolixAC::getSensorTemp() { - return ((getNormalState() & kCoolixSensorTempMask) >> 8) + - kCoolixSensorTempMin; + return GETBITS32(remote_state, kCoolixSensorTempOffset, + kCoolixSensorTempSize) + kCoolixSensorTempMin; } bool IRCoolixAC::getPower() { // There is only an off state. Everything else is "on". - return remote_state != kCoolixOff; + return powerFlag; } -void IRCoolixAC::setPower(const bool power) { - if (power) { - // There really is no distinct "on" setting, just ensure it a normal state. - recoverSavedState(); +void IRCoolixAC::setPower(const bool on) { + if (powerFlag) { + if (!on) { + updateSavedState(); + remote_state = kCoolixOff; + } } else { - updateSavedState(); - remote_state = kCoolixOff; + if (on) { + // at this point remote_state must be ready + // to be transmitted + recoverSavedState(); + } } + powerFlag = on; } -void IRCoolixAC::on(void) { - this->setPower(true); -} +void IRCoolixAC::on(void) { this->setPower(true); } -void IRCoolixAC::off(void) { - this->setPower(false); -} +void IRCoolixAC::off(void) { this->setPower(false); } -bool IRCoolixAC::getSwing() { return remote_state == kCoolixSwing; } +bool IRCoolixAC::getSwing() { return swingFlag; } void IRCoolixAC::setSwing() { // Assumes that repeated sending "swing" toggles the action on the device. updateSavedState(); remote_state = kCoolixSwing; + swingFlag = !swingFlag; } -bool IRCoolixAC::getSleep() { return remote_state == kCoolixSleep; } +bool IRCoolixAC::getSleep() { return sleepFlag; } void IRCoolixAC::setSleep() { updateSavedState(); remote_state = kCoolixSleep; + sleepFlag = !sleepFlag; } -bool IRCoolixAC::getTurbo() { return remote_state == kCoolixTurbo; } +bool IRCoolixAC::getTurbo() { return turboFlag; } void IRCoolixAC::setTurbo() { // Assumes that repeated sending "turbo" toggles the action on the device. updateSavedState(); remote_state = kCoolixTurbo; + turboFlag = !turboFlag; } -bool IRCoolixAC::getLed() { return remote_state == kCoolixLed; } +bool IRCoolixAC::getLed() { return ledFlag; } void IRCoolixAC::setLed() { // Assumes that repeated sending "Led" toggles the action on the device. updateSavedState(); remote_state = kCoolixLed; + ledFlag = !ledFlag; } -bool IRCoolixAC::getClean() { return remote_state == kCoolixClean; } +bool IRCoolixAC::getClean() { return cleanFlag; } void IRCoolixAC::setClean() { updateSavedState(); remote_state = kCoolixClean; + cleanFlag = !cleanFlag; } bool IRCoolixAC::getZoneFollow() { - return getNormalState() & kCoolixZoneFollowMask; + return zoneFollowFlag; } // Internal use only. -void IRCoolixAC::setZoneFollow(bool state) { - recoverSavedState(); - if (state) { - remote_state |= kCoolixZoneFollowMask; - } else { - remote_state &= ~kCoolixZoneFollowMask; - } +void IRCoolixAC::setZoneFollow(bool on) { + zoneFollowFlag = on; + setBit(&remote_state, kCoolixZoneFollowMaskOffset, on); } void IRCoolixAC::clearSensorTemp() { - recoverSavedState(); setZoneFollow(false); setSensorTempRaw(kCoolixSensorTempIgnoreCode); } @@ -278,43 +325,40 @@ void IRCoolixAC::setMode(const uint8_t mode) { switch (actualmode) { case kCoolixAuto: case kCoolixDry: - if (this->getFan() == kCoolixFanAuto) - // No kCoolixFanAuto in Dry/Auto mode. - this->setFan(kCoolixFanAuto0, false); + setFan(kCoolixFanAuto0, false); break; case kCoolixCool: case kCoolixHeat: case kCoolixFan: - if (this->getFan() == kCoolixFanAuto0) - // kCoolixFanAuto0 only in Dry/Auto mode. - this->setFan(kCoolixFanAuto, false); + setFan(kCoolixFanAuto, false); break; default: // Anything else, go with Auto mode. - this->setMode(kCoolixAuto); + setMode(kCoolixAuto); + setFan(kCoolixFanAuto0, false); return; } - // Fan mode is a special case of Dry. - if (mode == kCoolixFan) actualmode = kCoolixDry; - recoverSavedState(); - remote_state = (remote_state & ~kCoolixModeMask) | (actualmode << 2); - // Force the temp into a known-good state. setTemp(getTemp()); - if (mode == kCoolixFan) setTempRaw(kCoolixFanTempCode); + // Fan mode is a special case of Dry. + if (mode == kCoolixFan) { + actualmode = kCoolixDry; + setTempRaw(kCoolixFanTempCode); + } + setBits(&remote_state, kCoolixModeOffset, kCoolixModeSize, actualmode); } uint8_t IRCoolixAC::getMode() { - uint8_t mode = (getNormalState() & kCoolixModeMask) >> 2; + uint8_t mode = GETBITS32(remote_state, kCoolixModeOffset, + kCoolixModeSize); if (mode == kCoolixDry) if (getTempRaw() == kCoolixFanTempCode) return kCoolixFan; return mode; } uint8_t IRCoolixAC::getFan() { - return (getNormalState() & kCoolixFanMask) >> 13; + return GETBITS32(remote_state, kCoolixFanOffset, kCoolixFanSize); } void IRCoolixAC::setFan(const uint8_t speed, const bool modecheck) { - recoverSavedState(); uint8_t newspeed = speed; switch (speed) { case kCoolixFanAuto: // Dry & Auto mode can't have this speed. @@ -323,6 +367,7 @@ void IRCoolixAC::setFan(const uint8_t speed, const bool modecheck) { case kCoolixAuto: case kCoolixDry: newspeed = kCoolixFanAuto0; + break; } } break; @@ -330,10 +375,8 @@ void IRCoolixAC::setFan(const uint8_t speed, const bool modecheck) { if (modecheck) { switch (this->getMode()) { case kCoolixAuto: - case kCoolixDry: - break; - default: - newspeed = kCoolixFanAuto; + case kCoolixDry: break; + default: newspeed = kCoolixFanAuto; } } break; @@ -345,24 +388,19 @@ void IRCoolixAC::setFan(const uint8_t speed, const bool modecheck) { break; default: // Unknown speed requested. newspeed = kCoolixFanAuto; + break; } - remote_state &= ~kCoolixFanMask; - remote_state |= ((newspeed << 13) & kCoolixFanMask); + setBits(&remote_state, kCoolixFanOffset, kCoolixFanSize, newspeed); } // Convert a standard A/C mode into its native mode. uint8_t IRCoolixAC::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kCoolixCool; - case stdAc::opmode_t::kHeat: - return kCoolixHeat; - case stdAc::opmode_t::kDry: - return kCoolixDry; - case stdAc::opmode_t::kFan: - return kCoolixFan; - default: - return kCoolixAuto; + case stdAc::opmode_t::kCool: return kCoolixCool; + case stdAc::opmode_t::kHeat: return kCoolixHeat; + case stdAc::opmode_t::kDry: return kCoolixDry; + case stdAc::opmode_t::kFan: return kCoolixFan; + default: return kCoolixAuto; } } @@ -370,15 +408,11 @@ uint8_t IRCoolixAC::convertMode(const stdAc::opmode_t mode) { uint8_t IRCoolixAC::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kCoolixFanMin; - case stdAc::fanspeed_t::kMedium: - return kCoolixFanMed; + case stdAc::fanspeed_t::kLow: return kCoolixFanMin; + case stdAc::fanspeed_t::kMedium: return kCoolixFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kCoolixFanMax; - default: - return kCoolixFanAuto; + case stdAc::fanspeed_t::kMax: return kCoolixFanMax; + default: return kCoolixFanAuto; } } @@ -459,69 +493,69 @@ stdAc::state_t IRCoolixAC::toCommon(const stdAc::state_t *prev) { } // Convert the internal state into a human readable string. -String IRCoolixAC::toString() { +String IRCoolixAC::toString(void) { String result = ""; result.reserve(100); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); if (!getPower()) return result; // If it's off, there is no other info. // Special modes. if (getSwing()) { - result += F(", Swing: Toggle"); + result += kCommaSpaceStr + kSwingStr + kColonSpaceStr + kToggleStr; return result; } if (getSleep()) { - result += F(", Sleep: Toggle"); + result += kCommaSpaceStr + kSleepStr + kColonSpaceStr + kToggleStr; return result; } if (getTurbo()) { - result += F(", Turbo: Toggle"); + result += kCommaSpaceStr + kTurboStr + kColonSpaceStr + kToggleStr; return result; } if (getLed()) { - result += F(", Led: Toggle"); + result += kCommaSpaceStr + kLightStr + kColonSpaceStr + kToggleStr; return result; } if (getClean()) { - result += F(", Clean: Toggle"); + result += kCommaSpaceStr + kCleanStr + kColonSpaceStr + kToggleStr; return result; } - result += addModeToString(getMode(), kCoolixAuto, - kCoolixCool, kCoolixHeat, - kCoolixDry, kCoolixFan); - result += addIntToString(getFan(), F("Fan")); + result += addModeToString(getMode(), kCoolixAuto, kCoolixCool, kCoolixHeat, + kCoolixDry, kCoolixFan); + result += addIntToString(getFan(), kFanStr); + result += kSpaceLBraceStr; switch (getFan()) { case kCoolixFanAuto: - result += F(" (AUTO)"); + result += kAutoStr; break; case kCoolixFanAuto0: - result += F(" (AUTO0)"); + result += kAutoStr + '0'; break; case kCoolixFanMax: - result += F(" (MAX)"); + result += kMaxStr; break; case kCoolixFanMin: - result += F(" (MIN)"); + result += kMinStr; break; case kCoolixFanMed: - result += F(" (MED)"); + result += kMedStr; break; case kCoolixFanZoneFollow: - result += F(" (ZONEFOLLOW)"); + result += kZoneFollowStr; break; case kCoolixFanFixed: - result += F(" (FIXED)"); + result += kFixedStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } + result += ')'; // Fan mode doesn't have a temperature. if (getMode() != kCoolixFan) result += addTempToString(getTemp()); - result += addBoolToString(getZoneFollow(), F("Zone Follow")); - result += F(", Sensor Temp: "); - if (getSensorTemp() > kCoolixSensorTempMax) - result += F("Ignored"); - else - result += uint64ToString(getSensorTemp()) + F("C"); + result += addBoolToString(getZoneFollow(), kZoneFollowStr); + result += addLabeledString( + (getSensorTemp() > kCoolixSensorTempMax) + ? kOffStr : uint64ToString(getSensorTemp()) + F("C"), + kSensorStr + ' ' + kTempStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Coolix.h b/lib/IRremoteESP8266-2.7.0/src/ir_Coolix.h old mode 100755 new mode 100644 similarity index 68% rename from lib/IRremoteESP8266-2.6.5/src/ir_Coolix.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Coolix.h index 0c2e44676..c2fb2034d --- a/lib/IRremoteESP8266-2.6.5/src/ir_Coolix.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Coolix.h @@ -22,6 +22,7 @@ // Brand: Midea, Model: RG52D/BGE Remote // Brand: Midea, Model: MS12FU-10HRDN1-QRD0GW(B) A/C // Brand: Midea, Model: MSABAU-07HRFN1-QRD0GW A/C (circa 2016) +// Brand: Tokio, Model: AATOEMF17-12CHR1SW split-type RG51|50/BGE Remote // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/484 // Kudos: @@ -34,9 +35,15 @@ const uint8_t kCoolixDry = 0b001; const uint8_t kCoolixAuto = 0b010; const uint8_t kCoolixHeat = 0b011; const uint8_t kCoolixFan = 0b100; // Synthetic. -const uint32_t kCoolixModeMask = 0b000000000000000000001100; // 0xC -const uint32_t kCoolixZoneFollowMask = 0b000010000000000000000000; // 0x80000 +// const uint32_t kCoolixModeMask = 0b000000000000000000001100; // 0xC +const uint8_t kCoolixModeOffset = 2; +const uint8_t kCoolixModeSize = 2; +// const uint32_t kCoolixZoneFollowMask = 0b000010000000000000000000 0x80000 +const uint8_t kCoolixZoneFollowMaskOffset = 19; // Fan Control +// const uint32_t kCoolixFanMask = 0b000000001110000000000000; // 0x00E000 +const uint8_t kCoolixFanOffset = 13; +const uint8_t kCoolixFanSize = 3; const uint8_t kCoolixFanMin = 0b100; const uint8_t kCoolixFanMed = 0b010; const uint8_t kCoolixFanMax = 0b001; @@ -44,13 +51,14 @@ const uint8_t kCoolixFanAuto = 0b101; const uint8_t kCoolixFanAuto0 = 0b000; const uint8_t kCoolixFanZoneFollow = 0b110; const uint8_t kCoolixFanFixed = 0b111; -const uint32_t kCoolixFanMask = 0b000000001110000000000000; // 0x00E000 // Temperature const uint8_t kCoolixTempMin = 17; // Celsius const uint8_t kCoolixTempMax = 30; // Celsius const uint8_t kCoolixTempRange = kCoolixTempMax - kCoolixTempMin + 1; const uint8_t kCoolixFanTempCode = 0b1110; // Part of Fan Mode. -const uint32_t kCoolixTempMask = 0b11110000; +// const uint32_t kCoolixTempMask = 0b11110000; +const uint8_t kCoolixTempOffset = 4; +const uint8_t kCoolixTempSize = 4; const uint8_t kCoolixTempMap[kCoolixTempRange] = { 0b0000, // 17C 0b0001, // 18c @@ -70,18 +78,23 @@ const uint8_t kCoolixTempMap[kCoolixTempRange] = { const uint8_t kCoolixSensorTempMin = 16; // Celsius const uint8_t kCoolixSensorTempMax = 30; // Celsius const uint8_t kCoolixSensorTempIgnoreCode = 0b1111; -const uint32_t kCoolixSensorTempMask = 0b000000000000111100000000; // 0xF00 +// kCoolixSensorTempMask = 0b000000000000111100000000; // 0xF00 +const uint8_t kCoolixSensorTempOffset = 8; +const uint8_t kCoolixSensorTempSize = 4; // Fixed states/messages. const uint8_t kCoolixPrefix = 0b1011; // 0xB const uint8_t kCoolixUnknown = 0xFF; -const uint32_t kCoolixOff = 0b101100100111101111100000; // 0xB27BE0 -const uint32_t kCoolixSwing = 0b101100100110101111100000; // 0xB26BE0 -const uint32_t kCoolixSleep = 0b101100101110000000000011; // 0xB2E003 -const uint32_t kCoolixTurbo = 0b101101011111010110100010; // 0xB5F5A2 -const uint32_t kCoolixLed = 0b101101011111010110100101; // 0xB5F5A5 -const uint32_t kCoolixClean = 0b101101011111010110101010; // 0xB5F5AA +const uint32_t kCoolixOff = 0b101100100111101111100000; // 0xB27BE0 +const uint32_t kCoolixSwing = 0b101100100110101111100000; // 0xB26BE0 +const uint32_t kCoolixSwingH = 0b101100101111010110100010; // 0xB5F5A2 +const uint32_t kCoolixSwingV = 0b101100100000111111100000; // 0xB20FE0 +const uint32_t kCoolixSleep = 0b101100101110000000000011; // 0xB2E003 +const uint32_t kCoolixTurbo = 0b101101011111010110100010; // 0xB5F5A2 +const uint32_t kCoolixLed = 0b101101011111010110100101; // 0xB5F5A5 +const uint32_t kCoolixClean = 0b101101011111010110101010; // 0xB5F5AA +const uint32_t kCoolixCmdFan = 0b101100101011111111100100; // 0xB2BFE4 // On, 25C, Mode: Auto, Fan: Auto, Zone Follow: Off, Sensor Temp: Ignore. -const uint32_t kCoolixDefaultState = 0b101100101011111111001000; // 0xB2BFC8 +const uint32_t kCoolixDefaultState = 0b101100100001111111001000; // 0xB21FC8 // Classes class IRCoolixAC { @@ -134,13 +147,25 @@ class IRCoolixAC { #else IRsendTest _irsend; #endif + // internal state + bool powerFlag; + bool turboFlag; + bool ledFlag; + bool cleanFlag; + bool sleepFlag; + bool zoneFollowFlag; + bool swingFlag; + bool swingHFlag; + bool swingVFlag; + uint32_t remote_state; // The state of the IR remote in IR code form. uint32_t saved_state; // Copy of the state if we required a special mode. void setTempRaw(const uint8_t code); uint8_t getTempRaw(); void setSensorTempRaw(const uint8_t code); - void setZoneFollow(const bool state); + void setZoneFollow(const bool on); bool isSpecialState(void); + bool handleSpecialState(const uint32_t data); void updateSavedState(void); void recoverSavedState(void); uint32_t getNormalState(void); diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Daikin.cpp old mode 100755 new mode 100644 similarity index 70% rename from lib/IRremoteESP8266-2.6.5/src/ir_Daikin.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Daikin.cpp index 317526f5e..b90dd682b --- a/lib/IRremoteESP8266-2.6.5/src/ir_Daikin.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Daikin.cpp @@ -11,6 +11,7 @@ Copyright 2019 pasna (IRDaikin160 class / Daikin176 class) #include "ir_Daikin.h" #include +#include #ifndef ARDUINO #include #endif @@ -20,6 +21,7 @@ Copyright 2019 pasna (IRDaikin160 class / Daikin176 class) #ifdef UNIT_TEST #include "IRsend_test.h" #endif +#include "IRtext.h" #include "IRutils.h" // Constants @@ -29,6 +31,7 @@ Copyright 2019 pasna (IRDaikin160 class / Daikin176 class) // https://github.com/crankyoldgit/IRremoteESP8266/issues/582 using irutils::addBoolToString; +using irutils::addDayToString; using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; @@ -36,6 +39,8 @@ using irutils::addTempToString; using irutils::addFanToString; using irutils::bcdToUint8; using irutils::minsToString; +using irutils::setBit; +using irutils::setBits; using irutils::sumNibbles; using irutils::uint8ToBcd; @@ -101,8 +106,7 @@ void IRDaikinESP::begin(void) { _irsend.begin(); } #if SEND_DAIKIN void IRDaikinESP::send(const uint16_t repeat) { - this->checksum(); - _irsend.sendDaikin(remote, kDaikinStateLength, repeat); + _irsend.sendDaikin(getRaw(), kDaikinStateLength, repeat); } #endif // SEND_DAIKIN @@ -184,19 +188,16 @@ void IRDaikinESP::setRaw(const uint8_t new_code[], const uint16_t length) { remote[i + offset] = new_code[i]; } -void IRDaikinESP::on(void) { remote[kDaikinBytePower] |= kDaikinBitPower; } +void IRDaikinESP::on(void) { setPower(true); } -void IRDaikinESP::off(void) { remote[kDaikinBytePower] &= ~kDaikinBitPower; } +void IRDaikinESP::off(void) { setPower(false); } void IRDaikinESP::setPower(const bool on) { - if (on) - this->on(); - else - this->off(); + setBit(&remote[kDaikinBytePower], kDaikinBitPowerOffset, on); } bool IRDaikinESP::getPower(void) { - return remote[kDaikinBytePower] & kDaikinBitPower; + return GETBIT8(remote[kDaikinBytePower], kDaikinBitPowerOffset); } // Set the temp in deg C @@ -218,17 +219,19 @@ void IRDaikinESP::setFan(const uint8_t fan) { fanset = kDaikinFanAuto; else fanset = 2 + fan; - remote[kDaikinByteFan] &= 0x0F; - remote[kDaikinByteFan] |= (fanset << 4); + setBits(&remote[kDaikinByteFan], kDaikinFanOffset, kDaikinFanSize, fanset); } uint8_t IRDaikinESP::getFan(void) { - uint8_t fan = remote[kDaikinByteFan] >> 4; + uint8_t fan = GETBITS8(remote[kDaikinByteFan], kDaikinFanOffset, + kDaikinFanSize); if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2; return fan; } -uint8_t IRDaikinESP::getMode(void) { return remote[kDaikinBytePower] >> 4; } +uint8_t IRDaikinESP::getMode(void) { + return GETBITS8(remote[kDaikinBytePower], kDaikinModeOffset, kDaikinModeSize); +} void IRDaikinESP::setMode(const uint8_t mode) { switch (mode) { @@ -237,8 +240,8 @@ void IRDaikinESP::setMode(const uint8_t mode) { case kDaikinHeat: case kDaikinFan: case kDaikinDry: - remote[kDaikinBytePower] &= 0b10001111; - remote[kDaikinBytePower] |= (mode << 4); + setBits(&remote[kDaikinBytePower], kDaikinModeOffset, kDaikinModeSize, + mode); break; default: this->setMode(kDaikinAuto); @@ -246,146 +249,126 @@ void IRDaikinESP::setMode(const uint8_t mode) { } void IRDaikinESP::setSwingVertical(const bool on) { - if (on) - remote[kDaikinByteFan] |= 0x0F; - else - remote[kDaikinByteFan] &= 0xF0; + setBits(&remote[kDaikinByteFan], kDaikinSwingOffset, kDaikinSwingSize, + on ? kDaikinSwingOn : kDaikinSwingOff); } bool IRDaikinESP::getSwingVertical(void) { - return remote[kDaikinByteFan] & 0x0F; + return GETBITS8(remote[kDaikinByteFan], kDaikinSwingOffset, kDaikinSwingSize); } void IRDaikinESP::setSwingHorizontal(const bool on) { - if (on) - remote[kDaikinByteSwingH] |= 0x0F; - else - remote[kDaikinByteSwingH] &= 0xF0; + setBits(&remote[kDaikinByteSwingH], kDaikinSwingOffset, kDaikinSwingSize, + on ? kDaikinSwingOn : kDaikinSwingOff); } bool IRDaikinESP::getSwingHorizontal(void) { - return remote[kDaikinByteSwingH] & 0x0F; + return GETBITS8(remote[kDaikinByteSwingH], kDaikinSwingOffset, + kDaikinSwingSize); } void IRDaikinESP::setQuiet(const bool on) { - if (on) { - remote[kDaikinByteSilent] |= kDaikinBitSilent; - // Powerful & Quiet mode being on are mutually exclusive. - this->setPowerful(false); - } else { - remote[kDaikinByteSilent] &= ~kDaikinBitSilent; - } + setBit(&remote[kDaikinByteSilent], kDaikinBitSilentOffset, on); + // Powerful & Quiet mode being on are mutually exclusive. + if (on) this->setPowerful(false); } bool IRDaikinESP::getQuiet(void) { - return remote[kDaikinByteSilent] & kDaikinBitSilent; + return GETBIT8(remote[kDaikinByteSilent], kDaikinBitSilentOffset); } void IRDaikinESP::setPowerful(const bool on) { + setBit(&remote[kDaikinBytePowerful], kDaikinBitPowerfulOffset, on); if (on) { - remote[kDaikinBytePowerful] |= kDaikinBitPowerful; // Powerful, Quiet, & Econo mode being on are mutually exclusive. this->setQuiet(false); this->setEcono(false); - } else { - remote[kDaikinBytePowerful] &= ~kDaikinBitPowerful; } } bool IRDaikinESP::getPowerful(void) { - return remote[kDaikinBytePowerful] & kDaikinBitPowerful; + return GETBIT8(remote[kDaikinBytePowerful], kDaikinBitPowerfulOffset); } void IRDaikinESP::setSensor(const bool on) { - if (on) - remote[kDaikinByteSensor] |= kDaikinBitSensor; - else - remote[kDaikinByteSensor] &= ~kDaikinBitSensor; + setBit(&remote[kDaikinByteSensor], kDaikinBitSensorOffset, on); } bool IRDaikinESP::getSensor(void) { - return remote[kDaikinByteSensor] & kDaikinBitSensor; + return GETBIT8(remote[kDaikinByteSensor], kDaikinBitSensorOffset); } void IRDaikinESP::setEcono(const bool on) { - if (on) { - remote[kDaikinByteEcono] |= kDaikinBitEcono; - // Powerful & Econo mode being on are mutually exclusive. - this->setPowerful(false); - } else { - remote[kDaikinByteEcono] &= ~kDaikinBitEcono; - } + setBit(&remote[kDaikinByteEcono], kDaikinBitEconoOffset, on); + // Powerful & Econo mode being on are mutually exclusive. + if (on) this->setPowerful(false); } bool IRDaikinESP::getEcono(void) { - return remote[kDaikinByteEcono] & kDaikinBitEcono; + return GETBIT8(remote[kDaikinByteEcono], kDaikinBitEconoOffset); } void IRDaikinESP::setMold(const bool on) { - if (on) - remote[kDaikinByteMold] |= kDaikinBitMold; - else - remote[kDaikinByteMold] &= ~kDaikinBitMold; + setBit(&remote[kDaikinByteMold], kDaikinBitMoldOffset, on); } bool IRDaikinESP::getMold(void) { - return remote[kDaikinByteMold] & kDaikinBitMold; + return GETBIT8(remote[kDaikinByteMold], kDaikinBitMoldOffset); } void IRDaikinESP::setComfort(const bool on) { - if (on) - remote[kDaikinByteComfort] |= kDaikinBitComfort; - else - remote[kDaikinByteComfort] &= ~kDaikinBitComfort; + setBit(&remote[kDaikinByteComfort], kDaikinBitComfortOffset, on); } bool IRDaikinESP::getComfort(void) { - return remote[kDaikinByteComfort] & kDaikinBitComfort; + return GETBIT8(remote[kDaikinByteComfort], kDaikinBitComfortOffset); } // starttime: Number of minutes after midnight. void IRDaikinESP::enableOnTimer(const uint16_t starttime) { - remote[kDaikinByteOnTimer] |= kDaikinBitOnTimer; + setBit(&remote[kDaikinByteOnTimer], kDaikinBitOnTimerOffset); remote[kDaikinByteOnTimerMinsLow] = starttime; // only keep 4 bits - remote[kDaikinByteOnTimerMinsHigh] &= 0xF0; - remote[kDaikinByteOnTimerMinsHigh] |= ((starttime >> 8) & 0x0F); + setBits(&remote[kDaikinByteOnTimerMinsHigh], kDaikinOnTimerMinsHighOffset, + kDaikinOnTimerMinsHighSize, starttime >> 8); } void IRDaikinESP::disableOnTimer(void) { this->enableOnTimer(kDaikinUnusedTime); - remote[kDaikinByteOnTimer] &= ~kDaikinBitOnTimer; + setBit(&remote[kDaikinByteOnTimer], kDaikinBitOnTimerOffset, false); } uint16_t IRDaikinESP::getOnTime(void) { - return ((remote[kDaikinByteOnTimerMinsHigh] & 0x0F) << 8) + + return (GETBITS8(remote[kDaikinByteOnTimerMinsHigh], + kDaikinOnTimerMinsHighOffset, + kDaikinOnTimerMinsHighSize) << 8) + remote[kDaikinByteOnTimerMinsLow]; } bool IRDaikinESP::getOnTimerEnabled(void) { - return remote[kDaikinByteOnTimer] & kDaikinBitOnTimer; + return GETBIT8(remote[kDaikinByteOnTimer], kDaikinBitOnTimerOffset); } // endtime: Number of minutes after midnight. void IRDaikinESP::enableOffTimer(const uint16_t endtime) { - remote[kDaikinByteOffTimer] |= kDaikinBitOffTimer; - remote[kDaikinByteOffTimerMinsHigh] = endtime >> 4; - remote[kDaikinByteOffTimerMinsLow] &= 0x0F; - remote[kDaikinByteOffTimerMinsLow] |= ((endtime & 0x0F) << 4); + setBit(&remote[kDaikinByteOffTimer], kDaikinBitOffTimerOffset); + remote[kDaikinByteOffTimerMinsHigh] = endtime >> kNibbleSize; + setBits(&remote[kDaikinByteOffTimerMinsLow], kHighNibble, kNibbleSize, + endtime); } void IRDaikinESP::disableOffTimer(void) { this->enableOffTimer(kDaikinUnusedTime); - remote[kDaikinByteOffTimer] &= ~kDaikinBitOffTimer; + setBit(&remote[kDaikinByteOffTimer], kDaikinBitOffTimerOffset, false); } uint16_t IRDaikinESP::getOffTime(void) { - return (remote[kDaikinByteOffTimerMinsHigh] << 4) + - ((remote[kDaikinByteOffTimerMinsLow] & 0xF0) >> 4); + return (remote[kDaikinByteOffTimerMinsHigh] << kNibbleSize) + + GETBITS8(remote[kDaikinByteOffTimerMinsLow], kHighNibble, kNibbleSize); } bool IRDaikinESP::getOffTimerEnabled(void) { - return remote[kDaikinByteOffTimer] & kDaikinBitOffTimer; + return GETBIT8(remote[kDaikinByteOffTimer], kDaikinBitOffTimerOffset); } void IRDaikinESP::setCurrentTime(const uint16_t mins_since_midnight) { @@ -393,70 +376,56 @@ void IRDaikinESP::setCurrentTime(const uint16_t mins_since_midnight) { if (mins > 24 * 60) mins = 0; // If > 23:59, set to 00:00 remote[kDaikinByteClockMinsLow] = mins; // only keep 3 bits - remote[kDaikinByteClockMinsHigh] &= 0xF8; - remote[kDaikinByteClockMinsHigh] |= ((mins >> 8) & 0x07); + setBits(&remote[kDaikinByteClockMinsHigh], kDaikinClockMinsHighOffset, + kDaikinClockMinsHighSize, mins >> 8); } uint16_t IRDaikinESP::getCurrentTime(void) { - return ((remote[kDaikinByteClockMinsHigh] & 0x07) << 8) + + return (GETBITS8(remote[kDaikinByteClockMinsHigh], kDaikinClockMinsHighOffset, + kDaikinClockMinsHighSize) << 8) + remote[kDaikinByteClockMinsLow]; } void IRDaikinESP::setCurrentDay(const uint8_t day_of_week) { // 1 is SUN, 2 is MON, ..., 7 is SAT - uint8_t days = day_of_week; - if (days > 7) days = 0; // Enforce the limit - // Update bits 5-3 - remote[kDaikinByteClockMinsHigh] &= 0xc7; - remote[kDaikinByteClockMinsHigh] |= days << 3; + setBits(&remote[kDaikinByteClockMinsHigh], kDaikinDoWOffset, kDaikinDoWSize, + day_of_week); } uint8_t IRDaikinESP::getCurrentDay(void) { - return ((remote[kDaikinByteClockMinsHigh] & 0x38) >> 3); + return GETBITS8(remote[kDaikinByteClockMinsHigh], kDaikinDoWOffset, + kDaikinDoWSize); } void IRDaikinESP::setWeeklyTimerEnable(const bool on) { - if (on) - remote[kDaikinByteWeeklyTimer] &= ~kDaikinBitWeeklyTimer; // Clear the bit. - else - remote[kDaikinByteWeeklyTimer] |= kDaikinBitWeeklyTimer; // Set the bit. + // Bit is cleared for `on`. + setBit(&remote[kDaikinByteWeeklyTimer], kDaikinBitWeeklyTimerOffset, !on); } bool IRDaikinESP::getWeeklyTimerEnable(void) { - return !(remote[kDaikinByteWeeklyTimer] & kDaikinBitWeeklyTimer); + return !GETBIT8(remote[kDaikinByteWeeklyTimer], kDaikinBitWeeklyTimerOffset); } // Convert a standard A/C mode into its native mode. uint8_t IRDaikinESP::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kDaikinCool; - case stdAc::opmode_t::kHeat: - return kDaikinHeat; - case stdAc::opmode_t::kDry: - return kDaikinDry; - case stdAc::opmode_t::kFan: - return kDaikinFan; - default: - return kDaikinAuto; + case stdAc::opmode_t::kCool: return kDaikinCool; + case stdAc::opmode_t::kHeat: return kDaikinHeat; + case stdAc::opmode_t::kDry: return kDaikinDry; + case stdAc::opmode_t::kFan: return kDaikinFan; + default: return kDaikinAuto; } } // Convert a standard A/C Fan speed into its native fan speed. uint8_t IRDaikinESP::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { - case stdAc::fanspeed_t::kMin: - return kDaikinFanQuiet; - case stdAc::fanspeed_t::kLow: - return kDaikinFanMin; - case stdAc::fanspeed_t::kMedium: - return kDaikinFanMin + 1; - case stdAc::fanspeed_t::kHigh: - return kDaikinFanMax - 1; - case stdAc::fanspeed_t::kMax: - return kDaikinFanMax; - default: - return kDaikinFanAuto; + case stdAc::fanspeed_t::kMin: return kDaikinFanQuiet; + case stdAc::fanspeed_t::kLow: return kDaikinFanMin; + case stdAc::fanspeed_t::kMedium: return kDaikinFanMed; + case stdAc::fanspeed_t::kHigh: return kDaikinFanMax - 1; + case stdAc::fanspeed_t::kMax: return kDaikinFanMax; + default: return kDaikinFanAuto; } } @@ -476,6 +445,7 @@ stdAc::fanspeed_t IRDaikinESP::toCommonFanSpeed(const uint8_t speed) { switch (speed) { case kDaikinFanMax: return stdAc::fanspeed_t::kMax; case kDaikinFanMax - 1: return stdAc::fanspeed_t::kHigh; + case kDaikinFanMed: case kDaikinFanMin + 1: return stdAc::fanspeed_t::kMedium; case kDaikinFanMin: return stdAc::fanspeed_t::kLow; case kDaikinFanQuiet: return stdAc::fanspeed_t::kMin; @@ -514,47 +484,28 @@ stdAc::state_t IRDaikinESP::toCommon(void) { String IRDaikinESP::toString(void) { String result = ""; result.reserve(230); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kDaikinAuto, kDaikinCool, kDaikinHeat, kDaikinDry, kDaikinFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kDaikinFanMax, kDaikinFanMin, kDaikinFanAuto, kDaikinFanQuiet, kDaikinFanMed); - result += addBoolToString(getPowerful(), F("Powerful")); - result += addBoolToString(getQuiet(), F("Quiet")); - result += addBoolToString(getSensor(), F("Sensor")); - result += addBoolToString(getMold(), F("Mold")); - result += addBoolToString(getComfort(), F("Comfort")); - result += addBoolToString(getSwingHorizontal(), F("Swing (Horizontal)")); - result += addBoolToString(getSwingVertical(), F("Swing (Vertical)")); - result += addLabeledString(minsToString(this->getCurrentTime()), - F("Current Time")); - result += F(", Current Day: "); - switch (this->getCurrentDay()) { - case 1: - result +=F("SUN"); break; - case 2: - result +=F("MON"); break; - case 3: - result +=F("TUE"); break; - case 4: - result +=F("WED"); break; - case 5: - result +=F("THU"); break; - case 6: - result +=F("FRI"); break; - case 7: - result +=F("SAT"); break; - default: - result +=F("(UNKNOWN)"); break; - } + result += addBoolToString(getPowerful(), kPowerfulStr); + result += addBoolToString(getQuiet(), kQuietStr); + result += addBoolToString(getSensor(), kSensorStr); + result += addBoolToString(getMold(), kMouldStr); + result += addBoolToString(getComfort(), kComfortStr); + result += addBoolToString(getSwingHorizontal(), kSwingHStr); + result += addBoolToString(getSwingVertical(), kSwingVStr); + result += addLabeledString(minsToString(this->getCurrentTime()), kClockStr); + result += addDayToString(getCurrentDay(), -1); result += addLabeledString(getOnTimerEnabled() - ? minsToString(this->getOnTime()) : F("Off"), - F("On Time")); + ? minsToString(this->getOnTime()) : kOffStr, + kOnTimerStr); result += addLabeledString(getOffTimerEnabled() - ? minsToString(this->getOffTime()) : F("Off"), - F("Off Time")); - result += addBoolToString(getWeeklyTimerEnable(), F("Weekly Timer")); + ? minsToString(this->getOffTime()) : kOffStr, + kOffTimerStr); + result += addBoolToString(getWeeklyTimerEnable(), kWeeklyTimerStr); return result; } @@ -567,7 +518,7 @@ String IRDaikinESP::toString(void) { // Returns: // boolean: True if it can decode it, false if it can't. // -// Status: BETA / Should be working. +// Status: STABLE / Reported as working. // // Ref: // https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote @@ -683,12 +634,11 @@ IRDaikin2::IRDaikin2(const uint16_t pin, const bool inverted, const bool use_modulation) : _irsend(pin, inverted, use_modulation) { stateReset(); } -void IRDaikin2::begin() { _irsend.begin(); } +void IRDaikin2::begin(void) { _irsend.begin(); } #if SEND_DAIKIN2 void IRDaikin2::send(const uint16_t repeat) { - checksum(); - _irsend.sendDaikin2(remote_state, kDaikin2StateLength, repeat); + _irsend.sendDaikin2(getRaw(), kDaikin2StateLength, repeat); } #endif // SEND_DAIKIN2 @@ -713,14 +663,14 @@ bool IRDaikin2::validChecksum(uint8_t state[], const uint16_t length) { } // Calculate and set the checksum values for the internal state. -void IRDaikin2::checksum() { +void IRDaikin2::checksum(void) { remote_state[kDaikin2Section1Length - 1] = sumBytes( remote_state, kDaikin2Section1Length - 1); remote_state[kDaikin2StateLength -1 ] = sumBytes( remote_state + kDaikin2Section1Length, kDaikin2Section2Length - 1); } -void IRDaikin2::stateReset() { +void IRDaikin2::stateReset(void) { for (uint8_t i = 0; i < kDaikin2StateLength; i++) remote_state[i] = 0x0; remote_state[0] = 0x11; @@ -754,53 +704,43 @@ void IRDaikin2::stateReset() { checksum(); } -uint8_t *IRDaikin2::getRaw() { +uint8_t *IRDaikin2::getRaw(void) { checksum(); // Ensure correct settings before sending. return remote_state; } void IRDaikin2::setRaw(const uint8_t new_code[]) { - for (uint8_t i = 0; i < kDaikin2StateLength; i++) - remote_state[i] = new_code[i]; + memcpy(remote_state, new_code, kDaikin2StateLength); } -void IRDaikin2::on() { - remote_state[25] |= kDaikinBitPower; - remote_state[6] &= ~kDaikin2BitPower; +void IRDaikin2::on(void) { setPower(true); } + +void IRDaikin2::off(void) { setPower(false); } + +void IRDaikin2::setPower(const bool on) { + setBit(&remote_state[25], kDaikinBitPowerOffset, on); + setBit(&remote_state[6], kDaikin2BitPowerOffset, !on); } -void IRDaikin2::off() { - remote_state[25] &= ~kDaikinBitPower; - remote_state[6] |= kDaikin2BitPower; +bool IRDaikin2::getPower(void) { + return GETBIT8(remote_state[25], kDaikinBitPowerOffset) && + !GETBIT8(remote_state[6], kDaikin2BitPowerOffset); } -void IRDaikin2::setPower(const bool state) { - if (state) - on(); - else - off(); +uint8_t IRDaikin2::getMode(void) { + return GETBITS8(remote_state[25], kHighNibble, kModeBitsSize); } -bool IRDaikin2::getPower() { - return (remote_state[25] & kDaikinBitPower) && - !(remote_state[6] & kDaikin2BitPower); -} - -uint8_t IRDaikin2::getMode() { return remote_state[25] >> 4; } - void IRDaikin2::setMode(const uint8_t desired_mode) { uint8_t mode = desired_mode; switch (mode) { case kDaikinCool: case kDaikinHeat: case kDaikinFan: - case kDaikinDry: - break; - default: - mode = kDaikinAuto; + case kDaikinDry: break; + default: mode = kDaikinAuto; } - remote_state[25] &= 0b10001111; - remote_state[25] |= (mode << 4); + setBits(&remote_state[25], kHighNibble, kModeBitsSize, mode); // Redo the temp setting as Cool mode has a different min temp. if (mode == kDaikinCool) this->setTemp(this->getTemp()); } @@ -811,8 +751,7 @@ void IRDaikin2::setTemp(const uint8_t desired) { uint8_t temp = std::max( (this->getMode() == kDaikinCool) ? kDaikin2MinCoolTemp : kDaikinMinTemp, desired); - temp = std::min(kDaikinMaxTemp, temp); - remote_state[26] = temp * 2; + remote_state[26] = std::min(kDaikinMaxTemp, temp) << 1; } // Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet @@ -825,17 +764,20 @@ void IRDaikin2::setFan(const uint8_t fan) { fanset = kDaikinFanAuto; else fanset = 2 + fan; - remote_state[28] &= 0x0F; - remote_state[28] |= (fanset << 4); + setBits(&remote_state[kDaikin2FanByte], kHighNibble, kNibbleSize, fanset); } -uint8_t IRDaikin2::getFan() { - uint8_t fan = remote_state[28] >> 4; - if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2; - return fan; +uint8_t IRDaikin2::getFan(void) { + const uint8_t fan = GETBITS8(remote_state[kDaikin2FanByte], kHighNibble, + kNibbleSize); + switch (fan) { + case kDaikinFanAuto: + case kDaikinFanQuiet: return fan; + default: return fan - 2; + } } -uint8_t IRDaikin2::getTemp() { return remote_state[26] / 2; } +uint8_t IRDaikin2::getTemp(void) { return remote_state[26] >> 1; } void IRDaikin2::setSwingVertical(const uint8_t position) { switch (position) { @@ -845,247 +787,16 @@ void IRDaikin2::setSwingVertical(const uint8_t position) { case 4: case 5: case kDaikin2SwingVLow: + case kDaikin2SwingVSwing: case kDaikin2SwingVBreeze: case kDaikin2SwingVCirculate: case kDaikin2SwingVAuto: - remote_state[18] &= 0xF0; - remote_state[18] |= (position & 0x0F); + setBits(&remote_state[18], kLowNibble, kNibbleSize, position); } } -uint8_t IRDaikin2::getSwingVertical() { return remote_state[18] & 0x0F; } - -void IRDaikin2::setSwingHorizontal(const uint8_t position) { - remote_state[17] = position; -} - -uint8_t IRDaikin2::getSwingHorizontal() { return remote_state[17]; } - -void IRDaikin2::setCurrentTime(const uint16_t numMins) { - uint16_t mins = numMins; - if (numMins > 24 * 60) mins = 0; // If > 23:59, set to 00:00 - remote_state[5] = (uint8_t)(mins & 0xFF); - // only keep 4 bits - remote_state[6] &= 0xF0; - remote_state[6] |= (uint8_t)((mins >> 8) & 0x0F); -} - -uint16_t IRDaikin2::getCurrentTime() { - return ((remote_state[6] & 0x0F) << 8) + remote_state[5]; -} - -// starttime: Number of minutes after midnight. -// Note: Timer location is shared with sleep timer. -void IRDaikin2::enableOnTimer(const uint16_t starttime) { - clearSleepTimerFlag(); - remote_state[25] |= kDaikinBitOnTimer; // Set the On Timer flag. - remote_state[30] = (uint8_t)(starttime & 0xFF); - // only keep 4 bits - remote_state[31] &= 0xF0; - remote_state[31] |= (uint8_t)((starttime >> 8) & 0x0F); -} - -void IRDaikin2::clearOnTimerFlag() { - remote_state[25] &= ~kDaikinBitOnTimer; -} - -void IRDaikin2::disableOnTimer() { - enableOnTimer(kDaikinUnusedTime); - clearOnTimerFlag(); - clearSleepTimerFlag(); -} - -uint16_t IRDaikin2::getOnTime() { - return ((remote_state[31] & 0x0F) << 8) + remote_state[30]; -} - -bool IRDaikin2::getOnTimerEnabled() { - return remote_state[25] & kDaikinBitOnTimer; -} - -// endtime: Number of minutes after midnight. -void IRDaikin2::enableOffTimer(const uint16_t endtime) { - remote_state[25] |= kDaikinBitOffTimer; // Set the Off Timer flag. - remote_state[32] = (uint8_t)((endtime >> 4) & 0xFF); - remote_state[31] &= 0x0F; - remote_state[31] |= (uint8_t)((endtime & 0xF) << 4); -} - -void IRDaikin2::disableOffTimer() { - enableOffTimer(kDaikinUnusedTime); - remote_state[25] &= ~kDaikinBitOffTimer; // Clear the Off Timer flag. -} - -uint16_t IRDaikin2::getOffTime() { - return (remote_state[32] << 4) + (remote_state[31] >> 4); -} - -bool IRDaikin2::getOffTimerEnabled() { - return remote_state[25] & kDaikinBitOffTimer; -} - -uint8_t IRDaikin2::getBeep() { - return remote_state[7] >> 6; -} - -void IRDaikin2::setBeep(const uint8_t beep) { - remote_state[7] &= ~kDaikin2BeepMask; - remote_state[7] |= ((beep << 6) & kDaikin2BeepMask); -} - -uint8_t IRDaikin2::getLight() { - return (remote_state[7] & kDaikin2LightMask) >> 4; -} - -void IRDaikin2::setLight(const uint8_t light) { - remote_state[7] &= ~kDaikin2LightMask; - remote_state[7] |= ((light << 4) & kDaikin2LightMask); -} - -void IRDaikin2::setMold(const bool on) { - if (on) - remote_state[8] |= kDaikin2BitMold; - else - remote_state[8] &= ~kDaikin2BitMold; -} - -bool IRDaikin2::getMold() { - return remote_state[8] & kDaikin2BitMold; -} - -// Auto clean setting. -void IRDaikin2::setClean(const bool on) { - if (on) - remote_state[8] |= kDaikin2BitClean; - else - remote_state[8] &= ~kDaikin2BitClean; -} - -bool IRDaikin2::getClean() { - return remote_state[8] & kDaikin2BitClean; -} - -// Fresh Air settings. -void IRDaikin2::setFreshAir(const bool on) { - if (on) - remote_state[8] |= kDaikin2BitFreshAir; - else - remote_state[8] &= ~kDaikin2BitFreshAir; -} - -bool IRDaikin2::getFreshAir() { - return remote_state[8] & kDaikin2BitFreshAir; -} - -void IRDaikin2::setFreshAirHigh(const bool on) { - if (on) - remote_state[8] |= kDaikin2BitFreshAirHigh; - else - remote_state[8] &= ~kDaikin2BitFreshAirHigh; -} - -bool IRDaikin2::getFreshAirHigh() { - return remote_state[8] & kDaikin2BitFreshAirHigh; -} - -void IRDaikin2::setEyeAuto(bool on) { - if (on) - remote_state[13] |= kDaikin2BitEyeAuto; - else - remote_state[13] &= ~kDaikin2BitEyeAuto; -} - -bool IRDaikin2::getEyeAuto() { - return remote_state[13] & kDaikin2BitEyeAuto; -} - -void IRDaikin2::setEye(bool on) { - if (on) - remote_state[36] |= kDaikin2BitEye; - else - remote_state[36] &= ~kDaikin2BitEye; -} - -bool IRDaikin2::getEye() { - return remote_state[36] & kDaikin2BitEye; -} - -void IRDaikin2::setEcono(bool on) { - if (on) - remote_state[36] |= kDaikinBitEcono; - else - remote_state[36] &= ~kDaikinBitEcono; -} - -bool IRDaikin2::getEcono() { - return remote_state[36] & kDaikinBitEcono; -} - -// sleeptime: Number of minutes. -// Note: Timer location is shared with On Timer. -void IRDaikin2::enableSleepTimer(const uint16_t sleeptime) { - enableOnTimer(sleeptime); - clearOnTimerFlag(); - remote_state[36] |= kDaikin2BitSleepTimer; // Set the Sleep Timer flag. -} - -void IRDaikin2::clearSleepTimerFlag() { - remote_state[36] &= ~kDaikin2BitSleepTimer; -} - -void IRDaikin2::disableSleepTimer() { - disableOnTimer(); -} - -uint16_t IRDaikin2::getSleepTime() { - return getOnTime(); -} - -bool IRDaikin2::getSleepTimerEnabled() { - return remote_state[36] & kDaikin2BitSleepTimer; -} - -void IRDaikin2::setQuiet(const bool on) { - if (on) { - remote_state[33] |= kDaikinBitSilent; - // Powerful & Quiet mode being on are mutually exclusive. - setPowerful(false); - } else { - remote_state[33] &= ~kDaikinBitSilent; - } -} - -bool IRDaikin2::getQuiet() { return remote_state[33] & kDaikinBitSilent; } - -void IRDaikin2::setPowerful(const bool on) { - if (on) { - remote_state[33] |= kDaikinBitPowerful; - // Powerful & Quiet mode being on are mutually exclusive. - setQuiet(false); - } else { - remote_state[33] &= ~kDaikinBitPowerful; - } -} - -bool IRDaikin2::getPowerful() { return remote_state[33] & kDaikinBitPowerful; } - -void IRDaikin2::setPurify(const bool on) { - if (on) - remote_state[36] |= kDaikin2BitPurify; - else - remote_state[36] &= ~kDaikin2BitPurify; -} - -bool IRDaikin2::getPurify() { return remote_state[36] & kDaikin2BitPurify; } - -// Convert a standard A/C mode into its native mode. -uint8_t IRDaikin2::convertMode(const stdAc::opmode_t mode) { - return IRDaikinESP::convertMode(mode); -} - -// Convert a standard A/C Fan speed into its native fan speed. -uint8_t IRDaikin2::convertFan(const stdAc::fanspeed_t speed) { - return IRDaikinESP::convertFan(speed); +uint8_t IRDaikin2::getSwingVertical(void) { + return GETBITS8(remote_state[18], kLowNibble, kNibbleSize); } // Convert a standard A/C vertical swing into its native version. @@ -1097,8 +808,8 @@ uint8_t IRDaikin2::convertSwingV(const stdAc::swingv_t position) { case stdAc::swingv_t::kLow: case stdAc::swingv_t::kLowest: return (uint8_t)position + kDaikin2SwingVHigh; - default: - return kDaikin2SwingVAuto; + case stdAc::swingv_t::kAuto: return kDaikin2SwingVSwing; + default: return kDaikin2SwingVAuto; } } @@ -1111,15 +822,241 @@ stdAc::swingv_t IRDaikin2::toCommonSwingV(const uint8_t setting) { case kDaikin2SwingVHigh + 3: return stdAc::swingv_t::kMiddle; case kDaikin2SwingVLow - 1: return stdAc::swingv_t::kLow; case kDaikin2SwingVLow: return stdAc::swingv_t::kLowest; + case kDaikin2SwingVAuto: return stdAc::swingv_t::kOff; default: return stdAc::swingv_t::kAuto; } } +void IRDaikin2::setSwingHorizontal(const uint8_t position) { + remote_state[17] = position; +} + +uint8_t IRDaikin2::getSwingHorizontal(void) { return remote_state[17]; } + +void IRDaikin2::setCurrentTime(const uint16_t numMins) { + uint16_t mins = numMins; + if (numMins > 24 * 60) mins = 0; // If > 23:59, set to 00:00 + remote_state[5] = mins; + setBits(&remote_state[6], kLowNibble, kNibbleSize, mins >> 8); +} + +uint16_t IRDaikin2::getCurrentTime(void) { + return (GETBITS8(remote_state[6], kLowNibble, kNibbleSize) << 8) | + remote_state[5]; +} + +// starttime: Number of minutes after midnight. +// Note: Timer location is shared with sleep timer. +void IRDaikin2::enableOnTimer(const uint16_t starttime) { + clearSleepTimerFlag(); + setBit(&remote_state[25], kDaikinBitOnTimerOffset); // Set the On Timer flag. + remote_state[30] = starttime; + setBits(&remote_state[31], kLowNibble, kNibbleSize, starttime >> 8); +} + +void IRDaikin2::clearOnTimerFlag(void) { + setBit(&remote_state[25], kDaikinBitOnTimerOffset, false); +} + +void IRDaikin2::disableOnTimer(void) { + enableOnTimer(kDaikinUnusedTime); + clearOnTimerFlag(); + clearSleepTimerFlag(); +} + +uint16_t IRDaikin2::getOnTime(void) { + return (GETBITS8(remote_state[31], kLowNibble, kNibbleSize) << 8) + + remote_state[30]; +} + +bool IRDaikin2::getOnTimerEnabled(void) { + return GETBIT8(remote_state[25], kDaikinBitOnTimerOffset); +} + +// endtime: Number of minutes after midnight. +void IRDaikin2::enableOffTimer(const uint16_t endtime) { + // Set the Off Timer flag. + setBit(&remote_state[25], kDaikinBitOffTimerOffset); + remote_state[32] = endtime >> 4; + setBits(&remote_state[31], kHighNibble, kNibbleSize, endtime); +} + +void IRDaikin2::disableOffTimer(void) { + enableOffTimer(kDaikinUnusedTime); + // Clear the Off Timer flag. + setBit(&remote_state[25], kDaikinBitOffTimerOffset, false); +} + +uint16_t IRDaikin2::getOffTime(void) { + return (remote_state[32] << 4) + GETBITS8(remote_state[31], kHighNibble, + kNibbleSize); +} + +bool IRDaikin2::getOffTimerEnabled(void) { + return GETBIT8(remote_state[25], kDaikinBitOffTimerOffset); +} + +uint8_t IRDaikin2::getBeep(void) { + return GETBITS8(remote_state[7], kDaikin2BeepOffset, kDaikin2BeepSize); +} + +void IRDaikin2::setBeep(const uint8_t beep) { + setBits(&remote_state[7], kDaikin2BeepOffset, kDaikin2BeepSize, beep); +} + +uint8_t IRDaikin2::getLight(void) { + return GETBITS8(remote_state[7], kDaikin2LightOffset, kDaikin2LightSize); +} + +void IRDaikin2::setLight(const uint8_t light) { + setBits(&remote_state[7], kDaikin2LightOffset, kDaikin2LightSize, light); +} + +void IRDaikin2::setMold(const bool on) { + setBit(&remote_state[8], kDaikin2BitMoldOffset, on); +} + +bool IRDaikin2::getMold(void) { + return GETBIT8(remote_state[8], kDaikin2BitMoldOffset); +} + +// Auto clean setting. +void IRDaikin2::setClean(const bool on) { + setBit(&remote_state[8], kDaikin2BitCleanOffset, on); +} + +bool IRDaikin2::getClean(void) { + return GETBIT8(remote_state[8], kDaikin2BitCleanOffset); +} + +// Fresh Air settings. +void IRDaikin2::setFreshAir(const bool on) { + setBit(&remote_state[8], kDaikin2BitFreshAirOffset, on); +} + +bool IRDaikin2::getFreshAir(void) { + return GETBIT8(remote_state[8], kDaikin2BitFreshAirOffset); +} + +void IRDaikin2::setFreshAirHigh(const bool on) { + setBit(&remote_state[8], kDaikin2BitFreshAirHighOffset, on); +} + +bool IRDaikin2::getFreshAirHigh(void) { + return GETBIT8(remote_state[8], kDaikin2BitFreshAirHighOffset); +} + +void IRDaikin2::setEyeAuto(bool on) { + setBit(&remote_state[13], kDaikin2BitEyeAutoOffset, on); +} + +bool IRDaikin2::getEyeAuto(void) { + return GETBIT8(remote_state[13], kDaikin2BitEyeAutoOffset); +} + +void IRDaikin2::setEye(bool on) { + setBit(&remote_state[36], kDaikin2BitEyeOffset, on); +} + +bool IRDaikin2::getEye(void) { + return GETBIT8(remote_state[36], kDaikin2BitEyeOffset); +} + +void IRDaikin2::setEcono(bool on) { + setBit(&remote_state[36], kDaikinBitEconoOffset, on); +} + +bool IRDaikin2::getEcono(void) { + return GETBIT8(remote_state[36], kDaikinBitEconoOffset); +} + +// sleeptime: Number of minutes. +// Note: Timer location is shared with On Timer. +void IRDaikin2::enableSleepTimer(const uint16_t sleeptime) { + enableOnTimer(sleeptime); + clearOnTimerFlag(); + // Set the Sleep Timer flag. + setBit(&remote_state[36], kDaikin2BitSleepTimerOffset); +} + +void IRDaikin2::clearSleepTimerFlag(void) { + setBit(&remote_state[36], kDaikin2BitSleepTimerOffset, false); +} + +void IRDaikin2::disableSleepTimer(void) { + disableOnTimer(); +} + +uint16_t IRDaikin2::getSleepTime(void) { + return getOnTime(); +} + +bool IRDaikin2::getSleepTimerEnabled(void) { + return GETBIT8(remote_state[36], kDaikin2BitSleepTimerOffset); +} + +void IRDaikin2::setQuiet(const bool on) { + setBit(&remote_state[33], kDaikinBitSilentOffset, on); + // Powerful & Quiet mode being on are mutually exclusive. + if (on) setPowerful(false); +} + +bool IRDaikin2::getQuiet(void) { + return GETBIT8(remote_state[33], kDaikinBitSilentOffset); +} + +void IRDaikin2::setPowerful(const bool on) { + setBit(&remote_state[33], kDaikinBitPowerfulOffset, on); + // Powerful & Quiet mode being on are mutually exclusive. + if (on) setQuiet(false); +} + +bool IRDaikin2::getPowerful(void) { + return GETBIT8(remote_state[33], kDaikinBitPowerfulOffset); +} + +void IRDaikin2::setPurify(const bool on) { + setBit(&remote_state[36], kDaikin2BitPurifyOffset, on); +} + +bool IRDaikin2::getPurify(void) { + return GETBIT8(remote_state[36], kDaikin2BitPurifyOffset); +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRDaikin2::convertMode(const stdAc::opmode_t mode) { + return IRDaikinESP::convertMode(mode); +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRDaikin2::convertFan(const stdAc::fanspeed_t speed) { + return IRDaikinESP::convertFan(speed); +} + +// Convert a standard A/C horizontal swing into its native version. +uint8_t IRDaikin2::convertSwingH(const stdAc::swingh_t position) { + switch (position) { + case stdAc::swingh_t::kAuto: return kDaikin2SwingHSwing; + case stdAc::swingh_t::kLeftMax: return kDaikin2SwingHLeftMax; + case stdAc::swingh_t::kLeft: return kDaikin2SwingHLeft; + case stdAc::swingh_t::kMiddle: return kDaikin2SwingHMiddle; + case stdAc::swingh_t::kRight: return kDaikin2SwingHRight; + case stdAc::swingh_t::kRightMax: return kDaikin2SwingHRightMax; + case stdAc::swingh_t::kWide: return kDaikin2SwingHWide; + default: return kDaikin2SwingHAuto; + } +} + // Convert a native horizontal swing to it's common equivalent. stdAc::swingh_t IRDaikin2::toCommonSwingH(const uint8_t setting) { switch (setting) { - case kDaikin2SwingHSwing: - case kDaikin2SwingHAuto: return stdAc::swingh_t::kAuto; + case kDaikin2SwingHSwing: return stdAc::swingh_t::kAuto; + case kDaikin2SwingHLeftMax: return stdAc::swingh_t::kLeftMax; + case kDaikin2SwingHLeft: return stdAc::swingh_t::kLeft; + case kDaikin2SwingHMiddle: return stdAc::swingh_t::kMiddle; + case kDaikin2SwingHRight: return stdAc::swingh_t::kRight; + case kDaikin2SwingHRightMax: return stdAc::swingh_t::kRightMax; + case kDaikin2SwingHWide: return stdAc::swingh_t::kWide; default: return stdAc::swingh_t::kOff; } } @@ -1137,12 +1074,12 @@ stdAc::state_t IRDaikin2::toCommon(void) { result.swingv = this->toCommonSwingV(this->getSwingVertical()); result.swingh = this->toCommonSwingH(this->getSwingHorizontal()); result.quiet = this->getQuiet(); - result.light = this->getLight(); + result.light = this->getLight() != 3; // 3 is Off, everything else is On. result.turbo = this->getPowerful(); result.clean = this->getMold(); result.econo = this->getEcono(); result.filter = this->getPurify(); - result.beep = this->getBeep(); + result.beep = this->getBeep() != 3; // 3 is Off, everything else is On. result.sleep = this->getSleepTimerEnabled() ? this->getSleepTime() : -1; // Not supported. result.clock = -1; @@ -1150,97 +1087,109 @@ stdAc::state_t IRDaikin2::toCommon(void) { } // Convert the internal state into a human readable string. -String IRDaikin2::toString() { +String IRDaikin2::toString(void) { String result = ""; result.reserve(310); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kDaikinAuto, kDaikinCool, kDaikinHeat, kDaikinDry, kDaikinFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kDaikinFanMax, kDaikinFanMin, kDaikinFanAuto, kDaikinFanQuiet, kDaikinFanMed); - result += addIntToString(getSwingVertical(), F("Swing (V)")); + result += addIntToString(getSwingVertical(), kSwingVStr); + result += kSpaceLBraceStr; switch (getSwingVertical()) { case kDaikin2SwingVHigh: - result += F(" (Highest)"); + result += kHighestStr; break; - case 2: - case 3: - case 4: - case 5: + case 2: result += kHighStr; break; + case 3: result += kUpperStr + kMiddleStr; break; + case 4: result += kLowerStr + kMiddleStr; break; + case 5: result += kLowStr; break; break; case kDaikin2SwingVLow: - result += F(" (Lowest)"); + result += kLowestStr; break; case kDaikin2SwingVBreeze: - result += F(" (Breeze)"); + result += kBreezeStr; break; case kDaikin2SwingVCirculate: - result += F(" (Circulate)"); + result += kCirculateStr; break; case kDaikin2SwingVAuto: - result += F(" (Auto)"); + result += kAutoStr; + break; + case kDaikin2SwingVSwing: + result += kSwingStr; break; default: - result += F(" (Unknown)"); + result += kUnknownStr; } - result += addIntToString(getSwingHorizontal(), F("Swing (H)")); + result += ')'; + result += addIntToString(getSwingHorizontal(), kSwingHStr); + result += kSpaceLBraceStr; switch (getSwingHorizontal()) { case kDaikin2SwingHAuto: - result += F(" (Auto)"); + result += kAutoStr; break; case kDaikin2SwingHSwing: - result += F(" (Swing)"); + result += kSwingStr; break; + default: result += kUnknownStr; } - result += addLabeledString(minsToString(getCurrentTime()), F("Clock")); + result += ')'; + result += addLabeledString(minsToString(getCurrentTime()), kClockStr); result += addLabeledString( - getOnTimerEnabled() ? minsToString(getOnTime()) : F("Off"), F("On Time")); + getOnTimerEnabled() ? minsToString(getOnTime()) : kOffStr, kOnTimerStr); result += addLabeledString( - getOffTimerEnabled() ? minsToString(getOffTime()) : F("Off"), - F("Off Time")); + getOffTimerEnabled() ? minsToString(getOffTime()) : kOffStr, + kOffTimerStr); result += addLabeledString( - getSleepTimerEnabled() ? minsToString(getSleepTime()) : F("Off"), - F("Sleep Time")); - result += addIntToString(getBeep(), F("Beep")); + getSleepTimerEnabled() ? minsToString(getSleepTime()) : kOffStr, + kSleepStr + ' ' + kTimerStr); + result += addIntToString(getBeep(), kBeepStr); + result += kSpaceLBraceStr; switch (getBeep()) { case kDaikinBeepLoud: - result += F(" (Loud)"); + result += kLoudStr; break; case kDaikinBeepQuiet: - result += F(" (Quiet)"); + result += kQuietStr; break; case kDaikinBeepOff: - result += F(" (Off)"); + result += kOffStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } - result += addIntToString(getLight(), F("Light")); + result += ')'; + result += addIntToString(getLight(), kLightStr); + result += kSpaceLBraceStr; switch (getLight()) { case kDaikinLightBright: - result += F(" (Bright)"); + result += kHighStr; break; case kDaikinLightDim: - result += F(" (Dim)"); + result += kLowStr; break; case kDaikinLightOff: - result += F(" (Off)"); + result += kOffStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } - result += addBoolToString(getMold(), F("Mold")); - result += addBoolToString(getClean(), F("Clean")); + result += ')'; + result += addBoolToString(getMold(), kMouldStr); + result += addBoolToString(getClean(), kCleanStr); result += addLabeledString( - getFreshAir() ? (getFreshAirHigh() ? F("High") : F("On")) : F("Off"), - F("Fresh Air")); - result += addBoolToString(getEye(), F("Eye")); - result += addBoolToString(getEyeAuto(), F("Eye Auto")); - result += addBoolToString(getQuiet(), F("Quiet")); - result += addBoolToString(getPowerful(), F("Powerful")); - result += addBoolToString(getPurify(), F("Purify")); - result += addBoolToString(getEcono(), F("Econo")); + getFreshAir() ? (getFreshAirHigh() ? kHighStr : kOnStr) : kOffStr, + kFreshStr); + result += addBoolToString(getEye(), kEyeStr); + result += addBoolToString(getEyeAuto(), kEyeStr + ' ' + kAutoStr); + result += addBoolToString(getQuiet(), kQuietStr); + result += addBoolToString(getPowerful(), kPowerfulStr); + result += addBoolToString(getPurify(), kPurifyStr); + result += addBoolToString(getEcono(), kEconoStr); return result; } @@ -1365,12 +1314,11 @@ IRDaikin216::IRDaikin216(const uint16_t pin, const bool inverted, const bool use_modulation) : _irsend(pin, inverted, use_modulation) { stateReset(); } -void IRDaikin216::begin() { _irsend.begin(); } +void IRDaikin216::begin(void) { _irsend.begin(); } #if SEND_DAIKIN216 void IRDaikin216::send(const uint16_t repeat) { - checksum(); - _irsend.sendDaikin216(remote_state, kDaikin216StateLength, repeat); + _irsend.sendDaikin216(getRaw(), kDaikin216StateLength, repeat); } #endif // SEND_DAIKIN216 @@ -1395,14 +1343,14 @@ bool IRDaikin216::validChecksum(uint8_t state[], const uint16_t length) { } // Calculate and set the checksum values for the internal state. -void IRDaikin216::checksum() { +void IRDaikin216::checksum(void) { remote_state[kDaikin216Section1Length - 1] = sumBytes( remote_state, kDaikin216Section1Length - 1); remote_state[kDaikin216StateLength - 1] = sumBytes( remote_state + kDaikin216Section1Length, kDaikin216Section2Length - 1); } -void IRDaikin216::stateReset() { +void IRDaikin216::stateReset(void) { for (uint8_t i = 0; i < kDaikin216StateLength; i++) remote_state[i] = 0x00; remote_state[0] = 0x11; remote_state[1] = 0xDA; @@ -1416,38 +1364,29 @@ void IRDaikin216::stateReset() { // remote_state[26] is a checksum byte, it will be set by checksum(). } -uint8_t *IRDaikin216::getRaw() { +uint8_t *IRDaikin216::getRaw(void) { checksum(); // Ensure correct settings before sending. return remote_state; } void IRDaikin216::setRaw(const uint8_t new_code[]) { - for (uint8_t i = 0; i < kDaikin216StateLength; i++) - remote_state[i] = new_code[i]; + memcpy(remote_state, new_code, kDaikin216StateLength); } +void IRDaikin216::on(void) { setPower(true); } -void IRDaikin216::on() { - remote_state[kDaikin216BytePower] |= kDaikinBitPower; +void IRDaikin216::off(void) { setPower(false); } + +void IRDaikin216::setPower(const bool on) { + setBit(&remote_state[kDaikin216BytePower], kDaikinBitPowerOffset, on); } -void IRDaikin216::off() { - remote_state[kDaikin216BytePower] &= ~kDaikinBitPower; +bool IRDaikin216::getPower(void) { + return GETBIT8(remote_state[kDaikin216BytePower], kDaikinBitPowerOffset); } -void IRDaikin216::setPower(const bool state) { - if (state) - on(); - else - off(); -} - -bool IRDaikin216::getPower() { - return remote_state[kDaikin216BytePower] & kDaikinBitPower; -} - -uint8_t IRDaikin216::getMode() { - return (remote_state[kDaikin216ByteMode] & kDaikin216MaskMode) >> 4; +uint8_t IRDaikin216::getMode(void) { + return GETBITS8(remote_state[kDaikin216ByteMode], kHighNibble, kModeBitsSize); } void IRDaikin216::setMode(const uint8_t mode) { @@ -1457,8 +1396,8 @@ void IRDaikin216::setMode(const uint8_t mode) { case kDaikinHeat: case kDaikinFan: case kDaikinDry: - remote_state[kDaikin216ByteMode] &= ~kDaikin216MaskMode; - remote_state[kDaikin216ByteMode] |= (mode << 4); + setBits(&remote_state[kDaikin216ByteMode], kHighNibble, kModeBitsSize, + mode); break; default: this->setMode(kDaikinAuto); @@ -1474,12 +1413,13 @@ uint8_t IRDaikin216::convertMode(const stdAc::opmode_t mode) { void IRDaikin216::setTemp(const uint8_t temp) { uint8_t degrees = std::max(temp, kDaikinMinTemp); degrees = std::min(degrees, kDaikinMaxTemp); - remote_state[kDaikin216ByteTemp] &= ~kDaikin216MaskTemp; - remote_state[kDaikin216ByteTemp] |= (degrees << 1); + setBits(&remote_state[kDaikin216ByteTemp], kDaikin216TempOffset, + kDaikin216TempSize, degrees); } uint8_t IRDaikin216::getTemp(void) { - return (remote_state[kDaikin216ByteTemp] & kDaikin216MaskTemp) >> 1; + return GETBITS8(remote_state[kDaikin216ByteTemp], kDaikin216TempOffset, + kDaikin216TempSize); } // Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet @@ -1492,12 +1432,13 @@ void IRDaikin216::setFan(const uint8_t fan) { fanset = kDaikinFanAuto; else fanset = 2 + fan; - remote_state[kDaikin216ByteFan] &= ~kDaikin216MaskFan; - remote_state[kDaikin216ByteFan] |= (fanset << 4); + setBits(&remote_state[kDaikin216ByteFan], kHighNibble, kDaikinFanSize, + fanset); } -uint8_t IRDaikin216::getFan() { - uint8_t fan = remote_state[kDaikin216ByteFan] >> 4; +uint8_t IRDaikin216::getFan(void) { + uint8_t fan = GETBITS8(remote_state[kDaikin216ByteFan], kHighNibble, + kDaikinFanSize); if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2; return fan; } @@ -1508,25 +1449,23 @@ uint8_t IRDaikin216::convertFan(const stdAc::fanspeed_t speed) { } void IRDaikin216::setSwingVertical(const bool on) { - if (on) - remote_state[kDaikin216ByteSwingV] |= kDaikin216MaskSwingV; - else - remote_state[kDaikin216ByteSwingV] &= ~kDaikin216MaskSwingV; + setBits(&remote_state[kDaikin216ByteSwingV], kLowNibble, kDaikin216SwingSize, + on ? kDaikin216SwingOn : kDaikin216SwingOff); } bool IRDaikin216::getSwingVertical(void) { - return remote_state[kDaikin216ByteSwingV] & kDaikin216MaskSwingV; + return GETBITS8(remote_state[kDaikin216ByteSwingV], kLowNibble, + kDaikin216SwingSize); } void IRDaikin216::setSwingHorizontal(const bool on) { - if (on) - remote_state[kDaikin216ByteSwingH] |= kDaikin216MaskSwingH; - else - remote_state[kDaikin216ByteSwingH] &= ~kDaikin216MaskSwingH; + setBits(&remote_state[kDaikin216ByteSwingH], kLowNibble, kDaikin216SwingSize, + on ? kDaikin216SwingOn : kDaikin216SwingOff); } bool IRDaikin216::getSwingHorizontal(void) { - return remote_state[kDaikin216ByteSwingH] & kDaikin216MaskSwingH; + return GETBITS8(remote_state[kDaikin216ByteSwingH], kLowNibble, + kDaikin216SwingSize); } // This is a horrible hack till someone works out the quiet mode bit. @@ -1546,17 +1485,14 @@ bool IRDaikin216::getQuiet(void) { } void IRDaikin216::setPowerful(const bool on) { - if (on) { - remote_state[kDaikin216BytePowerful] |= kDaikinBitPowerful; - // Powerful & Quiet mode being on are mutually exclusive. - this->setQuiet(false); - } else { - remote_state[kDaikin216BytePowerful] &= ~kDaikinBitPowerful; - } + setBit(&remote_state[kDaikin216BytePowerful], kDaikinBitPowerfulOffset, on); + // Powerful & Quiet mode being on are mutually exclusive. + if (on) this->setQuiet(false); } -bool IRDaikin216::getPowerful() { - return remote_state[kDaikin216BytePowerful] & kDaikinBitPowerful; +bool IRDaikin216::getPowerful(void) { + return GETBIT8(remote_state[kDaikin216BytePowerful], + kDaikinBitPowerfulOffset); } // Convert the A/C state to it's common equivalent. @@ -1587,19 +1523,19 @@ stdAc::state_t IRDaikin216::toCommon(void) { } // Convert the internal state into a human readable string. -String IRDaikin216::toString() { +String IRDaikin216::toString(void) { String result = ""; result.reserve(120); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kDaikinAuto, kDaikinCool, kDaikinHeat, kDaikinDry, kDaikinFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kDaikinFanMax, kDaikinFanMin, kDaikinFanAuto, kDaikinFanQuiet, kDaikinFanMed); - result += addBoolToString(getSwingHorizontal(), F("Swing (Horizontal)")); - result += addBoolToString(getSwingVertical(), F("Swing (Vertical)")); - result += addBoolToString(getQuiet(), F("Quiet")); - result += addBoolToString(getPowerful(), F("Powerful")); + result += addBoolToString(getSwingHorizontal(), kSwingHStr); + result += addBoolToString(getSwingVertical(), kSwingVStr); + result += addBoolToString(getQuiet(), kQuietStr); + result += addBoolToString(getPowerful(), kPowerfulStr); return result; } @@ -1713,7 +1649,7 @@ IRDaikin160::IRDaikin160(const uint16_t pin, const bool inverted, const bool use_modulation) : _irsend(pin, inverted, use_modulation) { stateReset(); } -void IRDaikin160::begin() { _irsend.begin(); } +void IRDaikin160::begin(void) { _irsend.begin(); } // Verify the checksum is valid for a given state. // Args: @@ -1736,14 +1672,14 @@ bool IRDaikin160::validChecksum(uint8_t state[], const uint16_t length) { } // Calculate and set the checksum values for the internal state. -void IRDaikin160::checksum() { +void IRDaikin160::checksum(void) { remote_state[kDaikin160Section1Length - 1] = sumBytes( remote_state, kDaikin160Section1Length - 1); remote_state[kDaikin160StateLength - 1] = sumBytes( remote_state + kDaikin160Section1Length, kDaikin160Section2Length - 1); } -void IRDaikin160::stateReset() { +void IRDaikin160::stateReset(void) { for (uint8_t i = 0; i < kDaikin160StateLength; i++) remote_state[i] = 0x00; remote_state[0] = 0x11; remote_state[1] = 0xDA; @@ -1763,44 +1699,35 @@ void IRDaikin160::stateReset() { // remote_state[19] is a checksum byte, it will be set by checksum(). } -uint8_t *IRDaikin160::getRaw() { +uint8_t *IRDaikin160::getRaw(void) { checksum(); // Ensure correct settings before sending. return remote_state; } void IRDaikin160::setRaw(const uint8_t new_code[]) { - for (uint8_t i = 0; i < kDaikin160StateLength; i++) - remote_state[i] = new_code[i]; + memcpy(remote_state, new_code, kDaikin160StateLength); } #if SEND_DAIKIN160 void IRDaikin160::send(const uint16_t repeat) { - checksum(); - _irsend.sendDaikin160(remote_state, kDaikin160StateLength, repeat); + _irsend.sendDaikin160(getRaw(), kDaikin160StateLength, repeat); } #endif // SEND_DAIKIN160 -void IRDaikin160::on() { - remote_state[kDaikin160BytePower] |= kDaikinBitPower; +void IRDaikin160::on(void) { setPower(true); } + +void IRDaikin160::off(void) { setPower(false); } + +void IRDaikin160::setPower(const bool on) { + setBit(&remote_state[kDaikin160BytePower], kDaikinBitPowerOffset, on); } -void IRDaikin160::off() { - remote_state[kDaikin160BytePower] &= ~kDaikinBitPower; +bool IRDaikin160::getPower(void) { + return GETBIT8(remote_state[kDaikin160BytePower], kDaikinBitPowerOffset); } -void IRDaikin160::setPower(const bool state) { - if (state) - on(); - else - off(); -} - -bool IRDaikin160::getPower() { - return remote_state[kDaikin160BytePower] & kDaikinBitPower; -} - -uint8_t IRDaikin160::getMode() { - return (remote_state[kDaikin160ByteMode] & kDaikin160MaskMode) >> 4; +uint8_t IRDaikin160::getMode(void) { + return GETBITS8(remote_state[kDaikin160ByteMode], kHighNibble, kModeBitsSize); } void IRDaikin160::setMode(const uint8_t mode) { @@ -1810,11 +1737,10 @@ void IRDaikin160::setMode(const uint8_t mode) { case kDaikinHeat: case kDaikinFan: case kDaikinDry: - remote_state[kDaikin160ByteMode] &= ~kDaikin160MaskMode; - remote_state[kDaikin160ByteMode] |= (mode << 4); + setBits(&remote_state[kDaikin160ByteMode], kHighNibble, kModeBitsSize, + mode); break; - default: - this->setMode(kDaikinAuto); + default: this->setMode(kDaikinAuto); } } @@ -1826,13 +1752,14 @@ uint8_t IRDaikin160::convertMode(const stdAc::opmode_t mode) { // Set the temp in deg C void IRDaikin160::setTemp(const uint8_t temp) { uint8_t degrees = std::max(temp, kDaikinMinTemp); - degrees = std::min(degrees, kDaikinMaxTemp) * 2 - 20; - remote_state[kDaikin160ByteTemp] &= ~kDaikin160MaskTemp; - remote_state[kDaikin160ByteTemp] |= degrees; + degrees = std::min(degrees, kDaikinMaxTemp) - 10; + setBits(&remote_state[kDaikin160ByteTemp], kDaikin160TempOffset, + kDaikin160TempSize, degrees); } uint8_t IRDaikin160::getTemp(void) { - return (((remote_state[kDaikin160ByteTemp] & kDaikin160MaskTemp) / 2 ) + 10); + return GETBITS8(remote_state[kDaikin160ByteTemp], kDaikin160TempOffset, + kDaikin160TempSize) + 10; } // Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet @@ -1845,12 +1772,12 @@ void IRDaikin160::setFan(const uint8_t fan) { else fanset = 2 + fan; // Set the fan speed bits, leave *upper* 4 bits alone - remote_state[kDaikin160ByteFan] &= ~kDaikin160MaskFan; - remote_state[kDaikin160ByteFan] |= fanset; + setBits(&remote_state[kDaikin160ByteFan], kLowNibble, kDaikinFanSize, fanset); } -uint8_t IRDaikin160::getFan() { - uint8_t fan = remote_state[kDaikin160ByteFan] & kDaikin160MaskFan; +uint8_t IRDaikin160::getFan(void) { + uint8_t fan = GETBITS8(remote_state[kDaikin160ByteFan], kLowNibble, + kDaikinFanSize); if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2; return fan; } @@ -1876,16 +1803,16 @@ void IRDaikin160::setSwingVertical(const uint8_t position) { case kDaikin160SwingVHigh: case kDaikin160SwingVHighest: case kDaikin160SwingVAuto: - remote_state[kDaikin160ByteSwingV] &= ~kDaikin160MaskSwingV; - remote_state[kDaikin160ByteSwingV] |= (position << 4); + setBits(&remote_state[kDaikin160ByteSwingV], kHighNibble, + kDaikinSwingSize, position); break; - default: - setSwingVertical(kDaikin160SwingVAuto); + default: setSwingVertical(kDaikin160SwingVAuto); } } uint8_t IRDaikin160::getSwingVertical(void) { - return remote_state[kDaikin160ByteSwingV] >> 4; + return GETBITS8(remote_state[kDaikin160ByteSwingV], kHighNibble, + kDaikinSwingSize); } // Convert a standard A/C vertical swing into its native version. @@ -1941,26 +1868,27 @@ stdAc::state_t IRDaikin160::toCommon(void) { } // Convert the internal state into a human readable string. -String IRDaikin160::toString() { +String IRDaikin160::toString(void) { String result = ""; result.reserve(150); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kDaikinAuto, kDaikinCool, kDaikinHeat, kDaikinDry, kDaikinFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kDaikinFanMax, kDaikinFanMin, kDaikinFanAuto, kDaikinFanQuiet, kDaikinFanMed); - result += addIntToString(getSwingVertical(), F("Vent Position (V)")); + result += addIntToString(getSwingVertical(), kSwingVStr); + result += kSpaceLBraceStr; switch (getSwingVertical()) { - case kDaikin160SwingVHighest: result += F(" (Highest)"); break; - case kDaikin160SwingVHigh: result += F(" (High)"); break; - case kDaikin160SwingVMiddle: result += F(" (Middle)"); break; - case kDaikin160SwingVLow: result += F(" (Low)"); break; - case kDaikin160SwingVLowest: result += F(" (Lowest)"); break; - case kDaikin160SwingVAuto: result += F(" (Auto)"); break; - default: - result += F(" (Unknown)"); + case kDaikin160SwingVHighest: result += kHighestStr; break; + case kDaikin160SwingVHigh: result += kHighStr; break; + case kDaikin160SwingVMiddle: result += kMiddleStr; break; + case kDaikin160SwingVLow: result += kLowStr; break; + case kDaikin160SwingVLowest: result += kLowestStr; break; + case kDaikin160SwingVAuto: result += kAutoStr; break; + default: result += kUnknownStr; } + result += ')'; return result; } @@ -2069,7 +1997,7 @@ IRDaikin176::IRDaikin176(const uint16_t pin, const bool inverted, const bool use_modulation) : _irsend(pin, inverted, use_modulation) { stateReset(); } -void IRDaikin176::begin() { _irsend.begin(); } +void IRDaikin176::begin(void) { _irsend.begin(); } // Verify the checksum is valid for a given state. // Args: @@ -2092,14 +2020,14 @@ bool IRDaikin176::validChecksum(uint8_t state[], const uint16_t length) { } // Calculate and set the checksum values for the internal state. -void IRDaikin176::checksum() { +void IRDaikin176::checksum(void) { remote_state[kDaikin176Section1Length - 1] = sumBytes( remote_state, kDaikin176Section1Length - 1); remote_state[kDaikin176StateLength - 1] = sumBytes( remote_state + kDaikin176Section1Length, kDaikin176Section2Length - 1); } -void IRDaikin176::stateReset() { +void IRDaikin176::stateReset(void) { for (uint8_t i = 0; i < kDaikin176StateLength; i++) remote_state[i] = 0x00; remote_state[0] = 0x11; remote_state[1] = 0xDA; @@ -2119,42 +2047,37 @@ void IRDaikin176::stateReset() { _saved_temp = getTemp(); } -uint8_t *IRDaikin176::getRaw() { +uint8_t *IRDaikin176::getRaw(void) { checksum(); // Ensure correct settings before sending. return remote_state; } void IRDaikin176::setRaw(const uint8_t new_code[]) { - for (uint8_t i = 0; i < kDaikin176StateLength; i++) - remote_state[i] = new_code[i]; + memcpy(remote_state, new_code, kDaikin176StateLength); _saved_temp = getTemp(); } #if SEND_DAIKIN176 void IRDaikin176::send(const uint16_t repeat) { - checksum(); - _irsend.sendDaikin176(remote_state, kDaikin176StateLength, repeat); + _irsend.sendDaikin176(getRaw(), kDaikin176StateLength, repeat); } #endif // SEND_DAIKIN176 -void IRDaikin176::on() { setPower(true); } +void IRDaikin176::on(void) { setPower(true); } -void IRDaikin176::off() { setPower(false); } +void IRDaikin176::off(void) { setPower(false); } -void IRDaikin176::setPower(const bool state) { +void IRDaikin176::setPower(const bool on) { remote_state[kDaikin176ByteModeButton] = 0; - if (state) - remote_state[kDaikin176BytePower] |= kDaikinBitPower; - else - remote_state[kDaikin176BytePower] &= ~kDaikinBitPower; + setBit(&remote_state[kDaikin176BytePower], kDaikinBitPowerOffset, on); } -bool IRDaikin176::getPower() { - return remote_state[kDaikin176BytePower] & kDaikinBitPower; +bool IRDaikin176::getPower(void) { + return GETBIT8(remote_state[kDaikin176BytePower], kDaikinBitPowerOffset); } -uint8_t IRDaikin176::getMode() { - return (remote_state[kDaikin176ByteMode] & kDaikin176MaskMode) >> 4; +uint8_t IRDaikin176::getMode(void) { + return GETBITS8(remote_state[kDaikin176ByteMode], kHighNibble, kModeBitsSize); } void IRDaikin176::setMode(const uint8_t mode) { @@ -2166,11 +2089,9 @@ void IRDaikin176::setMode(const uint8_t mode) { default: this->setMode(kDaikin176Cool); return; } // Set the mode. - remote_state[kDaikin176ByteMode] &= ~kDaikin176MaskMode; - remote_state[kDaikin176ByteMode] |= (mode << 4); - // Set the altmode - remote_state[kDaikin176BytePower] &= ~kDaikin176MaskMode; - remote_state[kDaikin176BytePower] |= (altmode << 4); + setBits(&remote_state[kDaikin176ByteMode], kHighNibble, kModeBitsSize, mode); + setBits(&remote_state[kDaikin176BytePower], kHighNibble, kModeBitsSize, + altmode); setTemp(_saved_temp); // Needs to happen after setTemp() as it will clear it. remote_state[kDaikin176ByteModeButton] = kDaikin176ModeButton; @@ -2179,13 +2100,10 @@ void IRDaikin176::setMode(const uint8_t mode) { // Convert a standard A/C mode into its native mode. uint8_t IRDaikin176::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kDry: - return kDaikinDry; + case stdAc::opmode_t::kDry: return kDaikinDry; case stdAc::opmode_t::kHeat: // Heat not supported, but fan is the closest. - case stdAc::opmode_t::kFan: - return kDaikinFan; - default: - return kDaikin176Cool; + case stdAc::opmode_t::kFan: return kDaikinFan; + default: return kDaikin176Cool; } } @@ -2208,14 +2126,14 @@ void IRDaikin176::setTemp(const uint8_t temp) { case kDaikinFan: degrees = kDaikin176DryFanTemp; } - degrees = degrees * 2 - 18; - remote_state[kDaikin176ByteTemp] &= ~kDaikin176MaskTemp; - remote_state[kDaikin176ByteTemp] |= degrees; + setBits(&remote_state[kDaikin176ByteTemp], kDaikin176TempOffset, + kDaikin176TempSize, degrees - 9); remote_state[kDaikin176ByteModeButton] = 0; } uint8_t IRDaikin176::getTemp(void) { - return (((remote_state[kDaikin176ByteTemp] & kDaikin176MaskTemp) / 2 ) + 9); + return GETBITS8(remote_state[kDaikin176ByteTemp], kDaikin176TempOffset, + kDaikin176TempSize) + 9; } // Set the speed of the fan, 1 for Min or 3 for Max @@ -2223,8 +2141,8 @@ void IRDaikin176::setFan(const uint8_t fan) { switch (fan) { case kDaikinFanMin: case kDaikin176FanMax: - remote_state[kDaikin176ByteFan] &= ~kDaikin176MaskFan; - remote_state[kDaikin176ByteFan] |= (fan << 4); + setBits(&remote_state[kDaikin176ByteFan], kHighNibble, kDaikinFanSize, + fan); remote_state[kDaikin176ByteModeButton] = 0; break; default: @@ -2232,16 +2150,16 @@ void IRDaikin176::setFan(const uint8_t fan) { } } -uint8_t IRDaikin176::getFan() { return remote_state[kDaikin176ByteFan] >> 4; } +uint8_t IRDaikin176::getFan(void) { + return GETBITS8(remote_state[kDaikin176ByteFan], kHighNibble, kDaikinFanSize); +} // Convert a standard A/C Fan speed into its native fan speed. uint8_t IRDaikin176::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kDaikinFanMin; - default: - return kDaikin176FanMax; + case stdAc::fanspeed_t::kLow: return kDaikinFanMin; + default: return kDaikin176FanMax; } } @@ -2249,27 +2167,24 @@ void IRDaikin176::setSwingHorizontal(const uint8_t position) { switch (position) { case kDaikin176SwingHOff: case kDaikin176SwingHAuto: - remote_state[kDaikin176ByteSwingH] &= ~kDaikin176MaskSwingH; - remote_state[kDaikin176ByteSwingH] |= position; + setBits(&remote_state[kDaikin176ByteSwingH], kLowNibble, kDaikinSwingSize, + position); break; - default: - setSwingHorizontal(kDaikin176SwingHAuto); + default: setSwingHorizontal(kDaikin176SwingHAuto); } } -uint8_t IRDaikin176::getSwingHorizontal() { - return remote_state[kDaikin176ByteSwingH] & kDaikin176MaskSwingH; +uint8_t IRDaikin176::getSwingHorizontal(void) { + return GETBITS8(remote_state[kDaikin176ByteSwingH], kLowNibble, + kDaikinSwingSize); } // Convert a standard A/C horizontal swing into its native version. uint8_t IRDaikin176::convertSwingH(const stdAc::swingh_t position) { switch (position) { - case stdAc::swingh_t::kOff: - return kDaikin176SwingHOff; - case stdAc::swingh_t::kAuto: - return kDaikin176SwingHAuto; - default: - return kDaikin176SwingHAuto; + case stdAc::swingh_t::kOff: return kDaikin176SwingHOff; + case stdAc::swingh_t::kAuto: return kDaikin176SwingHAuto; + default: return kDaikin176SwingHAuto; } } // Convert a native horizontal swing to it's common equivalent. @@ -2315,27 +2230,28 @@ stdAc::state_t IRDaikin176::toCommon(void) { } // Convert the internal state into a human readable string. -String IRDaikin176::toString() { +String IRDaikin176::toString(void) { String result = ""; result.reserve(80); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kDaikinAuto, kDaikin176Cool, kDaikinHeat, kDaikinDry, kDaikinFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kDaikin176FanMax, kDaikinFanMin, kDaikinFanMin, kDaikinFanMin, kDaikinFanMin); - result += F(", Swing (H): "); - result += uint64ToString(getSwingHorizontal()); + result += addIntToString(getSwingHorizontal(), kSwingHStr); + result += kSpaceLBraceStr; switch (getSwingHorizontal()) { case kDaikin176SwingHAuto: - result += F(" (Auto)"); + result += kAutoStr; break; case kDaikin176SwingHOff: - result += F(" (Off)"); + result += kOffStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } + result += ')'; return result; } @@ -2453,7 +2369,7 @@ IRDaikin128::IRDaikin128(const uint16_t pin, const bool inverted, const bool use_modulation) : _irsend(pin, inverted, use_modulation) { stateReset(); } -void IRDaikin128::begin() { _irsend.begin(); } +void IRDaikin128::begin(void) { _irsend.begin(); } uint8_t IRDaikin128::calcFirstChecksum(const uint8_t state[]) { return sumNibbles(state, kDaikin128SectionLength - 1, @@ -2481,14 +2397,14 @@ bool IRDaikin128::validChecksum(uint8_t state[]) { } // Calculate and set the checksum values for the internal state. -void IRDaikin128::checksum() { +void IRDaikin128::checksum(void) { remote_state[kDaikin128SectionLength - 1] &= 0x0F; // Clear upper half. remote_state[kDaikin128SectionLength - 1] |= (calcFirstChecksum(remote_state) << 4); remote_state[kDaikin128StateLength - 1] = calcSecondChecksum(remote_state); } -void IRDaikin128::stateReset() { +void IRDaikin128::stateReset(void) { for (uint8_t i = 0; i < kDaikin128StateLength; i++) remote_state[i] = 0x00; remote_state[0] = 0x16; remote_state[7] = 0x04; // Most significant nibble is a checksum. @@ -2496,36 +2412,34 @@ void IRDaikin128::stateReset() { // remote_state[15] is a checksum byte, it will be set by checksum(). } -uint8_t *IRDaikin128::getRaw() { +uint8_t *IRDaikin128::getRaw(void) { checksum(); // Ensure correct settings before sending. return remote_state; } void IRDaikin128::setRaw(const uint8_t new_code[]) { - for (uint8_t i = 0; i < kDaikin128StateLength; i++) - remote_state[i] = new_code[i]; + memcpy(remote_state, new_code, kDaikin128StateLength); } #if SEND_DAIKIN128 void IRDaikin128::send(const uint16_t repeat) { - checksum(); - _irsend.sendDaikin128(remote_state, kDaikin128StateLength, repeat); + _irsend.sendDaikin128(getRaw(), kDaikin128StateLength, repeat); } #endif // SEND_DAIKIN128 void IRDaikin128::setPowerToggle(const bool toggle) { - if (toggle) - remote_state[kDaikin128BytePowerSwingSleep] |= kDaikin128BitPowerToggle; - else - remote_state[kDaikin128BytePowerSwingSleep] &= ~kDaikin128BitPowerToggle; + setBit(&remote_state[kDaikin128BytePowerSwingSleep], + kDaikin128BitPowerToggleOffset, toggle); } bool IRDaikin128::getPowerToggle(void) { - return remote_state[kDaikin128BytePowerSwingSleep] & kDaikin128BitPowerToggle; + return GETBIT8(remote_state[kDaikin128BytePowerSwingSleep], + kDaikin128BitPowerToggleOffset); } -uint8_t IRDaikin128::getMode() { - return remote_state[kDaikin128ByteModeFan] & kDaikin128MaskMode; +uint8_t IRDaikin128::getMode(void) { + return GETBITS8(remote_state[kDaikin128ByteModeFan], kLowNibble, + kDaikin128ModeSize); } void IRDaikin128::setMode(const uint8_t mode) { @@ -2535,8 +2449,8 @@ void IRDaikin128::setMode(const uint8_t mode) { case kDaikin128Heat: case kDaikin128Fan: case kDaikin128Dry: - remote_state[kDaikin128ByteModeFan] &= ~kDaikin128MaskMode; - remote_state[kDaikin128ByteModeFan] |= mode; + setBits(&remote_state[kDaikin128ByteModeFan], kLowNibble, + kDaikin128ModeSize, mode); break; default: this->setMode(kDaikin128Auto); @@ -2550,16 +2464,11 @@ void IRDaikin128::setMode(const uint8_t mode) { // Convert a standard A/C mode into its native mode. uint8_t IRDaikin128::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kDaikin128Cool; - case stdAc::opmode_t::kHeat: - return kDaikin128Heat; - case stdAc::opmode_t::kDry: - return kDaikinDry; - case stdAc::opmode_t::kFan: - return kDaikin128Fan; - default: - return kDaikin128Auto; + case stdAc::opmode_t::kCool: return kDaikin128Cool; + case stdAc::opmode_t::kHeat: return kDaikin128Heat; + case stdAc::opmode_t::kDry: return kDaikinDry; + case stdAc::opmode_t::kFan: return kDaikin128Fan; + default: return kDaikin128Auto; } } @@ -2584,8 +2493,9 @@ uint8_t IRDaikin128::getTemp(void) { return bcdToUint8(remote_state[kDaikin128ByteTemp]); } -uint8_t IRDaikin128::getFan() { - return (remote_state[kDaikin128ByteModeFan] & kDaikin128MaskFan) >> 4; +uint8_t IRDaikin128::getFan(void) { + return GETBITS8(remote_state[kDaikin128ByteModeFan], kHighNibble, + kDaikinFanSize); } void IRDaikin128::setFan(const uint8_t speed) { @@ -2600,9 +2510,8 @@ void IRDaikin128::setFan(const uint8_t speed) { case kDaikin128FanHigh: case kDaikin128FanMed: case kDaikin128FanLow: - // if (mode == kDaikinDry) new_speed = kDaikin128FanMed; - remote_state[kDaikin128ByteModeFan] &= ~kDaikin128MaskFan; - remote_state[kDaikin128ByteModeFan] |= (new_speed << 4); + setBits(&remote_state[kDaikin128ByteModeFan], kHighNibble, kDaikinFanSize, + new_speed); break; default: this->setFan(kDaikin128FanAuto); @@ -2634,37 +2543,34 @@ stdAc::fanspeed_t IRDaikin128::toCommonFanSpeed(const uint8_t speed) { } void IRDaikin128::setSwingVertical(const bool on) { - if (on) - remote_state[kDaikin128BytePowerSwingSleep] |= kDaikin128BitSwing; - else - remote_state[kDaikin128BytePowerSwingSleep] &= ~kDaikin128BitSwing; + setBit(&remote_state[kDaikin128BytePowerSwingSleep], kDaikin128BitSwingOffset, + on); } bool IRDaikin128::getSwingVertical(void) { - return remote_state[kDaikin128BytePowerSwingSleep] & kDaikin128BitSwing; + return GETBIT8(remote_state[kDaikin128BytePowerSwingSleep], + kDaikin128BitSwingOffset); } void IRDaikin128::setSleep(const bool on) { - if (on) - remote_state[kDaikin128BytePowerSwingSleep] |= kDaikin128BitSleep; - else - remote_state[kDaikin128BytePowerSwingSleep] &= ~kDaikin128BitSleep; + setBit(&remote_state[kDaikin128BytePowerSwingSleep], kDaikin128BitSleepOffset, + on); } bool IRDaikin128::getSleep(void) { - return remote_state[kDaikin128BytePowerSwingSleep] & kDaikin128BitSleep; + return GETBIT8(remote_state[kDaikin128BytePowerSwingSleep], + kDaikin128BitSleepOffset); } void IRDaikin128::setEcono(const bool on) { uint8_t mode = getMode(); - if (on && (mode == kDaikin128Cool || mode == kDaikin128Heat)) - remote_state[kDaikin128ByteEconoLight] |= kDaikin128BitEcono; - else - remote_state[kDaikin128ByteEconoLight] &= ~kDaikin128BitEcono; + setBit(&remote_state[kDaikin128ByteEconoLight], kDaikin128BitEconoOffset, + on && (mode == kDaikin128Cool || mode == kDaikin128Heat)); } bool IRDaikin128::getEcono(void) { - return remote_state[kDaikin128ByteEconoLight] & kDaikin128BitEcono; + return GETBIT8(remote_state[kDaikin128ByteEconoLight], + kDaikin128BitEconoOffset); } void IRDaikin128::setQuiet(const bool on) { @@ -2707,14 +2613,13 @@ uint16_t IRDaikin128::getClock(void) { } void IRDaikin128::setOnTimerEnabled(const bool on) { - if (on) - remote_state[kDaikin128ByteOnTimer] |= kDaikin128BitTimerEnabled; - else - remote_state[kDaikin128ByteOnTimer] &= ~kDaikin128BitTimerEnabled; + setBit(&remote_state[kDaikin128ByteOnTimer], kDaikin128BitTimerEnabledOffset, + on); } bool IRDaikin128::getOnTimerEnabled(void) { - return remote_state[kDaikin128ByteOnTimer] & kDaikin128BitTimerEnabled; + return GETBIT8(remote_state[kDaikin128ByteOnTimer], + kDaikin128BitTimerEnabledOffset); } // Timer is rounds down to the nearest half hour. @@ -2724,11 +2629,11 @@ bool IRDaikin128::getOnTimerEnabled(void) { void IRDaikin128::setTimer(uint8_t *ptr, const uint16_t mins_since_midnight) { uint16_t mins = mins_since_midnight; if (mins_since_midnight >= 24 * 60) mins = 0; // Bounds check. - // Clear the time component - *ptr &= kDaikin128BitTimerEnabled; - uint8_t bcdhours = uint8ToBcd(mins / 60); - bool addhalf = (mins % 60) >= 30; - *ptr |= ((addhalf << 6) | bcdhours); + // Set the half hour bit + setBit(ptr, kDaikin128HalfHourOffset, (mins % 60) >= 30); + // Set the nr of whole hours. + setBits(ptr, kDaikin128HoursOffset, kDaikin128HoursSize, + uint8ToBcd(mins / 60)); } // Timer is stored in nr of half hours internally. @@ -2737,9 +2642,9 @@ void IRDaikin128::setTimer(uint8_t *ptr, const uint16_t mins_since_midnight) { // Returns: // A uint16_t containing the number of minutes since midnight. uint16_t IRDaikin128::getTimer(const uint8_t *ptr) { - uint8_t bcdhours = *ptr & kDaikin128MaskHours; - bool addhalf = *ptr & kDaikin128BitHalfHour; - return bcdToUint8(bcdhours) * 60 + (addhalf ? 30 : 0); + return bcdToUint8(GETBITS8(*ptr, kDaikin128HoursOffset, + kDaikin128HoursSize)) * 60 + + (GETBIT8(*ptr, kDaikin128HalfHourOffset) ? 30 : 0); } void IRDaikin128::setOnTimer(const uint16_t mins_since_midnight) { @@ -2751,14 +2656,13 @@ uint16_t IRDaikin128::getOnTimer(void) { } void IRDaikin128::setOffTimerEnabled(const bool on) { - if (on) - remote_state[kDaikin128ByteOffTimer] |= kDaikin128BitTimerEnabled; - else - remote_state[kDaikin128ByteOffTimer] &= ~kDaikin128BitTimerEnabled; + setBit(&remote_state[kDaikin128ByteOffTimer], kDaikin128BitTimerEnabledOffset, + on); } bool IRDaikin128::getOffTimerEnabled(void) { - return remote_state[kDaikin128ByteOffTimer] & kDaikin128BitTimerEnabled; + return GETBIT8(remote_state[kDaikin128ByteOffTimer], + kDaikin128BitTimerEnabledOffset); } void IRDaikin128::setOffTimer(const uint16_t mins_since_midnight) { @@ -2771,9 +2675,9 @@ uint16_t IRDaikin128::getOffTimer(void) { void IRDaikin128::setLightToggle(const uint8_t unit) { switch (unit) { + case 0: case kDaikin128BitCeiling: case kDaikin128BitWall: - case 0: remote_state[kDaikin128ByteEconoLight] &= ~kDaikin128MaskLight; remote_state[kDaikin128ByteEconoLight] |= unit; break; @@ -2789,30 +2693,31 @@ uint8_t IRDaikin128::getLightToggle(void) { String IRDaikin128::toString(void) { String result = ""; result.reserve(240); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPowerToggle(), F("Power Toggle"), false); + result += addBoolToString(getPowerToggle(), kPowerStr + ' ' + kToggleStr, + false); result += addModeToString(getMode(), kDaikin128Auto, kDaikin128Cool, kDaikin128Heat, kDaikin128Dry, kDaikin128Fan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kDaikin128FanHigh, kDaikin128FanLow, kDaikin128FanAuto, kDaikin128FanQuiet, kDaikin128FanMed); - result += addBoolToString(getPowerful(), F("Powerful")); - result += addBoolToString(getQuiet(), F("Quiet")); - result += addBoolToString(getSwingVertical(), F("Swing (V)")); - result += addBoolToString(getSleep(), F("Sleep")); - result += addBoolToString(getEcono(), F("Econo")); - result += addLabeledString(minsToString(getClock()), F("Clock")); - result += addBoolToString(getOnTimerEnabled(), F("On Timer")); - result += addLabeledString(minsToString(getOnTimer()), F("On Time")); - result += addBoolToString(getOffTimerEnabled(), F("Off Timer")); - result += addLabeledString(minsToString(getOffTimer()), F("Off Time")); - result += addIntToString(getLightToggle(), F("Light Toggle")); - result += F(" ("); + result += addBoolToString(getPowerful(), kPowerfulStr); + result += addBoolToString(getQuiet(), kQuietStr); + result += addBoolToString(getSwingVertical(), kSwingVStr); + result += addBoolToString(getSleep(), kSleepStr); + result += addBoolToString(getEcono(), kEconoStr); + result += addLabeledString(minsToString(getClock()), kClockStr); + result += addBoolToString(getOnTimerEnabled(), kOnTimerStr); + result += addLabeledString(minsToString(getOnTimer()), kOnTimerStr); + result += addBoolToString(getOffTimerEnabled(), kOffTimerStr); + result += addLabeledString(minsToString(getOffTimer()), kOffTimerStr); + result += addIntToString(getLightToggle(), kLightStr + ' ' + kToggleStr); + result += kSpaceLBraceStr; switch (getLightToggle()) { - case kDaikin128BitCeiling: result += F("Ceiling"); break; - case kDaikin128BitWall: result += F("Wall"); break; - case 0: result += F("Off"); break; - default: result += F("UNKNOWN"); + case kDaikin128BitCeiling: result += kCeilingStr; break; + case kDaikin128BitWall: result += kWallStr; break; + case 0: result += kOffStr; break; + default: result += kUnknownStr; } result += ')'; return result; @@ -2924,7 +2829,7 @@ bool IRrecv::decodeDaikin128(decode_results *results, const uint16_t nbits, // Supported devices: // - Daikin ARC480A5 remote. // -// Status: Beta / Probably working. +// Status: STABLE / Known working. // // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/873 void IRsend::sendDaikin152(const unsigned char data[], const uint16_t nbytes, @@ -2957,7 +2862,7 @@ void IRsend::sendDaikin152(const unsigned char data[], const uint16_t nbytes, // Supported devices: // - Daikin ARC480A5 remote. // -// Status: Beta / Probably working. +// Status: STABLE / Known working. // // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/873 bool IRrecv::decodeDaikin152(decode_results *results, const uint16_t nbits, @@ -3017,16 +2922,17 @@ bool IRrecv::decodeDaikin152(decode_results *results, const uint16_t nbits, // // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/873 +// https://github.com/ToniA/arduino-heatpumpir/blob/master/DaikinHeatpumpARC480A14IR.cpp +// https://github.com/ToniA/arduino-heatpumpir/blob/master/DaikinHeatpumpARC480A14IR.h IRDaikin152::IRDaikin152(const uint16_t pin, const bool inverted, const bool use_modulation) : _irsend(pin, inverted, use_modulation) { stateReset(); } -void IRDaikin152::begin() { _irsend.begin(); } +void IRDaikin152::begin(void) { _irsend.begin(); } #if SEND_DAIKIN152 void IRDaikin152::send(const uint16_t repeat) { - checksum(); - _irsend.sendDaikin152(remote_state, kDaikin152StateLength, repeat); + _irsend.sendDaikin152(getRaw(), kDaikin152StateLength, repeat); } #endif // SEND_DAIKIN152 @@ -3045,25 +2951,223 @@ bool IRDaikin152::validChecksum(uint8_t state[], const uint16_t length) { } // Calculate and set the checksum values for the internal state. -void IRDaikin152::checksum() { +void IRDaikin152::checksum(void) { remote_state[kDaikin152StateLength - 1] = sumBytes( remote_state, kDaikin152StateLength - 1); } -void IRDaikin152::stateReset() { +void IRDaikin152::stateReset(void) { for (uint8_t i = 3; i < kDaikin152StateLength; i++) remote_state[i] = 0x00; remote_state[0] = 0x11; remote_state[1] = 0xDA; remote_state[2] = 0x27; + remote_state[15] = 0xC5; // remote_state[19] is a checksum byte, it will be set by checksum(). } -uint8_t *IRDaikin152::getRaw() { +uint8_t *IRDaikin152::getRaw(void) { checksum(); // Ensure correct settings before sending. return remote_state; } void IRDaikin152::setRaw(const uint8_t new_code[]) { - for (uint8_t i = 0; i < kDaikin152StateLength; i++) - remote_state[i] = new_code[i]; + memcpy(remote_state, new_code, kDaikin152StateLength); +} + +void IRDaikin152::on(void) { setPower(true); } + +void IRDaikin152::off(void) { setPower(false); } + +void IRDaikin152::setPower(const bool on) { + setBit(&remote_state[kDaikin152PowerByte], kDaikinBitPowerOffset, on); +} + +bool IRDaikin152::getPower(void) { + return GETBIT8(remote_state[kDaikin152PowerByte], kDaikinBitPowerOffset); +} + +uint8_t IRDaikin152::getMode(void) { + return GETBITS8(remote_state[kDaikin152ModeByte], kDaikinModeOffset, + kDaikinModeSize); +} + +void IRDaikin152::setMode(const uint8_t mode) { + switch (mode) { + case kDaikinFan: + setTemp(kDaikin152FanTemp); // Handle special temp for fan mode. + break; + case kDaikinDry: + setTemp(kDaikin152DryTemp); // Handle special temp for dry mode. + break; + case kDaikinAuto: + case kDaikinCool: + case kDaikinHeat: + break; + default: + this->setMode(kDaikinAuto); + return; + } + setBits(&remote_state[kDaikin152ModeByte], kDaikinModeOffset, + kDaikinModeSize, mode); +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRDaikin152::convertMode(const stdAc::opmode_t mode) { + return IRDaikinESP::convertMode(mode); +} + +// Set the temp in deg C +void IRDaikin152::setTemp(const uint8_t temp) { + uint8_t degrees = std::max( + temp, (getMode() == kDaikinHeat) ? kDaikinMinTemp : kDaikin2MinCoolTemp); + degrees = std::min(degrees, kDaikinMaxTemp); + if (temp == kDaikin152FanTemp) degrees = temp; // Handle fan only temp. + setBits(&remote_state[kDaikin152TempByte], kDaikinTempOffset, + kDaikin152TempSize, degrees); +} + +uint8_t IRDaikin152::getTemp(void) { + return GETBITS8(remote_state[kDaikin152TempByte], kDaikinTempOffset, + kDaikin152TempSize); +} + +// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet +void IRDaikin152::setFan(const uint8_t fan) { + // Set the fan speed bits, leave low 4 bits alone + uint8_t fanset; + if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto) + fanset = fan; + else if (fan < kDaikinFanMin || fan > kDaikinFanMax) + fanset = kDaikinFanAuto; + else + fanset = 2 + fan; + setBits(&remote_state[kDaikin152FanByte], kHighNibble, kNibbleSize, fanset); +} + +uint8_t IRDaikin152::getFan(void) { + const uint8_t fan = GETBITS8(remote_state[kDaikin152FanByte], kHighNibble, + kNibbleSize); + switch (fan) { + case kDaikinFanAuto: + case kDaikinFanQuiet: return fan; + default: return fan - 2; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRDaikin152::convertFan(const stdAc::fanspeed_t speed) { + return IRDaikinESP::convertFan(speed); +} + +void IRDaikin152::setSwingV(const bool on) { + setBits(&remote_state[kDaikin152SwingVByte], kDaikinSwingOffset, + kDaikinSwingSize, on ? kDaikinSwingOn : kDaikinSwingOff); +} + +bool IRDaikin152::getSwingV(void) { + return GETBITS8(remote_state[kDaikin152SwingVByte], kDaikinSwingOffset, + kDaikinSwingSize); +} + +void IRDaikin152::setQuiet(const bool on) { + setBit(&remote_state[kDaikin152QuietByte], kDaikinBitSilentOffset, on); + // Powerful & Quiet mode being on are mutually exclusive. + if (on) this->setPowerful(false); +} + +bool IRDaikin152::getQuiet(void) { + return GETBIT8(remote_state[kDaikin152QuietByte], kDaikinBitSilentOffset); +} + +void IRDaikin152::setPowerful(const bool on) { + setBit(&remote_state[kDaikin152PowerfulByte], kDaikinBitPowerfulOffset, on); + if (on) { + // Powerful, Quiet, Comfortm & Econo mode being on are mutually exclusive. + this->setQuiet(false); + this->setComfort(false); + this->setEcono(false); + } +} + +bool IRDaikin152::getPowerful(void) { + return GETBIT8(remote_state[kDaikin152PowerfulByte], + kDaikinBitPowerfulOffset); +} + +void IRDaikin152::setEcono(const bool on) { + setBit(&remote_state[kDaikin152EconoByte], kDaikinBitEconoOffset, on); + // Powerful & Econo mode being on are mutually exclusive. + if (on) this->setPowerful(false); +} + +bool IRDaikin152::getEcono(void) { + return GETBIT8(remote_state[kDaikin152EconoByte], kDaikinBitEconoOffset); +} + +void IRDaikin152::setSensor(const bool on) { + setBit(&remote_state[kDaikin152SensorByte], kDaikin152SensorOffset, on); +} + +bool IRDaikin152::getSensor(void) { + return GETBIT8(remote_state[kDaikin152SensorByte], kDaikin152SensorOffset); +} + +void IRDaikin152::setComfort(const bool on) { + setBit(&remote_state[kDaikin152ComfortByte], kDaikin152ComfortOffset, on); + if (on) { + // Comfort mode is incompatible with Powerful mode. + setPowerful(false); + // It also sets the fan to auto and turns off swingv. + setFan(kDaikinFanAuto); + setSwingV(false); + } +} + +bool IRDaikin152::getComfort(void) { + return GETBIT8(remote_state[kDaikin152ComfortByte], kDaikin152ComfortOffset); +} + +// Convert the A/C state to it's common equivalent. +stdAc::state_t IRDaikin152::toCommon(void) { + stdAc::state_t result; + result.protocol = decode_type_t::DAIKIN152; + result.model = -1; // No models used. + result.power = this->getPower(); + result.mode = IRDaikinESP::toCommonMode(this->getMode()); + result.celsius = true; + result.degrees = this->getTemp(); + result.fanspeed = IRDaikinESP::toCommonFanSpeed(this->getFan()); + result.swingv = this->getSwingV() ? stdAc::swingv_t::kAuto + : stdAc::swingv_t::kOff; + result.quiet = this->getQuiet(); + result.turbo = this->getPowerful(); + result.econo = this->getEcono(); + // Not supported. + result.swingh = stdAc::swingh_t::kOff; + result.clean = false; + result.filter = false; + result.light = false; + result.beep = false; + result.sleep = -1; + result.clock = -1; + return result; +} + +// Convert the internal state into a human readable string. +String IRDaikin152::toString(void) { + String result = ""; + result.reserve(180); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(getMode(), kDaikinAuto, kDaikinCool, kDaikinHeat, + kDaikinDry, kDaikinFan); + result += addTempToString(getTemp()); + result += addFanToString(getFan(), kDaikinFanMax, kDaikinFanMin, + kDaikinFanAuto, kDaikinFanQuiet, kDaikinFanMed); + result += addBoolToString(getSwingV(), kSwingVStr); + result += addBoolToString(getPowerful(), kPowerfulStr); + result += addBoolToString(getQuiet(), kQuietStr); + result += addBoolToString(getEcono(), kEconoStr); + result += addBoolToString(getSensor(), kSensorStr); + result += addBoolToString(getComfort(), kComfortStr); + return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Daikin.h b/lib/IRremoteESP8266-2.7.0/src/ir_Daikin.h old mode 100755 new mode 100644 similarity index 76% rename from lib/IRremoteESP8266-2.6.5/src/ir_Daikin.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Daikin.h index 98a38c640..42039b07b --- a/lib/IRremoteESP8266-2.6.5/src/ir_Daikin.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Daikin.h @@ -91,17 +91,25 @@ // Constants const uint8_t kDaikinAuto = 0b000; -const uint8_t kDaikinDry = 0b010; +const uint8_t kDaikinDry = 0b010; const uint8_t kDaikinCool = 0b011; const uint8_t kDaikinHeat = 0b100; -const uint8_t kDaikinFan = 0b110; +const uint8_t kDaikinFan = 0b110; +const uint8_t kDaikinModeOffset = 4; +const uint8_t kDaikinModeSize = 3; const uint8_t kDaikinMinTemp = 10; // Celsius const uint8_t kDaikinMaxTemp = 32; // Celsius const uint8_t kDaikinFanMin = 1; const uint8_t kDaikinFanMed = 3; const uint8_t kDaikinFanMax = 5; -const uint8_t kDaikinFanAuto = 0b1010; -const uint8_t kDaikinFanQuiet = 0b1011; +const uint8_t kDaikinFanAuto = 0b1010; // 10 / 0xA +const uint8_t kDaikinFanQuiet = 0b1011; // 11 / 0xB +const uint8_t kDaikinFanOffset = 4; +const uint8_t kDaikinFanSize = 4; +const uint8_t kDaikinSwingOffset = 0; +const uint8_t kDaikinSwingSize = 4; +const uint8_t kDaikinSwingOn = 0b1111; +const uint8_t kDaikinSwingOff = 0b0000; const uint16_t kDaikinHeaderLength = 5; const uint8_t kDaikinSections = 3; const uint8_t kDaikinSection1Length = 8; @@ -110,37 +118,55 @@ const uint8_t kDaikinSection3Length = kDaikinStateLength - kDaikinSection1Length - kDaikinSection2Length; const uint8_t kDaikinByteComfort = 6; const uint8_t kDaikinByteChecksum1 = 7; -const uint8_t kDaikinBitComfort = 0b00010000; +const uint8_t kDaikinBitComfortOffset = 4; +const uint8_t kDaikinBitComfort = 1 << kDaikinBitComfortOffset; const uint8_t kDaikinByteClockMinsLow = 13; const uint8_t kDaikinByteClockMinsHigh = 14; +const uint8_t kDaikinClockMinsHighOffset = 0; +const uint8_t kDaikinClockMinsHighSize = 3; +const uint8_t kDaikinDoWOffset = 3; +const uint8_t kDaikinDoWSize = 3; const uint8_t kDaikinByteChecksum2 = 15; const uint8_t kDaikinBytePower = 21; -const uint8_t kDaikinBitPower = 0b00000001; +const uint8_t kDaikinBitPowerOffset = 0; +const uint8_t kDaikinBitPower = 1 << kDaikinBitPowerOffset; +const uint8_t kDaikinTempOffset = 1; +const uint8_t kDaikinTempSize = 6; const uint8_t kDaikinByteTemp = 22; const uint8_t kDaikinByteFan = 24; const uint8_t kDaikinByteSwingH = 25; const uint8_t kDaikinByteOnTimerMinsLow = 26; const uint8_t kDaikinByteOnTimerMinsHigh = 27; +const uint8_t kDaikinOnTimerMinsHighOffset = 0; +const uint8_t kDaikinOnTimerMinsHighSize = 4; const uint8_t kDaikinByteOffTimerMinsLow = kDaikinByteOnTimerMinsHigh; const uint8_t kDaikinByteOffTimerMinsHigh = 28; const uint8_t kDaikinBytePowerful = 29; -const uint8_t kDaikinBitPowerful = 0b00000001; +const uint8_t kDaikinBitPowerfulOffset = 0; +const uint8_t kDaikinBitPowerful = 1 << kDaikinBitPowerfulOffset; const uint8_t kDaikinByteSilent = kDaikinBytePowerful; -const uint8_t kDaikinBitSilent = 0b00100000; +const uint8_t kDaikinBitSilentOffset = 5; +const uint8_t kDaikinBitSilent = 1 << kDaikinBitSilentOffset; const uint8_t kDaikinByteSensor = 32; -const uint8_t kDaikinBitSensor = 0b00000010; +const uint8_t kDaikinBitSensorOffset = 1; +const uint8_t kDaikinBitSensor = 1 << kDaikinBitSensorOffset; const uint8_t kDaikinByteEcono = kDaikinByteSensor; -const uint8_t kDaikinBitEcono = 0b00000100; +const uint8_t kDaikinBitEconoOffset = 2; +const uint8_t kDaikinBitEcono = 1 << kDaikinBitEconoOffset; const uint8_t kDaikinByteEye = kDaikinByteSensor; const uint8_t kDaikinBitEye = 0b10000000; const uint8_t kDaikinByteWeeklyTimer = kDaikinByteSensor; -const uint8_t kDaikinBitWeeklyTimer = 0b10000000; +const uint8_t kDaikinBitWeeklyTimerOffset = 7; +const uint8_t kDaikinBitWeeklyTimer = 1 << kDaikinBitWeeklyTimerOffset; const uint8_t kDaikinByteMold = 33; -const uint8_t kDaikinBitMold = 0b00000010; +const uint8_t kDaikinBitMoldOffset = 1; +const uint8_t kDaikinBitMold = 1 << kDaikinBitMoldOffset; const uint8_t kDaikinByteOffTimer = kDaikinBytePower; -const uint8_t kDaikinBitOffTimer = 0b00000100; +const uint8_t kDaikinBitOffTimerOffset = 2; +const uint8_t kDaikinBitOffTimer = 1 << kDaikinBitOffTimerOffset; const uint8_t kDaikinByteOnTimer = kDaikinByteOffTimer; -const uint8_t kDaikinBitOnTimer = 0b00000010; +const uint8_t kDaikinBitOnTimerOffset = 1; +const uint8_t kDaikinBitOnTimer = 1 << kDaikinBitOnTimerOffset; const uint8_t kDaikinByteChecksum3 = kDaikinStateLength - 1; const uint16_t kDaikinUnusedTime = 0x600; const uint8_t kDaikinBeepQuiet = 1; @@ -177,25 +203,49 @@ const uint16_t kDaikin2Sections = 2; const uint16_t kDaikin2Section1Length = 20; const uint16_t kDaikin2Section2Length = 19; const uint8_t kDaikin2Tolerance = 5; // Extra percentage tolerance - -const uint8_t kDaikin2BitSleepTimer = 0b00100000; -const uint8_t kDaikin2BitPurify = 0b00010000; -const uint8_t kDaikin2BitEye = 0b00000010; -const uint8_t kDaikin2BitEyeAuto = 0b10000000; -const uint8_t kDaikin2BitMold = 0b00001000; -const uint8_t kDaikin2BitClean = 0b00100000; -const uint8_t kDaikin2BitFreshAir = 0b00000001; -const uint8_t kDaikin2BitFreshAirHigh = 0b10000000; -const uint8_t kDaikin2BitPower = 0b10000000; -const uint8_t kDaikin2LightMask = 0b00110000; -const uint8_t kDaikin2BeepMask = 0b11000000; +const uint8_t kDaikin2BitSleepTimerOffset = 5; +const uint8_t kDaikin2BitSleepTimer = 1 << kDaikin2BitSleepTimerOffset; +const uint8_t kDaikin2BitPurifyOffset = 4; +const uint8_t kDaikin2BitPurify = 1 << kDaikin2BitPurifyOffset; // 0b00010000 +const uint8_t kDaikin2BitEyeOffset = 1; +const uint8_t kDaikin2BitEye = 1 << kDaikin2BitEyeOffset; // 0b00000010 +const uint8_t kDaikin2BitEyeAutoOffset = 7; +const uint8_t kDaikin2BitEyeAuto = 1 << kDaikin2BitEyeAutoOffset; // 0b10000000 +const uint8_t kDaikin2BitMoldOffset = 3; +const uint8_t kDaikin2BitMold = 1 << kDaikin2BitMoldOffset; // 0b00001000 +const uint8_t kDaikin2BitCleanOffset = 5; // Byte[8] +const uint8_t kDaikin2BitClean = 1 << kDaikin2BitCleanOffset; // 0b00100000 +const uint8_t kDaikin2BitFreshAirOffset = 0; +const uint8_t kDaikin2BitFreshAir = 1 << kDaikin2BitFreshAirOffset; +const uint8_t kDaikin2BitFreshAirHighOffset = 7; +const uint8_t kDaikin2BitFreshAirHigh = 1 << kDaikin2BitFreshAirHighOffset; +const uint8_t kDaikin2BitPowerOffset = 7; +const uint8_t kDaikin2BitPower = 1 << kDaikin2BitPowerOffset; // 0b10000000 +// const uint8_t kDaikin2LightMask = 0b00110000; // Byte[7] +const uint8_t kDaikin2LightOffset = 4; // Byte[7] +const uint8_t kDaikin2LightSize = 2; +// const uint8_t kDaikin2BeepMask = 0b11000000; // Byte[7] +const uint8_t kDaikin2BeepOffset = 6; // Byte[7] +const uint8_t kDaikin2BeepSize = 2; const uint8_t kDaikin2SwingVHigh = 0x1; const uint8_t kDaikin2SwingVLow = 0x6; +const uint8_t kDaikin2SwingVSwing = 0xF; +const uint8_t kDaikin2SwingVAuto = 0xE; const uint8_t kDaikin2SwingVBreeze = 0xC; const uint8_t kDaikin2SwingVCirculate = 0xD; -const uint8_t kDaikin2SwingVAuto = 0xE; -const uint8_t kDaikin2SwingHAuto = 0xBE; -const uint8_t kDaikin2SwingHSwing = 0xBF; +const uint8_t kDaikin2FanByte = 28; + +// Ref: +// https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit#gid=236366525&range=B25:D32 +const uint8_t kDaikin2SwingHWide = 0xA3; +const uint8_t kDaikin2SwingHLeftMax = 0xA8; +const uint8_t kDaikin2SwingHLeft = 0xA9; +const uint8_t kDaikin2SwingHMiddle = 0xAA; +const uint8_t kDaikin2SwingHRight = 0xAB; +const uint8_t kDaikin2SwingHRightMax = 0xAC; +const uint8_t kDaikin2SwingHAuto = 0xBE; +const uint8_t kDaikin2SwingHSwing = 0xBF; + const uint8_t kDaikin2MinCoolTemp = 18; // Min temp (in C) when in Cool mode. // Another variant of the protocol for the Daikin ARC433B69 remote. @@ -212,15 +262,20 @@ const uint16_t kDaikin216Section2Length = kDaikin216StateLength - kDaikin216Section1Length; const uint8_t kDaikin216BytePower = 13; const uint8_t kDaikin216ByteMode = kDaikin216BytePower; -const uint8_t kDaikin216MaskMode = 0b01110000; +// const uint8_t kDaikin216MaskMode = 0b01110000; const uint8_t kDaikin216ByteTemp = 14; -const uint8_t kDaikin216MaskTemp = 0b01111110; +// const uint8_t kDaikin216MaskTemp = 0b01111110; +const uint8_t kDaikin216TempOffset = 1; +const uint8_t kDaikin216TempSize = 6; + const uint8_t kDaikin216ByteFan = 16; const uint8_t kDaikin216MaskFan = 0b11110000; const uint8_t kDaikin216ByteSwingV = 16; -const uint8_t kDaikin216MaskSwingV = 0b00001111; +// const uint8_t kDaikin216MaskSwingV = 0b00001111; +const uint8_t kDaikin216SwingSize = 4; +const uint8_t kDaikin216SwingOn = 0b1111; +const uint8_t kDaikin216SwingOff = 0b0000; const uint8_t kDaikin216ByteSwingH = 17; -const uint8_t kDaikin216MaskSwingH = kDaikin216MaskSwingV; const uint8_t kDaikin216BytePowerful = 21; // Another variant of the protocol for the Daikin ARC423A5 remote. @@ -237,9 +292,11 @@ const uint16_t kDaikin160Section2Length = kDaikin160StateLength - kDaikin160Section1Length; const uint8_t kDaikin160BytePower = 12; const uint8_t kDaikin160ByteMode = kDaikin160BytePower; -const uint8_t kDaikin160MaskMode = 0b01110000; +// const uint8_t kDaikin160MaskMode = 0b01110000; const uint8_t kDaikin160ByteTemp = 16; -const uint8_t kDaikin160MaskTemp = 0b01111110; +// const uint8_t kDaikin160MaskTemp = 0b01111110; +const uint8_t kDaikin160TempOffset = 1; +const uint8_t kDaikin160TempSize = 6; const uint8_t kDaikin160ByteFan = 17; const uint8_t kDaikin160MaskFan = 0b00001111; const uint8_t kDaikin160ByteSwingV = 13; @@ -270,13 +327,15 @@ const uint8_t kDaikin176MaskMode = 0b01110000; const uint8_t kDaikin176ByteModeButton = 13; const uint8_t kDaikin176ModeButton = 0b00000100; const uint8_t kDaikin176ByteTemp = 17; -const uint8_t kDaikin176MaskTemp = 0b01111110; +// const uint8_t kDaikin176MaskTemp = 0b01111110; +const uint8_t kDaikin176TempOffset = 1; +const uint8_t kDaikin176TempSize = 6; const uint8_t kDaikin176DryFanTemp = 17; // Dry/Fan mode is always 17 Celsius. const uint8_t kDaikin176ByteFan = 18; const uint8_t kDaikin176MaskFan = 0b11110000; const uint8_t kDaikin176FanMax = 3; const uint8_t kDaikin176ByteSwingH = 18; -const uint8_t kDaikin176MaskSwingH = 0b00001111; +// const uint8_t kDaikin176MaskSwingH = 0b00001111; const uint8_t kDaikin176SwingHAuto = 0x5; const uint8_t kDaikin176SwingHOff = 0x6; @@ -295,7 +354,8 @@ const uint16_t kDaikin128FooterMark = kDaikin128HdrMark; const uint16_t kDaikin128Sections = 2; const uint16_t kDaikin128SectionLength = 8; const uint8_t kDaikin128ByteModeFan = 1; -const uint8_t kDaikin128MaskMode = 0b00001111; +// const uint8_t kDaikin128MaskMode = 0b00001111; +const uint8_t kDaikin128ModeSize = 4; const uint8_t kDaikin128Dry = 0b00000001; const uint8_t kDaikin128Cool = 0b00000010; const uint8_t kDaikin128Fan = 0b00000100; @@ -312,18 +372,28 @@ const uint8_t kDaikin128ByteClockMins = 2; const uint8_t kDaikin128ByteClockHours = 3; const uint8_t kDaikin128ByteOnTimer = 4; const uint8_t kDaikin128ByteOffTimer = 5; -const uint8_t kDaikin128BitTimerEnabled = 0b10000000; -const uint8_t kDaikin128BitHalfHour = 0b01000000; -const uint8_t kDaikin128MaskHours = 0b00111111; +const uint8_t kDaikin128BitTimerEnabledOffset = 7; +const uint8_t kDaikin128BitTimerEnabled = 1 << kDaikin128BitTimerEnabledOffset; +const uint8_t kDaikin128TimerOffset = 0; +const uint8_t kDaikin128TimerSize = 7; +const uint8_t kDaikin128HalfHourOffset = 6; +const uint8_t kDaikin128BitHalfHour = 1 << kDaikin128HalfHourOffset; +// const uint8_t kDaikin128MaskHours = 0b00111111; +const uint8_t kDaikin128HoursOffset = 0; +const uint8_t kDaikin128HoursSize = 6; const uint8_t kDaikin128ByteTemp = 6; const uint8_t kDaikin128MinTemp = 16; // C const uint8_t kDaikin128MaxTemp = 30; // C const uint8_t kDaikin128BytePowerSwingSleep = 7; -const uint8_t kDaikin128BitSwing = 0b00000001; -const uint8_t kDaikin128BitSleep = 0b00000010; -const uint8_t kDaikin128BitPowerToggle = 0b00001000; +const uint8_t kDaikin128BitSwingOffset = 0; +const uint8_t kDaikin128BitSwing = 1 << kDaikin128BitSwingOffset; // 0b00000001 +const uint8_t kDaikin128BitSleepOffset = 1; +const uint8_t kDaikin128BitSleep = 1 << kDaikin128BitSleepOffset; // 0b00000010 +const uint8_t kDaikin128BitPowerToggleOffset = 3; +const uint8_t kDaikin128BitPowerToggle = 1 << kDaikin128BitPowerToggleOffset; const uint8_t kDaikin128ByteEconoLight = 9; -const uint8_t kDaikin128BitEcono = 0b00000100; +const uint8_t kDaikin128BitEconoOffset = 2; +const uint8_t kDaikin128BitEcono = 1 << kDaikin128BitEconoOffset; // 0b00000100 const uint8_t kDaikin128BitWall = 0b00001000; const uint8_t kDaikin128BitCeiling = 0b00000001; const uint8_t kDaikin128MaskLight = kDaikin128BitWall | kDaikin128BitCeiling; @@ -339,6 +409,28 @@ const uint16_t kDaikin152OneSpace = 1529; const uint16_t kDaikin152ZeroSpace = kDaikin152BitMark; const uint16_t kDaikin152Gap = 25182; +// Byte[5] +const uint8_t kDaikin152ModeByte = 5; // Mask 0b01110000 +const uint8_t kDaikin152PowerByte = kDaikin152ModeByte; // Mask 0b00000001 +// Byte[6] +const uint8_t kDaikin152TempByte = 6; // Mask 0b11111110 +const uint8_t kDaikin152TempSize = 7; +const uint8_t kDaikin152DryTemp = kDaikin2MinCoolTemp; // Celsius +const uint8_t kDaikin152FanTemp = 0x60; // 96 Celsius +// Byte[8] +const uint8_t kDaikin152FanByte = 8; +const uint8_t kDaikin152SwingVByte = kDaikin152FanByte; +// Byte[13] +const uint8_t kDaikin152QuietByte = 13; // Mask 0b00100000 +const uint8_t kDaikin152PowerfulByte = kDaikin152QuietByte; // Mask 0b00000001 +// Byte[16] +const uint8_t kDaikin152EconoByte = 16; // Mask 0b00000100 +const uint8_t kDaikin152ComfortByte = kDaikin152EconoByte; // Mask 0b00000010 +const uint8_t kDaikin152ComfortOffset = 1; // Mask 0b00000010 +const uint8_t kDaikin152SensorByte = kDaikin152EconoByte; // Mask 0b00001000 +const uint8_t kDaikin152SensorOffset = 3; // Mask 0b00001000 + + // Legacy defines. #define DAIKIN_COOL kDaikinCool #define DAIKIN_HEAT kDaikinHeat @@ -499,7 +591,8 @@ class IRDaikin2 { const uint16_t length = kDaikin2StateLength); static uint8_t convertMode(const stdAc::opmode_t mode); static uint8_t convertFan(const stdAc::fanspeed_t speed); - uint8_t convertSwingV(const stdAc::swingv_t position); + static uint8_t convertSwingV(const stdAc::swingv_t position); + static uint8_t convertSwingH(const stdAc::swingh_t position); static stdAc::swingv_t toCommonSwingV(const uint8_t setting); static stdAc::swingh_t toCommonSwingH(const uint8_t setting); stdAc::state_t toCommon(void); @@ -748,6 +841,34 @@ class IRDaikin152 { void setRaw(const uint8_t new_code[]); static bool validChecksum(uint8_t state[], const uint16_t length = kDaikin152StateLength); + void on(void); + void off(void); + void setPower(const bool on); + bool getPower(void); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setFan(const uint8_t fan); + uint8_t getFan(void); + void setMode(const uint8_t mode); + uint8_t getMode(void); + void setSwingV(const bool on); + bool getSwingV(void); + bool getQuiet(void); + void setQuiet(const bool on); + bool getPowerful(void); + void setPowerful(const bool on); + void setSensor(const bool on); + bool getSensor(void); + void setEcono(const bool on); + bool getEcono(void); + void setComfort(const bool on); + bool getComfort(void); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); + stdAc::state_t toCommon(void); + String toString(void); #ifndef UNIT_TEST private: diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Denon.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Denon.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Denon.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Denon.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Dish.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Dish.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Dish.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Dish.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Electra.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Electra.cpp old mode 100755 new mode 100644 similarity index 79% rename from lib/IRremoteESP8266-2.6.5/src/ir_Electra.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Electra.cpp index 6b945aa3f..e423bfa0a --- a/lib/IRremoteESP8266-2.6.5/src/ir_Electra.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Electra.cpp @@ -2,8 +2,10 @@ #include "ir_Electra.h" #include +#include #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Electra A/C added by crankyoldgit @@ -29,6 +31,8 @@ using irutils::addLabeledString; using irutils::addModeToString; using irutils::addFanToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_ELECTRA_AC // Send a Electra message @@ -60,8 +64,7 @@ IRElectraAc::IRElectraAc(const uint16_t pin, const bool inverted, } void IRElectraAc::stateReset(void) { - for (uint8_t i = 1; i < kElectraAcStateLength - 2; i++) - remote_state[i] = 0; + for (uint8_t i = 1; i < kElectraAcStateLength - 2; i++) remote_state[i] = 0; remote_state[0] = 0xC3; remote_state[11] = 0x08; // [12] is the checksum. @@ -100,8 +103,7 @@ uint8_t *IRElectraAc::getRaw(void) { } void IRElectraAc::setRaw(const uint8_t new_code[], const uint16_t length) { - for (uint8_t i = 0; i < length && i < kElectraAcStateLength; i++) - remote_state[i] = new_code[i]; + memcpy(remote_state, new_code, std::min(length, kElectraAcStateLength)); } void IRElectraAc::on(void) { this->setPower(true); } @@ -109,14 +111,11 @@ void IRElectraAc::on(void) { this->setPower(true); } void IRElectraAc::off(void) { this->setPower(false); } void IRElectraAc::setPower(const bool on) { - if (on) - remote_state[9] |= kElectraAcPowerMask; - else - remote_state[9] &= ~kElectraAcPowerMask; + setBit(&remote_state[9], kElectraAcPowerOffset, on); } bool IRElectraAc::getPower(void) { - return remote_state[9] & kElectraAcPowerMask; + return GETBIT8(remote_state[9], kElectraAcPowerOffset); } void IRElectraAc::setMode(const uint8_t mode) { @@ -126,8 +125,7 @@ void IRElectraAc::setMode(const uint8_t mode) { case kElectraAcCool: case kElectraAcHeat: case kElectraAcFan: - remote_state[6] &= ~kElectraAcModeMask; - remote_state[6] |= (mode << 5); + setBits(&remote_state[6], kElectraAcModeOffset, kModeBitsSize, mode); break; default: // If we get an unexpected mode, default to AUTO. @@ -136,22 +134,17 @@ void IRElectraAc::setMode(const uint8_t mode) { } uint8_t IRElectraAc::getMode(void) { - return (remote_state[6] & kElectraAcModeMask) >> 5; + return GETBITS8(remote_state[6], kElectraAcModeOffset, kModeBitsSize); } // Convert a standard A/C mode into its native mode. uint8_t IRElectraAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kElectraAcCool; - case stdAc::opmode_t::kHeat: - return kElectraAcHeat; - case stdAc::opmode_t::kDry: - return kElectraAcDry; - case stdAc::opmode_t::kFan: - return kElectraAcFan; - default: - return kElectraAcAuto; + case stdAc::opmode_t::kCool: return kElectraAcCool; + case stdAc::opmode_t::kHeat: return kElectraAcHeat; + case stdAc::opmode_t::kDry: return kElectraAcDry; + case stdAc::opmode_t::kFan: return kElectraAcFan; + default: return kElectraAcAuto; } } @@ -160,23 +153,23 @@ stdAc::opmode_t IRElectraAc::toCommonMode(const uint8_t mode) { switch (mode) { case kElectraAcCool: return stdAc::opmode_t::kCool; case kElectraAcHeat: return stdAc::opmode_t::kHeat; - case kElectraAcDry: return stdAc::opmode_t::kDry; - case kElectraAcFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kElectraAcDry: return stdAc::opmode_t::kDry; + case kElectraAcFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } // Set the temp. in deg C void IRElectraAc::setTemp(const uint8_t temp) { uint8_t newtemp = std::max(kElectraAcMinTemp, temp); - newtemp = std::min(kElectraAcMaxTemp, newtemp); - remote_state[1] = (remote_state[1] & ~kElectraAcTempMask) | - ((newtemp - kElectraAcOffsetTemp) << 3); + newtemp = std::min(kElectraAcMaxTemp, newtemp) - kElectraAcTempDelta; + setBits(&remote_state[1], kElectraAcTempOffset, kElectraAcTempSize, newtemp); } // Return the set temp. in deg C uint8_t IRElectraAc::getTemp(void) { - return ((remote_state[1] & kElectraAcTempMask) >> 3) + kElectraAcOffsetTemp; + return GETBITS8(remote_state[1], kElectraAcTempOffset, kElectraAcTempSize) + + kElectraAcTempDelta; } // Set the speed of the fan, 0-3, 0 is auto, 1-3 is the speed @@ -186,8 +179,7 @@ void IRElectraAc::setFan(const uint8_t speed) { case kElectraAcFanHigh: case kElectraAcFanMed: case kElectraAcFanLow: - remote_state[4] &= ~kElectraAcFanMask; - remote_state[4] |= (speed << 5); + setBits(&remote_state[4], kElectraAcFanOffset, kElectraAcFanSize, speed); break; default: // If we get an unexpected speed, default to Auto. @@ -196,22 +188,18 @@ void IRElectraAc::setFan(const uint8_t speed) { } uint8_t IRElectraAc::getFan(void) { - return (remote_state[4] & kElectraAcFanMask) >> 5; + return GETBITS8(remote_state[4], kElectraAcFanOffset, kElectraAcFanSize); } // Convert a standard A/C Fan speed into its native fan speed. uint8_t IRElectraAc::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kElectraAcFanLow; - case stdAc::fanspeed_t::kMedium: - return kElectraAcFanMed; + case stdAc::fanspeed_t::kLow: return kElectraAcFanLow; + case stdAc::fanspeed_t::kMedium: return kElectraAcFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kElectraAcFanHigh; - default: - return kElectraAcFanAuto; + case stdAc::fanspeed_t::kMax: return kElectraAcFanHigh; + default: return kElectraAcFanAuto; } } @@ -226,25 +214,23 @@ stdAc::fanspeed_t IRElectraAc::toCommonFanSpeed(const uint8_t speed) { } void IRElectraAc::setSwingV(const bool on) { - if (on) - remote_state[1] &= ~kElectraAcSwingVMask; - else - remote_state[1] |= kElectraAcSwingVMask; + setBits(&remote_state[1], kElectraAcSwingVOffset, kElectraAcSwingSize, + on ? kElectraAcSwingOn : kElectraAcSwingOff); } bool IRElectraAc::getSwingV(void) { - return !(remote_state[1] & kElectraAcSwingVMask); + return !GETBITS8(remote_state[1], kElectraAcSwingVOffset, + kElectraAcSwingSize); } void IRElectraAc::setSwingH(const bool on) { - if (on) - remote_state[2] &= ~kElectraAcSwingHMask; - else - remote_state[2] |= kElectraAcSwingHMask; + setBits(&remote_state[2], kElectraAcSwingHOffset, kElectraAcSwingSize, + on ? kElectraAcSwingOn : kElectraAcSwingOff); } bool IRElectraAc::getSwingH(void) { - return !(remote_state[2] & kElectraAcSwingHMask); + return !GETBITS8(remote_state[2], kElectraAcSwingHOffset, + kElectraAcSwingSize); } // Convert the A/C state to it's common equivalent. @@ -278,15 +264,15 @@ stdAc::state_t IRElectraAc::toCommon(void) { String IRElectraAc::toString(void) { String result = ""; result.reserve(80); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kElectraAcAuto, kElectraAcCool, kElectraAcHeat, kElectraAcDry, kElectraAcFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kElectraAcFanHigh, kElectraAcFanLow, kElectraAcFanAuto, kElectraAcFanAuto, kElectraAcFanMed); - result += addBoolToString(getSwingV(), F("Swing(V)")); - result += addBoolToString(getSwingH(), F("Swing(H)")); + result += addBoolToString(getSwingV(), kSwingVStr); + result += addBoolToString(getSwingH(), kSwingHStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Electra.h b/lib/IRremoteESP8266-2.7.0/src/ir_Electra.h old mode 100755 new mode 100644 similarity index 78% rename from lib/IRremoteESP8266-2.6.5/src/ir_Electra.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Electra.h index c9c6f018e..ef28b44cf --- a/lib/IRremoteESP8266-2.6.5/src/ir_Electra.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Electra.h @@ -25,28 +25,39 @@ // Constants // state[1] -const uint8_t kElectraAcTempMask = 0b11111000; +// Temp 0b11111000 +const uint8_t kElectraAcTempOffset = 3; +const uint8_t kElectraAcTempSize = 5; // Bits const uint8_t kElectraAcMinTemp = 16; // 16C const uint8_t kElectraAcMaxTemp = 32; // 32C -const uint8_t kElectraAcOffsetTemp = 8; -const uint8_t kElectraAcSwingVMask = 0b00000111; +const uint8_t kElectraAcTempDelta = 8; +const uint8_t kElectraAcSwingSize = 3; // Bits +const uint8_t kElectraAcSwingOn = 0b000; +const uint8_t kElectraAcSwingOff = 0b111; +// SwingVMask = 0b00000111; +const uint8_t kElectraAcSwingVOffset = 0; // state[2] -const uint8_t kElectraAcSwingHMask = 0b11100000; +// SwingHMask = 0b11100000; +const uint8_t kElectraAcSwingHOffset = 5; // state[4] -const uint8_t kElectraAcFanMask = 0b11100000; +// FanMask = 0b11100000; +const uint8_t kElectraAcFanOffset = 5; +const uint8_t kElectraAcFanSize = 3; // Bits + const uint8_t kElectraAcFanAuto = 0b101; const uint8_t kElectraAcFanLow = 0b011; const uint8_t kElectraAcFanMed = 0b010; const uint8_t kElectraAcFanHigh = 0b001; // state[6] -const uint8_t kElectraAcModeMask = 0b11100000; +// Mode 0b11100000 +const uint8_t kElectraAcModeOffset = 5; const uint8_t kElectraAcAuto = 0b000; const uint8_t kElectraAcCool = 0b001; const uint8_t kElectraAcDry = 0b010; const uint8_t kElectraAcHeat = 0b100; const uint8_t kElectraAcFan = 0b110; // state[9] -const uint8_t kElectraAcPowerMask = 0b00100000; +const uint8_t kElectraAcPowerOffset = 5; // Classes diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Fujitsu.cpp old mode 100755 new mode 100644 similarity index 76% rename from lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Fujitsu.cpp index fa6a0ce8c..fe8c2bfed --- a/lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Fujitsu.cpp @@ -6,6 +6,7 @@ #include #endif #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Fujitsu A/C support added by Jonny Graham & David Conran @@ -31,8 +32,11 @@ using irutils::addBoolToString; using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; +using irutils::addModelToString; using irutils::addFanToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_FUJITSU_AC // Send a Fujitsu A/C message. @@ -72,13 +76,14 @@ IRFujitsuAC::IRFujitsuAC(const uint16_t pin, void IRFujitsuAC::setModel(const fujitsu_ac_remote_model_t model) { _model = model; switch (model) { - case ARDB1: - case ARJW2: + case fujitsu_ac_remote_model_t::ARDB1: + case fujitsu_ac_remote_model_t::ARJW2: _state_length = kFujitsuAcStateLength - 1; _state_length_short = kFujitsuAcStateLengthShort - 1; break; - case ARRAH2E: - case ARREB1E: + case fujitsu_ac_remote_model_t::ARRY4: + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARREB1E: default: _state_length = kFujitsuAcStateLength; _state_length_short = kFujitsuAcStateLengthShort; @@ -94,6 +99,8 @@ void IRFujitsuAC::stateReset(void) { _mode = kFujitsuAcModeCool; _swingMode = kFujitsuAcSwingBoth; _cmd = kFujitsuAcCmdTurnOn; + _filter = false; + _clean = false; this->buildState(); } @@ -127,12 +134,13 @@ void IRFujitsuAC::buildState(void) { break; default: switch (_model) { - case ARRAH2E: - case ARREB1E: + case fujitsu_ac_remote_model_t::ARRY4: + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARREB1E: remote_state[5] = 0xFE; break; - case ARDB1: - case ARJW2: + case fujitsu_ac_remote_model_t::ARDB1: + case fujitsu_ac_remote_model_t::ARJW2: remote_state[5] = 0xFC; break; } @@ -151,21 +159,30 @@ void IRFujitsuAC::buildState(void) { remote_state[11] = 0; // timerOff values remote_state[12] = 0; // timerOff/On values remote_state[13] = 0; // timerOn values - remote_state[14] = 0; + switch (_model) { + case fujitsu_ac_remote_model_t::ARRY4: + remote_state[14] = _filter << 3; + remote_state[9] |= (_clean << 3); + break; + default: + remote_state[14] = 0; + } uint8_t checksum = 0; uint8_t checksum_complement = 0; switch (_model) { - case ARDB1: - case ARJW2: + case fujitsu_ac_remote_model_t::ARDB1: + case fujitsu_ac_remote_model_t::ARJW2: checksum = sumBytes(remote_state, _state_length - 1); checksum_complement = 0x9B; break; - case ARREB1E: - remote_state[14] |= (_outsideQuiet << 7); + case fujitsu_ac_remote_model_t::ARREB1E: + setBit(&remote_state[14], kFujitsuAcOutsideQuietOffset, _outsideQuiet); // FALL THRU - case ARRAH2E: - remote_state[14] |= 0x20; - remote_state[10] |= _swingMode << 4; + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARRY4: + setBit(&remote_state[14], 5); // |= 0b00100000 + setBits(&remote_state[10], kHighNibble, kFujitsuAcSwingSize, + _swingMode); // FALL THRU default: checksum = sumBytes(remote_state + _state_length_short, @@ -175,8 +192,9 @@ void IRFujitsuAC::buildState(void) { remote_state[_state_length - 1] = checksum_complement - checksum; } else { // short codes switch (_model) { - case ARRAH2E: - case ARREB1E: + case fujitsu_ac_remote_model_t::ARRY4: + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARREB1E: // The last byte is the inverse of penultimate byte remote_state[_state_length_short - 1] = ~remote_state[_state_length_short - 2]; @@ -192,8 +210,12 @@ void IRFujitsuAC::buildState(void) { uint8_t IRFujitsuAC::getStateLength(void) { this->buildState(); // Force an update of the internal state. - if (((_model == ARRAH2E || _model == ARREB1E) && remote_state[5] != 0xFE) || - ((_model == ARDB1 || _model == ARJW2) && remote_state[5] != 0xFC)) + if (((_model == fujitsu_ac_remote_model_t::ARRAH2E || + _model == fujitsu_ac_remote_model_t::ARREB1E || + _model == fujitsu_ac_remote_model_t::ARRY4) && + remote_state[5] != 0xFE) || + ((_model == fujitsu_ac_remote_model_t::ARDB1 || + _model == fujitsu_ac_remote_model_t::ARJW2) && remote_state[5] != 0xFC)) return _state_length_short; else return _state_length; @@ -209,9 +231,10 @@ void IRFujitsuAC::buildFromState(const uint16_t length) { switch (length) { case kFujitsuAcStateLength - 1: case kFujitsuAcStateLengthShort - 1: - this->setModel(ARDB1); + this->setModel(fujitsu_ac_remote_model_t::ARDB1); // ARJW2 has horizontal swing. - if (this->getSwing(true) > kFujitsuAcSwingVert) this->setModel(ARJW2); + if (this->getSwing(true) > kFujitsuAcSwingVert) + this->setModel(fujitsu_ac_remote_model_t::ARJW2); break; default: switch (this->getCmd(true)) { @@ -226,21 +249,28 @@ void IRFujitsuAC::buildFromState(const uint16_t length) { switch (remote_state[6]) { case 8: if (this->getModel() != fujitsu_ac_remote_model_t::ARJW2) - this->setModel(ARDB1); + this->setModel(fujitsu_ac_remote_model_t::ARDB1); break; case 9: if (this->getModel() != fujitsu_ac_remote_model_t::ARREB1E) - this->setModel(ARRAH2E); + this->setModel(fujitsu_ac_remote_model_t::ARRAH2E); break; } setTemp((remote_state[8] >> 4) + kFujitsuAcMinTemp); - if (remote_state[8] & 0x1) + if (GETBIT8(remote_state[8], 0)) setCmd(kFujitsuAcCmdTurnOn); else setCmd(kFujitsuAcCmdStayOn); - setMode(remote_state[9] & 0b111); - setFanSpeed(remote_state[10] & 0b111); - setSwing(remote_state[10] >> 4); + setMode(GETBITS8(remote_state[9], kLowNibble, kModeBitsSize)); + setFanSpeed(GETBITS8(remote_state[10], kLowNibble, kFujitsuAcFanSize)); + setSwing(GETBITS8(remote_state[10], kHighNibble, kFujitsuAcSwingSize)); + setClean(getClean(true)); + setFilter(getFilter(true)); + // Currently the only way we know how to tell ARRAH2E & ARRY4 apart is if + // either the raw Filter or Clean setting is on. + if (getModel() == fujitsu_ac_remote_model_t::ARRAH2E && (getFilter(true) || + getClean(true))) + setModel(fujitsu_ac_remote_model_t::ARRY4); switch (remote_state[5]) { case kFujitsuAcCmdTurnOff: case kFujitsuAcCmdStepHoriz: @@ -298,9 +328,9 @@ void IRFujitsuAC::setCmd(const uint8_t cmd) { case kFujitsuAcCmdStepHoriz: case kFujitsuAcCmdToggleSwingHoriz: switch (_model) { - // Only these remotes have step horizontal. - case ARRAH2E: - case ARJW2: + // Only these remotes have horizontal. + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARJW2: _cmd = cmd; break; default: @@ -358,7 +388,7 @@ void IRFujitsuAC::setOutsideQuiet(const bool on) { // A boolean for if it is set or not. bool IRFujitsuAC::getOutsideQuiet(const bool raw) { if (_state_length == kFujitsuAcStateLength && raw) { - _outsideQuiet = remote_state[14] & 0b10000000; + _outsideQuiet = GETBIT8(remote_state[14], kFujitsuAcOutsideQuietOffset); // Only ARREB1E seems to have this mode. if (_outsideQuiet) this->setModel(fujitsu_ac_remote_model_t::ARREB1E); } @@ -400,14 +430,15 @@ void IRFujitsuAC::setSwing(const uint8_t swingMode) { _swingMode = swingMode; switch (_model) { // No Horizontal support. - case ARDB1: - case ARREB1E: + case fujitsu_ac_remote_model_t::ARDB1: + case fujitsu_ac_remote_model_t::ARREB1E: + case fujitsu_ac_remote_model_t::ARRY4: // Set the mode to max if out of range if (swingMode > kFujitsuAcSwingVert) _swingMode = kFujitsuAcSwingVert; break; // Has Horizontal support. - case ARRAH2E: - case ARJW2: + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARJW2: default: // Set the mode to max if out of range if (swingMode > kFujitsuAcSwingBoth) _swingMode = kFujitsuAcSwingBoth; @@ -421,22 +452,55 @@ void IRFujitsuAC::setSwing(const uint8_t swingMode) { // Returns: // A uint8_t containing the contents of the swing state. uint8_t IRFujitsuAC::getSwing(const bool raw) { - if (raw) _swingMode = remote_state[10] >> 4; + if (raw) _swingMode = GETBITS8(remote_state[10], kHighNibble, + kFujitsuAcSwingSize); return _swingMode; } +void IRFujitsuAC::setClean(const bool on) { + _clean = on; + this->setCmd(kFujitsuAcCmdStayOn); // No special command involved. +} + +bool IRFujitsuAC::getClean(const bool raw) { + if (raw) { + return GETBIT8(remote_state[9], kFujitsuAcCleanOffset); + } else { + switch (getModel()) { + case fujitsu_ac_remote_model_t::ARRY4: return _clean; + default: return false; + } + } +} + +void IRFujitsuAC::setFilter(const bool on) { + _filter = on; + this->setCmd(kFujitsuAcCmdStayOn); // No special command involved. +} + +bool IRFujitsuAC::getFilter(const bool raw) { + if (raw) { + return GETBIT8(remote_state[14], kFujitsuAcFilterOffset); + } else { + switch (getModel()) { + case fujitsu_ac_remote_model_t::ARRY4: return _filter; + default: return false; + } + } +} + bool IRFujitsuAC::validChecksum(uint8_t state[], const uint16_t length) { uint8_t sum = 0; uint8_t sum_complement = 0; uint8_t checksum = state[length - 1]; switch (length) { - case kFujitsuAcStateLengthShort: // ARRAH2E & ARREB1E + case kFujitsuAcStateLengthShort: // ARRAH2E, ARREB1E, & ARRY4 return state[length - 1] == (uint8_t)~state[length - 2]; case kFujitsuAcStateLength - 1: // ARDB1 & ARJW2 sum = sumBytes(state, length - 1); sum_complement = 0x9B; break; - case kFujitsuAcStateLength: // ARRAH2E & ARREB1E + case kFujitsuAcStateLength: // ARRAH2E, ARRY4, & ARREB1E sum = sumBytes(state + kFujitsuAcStateLengthShort, length - 1 - kFujitsuAcStateLengthShort); break; @@ -449,33 +513,23 @@ bool IRFujitsuAC::validChecksum(uint8_t state[], const uint16_t length) { // Convert a standard A/C mode into its native mode. uint8_t IRFujitsuAC::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kFujitsuAcModeCool; - case stdAc::opmode_t::kHeat: - return kFujitsuAcModeHeat; - case stdAc::opmode_t::kDry: - return kFujitsuAcModeDry; - case stdAc::opmode_t::kFan: - return kFujitsuAcModeFan; - default: - return kFujitsuAcModeAuto; + case stdAc::opmode_t::kCool: return kFujitsuAcModeCool; + case stdAc::opmode_t::kHeat: return kFujitsuAcModeHeat; + case stdAc::opmode_t::kDry: return kFujitsuAcModeDry; + case stdAc::opmode_t::kFan: return kFujitsuAcModeFan; + default: return kFujitsuAcModeAuto; } } // Convert a standard A/C Fan speed into its native fan speed. uint8_t IRFujitsuAC::convertFan(stdAc::fanspeed_t speed) { switch (speed) { - case stdAc::fanspeed_t::kMin: - return kFujitsuAcFanQuiet; - case stdAc::fanspeed_t::kLow: - return kFujitsuAcFanLow; - case stdAc::fanspeed_t::kMedium: - return kFujitsuAcFanMed; + case stdAc::fanspeed_t::kMin: return kFujitsuAcFanQuiet; + case stdAc::fanspeed_t::kLow: return kFujitsuAcFanLow; + case stdAc::fanspeed_t::kMedium: return kFujitsuAcFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kFujitsuAcFanHigh; - default: - return kFujitsuAcFanAuto; + case stdAc::fanspeed_t::kMax: return kFujitsuAcFanHigh; + default: return kFujitsuAcFanAuto; } } @@ -484,20 +538,20 @@ stdAc::opmode_t IRFujitsuAC::toCommonMode(const uint8_t mode) { switch (mode) { case kFujitsuAcModeCool: return stdAc::opmode_t::kCool; case kFujitsuAcModeHeat: return stdAc::opmode_t::kHeat; - case kFujitsuAcModeDry: return stdAc::opmode_t::kDry; - case kFujitsuAcModeFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kFujitsuAcModeDry: return stdAc::opmode_t::kDry; + case kFujitsuAcModeFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } // Convert a native fan speed to it's common equivalent. stdAc::fanspeed_t IRFujitsuAC::toCommonFanSpeed(const uint8_t speed) { switch (speed) { - case kFujitsuAcFanHigh: return stdAc::fanspeed_t::kMax; - case kFujitsuAcFanMed: return stdAc::fanspeed_t::kMedium; - case kFujitsuAcFanLow: return stdAc::fanspeed_t::kLow; + case kFujitsuAcFanHigh: return stdAc::fanspeed_t::kMax; + case kFujitsuAcFanMed: return stdAc::fanspeed_t::kMedium; + case kFujitsuAcFanLow: return stdAc::fanspeed_t::kLow; case kFujitsuAcFanQuiet: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + default: return stdAc::fanspeed_t::kAuto; } } @@ -515,6 +569,9 @@ stdAc::state_t IRFujitsuAC::toCommon(void) { switch (result.model) { case fujitsu_ac_remote_model_t::ARREB1E: case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARRY4: + result.clean = _clean; + result.filter = _filter; result.swingv = (swing & kFujitsuAcSwingVert) ? stdAc::swingv_t::kAuto : stdAc::swingv_t::kOff; result.swingh = (swing & kFujitsuAcSwingHoriz) ? stdAc::swingh_t::kAuto : @@ -545,15 +602,8 @@ String IRFujitsuAC::toString(void) { String result = ""; result.reserve(100); // Reserve some heap for the string to reduce fragging. fujitsu_ac_remote_model_t model = this->getModel(); - result += addIntToString(model, F("Model"), false); - switch (model) { - case fujitsu_ac_remote_model_t::ARRAH2E: result += F(" (ARRAH2E)"); break; - case fujitsu_ac_remote_model_t::ARDB1: result += F(" (ARDB1)"); break; - case fujitsu_ac_remote_model_t::ARREB1E: result += F(" (ARREB1E)"); break; - case fujitsu_ac_remote_model_t::ARJW2: result += F(" (ARJW2)"); break; - default: result += F(" (UNKNOWN)"); - } - result += addBoolToString(getPower(), F("Power")); + result += addModelToString(decode_type_t::FUJITSU_AC, model, false); + result += addBoolToString(getPower(), kPowerStr); result += addModeToString(getMode(), kFujitsuAcModeAuto, kFujitsuAcModeCool, kFujitsuAcModeHeat, kFujitsuAcModeDry, kFujitsuAcModeFan); @@ -562,54 +612,58 @@ String IRFujitsuAC::toString(void) { kFujitsuAcFanAuto, kFujitsuAcFanQuiet, kFujitsuAcFanMed); switch (model) { - // These models have no internal swing state. + // These models have no internal swing, clean. or filter state. case fujitsu_ac_remote_model_t::ARDB1: case fujitsu_ac_remote_model_t::ARJW2: break; default: // Assume everything else does. - result += F(", Swing: "); + result += addBoolToString(getClean(), kCleanStr); + result += addBoolToString(getFilter(), kFilterStr); + result += addIntToString(this->getSwing(), kSwingStr); + result += kSpaceLBraceStr; switch (this->getSwing()) { case kFujitsuAcSwingOff: - result += F("Off"); + result += kOffStr; break; case kFujitsuAcSwingVert: - result += F("Vert"); + result += kSwingVStr; break; case kFujitsuAcSwingHoriz: - result += F("Horiz"); + result += kSwingHStr; break; case kFujitsuAcSwingBoth: - result += F("Vert + Horiz"); + result += kSwingVStr + '+' + kSwingHStr; break; default: - result += F("UNKNOWN"); + result += kUnknownStr; } + result += ')'; } - result += F(", Command: "); + result += kCommaSpaceStr + kCommandStr + kColonSpaceStr; switch (this->getCmd()) { case kFujitsuAcCmdStepHoriz: - result += F("Step vane horizontally"); + result += kStepStr + ' ' + kSwingHStr; break; case kFujitsuAcCmdStepVert: - result += F("Step vane vertically"); + result += kStepStr + ' ' + kSwingVStr; break; case kFujitsuAcCmdToggleSwingHoriz: - result += F("Toggle horizontal swing"); + result += kToggleStr + ' ' + kSwingHStr; break; case kFujitsuAcCmdToggleSwingVert: - result += F("Toggle vertically swing"); + result += kToggleStr + ' ' + kSwingVStr; break; case kFujitsuAcCmdEcono: - result += F("Economy"); + result += kEconoStr; break; case kFujitsuAcCmdPowerful: - result += F("Powerful"); + result += kPowerfulStr; break; default: - result += F("N/A"); + result += kNAStr; } if (this->getModel() == fujitsu_ac_remote_model_t::ARREB1E) - result += addBoolToString(getOutsideQuiet(), F("Outside Quiet")); + result += addBoolToString(getOutsideQuiet(), kOutsideStr + ' ' + kQuietStr); return result; } @@ -642,10 +696,8 @@ bool IRrecv::decodeFujitsuAC(decode_results* results, uint16_t nbits, case kFujitsuAcBits: case kFujitsuAcBits - 8: case kFujitsuAcMinBits: - case kFujitsuAcMinBits + 8: - break; - default: - return false; // Must be called with the correct nr. of bits. + case kFujitsuAcMinBits + 8: break; + default: return false; // Must be called with the correct nr. of bits. } } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.h b/lib/IRremoteESP8266-2.7.0/src/ir_Fujitsu.h old mode 100755 new mode 100644 similarity index 88% rename from lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Fujitsu.h index e953f9058..eae0edb8f --- a/lib/IRremoteESP8266-2.6.5/src/ir_Fujitsu.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Fujitsu.h @@ -9,7 +9,13 @@ // Brand: Fujitsu, Model: AR-REB1E remote // Brand: Fujitsu, Model: ASYG7LMCA A/C // Brand: Fujitsu, Model: AR-RAE1E remote +// Brand: Fujitsu, Model: AGTV14LAC A/C +// Brand: Fujitsu, Model: AR-RAC1E remote +// Brand: Fujitsu, Model: ASTB09LBC A/C +// Brand: Fujitsu, Model: AR-RY4 remote // Brand: Fujitsu General, Model: AR-JW2 remote +// Brand: Fujitsu, Model: AR-DL10 remote +// Brand: Fujitsu, Model: ASU30C1 A/C #ifndef IR_FUJITSU_H_ #define IR_FUJITSU_H_ @@ -50,15 +56,21 @@ const uint8_t kFujitsuAcFanHigh = 0x01; const uint8_t kFujitsuAcFanMed = 0x02; const uint8_t kFujitsuAcFanLow = 0x03; const uint8_t kFujitsuAcFanQuiet = 0x04; +const uint8_t kFujitsuAcFanSize = 3; // Bits const uint8_t kFujitsuAcMinTemp = 16; // 16C const uint8_t kFujitsuAcMaxTemp = 30; // 30C +const uint8_t kFujitsuAcSwingSize = 2; const uint8_t kFujitsuAcSwingOff = 0x00; const uint8_t kFujitsuAcSwingVert = 0x01; const uint8_t kFujitsuAcSwingHoriz = 0x02; const uint8_t kFujitsuAcSwingBoth = 0x03; +const uint8_t kFujitsuAcOutsideQuietOffset = 7; +const uint8_t kFujitsuAcCleanOffset = 3; +const uint8_t kFujitsuAcFilterOffset = 3; + // Legacy defines. #define FUJITSU_AC_MODE_AUTO kFujitsuAcModeAuto #define FUJITSU_AC_MODE_COOL kFujitsuAcModeCool @@ -82,12 +94,6 @@ const uint8_t kFujitsuAcSwingBoth = 0x03; #define FUJITSU_AC_SWING_HORIZ kFujitsuAcSwingHoriz #define FUJITSU_AC_SWING_BOTH kFujitsuAcSwingBoth -enum fujitsu_ac_remote_model_t { - ARRAH2E = 1, // (1) AR-RAH2E, AR-RAE1E (Default) - ARDB1, // (2) AR-DB1 - ARREB1E, // (3) AR-REB1E - ARJW2, // (4) AR-JW2 (Same as ARDB1 but with horiz control) -}; class IRFujitsuAC { public: @@ -126,6 +132,10 @@ class IRFujitsuAC { void off(void); void on(void); bool getPower(void); + void setClean(const bool on); + bool getClean(const bool raw = false); + void setFilter(const bool on); + bool getFilter(const bool raw = false); void setOutsideQuiet(const bool on); bool getOutsideQuiet(const bool raw = false); @@ -153,6 +163,8 @@ class IRFujitsuAC { uint8_t _state_length; uint8_t _state_length_short; bool _outsideQuiet; + bool _clean; + bool _filter; void buildState(void); void buildFromState(const uint16_t length); }; diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_GICable.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_GICable.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_GICable.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_GICable.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_GlobalCache.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_GlobalCache.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_GlobalCache.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_GlobalCache.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Goodweather.cpp old mode 100755 new mode 100644 similarity index 72% rename from lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Goodweather.cpp index d8ac45f1b..4cf2e55cd --- a/lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Goodweather.cpp @@ -14,6 +14,7 @@ #include "IRrecv.h" #include "IRremoteESP8266.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" using irutils::addBoolToString; @@ -22,6 +23,8 @@ using irutils::addLabeledString; using irutils::addModeToString; using irutils::addFanToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_GOODWEATHER // Send a Goodweather message. @@ -68,8 +71,7 @@ IRGoodweatherAc::IRGoodweatherAc(const uint16_t pin, const bool inverted, const bool use_modulation) : _irsend(pin, inverted, use_modulation) { stateReset(); } -void IRGoodweatherAc::stateReset(void) { -} +void IRGoodweatherAc::stateReset(void) { remote = kGoodweatherStateInit; } void IRGoodweatherAc::begin(void) { _irsend.begin(); } @@ -89,13 +91,12 @@ void IRGoodweatherAc::off(void) { this->setPower(false); } void IRGoodweatherAc::setPower(const bool on) { this->setCommand(kGoodweatherCmdPower); - if (on) - remote |= kGoodweatherPowerMask; - else - remote &= ~kGoodweatherPowerMask; + setBit(&remote, kGoodweatherBitPower, on); } -bool IRGoodweatherAc::getPower(void) { return remote & kGoodweatherPowerMask; } +bool IRGoodweatherAc::getPower(void) { + return GETBIT64(remote, kGoodweatherBitPower); +} // Set the temp. in deg C void IRGoodweatherAc::setTemp(const uint8_t temp) { @@ -103,13 +104,13 @@ void IRGoodweatherAc::setTemp(const uint8_t temp) { new_temp = std::min(kGoodweatherTempMax, new_temp); if (new_temp > this->getTemp()) this->setCommand(kGoodweatherCmdUpTemp); if (new_temp < this->getTemp()) this->setCommand(kGoodweatherCmdDownTemp); - remote &= ~kGoodweatherTempMask; - remote |= (uint64_t)(new_temp - kGoodweatherTempMin) << kGoodweatherBitTemp; + setBits(&remote, kGoodweatherBitTemp, kGoodweatherTempSize, + new_temp - kGoodweatherTempMin); } // Return the set temp. in deg C uint8_t IRGoodweatherAc::getTemp(void) { - return ((remote & kGoodweatherTempMask) >> kGoodweatherBitTemp) + + return GETBITS64(remote, kGoodweatherBitTemp, kGoodweatherTempSize) + kGoodweatherTempMin; } @@ -121,8 +122,7 @@ void IRGoodweatherAc::setFan(const uint8_t speed) { case kGoodweatherFanMed: case kGoodweatherFanHigh: this->setCommand(kGoodweatherCmdFan); - remote &= ~kGoodweatherFanMask; - remote |= ((uint64_t)speed << kGoodweatherBitFan); + setBits(&remote, kGoodweatherBitFan, kGoodweatherFanSize, speed); break; default: this->setFan(kGoodweatherFanAuto); @@ -130,7 +130,7 @@ void IRGoodweatherAc::setFan(const uint8_t speed) { } uint8_t IRGoodweatherAc::getFan() { - return (remote & kGoodweatherFanMask) >> kGoodweatherBitFan; + return GETBITS64(remote, kGoodweatherBitFan, kGoodweatherFanSize); } void IRGoodweatherAc::setMode(const uint8_t mode) { @@ -141,8 +141,7 @@ void IRGoodweatherAc::setMode(const uint8_t mode) { case kGoodweatherFan: case kGoodweatherHeat: this->setCommand(kGoodweatherCmdMode); - remote &= ~kGoodweatherModeMask; - remote |= (uint64_t)mode << kGoodweatherBitMode; + setBits(&remote, kGoodweatherBitMode, kModeBitsSize, mode); break; default: // If we get an unexpected mode, default to AUTO. @@ -151,38 +150,35 @@ void IRGoodweatherAc::setMode(const uint8_t mode) { } uint8_t IRGoodweatherAc::getMode() { - return (remote & kGoodweatherModeMask) >> kGoodweatherBitMode; + return GETBITS64(remote, kGoodweatherBitMode, kModeBitsSize); } void IRGoodweatherAc::setLight(const bool toggle) { this->setCommand(kGoodweatherCmdLight); - if (toggle) - remote |= kGoodweatherLightMask; - else - remote &= ~kGoodweatherLightMask; + setBit(&remote, kGoodweatherBitLight, toggle); } -bool IRGoodweatherAc::getLight() { return remote & kGoodweatherLightMask; } +bool IRGoodweatherAc::getLight() { + return GETBIT64(remote, kGoodweatherBitLight); +} void IRGoodweatherAc::setSleep(const bool toggle) { this->setCommand(kGoodweatherCmdSleep); - if (toggle) - remote |= kGoodweatherSleepMask; - else - remote &= ~kGoodweatherSleepMask; + setBit(&remote, kGoodweatherBitSleep, toggle); } -bool IRGoodweatherAc::getSleep() { return remote & kGoodweatherSleepMask; } +bool IRGoodweatherAc::getSleep() { + return GETBIT64(remote, kGoodweatherBitSleep); +} void IRGoodweatherAc::setTurbo(const bool toggle) { this->setCommand(kGoodweatherCmdTurbo); - if (toggle) - remote |= kGoodweatherTurboMask; - else - remote &= ~kGoodweatherTurboMask; + setBit(&remote, kGoodweatherBitTurbo, toggle); } -bool IRGoodweatherAc::getTurbo() { return remote & kGoodweatherTurboMask; } +bool IRGoodweatherAc::getTurbo() { + return GETBIT64(remote, kGoodweatherBitTurbo); +} void IRGoodweatherAc::setSwing(const uint8_t speed) { switch (speed) { @@ -190,8 +186,7 @@ void IRGoodweatherAc::setSwing(const uint8_t speed) { case kGoodweatherSwingSlow: case kGoodweatherSwingFast: this->setCommand(kGoodweatherCmdSwing); - remote &= ~kGoodweatherSwingMask; - remote |= ((uint64_t)speed << kGoodweatherBitSwing); + setBits(&remote, kGoodweatherBitSwing, kGoodweatherSwingSize, speed); break; default: this->setSwing(kGoodweatherSwingOff); @@ -199,33 +194,26 @@ void IRGoodweatherAc::setSwing(const uint8_t speed) { } uint8_t IRGoodweatherAc::getSwing() { - return (remote & kGoodweatherSwingMask) >> kGoodweatherBitSwing; + return GETBITS64(remote, kGoodweatherBitSwing, kGoodweatherSwingSize); } void IRGoodweatherAc::setCommand(const uint8_t cmd) { - if (cmd <= kGoodweatherCmdLight) { - remote &= ~kGoodweatherCommandMask; - remote |= (cmd << kGoodweatherBitCommand); - } + if (cmd <= kGoodweatherCmdLight) + setBits(&remote, kGoodweatherBitCommand, kGoodweatherCommandSize, cmd); } uint8_t IRGoodweatherAc::getCommand() { - return (remote & kGoodweatherCommandMask) >> kGoodweatherBitCommand; + return GETBITS64(remote, kGoodweatherBitCommand, kGoodweatherCommandSize); } // Convert a standard A/C mode into its native mode. uint8_t IRGoodweatherAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kGoodweatherCool; - case stdAc::opmode_t::kHeat: - return kGoodweatherHeat; - case stdAc::opmode_t::kDry: - return kGoodweatherDry; - case stdAc::opmode_t::kFan: - return kGoodweatherFan; - default: - return kGoodweatherAuto; + case stdAc::opmode_t::kCool: return kGoodweatherCool; + case stdAc::opmode_t::kHeat: return kGoodweatherHeat; + case stdAc::opmode_t::kDry: return kGoodweatherDry; + case stdAc::opmode_t::kFan: return kGoodweatherFan; + default: return kGoodweatherAuto; } } @@ -233,15 +221,11 @@ uint8_t IRGoodweatherAc::convertMode(const stdAc::opmode_t mode) { uint8_t IRGoodweatherAc::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kGoodweatherFanLow; - case stdAc::fanspeed_t::kMedium: - return kGoodweatherFanMed; + case stdAc::fanspeed_t::kLow: return kGoodweatherFanLow; + case stdAc::fanspeed_t::kMedium: return kGoodweatherFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kGoodweatherFanHigh; - default: - return kGoodweatherFanAuto; + case stdAc::fanspeed_t::kMax: return kGoodweatherFanHigh; + default: return kGoodweatherFanAuto; } } @@ -250,14 +234,11 @@ uint8_t IRGoodweatherAc::convertSwingV(const stdAc::swingv_t swingv) { switch (swingv) { case stdAc::swingv_t::kHighest: case stdAc::swingv_t::kHigh: - case stdAc::swingv_t::kMiddle: - return kGoodweatherSwingFast; + case stdAc::swingv_t::kMiddle: return kGoodweatherSwingFast; case stdAc::swingv_t::kLow: case stdAc::swingv_t::kLowest: - case stdAc::swingv_t::kAuto: - return kGoodweatherSwingSlow; - default: - return kGoodweatherSwingOff; + case stdAc::swingv_t::kAuto: return kGoodweatherSwingSlow; + default: return kGoodweatherSwingOff; } } @@ -266,9 +247,9 @@ stdAc::opmode_t IRGoodweatherAc::toCommonMode(const uint8_t mode) { switch (mode) { case kGoodweatherCool: return stdAc::opmode_t::kCool; case kGoodweatherHeat: return stdAc::opmode_t::kHeat; - case kGoodweatherDry: return stdAc::opmode_t::kDry; - case kGoodweatherFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kGoodweatherDry: return stdAc::opmode_t::kDry; + case kGoodweatherFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -276,9 +257,9 @@ stdAc::opmode_t IRGoodweatherAc::toCommonMode(const uint8_t mode) { stdAc::fanspeed_t IRGoodweatherAc::toCommonFanSpeed(const uint8_t speed) { switch (speed) { case kGoodweatherFanHigh: return stdAc::fanspeed_t::kMax; - case kGoodweatherFanMed: return stdAc::fanspeed_t::kMedium; - case kGoodweatherFanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kGoodweatherFanMed: return stdAc::fanspeed_t::kMedium; + case kGoodweatherFanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } @@ -309,74 +290,78 @@ stdAc::state_t IRGoodweatherAc::toCommon(void) { } // Convert the internal state into a human readable string. -String IRGoodweatherAc::toString() { +String IRGoodweatherAc::toString(void) { String result = ""; result.reserve(150); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kGoodweatherAuto, kGoodweatherCool, kGoodweatherHeat, kGoodweatherDry, kGoodweatherFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kGoodweatherFanHigh, kGoodweatherFanLow, kGoodweatherFanAuto, kGoodweatherFanAuto, kGoodweatherFanMed); - result += addLabeledString(getTurbo() ? F("Toggle") : F("-"), F("Turbo")); - result += addLabeledString(getLight() ? F("Toggle") : F("-"), F("Light")); - result += addLabeledString(getSleep() ? F("Toggle") : F("-"), F("Sleep")); - result += addIntToString(getSwing(), F("Swing")); + result += addLabeledString(getTurbo() ? kToggleStr : F("-"), kTurboStr); + result += addLabeledString(getLight() ? kToggleStr : F("-"), kLightStr); + result += addLabeledString(getSleep() ? kToggleStr : F("-"), kSleepStr); + result += addIntToString(getSwing(), kSwingStr); + result += kSpaceLBraceStr; switch (this->getSwing()) { case kGoodweatherSwingFast: - result += F(" (Fast)"); + result += kFastStr; break; case kGoodweatherSwingSlow: - result += F(" (Slow)"); + result += kSlowStr; break; case kGoodweatherSwingOff: - result += F(" (Off)"); + result += kOffStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } - result += addIntToString(getCommand(), F("Command")); + result += ')'; + result += addIntToString(getCommand(), kCommandStr); + result += kSpaceLBraceStr; switch (this->getCommand()) { case kGoodweatherCmdPower: - result += F(" (Power)"); + result += kPowerStr; break; case kGoodweatherCmdMode: - result += F(" (Mode)"); + result += kModeStr; break; case kGoodweatherCmdUpTemp: - result += F(" (Temp Up)"); + result += kTempUpStr; break; case kGoodweatherCmdDownTemp: - result += F(" (Temp Down)"); + result += kTempDownStr; break; case kGoodweatherCmdSwing: - result += F(" (Swing)"); + result += kSwingStr; break; case kGoodweatherCmdFan: - result += F(" (Fan)"); + result += kFanStr; break; case kGoodweatherCmdTimer: - result += F(" (Timer)"); + result += kTimerStr; break; case kGoodweatherCmdAirFlow: - result += F(" (Air Flow)"); + result += kAirFlowStr; break; case kGoodweatherCmdHold: - result += F(" (Hold)"); + result += kHoldStr; break; case kGoodweatherCmdSleep: - result += F(" (Sleep)"); + result += kSleepStr; break; case kGoodweatherCmdTurbo: - result += F(" (Turbo)"); + result += kTurboStr; break; case kGoodweatherCmdLight: - result += F(" (Light)"); + result += kLightStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } + result += ')'; return result; } @@ -419,7 +404,8 @@ bool IRrecv::decodeGoodweather(decode_results* results, data_result = matchData(&(results->rawbuf[offset]), 8, kGoodweatherBitMark, kGoodweatherOneSpace, kGoodweatherBitMark, kGoodweatherZeroSpace, - _tolerance, kMarkExcess, false); + _tolerance + kGoodweatherExtraTolerance, + kMarkExcess, false); if (data_result.success == false) return false; DPRINTLN("DEBUG: Normal byte read okay."); offset += data_result.used; @@ -428,7 +414,8 @@ bool IRrecv::decodeGoodweather(decode_results* results, data_result = matchData(&(results->rawbuf[offset]), 8, kGoodweatherBitMark, kGoodweatherOneSpace, kGoodweatherBitMark, kGoodweatherZeroSpace, - _tolerance, kMarkExcess, false); + _tolerance + kGoodweatherExtraTolerance, + kMarkExcess, false); if (data_result.success == false) return false; DPRINTLN("DEBUG: Inverted byte read okay."); offset += data_result.used; @@ -442,10 +429,12 @@ bool IRrecv::decodeGoodweather(decode_results* results, } // Footer. - if (!matchMark(results->rawbuf[offset++], kGoodweatherBitMark)) return false; + if (!matchMark(results->rawbuf[offset++], kGoodweatherBitMark, + _tolerance + kGoodweatherExtraTolerance)) return false; if (!matchSpace(results->rawbuf[offset++], kGoodweatherHdrSpace)) return false; - if (!matchMark(results->rawbuf[offset++], kGoodweatherBitMark)) return false; + if (!matchMark(results->rawbuf[offset++], kGoodweatherBitMark, + _tolerance + kGoodweatherExtraTolerance)) return false; if (offset <= results->rawlen && !matchAtLeast(results->rawbuf[offset], kGoodweatherHdrSpace)) return false; diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.h b/lib/IRremoteESP8266-2.7.0/src/ir_Goodweather.h old mode 100755 new mode 100644 similarity index 81% rename from lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Goodweather.h index 76d559779..8f1953581 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Goodweather.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Goodweather.h @@ -26,31 +26,30 @@ // Constants // Timing -const uint16_t kGoodweatherBitMark = 640; +const uint16_t kGoodweatherBitMark = 580; const uint16_t kGoodweatherOneSpace = 580; -const uint16_t kGoodweatherZeroSpace = 1600; -const uint16_t kGoodweatherHdrMark = 6800; -const uint16_t kGoodweatherHdrSpace = 6800; +const uint16_t kGoodweatherZeroSpace = 1860; +const uint16_t kGoodweatherHdrMark = 6820; +const uint16_t kGoodweatherHdrSpace = 6820; +const uint8_t kGoodweatherExtraTolerance = 12; // +12% extra // Masks const uint8_t kGoodweatherBitLight = 8; -const uint64_t kGoodweatherLightMask = 0x1ULL << kGoodweatherBitLight; const uint8_t kGoodweatherBitTurbo = kGoodweatherBitLight + 3; // 11 -const uint64_t kGoodweatherTurboMask = 0x1ULL << kGoodweatherBitTurbo; const uint8_t kGoodweatherBitCommand = kGoodweatherBitTurbo + 5; // 16 -const uint64_t kGoodweatherCommandMask = 0xFULL << kGoodweatherBitCommand; +const uint8_t kGoodweatherCommandSize = 4; // Bits const uint8_t kGoodweatherBitSleep = kGoodweatherBitCommand + 8; // 24 -const uint64_t kGoodweatherSleepMask = 0x1ULL << kGoodweatherBitSleep; const uint8_t kGoodweatherBitPower = kGoodweatherBitSleep + 1; // 25 -const uint64_t kGoodweatherPowerMask = 0x1ULL << kGoodweatherBitPower; const uint8_t kGoodweatherBitSwing = kGoodweatherBitPower + 1; // 26 -const uint64_t kGoodweatherSwingMask = 0x3ULL << kGoodweatherBitSwing; -const uint8_t kGoodweatherBitFan = kGoodweatherBitSwing + 3; // 29 -const uint64_t kGoodweatherFanMask = 0x3ULL << kGoodweatherBitFan; +const uint8_t kGoodweatherSwingSize = 2; // Bits +const uint8_t kGoodweatherBitAirFlow = kGoodweatherBitSwing + 2; // 28 +const uint8_t kGoodweatherBitFan = kGoodweatherBitAirFlow + 1; // 29 +const uint8_t kGoodweatherFanSize = 2; // Bits const uint8_t kGoodweatherBitTemp = kGoodweatherBitFan + 3; // 32 -const uint64_t kGoodweatherTempMask = 0xFULL << kGoodweatherBitTemp; +const uint8_t kGoodweatherTempSize = 4; // Bits const uint8_t kGoodweatherBitMode = kGoodweatherBitTemp + 5; // 37 -const uint64_t kGoodweatherModeMask = 0x7ULL << kGoodweatherBitMode; +const uint8_t kGoodweatherBitEOF = kGoodweatherBitMode + 3; // 40 +const uint64_t kGoodweatherEOFMask = 0xFFULL << kGoodweatherBitEOF; // Modes const uint8_t kGoodweatherAuto = 0b000; @@ -58,6 +57,7 @@ const uint8_t kGoodweatherCool = 0b001; const uint8_t kGoodweatherDry = 0b010; const uint8_t kGoodweatherFan = 0b011; const uint8_t kGoodweatherHeat = 0b100; +// Swing const uint8_t kGoodweatherSwingFast = 0b00; const uint8_t kGoodweatherSwingSlow = 0b01; const uint8_t kGoodweatherSwingOff = 0b10; @@ -82,6 +82,8 @@ const uint8_t kGoodweatherCmdHold = 0x08; const uint8_t kGoodweatherCmdSleep = 0x09; const uint8_t kGoodweatherCmdTurbo = 0x0A; const uint8_t kGoodweatherCmdLight = 0x0B; +// PAD EOF +const uint64_t kGoodweatherStateInit = 0xD50000000000; // Classes diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Gree.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Gree.cpp old mode 100755 new mode 100644 similarity index 71% rename from lib/IRremoteESP8266-2.6.5/src/ir_Gree.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Gree.cpp index a4d906424..21eb78e28 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Gree.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Gree.cpp @@ -9,12 +9,14 @@ #include "ir_Gree.h" #include +#include #ifndef ARDUINO #include #endif #include "IRrecv.h" #include "IRremoteESP8266.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" #include "ir_Kelvinator.h" @@ -33,9 +35,12 @@ using irutils::addBoolToString; using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; +using irutils::addModelToString; using irutils::addFanToString; using irutils::addTempToString; using irutils::minsToString; +using irutils::setBit; +using irutils::setBits; #if SEND_GREE // Send a Gree Heat Pump message. @@ -151,12 +156,10 @@ uint8_t* IRGreeAC::getRaw(void) { } void IRGreeAC::setRaw(const uint8_t new_code[]) { - for (uint8_t i = 0; i < kGreeStateLength; i++) { - remote_state[i] = new_code[i]; - } + memcpy(remote_state, new_code, kGreeStateLength); // We can only detect the difference between models when the power is on. if (getPower()) { - if (remote_state[2] & kGreePower2Mask) + if (GETBIT8(remote_state[2], kGreePower2Offset)) _model = gree_ac_remote_model_t::YAW1F; else _model = gree_ac_remote_model_t::YBOFB; @@ -165,8 +168,8 @@ void IRGreeAC::setRaw(const uint8_t new_code[]) { void IRGreeAC::checksum(const uint16_t length) { // Gree uses the same checksum alg. as Kelvinator's block checksum. - uint8_t sum = IRKelvinatorAC::calcBlockChecksum(remote_state, length); - remote_state[length - 1] = (sum << 4) | (remote_state[length - 1] & 0xFU); + setBits(&remote_state[length - 1], kHighNibble, kNibbleSize, + IRKelvinatorAC::calcBlockChecksum(remote_state, length)); } // Verify the checksum is valid for a given state. @@ -177,45 +180,34 @@ void IRGreeAC::checksum(const uint16_t length) { // A boolean. bool IRGreeAC::validChecksum(const uint8_t state[], const uint16_t length) { // Top 4 bits of the last byte in the state is the state's checksum. - return (state[length - 1] >> 4 == IRKelvinatorAC::calcBlockChecksum(state, - length)); + return GETBITS8(state[length - 1], kHighNibble, kNibbleSize) == + IRKelvinatorAC::calcBlockChecksum(state, length); } void IRGreeAC::setModel(const gree_ac_remote_model_t model) { switch (model) { case gree_ac_remote_model_t::YAW1F: - case gree_ac_remote_model_t::YBOFB: - _model = model; break; - default: - setModel(gree_ac_remote_model_t::YAW1F); + case gree_ac_remote_model_t::YBOFB: _model = model; break; + default: setModel(gree_ac_remote_model_t::YAW1F); } } -gree_ac_remote_model_t IRGreeAC::getModel(void) { - return _model; -} +gree_ac_remote_model_t IRGreeAC::getModel(void) { return _model; } void IRGreeAC::on(void) { setPower(true); } void IRGreeAC::off(void) { setPower(false); } void IRGreeAC::setPower(const bool on) { - if (on) { - remote_state[0] |= kGreePower1Mask; - switch (_model) { - case gree_ac_remote_model_t::YBOFB: break; - default: - remote_state[2] |= kGreePower2Mask; - } - } else { - remote_state[0] &= ~kGreePower1Mask; - remote_state[2] &= ~kGreePower2Mask; // May not be needed. See #814 - } + setBit(&remote_state[0], kGreePower1Offset, on); + // May not be needed. See #814 + setBit(&remote_state[2], kGreePower2Offset, + on && _model != gree_ac_remote_model_t::YBOFB); } bool IRGreeAC::getPower(void) { // See #814. Not checking/requiring: (remote_state[2] & kGreePower2Mask) - return remote_state[0] & kGreePower1Mask; + return GETBIT8(remote_state[0], kGreePower1Offset); } // Set the temp. in deg C @@ -223,109 +215,96 @@ void IRGreeAC::setTemp(const uint8_t temp) { uint8_t new_temp = std::max((uint8_t)kGreeMinTemp, temp); new_temp = std::min((uint8_t)kGreeMaxTemp, new_temp); if (getMode() == kGreeAuto) new_temp = 25; - remote_state[1] = (remote_state[1] & ~kGreeTempMask) | - (new_temp - kGreeMinTemp); + setBits(&remote_state[1], kLowNibble, kGreeTempSize, new_temp - kGreeMinTemp); } // Return the set temp. in deg C uint8_t IRGreeAC::getTemp(void) { - return ((remote_state[1] & kGreeTempMask) + kGreeMinTemp); + return GETBITS8(remote_state[1], kLowNibble, kGreeTempSize) + kGreeMinTemp; } // Set the speed of the fan, 0-3, 0 is auto, 1-3 is the speed void IRGreeAC::setFan(const uint8_t speed) { uint8_t fan = std::min((uint8_t)kGreeFanMax, speed); // Bounds check - if (getMode() == kGreeDry) fan = 1; // DRY mode is always locked to fan 1. // Set the basic fan values. - remote_state[0] &= ~kGreeFanMask; - remote_state[0] |= (fan << 4); + setBits(&remote_state[0], kGreeFanOffset, kGreeFanSize, fan); } -uint8_t IRGreeAC::getFan(void) { return (remote_state[0] & kGreeFanMask) >> 4; } +uint8_t IRGreeAC::getFan(void) { + return GETBITS8(remote_state[0], kGreeFanOffset, kGreeFanSize); +} void IRGreeAC::setMode(const uint8_t new_mode) { uint8_t mode = new_mode; switch (mode) { - case kGreeAuto: - // AUTO is locked to 25C - setTemp(25); - break; - case kGreeDry: - // DRY always sets the fan to 1. - setFan(1); - break; + // AUTO is locked to 25C + case kGreeAuto: setTemp(25); break; + // DRY always sets the fan to 1. + case kGreeDry: setFan(1); break; case kGreeCool: case kGreeFan: - case kGreeHeat: - break; - default: - // If we get an unexpected mode, default to AUTO. - mode = kGreeAuto; + case kGreeHeat: break; + // If we get an unexpected mode, default to AUTO. + default: mode = kGreeAuto; } - remote_state[0] &= ~kGreeModeMask; - remote_state[0] |= mode; + setBits(&remote_state[0], kLowNibble, kModeBitsSize, mode); } -uint8_t IRGreeAC::getMode(void) { return (remote_state[0] & kGreeModeMask); } +uint8_t IRGreeAC::getMode(void) { + return GETBITS8(remote_state[0], kLowNibble, kModeBitsSize); +} void IRGreeAC::setLight(const bool on) { - if (on) - remote_state[2] |= kGreeLightMask; - else - remote_state[2] &= ~kGreeLightMask; + setBit(&remote_state[2], kGreeLightOffset, on); } -bool IRGreeAC::getLight(void) { return remote_state[2] & kGreeLightMask; } +bool IRGreeAC::getLight(void) { + return GETBIT8(remote_state[2], kGreeLightOffset); +} void IRGreeAC::setIFeel(const bool on) { - if (on) - remote_state[5] |= kGreeIFeelMask; - else - remote_state[5] &= ~kGreeIFeelMask; + setBit(&remote_state[5], kGreeIFeelOffset, on); } -bool IRGreeAC::getIFeel(void) { return remote_state[5] & kGreeIFeelMask; } +bool IRGreeAC::getIFeel(void) { + return GETBIT8(remote_state[5], kGreeIFeelOffset); +} void IRGreeAC::setWiFi(const bool on) { - if (on) - remote_state[5] |= kGreeWiFiMask; - else - remote_state[5] &= ~kGreeWiFiMask; + setBit(&remote_state[5], kGreeWiFiOffset, on); } -bool IRGreeAC::getWiFi(void) { return remote_state[5] & kGreeWiFiMask; } +bool IRGreeAC::getWiFi(void) { + return GETBIT8(remote_state[5], kGreeWiFiOffset); +} void IRGreeAC::setXFan(const bool on) { - if (on) - remote_state[2] |= kGreeXfanMask; - else - remote_state[2] &= ~kGreeXfanMask; + setBit(&remote_state[2], kGreeXfanOffset, on); } -bool IRGreeAC::getXFan(void) { return remote_state[2] & kGreeXfanMask; } +bool IRGreeAC::getXFan(void) { + return GETBIT8(remote_state[2], kGreeXfanOffset); +} void IRGreeAC::setSleep(const bool on) { - if (on) - remote_state[0] |= kGreeSleepMask; - else - remote_state[0] &= ~kGreeSleepMask; + setBit(&remote_state[0], kGreeSleepOffset, on); } -bool IRGreeAC::getSleep(void) { return remote_state[0] & kGreeSleepMask; } +bool IRGreeAC::getSleep(void) { + return GETBIT8(remote_state[0], kGreeSleepOffset); +} void IRGreeAC::setTurbo(const bool on) { - if (on) - remote_state[2] |= kGreeTurboMask; - else - remote_state[2] &= ~kGreeTurboMask; + setBit(&remote_state[2], kGreeTurboOffset, on); } -bool IRGreeAC::getTurbo(void) { return remote_state[2] & kGreeTurboMask; } +bool IRGreeAC::getTurbo(void) { + return GETBIT8(remote_state[2], kGreeTurboOffset); +} void IRGreeAC::setSwingVertical(const bool automatic, const uint8_t position) { - remote_state[0] &= ~kGreeSwingAutoMask; - remote_state[0] |= (automatic << 6); + setBit(&remote_state[0], kGreeSwingAutoOffset, automatic); uint8_t new_position = position; if (!automatic) { switch (position) { @@ -349,35 +328,32 @@ void IRGreeAC::setSwingVertical(const bool automatic, const uint8_t position) { new_position = kGreeSwingAuto; } } - remote_state[4] &= ~kGreeSwingPosMask; - remote_state[4] |= new_position; + setBits(&remote_state[4], kLowNibble, kGreeSwingSize, new_position); } bool IRGreeAC::getSwingVerticalAuto(void) { - return remote_state[0] & kGreeSwingAutoMask; + return GETBIT8(remote_state[0], kGreeSwingAutoOffset); } uint8_t IRGreeAC::getSwingVerticalPosition(void) { - return remote_state[4] & kGreeSwingPosMask; + return GETBITS8(remote_state[4], kLowNibble, kGreeSwingSize); } void IRGreeAC::setTimerEnabled(const bool on) { - if (on) - remote_state[1] |= kGreeTimerEnabledBit; - else - remote_state[1] &= ~kGreeTimerEnabledBit; + setBit(&remote_state[1], kGreeTimerEnabledOffset, on); } bool IRGreeAC::getTimerEnabled(void) { - return remote_state[1] & kGreeTimerEnabledBit; + return GETBIT8(remote_state[1], kGreeTimerEnabledOffset); } // Returns the number of minutes the timer is set for. uint16_t IRGreeAC::getTimer(void) { uint16_t hrs = irutils::bcdToUint8( - (remote_state[2] & kGreeTimerHoursMask) | - ((remote_state[1] & kGreeTimerTensHrMask) >> 1)); - return hrs * 60 + ((remote_state[1] & kGreeTimerHalfHrBit) ? 30 : 0); + (GETBITS8(remote_state[1], kGreeTimerTensHrOffset, + kGreeTimerTensHrSize) << kNibbleSize) | + GETBITS8(remote_state[2], kGreeTimerHoursOffset, kGreeTimerHoursSize)); + return hrs * 60 + (GETBIT8(remote_state[1], kGreeTimerHalfHrOffset) ? 30 : 0); } // Set the A/C's timer to turn off in X many minutes. @@ -387,66 +363,51 @@ uint16_t IRGreeAC::getTimer(void) { // Args: // minutes: The number of minutes the timer should be set for. void IRGreeAC::setTimer(const uint16_t minutes) { - // Clear the previous settings. - remote_state[1] &= ~kGreeTimer1Mask; - remote_state[2] &= ~kGreeTimerHoursMask; uint16_t mins = std::min(kGreeTimerMax, minutes); // Bounds check. setTimerEnabled(mins >= 30); // Timer is enabled when >= 30 mins. uint8_t hours = mins / 60; - uint8_t halfhour = (mins % 60) < 30 ? 0 : 1; - // Set the "tens" digit of hours & the half hour. - remote_state[1] |= (((hours / 10) << 1) | halfhour) << 4; + // Set the half hour bit. + setBit(&remote_state[1], kGreeTimerHalfHrOffset, !((mins % 60) < 30)); + // Set the "tens" digit of hours. + setBits(&remote_state[1], kGreeTimerTensHrOffset, kGreeTimerTensHrSize, + hours / 10); // Set the "units" digit of hours. - remote_state[2] |= (hours % 10); + setBits(&remote_state[2], kGreeTimerHoursOffset, kGreeTimerHoursSize, + hours % 10); } // Convert a standard A/C mode into its native mode. uint8_t IRGreeAC::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kGreeCool; - case stdAc::opmode_t::kHeat: - return kGreeHeat; - case stdAc::opmode_t::kDry: - return kGreeDry; - case stdAc::opmode_t::kFan: - return kGreeFan; - default: - return kGreeAuto; + case stdAc::opmode_t::kCool: return kGreeCool; + case stdAc::opmode_t::kHeat: return kGreeHeat; + case stdAc::opmode_t::kDry: return kGreeDry; + case stdAc::opmode_t::kFan: return kGreeFan; + default: return kGreeAuto; } } // Convert a standard A/C Fan speed into its native fan speed. uint8_t IRGreeAC::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { - case stdAc::fanspeed_t::kMin: - return kGreeFanMin; + case stdAc::fanspeed_t::kMin: return kGreeFanMin; case stdAc::fanspeed_t::kLow: - case stdAc::fanspeed_t::kMedium: - return kGreeFanMax - 1; + case stdAc::fanspeed_t::kMedium: return kGreeFanMax - 1; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kGreeFanMax; - default: - return kGreeFanAuto; + case stdAc::fanspeed_t::kMax: return kGreeFanMax; + default: return kGreeFanAuto; } } // Convert a standard A/C Vertical Swing into its native version. uint8_t IRGreeAC::convertSwingV(const stdAc::swingv_t swingv) { switch (swingv) { - case stdAc::swingv_t::kHighest: - return kGreeSwingUp; - case stdAc::swingv_t::kHigh: - return kGreeSwingMiddleUp; - case stdAc::swingv_t::kMiddle: - return kGreeSwingMiddle; - case stdAc::swingv_t::kLow: - return kGreeSwingMiddleDown; - case stdAc::swingv_t::kLowest: - return kGreeSwingDown; - default: - return kGreeSwingAuto; + case stdAc::swingv_t::kHighest: return kGreeSwingUp; + case stdAc::swingv_t::kHigh: return kGreeSwingMiddleUp; + case stdAc::swingv_t::kMiddle: return kGreeSwingMiddle; + case stdAc::swingv_t::kLow: return kGreeSwingMiddleDown; + case stdAc::swingv_t::kLowest: return kGreeSwingDown; + default: return kGreeSwingAuto; } } @@ -515,40 +476,35 @@ stdAc::state_t IRGreeAC::toCommon(void) { String IRGreeAC::toString(void) { String result = ""; result.reserve(150); // Reserve some heap for the string to reduce fragging. - result += addIntToString(getModel(), F("Model"), false); - switch (getModel()) { - case gree_ac_remote_model_t::YAW1F: result += F(" (YAW1F)"); break; - case gree_ac_remote_model_t::YBOFB: result += F(" (YBOFB)"); break; - default: result += F(" (UNKNOWN)"); - } - result += addBoolToString(getPower(), F("Power")); + result += addModelToString(decode_type_t::GREE, getModel(), false); + result += addBoolToString(getPower(), kPowerStr); result += addModeToString(getMode(), kGreeAuto, kGreeCool, kGreeHeat, kGreeDry, kGreeFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kGreeFanMax, kGreeFanMin, kGreeFanAuto, kGreeFanAuto, kGreeFanMed); - result += addBoolToString(getTurbo(), F("Turbo")); - result += addBoolToString(getIFeel(), F("IFeel")); - result += addBoolToString(getWiFi(), F("WiFi")); - result += addBoolToString(getXFan(), F("XFan")); - result += addBoolToString(getLight(), F("Light")); - result += addBoolToString(getSleep(), F("Sleep")); - result += addLabeledString(getSwingVerticalAuto() ? F("Auto") : F("Manual"), - F("Swing Vertical Mode")); - result += addIntToString(getSwingVerticalPosition(), F("Swing Vertical Pos")); + result += addBoolToString(getTurbo(), kTurboStr); + result += addBoolToString(getIFeel(), kIFeelStr); + result += addBoolToString(getWiFi(), kWifiStr); + result += addBoolToString(getXFan(), kXFanStr); + result += addBoolToString(getLight(), kLightStr); + result += addBoolToString(getSleep(), kSleepStr); + result += addLabeledString(getSwingVerticalAuto() ? kAutoStr : kManualStr, + kSwingVStr + ' ' + kModeStr); + result += addIntToString(getSwingVerticalPosition(), kSwingVStr); + result += kSpaceLBraceStr; switch (getSwingVerticalPosition()) { case kGreeSwingLastPos: - result += F(" (Last Pos)"); + result += kLastStr; break; case kGreeSwingAuto: - result += F(" (Auto)"); + result += kAutoStr; break; + default: result += kUnknownStr; } - result += F(", Timer: "); - if (getTimerEnabled()) - result += minsToString(getTimer()); - else - result += F("Off"); + result += ')'; + result += addLabeledString( + getTimerEnabled() ? minsToString(getTimer()) : kOffStr, kTimerStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Gree.h b/lib/IRremoteESP8266-2.7.0/src/ir_Gree.h old mode 100755 new mode 100644 similarity index 72% rename from lib/IRremoteESP8266-2.6.5/src/ir_Gree.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Gree.h index a399d50d5..14cd7b84a --- a/lib/IRremoteESP8266-2.6.5/src/ir_Gree.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Gree.h @@ -24,10 +24,6 @@ #endif // Constants -enum gree_ac_remote_model_t { - YAW1F = 1, // (1) Ultimate, EKOKAI, RusClimate (Default) - YBOFB, // (2) Green, YBOFB2, YAPOF3 -}; const uint8_t kGreeAuto = 0; const uint8_t kGreeCool = 1; @@ -36,48 +32,48 @@ const uint8_t kGreeFan = 3; const uint8_t kGreeHeat = 4; // Byte 0 -const uint8_t kGreeModeMask = 0b00000111; -const uint8_t kGreePower1Mask = 0b00001000; -const uint8_t kGreeFanMask = 0b00110000; +const uint8_t kGreePower1Offset = 3; +const uint8_t kGreeFanOffset = 4; +const uint8_t kGreeFanSize = 2; // Bits const uint8_t kGreeFanAuto = 0; const uint8_t kGreeFanMin = 1; const uint8_t kGreeFanMed = 2; const uint8_t kGreeFanMax = 3; -const uint8_t kGreeSwingAutoMask = 0b01000000; -const uint8_t kGreeSleepMask = 0b10000000; +const uint8_t kGreeSwingAutoOffset = 6; +const uint8_t kGreeSleepOffset = 7; // Byte 1 -const uint8_t kGreeTempMask = 0b00001111; +const uint8_t kGreeTempSize = 4; const uint8_t kGreeMinTemp = 16; // Celsius const uint8_t kGreeMaxTemp = 30; // Celsius -const uint8_t kGreeTimerEnabledBit = 0b10000000; -const uint8_t kGreeTimerHalfHrBit = 0b00010000; -const uint8_t kGreeTimerTensHrMask = 0b01100000; -const uint8_t kGreeTimer1Mask = kGreeTimerTensHrMask | kGreeTimerHalfHrBit; +const uint8_t kGreeTimerHalfHrOffset = 4; +const uint8_t kGreeTimerTensHrOffset = 5; +const uint8_t kGreeTimerTensHrSize = 2; // Bits const uint16_t kGreeTimerMax = 24 * 60; +const uint8_t kGreeTimerEnabledOffset = 7; // Byte 2 -const uint8_t kGreeTimerHoursMask = 0b00001111; -const uint8_t kGreeTurboMask = 0b00010000; -const uint8_t kGreeLightMask = 0b00100000; +const uint8_t kGreeTimerHoursOffset = 0; +const uint8_t kGreeTimerHoursSize = 4; // Bits +const uint8_t kGreeTurboOffset = 4; +const uint8_t kGreeLightOffset = 5; // This might not be used. See #814 -const uint8_t kGreePower2Mask = 0b01000000; -const uint8_t kGreeXfanMask = 0b10000000; +const uint8_t kGreePower2Offset = 6; +const uint8_t kGreeXfanOffset = 7; // Byte 4 -const uint8_t kGreeSwingPosMask = 0b00001111; +const uint8_t kGreeSwingSize = 4; // Bits +const uint8_t kGreeSwingLastPos = 0b0000; +const uint8_t kGreeSwingAuto = 0b0001; +const uint8_t kGreeSwingUp = 0b0010; +const uint8_t kGreeSwingMiddleUp = 0b0011; +const uint8_t kGreeSwingMiddle = 0b0100; +const uint8_t kGreeSwingMiddleDown = 0b0101; +const uint8_t kGreeSwingDown = 0b0110; +const uint8_t kGreeSwingDownAuto = 0b0111; +const uint8_t kGreeSwingMiddleAuto = 0b1001; +const uint8_t kGreeSwingUpAuto = 0b1011; // byte 5 -const uint8_t kGreeIFeelMask = 0b00000100; -const uint8_t kGreeWiFiMask = 0b01000000; - -const uint8_t kGreeSwingLastPos = 0b00000000; -const uint8_t kGreeSwingAuto = 0b00000001; -const uint8_t kGreeSwingUp = 0b00000010; -const uint8_t kGreeSwingMiddleUp = 0b00000011; -const uint8_t kGreeSwingMiddle = 0b00000100; -const uint8_t kGreeSwingMiddleDown = 0b00000101; -const uint8_t kGreeSwingDown = 0b00000110; -const uint8_t kGreeSwingDownAuto = 0b00000111; -const uint8_t kGreeSwingMiddleAuto = 0b00001001; -const uint8_t kGreeSwingUpAuto = 0b00001011; +const uint8_t kGreeIFeelOffset = 2; +const uint8_t kGreeWiFiOffset = 6; // Legacy defines. #define GREE_AUTO kGreeAuto diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Haier.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Haier.cpp old mode 100755 new mode 100644 similarity index 67% rename from lib/IRremoteESP8266-2.6.5/src/ir_Haier.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Haier.cpp index d2b947f9e..d0cbf5230 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Haier.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Haier.cpp @@ -5,10 +5,12 @@ // * YR-W02/HSU-09HMC203 by non7top. #include "ir_Haier.h" +#include #ifndef UNIT_TEST #include #endif #include "IRremoteESP8266.h" +#include "IRtext.h" #include "IRutils.h" // Supported devices: @@ -37,6 +39,8 @@ using irutils::addModeToString; using irutils::addFanToString; using irutils::addTempToString; using irutils::minsToString; +using irutils::setBit; +using irutils::setBits; #if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02) // Send a Haier A/C message. (HSU07-HEA03 remote) @@ -90,8 +94,7 @@ void IRHaierAC::begin(void) { _irsend.begin(); } #if SEND_HAIER_AC void IRHaierAC::send(const uint16_t repeat) { - checksum(); - _irsend.sendHaierAC(remote_state, kHaierACStateLength, repeat); + _irsend.sendHaierAC(getRaw(), kHaierACStateLength, repeat); } #endif // SEND_HAIER_AC @@ -123,14 +126,11 @@ uint8_t* IRHaierAC::getRaw(void) { } void IRHaierAC::setRaw(const uint8_t new_code[]) { - for (uint8_t i = 0; i < kHaierACStateLength; i++) { - remote_state[i] = new_code[i]; - } + memcpy(remote_state, new_code, kHaierACStateLength); } -void IRHaierAC::setCommand(const uint8_t state) { - remote_state[1] &= 0b11110000; - switch (state) { +void IRHaierAC::setCommand(const uint8_t command) { + switch (command) { case kHaierAcCmdOff: case kHaierAcCmdOn: case kHaierAcCmdMode: @@ -142,61 +142,51 @@ void IRHaierAC::setCommand(const uint8_t state) { case kHaierAcCmdTimerCancel: case kHaierAcCmdHealth: case kHaierAcCmdSwing: - remote_state[1] |= (state & 0b00001111); + setBits(&remote_state[1], kLowNibble, kNibbleSize, command); } } -uint8_t IRHaierAC::getCommand(void) { return remote_state[1] & (0b00001111); } +uint8_t IRHaierAC::getCommand(void) { + return GETBITS8(remote_state[1], kLowNibble, kNibbleSize); +} void IRHaierAC::setFan(const uint8_t speed) { uint8_t new_speed = kHaierAcFanAuto; switch (speed) { - case kHaierAcFanLow: - new_speed = 3; - break; - case kHaierAcFanMed: - new_speed = 1; - break; - case kHaierAcFanHigh: - new_speed = 2; - break; - default: - new_speed = kHaierAcFanAuto; // Default to auto for anything else. + case kHaierAcFanLow: new_speed = 3; break; + case kHaierAcFanMed: new_speed = 1; break; + case kHaierAcFanHigh: new_speed = 2; break; + // Default to auto for anything else. + default: new_speed = kHaierAcFanAuto; } if (speed != getFan()) setCommand(kHaierAcCmdFan); - remote_state[5] &= 0b11111100; - remote_state[5] |= new_speed; + setBits(&remote_state[5], kLowNibble, kHaierAcSwingSize, new_speed); } uint8_t IRHaierAC::getFan(void) { - switch (remote_state[5] & 0b00000011) { - case 1: - return kHaierAcFanMed; - case 2: - return kHaierAcFanHigh; - case 3: - return kHaierAcFanLow; - default: - return kHaierAcFanAuto; + switch (GETBITS8(remote_state[5], kLowNibble, kHaierAcSwingSize)) { + case 1: return kHaierAcFanMed; + case 2: return kHaierAcFanHigh; + case 3: return kHaierAcFanLow; + default: return kHaierAcFanAuto; } } void IRHaierAC::setMode(uint8_t mode) { uint8_t new_mode = mode; setCommand(kHaierAcCmdMode); - if (mode > kHaierAcFan) // If out of range, default to auto mode. - new_mode = kHaierAcAuto; - remote_state[6] &= ~kHaierAcModeMask; - remote_state[6] |= (new_mode << 5); + // If out of range, default to auto mode. + if (mode > kHaierAcFan) new_mode = kHaierAcAuto; + setBits(&remote_state[6], kHaierAcModeOffset, kModeBitsSize, new_mode); } uint8_t IRHaierAC::getMode(void) { - return (remote_state[6] & kHaierAcModeMask) >> 5; + return GETBITS8(remote_state[6], kHaierAcModeOffset, kModeBitsSize); } -void IRHaierAC::setTemp(const uint8_t celsius) { - uint8_t temp = celsius; +void IRHaierAC::setTemp(const uint8_t degrees) { + uint8_t temp = degrees; if (temp < kHaierAcMinTemp) temp = kHaierAcMinTemp; else if (temp > kHaierAcMaxTemp) @@ -208,46 +198,47 @@ void IRHaierAC::setTemp(const uint8_t celsius) { setCommand(kHaierAcCmdTempDown); else setCommand(kHaierAcCmdTempUp); - - remote_state[1] &= 0b00001111; // Clear the previous temp. - remote_state[1] |= ((temp - kHaierAcMinTemp) << 4); + setBits(&remote_state[1], kHighNibble, kNibbleSize, temp - kHaierAcMinTemp); } uint8_t IRHaierAC::getTemp(void) { - return ((remote_state[1] & 0b11110000) >> 4) + kHaierAcMinTemp; + return GETBITS8(remote_state[1], kHighNibble, kNibbleSize) + kHaierAcMinTemp; } void IRHaierAC::setHealth(const bool on) { setCommand(kHaierAcCmdHealth); - remote_state[4] &= 0b11011111; - remote_state[4] |= (on << 5); + setBit(&remote_state[4], kHaierAcHealthBitOffset, on); } -bool IRHaierAC::getHealth(void) { return remote_state[4] & (1 << 5); } +bool IRHaierAC::getHealth(void) { + return GETBIT8(remote_state[4], kHaierAcHealthBitOffset); +} void IRHaierAC::setSleep(const bool on) { setCommand(kHaierAcCmdSleep); - if (on) - remote_state[7] |= kHaierAcSleepBit; - else - remote_state[7] &= ~kHaierAcSleepBit; + setBit(&remote_state[7], kHaierAcSleepBitOffset, on); } -bool IRHaierAC::getSleep(void) { return remote_state[7] & kHaierAcSleepBit; } +bool IRHaierAC::getSleep(void) { + return GETBIT8(remote_state[7], kHaierAcSleepBitOffset); +} uint16_t IRHaierAC::getTime(const uint8_t ptr[]) { - return (ptr[0] & 0b00011111) * 60 + (ptr[1] & 0b00111111); + return GETBITS8(ptr[0], kHaierAcTimeOffset, kHaierAcHoursSize) * 60 + + GETBITS8(ptr[1], kHaierAcTimeOffset, kHaierAcMinsSize); } int16_t IRHaierAC::getOnTimer(void) { - if (remote_state[3] & 0b10000000) // Check if the timer is turned on. + // Check if the timer is turned on. + if (GETBIT8(remote_state[3], kHaierAcOnTimerOffset)) return getTime(remote_state + 6); else return -1; } int16_t IRHaierAC::getOffTimer(void) { - if (remote_state[3] & 0b01000000) // Check if the timer is turned on. + // Check if the timer is turned on. + if (GETBIT8(remote_state[3], kHaierAcOffTimerOffset)) return getTime(remote_state + 4); else return -1; @@ -258,30 +249,25 @@ uint16_t IRHaierAC::getCurrTime(void) { return getTime(remote_state + 2); } void IRHaierAC::setTime(uint8_t ptr[], const uint16_t nr_mins) { uint16_t mins = nr_mins; if (nr_mins > kHaierAcMaxTime) mins = kHaierAcMaxTime; - - // Hours - ptr[0] &= 0b11100000; - ptr[0] |= (mins / 60); - // Minutes - ptr[1] &= 0b11000000; - ptr[1] |= (mins % 60); + setBits(ptr, kHaierAcTimeOffset, kHaierAcHoursSize, mins / 60); // Hours + setBits(ptr + 1, kHaierAcTimeOffset, kHaierAcMinsSize, mins % 60); // Minutes } void IRHaierAC::setOnTimer(const uint16_t nr_mins) { setCommand(kHaierAcCmdTimerSet); - remote_state[3] |= 0b10000000; + setBit(&remote_state[3], kHaierAcOnTimerOffset); setTime(remote_state + 6, nr_mins); } void IRHaierAC::setOffTimer(const uint16_t nr_mins) { setCommand(kHaierAcCmdTimerSet); - remote_state[3] |= 0b01000000; + setBit(&remote_state[3], kHaierAcOffTimerOffset); setTime(remote_state + 4, nr_mins); } void IRHaierAC::cancelTimers(void) { setCommand(kHaierAcCmdTimerCancel); - remote_state[3] &= 0b00111111; + setBits(&remote_state[3], kHaierAcOffTimerOffset, 2, 0); } void IRHaierAC::setCurrTime(const uint16_t nr_mins) { @@ -289,19 +275,18 @@ void IRHaierAC::setCurrTime(const uint16_t nr_mins) { } uint8_t IRHaierAC::getSwing(void) { - return (remote_state[2] & 0b11000000) >> 6; + return GETBITS8(remote_state[2], kHaierAcSwingOffset, kHaierAcSwingSize); } -void IRHaierAC::setSwing(const uint8_t state) { - if (state == getSwing()) return; // Nothing to do. - setCommand(kHaierAcCmdSwing); - switch (state) { +void IRHaierAC::setSwing(const uint8_t cmd) { + if (cmd == getSwing()) return; // Nothing to do. + switch (cmd) { case kHaierAcSwingOff: case kHaierAcSwingUp: case kHaierAcSwingDown: case kHaierAcSwingChg: - remote_state[2] &= 0b00111111; - remote_state[2] |= (state << 6); + setCommand(kHaierAcCmdSwing); + setBits(&remote_state[2], kHaierAcSwingOffset, kHaierAcSwingSize, cmd); break; } } @@ -309,16 +294,11 @@ void IRHaierAC::setSwing(const uint8_t state) { // Convert a standard A/C mode into its native mode. uint8_t IRHaierAC::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kHaierAcCool; - case stdAc::opmode_t::kHeat: - return kHaierAcHeat; - case stdAc::opmode_t::kDry: - return kHaierAcDry; - case stdAc::opmode_t::kFan: - return kHaierAcFan; - default: - return kHaierAcAuto; + case stdAc::opmode_t::kCool: return kHaierAcCool; + case stdAc::opmode_t::kHeat: return kHaierAcHeat; + case stdAc::opmode_t::kDry: return kHaierAcDry; + case stdAc::opmode_t::kFan: return kHaierAcFan; + default: return kHaierAcAuto; } } @@ -326,15 +306,11 @@ uint8_t IRHaierAC::convertMode(const stdAc::opmode_t mode) { uint8_t IRHaierAC::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kHaierAcFanLow; - case stdAc::fanspeed_t::kMedium: - return kHaierAcFanMed; + case stdAc::fanspeed_t::kLow: return kHaierAcFanLow; + case stdAc::fanspeed_t::kMedium: return kHaierAcFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kHaierAcFanHigh; - default: - return kHaierAcFanAuto; + case stdAc::fanspeed_t::kMax: return kHaierAcFanHigh; + default: return kHaierAcFanAuto; } } @@ -343,15 +319,11 @@ uint8_t IRHaierAC::convertSwingV(const stdAc::swingv_t position) { switch (position) { case stdAc::swingv_t::kHighest: case stdAc::swingv_t::kHigh: - case stdAc::swingv_t::kMiddle: - return kHaierAcSwingUp; + case stdAc::swingv_t::kMiddle: return kHaierAcSwingUp; case stdAc::swingv_t::kLow: - case stdAc::swingv_t::kLowest: - return kHaierAcSwingDown; - case stdAc::swingv_t::kOff: - return kHaierAcSwingOff; - default: - return kHaierAcSwingChg; + case stdAc::swingv_t::kLowest: return kHaierAcSwingDown; + case stdAc::swingv_t::kOff: return kHaierAcSwingOff; + default: return kHaierAcSwingChg; } } @@ -360,9 +332,9 @@ stdAc::opmode_t IRHaierAC::toCommonMode(const uint8_t mode) { switch (mode) { case kHaierAcCool: return stdAc::opmode_t::kCool; case kHaierAcHeat: return stdAc::opmode_t::kHeat; - case kHaierAcDry: return stdAc::opmode_t::kDry; - case kHaierAcFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kHaierAcDry: return stdAc::opmode_t::kDry; + case kHaierAcFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -370,19 +342,19 @@ stdAc::opmode_t IRHaierAC::toCommonMode(const uint8_t mode) { stdAc::fanspeed_t IRHaierAC::toCommonFanSpeed(const uint8_t speed) { switch (speed) { case kHaierAcFanHigh: return stdAc::fanspeed_t::kMax; - case kHaierAcFanMed: return stdAc::fanspeed_t::kMedium; - case kHaierAcFanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kHaierAcFanMed: return stdAc::fanspeed_t::kMedium; + case kHaierAcFanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } // Convert a native vertical swing to it's common equivalent. stdAc::swingv_t IRHaierAC::toCommonSwingV(const uint8_t pos) { switch (pos) { - case kHaierAcSwingUp: return stdAc::swingv_t::kHighest; + case kHaierAcSwingUp: return stdAc::swingv_t::kHighest; case kHaierAcSwingDown: return stdAc::swingv_t::kLowest; - case kHaierAcSwingOff: return stdAc::swingv_t::kOff; - default: return stdAc::swingv_t::kAuto; + case kHaierAcSwingOff: return stdAc::swingv_t::kOff; + default: return stdAc::swingv_t::kAuto; } } @@ -417,44 +389,44 @@ String IRHaierAC::toString(void) { String result = ""; result.reserve(150); // Reserve some heap for the string to reduce fragging. uint8_t cmd = getCommand(); - result += addIntToString(cmd, F("Command"), false); - result += F(" ("); + result += addIntToString(cmd, kCommandStr, false); + result += kSpaceLBraceStr; switch (cmd) { case kHaierAcCmdOff: - result += F("Off"); + result += kOffStr; break; case kHaierAcCmdOn: - result += F("On"); + result += kOnStr; break; case kHaierAcCmdMode: - result += F("Mode"); + result += kModeStr; break; case kHaierAcCmdFan: - result += F("Fan"); + result += kFanStr; break; case kHaierAcCmdTempUp: - result += F("Temp Up"); + result += kTempUpStr; break; case kHaierAcCmdTempDown: - result += F("Temp Down"); + result += kTempDownStr; break; case kHaierAcCmdSleep: - result += F("Sleep"); + result += kSleepStr; break; case kHaierAcCmdTimerSet: - result += F("Timer Set"); + result += kTimerStr + ' ' + kSetStr; break; case kHaierAcCmdTimerCancel: - result += F("Timer Cancel"); + result += kTimerStr + ' ' + kCancelStr; break; case kHaierAcCmdHealth: - result += F("Health"); + result += kHealthStr; break; case kHaierAcCmdSwing: - result += F("Swing"); + result += kSwingStr; break; default: - result += F("Unknown"); + result += kUnknownStr; } result += ')'; result += addModeToString(getMode(), kHaierAcAuto, kHaierAcCool, kHaierAcHeat, @@ -462,33 +434,33 @@ String IRHaierAC::toString(void) { result += addTempToString(getTemp()); result += addFanToString(getFan(), kHaierAcFanHigh, kHaierAcFanLow, kHaierAcFanAuto, kHaierAcFanAuto, kHaierAcFanMed); - result += addIntToString(getSwing(), F("Swing")); - result += F(" ("); + result += addIntToString(getSwing(), kSwingStr); + result += kSpaceLBraceStr; switch (getSwing()) { case kHaierAcSwingOff: - result += F("Off"); + result += kOffStr; break; case kHaierAcSwingUp: - result += F("Up"); + result += kUpStr; break; case kHaierAcSwingDown: - result += F("Down"); + result += kDownStr; break; case kHaierAcSwingChg: - result += F("Chg"); + result += kChangeStr; break; default: - result += F("Unknown"); + result += kUnknownStr; } result += ')'; - result += addBoolToString(getSleep(), F("Sleep")); - result += addBoolToString(getHealth(), F("Health")); - result += addLabeledString(minsToString(getCurrTime()), F("Current Time")); + result += addBoolToString(getSleep(), kSleepStr); + result += addBoolToString(getHealth(), kHealthStr); + result += addLabeledString(minsToString(getCurrTime()), kClockStr); result += addLabeledString( - getOnTimer() >= 0 ? minsToString(getOnTimer()) : F("Off"), F("On Timer")); + getOnTimer() >= 0 ? minsToString(getOnTimer()) : kOffStr, kOnTimerStr); result += addLabeledString( - getOffTimer() >= 0 ? minsToString(getOffTimer()) : F("Off"), - F("Off Timer")); + getOffTimer() >= 0 ? minsToString(getOffTimer()) : kOffStr, + kOffTimerStr); return result; } // End of IRHaierAC class. @@ -502,8 +474,7 @@ void IRHaierACYRW02::begin(void) { _irsend.begin(); } #if SEND_HAIER_AC_YRW02 void IRHaierACYRW02::send(const uint16_t repeat) { - checksum(); - _irsend.sendHaierACYRW02(remote_state, kHaierACYRW02StateLength, repeat); + _irsend.sendHaierACYRW02(getRaw(), kHaierACYRW02StateLength, repeat); } #endif // SEND_HAIER_AC_YRW02 @@ -537,9 +508,7 @@ uint8_t* IRHaierACYRW02::getRaw(void) { } void IRHaierACYRW02::setRaw(const uint8_t new_code[]) { - for (uint8_t i = 0; i < kHaierACYRW02StateLength; i++) { - remote_state[i] = new_code[i]; - } + memcpy(remote_state, new_code, kHaierACYRW02StateLength); } void IRHaierACYRW02::setButton(uint8_t button) { @@ -553,13 +522,12 @@ void IRHaierACYRW02::setButton(uint8_t button) { case kHaierAcYrw02ButtonHealth: case kHaierAcYrw02ButtonTurbo: case kHaierAcYrw02ButtonSleep: - remote_state[12] &= 0b11110000; - remote_state[12] |= (button & 0b00001111); + setBits(&remote_state[12], kLowNibble, kNibbleSize, button); } } uint8_t IRHaierACYRW02::getButton(void) { - return remote_state[12] & 0b00001111; + return GETBITS8(remote_state[12], kLowNibble, kNibbleSize); } void IRHaierACYRW02::setMode(uint8_t mode) { @@ -570,16 +538,15 @@ void IRHaierACYRW02::setMode(uint8_t mode) { case kHaierAcYrw02Cool: case kHaierAcYrw02Dry: case kHaierAcYrw02Heat: - case kHaierAcYrw02Fan: - break; - default: // If unexpected, default to auto mode. - new_mode = kHaierAcYrw02Auto; + case kHaierAcYrw02Fan: break; + default: new_mode = kHaierAcYrw02Auto; // Unexpected, default to auto mode. } - remote_state[7] &= 0b0001111; - remote_state[7] |= (new_mode << 4); + setBits(&remote_state[7], kHaierAcYrw02ModeOffset, kModeBitsSize, new_mode); } -uint8_t IRHaierACYRW02::getMode(void) { return remote_state[7] >> 4; } +uint8_t IRHaierACYRW02::getMode(void) { + return GETBITS8(remote_state[7], kHaierAcYrw02ModeOffset, kModeBitsSize); +} void IRHaierACYRW02::setTemp(const uint8_t celsius) { uint8_t temp = celsius; @@ -594,33 +561,29 @@ void IRHaierACYRW02::setTemp(const uint8_t celsius) { setButton(kHaierAcYrw02ButtonTempDown); else setButton(kHaierAcYrw02ButtonTempUp); - - remote_state[1] &= 0b00001111; // Clear the previous temp. - remote_state[1] |= ((temp - kHaierAcMinTemp) << 4); + setBits(&remote_state[1], kHighNibble, kNibbleSize, temp - kHaierAcMinTemp); } uint8_t IRHaierACYRW02::getTemp(void) { - return ((remote_state[1] & 0b11110000) >> 4) + kHaierAcMinTemp; + return GETBITS8(remote_state[1], kHighNibble, kNibbleSize) + kHaierAcMinTemp; } void IRHaierACYRW02::setHealth(const bool on) { setButton(kHaierAcYrw02ButtonHealth); - remote_state[3] &= 0b11111101; - remote_state[3] |= (on << 1); + setBit(&remote_state[3], kHaierAcYrw02HealthOffset, on); } -bool IRHaierACYRW02::getHealth(void) { return remote_state[3] & 0b00000010; } +bool IRHaierACYRW02::getHealth(void) { + return GETBIT8(remote_state[3], kHaierAcYrw02HealthOffset); +} bool IRHaierACYRW02::getPower(void) { - return remote_state[4] & kHaierAcYrw02Power; + return GETBIT8(remote_state[4], kHaierAcYrw02PowerOffset); } void IRHaierACYRW02::setPower(const bool on) { setButton(kHaierAcYrw02ButtonPower); - if (on) - remote_state[4] |= kHaierAcYrw02Power; - else - remote_state[4] &= ~kHaierAcYrw02Power; + setBit(&remote_state[4], kHaierAcYrw02PowerOffset, on); } void IRHaierACYRW02::on(void) { setPower(true); } @@ -628,31 +591,34 @@ void IRHaierACYRW02::on(void) { setPower(true); } void IRHaierACYRW02::off(void) { setPower(false); } bool IRHaierACYRW02::getSleep(void) { - return remote_state[8] & kHaierAcYrw02Sleep; + return GETBIT8(remote_state[8], kHaierAcYrw02SleepOffset); } void IRHaierACYRW02::setSleep(const bool on) { setButton(kHaierAcYrw02ButtonSleep); - if (on) - remote_state[8] |= kHaierAcYrw02Sleep; - else - remote_state[8] &= ~kHaierAcYrw02Sleep; + setBit(&remote_state[8], kHaierAcYrw02SleepOffset, on); } -uint8_t IRHaierACYRW02::getTurbo(void) { return remote_state[6] >> 6; } +uint8_t IRHaierACYRW02::getTurbo(void) { + return GETBITS8(remote_state[6], kHaierAcYrw02TurboOffset, + kHaierAcYrw02TurboSize); +} void IRHaierACYRW02::setTurbo(uint8_t speed) { switch (speed) { case kHaierAcYrw02TurboOff: case kHaierAcYrw02TurboLow: case kHaierAcYrw02TurboHigh: - remote_state[6] &= 0b00111111; - remote_state[6] |= (speed << 6); + setBits(&remote_state[6], kHaierAcYrw02TurboOffset, + kHaierAcYrw02TurboSize, speed); setButton(kHaierAcYrw02ButtonTurbo); } } -uint8_t IRHaierACYRW02::getFan(void) { return remote_state[5] >> 4; } +uint8_t IRHaierACYRW02::getFan(void) { + return GETBITS8(remote_state[5], kHaierAcYrw02FanOffset, + kHaierAcYrw02FanSize); +} void IRHaierACYRW02::setFan(uint8_t speed) { switch (speed) { @@ -660,54 +626,44 @@ void IRHaierACYRW02::setFan(uint8_t speed) { case kHaierAcYrw02FanMed: case kHaierAcYrw02FanHigh: case kHaierAcYrw02FanAuto: - remote_state[5] &= 0b00001111; - remote_state[5] |= (speed << 4); + setBits(&remote_state[5], kHaierAcYrw02FanOffset, kHaierAcYrw02FanSize, + speed); setButton(kHaierAcYrw02ButtonFan); } } -uint8_t IRHaierACYRW02::getSwing(void) { return remote_state[1] & 0b00001111; } +uint8_t IRHaierACYRW02::getSwing(void) { + return GETBITS8(remote_state[1], kLowNibble, kNibbleSize); +} -void IRHaierACYRW02::setSwing(uint8_t state) { - uint8_t newstate = state; - switch (state) { +void IRHaierACYRW02::setSwing(uint8_t pos) { + uint8_t newpos = pos; + switch (pos) { case kHaierAcYrw02SwingOff: case kHaierAcYrw02SwingAuto: case kHaierAcYrw02SwingTop: case kHaierAcYrw02SwingMiddle: case kHaierAcYrw02SwingBottom: - case kHaierAcYrw02SwingDown: - setButton(kHaierAcYrw02ButtonSwing); - break; - default: - return; // Unexpected value so don't do anything. + case kHaierAcYrw02SwingDown: setButton(kHaierAcYrw02ButtonSwing); break; + default: return; // Unexpected value so don't do anything. } - // Heat mode has no MIDDLE setting, use BOTTOM instead. - if (state == kHaierAcYrw02SwingMiddle && getMode() == kHaierAcYrw02Heat) - newstate = kHaierAcYrw02SwingBottom; - + if (pos == kHaierAcYrw02SwingMiddle && getMode() == kHaierAcYrw02Heat) + newpos = kHaierAcYrw02SwingBottom; // BOTTOM is only allowed if we are in Heat mode, otherwise MIDDLE. - if (state == kHaierAcYrw02SwingBottom && getMode() != kHaierAcYrw02Heat) - newstate = kHaierAcYrw02SwingMiddle; - - remote_state[1] &= 0b11110000; - remote_state[1] |= newstate; + if (pos == kHaierAcYrw02SwingBottom && getMode() != kHaierAcYrw02Heat) + newpos = kHaierAcYrw02SwingMiddle; + setBits(&remote_state[1], kLowNibble, kNibbleSize, newpos); } // Convert a standard A/C mode into its native mode. uint8_t IRHaierACYRW02::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kHaierAcYrw02Cool; - case stdAc::opmode_t::kHeat: - return kHaierAcYrw02Heat; - case stdAc::opmode_t::kDry: - return kHaierAcYrw02Dry; - case stdAc::opmode_t::kFan: - return kHaierAcYrw02Fan; - default: - return kHaierAcYrw02Auto; + case stdAc::opmode_t::kCool: return kHaierAcYrw02Cool; + case stdAc::opmode_t::kHeat: return kHaierAcYrw02Heat; + case stdAc::opmode_t::kDry: return kHaierAcYrw02Dry; + case stdAc::opmode_t::kFan: return kHaierAcYrw02Fan; + default: return kHaierAcYrw02Auto; } } @@ -715,15 +671,11 @@ uint8_t IRHaierACYRW02::convertMode(const stdAc::opmode_t mode) { uint8_t IRHaierACYRW02::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kHaierAcYrw02FanLow; - case stdAc::fanspeed_t::kMedium: - return kHaierAcYrw02FanMed; + case stdAc::fanspeed_t::kLow: return kHaierAcYrw02FanLow; + case stdAc::fanspeed_t::kMedium: return kHaierAcYrw02FanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kHaierAcYrw02FanHigh; - default: - return kHaierAcYrw02FanAuto; + case stdAc::fanspeed_t::kMax: return kHaierAcYrw02FanHigh; + default: return kHaierAcYrw02FanAuto; } } @@ -731,18 +683,12 @@ uint8_t IRHaierACYRW02::convertFan(const stdAc::fanspeed_t speed) { uint8_t IRHaierACYRW02::convertSwingV(const stdAc::swingv_t position) { switch (position) { case stdAc::swingv_t::kHighest: - case stdAc::swingv_t::kHigh: - return kHaierAcYrw02SwingTop; - case stdAc::swingv_t::kMiddle: - return kHaierAcYrw02SwingMiddle; - case stdAc::swingv_t::kLow: - return kHaierAcYrw02SwingDown; - case stdAc::swingv_t::kLowest: - return kHaierAcYrw02SwingBottom; - case stdAc::swingv_t::kOff: - return kHaierAcYrw02SwingOff; - default: - return kHaierAcYrw02SwingAuto; + case stdAc::swingv_t::kHigh: return kHaierAcYrw02SwingTop; + case stdAc::swingv_t::kMiddle: return kHaierAcYrw02SwingMiddle; + case stdAc::swingv_t::kLow: return kHaierAcYrw02SwingDown; + case stdAc::swingv_t::kLowest: return kHaierAcYrw02SwingBottom; + case stdAc::swingv_t::kOff: return kHaierAcYrw02SwingOff; + default: return kHaierAcYrw02SwingAuto; } } @@ -751,9 +697,9 @@ stdAc::opmode_t IRHaierACYRW02::toCommonMode(const uint8_t mode) { switch (mode) { case kHaierAcYrw02Cool: return stdAc::opmode_t::kCool; case kHaierAcYrw02Heat: return stdAc::opmode_t::kHeat; - case kHaierAcYrw02Dry: return stdAc::opmode_t::kDry; - case kHaierAcYrw02Fan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kHaierAcYrw02Dry: return stdAc::opmode_t::kDry; + case kHaierAcYrw02Fan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -761,21 +707,21 @@ stdAc::opmode_t IRHaierACYRW02::toCommonMode(const uint8_t mode) { stdAc::fanspeed_t IRHaierACYRW02::toCommonFanSpeed(const uint8_t speed) { switch (speed) { case kHaierAcYrw02FanHigh: return stdAc::fanspeed_t::kMax; - case kHaierAcYrw02FanMed: return stdAc::fanspeed_t::kMedium; - case kHaierAcYrw02FanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kHaierAcYrw02FanMed: return stdAc::fanspeed_t::kMedium; + case kHaierAcYrw02FanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } // Convert a native vertical swing to it's common equivalent. stdAc::swingv_t IRHaierACYRW02::toCommonSwingV(const uint8_t pos) { switch (pos) { - case kHaierAcYrw02SwingTop: return stdAc::swingv_t::kHighest; + case kHaierAcYrw02SwingTop: return stdAc::swingv_t::kHighest; case kHaierAcYrw02SwingMiddle: return stdAc::swingv_t::kMiddle; - case kHaierAcYrw02SwingDown: return stdAc::swingv_t::kLow; + case kHaierAcYrw02SwingDown: return stdAc::swingv_t::kLow; case kHaierAcYrw02SwingBottom: return stdAc::swingv_t::kLowest; - case kHaierAcYrw02SwingOff: return stdAc::swingv_t::kOff; - default: return stdAc::swingv_t::kAuto; + case kHaierAcYrw02SwingOff: return stdAc::swingv_t::kOff; + default: return stdAc::swingv_t::kAuto; } } @@ -808,40 +754,40 @@ stdAc::state_t IRHaierACYRW02::toCommon(void) { String IRHaierACYRW02::toString(void) { String result = ""; result.reserve(130); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); uint8_t cmd = getButton(); - result += addIntToString(cmd, F("Button")); - result += F(" ("); + result += addIntToString(cmd, kButtonStr); + result += kSpaceLBraceStr; switch (cmd) { case kHaierAcYrw02ButtonPower: - result += F("Power"); + result += kPowerStr; break; case kHaierAcYrw02ButtonMode: - result += F("Mode"); + result += kModeStr; break; case kHaierAcYrw02ButtonFan: - result += F("Fan"); + result += kFanStr; break; case kHaierAcYrw02ButtonTempUp: - result += F("Temp Up"); + result += kTempUpStr; break; case kHaierAcYrw02ButtonTempDown: - result += F("Temp Down"); + result += kTempDownStr; break; case kHaierAcYrw02ButtonSleep: - result += F("Sleep"); + result += kSleepStr; break; case kHaierAcYrw02ButtonHealth: - result += "Health"; + result += kHealthStr; break; case kHaierAcYrw02ButtonSwing: - result += F("Swing"); + result += kSwingStr; break; case kHaierAcYrw02ButtonTurbo: - result += F("Turbo"); + result += kTurboStr; break; default: - result += F("Unknown"); + result += kUnknownStr; } result += ')'; result += addModeToString(getMode(), kHaierAcYrw02Auto, kHaierAcYrw02Cool, @@ -851,49 +797,49 @@ String IRHaierACYRW02::toString(void) { result += addFanToString(getFan(), kHaierAcYrw02FanHigh, kHaierAcYrw02FanLow, kHaierAcYrw02FanAuto, kHaierAcYrw02FanAuto, kHaierAcYrw02FanMed); - result += addIntToString(getTurbo(), F("Turbo")); - result += F(" ("); + result += addIntToString(getTurbo(), kTurboStr); + result += kSpaceLBraceStr; switch (getTurbo()) { case kHaierAcYrw02TurboOff: - result += F("Off"); + result += kOffStr; break; case kHaierAcYrw02TurboLow: - result += F("Low"); + result += kLowStr; break; case kHaierAcYrw02TurboHigh: - result += F("High"); + result += kHighStr; break; default: - result += F("Unknown"); + result += kUnknownStr; } result += ')'; - result += addIntToString(getSwing(), F("Swing")); - result += F(" ("); + result += addIntToString(getSwing(), kSwingStr); + result += kSpaceLBraceStr; switch (getSwing()) { case kHaierAcYrw02SwingOff: - result += F("Off"); + result += kOffStr; break; case kHaierAcYrw02SwingAuto: - result += F("Auto"); + result += kAutoStr; break; case kHaierAcYrw02SwingBottom: - result += F("Bottom"); + result += kLowestStr; break; case kHaierAcYrw02SwingDown: - result += F("Down"); + result += kLowStr; break; case kHaierAcYrw02SwingTop: - result += F("Top"); + result += kHighestStr; break; case kHaierAcYrw02SwingMiddle: - result += F("Middle"); + result += kMiddleStr; break; default: - result += F("Unknown"); + result += kUnknownStr; } result += ')'; - result += addBoolToString(getSleep(), F("Sleep")); - result += addBoolToString(getHealth(), F("Health")); + result += addBoolToString(getSleep(), kSleepStr); + result += addBoolToString(getHealth(), kHealthStr); return result; } // End of IRHaierACYRW02 class. diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Haier.h b/lib/IRremoteESP8266-2.7.0/src/ir_Haier.h old mode 100755 new mode 100644 similarity index 80% rename from lib/IRremoteESP8266-2.6.5/src/ir_Haier.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Haier.h index ea5f67ab3..587c4c560 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Haier.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Haier.h @@ -34,26 +34,37 @@ const uint8_t kHaierAcPrefix = 0b10100101; const uint8_t kHaierAcMinTemp = 16; const uint8_t kHaierAcDefTemp = 25; const uint8_t kHaierAcMaxTemp = 30; -const uint8_t kHaierAcCmdOff = 0b00000000; -const uint8_t kHaierAcCmdOn = 0b00000001; -const uint8_t kHaierAcCmdMode = 0b00000010; -const uint8_t kHaierAcCmdFan = 0b00000011; -const uint8_t kHaierAcCmdTempUp = 0b00000110; -const uint8_t kHaierAcCmdTempDown = 0b00000111; -const uint8_t kHaierAcCmdSleep = 0b00001000; -const uint8_t kHaierAcCmdTimerSet = 0b00001001; -const uint8_t kHaierAcCmdTimerCancel = 0b00001010; -const uint8_t kHaierAcCmdHealth = 0b00001100; -const uint8_t kHaierAcCmdSwing = 0b00001101; +const uint8_t kHaierAcCmdOff = 0b0000; +const uint8_t kHaierAcCmdOn = 0b0001; +const uint8_t kHaierAcCmdMode = 0b0010; +const uint8_t kHaierAcCmdFan = 0b0011; +const uint8_t kHaierAcCmdTempUp = 0b0110; +const uint8_t kHaierAcCmdTempDown = 0b0111; +const uint8_t kHaierAcCmdSleep = 0b1000; +const uint8_t kHaierAcCmdTimerSet = 0b1001; +const uint8_t kHaierAcCmdTimerCancel = 0b1010; +const uint8_t kHaierAcCmdHealth = 0b1100; +const uint8_t kHaierAcCmdSwing = 0b1101; -// Byte 2 -const uint8_t kHaierAcSwingOff = 0b00000000; -const uint8_t kHaierAcSwingUp = 0b00000001; -const uint8_t kHaierAcSwingDown = 0b00000010; -const uint8_t kHaierAcSwingChg = 0b00000011; +// Byte 2 (Clock Hours) -// Byte 6 -const uint8_t kHaierAcModeMask = 0b11100000; +// Byte 3 (Timer Flags & Clock Minutes) +const uint8_t kHaierAcOffTimerOffset = 6; +const uint8_t kHaierAcOnTimerOffset = 7; + +// Byte 4 (Health & Off Time Hours) +const uint8_t kHaierAcHealthBitOffset = 5; + +// Byte 5 (Swing & Off Time Mins) +const uint8_t kHaierAcSwingOffset = 6; +const uint8_t kHaierAcSwingSize = 2; // Bits +const uint8_t kHaierAcSwingOff = 0b00; +const uint8_t kHaierAcSwingUp = 0b01; +const uint8_t kHaierAcSwingDown = 0b10; +const uint8_t kHaierAcSwingChg = 0b11; + +// Byte 6 (Mode & On Time Hours) +const uint8_t kHaierAcModeOffset = 5; const uint8_t kHaierAcAuto = 0; const uint8_t kHaierAcCool = 1; const uint8_t kHaierAcDry = 2; @@ -65,9 +76,17 @@ const uint8_t kHaierAcFanLow = 1; const uint8_t kHaierAcFanMed = 2; const uint8_t kHaierAcFanHigh = 3; +// Byte 7 (On Time Minutes) + +// Time +const uint8_t kHaierAcTimeOffset = 0; // Bits +const uint8_t kHaierAcHoursSize = 5; // Bits +const uint8_t kHaierAcMinsSize = 6; // Bits + const uint16_t kHaierAcMaxTime = (23 * 60) + 59; // Byte 7 +const uint8_t kHaierAcSleepBitOffset = 6; const uint8_t kHaierAcSleepBit = 0b01000000; // Legacy Haier AC defines. @@ -104,9 +123,9 @@ const uint8_t kHaierAcSleepBit = 0b01000000; const uint8_t kHaierAcYrw02Prefix = 0xA6; // Byte 1 -// Bits 0-3 +// High Nibble - Temperature // 0x0 = 16DegC, ... 0xE = 30DegC -// Bits 4-7 - Swing +// Low Nibble - Swing const uint8_t kHaierAcYrw02SwingOff = 0x0; const uint8_t kHaierAcYrw02SwingTop = 0x1; const uint8_t kHaierAcYrw02SwingMiddle = 0x2; // Not available in heat mode. @@ -115,33 +134,39 @@ const uint8_t kHaierAcYrw02SwingDown = 0xA; const uint8_t kHaierAcYrw02SwingAuto = 0xC; // Airflow // Byte 3 -// Bit 7 - Health mode +const uint8_t kHaierAcYrw02HealthOffset = 1; // Byte 4 +const uint8_t kHaierAcYrw02PowerOffset = 6; const uint8_t kHaierAcYrw02Power = 0b01000000; // Byte 5 // Bits 0-3 -const uint8_t kHaierAcYrw02FanHigh = 0x2; -const uint8_t kHaierAcYrw02FanMed = 0x4; -const uint8_t kHaierAcYrw02FanLow = 0x6; -const uint8_t kHaierAcYrw02FanAuto = 0xA; +const uint8_t kHaierAcYrw02FanOffset = 5; +const uint8_t kHaierAcYrw02FanSize = 3; +const uint8_t kHaierAcYrw02FanHigh = 0b001; +const uint8_t kHaierAcYrw02FanMed = 0b010; +const uint8_t kHaierAcYrw02FanLow = 0b011; +const uint8_t kHaierAcYrw02FanAuto = 0b101; // Byte 6 -// Bits 0-1 +const uint8_t kHaierAcYrw02TurboOffset = 6; +const uint8_t kHaierAcYrw02TurboSize = 2; const uint8_t kHaierAcYrw02TurboOff = 0x0; const uint8_t kHaierAcYrw02TurboHigh = 0x1; const uint8_t kHaierAcYrw02TurboLow = 0x2; // Byte 7 -// Bits 0-3 -const uint8_t kHaierAcYrw02Auto = 0x0; -const uint8_t kHaierAcYrw02Cool = 0x2; -const uint8_t kHaierAcYrw02Dry = 0x4; -const uint8_t kHaierAcYrw02Heat = 0x8; -const uint8_t kHaierAcYrw02Fan = 0xC; +// Mode mask 0b11100000 +const uint8_t kHaierAcYrw02ModeOffset = 5; +const uint8_t kHaierAcYrw02Auto = 0b000; // 0 +const uint8_t kHaierAcYrw02Cool = 0b001; // 1 +const uint8_t kHaierAcYrw02Dry = 0b010; // 2 +const uint8_t kHaierAcYrw02Heat = 0b100; // 4 +const uint8_t kHaierAcYrw02Fan = 0b110; // 5 // Byte 8 +const uint8_t kHaierAcYrw02SleepOffset = 7; const uint8_t kHaierAcYrw02Sleep = 0b10000000; // Byte 12 diff --git a/lib/IRremoteESP8266-2.7.0/src/ir_Hitachi.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Hitachi.cpp new file mode 100644 index 000000000..6fe776362 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Hitachi.cpp @@ -0,0 +1,753 @@ +// Copyright 2018-2019 David Conran +// +// Code to emulate Hitachi protocol compatible devices. +// Should be compatible with: +// * Hitachi RAS-35THA6 remote +// + +#include "ir_Hitachi.h" +#include +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRtext.h" +#include "IRutils.h" + +// Constants +// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/417 +const uint16_t kHitachiAcHdrMark = 3300; +const uint16_t kHitachiAcHdrSpace = 1700; +const uint16_t kHitachiAc1HdrMark = 3400; +const uint16_t kHitachiAc1HdrSpace = 3400; +const uint16_t kHitachiAcBitMark = 400; +const uint16_t kHitachiAcOneSpace = 1250; +const uint16_t kHitachiAcZeroSpace = 500; +const uint32_t kHitachiAcMinGap = kDefaultMessageGap; // Just a guess. +// Support for HitachiAc424 protocol +// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/973 +const uint16_t kHitachiAc424LdrMark = 29784; // Leader +const uint16_t kHitachiAc424LdrSpace = 49290; // Leader +const uint16_t kHitachiAc424HdrMark = 3416; // Header +const uint16_t kHitachiAc424HdrSpace = 1604; // Header +const uint16_t kHitachiAc424BitMark = 463; +const uint16_t kHitachiAc424OneSpace = 1208; +const uint16_t kHitachiAc424ZeroSpace = 372; + +using irutils::addBoolToString; +using irutils::addIntToString; +using irutils::addLabeledString; +using irutils::addModeToString; +using irutils::addFanToString; +using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; + +#if (SEND_HITACHI_AC || SEND_HITACHI_AC2) +// Send a Hitachi A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHitachiAcStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/417 +void IRsend::sendHitachiAC(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kHitachiAcStateLength) + return; // Not enough bytes to send a proper message. + sendGeneric(kHitachiAcHdrMark, kHitachiAcHdrSpace, kHitachiAcBitMark, + kHitachiAcOneSpace, kHitachiAcBitMark, kHitachiAcZeroSpace, + kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, 38, true, + repeat, 50); +} +#endif // (SEND_HITACHI_AC || SEND_HITACHI_AC2) + +#if SEND_HITACHI_AC1 +// Send a Hitachi A/C 13-byte message. +// +// For devices: +// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHitachiAc1StateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: BETA / Appears to work. +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/453 +// Basically the same as sendHitatchiAC() except different size and header. +void IRsend::sendHitachiAC1(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kHitachiAc1StateLength) + return; // Not enough bytes to send a proper message. + sendGeneric(kHitachiAc1HdrMark, kHitachiAc1HdrSpace, kHitachiAcBitMark, + kHitachiAcOneSpace, kHitachiAcBitMark, kHitachiAcZeroSpace, + kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, kHitachiAcFreq, + true, repeat, kDutyDefault); +} +#endif // SEND_HITACHI_AC1 + +#if SEND_HITACHI_AC2 +// Send a Hitachi A/C 53-byte message. +// +// For devices: +// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHitachiAc2StateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: BETA / Appears to work. +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/417 +// Basically the same as sendHitatchiAC() except different size. +void IRsend::sendHitachiAC2(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kHitachiAc2StateLength) + return; // Not enough bytes to send a proper message. + sendHitachiAC(data, nbytes, repeat); +} +#endif // SEND_HITACHI_AC2 + +// Class for handling the remote control on a Hitachi 28 byte A/C message. +// Inspired by: +// https://github.com/ToniA/arduino-heatpumpir/blob/master/HitachiHeatpumpIR.cpp + +IRHitachiAc::IRHitachiAc(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { stateReset(); } + +void IRHitachiAc::stateReset(void) { + remote_state[0] = 0x80; + remote_state[1] = 0x08; + remote_state[2] = 0x0C; + remote_state[3] = 0x02; + remote_state[4] = 0xFD; + remote_state[5] = 0x80; + remote_state[6] = 0x7F; + remote_state[7] = 0x88; + remote_state[8] = 0x48; + remote_state[9] = 0x10; + for (uint8_t i = 10; i < kHitachiAcStateLength; i++) remote_state[i] = 0x00; + remote_state[14] = 0x60; + remote_state[15] = 0x60; + remote_state[24] = 0x80; + setTemp(23); +} + +void IRHitachiAc::begin(void) { _irsend.begin(); } + +uint8_t IRHitachiAc::calcChecksum(const uint8_t state[], + const uint16_t length) { + uint8_t sum = 62; + for (uint16_t i = 0; i < length - 1; i++) sum -= reverseBits(state[i], 8); + return reverseBits(sum, 8); +} + +void IRHitachiAc::checksum(const uint16_t length) { + remote_state[length - 1] = calcChecksum(remote_state, length); +} + +bool IRHitachiAc::validChecksum(const uint8_t state[], const uint16_t length) { + if (length < 2) return true; // Assume true for lengths that are too short. + return (state[length - 1] == calcChecksum(state, length)); +} + +uint8_t *IRHitachiAc::getRaw(void) { + checksum(); + return remote_state; +} + +void IRHitachiAc::setRaw(const uint8_t new_code[], const uint16_t length) { + memcpy(remote_state, new_code, std::min(length, kHitachiAcStateLength)); +} + +#if SEND_HITACHI_AC +void IRHitachiAc::send(const uint16_t repeat) { + _irsend.sendHitachiAC(getRaw(), kHitachiAcStateLength, repeat); +} +#endif // SEND_HITACHI_AC + +bool IRHitachiAc::getPower(void) { + return GETBIT8(remote_state[17], kHitachiAcPowerOffset); +} + +void IRHitachiAc::setPower(const bool on) { + setBit(&remote_state[17], kHitachiAcPowerOffset, on); +} + +void IRHitachiAc::on(void) { setPower(true); } + +void IRHitachiAc::off(void) { setPower(false); } + +uint8_t IRHitachiAc::getMode(void) { return reverseBits(remote_state[10], 8); } + +void IRHitachiAc::setMode(const uint8_t mode) { + uint8_t newmode = mode; + switch (mode) { + // Fan mode sets a special temp. + case kHitachiAcFan: setTemp(64); break; + case kHitachiAcAuto: + case kHitachiAcHeat: + case kHitachiAcCool: + case kHitachiAcDry: break; + default: newmode = kHitachiAcAuto; + } + remote_state[10] = reverseBits(newmode, 8); + if (mode != kHitachiAcFan) setTemp(_previoustemp); + setFan(getFan()); // Reset the fan speed after the mode change. +} + +uint8_t IRHitachiAc::getTemp(void) { + return reverseBits(remote_state[11], 8) >> 1; +} + +void IRHitachiAc::setTemp(const uint8_t celsius) { + uint8_t temp; + if (celsius != 64) _previoustemp = celsius; + switch (celsius) { + case 64: + temp = celsius; + break; + default: + temp = std::min(celsius, kHitachiAcMaxTemp); + temp = std::max(temp, kHitachiAcMinTemp); + } + remote_state[11] = reverseBits(temp << 1, 8); + if (temp == kHitachiAcMinTemp) + remote_state[9] = 0x90; + else + remote_state[9] = 0x10; +} + +uint8_t IRHitachiAc::getFan(void) { return reverseBits(remote_state[13], 8); } + +void IRHitachiAc::setFan(const uint8_t speed) { + uint8_t fanmin = kHitachiAcFanAuto; + uint8_t fanmax = kHitachiAcFanHigh; + switch (getMode()) { + case kHitachiAcDry: // Only 2 x low speeds in Dry mode. + fanmin = kHitachiAcFanLow; + fanmax = kHitachiAcFanLow + 1; + break; + case kHitachiAcFan: + fanmin = kHitachiAcFanLow; // No Auto in Fan mode. + break; + } + uint8_t newspeed = std::max(speed, fanmin); + newspeed = std::min(newspeed, fanmax); + remote_state[13] = reverseBits(newspeed, 8); +} + +bool IRHitachiAc::getSwingVertical(void) { + return GETBIT8(remote_state[14], kHitachiAcSwingOffset); +} + +void IRHitachiAc::setSwingVertical(const bool on) { + setBit(&remote_state[14], kHitachiAcSwingOffset, on); +} + +bool IRHitachiAc::getSwingHorizontal(void) { + return GETBIT8(remote_state[15], kHitachiAcSwingOffset); +} + +void IRHitachiAc::setSwingHorizontal(const bool on) { + setBit(&remote_state[15], kHitachiAcSwingOffset, on); +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRHitachiAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: return kHitachiAcCool; + case stdAc::opmode_t::kHeat: return kHitachiAcHeat; + case stdAc::opmode_t::kDry: return kHitachiAcDry; + case stdAc::opmode_t::kFan: return kHitachiAcFan; + default: return kHitachiAcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRHitachiAc::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: return kHitachiAcFanLow; + case stdAc::fanspeed_t::kMedium: return kHitachiAcFanLow + 1; + case stdAc::fanspeed_t::kHigh: return kHitachiAcFanHigh - 1; + case stdAc::fanspeed_t::kMax: return kHitachiAcFanHigh; + default: return kHitachiAcFanAuto; + } +} + +// Convert a native mode to it's common equivalent. +stdAc::opmode_t IRHitachiAc::toCommonMode(const uint8_t mode) { + switch (mode) { + case kHitachiAcCool: return stdAc::opmode_t::kCool; + case kHitachiAcHeat: return stdAc::opmode_t::kHeat; + case kHitachiAcDry: return stdAc::opmode_t::kDry; + case kHitachiAcFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; + } +} + +// Convert a native fan speed to it's common equivalent. +stdAc::fanspeed_t IRHitachiAc::toCommonFanSpeed(const uint8_t speed) { + switch (speed) { + case kHitachiAcFanHigh: return stdAc::fanspeed_t::kMax; + case kHitachiAcFanHigh - 1: return stdAc::fanspeed_t::kHigh; + case kHitachiAcFanLow + 1: return stdAc::fanspeed_t::kMedium; + case kHitachiAcFanLow: return stdAc::fanspeed_t::kLow; + default: return stdAc::fanspeed_t::kAuto; + } +} + +// Convert the A/C state to it's common equivalent. +stdAc::state_t IRHitachiAc::toCommon(void) { + stdAc::state_t result; + result.protocol = decode_type_t::HITACHI_AC; + result.model = -1; // No models used. + result.power = this->getPower(); + result.mode = this->toCommonMode(this->getMode()); + result.celsius = true; + result.degrees = this->getTemp(); + result.fanspeed = this->toCommonFanSpeed(this->getFan()); + result.swingv = this->getSwingVertical() ? stdAc::swingv_t::kAuto : + stdAc::swingv_t::kOff; + result.swingh = this->getSwingHorizontal() ? stdAc::swingh_t::kAuto : + stdAc::swingh_t::kOff; + // Not supported. + result.quiet = false; + result.turbo = false; + result.clean = false; + result.econo = false; + result.filter = false; + result.light = false; + result.beep = false; + result.sleep = -1; + result.clock = -1; + return result; +} + +// Convert the internal state into a human readable string. +String IRHitachiAc::toString(void) { + String result = ""; + result.reserve(110); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(getMode(), kHitachiAcAuto, kHitachiAcCool, + kHitachiAcHeat, kHitachiAcDry, kHitachiAcFan); + result += addTempToString(getTemp()); + result += addFanToString(getFan(), kHitachiAcFanHigh, kHitachiAcFanLow, + kHitachiAcFanAuto, kHitachiAcFanAuto, + kHitachiAcFanMed); + result += addBoolToString(getSwingVertical(), kSwingVStr); + result += addBoolToString(getSwingHorizontal(), kSwingHStr); + return result; +} + +#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2) +// Decode the supplied Hitachi A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. +// Typically kHitachiAcBits, kHitachiAc1Bits, kHitachiAc2Bits +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +// Supported devices: +// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/417 +// https://github.com/crankyoldgit/IRremoteESP8266/issues/453 +bool IRrecv::decodeHitachiAC(decode_results *results, const uint16_t nbits, + const bool strict) { + const uint8_t k_tolerance = _tolerance + 5; + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid HitachiAC message. + if (strict) { + switch (nbits) { + case kHitachiAcBits: + case kHitachiAc1Bits: + case kHitachiAc2Bits: + break; // Okay to continue. + default: + return false; // Not strictly a Hitachi message. + } + } + uint16_t offset = kStartOffset; + uint16_t hmark; + uint32_t hspace; + if (nbits == kHitachiAc1Bits) { + hmark = kHitachiAc1HdrMark; + hspace = kHitachiAc1HdrSpace; + } else { + hmark = kHitachiAcHdrMark; + hspace = kHitachiAcHdrSpace; + } + // Match Header + Data + Footer + if (!matchGeneric(results->rawbuf + offset, results->state, + results->rawlen - offset, nbits, + hmark, hspace, + kHitachiAcBitMark, kHitachiAcOneSpace, + kHitachiAcBitMark, kHitachiAcZeroSpace, + kHitachiAcBitMark, kHitachiAcMinGap, true, + k_tolerance)) return false; + + // Compliance + if (strict) { + if (nbits / 8 == kHitachiAcStateLength && + !IRHitachiAc::validChecksum(results->state, kHitachiAcStateLength)) + return false; + } + + // Success + switch (nbits) { + case kHitachiAc1Bits: + results->decode_type = HITACHI_AC1; + break; + case kHitachiAc2Bits: + results->decode_type = HITACHI_AC2; + break; + case kHitachiAcBits: + default: + results->decode_type = HITACHI_AC; + } + results->bits = nbits; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2) + +#if SEND_HITACHI_AC424 +// Send HITACHI_AC424 messages +// +// Note: This protocol is almost exactly the same as HitachiAC2 except this +// variant has a leader section as well, and subtle timing differences. +// It is also in LSBF order (per byte), rather than MSBF order. +// +// Args: +// data: An array of bytes containing the IR command. +// It is assumed to be in LSBF order for this code. +// nbytes: Nr. of bytes of data in the array. (>=kHitachiAc424StateLength) +// repeat: Nr. of times the message is to be repeated. +// +// Status: STABLE / Reported as working. +void IRsend::sendHitachiAc424(const uint8_t data[], const uint16_t nbytes, + const uint16_t repeat) { + enableIROut(kHitachiAcFreq); + for (uint16_t r = 0; r <= repeat; r++) { + // Leader + mark(kHitachiAc424LdrMark); + space(kHitachiAc424LdrSpace); + // Header + Data + Footer + sendGeneric(kHitachiAc424HdrMark, kHitachiAc424HdrSpace, + kHitachiAc424BitMark, kHitachiAc424OneSpace, + kHitachiAc424BitMark, kHitachiAc424ZeroSpace, + kHitachiAc424BitMark, kHitachiAcMinGap, + data, nbytes, // Bytes + kHitachiAcFreq, false, kNoRepeat, kDutyDefault); + } +} +#endif // SEND_HITACHI_AC424 + +#if DECODE_HITACHI_AC424 +// Decode the supplied Hitachi 424 bit A/C message. +// +// Note: This protocol is almost exactly the same as HitachiAC2 except this +// variant has a leader section as well, and subtle timing differences. +// It is also in LSBF order (per byte), rather than MSBF order. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kHitachiAc424Bits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE / Reported as working. +// +// Supported devices: +// Hitachi Shirokumakun / AC Model: RAS-AJ25H / AC Remote Model: RAR-8P2 +// Manual (Japanese): +// https://kadenfan.hitachi.co.jp/support/raj/item/docs/ras_aj22h_a_tori.pdf +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/973 +bool IRrecv::decodeHitachiAc424(decode_results *results, const uint16_t nbits, + const bool strict) { + if (results->rawlen < 2 * nbits + kHeader + kHeader + kFooter - 1) + return false; // Too short a message to match. + if (strict && nbits != kHitachiAc424Bits) + return false; + + uint16_t offset = kStartOffset; + uint16_t used; + + // Leader + if (!matchMark(results->rawbuf[offset++], kHitachiAc424LdrMark)) + return false; + if (!matchSpace(results->rawbuf[offset++], kHitachiAc424LdrSpace)) + return false; + + // Header + Data + Footer + used = matchGeneric(results->rawbuf + offset, results->state, + results->rawlen - offset, nbits, + kHitachiAc424HdrMark, kHitachiAc424HdrSpace, + kHitachiAc424BitMark, kHitachiAc424OneSpace, + kHitachiAc424BitMark, kHitachiAc424ZeroSpace, + kHitachiAc424BitMark, kHitachiAcMinGap, true, + kUseDefTol, 0, false); + if (used == 0) return false; // We failed to find any data. + + // Success + results->decode_type = decode_type_t::HITACHI_AC424; + results->bits = nbits; + return true; +} +#endif // DECODE_HITACHI_AC424 + +// Class for handling the remote control on a Hitachi_AC424 53 byte A/C message +IRHitachiAc424::IRHitachiAc424(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { stateReset(); } + +// Reset to auto fan, cooling, 23° Celcius +void IRHitachiAc424::stateReset(void) { + for (uint8_t i = 0; i < kHitachiAc424StateLength; i++) + remote_state[i] = 0x00; + + remote_state[0] = 0x01; + remote_state[1] = 0x10; + remote_state[3] = 0x40; + remote_state[5] = 0xFF; + remote_state[7] = 0xCC; + remote_state[11] = 0x13; // Button Action + remote_state[33] = 0x80; + remote_state[35] = 0x03; + remote_state[37] = 0x01; + remote_state[39] = 0x88; + remote_state[45] = 0xFF; + remote_state[47] = 0xFF; + remote_state[49] = 0xFF; + remote_state[51] = 0xFF; + + setTemp(23); + setPower(true); + setMode(kHitachiAc424Cool); + setFan(kHitachiAc424FanAuto); +} + +void IRHitachiAc424::setInvertedStates(void) { + for (uint8_t i = 3; i < kHitachiAc424StateLength - 1; i += 2) + remote_state[i + 1] = ~remote_state[i]; +} + +void IRHitachiAc424::begin(void) { _irsend.begin(); } + +uint8_t *IRHitachiAc424::getRaw(void) { + setInvertedStates(); + return remote_state; +} + +void IRHitachiAc424::setRaw(const uint8_t new_code[], const uint16_t length) { + memcpy(remote_state, new_code, std::min(length, kHitachiAc424StateLength)); +} + +#if SEND_HITACHI_AC424 +void IRHitachiAc424::send(const uint16_t repeat) { + _irsend.sendHitachiAc424(getRaw(), kHitachiAc424StateLength, repeat); +} +#endif // SEND_HITACHI_AC424 + +bool IRHitachiAc424::getPower(void) { + return GETBIT8(remote_state[kHitachiAc424PowerByte], + kHitachiAc424PowerOffset); +} + +void IRHitachiAc424::setPower(const bool on) { + setBit(&remote_state[kHitachiAc424PowerByte], kHitachiAc424PowerOffset, on); +} + +void IRHitachiAc424::on(void) { setPower(true); } + +void IRHitachiAc424::off(void) { setPower(false); } + +uint8_t IRHitachiAc424::getMode(void) { + return GETBITS8(remote_state[kHitachiAc424ModeByte], kLowNibble, kNibbleSize); +} + +void IRHitachiAc424::setMode(const uint8_t mode) { + uint8_t newMode = mode; + switch (mode) { + // Fan mode sets a special temp. + case kHitachiAc424Fan: setTemp(kHitachiAc424FanTemp, false); break; + case kHitachiAc424Heat: + case kHitachiAc424Cool: + case kHitachiAc424Dry: break; + default: newMode = kHitachiAc424Cool; + } + setBits(&remote_state[kHitachiAc424ModeByte], kLowNibble, kNibbleSize, + newMode); + if (newMode != kHitachiAc424Fan) setTemp(_previoustemp); + setFan(getFan()); // Reset the fan speed after the mode change. +} + +uint8_t IRHitachiAc424::getTemp(void) { + return GETBITS8(remote_state[kHitachiAc424TempByte], kHitachiAc424TempOffset, + kHitachiAc424TempSize); +} + +void IRHitachiAc424::setTemp(const uint8_t celsius, bool setPrevious) { + uint8_t temp; + if (setPrevious) _previoustemp = celsius; + temp = std::min(celsius, kHitachiAc424MaxTemp); + temp = std::max(temp, kHitachiAc424MinTemp); + setBits(&remote_state[kHitachiAc424TempByte], kHitachiAc424TempOffset, + kHitachiAc424TempSize, temp); +} + +uint8_t IRHitachiAc424::getFan(void) { + return GETBITS8(remote_state[kHitachiAc424FanByte], kHighNibble, kNibbleSize); +} + +void IRHitachiAc424::setFan(const uint8_t speed) { + uint8_t newSpeed = std::max(speed, kHitachiAc424FanMin); + uint8_t fanMax = kHitachiAc424FanMax; + + // Only 2 x low speeds in Dry mode or Auto + if (getMode() == kHitachiAc424Dry && speed == kHitachiAc424FanAuto) { + fanMax = kHitachiAc424FanAuto; + } else if (getMode() == kHitachiAc424Dry) { + fanMax = kHitachiAc424FanMaxDry; + } else if (getMode() == kHitachiAc424Fan && speed == kHitachiAc424FanAuto) { + // Fan Mode does not have auto. Set to safe low + newSpeed = kHitachiAc424FanMin; + } + + newSpeed = std::min(newSpeed, fanMax); + setBits(&remote_state[kHitachiAc424FanByte], kHighNibble, kNibbleSize, + newSpeed); + remote_state[9] = 0x92; + remote_state[29] = 0x00; + + // When fan is at min/max, additional bytes seem to be set + if (newSpeed == kHitachiAc424FanMin) remote_state[9] = 0x98; + if (newSpeed == kHitachiAc424FanMax) { + remote_state[9] = 0xA9; + remote_state[29] = 0x30; + } +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRHitachiAc424::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: return kHitachiAc424Cool; + case stdAc::opmode_t::kHeat: return kHitachiAc424Heat; + case stdAc::opmode_t::kDry: return kHitachiAc424Dry; + case stdAc::opmode_t::kFan: return kHitachiAc424Fan; + default: return kHitachiAc424Cool; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRHitachiAc424::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: return kHitachiAc424FanMin; + case stdAc::fanspeed_t::kLow: return kHitachiAc424FanLow; + case stdAc::fanspeed_t::kMedium: return kHitachiAc424FanMedium; + case stdAc::fanspeed_t::kHigh: return kHitachiAc424FanHigh; + case stdAc::fanspeed_t::kMax: return kHitachiAc424FanMax; + default: return kHitachiAc424FanAuto; + } +} + +// Convert a native mode to it's common equivalent. +stdAc::opmode_t IRHitachiAc424::toCommonMode(const uint8_t mode) { + switch (mode) { + case kHitachiAc424Cool: return stdAc::opmode_t::kCool; + case kHitachiAc424Heat: return stdAc::opmode_t::kHeat; + case kHitachiAc424Dry: return stdAc::opmode_t::kDry; + case kHitachiAc424Fan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kCool; + } +} + +// Convert a native fan speed to it's common equivalent. +stdAc::fanspeed_t IRHitachiAc424::toCommonFanSpeed(const uint8_t speed) { + switch (speed) { + case kHitachiAc424FanMax: return stdAc::fanspeed_t::kMax; + case kHitachiAc424FanHigh: return stdAc::fanspeed_t::kHigh; + case kHitachiAc424FanMedium: return stdAc::fanspeed_t::kMedium; + case kHitachiAc424FanLow: return stdAc::fanspeed_t::kLow; + case kHitachiAc424FanMin: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; + } +} + +// Convert the A/C state to it's common equivalent. +stdAc::state_t IRHitachiAc424::toCommon(void) { + stdAc::state_t result; + result.protocol = decode_type_t::HITACHI_AC424; + result.model = -1; // No models used. + result.power = this->getPower(); + result.mode = this->toCommonMode(this->getMode()); + result.celsius = true; + result.degrees = this->getTemp(); + result.fanspeed = this->toCommonFanSpeed(this->getFan()); + + // TODO(jamsinclair): Add support. + result.swingv = stdAc::swingv_t::kOff; + + // Not supported. + result.swingh = stdAc::swingh_t::kOff; + result.quiet = false; + result.turbo = false; + result.clean = false; + result.econo = false; + result.filter = false; + result.light = false; + result.beep = false; + result.sleep = -1; + result.clock = -1; + return result; +} + +// Convert the internal state into a human readable string. +String IRHitachiAc424::toString(void) { + String result = ""; + result.reserve(60); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(getMode(), 0, kHitachiAc424Cool, + kHitachiAc424Heat, kHitachiAc424Dry, + kHitachiAc424Fan); + result += addTempToString(getTemp()); + result += addIntToString(getFan(), kFanStr); + result += kSpaceLBraceStr; + switch (getFan()) { + case kHitachiAc424FanAuto: result += kAutoStr; break; + case kHitachiAc424FanMax: result += kMaxStr; break; + case kHitachiAc424FanHigh: result += kHighStr; break; + case kHitachiAc424FanMedium: result += kMedStr; break; + case kHitachiAc424FanLow: result += kLowStr; break; + case kHitachiAc424FanMin: result += kMinStr; break; + default: result += kUnknownStr; + } + result += ')'; + return result; +} diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.h b/lib/IRremoteESP8266-2.7.0/src/ir_Hitachi.h old mode 100755 new mode 100644 similarity index 51% rename from lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Hitachi.h index b9bfd391c..4b02b3a4c --- a/lib/IRremoteESP8266-2.6.5/src/ir_Hitachi.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Hitachi.h @@ -1,11 +1,13 @@ // Hitachi A/C // -// Copyright 2018 David Conran +// Copyright 2018-2019 David Conran // Supports: // Brand: Hitachi, Model: RAS-35THA6 remote // Brand: Hitachi, Model: LT0541-HTA remote // Brand: Hitachi, Model: Series VI A/C (Circa 2007) +// Brand: Hitachi, Model: RAR-8P2 remote +// Brand: Hitachi, Model: RAS-AJ25H A/C #ifndef IR_HITACHI_H_ #define IR_HITACHI_H_ @@ -22,6 +24,7 @@ #endif // Constants +const uint16_t kHitachiAcFreq = 38000; // Hz. const uint8_t kHitachiAcAuto = 2; const uint8_t kHitachiAcHeat = 3; const uint8_t kHitachiAcCool = 4; @@ -34,6 +37,35 @@ const uint8_t kHitachiAcFanHigh = 5; const uint8_t kHitachiAcMinTemp = 16; // 16C const uint8_t kHitachiAcMaxTemp = 32; // 32C const uint8_t kHitachiAcAutoTemp = 23; // 23C +const uint8_t kHitachiAcPowerOffset = 0; +const uint8_t kHitachiAcSwingOffset = 7; + +// HitachiAc424 +// Byte[13] +const uint8_t kHitachiAc424TempByte = 13; +const uint8_t kHitachiAc424TempOffset = 2; +const uint8_t kHitachiAc424TempSize = 6; +const uint8_t kHitachiAc424MinTemp = 16; // 16C +const uint8_t kHitachiAc424MaxTemp = 32; // 32C +const uint8_t kHitachiAc424FanTemp = 27; // 27C + +// Byte[25] +const uint8_t kHitachiAc424ModeByte = 25; +const uint8_t kHitachiAc424Fan = 1; +const uint8_t kHitachiAc424Cool = 3; +const uint8_t kHitachiAc424Dry = 5; +const uint8_t kHitachiAc424Heat = 6; +const uint8_t kHitachiAc424FanByte = kHitachiAc424ModeByte; +const uint8_t kHitachiAc424FanMin = 1; +const uint8_t kHitachiAc424FanLow = 2; +const uint8_t kHitachiAc424FanMedium = 3; +const uint8_t kHitachiAc424FanHigh = 4; +const uint8_t kHitachiAc424FanAuto = 5; +const uint8_t kHitachiAc424FanMax = 6; +const uint8_t kHitachiAc424FanMaxDry = 2; +// Byte[27] +const uint8_t kHitachiAc424PowerByte = 27; +const uint8_t kHitachiAc424PowerOffset = 4; // Classes class IRHitachiAc { @@ -87,4 +119,47 @@ class IRHitachiAc { uint8_t _previoustemp; }; +class IRHitachiAc424 { + public: + explicit IRHitachiAc424(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); + + void stateReset(void); +#if SEND_HITACHI_AC424 + void send(const uint16_t repeat = kHitachiAcDefaultRepeat); + uint8_t calibrate(void) { return _irsend.calibrate(); } +#endif // SEND_HITACHI_AC424 + void begin(void); + void on(void); + void off(void); + void setPower(const bool on); + bool getPower(void); + void setTemp(const uint8_t temp, bool setPrevious = true); + uint8_t getTemp(void); + void setFan(const uint8_t speed); + uint8_t getFan(void); + void setMode(const uint8_t mode); + uint8_t getMode(void); + uint8_t* getRaw(void); + void setRaw(const uint8_t new_code[], + const uint16_t length = kHitachiAc424StateLength); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); + stdAc::state_t toCommon(void); + String toString(void); +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + // The state of the IR remote in IR code form. + uint8_t remote_state[kHitachiAc424StateLength]; + void setInvertedStates(void); + uint8_t _previoustemp; +}; + #endif // IR_HITACHI_H_ diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Inax.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Inax.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Inax.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Inax.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_JVC.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_JVC.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_JVC.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_JVC.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Kelvinator.cpp old mode 100755 new mode 100644 similarity index 77% rename from lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Kelvinator.cpp index 0af521b15..320458b30 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Kelvinator.cpp @@ -16,12 +16,14 @@ #include "ir_Kelvinator.h" #include +#include #ifndef ARDUINO #include #endif #include "IRac.h" #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Constants @@ -44,27 +46,20 @@ const uint16_t kKelvinatorGapSpace = kKelvinatorGapSpaceTicks * kKelvinatorTick; const uint8_t kKelvinatorCmdFooter = 2; const uint8_t kKelvinatorCmdFooterBits = 3; -const uint8_t kKelvinatorPower = 8; -const uint8_t kKelvinatorModeMask = 0xF8; -const uint8_t kKelvinatorFanOffset = 4; -const uint8_t kKelvinatorBasicFanMask = 0xFF ^ (3U << kKelvinatorFanOffset); -const uint8_t kKelvinatorFanMask = 0xFF ^ (7U << kKelvinatorFanOffset); +const uint8_t kKelvinatorModeOffset = 0; // Mask 0b111 +const uint8_t kKelvinatorPowerOffset = 3; +const uint8_t kKelvinatorFanOffset = 4; // Mask 0b111 +const uint8_t kKelvinatorFanSize = 3; // Bits +const uint8_t kKelvinatorBasicFanSize = 2; // Bits, Mask 0b011 const uint8_t kKelvinatorChecksumStart = 10; const uint8_t kKelvinatorVentSwingOffset = 6; -const uint8_t kKelvinatorVentSwing = 1 << kKelvinatorVentSwingOffset; -const uint8_t kKelvinatorVentSwingV = 1; -const uint8_t kKelvinatorVentSwingH = 1 << 4; -const uint8_t kKelvinatorSleep1And3 = 1 << 7; +const uint8_t kKelvinatorVentSwingVOffset = 0; +const uint8_t kKelvinatorVentSwingHOffset = 4; const uint8_t kKelvinatorQuietOffset = 7; -const uint8_t kKelvinatorQuiet = 1 << kKelvinatorQuietOffset; const uint8_t kKelvinatorIonFilterOffset = 6; -const uint8_t kKelvinatorIonFilter = 1 << kKelvinatorIonFilterOffset; const uint8_t kKelvinatorLightOffset = 5; -const uint8_t kKelvinatorLight = 1 << kKelvinatorLightOffset; const uint8_t kKelvinatorXfanOffset = 7; -const uint8_t kKelvinatorXfan = 1 << kKelvinatorXfanOffset; const uint8_t kKelvinatorTurboOffset = 4; -const uint8_t kKelvinatorTurbo = 1 << kKelvinatorTurboOffset; using irutils::addBoolToString; using irutils::addIntToString; @@ -72,6 +67,8 @@ using irutils::addLabeledString; using irutils::addModeToString; using irutils::addFanToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_KELVINATOR // Send a Kelvinator A/C message. @@ -157,9 +154,7 @@ uint8_t *IRKelvinatorAC::getRaw(void) { } void IRKelvinatorAC::setRaw(const uint8_t new_code[]) { - for (uint8_t i = 0; i < kKelvinatorStateLength; i++) { - remote_state[i] = new_code[i]; - } + memcpy(remote_state, new_code, kKelvinatorStateLength); } uint8_t IRKelvinatorAC::calcBlockChecksum(const uint8_t *block, @@ -167,19 +162,19 @@ uint8_t IRKelvinatorAC::calcBlockChecksum(const uint8_t *block, uint8_t sum = kKelvinatorChecksumStart; // Sum the lower half of the first 4 bytes of this block. for (uint8_t i = 0; i < 4 && i < length - 1; i++, block++) - sum += (*block & 0x0FU); + sum += (*block & 0b1111); // then sum the upper half of the next 3 bytes. for (uint8_t i = 4; i < length - 1; i++, block++) sum += (*block >> 4); // Trim it down to fit into the 4 bits allowed. i.e. Mod 16. - return sum & 0x0FU; + return sum & 0b1111; } // Many Bothans died to bring us this information. void IRKelvinatorAC::checksum(const uint16_t length) { // For each command + options block. for (uint16_t offset = 0; offset + 7 < length; offset += 8) { - uint8_t sum = calcBlockChecksum(remote_state + offset); - remote_state[7 + offset] = (sum << 4) | (remote_state[7 + offset] & 0xFU); + setBits(&remote_state[7 + offset], kHighNibble, kNibbleSize, + calcBlockChecksum(remote_state + offset)); } } @@ -193,44 +188,38 @@ bool IRKelvinatorAC::validChecksum(const uint8_t state[], const uint16_t length) { for (uint16_t offset = 0; offset + 7 < length; offset += 8) { // Top 4 bits of the last byte in the block is the block's checksum. - if (state[offset + 7] >> 4 != calcBlockChecksum(state + offset)) + if (GETBITS8(state[offset + 7], kHighNibble, kNibbleSize) != + calcBlockChecksum(state + offset)) return false; } return true; } -void IRKelvinatorAC::on(void) { - remote_state[0] |= kKelvinatorPower; - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. -} +void IRKelvinatorAC::on(void) { setPower(true); } -void IRKelvinatorAC::off(void) { - remote_state[0] &= ~kKelvinatorPower; - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. -} +void IRKelvinatorAC::off(void) {setPower(false); } void IRKelvinatorAC::setPower(const bool on) { - if (on) - this->on(); - else - this->off(); + setBit(&remote_state[0], kKelvinatorPowerOffset, on); + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. } bool IRKelvinatorAC::getPower(void) { - return remote_state[0] & kKelvinatorPower; + return GETBIT8(remote_state[0], kKelvinatorPowerOffset); } // Set the temp. in deg C void IRKelvinatorAC::setTemp(const uint8_t degrees) { uint8_t temp = std::max(kKelvinatorMinTemp, degrees); temp = std::min(kKelvinatorMaxTemp, temp); - remote_state[1] = (remote_state[1] & 0xF0U) | (temp - kKelvinatorMinTemp); + setBits(&remote_state[1], kLowNibble, kNibbleSize, temp - kKelvinatorMinTemp); remote_state[9] = remote_state[1]; // Duplicate to the 2nd command chunk. } // Return the set temp. in deg C uint8_t IRKelvinatorAC::getTemp(void) { - return ((remote_state[1] & 0xFU) + kKelvinatorMinTemp); + return GETBITS8(remote_state[1], kLowNibble, kNibbleSize) + + kKelvinatorMinTemp; } // Set the speed of the fan, 0-5, 0 is auto, 1-5 is the speed @@ -240,24 +229,22 @@ void IRKelvinatorAC::setFan(const uint8_t speed) { // Only change things if we need to. if (fan != this->getFan()) { // Set the basic fan values. - uint8_t fan_basic = std::min(kKelvinatorBasicFanMax, fan); - remote_state[0] = (remote_state[0] & kKelvinatorBasicFanMask) | - (fan_basic << kKelvinatorFanOffset); + setBits(&remote_state[0], kKelvinatorFanOffset, kKelvinatorBasicFanSize, + std::min(kKelvinatorBasicFanMax, fan)); remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. // Set the advanced(?) fan value. - remote_state[14] = - (remote_state[14] & kKelvinatorFanMask) | (fan << kKelvinatorFanOffset); + setBits(&remote_state[14], kKelvinatorFanOffset, kKelvinatorFanSize, fan); // Turbo mode is turned off if we change the fan settings. this->setTurbo(false); } } uint8_t IRKelvinatorAC::getFan(void) { - return ((remote_state[14] & ~kKelvinatorFanMask) >> kKelvinatorFanOffset); + return GETBITS8(remote_state[14], kKelvinatorFanOffset, kKelvinatorFanSize); } uint8_t IRKelvinatorAC::getMode(void) { - return (remote_state[0] & ~kKelvinatorModeMask); + return GETBITS8(remote_state[0], kKelvinatorModeOffset, kModeBitsSize); } void IRKelvinatorAC::setMode(const uint8_t mode) { @@ -271,7 +258,7 @@ void IRKelvinatorAC::setMode(const uint8_t mode) { case kKelvinatorHeat: case kKelvinatorCool: case kKelvinatorFan: - remote_state[0] = (remote_state[0] & kKelvinatorModeMask) | mode; + setBits(&remote_state[0], kKelvinatorModeOffset, kModeBitsSize, mode); remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. break; default: // If we get an unexpected mode, default to AUTO. @@ -280,99 +267,81 @@ void IRKelvinatorAC::setMode(const uint8_t mode) { } void IRKelvinatorAC::setSwingVertical(const bool on) { - if (on) { - remote_state[0] |= kKelvinatorVentSwing; - remote_state[4] |= kKelvinatorVentSwingV; - } else { - remote_state[4] &= ~kKelvinatorVentSwingV; - if (!this->getSwingHorizontal()) remote_state[0] &= ~kKelvinatorVentSwing; - } + setBit(&remote_state[4], kKelvinatorVentSwingVOffset, on); + setBit(&remote_state[0], kKelvinatorVentSwingOffset, + on || getSwingHorizontal()); remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. } bool IRKelvinatorAC::getSwingVertical(void) { - return remote_state[4] & kKelvinatorVentSwingV; + return GETBIT8(remote_state[4], kKelvinatorVentSwingVOffset); } void IRKelvinatorAC::setSwingHorizontal(const bool on) { - if (on) { - remote_state[0] |= kKelvinatorVentSwing; - remote_state[4] |= kKelvinatorVentSwingH; - } else { - remote_state[4] &= ~kKelvinatorVentSwingH; - if (!this->getSwingVertical()) remote_state[0] &= ~kKelvinatorVentSwing; - } + setBit(&remote_state[4], kKelvinatorVentSwingHOffset, on); + setBit(&remote_state[0], kKelvinatorVentSwingOffset, + on || getSwingVertical()); remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. } bool IRKelvinatorAC::getSwingHorizontal(void) { - return remote_state[4] & kKelvinatorVentSwingH; + return GETBIT8(remote_state[4], kKelvinatorVentSwingHOffset); } void IRKelvinatorAC::setQuiet(const bool on) { - remote_state[12] &= ~kKelvinatorQuiet; - remote_state[12] |= (on << kKelvinatorQuietOffset); + setBit(&remote_state[12], kKelvinatorQuietOffset, on); } bool IRKelvinatorAC::getQuiet(void) { - return remote_state[12] & kKelvinatorQuiet; + return GETBIT8(remote_state[12], kKelvinatorQuietOffset); } void IRKelvinatorAC::setIonFilter(const bool on) { - remote_state[2] &= ~kKelvinatorIonFilter; - remote_state[2] |= (on << kKelvinatorIonFilterOffset); + setBit(&remote_state[2], kKelvinatorIonFilterOffset, on); remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. } bool IRKelvinatorAC::getIonFilter(void) { - return remote_state[2] & kKelvinatorIonFilter; + return GETBIT8(remote_state[2], kKelvinatorIonFilterOffset); } void IRKelvinatorAC::setLight(const bool on) { - remote_state[2] &= ~kKelvinatorLight; - remote_state[2] |= (on << kKelvinatorLightOffset); + setBit(&remote_state[2], kKelvinatorLightOffset, on); remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. } bool IRKelvinatorAC::getLight(void) { - return remote_state[2] & kKelvinatorLight; + return GETBIT8(remote_state[2], kKelvinatorLightOffset); } // Note: XFan mode is only valid in Cool or Dry mode. void IRKelvinatorAC::setXFan(const bool on) { - remote_state[2] &= ~kKelvinatorXfan; - remote_state[2] |= (on << kKelvinatorXfanOffset); + setBit(&remote_state[2], kKelvinatorXfanOffset, on); remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. } bool IRKelvinatorAC::getXFan(void) { - return remote_state[2] & kKelvinatorXfan; + return GETBIT8(remote_state[2], kKelvinatorXfanOffset); } // Note: Turbo mode is turned off if the fan speed is changed. void IRKelvinatorAC::setTurbo(const bool on) { - remote_state[2] &= ~kKelvinatorTurbo; - remote_state[2] |= (on << kKelvinatorTurboOffset); + setBit(&remote_state[2], kKelvinatorTurboOffset, on); remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. } bool IRKelvinatorAC::getTurbo(void) { - return remote_state[2] & kKelvinatorTurbo; + return GETBIT8(remote_state[2], kKelvinatorTurboOffset); } // Convert a standard A/C mode into its native mode. uint8_t IRKelvinatorAC::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kKelvinatorCool; - case stdAc::opmode_t::kHeat: - return kKelvinatorHeat; - case stdAc::opmode_t::kDry: - return kKelvinatorDry; - case stdAc::opmode_t::kFan: - return kKelvinatorFan; - default: - return kKelvinatorAuto; + case stdAc::opmode_t::kCool: return kKelvinatorCool; + case stdAc::opmode_t::kHeat: return kKelvinatorHeat; + case stdAc::opmode_t::kDry: return kKelvinatorDry; + case stdAc::opmode_t::kFan: return kKelvinatorFan; + default: return kKelvinatorAuto; } } @@ -381,9 +350,9 @@ stdAc::opmode_t IRKelvinatorAC::toCommonMode(const uint8_t mode) { switch (mode) { case kKelvinatorCool: return stdAc::opmode_t::kCool; case kKelvinatorHeat: return stdAc::opmode_t::kHeat; - case kKelvinatorDry: return stdAc::opmode_t::kDry; - case kKelvinatorFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kKelvinatorDry: return stdAc::opmode_t::kDry; + case kKelvinatorFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -423,20 +392,20 @@ stdAc::state_t IRKelvinatorAC::toCommon(void) { String IRKelvinatorAC::toString(void) { String result = ""; result.reserve(160); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kKelvinatorAuto, kKelvinatorCool, kKelvinatorHeat, kKelvinatorDry, kKelvinatorFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kKelvinatorFanMax, kKelvinatorFanMin, kKelvinatorFanAuto, kKelvinatorFanAuto, kKelvinatorBasicFanMax); - result += addBoolToString(getTurbo(), F("Turbo")); - result += addBoolToString(getQuiet(), F("Quiet")); - result += addBoolToString(getXFan(), F("XFan")); - result += addBoolToString(getIonFilter(), F("IonFilter")); - result += addBoolToString(getLight(), F("Light")); - result += addBoolToString(getSwingHorizontal(), F("Swing (Horizontal)")); - result += addBoolToString(getSwingVertical(), F("Swing (Vertical)")); + result += addBoolToString(getTurbo(), kTurboStr); + result += addBoolToString(getQuiet(), kQuietStr); + result += addBoolToString(getXFan(), kXFanStr); + result += addBoolToString(getIonFilter(), kIonStr); + result += addBoolToString(getLight(), kLightStr); + result += addBoolToString(getSwingHorizontal(), kSwingHStr); + result += addBoolToString(getSwingVertical(), kSwingVStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.h b/lib/IRremoteESP8266-2.7.0/src/ir_Kelvinator.h old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Kelvinator.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Kelvinator.h diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_LG.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_LG.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_LG.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_LG.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_LG.h b/lib/IRremoteESP8266-2.7.0/src/ir_LG.h old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_LG.h rename to lib/IRremoteESP8266-2.7.0/src/ir_LG.h diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Lasertag.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Lasertag.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Lasertag.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Lasertag.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Lego.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Lego.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Lego.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Lego.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Lutron.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Lutron.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Lutron.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Lutron.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_MWM.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_MWM.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_MWM.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_MWM.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Magiquest.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Magiquest.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Magiquest.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Magiquest.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Magiquest.h b/lib/IRremoteESP8266-2.7.0/src/ir_Magiquest.h old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Magiquest.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Magiquest.h diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Midea.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Midea.cpp old mode 100755 new mode 100644 similarity index 82% rename from lib/IRremoteESP8266-2.6.5/src/ir_Midea.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Midea.cpp index 80744c9cb..3160fc291 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Midea.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Midea.cpp @@ -8,6 +8,7 @@ #endif #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Midea A/C added by (send) bwze/crankyoldgit & (decode) crankyoldgit @@ -43,6 +44,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_MIDEA // Send a Midea message @@ -123,46 +126,38 @@ void IRMideaAC::send(const uint16_t repeat) { // Return a pointer to the internal state date of the remote. uint64_t IRMideaAC::getRaw(void) { this->checksum(); - return remote_state & kMideaACStateMask; + return GETBITS64(remote_state, 0, kMideaBits); } // Override the internal state with the new state. -void IRMideaAC::setRaw(const uint64_t newState) { - remote_state = newState & kMideaACStateMask; -} +void IRMideaAC::setRaw(const uint64_t newState) { remote_state = newState; } + +// Set the requested power state of the A/C to on. +void IRMideaAC::on(void) { setPower(true); } // Set the requested power state of the A/C to off. -void IRMideaAC::on(void) { remote_state |= kMideaACPower; } - -// Set the requested power state of the A/C to off. -void IRMideaAC::off(void) { - remote_state &= (kMideaACStateMask ^ kMideaACPower); -} +void IRMideaAC::off(void) { setPower(false); } // Set the requested power state of the A/C. void IRMideaAC::setPower(const bool on) { - if (on) - this->on(); - else - this->off(); + setBit(&remote_state, kMideaACPowerOffset, on); } // Return the requested power state of the A/C. -bool IRMideaAC::getPower(void) { return (remote_state & kMideaACPower); } +bool IRMideaAC::getPower(void) { + return GETBIT64(remote_state, kMideaACPowerOffset); +} // Returns true if we want the A/C unit to work natively in Celsius. bool IRMideaAC::getUseCelsius(void) { - return !(remote_state & kMideaACCelsiusBit); + return !GETBIT64(remote_state, kMideaACCelsiusOffset); } // Set the A/C unit to use Celsius natively. void IRMideaAC::setUseCelsius(const bool on) { if (on != getUseCelsius()) { // We need to change. uint8_t native_temp = getTemp(!on); // Get the old native temp. - if (on) - remote_state &= ~kMideaACCelsiusBit; // Clear the bit - else - remote_state |= kMideaACCelsiusBit; // Set the bit + setBit(&remote_state, kMideaACCelsiusOffset, !on); // Cleared is on. setTemp(native_temp, !on); // Reset temp using the old native temp. } } @@ -186,8 +181,7 @@ void IRMideaAC::setTemp(const uint8_t temp, const bool useCelsius) { else // Native and desired are the same units. new_temp -= min_temp; // Set the actual data. - remote_state &= kMideaACTempMask; - remote_state |= ((uint64_t)new_temp << 24); + setBits(&remote_state, kMideaACTempOffset, kMideaACTempSize, new_temp); } // Return the set temp. @@ -196,7 +190,7 @@ void IRMideaAC::setTemp(const uint8_t temp, const bool useCelsius) { // Returns: // A uint8_t containing the temperature. uint8_t IRMideaAC::getTemp(const bool celsius) { - uint8_t temp = ((remote_state >> 24) & 0x1F); + uint8_t temp = GETBITS64(remote_state, kMideaACTempOffset, kMideaACTempSize); if (getUseCelsius()) temp += kMideaACMinTempC; else @@ -209,27 +203,21 @@ uint8_t IRMideaAC::getTemp(const bool celsius) { // Set the speed of the fan, // 1-3 set the speed, 0 or anything else set it to auto. void IRMideaAC::setFan(const uint8_t fan) { - uint64_t new_fan; - switch (fan) { - case kMideaACFanLow: - case kMideaACFanMed: - case kMideaACFanHigh: - new_fan = fan; - break; - default: - new_fan = kMideaACFanAuto; - } - remote_state &= kMideaACFanMask; - remote_state |= (new_fan << 35); + setBits(&remote_state, kMideaACFanOffset, kMideaACFanSize, + (fan > kMideaACFanHigh) ? kMideaACFanAuto : fan); } // Return the requested state of the unit's fan. -uint8_t IRMideaAC::getFan(void) { return (remote_state >> 35) & 0b111; } +uint8_t IRMideaAC::getFan(void) { + return GETBITS64(remote_state, kMideaACFanOffset, kMideaACFanSize); +} // Get the requested climate operation mode of the a/c unit. // Returns: // A uint8_t containing the A/C mode. -uint8_t IRMideaAC::getMode(void) { return ((remote_state >> 32) & 0b111); } +uint8_t IRMideaAC::getMode(void) { + return GETBITS64(remote_state, kMideaACModeOffset, kModeBitsSize); +} // Set the requested climate operation mode of the a/c unit. void IRMideaAC::setMode(const uint8_t mode) { @@ -239,9 +227,8 @@ void IRMideaAC::setMode(const uint8_t mode) { case kMideaACHeat: case kMideaACDry: case kMideaACFan: - remote_state &= kMideaACModeMask; - remote_state |= ((uint64_t)mode << 32); - return; + setBits(&remote_state, kMideaACModeOffset, kModeBitsSize, mode); + break; default: this->setMode(kMideaACAuto); } @@ -249,24 +236,22 @@ void IRMideaAC::setMode(const uint8_t mode) { // Set the Sleep state of the A/C. void IRMideaAC::setSleep(const bool on) { - if (on) - remote_state |= kMideaACSleep; - else - remote_state &= (kMideaACStateMask ^ kMideaACSleep); + setBit(&remote_state, kMideaACSleepOffset, on); } // Return the Sleep state of the A/C. -bool IRMideaAC::getSleep(void) { return (remote_state & kMideaACSleep); } +bool IRMideaAC::getSleep(void) { + return GETBIT64(remote_state, kMideaACSleepOffset); +} // Set the A/C to toggle the vertical swing toggle for the next send. -void IRMideaAC::setSwingVToggle(const bool on) { - _SwingVToggle = on; -} +void IRMideaAC::setSwingVToggle(const bool on) { _SwingVToggle = on; } // Return if the message/state is just a Swing V toggle message/command. bool IRMideaAC::isSwingVToggle(void) { return remote_state == kMideaACToggleSwingV; } + // Return the Swing V toggle state of the A/C. bool IRMideaAC::getSwingVToggle(void) { _SwingVToggle |= isSwingVToggle(); @@ -296,30 +281,24 @@ uint8_t IRMideaAC::calcChecksum(const uint64_t state) { // Returns: // A boolean. bool IRMideaAC::validChecksum(const uint64_t state) { - return ((state & 0xFF) == calcChecksum(state)); + return GETBITS64(state, 0, 8) == calcChecksum(state); } // Calculate & set the checksum for the current internal state of the remote. void IRMideaAC::checksum(void) { // Stored the checksum value in the last byte. - remote_state &= kMideaACChecksumMask; - remote_state |= calcChecksum(remote_state); + setBits(&remote_state, 0, 8, calcChecksum(remote_state)); } // Convert a standard A/C mode into its native mode. uint8_t IRMideaAC::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kMideaACCool; - case stdAc::opmode_t::kHeat: - return kMideaACHeat; - case stdAc::opmode_t::kDry: - return kMideaACDry; - case stdAc::opmode_t::kFan: - return kMideaACFan; - default: - return kMideaACAuto; + case stdAc::opmode_t::kCool: return kMideaACCool; + case stdAc::opmode_t::kHeat: return kMideaACHeat; + case stdAc::opmode_t::kDry: return kMideaACDry; + case stdAc::opmode_t::kFan: return kMideaACFan; + default: return kMideaACAuto; } } @@ -327,15 +306,11 @@ uint8_t IRMideaAC::convertMode(const stdAc::opmode_t mode) { uint8_t IRMideaAC::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kMideaACFanLow; - case stdAc::fanspeed_t::kMedium: - return kMideaACFanMed; + case stdAc::fanspeed_t::kLow: return kMideaACFanLow; + case stdAc::fanspeed_t::kMedium: return kMideaACFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kMideaACFanHigh; - default: - return kMideaACFanAuto; + case stdAc::fanspeed_t::kMax: return kMideaACFanHigh; + default: return kMideaACFanAuto; } } @@ -344,9 +319,9 @@ stdAc::opmode_t IRMideaAC::toCommonMode(const uint8_t mode) { switch (mode) { case kMideaACCool: return stdAc::opmode_t::kCool; case kMideaACHeat: return stdAc::opmode_t::kHeat; - case kMideaACDry: return stdAc::opmode_t::kDry; - case kMideaACFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kMideaACDry: return stdAc::opmode_t::kDry; + case kMideaACFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -354,9 +329,9 @@ stdAc::opmode_t IRMideaAC::toCommonMode(const uint8_t mode) { stdAc::fanspeed_t IRMideaAC::toCommonFanSpeed(const uint8_t speed) { switch (speed) { case kMideaACFanHigh: return stdAc::fanspeed_t::kMax; - case kMideaACFanMed: return stdAc::fanspeed_t::kMedium; - case kMideaACFanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kMideaACFanMed: return stdAc::fanspeed_t::kMedium; + case kMideaACFanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } @@ -400,19 +375,19 @@ String IRMideaAC::toString(void) { String result = ""; result.reserve(100); // Reserve some heap for the string to reduce fragging. if (!isSwingVToggle()) { - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kMideaACAuto, kMideaACCool, kMideaACHeat, kMideaACDry, kMideaACFan); - result += addBoolToString(getUseCelsius(), F("Celsius")); + result += addBoolToString(getUseCelsius(), kCelsiusStr); result += addTempToString(getTemp(true)); result += '/'; result += uint64ToString(getTemp(false)); result += 'F'; result += addFanToString(getFan(), kMideaACFanHigh, kMideaACFanLow, kMideaACFanAuto, kMideaACFanAuto, kMideaACFanMed); - result += addBoolToString(getSleep(), F("Sleep")); + result += addBoolToString(getSleep(), kSleepStr); } - result += addBoolToString(getSwingVToggle(), F("Swing(V) Toggle"), + result += addBoolToString(getSwingVToggle(), kSwingVStr + ' ' + kToggleStr, !isSwingVToggle()); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Midea.h b/lib/IRremoteESP8266-2.7.0/src/ir_Midea.h old mode 100755 new mode 100644 similarity index 84% rename from lib/IRremoteESP8266-2.6.5/src/ir_Midea.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Midea.h index 289821778..af005d729 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Midea.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Midea.h @@ -26,27 +26,27 @@ // https://docs.google.com/spreadsheets/d/1TZh4jWrx4h9zzpYUI9aYXMl1fYOiqu-xVuOOMqagxrs/edit?usp=sharing // Constants +const uint8_t kMideaACTempOffset = 24; +const uint8_t kMideaACTempSize = 5; // Bits +const uint8_t kMideaACMinTempF = 62; // Fahrenheit +const uint8_t kMideaACMaxTempF = 86; // Fahrenheit +const uint8_t kMideaACMinTempC = 17; // Celsius +const uint8_t kMideaACMaxTempC = 30; // Celsius +const uint8_t kMideaACCelsiusOffset = 29; +const uint8_t kMideaACModeOffset = 32; const uint8_t kMideaACCool = 0; // 0b000 const uint8_t kMideaACDry = 1; // 0b001 const uint8_t kMideaACAuto = 2; // 0b010 const uint8_t kMideaACHeat = 3; // 0b011 const uint8_t kMideaACFan = 4; // 0b100 -const uint8_t kMideaACFanAuto = 0; // 0b000 -const uint8_t kMideaACFanLow = 1; // 0b001 -const uint8_t kMideaACFanMed = 2; // 0b010 -const uint8_t kMideaACFanHigh = 3; // 0b011 -const uint64_t kMideaACPower = 1ULL << 39; -const uint64_t kMideaACSleep = 1ULL << 38; -const uint8_t kMideaACMinTempF = 62; // Fahrenheit -const uint8_t kMideaACMaxTempF = 86; // Fahrenheit -const uint8_t kMideaACMinTempC = 17; // Celsius -const uint8_t kMideaACMaxTempC = 30; // Celsius -const uint64_t kMideaACStateMask = 0x0000FFFFFFFFFFFF; -const uint64_t kMideaACCelsiusBit = 0x0000000020000000; -const uint64_t kMideaACTempMask = 0x0000FFFFE0FFFFFF; -const uint64_t kMideaACFanMask = 0x0000FFC7FFFFFFFF; -const uint64_t kMideaACModeMask = 0x0000FFF8FFFFFFFF; -const uint64_t kMideaACChecksumMask = 0x0000FFFFFFFFFF00; +const uint8_t kMideaACFanOffset = 35; +const uint8_t kMideaACFanSize = 2; // Bits +const uint8_t kMideaACFanAuto = 0; // 0b00 +const uint8_t kMideaACFanLow = 1; // 0b01 +const uint8_t kMideaACFanMed = 2; // 0b10 +const uint8_t kMideaACFanHigh = 3; // 0b11 +const uint8_t kMideaACSleepOffset = 38; +const uint8_t kMideaACPowerOffset = 39; const uint64_t kMideaACToggleSwingV = 0x0000A201FFFFFF7C; // Legacy defines. (Deprecated) diff --git a/lib/IRremoteESP8266-2.7.0/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Mitsubishi.cpp new file mode 100644 index 000000000..7e28fd332 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Mitsubishi.cpp @@ -0,0 +1,1594 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017-2019 David Conran +// Copyright 2019 Mark Kuchel +// Copyright 2018 Denes Varga + +// Mitsubishi + +#include "ir_Mitsubishi.h" +#include +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtext.h" +#include "IRutils.h" +#include "ir_Tcl.h" + +// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote +// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran + +// Constants +// Mitsubishi TV +// period time is 1/33000Hz = 30.303 uSeconds (T) +// Ref: +// GlobalCache's Control Tower's Mitsubishi TV data. +// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp +const uint16_t kMitsubishiTick = 30; +const uint16_t kMitsubishiBitMarkTicks = 10; +const uint16_t kMitsubishiBitMark = kMitsubishiBitMarkTicks * kMitsubishiTick; +const uint16_t kMitsubishiOneSpaceTicks = 70; +const uint16_t kMitsubishiOneSpace = kMitsubishiOneSpaceTicks * kMitsubishiTick; +const uint16_t kMitsubishiZeroSpaceTicks = 30; +const uint16_t kMitsubishiZeroSpace = + kMitsubishiZeroSpaceTicks * kMitsubishiTick; +const uint16_t kMitsubishiMinCommandLengthTicks = 1786; +const uint16_t kMitsubishiMinCommandLength = + kMitsubishiMinCommandLengthTicks * kMitsubishiTick; +const uint16_t kMitsubishiMinGapTicks = 936; +const uint16_t kMitsubishiMinGap = kMitsubishiMinGapTicks * kMitsubishiTick; + +// Mitsubishi Projector (HC3000) +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/441 + +const uint16_t kMitsubishi2HdrMark = 8400; +const uint16_t kMitsubishi2HdrSpace = kMitsubishi2HdrMark / 2; +const uint16_t kMitsubishi2BitMark = 560; +const uint16_t kMitsubishi2ZeroSpace = 520; +const uint16_t kMitsubishi2OneSpace = kMitsubishi2ZeroSpace * 3; +const uint16_t kMitsubishi2MinGap = 28500; + +// Mitsubishi A/C +// Ref: +// https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L84 + +const uint16_t kMitsubishiAcHdrMark = 3400; +const uint16_t kMitsubishiAcHdrSpace = 1750; +const uint16_t kMitsubishiAcBitMark = 450; +const uint16_t kMitsubishiAcOneSpace = 1300; +const uint16_t kMitsubishiAcZeroSpace = 420; +const uint16_t kMitsubishiAcRptMark = 440; +const uint16_t kMitsubishiAcRptSpace = 17100; +const uint8_t kMitsubishiAcExtraTolerance = 5; + +// Mitsubishi 136 bit A/C +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/888 + +const uint16_t kMitsubishi136HdrMark = 3324; +const uint16_t kMitsubishi136HdrSpace = 1474; +const uint16_t kMitsubishi136BitMark = 467; +const uint16_t kMitsubishi136OneSpace = 1137; +const uint16_t kMitsubishi136ZeroSpace = 351; +const uint32_t kMitsubishi136Gap = kDefaultMessageGap; + +// Mitsubishi 112 bit A/C +// Ref: +// https://github.com/kuchel77 + +const uint16_t kMitsubishi112HdrMark = 3450; +const uint16_t kMitsubishi112HdrSpace = 1696; +const uint16_t kMitsubishi112BitMark = 450; +const uint16_t kMitsubishi112OneSpace = 1250; +const uint16_t kMitsubishi112ZeroSpace = 385; +const uint32_t kMitsubishi112Gap = kDefaultMessageGap; +// Total tolerance percentage to use for matching the header mark. +const uint8_t kMitsubishi112HdrMarkTolerance = 5; + + +using irutils::addBoolToString; +using irutils::addFanToString; +using irutils::addIntToString; +using irutils::addLabeledString; +using irutils::addModeToString; +using irutils::addTempToString; +using irutils::minsToString; +using irutils::setBit; +using irutils::setBits; + +#if SEND_MITSUBISHI +// Send a Mitsubishi message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kMitsubishiBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: ALPHA / untested. +// +// Notes: +// This protocol appears to have no header. +// Ref: +// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp +// GlobalCache's Control Tower's Mitsubishi TV data. +void IRsend::sendMitsubishi(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(0, 0, // No Header + kMitsubishiBitMark, kMitsubishiOneSpace, kMitsubishiBitMark, + kMitsubishiZeroSpace, kMitsubishiBitMark, kMitsubishiMinGap, + kMitsubishiMinCommandLength, data, nbits, 33, true, repeat, 50); +} +#endif // SEND_MITSUBISHI + +#if DECODE_MITSUBISHI +// Decode the supplied Mitsubishi message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / previously working. +// +// Notes: +// This protocol appears to have no header. +// +// Ref: +// GlobalCache's Control Tower's Mitsubishi TV data. +bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits, + bool strict) { + if (strict && nbits != kMitsubishiBits) + return false; // Request is out of spec. + + uint16_t offset = kStartOffset; + uint64_t data = 0; + + // Match Data + Footer + if (!matchGeneric(results->rawbuf + offset, &data, + results->rawlen - offset, nbits, + 0, 0, // No header + kMitsubishiBitMark, kMitsubishiOneSpace, + kMitsubishiBitMark, kMitsubishiZeroSpace, + kMitsubishiBitMark, kMitsubishiMinGap, + true, 30)) return false; + // Success + results->decode_type = MITSUBISHI; + results->bits = nbits; + results->value = data; + results->address = 0; + results->command = 0; + return true; +} +#endif // DECODE_MITSUBISHI + +#if SEND_MITSUBISHI2 +// Send a Mitsubishi2 message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kMitsubishiBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: ALPHA / untested. +// +// Notes: +// Based on a Mitsubishi HC3000 projector's remote. +// This protocol appears to have a manditory in-protocol repeat. +// That is in *addition* to the entire message needing to be sent twice +// for the device to accept the command. That is separate from the repeat. +// i.e. Allegedly, the real remote requires the "Off" button pressed twice. +// You will need to add a suitable gap yourself. +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/441 +void IRsend::sendMitsubishi2(uint64_t data, uint16_t nbits, uint16_t repeat) { + for (uint16_t i = 0; i <= repeat; i++) { + // First half of the data. + sendGeneric(kMitsubishi2HdrMark, kMitsubishi2HdrSpace, kMitsubishi2BitMark, + kMitsubishi2OneSpace, kMitsubishi2BitMark, + kMitsubishi2ZeroSpace, kMitsubishi2BitMark, + kMitsubishi2HdrSpace, data >> (nbits / 2), nbits / 2, 33, true, + 0, 50); + // Second half of the data. + sendGeneric(0, 0, // No header for the second data block + kMitsubishi2BitMark, kMitsubishi2OneSpace, kMitsubishi2BitMark, + kMitsubishi2ZeroSpace, kMitsubishi2BitMark, kMitsubishi2MinGap, + data & ((1 << (nbits / 2)) - 1), nbits / 2, 33, true, 0, 50); + } +} +#endif // SEND_MITSUBISHI2 + +#if DECODE_MITSUBISHI2 +// Decode the supplied Mitsubishi2 message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Works with simulated data. +// +// Notes: +// Hardware supported: +// * Mitsubishi HC3000 projector's remote. +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/441 +bool IRrecv::decodeMitsubishi2(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + kHeader + (kFooter * 2) - 1) + return false; // Shorter than shortest possibly expected. + if (strict && nbits != kMitsubishiBits) + return false; // Request is out of spec. + + uint16_t offset = kStartOffset; + results->value = 0; + + // Header + if (!matchMark(results->rawbuf[offset++], kMitsubishi2HdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kMitsubishi2HdrSpace)) + return false; + for (uint8_t i = 0; i < 2; i++) { + // Match Data + Footer + uint16_t used; + uint64_t data = 0; + used = matchGeneric(results->rawbuf + offset, &data, + results->rawlen - offset, nbits / 2, + 0, 0, // No header + kMitsubishi2BitMark, kMitsubishi2OneSpace, + kMitsubishi2BitMark, kMitsubishi2ZeroSpace, + kMitsubishi2BitMark, kMitsubishi2HdrSpace, + i % 2); + if (!used) return false; + offset += used; + results->value <<= (nbits / 2); + results->value |= data; + } + + // Success + results->decode_type = MITSUBISHI2; + results->bits = nbits; + results->address = GETBITS64(results->value, nbits / 2, nbits / 2); + results->command = GETBITS64(results->value, 0, nbits / 2); + return true; +} +#endif // DECODE_MITSUBISHI2 + +#if SEND_MITSUBISHI_AC +// Send a Mitsubishi A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kMitsubishiACStateLength) +// repeat: Nr. of times the message is to be repeated. +// (Default = kMitsubishiACMinRepeat). +// +// Status: BETA / Appears to be working. +// +void IRsend::sendMitsubishiAC(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kMitsubishiACStateLength) + return; // Not enough bytes to send a proper message. + + sendGeneric(kMitsubishiAcHdrMark, kMitsubishiAcHdrSpace, kMitsubishiAcBitMark, + kMitsubishiAcOneSpace, kMitsubishiAcBitMark, + kMitsubishiAcZeroSpace, kMitsubishiAcRptMark, + kMitsubishiAcRptSpace, data, nbytes, 38, false, repeat, 50); +} +#endif // SEND_MITSUBISHI_AC + +#if DECODE_MITSUBISHI_AC +// Decode the supplied Mitsubishi message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Under development +// +// Ref: +// https://www.analysir.com/blog/2015/01/06/reverse-engineering-mitsubishi-ac-infrared-protocol/ +bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < ((kMitsubishiACBits * 2) + 2)) { + DPRINTLN("Shorter than shortest possibly expected."); + return false; // Shorter than shortest possibly expected. + } + if (strict && nbits != kMitsubishiACBits) { + DPRINTLN("Request is out of spec."); + return false; // Request is out of spec. + } + uint16_t offset = kStartOffset; + for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) { + results->state[i] = 0; + } + bool failure = false; + uint8_t rep = 0; + do { + failure = false; + // Header: + // Sometime happens that junk signals arrives before the real message + bool headerFound = false; + while (!headerFound && + offset < (results->rawlen - (kMitsubishiACBits * 2 + 2))) { + headerFound = + matchMark(results->rawbuf[offset], kMitsubishiAcHdrMark) && + matchSpace(results->rawbuf[offset + 1], kMitsubishiAcHdrSpace); + offset += 2; + } + if (!headerFound) { + DPRINTLN("Header mark not found."); + return false; + } + DPRINT("Header mark found at #"); + DPRINTLN(offset - 2); + // Decode byte-by-byte: + match_result_t data_result; + for (uint8_t i = 0; i < kMitsubishiACStateLength && !failure; i++) { + results->state[i] = 0; + data_result = + matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark, + kMitsubishiAcOneSpace, kMitsubishiAcBitMark, + kMitsubishiAcZeroSpace, + _tolerance + kMitsubishiAcExtraTolerance, 0, false); + if (data_result.success == false) { + failure = true; + DPRINT("Byte decode failed at #"); + DPRINTLN((uint16_t)i); + } else { + results->state[i] = data_result.data; + offset += data_result.used; + DPRINT((uint16_t)results->state[i]); + DPRINT(","); + } + DPRINTLN(""); + } + // HEADER validation: + if (failure || results->state[0] != 0x23 || results->state[1] != 0xCB || + results->state[2] != 0x26 || results->state[3] != 0x01 || + results->state[4] != 0x00) { + DPRINTLN("Header mismatch."); + failure = true; + } else { + // DATA part: + + // FOOTER checksum: + if (!IRMitsubishiAC::validChecksum(results->state)) { + DPRINTLN("Checksum error."); + failure = true; + } + } + if (rep != kMitsubishiACMinRepeat && failure) { + bool repeatMarkFound = false; + while (!repeatMarkFound && + offset < (results->rawlen - (kMitsubishiACBits * 2 + 4))) { + repeatMarkFound = + matchMark(results->rawbuf[offset], kMitsubishiAcRptMark) && + matchSpace(results->rawbuf[offset + 1], kMitsubishiAcRptSpace); + offset += 2; + } + if (!repeatMarkFound) { + DPRINTLN("First attempt failure and repeat mark not found."); + return false; + } + } + rep++; + // Check if the repeat is correct if we need strict decode: + if (strict && !failure) { + DPRINTLN("Strict repeat check enabled."); + // Repeat mark and space: + if (!matchMark(results->rawbuf[offset++], kMitsubishiAcRptMark) || + !matchSpace(results->rawbuf[offset++], kMitsubishiAcRptSpace)) { + DPRINTLN("Repeat mark error."); + return false; + } + // Header mark and space: + if (!matchMark(results->rawbuf[offset++], kMitsubishiAcHdrMark) || + !matchSpace(results->rawbuf[offset++], kMitsubishiAcHdrSpace)) { + DPRINTLN("Repeat header error."); + return false; + } + // Payload: + for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) { + data_result = + matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark, + kMitsubishiAcOneSpace, kMitsubishiAcBitMark, + kMitsubishiAcZeroSpace, + _tolerance + kMitsubishiAcExtraTolerance, 0, false); + if (data_result.success == false || + data_result.data != results->state[i]) { + DPRINTLN("Repeat payload error."); + return false; + } + offset += data_result.used; + } + } // strict repeat check + } while (failure && rep <= kMitsubishiACMinRepeat); + results->decode_type = MITSUBISHI_AC; + results->bits = nbits; + return !failure; +} +#endif // DECODE_MITSUBISHI_AC + +// Code to emulate Mitsubishi A/C IR remote control unit. +// Inspired and derived from the work done at: +// https://github.com/r45635/HVAC-IR-Control +// +// Warning: Consider this very alpha code. Seems to work, but not validated. +// +// Equipment it seems compatible with: +// * +// Initialise the object. +IRMitsubishiAC::IRMitsubishiAC(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { this->stateReset(); } + +// Reset the state of the remote to a known good state/sequence. +void IRMitsubishiAC::stateReset(void) { + // The state of the IR remote in IR code form. + // Known good state obtained from: + // https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L108 + static const uint8_t kReset[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, 0x45, 0x67}; + setRaw(kReset); +} + +// Configure the pin for output. +void IRMitsubishiAC::begin(void) { _irsend.begin(); } + +#if SEND_MITSUBISHI_AC +// Send the current desired state to the IR LED. +void IRMitsubishiAC::send(const uint16_t repeat) { + _irsend.sendMitsubishiAC(getRaw(), kMitsubishiACStateLength, repeat); +} +#endif // SEND_MITSUBISHI_AC + +// Return a pointer to the internal state date of the remote. +uint8_t *IRMitsubishiAC::getRaw(void) { + this->checksum(); + return remote_state; +} + +void IRMitsubishiAC::setRaw(const uint8_t *data) { + memcpy(remote_state, data, kMitsubishiACStateLength); +} + +// Calculate the checksum for the current internal state of the remote. +void IRMitsubishiAC::checksum(void) { + remote_state[kMitsubishiACStateLength - 1] = calculateChecksum(remote_state); +} + +bool IRMitsubishiAC::validChecksum(const uint8_t *data) { + return calculateChecksum(data) == data[kMitsubishiACStateLength - 1]; +} + +uint8_t IRMitsubishiAC::calculateChecksum(const uint8_t *data) { + return sumBytes(data, kMitsubishiACStateLength - 1); +} + +// Set the requested power state of the A/C to on. +void IRMitsubishiAC::on(void) { setPower(true); } + +// Set the requested power state of the A/C to off. +void IRMitsubishiAC::off(void) { setPower(false); } + +// Set the requested power state of the A/C. +void IRMitsubishiAC::setPower(bool on) { + setBit(&remote_state[5], kMitsubishiAcPowerOffset, on); +} + +// Return the requested power state of the A/C. +bool IRMitsubishiAC::getPower(void) { + return GETBIT8(remote_state[5], kMitsubishiAcPowerOffset); +} + +// Set the temp. in deg C +void IRMitsubishiAC::setTemp(const uint8_t degrees) { + uint8_t temp = std::max((uint8_t)kMitsubishiAcMinTemp, degrees); + temp = std::min((uint8_t)kMitsubishiAcMaxTemp, temp); + remote_state[7] = temp - kMitsubishiAcMinTemp; +} + +// Return the set temp. in deg C +uint8_t IRMitsubishiAC::getTemp(void) { + return (remote_state[7] + kMitsubishiAcMinTemp); +} + +// Set the speed of the fan, 0-6. +// 0 is auto, 1-5 is the speed, 6 is silent. +void IRMitsubishiAC::setFan(const uint8_t speed) { + uint8_t fan = speed; + // Bounds check + if (fan > kMitsubishiAcFanSilent) + fan = kMitsubishiAcFanMax; // Set the fan to maximum if out of range. + // Auto has a special bit. + setBit(&remote_state[9], kMitsubishiAcFanAutoOffset, + fan == kMitsubishiAcFanAuto); + if (fan >= kMitsubishiAcFanMax) + fan--; // There is no spoon^H^H^Heed 5 (max), pretend it doesn't exist. + setBits(&remote_state[9], kMitsubishiAcFanOffset, kMitsubishiAcFanSize, fan); +} + +// Return the requested state of the unit's fan. +uint8_t IRMitsubishiAC::getFan(void) { + uint8_t fan = GETBITS8(remote_state[9], kMitsubishiAcFanOffset, + kMitsubishiAcFanSize); + if (fan == kMitsubishiAcFanMax) return kMitsubishiAcFanSilent; + return fan; +} + +// Return the requested climate operation mode of the a/c unit. +uint8_t IRMitsubishiAC::getMode(void) { + return GETBITS8(remote_state[6], kMitsubishiAcModeOffset, kModeBitsSize); +} + +// Set the requested climate operation mode of the a/c unit. +void IRMitsubishiAC::setMode(const uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + switch (mode) { + case kMitsubishiAcAuto: remote_state[8] = 0b00110000; break; + case kMitsubishiAcCool: remote_state[8] = 0b00110110; break; + case kMitsubishiAcDry: remote_state[8] = 0b00110010; break; + case kMitsubishiAcHeat: remote_state[8] = 0b00110000; break; + default: + this->setMode(kMitsubishiAcAuto); + return; + } + setBits(&remote_state[6], kMitsubishiAcModeOffset, kModeBitsSize, mode); +} + +// Set the requested vane operation mode of the a/c unit. +void IRMitsubishiAC::setVane(const uint8_t position) { + uint8_t pos = std::min(position, kMitsubishiAcVaneAutoMove); // bounds check + setBit(&remote_state[9], kMitsubishiAcVaneBitOffset); + setBits(&remote_state[9], kMitsubishiAcVaneOffset, kMitsubishiAcVaneSize, + pos); +} + +// Set the requested wide-vane operation mode of the a/c unit. +void IRMitsubishiAC::setWideVane(const uint8_t position) { + setBits(&remote_state[8], kHighNibble, kNibbleSize, + std::min(position, kMitsubishiAcWideVaneAuto)); +} + +// Return the requested vane operation mode of the a/c unit. +uint8_t IRMitsubishiAC::getVane(void) { + return GETBITS8(remote_state[9], kMitsubishiAcVaneOffset, + kMitsubishiAcVaneSize); +} + +// Return the requested wide vane operation mode of the a/c unit. +uint8_t IRMitsubishiAC::getWideVane(void) { + return GETBITS8(remote_state[8], kHighNibble, kNibbleSize); +} + +// Return the clock setting of the message. 1=1/6 hour. e.g. 4pm = 48 +uint8_t IRMitsubishiAC::getClock(void) { return remote_state[10]; } + +// Set the current time. 1 = 1/6 hour. e.g. 6am = 36. +void IRMitsubishiAC::setClock(const uint8_t clock) { + remote_state[10] = clock; +} + +// Return the desired start time. 1 = 1/6 hour. e.g. 1am = 6 +uint8_t IRMitsubishiAC::getStartClock(void) { return remote_state[12]; } + +// Set the desired start time of the AC. 1 = 1/6 hour. e.g. 8pm = 120 +void IRMitsubishiAC::setStartClock(const uint8_t clock) { + remote_state[12] = clock; +} + +// Return the desired stop time of the AC. 1 = 1/6 hour. e.g 10pm = 132 +uint8_t IRMitsubishiAC::getStopClock(void) { return remote_state[11]; } + +// Set the desired stop time of the AC. 1 = 1/6 hour. e.g 10pm = 132 +void IRMitsubishiAC::setStopClock(const uint8_t clock) { + remote_state[11] = clock; +} + +// Return the timer setting. Possible values: kMitsubishiAcNoTimer, +// kMitsubishiAcStartTimer, kMitsubishiAcStopTimer, +// kMitsubishiAcStartStopTimer +uint8_t IRMitsubishiAC::getTimer(void) { + return GETBITS8(remote_state[13], 0, 3); +} + +// Set the timer setting. Possible values: kMitsubishiAcNoTimer, +// kMitsubishiAcStartTimer, kMitsubishiAcStopTimer, +// kMitsubishiAcStartStopTimer +void IRMitsubishiAC::setTimer(uint8_t timer) { + setBits(&remote_state[13], 0, 3, timer); +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRMitsubishiAC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: return kMitsubishiAcCool; + case stdAc::opmode_t::kHeat: return kMitsubishiAcHeat; + case stdAc::opmode_t::kDry: return kMitsubishiAcDry; + default: return kMitsubishiAcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRMitsubishiAC::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: return kMitsubishiAcFanSilent; + case stdAc::fanspeed_t::kLow: return kMitsubishiAcFanRealMax - 3; + case stdAc::fanspeed_t::kMedium: return kMitsubishiAcFanRealMax - 2; + case stdAc::fanspeed_t::kHigh: return kMitsubishiAcFanRealMax - 1; + case stdAc::fanspeed_t::kMax: return kMitsubishiAcFanRealMax; + default: return kMitsubishiAcFanAuto; + } +} + +// Convert a standard A/C vertical swing into its native setting. +uint8_t IRMitsubishiAC::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: return kMitsubishiAcVaneAutoMove - 6; + case stdAc::swingv_t::kHigh: return kMitsubishiAcVaneAutoMove - 5; + case stdAc::swingv_t::kMiddle: return kMitsubishiAcVaneAutoMove - 4; + case stdAc::swingv_t::kLow: return kMitsubishiAcVaneAutoMove - 3; + case stdAc::swingv_t::kLowest: return kMitsubishiAcVaneAutoMove - 2; + case stdAc::swingv_t::kAuto: return kMitsubishiAcVaneAutoMove; + default: return kMitsubishiAcVaneAuto; + } +} + +// Convert a standard A/C wide wane swing into its native setting. +uint8_t IRMitsubishiAC::convertSwingH(const stdAc::swingh_t position) { + switch (position) { + case stdAc::swingh_t::kLeftMax: return kMitsubishiAcWideVaneAuto - 7; + case stdAc::swingh_t::kLeft: return kMitsubishiAcWideVaneAuto - 6; + case stdAc::swingh_t::kMiddle: return kMitsubishiAcWideVaneAuto - 5; + case stdAc::swingh_t::kRight: return kMitsubishiAcWideVaneAuto - 4; + case stdAc::swingh_t::kRightMax: return kMitsubishiAcWideVaneAuto - 3; + case stdAc::swingh_t::kWide: return kMitsubishiAcWideVaneAuto - 2; + case stdAc::swingh_t::kAuto: return kMitsubishiAcWideVaneAuto; + default: return kMitsubishiAcWideVaneAuto - 5; + } +} + +// Convert a native mode to it's common equivalent. +stdAc::opmode_t IRMitsubishiAC::toCommonMode(const uint8_t mode) { + switch (mode) { + case kMitsubishiAcCool: return stdAc::opmode_t::kCool; + case kMitsubishiAcHeat: return stdAc::opmode_t::kHeat; + case kMitsubishiAcDry: return stdAc::opmode_t::kDry; + default: return stdAc::opmode_t::kAuto; + } +} + +// Convert a native fan speed to it's common equivalent. +stdAc::fanspeed_t IRMitsubishiAC::toCommonFanSpeed(const uint8_t speed) { + switch (speed) { + case kMitsubishiAcFanRealMax: return stdAc::fanspeed_t::kMax; + case kMitsubishiAcFanRealMax - 1: return stdAc::fanspeed_t::kHigh; + case kMitsubishiAcFanRealMax - 2: return stdAc::fanspeed_t::kMedium; + case kMitsubishiAcFanRealMax - 3: return stdAc::fanspeed_t::kLow; + case kMitsubishiAcFanSilent: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; + } +} + +// Convert a native vertical swing to it's common equivalent. +stdAc::swingv_t IRMitsubishiAC::toCommonSwingV(const uint8_t pos) { + switch (pos) { + case 1: return stdAc::swingv_t::kHighest; + case 2: return stdAc::swingv_t::kHigh; + case 3: return stdAc::swingv_t::kMiddle; + case 4: return stdAc::swingv_t::kLow; + case 5: return stdAc::swingv_t::kLowest; + default: return stdAc::swingv_t::kAuto; + } +} + +// Convert a native horizontal swing to it's common equivalent. +stdAc::swingh_t IRMitsubishiAC::toCommonSwingH(const uint8_t pos) { + switch (pos) { + case 1: return stdAc::swingh_t::kLeftMax; + case 2: return stdAc::swingh_t::kLeft; + case 3: return stdAc::swingh_t::kMiddle; + case 4: return stdAc::swingh_t::kRight; + case 5: return stdAc::swingh_t::kRightMax; + case 6: return stdAc::swingh_t::kWide; + default: return stdAc::swingh_t::kAuto; + } +} + +// Convert the A/C state to it's common equivalent. +stdAc::state_t IRMitsubishiAC::toCommon(void) { + stdAc::state_t result; + result.protocol = decode_type_t::MITSUBISHI_AC; + result.model = -1; // No models used. + result.power = this->getPower(); + result.mode = this->toCommonMode(this->getMode()); + result.celsius = true; + result.degrees = this->getTemp(); + result.fanspeed = this->toCommonFanSpeed(this->getFan()); + result.swingv = this->toCommonSwingV(this->getVane()); + result.swingh = this->toCommonSwingH(this->getWideVane()); + result.quiet = this->getFan() == kMitsubishiAcFanSilent; + // Not supported. + result.turbo = false; + result.clean = false; + result.econo = false; + result.filter = false; + result.light = false; + result.beep = false; + result.sleep = -1; + result.clock = -1; + return result; +} + +// Convert the internal state into a human readable string. +String IRMitsubishiAC::toString(void) { + String result = ""; + result.reserve(110); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(getMode(), kMitsubishiAcAuto, kMitsubishiAcCool, + kMitsubishiAcHeat, kMitsubishiAcDry, + kMitsubishiAcAuto); + result += addTempToString(getTemp()); + result += addFanToString(getFan(), kMitsubishiAcFanRealMax, + kMitsubishiAcFanRealMax - 3, + kMitsubishiAcFanAuto, kMitsubishiAcFanQuiet, + kMitsubishiAcFanRealMax - 2); + result += addIntToString(this->getVane(), kSwingVStr); + result += kSpaceLBraceStr; + switch (this->getVane()) { + case kMitsubishiAcVaneAuto: result += kAutoStr; break; + case kMitsubishiAcVaneAutoMove: result += kAutoStr + ' ' + kMoveStr; break; + default: result += kUnknownStr; + } + result += ')'; + result += addIntToString(this->getWideVane(), kSwingHStr); + result += kSpaceLBraceStr; + switch (this->getWideVane()) { + case kMitsubishiAcWideVaneAuto: result += kAutoStr; break; + default: result += kUnknownStr; + } + result += ')'; + result += addLabeledString(minsToString(getClock() * 10), kClockStr); + result += addLabeledString(minsToString(getStartClock() * 10), kOnTimerStr); + result += addLabeledString(minsToString(getStopClock() * 10), kOffTimerStr); + result += kCommaSpaceStr + kTimerStr + kColonSpaceStr; + switch (this->getTimer()) { + case kMitsubishiAcNoTimer: + result += '-'; + break; + case kMitsubishiAcStartTimer: + result += kStartStr; + break; + case kMitsubishiAcStopTimer: + result += kStopStr; + break; + case kMitsubishiAcStartStopTimer: + result += kStartStr + '+' + kStopStr; + break; + default: + result += F("? ("); + result += this->getTimer(); + result += ')'; + } + return result; +} + +#if SEND_MITSUBISHI136 +// Send a Mitsubishi136 A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kMitsubishi136StateLength) +// repeat: Nr. of times the message is to be repeated. +// (Default = kMitsubishi136MinRepeat). +// +// Status: ALPHA / Probably working. Needs to be tested against a real device. +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/888 +void IRsend::sendMitsubishi136(const unsigned char data[], + const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kMitsubishi136StateLength) + return; // Not enough bytes to send a proper message. + + sendGeneric(kMitsubishi136HdrMark, kMitsubishi136HdrSpace, + kMitsubishi136BitMark, kMitsubishi136OneSpace, + kMitsubishi136BitMark, kMitsubishi136ZeroSpace, + kMitsubishi136BitMark, kMitsubishi136Gap, + data, nbytes, 38, false, repeat, 50); +} +#endif // SEND_MITSUBISHI136 + +#if DECODE_MITSUBISHI136 +// Decode the supplied Mitsubishi136 message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE / Reported as working. +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/888 +bool IRrecv::decodeMitsubishi136(decode_results *results, const uint16_t nbits, + const bool strict) { + // Too short to match? + if (results->rawlen < (2 * nbits) + kHeader + kFooter - 1) return false; + if (nbits % 8 != 0) return false; // Not a multiple of an 8 bit byte. + if (strict) { // Do checks to see if it matches the spec. + if (nbits != kMitsubishi136Bits) return false; + } + uint16_t used = matchGeneric(results->rawbuf + kStartOffset, results->state, + results->rawlen - kStartOffset, nbits, + kMitsubishi136HdrMark, kMitsubishi136HdrSpace, + kMitsubishi136BitMark, kMitsubishi136OneSpace, + kMitsubishi136BitMark, kMitsubishi136ZeroSpace, + kMitsubishi136BitMark, kMitsubishi136Gap, + true, _tolerance, 0, false); + if (!used) return false; + if (strict) { + // Header validation: Codes start with 0x23CB26 + if (results->state[0] != 0x23 || results->state[1] != 0xCB || + results->state[2] != 0x26) return false; + if (!IRMitsubishi136::validChecksum(results->state, nbits / 8)) + return false; + } + results->decode_type = MITSUBISHI136; + results->bits = nbits; + return true; +} +#endif // DECODE_MITSUBISHI136 + +// Code to emulate Mitsubishi 136bit A/C IR remote control unit. +// +// Equipment it seems compatible with: +// Brand: Mitsubishi Electric, Model: PEAD-RP71JAA Ducted A/C +// Brand: Mitsubishi Electric, Model: 001CP T7WE10714 remote + +// Initialise the object. +IRMitsubishi136::IRMitsubishi136(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { this->stateReset(); } + +// Reset the state of the remote to a known good state/sequence. +void IRMitsubishi136::stateReset(void) { + // The state of the IR remote in IR code form. + // Known good state obtained from: + // https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit#gid=312397579&range=A10 + static const uint8_t kReset[kMitsubishi136StateLength] = { + 0x23, 0xCB, 0x26, 0x21, 0x00, 0x40, 0xC2, 0xC7, 0x04}; + memcpy(remote_state, kReset, kMitsubishi136StateLength); +} + +// Calculate the checksum for the current internal state of the remote. +void IRMitsubishi136::checksum(void) { + for (uint8_t i = 0; i < 6; i++) + remote_state[kMitsubishi136PowerByte + 6 + i] = + ~remote_state[kMitsubishi136PowerByte + i]; +} + +bool IRMitsubishi136::validChecksum(const uint8_t *data, const uint16_t len) { + if (len < kMitsubishi136StateLength) return false; + const uint16_t half = (len - kMitsubishi136PowerByte) / 2; + for (uint8_t i = 0; i < half; i++) { + // This variable is needed to avoid the warning: (known compiler issue) + // warning: comparison of promoted ~unsigned with unsigned [-Wsign-compare] + const uint8_t inverted = ~data[kMitsubishi136PowerByte + half + i]; + if (data[kMitsubishi136PowerByte + i] != inverted) return false; + } + return true; +} + +// Configure the pin for output. +void IRMitsubishi136::begin(void) { _irsend.begin(); } + +#if SEND_MITSUBISHI136 +// Send the current desired state to the IR LED. +void IRMitsubishi136::send(const uint16_t repeat) { + _irsend.sendMitsubishi136(getRaw(), kMitsubishi136StateLength, repeat); +} +#endif // SEND_MITSUBISHI136 + +// Return a pointer to the internal state date of the remote. +uint8_t *IRMitsubishi136::getRaw(void) { + checksum(); + return remote_state; +} + +void IRMitsubishi136::setRaw(const uint8_t *data) { + memcpy(remote_state, data, kMitsubishi136StateLength); +} + +// Set the requested power state of the A/C to off. +void IRMitsubishi136::on(void) { setPower(true); } + +// Set the requested power state of the A/C to off. +void IRMitsubishi136::off(void) { setPower(false); } + +// Set the requested power state of the A/C. +void IRMitsubishi136::setPower(bool on) { + setBit(&remote_state[kMitsubishi136PowerByte], kMitsubishi136PowerOffset, on); +} + +// Return the requested power state of the A/C. +bool IRMitsubishi136::getPower(void) { + return GETBIT8(remote_state[kMitsubishi136PowerByte], + kMitsubishi136PowerOffset); +} + +// Set the temp. in deg C +void IRMitsubishi136::setTemp(const uint8_t degrees) { + uint8_t temp = std::max((uint8_t)kMitsubishi136MinTemp, degrees); + temp = std::min((uint8_t)kMitsubishi136MaxTemp, temp); + setBits(&remote_state[kMitsubishi136TempByte], kHighNibble, kNibbleSize, + temp - kMitsubishiAcMinTemp); +} + +// Return the set temp. in deg C +uint8_t IRMitsubishi136::getTemp(void) { + return GETBITS8(remote_state[kMitsubishi136TempByte], kHighNibble, + kNibbleSize) + kMitsubishiAcMinTemp; +} + +void IRMitsubishi136::setFan(const uint8_t speed) { + setBits(&remote_state[kMitsubishi136FanByte], kMitsubishi136FanOffset, + kMitsubishi136FanSize, std::min(speed, kMitsubishi136FanMax)); +} + +// Return the requested state of the unit's fan. +uint8_t IRMitsubishi136::getFan(void) { + return GETBITS8(remote_state[kMitsubishi136FanByte], kMitsubishi136FanOffset, + kMitsubishi136FanSize); +} + +// Return the requested climate operation mode of the a/c unit. +uint8_t IRMitsubishi136::getMode(void) { + return GETBITS8(remote_state[kMitsubishi136ModeByte], + kMitsubishi136ModeOffset, kModeBitsSize); +} + +// Set the requested climate operation mode of the a/c unit. +void IRMitsubishi136::setMode(const uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + switch (mode) { + case kMitsubishi136Fan: + case kMitsubishi136Cool: + case kMitsubishi136Heat: + case kMitsubishi136Auto: + case kMitsubishi136Dry: + setBits(&remote_state[kMitsubishi136ModeByte], kMitsubishi136ModeOffset, + kModeBitsSize, mode); + break; + default: + setMode(kMitsubishi136Auto); + } +} + +// Set the requested vane operation mode of the a/c unit. +void IRMitsubishi136::setSwingV(const uint8_t position) { + // If we get an unexpected mode, default to auto. + switch (position) { + case kMitsubishi136SwingVLowest: + case kMitsubishi136SwingVLow: + case kMitsubishi136SwingVHigh: + case kMitsubishi136SwingVHighest: + case kMitsubishi136SwingVAuto: + setBits(&remote_state[kMitsubishi136SwingVByte], kHighNibble, kNibbleSize, + position); + break; + default: + setMode(kMitsubishi136SwingVAuto); + } +} + +// Return the requested vane operation mode of the a/c unit. +uint8_t IRMitsubishi136::getSwingV(void) { + return GETBITS8(remote_state[kMitsubishi136SwingVByte], kHighNibble, + kNibbleSize); +} + +// Emulate a quiet setting. There is no true quiet setting on this a/c +void IRMitsubishi136::setQuiet(bool on) { + if (on) setFan(kMitsubishi136FanQuiet); + else if (getQuiet()) setFan(kMitsubishi136FanLow); +} + +// Return the requested power state of the A/C. +bool IRMitsubishi136::getQuiet(void) { + return getFan() == kMitsubishi136FanQuiet; +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRMitsubishi136::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: return kMitsubishi136Cool; + case stdAc::opmode_t::kHeat: return kMitsubishi136Heat; + case stdAc::opmode_t::kDry: return kMitsubishi136Dry; + case stdAc::opmode_t::kFan: return kMitsubishi136Fan; + default: return kMitsubishi136Auto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRMitsubishi136::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: return kMitsubishi136FanMin; + case stdAc::fanspeed_t::kLow: return kMitsubishi136FanLow; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: return kMitsubishi136FanMax; + default: return kMitsubishi136FanMed; + } +} + +// Convert a standard A/C vertical swing into its native setting. +uint8_t IRMitsubishi136::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: return kMitsubishi136SwingVHighest; + case stdAc::swingv_t::kHigh: + case stdAc::swingv_t::kMiddle: return kMitsubishi136SwingVHigh; + case stdAc::swingv_t::kLow: return kMitsubishi136SwingVLow; + case stdAc::swingv_t::kLowest: return kMitsubishi136SwingVLowest; + default: return kMitsubishi136SwingVAuto; + } +} + +// Convert a native mode to it's common equivalent. +stdAc::opmode_t IRMitsubishi136::toCommonMode(const uint8_t mode) { + switch (mode) { + case kMitsubishi136Cool: return stdAc::opmode_t::kCool; + case kMitsubishi136Heat: return stdAc::opmode_t::kHeat; + case kMitsubishi136Dry: return stdAc::opmode_t::kDry; + case kMitsubishi136Fan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; + } +} + +// Convert a native fan speed to it's common equivalent. +stdAc::fanspeed_t IRMitsubishi136::toCommonFanSpeed(const uint8_t speed) { + switch (speed) { + case kMitsubishi136FanMax: return stdAc::fanspeed_t::kMax; + case kMitsubishi136FanMed: return stdAc::fanspeed_t::kMedium; + case kMitsubishi136FanLow: return stdAc::fanspeed_t::kLow; + case kMitsubishi136FanMin: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kMedium; + } +} + +// Convert a native vertical swing to it's common equivalent. +stdAc::swingv_t IRMitsubishi136::toCommonSwingV(const uint8_t pos) { + switch (pos) { + case kMitsubishi136SwingVHighest: return stdAc::swingv_t::kHighest; + case kMitsubishi136SwingVHigh: return stdAc::swingv_t::kHigh; + case kMitsubishi136SwingVLow: return stdAc::swingv_t::kLow; + case kMitsubishi136SwingVLowest: return stdAc::swingv_t::kLowest; + default: return stdAc::swingv_t::kAuto; + } +} + +// Convert the A/C state to it's common equivalent. +stdAc::state_t IRMitsubishi136::toCommon(void) { + stdAc::state_t result; + result.protocol = decode_type_t::MITSUBISHI136; + result.model = -1; // No models used. + result.power = this->getPower(); + result.mode = this->toCommonMode(this->getMode()); + result.celsius = true; + result.degrees = this->getTemp(); + result.fanspeed = this->toCommonFanSpeed(this->getFan()); + result.swingv = this->toCommonSwingV(this->getSwingV()); + result.quiet = this->getQuiet(); + // Not supported. + result.swingh = stdAc::swingh_t::kOff; + result.turbo = false; + result.clean = false; + result.econo = false; + result.filter = false; + result.light = false; + result.beep = false; + result.sleep = -1; + result.clock = -1; + return result; +} + +// Convert the internal state into a human readable string. +String IRMitsubishi136::toString(void) { + String result = ""; + result.reserve(80); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(getMode(), kMitsubishi136Auto, kMitsubishi136Cool, + kMitsubishi136Heat, kMitsubishi136Dry, + kMitsubishi136Fan); + result += addTempToString(getTemp()); + result += addFanToString(getFan(), kMitsubishi136FanMax, + kMitsubishi136FanLow, kMitsubishi136FanMax, + kMitsubishi136FanQuiet, kMitsubishi136FanMed); + result += addIntToString(getSwingV(), kSwingVStr); + result += kSpaceLBraceStr; + switch (getSwingV()) { + case kMitsubishi136SwingVHighest: result += kHighestStr; break; + case kMitsubishi136SwingVHigh: result += kHighStr; break; + case kMitsubishi136SwingVLow: result += kLowStr; break; + case kMitsubishi136SwingVLowest: result += kLowestStr; break; + case kMitsubishi136SwingVAuto: result += kAutoStr; break; + default: result += kUnknownStr; + } + result += ')'; + result += addBoolToString(getQuiet(), kQuietStr); + return result; +} + + +#if SEND_MITSUBISHI112 +// Send a Mitsubishi112 A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kMitsubishi112StateLength) +// repeat: Nr. of times the message is to be repeated. +// (Default = kMitsubishi112MinRepeat). +// +// Status: Stable / Reported as working. +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/947 +void IRsend::sendMitsubishi112(const unsigned char data[], + const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kMitsubishi112StateLength) + return; // Not enough bytes to send a proper message. + + sendGeneric(kMitsubishi112HdrMark, kMitsubishi112HdrSpace, + kMitsubishi112BitMark, kMitsubishi112OneSpace, + kMitsubishi112BitMark, kMitsubishi112ZeroSpace, + kMitsubishi112BitMark, kMitsubishi112Gap, + data, nbytes, 38, false, repeat, 50); +} +#endif // SEND_MITSUBISHI112 + +#if DECODE_MITSUBISHI112 || DECODE_TCL112AC +// Decode the supplied Mitsubishi112 / Tcl112Ac message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE / Reported as working. +// +// Note: Mitsubishi112 & Tcl112Ac are basically the same protocol. +// The only significant difference I can see is Mitsubishi112 has a +// slightly longer header mark. We will use that to determine which +// varient it should be. The other differences require full decoding and +// only only with certain settings. +// There are some other timing differences too, but the tolerances will +// overlap. +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/619 +// https://github.com/crankyoldgit/IRremoteESP8266/issues/947 +bool IRrecv::decodeMitsubishi112(decode_results *results, const uint16_t nbits, + const bool strict) { + if (results->rawlen < ((2 * nbits) + kHeader + kFooter - 1)) return false; + if (nbits % 8 != 0) return false; // Not a multiple of an 8 bit byte. + if (strict) { // Do checks to see if it matches the spec. + if (nbits != kMitsubishi112Bits && nbits != kTcl112AcBits) return false; + } + uint16_t offset = kStartOffset; + decode_type_t typeguess = decode_type_t::UNKNOWN; + uint16_t hdrspace; + uint16_t bitmark; + uint16_t onespace; + uint16_t zerospace; + uint32_t gap; + uint8_t tolerance = _tolerance; + + // Header +#if DECODE_MITSUBISHI112 + if (matchMark(results->rawbuf[offset], kMitsubishi112HdrMark, + kMitsubishi112HdrMarkTolerance, 0)) { + typeguess = decode_type_t::MITSUBISHI112; + hdrspace = kMitsubishi112HdrSpace; + bitmark = kMitsubishi112BitMark; + onespace = kMitsubishi112OneSpace; + zerospace = kMitsubishi112ZeroSpace; + gap = kMitsubishi112Gap; + } +#endif // DECODE_MITSUBISHI112 +#if DECODE_TCL112AC + if (typeguess == decode_type_t::UNKNOWN && // We didn't match Mitsubishi112 + matchMark(results->rawbuf[offset], kTcl112AcHdrMark, + kTcl112AcHdrMarkTolerance, 0)) { + typeguess = decode_type_t::TCL112AC; + hdrspace = kTcl112AcHdrSpace; + bitmark = kTcl112AcBitMark; + onespace = kTcl112AcOneSpace; + zerospace = kTcl112AcZeroSpace; + gap = kTcl112AcGap; + tolerance += kTcl112AcTolerance; + } +#endif // DECODE_TCL112AC + if (typeguess == decode_type_t::UNKNOWN) return false; // No header matched. + offset++; + + uint16_t used = matchGeneric(results->rawbuf + offset, results->state, + results->rawlen - offset, nbits, + 0, // Skip the header as we matched it earlier. + hdrspace, bitmark, onespace, bitmark, zerospace, + bitmark, gap, + true, tolerance, 0, false); + if (!used) return false; + if (strict) { + // Header validation: Codes start with 0x23CB26 + if (results->state[0] != 0x23 || results->state[1] != 0xCB || + results->state[2] != 0x26) return false; + // TCL112 and MITSUBISHI112 share the exact same checksum. + if (!IRTcl112Ac::validChecksum(results->state, nbits / 8)) return false; + } + // Success + results->decode_type = typeguess; + results->bits = nbits; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_MITSUBISHI112 || DECODE_TCL112AC + +// Code to emulate Mitsubishi 112bit A/C IR remote control unit. +// +// Equipment it seems compatible with: +// Brand: Mitsubishi Electric, Model: MSH-A24WV / MUH-A24WV A/C +// Brand: Mitsubishi Electric, Model: KPOA remote + +// Initialise the object. +IRMitsubishi112::IRMitsubishi112(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { this->stateReset(); } + +// Reset the state of the remote to a known good state/sequence. +void IRMitsubishi112::stateReset(void) { + const uint8_t kReset[kMitsubishi112StateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, 0x0B, 0x10, + 0x00, 0x00, 0x00, 0x30}; + setRaw(kReset); +} + +// Calculate the checksum for the current internal state of the remote. +void IRMitsubishi112::checksum(void) { + remote_state[kMitsubishi112StateLength - 1] = IRTcl112Ac::calcChecksum( + remote_state, kMitsubishi112StateLength); +} + +// Configure the pin for output. +void IRMitsubishi112::begin(void) { _irsend.begin(); } + +#if SEND_MITSUBISHI112 +// Send the current desired state to the IR LED. +void IRMitsubishi112::send(const uint16_t repeat) { + _irsend.sendMitsubishi112(getRaw(), kMitsubishi112StateLength, repeat); +} +#endif // SEND_MITSUBISHI112 + +// Return a pointer to the internal state date of the remote. +uint8_t *IRMitsubishi112::getRaw(void) { + checksum(); + return remote_state; +} + +void IRMitsubishi112::setRaw(const uint8_t *data) { + memcpy(remote_state, data, kMitsubishi112StateLength); +} + +// Set the requested power state of the A/C to off. +void IRMitsubishi112::on(void) { setPower(true); } + +// Set the requested power state of the A/C to off. +void IRMitsubishi112::off(void) { setPower(false); } + +// Set the requested power state of the A/C. +void IRMitsubishi112::setPower(bool on) { + setBit(&remote_state[kMitsubishi112PowerByte], kMitsubishi112PowerOffset, on); +} + +// Return the requested power state of the A/C. +bool IRMitsubishi112::getPower(void) { + return GETBIT8(remote_state[kMitsubishi112PowerByte], + kMitsubishi112PowerOffset); +} + +// Set the temp. in deg C +void IRMitsubishi112::setTemp(const uint8_t degrees) { + uint8_t temp = std::max((uint8_t)kMitsubishi112MinTemp, degrees); + temp = std::min((uint8_t)kMitsubishi112MaxTemp, temp); + setBits(&remote_state[kMitsubishi112TempByte], kLowNibble, + kMitsubishi112TempSize, kMitsubishiAcMaxTemp - temp); +} + +// Return the set temp. in deg C +uint8_t IRMitsubishi112::getTemp(void) { + return kMitsubishiAcMaxTemp - GETBITS8(remote_state[kMitsubishi112TempByte], + kLowNibble, kMitsubishi112TempSize); +} + +void IRMitsubishi112::setFan(const uint8_t speed) { + switch (speed) { + case kMitsubishi112FanMin: + case kMitsubishi112FanLow: + case kMitsubishi112FanMed: + case kMitsubishi112FanMax: + setBits(&remote_state[kMitsubishi112FanByte], kMitsubishi112FanOffset, + kMitsubishi112FanSize, speed); + break; + default: + setFan(kMitsubishi112FanMax); + } +} + +// Return the requested state of the unit's fan. +uint8_t IRMitsubishi112::getFan(void) { + return GETBITS8(remote_state[kMitsubishi112FanByte], kMitsubishi112FanOffset, + kMitsubishi112FanSize); +} + +// Return the requested climate operation mode of the a/c unit. +uint8_t IRMitsubishi112::getMode(void) { + return GETBITS8(remote_state[kMitsubishi112ModeByte], + kMitsubishi112ModeOffset, kModeBitsSize); +} + +// Set the requested climate operation mode of the a/c unit. +void IRMitsubishi112::setMode(const uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + switch (mode) { + // Note: No Fan Only mode. + case kMitsubishi112Cool: + case kMitsubishi112Heat: + case kMitsubishi112Auto: + case kMitsubishi112Dry: + setBits(&remote_state[kMitsubishi112ModeByte], kMitsubishi112ModeOffset, + kModeBitsSize, mode); + break; + default: + setMode(kMitsubishi112Auto); + } +} + +// Set the requested vane operation mode of the a/c unit. +void IRMitsubishi112::setSwingV(const uint8_t position) { + // If we get an unexpected mode, default to auto. + switch (position) { + case kMitsubishi112SwingVLowest: + case kMitsubishi112SwingVLow: + case kMitsubishi112SwingVMiddle: + case kMitsubishi112SwingVHigh: + case kMitsubishi112SwingVHighest: + case kMitsubishi112SwingVAuto: + setBits(&remote_state[kMitsubishi112SwingVByte], + kMitsubishi112SwingVOffset, kMitsubishi112SwingVSize, position); + break; + default: + setMode(kMitsubishi112SwingVAuto); + } +} + +// Return the requested vane operation mode of the a/c unit. +uint8_t IRMitsubishi112::getSwingV(void) { + return GETBITS8(remote_state[kMitsubishi112SwingVByte], + kMitsubishi112SwingVOffset, kMitsubishi112SwingVSize); +} + +// Set the requested vane operation mode of the a/c unit. +void IRMitsubishi112::setSwingH(const uint8_t position) { + // If we get an unexpected mode, default to auto. + switch (position) { + case kMitsubishi112SwingHLeftMax: + case kMitsubishi112SwingHLeft: + case kMitsubishi112SwingHMiddle: + case kMitsubishi112SwingHRight: + case kMitsubishi112SwingHRightMax: + case kMitsubishi112SwingHWide: + case kMitsubishi112SwingHAuto: + setBits(&remote_state[kMitsubishi112SwingHByte], + kMitsubishi112SwingHOffset, kMitsubishi112SwingHSize, position); + break; + default: + setSwingH(kMitsubishi112SwingHAuto); + } +} + +// Return the requested vane operation mode of the a/c unit. +uint8_t IRMitsubishi112::getSwingH(void) { + return GETBITS8(remote_state[kMitsubishi112SwingHByte], + kMitsubishi112SwingHOffset, kMitsubishi112SwingHSize); +} + +// Emulate a quiet setting. There is no true quiet setting on this a/c +void IRMitsubishi112::setQuiet(bool on) { + if (on) + setFan(kMitsubishi112FanQuiet); + else if (getQuiet()) setFan(kMitsubishi112FanLow); +} + +// Return the requested power state of the A/C. +bool IRMitsubishi112::getQuiet(void) { + return getFan() == kMitsubishi112FanQuiet; +} + + +// Convert a standard A/C mode into its native mode. +uint8_t IRMitsubishi112::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: return kMitsubishi112Cool; + case stdAc::opmode_t::kHeat: return kMitsubishi112Heat; + case stdAc::opmode_t::kDry: return kMitsubishi112Dry; + // Note: No Fan Only mode. + default: return kMitsubishi112Auto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRMitsubishi112::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: return kMitsubishi112FanMin; + case stdAc::fanspeed_t::kLow: return kMitsubishi112FanLow; + case stdAc::fanspeed_t::kMedium: return kMitsubishi112FanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: return kMitsubishi112FanMax; + default: return kMitsubishi112FanMed; + } +} + +// Convert a standard A/C vertical swing into its native setting. +uint8_t IRMitsubishi112::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: return kMitsubishi112SwingVHighest; + case stdAc::swingv_t::kHigh: return kMitsubishi112SwingVHigh; + case stdAc::swingv_t::kMiddle: return kMitsubishi112SwingVMiddle; + case stdAc::swingv_t::kLow: return kMitsubishi112SwingVLow; + case stdAc::swingv_t::kLowest: return kMitsubishi112SwingVLowest; + default: return kMitsubishi112SwingVAuto; + } +} + +// Convert a standard A/C vertical swing into its native setting. +uint8_t IRMitsubishi112::convertSwingH(const stdAc::swingh_t position) { + switch (position) { + case stdAc::swingh_t::kLeftMax: return kMitsubishi112SwingHLeftMax; + case stdAc::swingh_t::kLeft: return kMitsubishi112SwingHLeft; + case stdAc::swingh_t::kMiddle: return kMitsubishi112SwingHMiddle; + case stdAc::swingh_t::kRight: return kMitsubishi112SwingHRight; + case stdAc::swingh_t::kRightMax: return kMitsubishi112SwingHRightMax; + case stdAc::swingh_t::kWide: return kMitsubishi112SwingHWide; + case stdAc::swingh_t::kAuto: return kMitsubishi112SwingHAuto; + default: return kMitsubishi112SwingHAuto; + } +} + +// Convert a native mode to it's common equivalent. +stdAc::opmode_t IRMitsubishi112::toCommonMode(const uint8_t mode) { + switch (mode) { + case kMitsubishi112Cool: return stdAc::opmode_t::kCool; + case kMitsubishi112Heat: return stdAc::opmode_t::kHeat; + case kMitsubishi112Dry: return stdAc::opmode_t::kDry; + default: return stdAc::opmode_t::kAuto; + } +} + +// Convert a native fan speed to it's common equivalent. +stdAc::fanspeed_t IRMitsubishi112::toCommonFanSpeed(const uint8_t speed) { + switch (speed) { + case kMitsubishi112FanMax: return stdAc::fanspeed_t::kMax; + case kMitsubishi112FanMed: return stdAc::fanspeed_t::kMedium; + case kMitsubishi112FanLow: return stdAc::fanspeed_t::kLow; + case kMitsubishi112FanMin: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kMedium; + } +} + +// Convert a native vertical swing to it's common equivalent. +stdAc::swingv_t IRMitsubishi112::toCommonSwingV(const uint8_t pos) { + switch (pos) { + case kMitsubishi112SwingVHighest: return stdAc::swingv_t::kHighest; + case kMitsubishi112SwingVHigh: return stdAc::swingv_t::kHigh; + case kMitsubishi112SwingVMiddle: return stdAc::swingv_t::kMiddle; + case kMitsubishi112SwingVLow: return stdAc::swingv_t::kLow; + case kMitsubishi112SwingVLowest: return stdAc::swingv_t::kLowest; + default: return stdAc::swingv_t::kAuto; + } +} + +// Convert a native vertical swing to it's common equivalent. +stdAc::swingh_t IRMitsubishi112::toCommonSwingH(const uint8_t pos) { + switch (pos) { + case kMitsubishi112SwingHLeftMax: return stdAc::swingh_t::kLeftMax; + case kMitsubishi112SwingHLeft: return stdAc::swingh_t::kLeft; + case kMitsubishi112SwingHMiddle: return stdAc::swingh_t::kMiddle; + case kMitsubishi112SwingHRight: return stdAc::swingh_t::kRight; + case kMitsubishi112SwingHRightMax: return stdAc::swingh_t::kRightMax; + case kMitsubishi112SwingHWide: return stdAc::swingh_t::kWide; + default: return stdAc::swingh_t::kAuto; + } +} + + +// Convert the A/C state to it's common equivalent. +stdAc::state_t IRMitsubishi112::toCommon(void) { + stdAc::state_t result; + result.protocol = decode_type_t::MITSUBISHI112; + result.model = -1; // No models used. + result.power = this->getPower(); + result.mode = this->toCommonMode(this->getMode()); + result.celsius = true; + result.degrees = this->getTemp(); + result.fanspeed = this->toCommonFanSpeed(this->getFan()); + result.swingv = this->toCommonSwingV(this->getSwingV()); + result.swingh = this->toCommonSwingH(this->getSwingH());; + result.quiet = this->getQuiet(); + // Not supported. + result.econo = false; // Need to figure this part from stdAc + result.clock = -1; + result.sleep = -1; + result.turbo = false; + result.clean = false; + result.filter = false; + result.light = false; + result.beep = false; + + + return result; +} + +// Convert the internal state into a human readable string. +String IRMitsubishi112::toString(void) { + String result = ""; + result.reserve(80); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(getMode(), kMitsubishi112Auto, kMitsubishi112Cool, + kMitsubishi112Heat, kMitsubishi112Dry, + kMitsubishi112Auto); + result += addTempToString(getTemp()); + result += addFanToString(getFan(), kMitsubishi112FanMax, + kMitsubishi112FanLow, kMitsubishi112FanMax, + kMitsubishi112FanQuiet, kMitsubishi112FanMed); + result += addIntToString(getSwingV(), kSwingVStr); + result += kSpaceLBraceStr; + switch (getSwingV()) { + case kMitsubishi112SwingVHighest: result += kHighestStr; break; + case kMitsubishi112SwingVHigh: result += kHighStr; break; + case kMitsubishi112SwingVMiddle: result += kMiddleStr; break; + case kMitsubishi112SwingVLow: result += kLowStr; break; + case kMitsubishi112SwingVLowest: result += kLowestStr; break; + case kMitsubishi112SwingVAuto: result += kAutoStr; break; + default: result += kUnknownStr; + } + result += ')'; + result += addIntToString(getSwingH(), kSwingHStr); + result += kSpaceLBraceStr; + switch (getSwingH()) { + case kMitsubishi112SwingHLeftMax: result += kLeftMaxStr; break; + case kMitsubishi112SwingHLeft: result += kLeftStr; break; + case kMitsubishi112SwingHMiddle: result += kMiddleStr; break; + case kMitsubishi112SwingHRight: result += kRightStr; break; + case kMitsubishi112SwingHRightMax: result += kRightMaxStr; break; + case kMitsubishi112SwingHWide: result += kWideStr; break; + case kMitsubishi112SwingHAuto: result += kAutoStr; break; + default: result += kUnknownStr; + } + result += ')'; + result += addBoolToString(getQuiet(), kQuietStr); + return result; +} diff --git a/lib/IRremoteESP8266-2.7.0/src/ir_Mitsubishi.h b/lib/IRremoteESP8266-2.7.0/src/ir_Mitsubishi.h new file mode 100644 index 000000000..31021514f --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Mitsubishi.h @@ -0,0 +1,312 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017-2019 David Conran +// Copyright 2019 Mark Kuchel + +// Mitsubishi + +// Supports: +// Brand: Mitsubishi, Model: TV +// Brand: Mitsubishi, Model: HC3000 Projector +// Brand: Mitsubishi, Model: MS-GK24VA A/C +// Brand: Mitsubishi, Model: KM14A 0179213 remote +// Brand: Mitsubishi Electric, Model: PEAD-RP71JAA Ducted A/C +// Brand: Mitsubishi Electric, Model: 001CP T7WE10714 remote +// Brand: Mitsubishi Electric, Model: MSH-A24WV / MUH-A24WV A/C +// Brand: Mitsubishi Electric, Model: KPOA remote + +#ifndef IR_MITSUBISHI_H_ +#define IR_MITSUBISHI_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote +// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran + +// Constants +const uint8_t kMitsubishiAcModeOffset = 3; +const uint8_t kMitsubishiAcAuto = 0b100; +const uint8_t kMitsubishiAcCool = 0b011; +const uint8_t kMitsubishiAcDry = 0b010; +const uint8_t kMitsubishiAcHeat = 0b001; +const uint8_t kMitsubishiAcPowerOffset = 5; +const uint8_t kMitsubishiAcPower = 1 << kMitsubishiAcPowerOffset; // 0x20 +const uint8_t kMitsubishiAcFanOffset = 0; +const uint8_t kMitsubishiAcFanSize = 3; // Mask 0b111 +const uint8_t kMitsubishiAcFanAuto = 0; +const uint8_t kMitsubishiAcFanAutoOffset = 7; +const uint8_t kMitsubishiAcFanMax = 5; +const uint8_t kMitsubishiAcFanRealMax = 4; +const uint8_t kMitsubishiAcFanSilent = 6; +const uint8_t kMitsubishiAcFanQuiet = kMitsubishiAcFanSilent; +const uint8_t kMitsubishiAcMinTemp = 16; // 16C +const uint8_t kMitsubishiAcMaxTemp = 31; // 31C +const uint8_t kMitsubishiAcVaneBitOffset = 6; +const uint8_t kMitsubishiAcVaneOffset = 3; +const uint8_t kMitsubishiAcVaneSize = 3; +const uint8_t kMitsubishiAcVaneAuto = 0; +const uint8_t kMitsubishiAcVaneAutoMove = 7; +const uint8_t kMitsubishiAcNoTimer = 0; +const uint8_t kMitsubishiAcStartTimer = 5; +const uint8_t kMitsubishiAcStopTimer = 3; +const uint8_t kMitsubishiAcStartStopTimer = 7; +const uint8_t kMitsubishiAcWideVaneAuto = 8; + +const uint8_t kMitsubishi136PowerByte = 5; +const uint8_t kMitsubishi136PowerOffset = 6; +const uint8_t kMitsubishi136PowerBit = 1 << kMitsubishi136PowerOffset; +const uint8_t kMitsubishi136TempByte = 6; +const uint8_t kMitsubishi136MinTemp = 17; // 17C +const uint8_t kMitsubishi136MaxTemp = 30; // 30C +const uint8_t kMitsubishi136ModeByte = kMitsubishi136TempByte; +const uint8_t kMitsubishi136ModeOffset = 0; +const uint8_t kMitsubishi136Fan = 0b000; +const uint8_t kMitsubishi136Cool = 0b001; +const uint8_t kMitsubishi136Heat = 0b010; +const uint8_t kMitsubishi136Auto = 0b011; +const uint8_t kMitsubishi136Dry = 0b101; +const uint8_t kMitsubishi136SwingVByte = 7; +const uint8_t kMitsubishi136SwingVLowest = 0b0000; +const uint8_t kMitsubishi136SwingVLow = 0b0001; +const uint8_t kMitsubishi136SwingVHigh = 0b0010; +const uint8_t kMitsubishi136SwingVHighest = 0b0011; +const uint8_t kMitsubishi136SwingVAuto = 0b1100; +const uint8_t kMitsubishi136FanByte = kMitsubishi136SwingVByte; +// FanMask = 0b00000110; +const uint8_t kMitsubishi136FanOffset = 1; +const uint8_t kMitsubishi136FanSize = 2; // Bits +const uint8_t kMitsubishi136FanMin = 0b00; +const uint8_t kMitsubishi136FanLow = 0b01; +const uint8_t kMitsubishi136FanMed = 0b10; +const uint8_t kMitsubishi136FanMax = 0b11; +const uint8_t kMitsubishi136FanQuiet = kMitsubishi136FanMin; + +// Mitsubishi112 + +// remote_state[5] +const uint8_t kMitsubishi112PowerByte = 5; +const uint8_t kMitsubishi112PowerOffset = 2; // 0b00000100 +// remote_state[6] +const uint8_t kMitsubishi112ModeByte = 6; +const uint8_t kMitsubishi112ModeOffset = 0; // Mask 0b00000111 +const uint8_t kMitsubishi112Cool = 0b011; +const uint8_t kMitsubishi112Heat = 0b001; +const uint8_t kMitsubishi112Auto = 0b111; +const uint8_t kMitsubishi112Dry = 0b010; +// remote_state[7] +const uint8_t kMitsubishi112TempByte = 7; +const uint8_t kMitsubishi112TempSize = 4; // Mask 0b00001111 +const uint8_t kMitsubishi112MinTemp = 16; // 16C +const uint8_t kMitsubishi112MaxTemp = 31; // 31C +// remote_state[8] +const uint8_t kMitsubishi112FanByte = 8; +const uint8_t kMitsubishi112FanOffset = 0; // Mask 0b00000111; +const uint8_t kMitsubishi112FanSize = 3; +const uint8_t kMitsubishi112FanMin = 0b010; +const uint8_t kMitsubishi112FanLow = 0b011; +const uint8_t kMitsubishi112FanMed = 0b101; +const uint8_t kMitsubishi112FanMax = 0b000; +const uint8_t kMitsubishi112FanQuiet = kMitsubishi112FanMin; +const uint8_t kMitsubishi112SwingVByte = kMitsubishi112FanByte; +const uint8_t kMitsubishi112SwingVOffset = 3; // Mask 0b00111000 +const uint8_t kMitsubishi112SwingVSize = 3; // Mask 0b00111000 +const uint8_t kMitsubishi112SwingVLowest = 0b101; +const uint8_t kMitsubishi112SwingVLow = 0b100; +const uint8_t kMitsubishi112SwingVMiddle = 0b011; +const uint8_t kMitsubishi112SwingVHigh = 0b010; +const uint8_t kMitsubishi112SwingVHighest = 0b001; +const uint8_t kMitsubishi112SwingVAuto = 0b111; +// remote_state[12] +const uint8_t kMitsubishi112SwingHByte = 12; +const uint8_t kMitsubishi112SwingHSize = 4; +const uint8_t kMitsubishi112SwingHOffset = 2; // Mask 0b00111100 +const uint8_t kMitsubishi112SwingHLeftMax = 0b0001; +const uint8_t kMitsubishi112SwingHLeft = 0b0010; +const uint8_t kMitsubishi112SwingHMiddle = 0b0011; +const uint8_t kMitsubishi112SwingHRight = 0b0100; +const uint8_t kMitsubishi112SwingHRightMax = 0b0101; +const uint8_t kMitsubishi112SwingHWide = 0b1000; +const uint8_t kMitsubishi112SwingHAuto = 0b1100; + +// Legacy defines (Deprecated) +#define MITSUBISHI_AC_VANE_AUTO_MOVE kMitsubishiAcVaneAutoMove +#define MITSUBISHI_AC_VANE_AUTO kMitsubishiAcVaneAuto +#define MITSUBISHI_AC_POWER kMitsubishiAcPower +#define MITSUBISHI_AC_MIN_TEMP kMitsubishiAcMinTemp +#define MITSUBISHI_AC_MAX_TEMP kMitsubishiAcMaxTemp +#define MITSUBISHI_AC_HEAT kMitsubishiAcHeat +#define MITSUBISHI_AC_FAN_SILENT kMitsubishiAcFanSilent +#define MITSUBISHI_AC_FAN_REAL_MAX kMitsubishiAcFanRealMax +#define MITSUBISHI_AC_FAN_MAX kMitsubishiAcFanMax +#define MITSUBISHI_AC_FAN_AUTO kMitsubishiAcFanAuto +#define MITSUBISHI_AC_DRY kMitsubishiAcDry +#define MITSUBISHI_AC_COOL kMitsubishiAcCool +#define MITSUBISHI_AC_AUTO kMitsubishiAcAuto + +class IRMitsubishiAC { + public: + explicit IRMitsubishiAC(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); + void stateReset(void); + static bool validChecksum(const uint8_t* data); +#if SEND_MITSUBISHI_AC + void send(const uint16_t repeat = kMitsubishiACMinRepeat); + uint8_t calibrate(void) { return _irsend.calibrate(); } +#endif // SEND_MITSUBISHI_AC + void begin(void); + void on(void); + void off(void); + void setPower(const bool on); + bool getPower(void); + void setTemp(const uint8_t degrees); + uint8_t getTemp(void); + void setFan(const uint8_t speed); + uint8_t getFan(void); + void setMode(const uint8_t mode); + uint8_t getMode(void); + void setVane(const uint8_t position); + void setWideVane(const uint8_t position); + uint8_t getVane(void); + uint8_t getWideVane(void); + uint8_t* getRaw(void); + void setRaw(const uint8_t* data); + uint8_t getClock(void); + void setClock(const uint8_t clock); + uint8_t getStartClock(void); + void setStartClock(const uint8_t clock); + uint8_t getStopClock(void); + void setStopClock(const uint8_t clock); + uint8_t getTimer(void); + void setTimer(const uint8_t timer); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + static uint8_t convertSwingV(const stdAc::swingv_t position); + static uint8_t convertSwingH(const stdAc::swingh_t position); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); + static stdAc::swingv_t toCommonSwingV(const uint8_t pos); + static stdAc::swingh_t toCommonSwingH(const uint8_t pos); + stdAc::state_t toCommon(void); + String toString(void); +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + uint8_t remote_state[kMitsubishiACStateLength]; + void checksum(void); + static uint8_t calculateChecksum(const uint8_t* data); +}; + +class IRMitsubishi136 { + public: + explicit IRMitsubishi136(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); + + + void stateReset(void); +#if SEND_MITSUBISHI136 + void send(const uint16_t repeat = kMitsubishi136MinRepeat); + uint8_t calibrate(void) { return _irsend.calibrate(); } +#endif // SEND_MITSUBISHI136 + void begin(void); + static bool validChecksum(const uint8_t* data, + const uint16_t len = kMitsubishi136StateLength); + void on(void); + void off(void); + void setPower(const bool on); + bool getPower(void); + void setTemp(const uint8_t degrees); + uint8_t getTemp(void); + void setFan(const uint8_t speed); + uint8_t getFan(void); + void setMode(const uint8_t mode); + uint8_t getMode(void); + void setSwingV(const uint8_t position); + uint8_t getSwingV(void); + void setQuiet(const bool on); + bool getQuiet(void); + uint8_t* getRaw(void); + void setRaw(const uint8_t* data); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + static uint8_t convertSwingV(const stdAc::swingv_t position); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); + static stdAc::swingv_t toCommonSwingV(const uint8_t pos); + stdAc::state_t toCommon(void); + String toString(void); +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + uint8_t remote_state[kMitsubishi136StateLength]; + void checksum(void); +}; + + +class IRMitsubishi112 { + public: + explicit IRMitsubishi112(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); + + + void stateReset(void); +#if SEND_MITSUBISHI112 + void send(const uint16_t repeat = kMitsubishi112MinRepeat); + uint8_t calibrate(void) { return _irsend.calibrate(); } +#endif // SEND_MITSUBISHI112 + void begin(void); + void on(void); + void off(void); + void setPower(const bool on); + bool getPower(void); + void setTemp(const uint8_t degrees); + uint8_t getTemp(void); + void setFan(const uint8_t speed); + uint8_t getFan(void); + void setMode(const uint8_t mode); + uint8_t getMode(void); + void setSwingV(const uint8_t position); + uint8_t getSwingV(void); + void setSwingH(const uint8_t position); + uint8_t getSwingH(void); + void setQuiet(const bool on); + bool getQuiet(void); + uint8_t* getRaw(void); + void setRaw(const uint8_t* data); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + static uint8_t convertSwingV(const stdAc::swingv_t position); + static uint8_t convertSwingH(const stdAc::swingh_t position); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); + static stdAc::swingv_t toCommonSwingV(const uint8_t pos); + static stdAc::swingh_t toCommonSwingH(const uint8_t pos); + stdAc::state_t toCommon(void); + String toString(void); +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + uint8_t remote_state[kMitsubishi112StateLength]; + void checksum(void); +}; + +#endif // IR_MITSUBISHI_H_ diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_MitsubishiHeavy.cpp old mode 100755 new mode 100644 similarity index 63% rename from lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_MitsubishiHeavy.cpp index 6b4295991..35ba18548 --- a/lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_MitsubishiHeavy.cpp @@ -15,7 +15,9 @@ #include "ir_MitsubishiHeavy.h" #include +#include #include "IRremoteESP8266.h" +#include "IRtext.h" #include "IRutils.h" #ifndef ARDUINO #include @@ -39,6 +41,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_MITSUBISHIHEAVY // Send a MitsubishiHeavy 88 bit A/C message. @@ -94,10 +98,9 @@ void IRMitsubishiHeavy152Ac::send(const uint16_t repeat) { #endif // SEND_MITSUBISHIHEAVY void IRMitsubishiHeavy152Ac::stateReset(void) { - uint8_t i = 0; - for (; i < kMitsubishiHeavySigLength; i++) - remote_state[i] = kMitsubishiHeavyZmsSig[i]; - for (; i < kMitsubishiHeavy152StateLength - 3; i += 2) remote_state[i] = 0; + memcpy(remote_state, kMitsubishiHeavyZmsSig, kMitsubishiHeavySigLength); + for (uint8_t i = kMitsubishiHeavySigLength; + i < kMitsubishiHeavy152StateLength - 3; i += 2) remote_state[i] = 0; remote_state[17] = 0x80; } @@ -107,40 +110,32 @@ uint8_t *IRMitsubishiHeavy152Ac::getRaw(void) { } void IRMitsubishiHeavy152Ac::setRaw(const uint8_t *data) { - for (uint8_t i = 0; i < kMitsubishiHeavy152StateLength; i++) - remote_state[i] = data[i]; + memcpy(remote_state, data, kMitsubishiHeavy152StateLength); } -void IRMitsubishiHeavy152Ac::on(void) { - remote_state[5] |= kMitsubishiHeavyPowerBit; -} +void IRMitsubishiHeavy152Ac::on(void) { setPower(true); } -void IRMitsubishiHeavy152Ac::off(void) { - remote_state[5] &= ~kMitsubishiHeavyPowerBit; -} +void IRMitsubishiHeavy152Ac::off(void) { setPower(false); } void IRMitsubishiHeavy152Ac::setPower(const bool on) { - if (on) - this->on(); - else - this->off(); + setBit(&remote_state[5], kMitsubishiHeavyPowerOffset, on); } bool IRMitsubishiHeavy152Ac::getPower(void) { - return remote_state[5] & kMitsubishiHeavyPowerBit; + return GETBIT8(remote_state[5], kMitsubishiHeavyPowerOffset); } void IRMitsubishiHeavy152Ac::setTemp(const uint8_t temp) { uint8_t newtemp = temp; newtemp = std::min(newtemp, kMitsubishiHeavyMaxTemp); newtemp = std::max(newtemp, kMitsubishiHeavyMinTemp); - - remote_state[7] &= ~kMitsubishiHeavyTempMask; - remote_state[7] |= newtemp - kMitsubishiHeavyMinTemp; + setBits(&remote_state[7], kLowNibble, kNibbleSize, + newtemp - kMitsubishiHeavyMinTemp); } uint8_t IRMitsubishiHeavy152Ac::getTemp(void) { - return (remote_state[7] & kMitsubishiHeavyTempMask) + kMitsubishiHeavyMinTemp; + return GETBITS8(remote_state[7], kLowNibble, kNibbleSize) + + kMitsubishiHeavyMinTemp; } // Set the speed of the fan @@ -152,17 +147,14 @@ void IRMitsubishiHeavy152Ac::setFan(const uint8_t speed) { case kMitsubishiHeavy152FanHigh: case kMitsubishiHeavy152FanMax: case kMitsubishiHeavy152FanEcono: - case kMitsubishiHeavy152FanTurbo: - break; - default: - newspeed = kMitsubishiHeavy152FanAuto; + case kMitsubishiHeavy152FanTurbo: break; + default: newspeed = kMitsubishiHeavy152FanAuto; } - remote_state[9] &= ~kMitsubishiHeavyFanMask; - remote_state[9] |= newspeed; + setBits(&remote_state[9], kLowNibble, kNibbleSize, newspeed); } uint8_t IRMitsubishiHeavy152Ac::getFan(void) { - return remote_state[9] & kMitsubishiHeavyFanMask; + return GETBITS8(remote_state[9], kLowNibble, kNibbleSize); } void IRMitsubishiHeavy152Ac::setMode(const uint8_t mode) { @@ -176,43 +168,39 @@ void IRMitsubishiHeavy152Ac::setMode(const uint8_t mode) { default: newmode = kMitsubishiHeavyAuto; } - remote_state[5] &= ~kMitsubishiHeavyModeMask; - remote_state[5] |= newmode; + setBits(&remote_state[5], kMitsubishiHeavyModeOffset, kModeBitsSize, newmode); } uint8_t IRMitsubishiHeavy152Ac::getMode(void) { - return remote_state[5] & kMitsubishiHeavyModeMask; + return GETBITS8(remote_state[5], kMitsubishiHeavyModeOffset, kModeBitsSize); } void IRMitsubishiHeavy152Ac::setSwingVertical(const uint8_t pos) { - uint8_t newpos = std::min(pos, kMitsubishiHeavy152SwingVOff); - remote_state[11] &= ~kMitsubishiHeavy152SwingVMask; - remote_state[11] |= (newpos << 5); + setBits(&remote_state[11], kMitsubishiHeavy152SwingVOffset, + kMitsubishiHeavy152SwingVSize, + std::min(pos, kMitsubishiHeavy152SwingVOff)); } uint8_t IRMitsubishiHeavy152Ac::getSwingVertical(void) { - return remote_state[11] >> 5; + return GETBITS8(remote_state[11], kMitsubishiHeavy152SwingVOffset, + kMitsubishiHeavy152SwingVSize); } void IRMitsubishiHeavy152Ac::setSwingHorizontal(const uint8_t pos) { - uint8_t newpos = std::min(pos, kMitsubishiHeavy152SwingHOff); - remote_state[13] &= ~kMitsubishiHeavy152SwingHMask; - remote_state[13] |= (newpos & kMitsubishiHeavy152SwingHMask); + setBits(&remote_state[13], kLowNibble, kNibbleSize, + std::min(pos, kMitsubishiHeavy152SwingHOff)); } uint8_t IRMitsubishiHeavy152Ac::getSwingHorizontal(void) { - return remote_state[13] & kMitsubishiHeavy152SwingHMask; + return GETBITS8(remote_state[13], kLowNibble, kNibbleSize); } void IRMitsubishiHeavy152Ac::setNight(const bool on) { - if (on) - remote_state[15] |= kMitsubishiHeavyNightBit; - else - remote_state[15] &= ~kMitsubishiHeavyNightBit; + setBit(&remote_state[15], kMitsubishiHeavyNightOffset, on); } bool IRMitsubishiHeavy152Ac::getNight(void) { - return remote_state[15] & kMitsubishiHeavyNightBit; + return GETBIT8(remote_state[15], kMitsubishiHeavyNightOffset); } void IRMitsubishiHeavy152Ac::set3D(const bool on) { @@ -227,37 +215,28 @@ bool IRMitsubishiHeavy152Ac::get3D(void) { } void IRMitsubishiHeavy152Ac::setSilent(const bool on) { - if (on) - remote_state[15] |= kMitsubishiHeavySilentBit; - else - remote_state[15] &= ~kMitsubishiHeavySilentBit; + setBit(&remote_state[15], kMitsubishiHeavySilentOffset, on); } bool IRMitsubishiHeavy152Ac::getSilent(void) { - return remote_state[15] & kMitsubishiHeavySilentBit; + return GETBIT8(remote_state[15], kMitsubishiHeavySilentOffset); } void IRMitsubishiHeavy152Ac::setFilter(const bool on) { - if (on) - remote_state[5] |= kMitsubishiHeavyFilterBit; - else - remote_state[5] &= ~kMitsubishiHeavyFilterBit; + setBit(&remote_state[5], kMitsubishiHeavyFilterOffset, on); } bool IRMitsubishiHeavy152Ac::getFilter(void) { - return remote_state[5] & kMitsubishiHeavyFilterBit; + return GETBIT8(remote_state[5], kMitsubishiHeavyFilterOffset); } void IRMitsubishiHeavy152Ac::setClean(const bool on) { this->setFilter(on); - if (on) - remote_state[5] |= kMitsubishiHeavyCleanBit; - else - remote_state[5] &= ~kMitsubishiHeavyCleanBit; + setBit(&remote_state[5], kMitsubishiHeavyCleanOffset, on); } bool IRMitsubishiHeavy152Ac::getClean(void) { - return remote_state[5] & kMitsubishiHeavyCleanBit && this->getFilter(); + return GETBIT8(remote_state[5], kMitsubishiHeavyCleanOffset) && getFilter(); } void IRMitsubishiHeavy152Ac::setTurbo(const bool on) { @@ -314,74 +293,50 @@ bool IRMitsubishiHeavy152Ac::validChecksum(const uint8_t *state, // Convert a standard A/C mode into its native mode. uint8_t IRMitsubishiHeavy152Ac::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kMitsubishiHeavyCool; - case stdAc::opmode_t::kHeat: - return kMitsubishiHeavyHeat; - case stdAc::opmode_t::kDry: - return kMitsubishiHeavyDry; - case stdAc::opmode_t::kFan: - return kMitsubishiHeavyFan; - default: - return kMitsubishiHeavyAuto; + case stdAc::opmode_t::kCool: return kMitsubishiHeavyCool; + case stdAc::opmode_t::kHeat: return kMitsubishiHeavyHeat; + case stdAc::opmode_t::kDry: return kMitsubishiHeavyDry; + case stdAc::opmode_t::kFan: return kMitsubishiHeavyFan; + default: return kMitsubishiHeavyAuto; } } // Convert a standard A/C Fan speed into its native fan speed. uint8_t IRMitsubishiHeavy152Ac::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { - case stdAc::fanspeed_t::kMin: - return kMitsubishiHeavy152FanEcono; // Assumes Econo is slower than Low. - case stdAc::fanspeed_t::kLow: - return kMitsubishiHeavy152FanLow; - case stdAc::fanspeed_t::kMedium: - return kMitsubishiHeavy152FanMed; - case stdAc::fanspeed_t::kHigh: - return kMitsubishiHeavy152FanHigh; - case stdAc::fanspeed_t::kMax: - return kMitsubishiHeavy152FanMax; - default: - return kMitsubishiHeavy152FanAuto; + // Assumes Econo is slower than Low. + case stdAc::fanspeed_t::kMin: return kMitsubishiHeavy152FanEcono; + case stdAc::fanspeed_t::kLow: return kMitsubishiHeavy152FanLow; + case stdAc::fanspeed_t::kMedium: return kMitsubishiHeavy152FanMed; + case stdAc::fanspeed_t::kHigh: return kMitsubishiHeavy152FanHigh; + case stdAc::fanspeed_t::kMax: return kMitsubishiHeavy152FanMax; + default: return kMitsubishiHeavy152FanAuto; } } // Convert a standard A/C vertical swing into its native setting. uint8_t IRMitsubishiHeavy152Ac::convertSwingV(const stdAc::swingv_t position) { switch (position) { - case stdAc::swingv_t::kAuto: - return kMitsubishiHeavy152SwingVAuto; - case stdAc::swingv_t::kHighest: - return kMitsubishiHeavy152SwingVHighest; - case stdAc::swingv_t::kHigh: - return kMitsubishiHeavy152SwingVHigh; - case stdAc::swingv_t::kMiddle: - return kMitsubishiHeavy152SwingVMiddle; - case stdAc::swingv_t::kLow: - return kMitsubishiHeavy152SwingVLow; - case stdAc::swingv_t::kLowest: - return kMitsubishiHeavy152SwingVLowest; - default: - return kMitsubishiHeavy152SwingVOff; + case stdAc::swingv_t::kAuto: return kMitsubishiHeavy152SwingVAuto; + case stdAc::swingv_t::kHighest: return kMitsubishiHeavy152SwingVHighest; + case stdAc::swingv_t::kHigh: return kMitsubishiHeavy152SwingVHigh; + case stdAc::swingv_t::kMiddle: return kMitsubishiHeavy152SwingVMiddle; + case stdAc::swingv_t::kLow: return kMitsubishiHeavy152SwingVLow; + case stdAc::swingv_t::kLowest: return kMitsubishiHeavy152SwingVLowest; + default: return kMitsubishiHeavy152SwingVOff; } } // Convert a standard A/C horizontal swing into its native setting. uint8_t IRMitsubishiHeavy152Ac::convertSwingH(const stdAc::swingh_t position) { switch (position) { - case stdAc::swingh_t::kAuto: - return kMitsubishiHeavy152SwingHAuto; - case stdAc::swingh_t::kLeftMax: - return kMitsubishiHeavy152SwingHLeftMax; - case stdAc::swingh_t::kLeft: - return kMitsubishiHeavy152SwingHLeft; - case stdAc::swingh_t::kMiddle: - return kMitsubishiHeavy152SwingHMiddle; - case stdAc::swingh_t::kRight: - return kMitsubishiHeavy152SwingHRight; - case stdAc::swingh_t::kRightMax: - return kMitsubishiHeavy152SwingHRightMax; - default: - return kMitsubishiHeavy152SwingHOff; + case stdAc::swingh_t::kAuto: return kMitsubishiHeavy152SwingHAuto; + case stdAc::swingh_t::kLeftMax: return kMitsubishiHeavy152SwingHLeftMax; + case stdAc::swingh_t::kLeft: return kMitsubishiHeavy152SwingHLeft; + case stdAc::swingh_t::kMiddle: return kMitsubishiHeavy152SwingHMiddle; + case stdAc::swingh_t::kRight: return kMitsubishiHeavy152SwingHRight; + case stdAc::swingh_t::kRightMax: return kMitsubishiHeavy152SwingHRightMax; + default: return kMitsubishiHeavy152SwingHOff; } } @@ -390,34 +345,34 @@ stdAc::opmode_t IRMitsubishiHeavy152Ac::toCommonMode(const uint8_t mode) { switch (mode) { case kMitsubishiHeavyCool: return stdAc::opmode_t::kCool; case kMitsubishiHeavyHeat: return stdAc::opmode_t::kHeat; - case kMitsubishiHeavyDry: return stdAc::opmode_t::kDry; - case kMitsubishiHeavyFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kMitsubishiHeavyDry: return stdAc::opmode_t::kDry; + case kMitsubishiHeavyFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } // Convert a native fan speed to it's common equivalent. stdAc::fanspeed_t IRMitsubishiHeavy152Ac::toCommonFanSpeed(const uint8_t spd) { switch (spd) { - case kMitsubishiHeavy152FanMax: return stdAc::fanspeed_t::kMax; - case kMitsubishiHeavy152FanHigh: return stdAc::fanspeed_t::kHigh; - case kMitsubishiHeavy152FanMed: return stdAc::fanspeed_t::kMedium; - case kMitsubishiHeavy152FanLow: return stdAc::fanspeed_t::kLow; + case kMitsubishiHeavy152FanMax: return stdAc::fanspeed_t::kMax; + case kMitsubishiHeavy152FanHigh: return stdAc::fanspeed_t::kHigh; + case kMitsubishiHeavy152FanMed: return stdAc::fanspeed_t::kMedium; + case kMitsubishiHeavy152FanLow: return stdAc::fanspeed_t::kLow; case kMitsubishiHeavy152FanEcono: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + default: return stdAc::fanspeed_t::kAuto; } } // Convert a native vertical swing to it's common equivalent. stdAc::swingh_t IRMitsubishiHeavy152Ac::toCommonSwingH(const uint8_t pos) { switch (pos) { - case kMitsubishiHeavy152SwingHLeftMax: return stdAc::swingh_t::kLeftMax; - case kMitsubishiHeavy152SwingHLeft: return stdAc::swingh_t::kLeft; - case kMitsubishiHeavy152SwingHMiddle: return stdAc::swingh_t::kMiddle; - case kMitsubishiHeavy152SwingHRight: return stdAc::swingh_t::kRight; + case kMitsubishiHeavy152SwingHLeftMax: return stdAc::swingh_t::kLeftMax; + case kMitsubishiHeavy152SwingHLeft: return stdAc::swingh_t::kLeft; + case kMitsubishiHeavy152SwingHMiddle: return stdAc::swingh_t::kMiddle; + case kMitsubishiHeavy152SwingHRight: return stdAc::swingh_t::kRight; case kMitsubishiHeavy152SwingHRightMax: return stdAc::swingh_t::kRightMax; - case kMitsubishiHeavy152SwingHOff: return stdAc::swingh_t::kOff; - default: return stdAc::swingh_t::kAuto; + case kMitsubishiHeavy152SwingHOff: return stdAc::swingh_t::kOff; + default: return stdAc::swingh_t::kAuto; } } @@ -425,12 +380,12 @@ stdAc::swingh_t IRMitsubishiHeavy152Ac::toCommonSwingH(const uint8_t pos) { stdAc::swingv_t IRMitsubishiHeavy152Ac::toCommonSwingV(const uint8_t pos) { switch (pos) { case kMitsubishiHeavy152SwingVHighest: return stdAc::swingv_t::kHighest; - case kMitsubishiHeavy152SwingVHigh: return stdAc::swingv_t::kHigh; - case kMitsubishiHeavy152SwingVMiddle: return stdAc::swingv_t::kMiddle; - case kMitsubishiHeavy152SwingVLow: return stdAc::swingv_t::kLow; - case kMitsubishiHeavy152SwingVLowest: return stdAc::swingv_t::kLowest; - case kMitsubishiHeavy152SwingVOff: return stdAc::swingv_t::kOff; - default: return stdAc::swingv_t::kAuto; + case kMitsubishiHeavy152SwingVHigh: return stdAc::swingv_t::kHigh; + case kMitsubishiHeavy152SwingVMiddle: return stdAc::swingv_t::kMiddle; + case kMitsubishiHeavy152SwingVLow: return stdAc::swingv_t::kLow; + case kMitsubishiHeavy152SwingVLowest: return stdAc::swingv_t::kLowest; + case kMitsubishiHeavy152SwingVOff: return stdAc::swingv_t::kOff; + default: return stdAc::swingv_t::kAuto; } } @@ -463,104 +418,108 @@ stdAc::state_t IRMitsubishiHeavy152Ac::toCommon(void) { String IRMitsubishiHeavy152Ac::toString(void) { String result = ""; result.reserve(180); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kMitsubishiHeavyAuto, kMitsubishiHeavyCool, kMitsubishiHeavyHeat, kMitsubishiHeavyDry, kMitsubishiHeavyFan); result += addTempToString(getTemp()); - result += addIntToString(getFan(), F("Fan")); - result += F(" ("); + result += addIntToString(getFan(), kFanStr); + result += kSpaceLBraceStr; switch (this->getFan()) { case kMitsubishiHeavy152FanAuto: - result += F("Auto"); + result += kAutoStr; break; case kMitsubishiHeavy152FanHigh: - result += F("High"); + result += kHighStr; break; case kMitsubishiHeavy152FanLow: - result += F("Low"); + result += kLowStr; break; case kMitsubishiHeavy152FanMed: - result += F("Medium"); + result += kMedStr; break; case kMitsubishiHeavy152FanMax: - result += F("Max"); + result += kMaxStr; break; case kMitsubishiHeavy152FanEcono: - result += F("Econo"); + result += kEconoStr; break; case kMitsubishiHeavy152FanTurbo: - result += F("Turbo"); + result += kTurboStr; break; default: - result += F("UNKNOWN"); + result += kUnknownStr; } result += ')'; - result += addIntToString(getSwingVertical(), F("Swing (V)")); + result += addIntToString(getSwingVertical(), kSwingVStr); + result += kSpaceLBraceStr; switch (this->getSwingVertical()) { case kMitsubishiHeavy152SwingVAuto: - result += F(" (Auto)"); + result += kAutoStr; break; case kMitsubishiHeavy152SwingVHighest: - result += F(" (Highest)"); + result += kHighestStr; break; case kMitsubishiHeavy152SwingVHigh: - result += F(" (High)"); + result += kHighStr; break; case kMitsubishiHeavy152SwingVMiddle: - result += F(" (Middle)"); + result += kMiddleStr; break; case kMitsubishiHeavy152SwingVLow: - result += F(" (Low)"); + result += kLowStr; break; case kMitsubishiHeavy152SwingVLowest: - result += F(" (Lowest)"); + result += kLowestStr; break; case kMitsubishiHeavy152SwingVOff: - result += F(" (Off)"); + result += kOffStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } - result += addIntToString(getSwingHorizontal(), F("Swing (H)")); + result += ')'; + result += addIntToString(getSwingHorizontal(), kSwingHStr); + result += kSpaceLBraceStr; switch (this->getSwingHorizontal()) { case kMitsubishiHeavy152SwingHAuto: - result += F(" (Auto)"); + result += kAutoStr; break; case kMitsubishiHeavy152SwingHLeftMax: - result += F(" (Max Left)"); + result += kMaxLeftStr; break; case kMitsubishiHeavy152SwingHLeft: - result += F(" (Left)"); + result += kLeftStr; break; case kMitsubishiHeavy152SwingHMiddle: - result += F(" (Middle)"); + result += kMiddleStr; break; case kMitsubishiHeavy152SwingHRight: - result += F(" (Right)"); + result += kRightStr; break; case kMitsubishiHeavy152SwingHRightMax: - result += F(" (Max Right)"); + result += kMaxRightStr; break; case kMitsubishiHeavy152SwingHLeftRight: - result += F(" (Left Right)"); + result += kLeftStr + ' ' + kRightStr; break; case kMitsubishiHeavy152SwingHRightLeft: - result += F(" (Right Left)"); + result += kRightStr + ' ' + kLeftStr; break; case kMitsubishiHeavy152SwingHOff: - result += F(" (Off)"); + result += kOffStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } - result += addBoolToString(getSilent(), F("Silent")); - result += addBoolToString(getTurbo(), F("Turbo")); - result += addBoolToString(getEcono(), F("Econo")); - result += addBoolToString(getNight(), F("Night")); - result += addBoolToString(getFilter(), F("Filter")); - result += addBoolToString(get3D(), F("3D")); - result += addBoolToString(getClean(), F("Clean")); + result += ')'; + result += addBoolToString(getSilent(), kSilentStr); + result += addBoolToString(getTurbo(), kTurboStr); + result += addBoolToString(getEcono(), kEconoStr); + result += addBoolToString(getNight(), kNightStr); + result += addBoolToString(getFilter(), kFilterStr); + result += addBoolToString(get3D(), k3DStr); + result += addBoolToString(getClean(), kCleanStr); return result; } @@ -581,10 +540,9 @@ void IRMitsubishiHeavy88Ac::send(const uint16_t repeat) { #endif // SEND_MITSUBISHIHEAVY void IRMitsubishiHeavy88Ac::stateReset(void) { - uint8_t i = 0; - for (; i < kMitsubishiHeavySigLength; i++) - remote_state[i] = kMitsubishiHeavyZjsSig[i]; - for (; i < kMitsubishiHeavy88StateLength; i++) remote_state[i] = 0; + memcpy(remote_state, kMitsubishiHeavyZjsSig, kMitsubishiHeavySigLength); + for (uint8_t i = kMitsubishiHeavySigLength; i < kMitsubishiHeavy88StateLength; + i++) remote_state[i] = 0; } uint8_t *IRMitsubishiHeavy88Ac::getRaw(void) { @@ -593,40 +551,32 @@ uint8_t *IRMitsubishiHeavy88Ac::getRaw(void) { } void IRMitsubishiHeavy88Ac::setRaw(const uint8_t *data) { - for (uint8_t i = 0; i < kMitsubishiHeavy88StateLength; i++) - remote_state[i] = data[i]; + memcpy(remote_state, data, kMitsubishiHeavy88StateLength); } -void IRMitsubishiHeavy88Ac::on(void) { - remote_state[9] |= kMitsubishiHeavyPowerBit; -} +void IRMitsubishiHeavy88Ac::on(void) { setPower(true); } -void IRMitsubishiHeavy88Ac::off(void) { - remote_state[9] &= ~kMitsubishiHeavyPowerBit; -} +void IRMitsubishiHeavy88Ac::off(void) { setPower(false); } void IRMitsubishiHeavy88Ac::setPower(const bool on) { - if (on) - this->on(); - else - this->off(); + setBit(&remote_state[9], kMitsubishiHeavyPowerOffset, on); } bool IRMitsubishiHeavy88Ac::getPower(void) { - return remote_state[9] & kMitsubishiHeavyPowerBit; + return GETBIT8(remote_state[9], kMitsubishiHeavyPowerOffset); } void IRMitsubishiHeavy88Ac::setTemp(const uint8_t temp) { uint8_t newtemp = temp; newtemp = std::min(newtemp, kMitsubishiHeavyMaxTemp); newtemp = std::max(newtemp, kMitsubishiHeavyMinTemp); - - remote_state[9] &= kMitsubishiHeavyTempMask; - remote_state[9] |= ((newtemp - kMitsubishiHeavyMinTemp) << 4); + setBits(&remote_state[9], kHighNibble, kNibbleSize, + newtemp - kMitsubishiHeavyMinTemp); } uint8_t IRMitsubishiHeavy88Ac::getTemp(void) { - return (remote_state[9] >> 4) + kMitsubishiHeavyMinTemp; + return GETBITS8(remote_state[9], kHighNibble, kNibbleSize) + + kMitsubishiHeavyMinTemp; } // Set the speed of the fan @@ -637,17 +587,16 @@ void IRMitsubishiHeavy88Ac::setFan(const uint8_t speed) { case kMitsubishiHeavy88FanMed: case kMitsubishiHeavy88FanHigh: case kMitsubishiHeavy88FanTurbo: - case kMitsubishiHeavy88FanEcono: - break; - default: - newspeed = kMitsubishiHeavy88FanAuto; + case kMitsubishiHeavy88FanEcono: break; + default: newspeed = kMitsubishiHeavy88FanAuto; } - remote_state[7] &= ~kMitsubishiHeavy88FanMask; - remote_state[7] |= (newspeed << 5); + setBits(&remote_state[7], kMitsubishiHeavy88FanOffset, + kMitsubishiHeavy88FanSize, newspeed); } uint8_t IRMitsubishiHeavy88Ac::getFan(void) { - return remote_state[7] >> 5; + return GETBITS8(remote_state[7], kMitsubishiHeavy88FanOffset, + kMitsubishiHeavy88FanSize); } void IRMitsubishiHeavy88Ac::setMode(const uint8_t mode) { @@ -661,12 +610,11 @@ void IRMitsubishiHeavy88Ac::setMode(const uint8_t mode) { default: newmode = kMitsubishiHeavyAuto; } - remote_state[9] &= ~kMitsubishiHeavyModeMask; - remote_state[9] |= newmode; + setBits(&remote_state[9], kMitsubishiHeavyModeOffset, kModeBitsSize, newmode); } uint8_t IRMitsubishiHeavy88Ac::getMode(void) { - return remote_state[9] & kMitsubishiHeavyModeMask; + return GETBITS8(remote_state[9], kMitsubishiHeavyModeOffset, kModeBitsSize); } void IRMitsubishiHeavy88Ac::setSwingVertical(const uint8_t pos) { @@ -677,21 +625,22 @@ void IRMitsubishiHeavy88Ac::setSwingVertical(const uint8_t pos) { case kMitsubishiHeavy88SwingVHigh: case kMitsubishiHeavy88SwingVMiddle: case kMitsubishiHeavy88SwingVLow: - case kMitsubishiHeavy88SwingVLowest: - newpos = pos; - break; - default: - newpos = kMitsubishiHeavy88SwingVOff; + case kMitsubishiHeavy88SwingVLowest: newpos = pos; break; + default: newpos = kMitsubishiHeavy88SwingVOff; } - remote_state[5] &= ~kMitsubishiHeavy88SwingVMaskByte5; - remote_state[5] |= (newpos & kMitsubishiHeavy88SwingVMaskByte5); - remote_state[7] &= ~kMitsubishiHeavy88SwingVMaskByte7; - remote_state[7] |= (newpos & kMitsubishiHeavy88SwingVMaskByte7); + setBit(&remote_state[5], kMitsubishiHeavy88SwingVByte5Offset, + newpos & 1); + setBits(&remote_state[7], kMitsubishiHeavy88SwingVByte7Offset, + kMitsubishiHeavy88SwingVByte7Size, + newpos >> kMitsubishiHeavy88SwingVByte5Size); } uint8_t IRMitsubishiHeavy88Ac::getSwingVertical(void) { - return (remote_state[5] & kMitsubishiHeavy88SwingVMaskByte5) | - (remote_state[7] & kMitsubishiHeavy88SwingVMaskByte7); + return GETBITS8(remote_state[5], kMitsubishiHeavy88SwingVByte5Offset, + kMitsubishiHeavy88SwingVByte5Size) | + (GETBITS8(remote_state[7], kMitsubishiHeavy88SwingVByte7Offset, + kMitsubishiHeavy88SwingVByte7Size) << + kMitsubishiHeavy88SwingVByte5Size); } void IRMitsubishiHeavy88Ac::setSwingHorizontal(const uint8_t pos) { @@ -705,18 +654,22 @@ void IRMitsubishiHeavy88Ac::setSwingHorizontal(const uint8_t pos) { case kMitsubishiHeavy88SwingHRightMax: case kMitsubishiHeavy88SwingHLeftRight: case kMitsubishiHeavy88SwingHRightLeft: - case kMitsubishiHeavy88SwingH3D: - newpos = pos; - break; - default: - newpos = kMitsubishiHeavy88SwingHOff; + case kMitsubishiHeavy88SwingH3D: newpos = pos; break; + default: newpos = kMitsubishiHeavy88SwingHOff; } - remote_state[5] &= ~kMitsubishiHeavy88SwingHMask; - remote_state[5] |= newpos; + setBits(&remote_state[5], kMitsubishiHeavy88SwingHOffset1, + kMitsubishiHeavy88SwingHSize, newpos); + setBits(&remote_state[5], kMitsubishiHeavy88SwingHOffset2, + kMitsubishiHeavy88SwingHSize, + newpos >> kMitsubishiHeavy88SwingHSize); } uint8_t IRMitsubishiHeavy88Ac::getSwingHorizontal(void) { - return remote_state[5] & kMitsubishiHeavy88SwingHMask; + return GETBITS8(remote_state[5], kMitsubishiHeavy88SwingHOffset1, + kMitsubishiHeavy88SwingHSize) | + (GETBITS8(remote_state[5], kMitsubishiHeavy88SwingHOffset2, + kMitsubishiHeavy88SwingHSize) << + kMitsubishiHeavy88SwingHSize); } void IRMitsubishiHeavy88Ac::setTurbo(const bool on) { @@ -751,14 +704,11 @@ bool IRMitsubishiHeavy88Ac::get3D(void) { } void IRMitsubishiHeavy88Ac::setClean(const bool on) { - if (on) - remote_state[5] |= kMitsubishiHeavy88CleanBit; - else - remote_state[5] &= ~kMitsubishiHeavy88CleanBit; + setBit(&remote_state[5], kMitsubishiHeavy88CleanOffset, on); } bool IRMitsubishiHeavy88Ac::getClean(void) { - return remote_state[5] & kMitsubishiHeavy88CleanBit; + return GETBIT8(remote_state[5], kMitsubishiHeavy88CleanOffset); } // Verify the given state has a ZJ-S signature. @@ -791,58 +741,39 @@ uint8_t IRMitsubishiHeavy88Ac::convertMode(const stdAc::opmode_t mode) { // Convert a standard A/C Fan speed into its native fan speed. uint8_t IRMitsubishiHeavy88Ac::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { - case stdAc::fanspeed_t::kMin: - return kMitsubishiHeavy88FanEcono; // Assumes Econo is slower than Low. - case stdAc::fanspeed_t::kLow: - return kMitsubishiHeavy88FanLow; - case stdAc::fanspeed_t::kMedium: - return kMitsubishiHeavy88FanMed; - case stdAc::fanspeed_t::kHigh: - return kMitsubishiHeavy88FanHigh; - case stdAc::fanspeed_t::kMax: - return kMitsubishiHeavy88FanTurbo; - default: - return kMitsubishiHeavy88FanAuto; + // Assumes Econo is slower than Low. + case stdAc::fanspeed_t::kMin: return kMitsubishiHeavy88FanEcono; + case stdAc::fanspeed_t::kLow: return kMitsubishiHeavy88FanLow; + case stdAc::fanspeed_t::kMedium: return kMitsubishiHeavy88FanMed; + case stdAc::fanspeed_t::kHigh: return kMitsubishiHeavy88FanHigh; + case stdAc::fanspeed_t::kMax: return kMitsubishiHeavy88FanTurbo; + default: return kMitsubishiHeavy88FanAuto; } } // Convert a standard A/C vertical swing into its native setting. uint8_t IRMitsubishiHeavy88Ac::convertSwingV(const stdAc::swingv_t position) { switch (position) { - case stdAc::swingv_t::kAuto: - return kMitsubishiHeavy88SwingVAuto; - case stdAc::swingv_t::kHighest: - return kMitsubishiHeavy88SwingVHighest; - case stdAc::swingv_t::kHigh: - return kMitsubishiHeavy88SwingVHigh; - case stdAc::swingv_t::kMiddle: - return kMitsubishiHeavy88SwingVMiddle; - case stdAc::swingv_t::kLow: - return kMitsubishiHeavy88SwingVLow; - case stdAc::swingv_t::kLowest: - return kMitsubishiHeavy88SwingVLowest; - default: - return kMitsubishiHeavy88SwingVOff; + case stdAc::swingv_t::kAuto: return kMitsubishiHeavy88SwingVAuto; + case stdAc::swingv_t::kHighest: return kMitsubishiHeavy88SwingVHighest; + case stdAc::swingv_t::kHigh: return kMitsubishiHeavy88SwingVHigh; + case stdAc::swingv_t::kMiddle: return kMitsubishiHeavy88SwingVMiddle; + case stdAc::swingv_t::kLow: return kMitsubishiHeavy88SwingVLow; + case stdAc::swingv_t::kLowest: return kMitsubishiHeavy88SwingVLowest; + default: return kMitsubishiHeavy88SwingVOff; } } // Convert a standard A/C horizontal swing into its native setting. uint8_t IRMitsubishiHeavy88Ac::convertSwingH(const stdAc::swingh_t position) { switch (position) { - case stdAc::swingh_t::kAuto: - return kMitsubishiHeavy88SwingHAuto; - case stdAc::swingh_t::kLeftMax: - return kMitsubishiHeavy88SwingHLeftMax; - case stdAc::swingh_t::kLeft: - return kMitsubishiHeavy88SwingHLeft; - case stdAc::swingh_t::kMiddle: - return kMitsubishiHeavy88SwingHMiddle; - case stdAc::swingh_t::kRight: - return kMitsubishiHeavy88SwingHRight; - case stdAc::swingh_t::kRightMax: - return kMitsubishiHeavy88SwingHRightMax; - default: - return kMitsubishiHeavy88SwingHOff; + case stdAc::swingh_t::kAuto: return kMitsubishiHeavy88SwingHAuto; + case stdAc::swingh_t::kLeftMax: return kMitsubishiHeavy88SwingHLeftMax; + case stdAc::swingh_t::kLeft: return kMitsubishiHeavy88SwingHLeft; + case stdAc::swingh_t::kMiddle: return kMitsubishiHeavy88SwingHMiddle; + case stdAc::swingh_t::kRight: return kMitsubishiHeavy88SwingHRight; + case stdAc::swingh_t::kRightMax: return kMitsubishiHeavy88SwingHRightMax; + default: return kMitsubishiHeavy88SwingHOff; } } @@ -850,24 +781,24 @@ uint8_t IRMitsubishiHeavy88Ac::convertSwingH(const stdAc::swingh_t position) { stdAc::fanspeed_t IRMitsubishiHeavy88Ac::toCommonFanSpeed(const uint8_t speed) { switch (speed) { case kMitsubishiHeavy88FanTurbo: return stdAc::fanspeed_t::kMax; - case kMitsubishiHeavy88FanHigh: return stdAc::fanspeed_t::kHigh; - case kMitsubishiHeavy88FanMed: return stdAc::fanspeed_t::kMedium; - case kMitsubishiHeavy88FanLow: return stdAc::fanspeed_t::kLow; + case kMitsubishiHeavy88FanHigh: return stdAc::fanspeed_t::kHigh; + case kMitsubishiHeavy88FanMed: return stdAc::fanspeed_t::kMedium; + case kMitsubishiHeavy88FanLow: return stdAc::fanspeed_t::kLow; case kMitsubishiHeavy88FanEcono: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + default: return stdAc::fanspeed_t::kAuto; } } // Convert a native vertical swing to it's common equivalent. stdAc::swingh_t IRMitsubishiHeavy88Ac::toCommonSwingH(const uint8_t pos) { switch (pos) { - case kMitsubishiHeavy88SwingHLeftMax: return stdAc::swingh_t::kLeftMax; - case kMitsubishiHeavy88SwingHLeft: return stdAc::swingh_t::kLeft; - case kMitsubishiHeavy88SwingHMiddle: return stdAc::swingh_t::kMiddle; - case kMitsubishiHeavy88SwingHRight: return stdAc::swingh_t::kRight; + case kMitsubishiHeavy88SwingHLeftMax: return stdAc::swingh_t::kLeftMax; + case kMitsubishiHeavy88SwingHLeft: return stdAc::swingh_t::kLeft; + case kMitsubishiHeavy88SwingHMiddle: return stdAc::swingh_t::kMiddle; + case kMitsubishiHeavy88SwingHRight: return stdAc::swingh_t::kRight; case kMitsubishiHeavy88SwingHRightMax: return stdAc::swingh_t::kRightMax; - case kMitsubishiHeavy88SwingHOff: return stdAc::swingh_t::kOff; - default: return stdAc::swingh_t::kAuto; + case kMitsubishiHeavy88SwingHOff: return stdAc::swingh_t::kOff; + default: return stdAc::swingh_t::kAuto; } } @@ -875,12 +806,12 @@ stdAc::swingh_t IRMitsubishiHeavy88Ac::toCommonSwingH(const uint8_t pos) { stdAc::swingv_t IRMitsubishiHeavy88Ac::toCommonSwingV(const uint8_t pos) { switch (pos) { case kMitsubishiHeavy88SwingVHighest: return stdAc::swingv_t::kHighest; - case kMitsubishiHeavy88SwingVHigh: return stdAc::swingv_t::kHigh; - case kMitsubishiHeavy88SwingVMiddle: return stdAc::swingv_t::kMiddle; - case kMitsubishiHeavy88SwingVLow: return stdAc::swingv_t::kLow; - case kMitsubishiHeavy88SwingVLowest: return stdAc::swingv_t::kLowest; - case kMitsubishiHeavy88SwingVOff: return stdAc::swingv_t::kOff; - default: return stdAc::swingv_t::kAuto; + case kMitsubishiHeavy88SwingVHigh: return stdAc::swingv_t::kHigh; + case kMitsubishiHeavy88SwingVMiddle: return stdAc::swingv_t::kMiddle; + case kMitsubishiHeavy88SwingVLow: return stdAc::swingv_t::kLow; + case kMitsubishiHeavy88SwingVLowest: return stdAc::swingv_t::kLowest; + case kMitsubishiHeavy88SwingVOff: return stdAc::swingv_t::kOff; + default: return stdAc::swingv_t::kAuto; } } @@ -913,101 +844,105 @@ stdAc::state_t IRMitsubishiHeavy88Ac::toCommon(void) { String IRMitsubishiHeavy88Ac::toString(void) { String result = ""; result.reserve(140); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kMitsubishiHeavyAuto, kMitsubishiHeavyCool, kMitsubishiHeavyHeat, kMitsubishiHeavyDry, kMitsubishiHeavyFan); result += addTempToString(getTemp()); - result += addIntToString(getFan(), F("Fan")); - result += F(" ("); + result += addIntToString(getFan(), kFanStr); + result += kSpaceLBraceStr; switch (this->getFan()) { case kMitsubishiHeavy88FanAuto: - result += F("Auto"); + result += kAutoStr; break; case kMitsubishiHeavy88FanHigh: - result += F("High"); + result += kHighStr; break; case kMitsubishiHeavy88FanLow: - result += F("Low"); + result += kLowStr; break; case kMitsubishiHeavy88FanMed: - result += F("Medium"); + result += kMedStr; break; case kMitsubishiHeavy88FanEcono: - result += F("Econo"); + result += kEconoStr; break; case kMitsubishiHeavy88FanTurbo: - result += F("Turbo"); + result += kTurboStr; break; default: - result += F("UNKNOWN"); + result += kUnknownStr; } result += ')'; - result += addIntToString(getSwingVertical(), F("Swing (V)")); + result += addIntToString(getSwingVertical(), kSwingVStr); + result += kSpaceLBraceStr; switch (this->getSwingVertical()) { case kMitsubishiHeavy88SwingVAuto: - result += F(" (Auto)"); + result += kAutoStr; break; case kMitsubishiHeavy88SwingVHighest: - result += F(" (Highest)"); + result += kHighestStr; break; case kMitsubishiHeavy88SwingVHigh: - result += F(" (High)"); + result += kHighStr; break; case kMitsubishiHeavy88SwingVMiddle: - result += F(" (Middle)"); + result += kMiddleStr; break; case kMitsubishiHeavy88SwingVLow: - result += F(" (Low)"); + result += kLowStr; break; case kMitsubishiHeavy88SwingVLowest: - result += F(" (Lowest)"); + result += kLowestStr; break; case kMitsubishiHeavy88SwingVOff: - result += F(" (Off)"); + result += kOffStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } - result += addIntToString(getSwingHorizontal(), F("Swing (H)")); + result += ')'; + result += addIntToString(getSwingHorizontal(), kSwingHStr); + result += kSpaceLBraceStr; switch (this->getSwingHorizontal()) { case kMitsubishiHeavy88SwingHAuto: - result += F(" (Auto)"); + result += kAutoStr; break; case kMitsubishiHeavy88SwingHLeftMax: - result += F(" (Max Left)"); + result += kMaxLeftStr; break; case kMitsubishiHeavy88SwingHLeft: - result += F(" (Left)"); + result += kLeftStr; break; case kMitsubishiHeavy88SwingHMiddle: - result += F(" (Middle)"); + result += kMiddleStr; break; case kMitsubishiHeavy88SwingHRight: - result += F(" (Right)"); + result += kRightStr; break; case kMitsubishiHeavy88SwingHRightMax: - result += F(" (Max Right)"); + result += kMaxRightStr; break; case kMitsubishiHeavy88SwingHLeftRight: - result += F(" (Left Right)"); + result += kLeftStr + ' ' + kRightStr; break; case kMitsubishiHeavy88SwingHRightLeft: - result += F(" (Right Left)"); + result += kRightStr + ' ' + kLeftStr; break; case kMitsubishiHeavy88SwingH3D: - result += F(" (3D)"); + result += k3DStr; break; case kMitsubishiHeavy88SwingHOff: - result += F(" (Off)"); + result += kOffStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } - result += addBoolToString(getTurbo(), F("Turbo")); - result += addBoolToString(getEcono(), F("Econo")); - result += addBoolToString(get3D(), F("3D")); - result += addBoolToString(getClean(), F("Clean")); + result += ')'; + result += addBoolToString(getTurbo(), kTurboStr); + result += addBoolToString(getEcono(), kEconoStr); + result += addBoolToString(get3D(), k3DStr); + result += addBoolToString(getClean(), kCleanStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.h b/lib/IRremoteESP8266-2.7.0/src/ir_MitsubishiHeavy.h old mode 100755 new mode 100644 similarity index 77% rename from lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.h rename to lib/IRremoteESP8266-2.7.0/src/ir_MitsubishiHeavy.h index c52eeb951..2c2097d03 --- a/lib/IRremoteESP8266-2.6.5/src/ir_MitsubishiHeavy.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_MitsubishiHeavy.h @@ -32,21 +32,21 @@ const uint8_t kMitsubishiHeavySigLength = 5; const uint8_t kMitsubishiHeavyZmsSig[kMitsubishiHeavySigLength] = { 0xAD, 0x51, 0x3C, 0xE5, 0x1A}; // Byte[5] -const uint8_t kMitsubishiHeavyFilterBit = 0b01000000; -const uint8_t kMitsubishiHeavyCleanBit = 0b00100000; -const uint8_t kMitsubishiHeavyPowerBit = 0b00001000; // Byte 9 on ZJS -const uint8_t kMitsubishiHeavyModeMask = 0b00000111; // Byte 9 on ZJS +const uint8_t kMitsubishiHeavyModeOffset = 0; +// Mode Mask = 0b00000111; // Byte 9 on ZJS const uint8_t kMitsubishiHeavyAuto = 0; // 0b000 const uint8_t kMitsubishiHeavyCool = 1; // 0b001 const uint8_t kMitsubishiHeavyDry = 2; // 0b010 const uint8_t kMitsubishiHeavyFan = 3; // 0b011 const uint8_t kMitsubishiHeavyHeat = 4; // 0b100 +const uint8_t kMitsubishiHeavyPowerOffset = 3; // Byte 9 on ZJS +const uint8_t kMitsubishiHeavyCleanOffset = 5; +const uint8_t kMitsubishiHeavyFilterOffset = 6; // Byte[7] -const uint8_t kMitsubishiHeavyTempMask = 0b00001111; const uint8_t kMitsubishiHeavyMinTemp = 17; // 17C const uint8_t kMitsubishiHeavyMaxTemp = 31; // 31C // Byte[9] -const uint8_t kMitsubishiHeavyFanMask = 0b00001111; // ~Byte 7 on ZJS. +// FanMask = 0b00001111; // ~Byte 7 on ZJS. const uint8_t kMitsubishiHeavy152FanAuto = 0x0; // 0b0000 const uint8_t kMitsubishiHeavy152FanLow = 0x1; // 0b0001 const uint8_t kMitsubishiHeavy152FanMed = 0x2; // 0b0010 @@ -56,7 +56,8 @@ const uint8_t kMitsubishiHeavy152FanEcono = 0x6; // 0b0110 const uint8_t kMitsubishiHeavy152FanTurbo = 0x8; // 0b1000 // Byte[11] const uint8_t kMitsubishiHeavy3DMask = 0b00010010; -const uint8_t kMitsubishiHeavy152SwingVMask = 0b11100000; +const uint8_t kMitsubishiHeavy152SwingVOffset = 5; +const uint8_t kMitsubishiHeavy152SwingVSize = 3; // Bits const uint8_t kMitsubishiHeavy152SwingVAuto = 0; // 0b000 const uint8_t kMitsubishiHeavy152SwingVHighest = 1; // 0b001 const uint8_t kMitsubishiHeavy152SwingVHigh = 2; // 0b010 @@ -65,7 +66,6 @@ const uint8_t kMitsubishiHeavy152SwingVLow = 4; // 0b100 const uint8_t kMitsubishiHeavy152SwingVLowest = 5; // 0b101 const uint8_t kMitsubishiHeavy152SwingVOff = 6; // 0b110 // Byte[13] -const uint8_t kMitsubishiHeavy152SwingHMask = 0b00001111; const uint8_t kMitsubishiHeavy152SwingHAuto = 0; // 0b0000 const uint8_t kMitsubishiHeavy152SwingHLeftMax = 1; // 0b0001 const uint8_t kMitsubishiHeavy152SwingHLeft = 2; // 0b0010 @@ -76,46 +76,50 @@ const uint8_t kMitsubishiHeavy152SwingHRightLeft = 6; // 0b0110 const uint8_t kMitsubishiHeavy152SwingHLeftRight = 7; // 0b0111 const uint8_t kMitsubishiHeavy152SwingHOff = 8; // 0b1000 // Byte[15] -const uint8_t kMitsubishiHeavyNightBit = 0b01000000; -const uint8_t kMitsubishiHeavySilentBit = 0b10000000; +const uint8_t kMitsubishiHeavyNightOffset = 6; +const uint8_t kMitsubishiHeavySilentOffset = 7; // ZJS (88 bit) const uint8_t kMitsubishiHeavyZjsSig[kMitsubishiHeavySigLength] = { 0xAD, 0x51, 0x3C, 0xD9, 0x26}; // Byte [5] -const uint8_t kMitsubishiHeavy88CleanBit = 0b00100000; -const uint8_t kMitsubishiHeavy88SwingHMask = 0b11001100; -const uint8_t kMitsubishiHeavy88SwingHAuto = 0x80; // 0b10000000 -const uint8_t kMitsubishiHeavy88SwingHLeftMax = 0x04; // 0b00000100 -const uint8_t kMitsubishiHeavy88SwingHLeft = 0x44; // 0b01000100 -const uint8_t kMitsubishiHeavy88SwingHMiddle = 0x84; // 0b10000100 -const uint8_t kMitsubishiHeavy88SwingHRight = 0xC4; // 0b11000100 -const uint8_t kMitsubishiHeavy88SwingHRightMax = 0x08; // 0b00001000 -const uint8_t kMitsubishiHeavy88SwingHRightLeft = 0x88; // 0b10001000 -const uint8_t kMitsubishiHeavy88SwingHLeftRight = 0x48; // 0b01001000 -const uint8_t kMitsubishiHeavy88SwingHOff = 0x00; // 0b00000000 -const uint8_t kMitsubishiHeavy88SwingH3D = 0xC8; // 0b11001000 +const uint8_t kMitsubishiHeavy88CleanOffset = 5; +const uint8_t kMitsubishiHeavy88SwingHOffset1 = 2; +const uint8_t kMitsubishiHeavy88SwingHOffset2 = 6; +const uint8_t kMitsubishiHeavy88SwingHSize = 2; // Bits (per offset) +const uint8_t kMitsubishiHeavy88SwingHOff = 0b0000; +const uint8_t kMitsubishiHeavy88SwingHAuto = 0b1000; +const uint8_t kMitsubishiHeavy88SwingHLeftMax = 0b0001; +const uint8_t kMitsubishiHeavy88SwingHLeft = 0b0101; +const uint8_t kMitsubishiHeavy88SwingHMiddle = 0b1001; +const uint8_t kMitsubishiHeavy88SwingHRight = 0b1101; +const uint8_t kMitsubishiHeavy88SwingHRightMax = 0b0010; +const uint8_t kMitsubishiHeavy88SwingHRightLeft = 0b1010; +const uint8_t kMitsubishiHeavy88SwingHLeftRight = 0b0110; +const uint8_t kMitsubishiHeavy88SwingH3D = 0b1110; // Byte[7] -const uint8_t kMitsubishiHeavy88FanMask = 0b11100000; +const uint8_t kMitsubishiHeavy88FanOffset = 5; +const uint8_t kMitsubishiHeavy88FanSize = 3; // Bits const uint8_t kMitsubishiHeavy88FanAuto = 0; // 0b000 const uint8_t kMitsubishiHeavy88FanLow = 2; // 0b010 const uint8_t kMitsubishiHeavy88FanMed = 3; // 0b011 const uint8_t kMitsubishiHeavy88FanHigh = 4; // 0b100 const uint8_t kMitsubishiHeavy88FanTurbo = 6; // 0b110 const uint8_t kMitsubishiHeavy88FanEcono = 7; // 0b111 -const uint8_t kMitsubishiHeavy88SwingVMaskByte5 = 0b00000010; -const uint8_t kMitsubishiHeavy88SwingVMaskByte7 = 0b00011000; -const uint8_t kMitsubishiHeavy88SwingVMask = - kMitsubishiHeavy88SwingVMaskByte5 | kMitsubishiHeavy88SwingVMaskByte7; - // i.e. 0b00011010 -const uint8_t kMitsubishiHeavy88SwingVAuto = 0b00010000; // 0x10 -const uint8_t kMitsubishiHeavy88SwingVHighest = 0b00011000; // 0x18 -const uint8_t kMitsubishiHeavy88SwingVHigh = 0b00000010; // 0x02 -const uint8_t kMitsubishiHeavy88SwingVMiddle = 0b00001010; // 0x0A -const uint8_t kMitsubishiHeavy88SwingVLow = 0b00010010; // 0x12 -const uint8_t kMitsubishiHeavy88SwingVLowest = 0b00011010; // 0x1A -const uint8_t kMitsubishiHeavy88SwingVOff = 0b00000000; // 0x00 +const uint8_t kMitsubishiHeavy88SwingVByte5Offset = 1; +const uint8_t kMitsubishiHeavy88SwingVByte5Size = 1; +const uint8_t kMitsubishiHeavy88SwingVByte7Offset = 3; +const uint8_t kMitsubishiHeavy88SwingVByte7Size = 2; + + // Mask 0b111 +const uint8_t kMitsubishiHeavy88SwingVOff = 0b000; // 0 +const uint8_t kMitsubishiHeavy88SwingVAuto = 0b100; // 4 +const uint8_t kMitsubishiHeavy88SwingVHighest = 0b110; // 6 +const uint8_t kMitsubishiHeavy88SwingVHigh = 0b001; // 1 +const uint8_t kMitsubishiHeavy88SwingVMiddle = 0b011; // 3 +const uint8_t kMitsubishiHeavy88SwingVLow = 0b101; // 5 +const uint8_t kMitsubishiHeavy88SwingVLowest = 0b111; // 7 // Byte[9] is Power & Mode & Temp. diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_NEC.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_NEC.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_NEC.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_NEC.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_NEC.h b/lib/IRremoteESP8266-2.7.0/src/ir_NEC.h old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_NEC.h rename to lib/IRremoteESP8266-2.7.0/src/ir_NEC.h diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Neoclima.cpp old mode 100755 new mode 100644 similarity index 69% rename from lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Neoclima.cpp index 353d43b14..8b944293e --- a/lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Neoclima.cpp @@ -15,8 +15,10 @@ #include "ir_Neoclima.h" #include +#include #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Constants @@ -34,6 +36,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_NEOCLIMA // Send a Neoclima message. @@ -73,13 +77,9 @@ IRNeoclimaAc::IRNeoclimaAc(const uint16_t pin, const bool inverted, } void IRNeoclimaAc::stateReset(void) { - for (uint8_t i = 0; i < kNeoclimaStateLength; i++) - remote_state[i] = 0x0; - remote_state[7] = 0x6A; - remote_state[8] = 0x00; - remote_state[9] = 0x2A; - remote_state[10] = 0xA5; - // [11] is the checksum. + static const uint8_t kReset[kNeoclimaStateLength] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x2A, 0xA5}; + setRaw(kReset); } void IRNeoclimaAc::begin(void) { _irsend.begin(); } @@ -104,8 +104,7 @@ void IRNeoclimaAc::checksum(uint16_t length) { #if SEND_NEOCLIMA void IRNeoclimaAc::send(const uint16_t repeat) { - this->checksum(); - _irsend.sendNeoclima(remote_state, kNeoclimaStateLength, repeat); + _irsend.sendNeoclima(getRaw(), kNeoclimaStateLength, repeat); } #endif // SEND_NEOCLIMA @@ -115,8 +114,7 @@ uint8_t *IRNeoclimaAc::getRaw(void) { } void IRNeoclimaAc::setRaw(const uint8_t new_code[], const uint16_t length) { - for (uint8_t i = 0; i < length && i < kNeoclimaStateLength; i++) - remote_state[i] = new_code[i]; + memcpy(remote_state, new_code, std::min(length, kNeoclimaStateLength)); } @@ -138,8 +136,8 @@ void IRNeoclimaAc::setButton(const uint8_t button) { case kNeoclimaButtonFresh: case kNeoclimaButton8CHeat: case kNeoclimaButtonTurbo: - remote_state[5] &= ~kNeoclimaButtonMask; - remote_state[5] |= button; + setBits(&remote_state[5], kNeoclimaButtonOffset, kNeoclimaButtonSize, + button); break; default: this->setButton(kNeoclimaButtonPower); @@ -147,7 +145,7 @@ void IRNeoclimaAc::setButton(const uint8_t button) { } uint8_t IRNeoclimaAc::getButton(void) { - return remote_state[5] & kNeoclimaButtonMask; + return GETBITS8(remote_state[5], kNeoclimaButtonOffset, kNeoclimaButtonSize); } void IRNeoclimaAc::on(void) { this->setPower(true); } @@ -156,14 +154,11 @@ void IRNeoclimaAc::off(void) { this->setPower(false); } void IRNeoclimaAc::setPower(const bool on) { this->setButton(kNeoclimaButtonPower); - if (on) - remote_state[7] |= kNeoclimaPowerMask; - else - remote_state[7] &= ~kNeoclimaPowerMask; + setBit(&remote_state[7], kNeoclimaPowerOffset, on); } bool IRNeoclimaAc::getPower(void) { - return remote_state[7] & kNeoclimaPowerMask; + return GETBIT8(remote_state[7], kNeoclimaPowerOffset); } void IRNeoclimaAc::setMode(const uint8_t mode) { @@ -176,8 +171,7 @@ void IRNeoclimaAc::setMode(const uint8_t mode) { case kNeoclimaCool: case kNeoclimaFan: case kNeoclimaHeat: - remote_state[9] &= ~kNeoclimaModeMask; - remote_state[9] |= (mode << 5); + setBits(&remote_state[9], kNeoclimaModeOffset, kModeBitsSize, mode); this->setButton(kNeoclimaButtonMode); break; default: @@ -187,22 +181,17 @@ void IRNeoclimaAc::setMode(const uint8_t mode) { } uint8_t IRNeoclimaAc::getMode(void) { - return (remote_state[9] & kNeoclimaModeMask) >> 5; + return GETBITS8(remote_state[9], kNeoclimaModeOffset, kModeBitsSize); } // Convert a standard A/C mode into its native mode. uint8_t IRNeoclimaAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kNeoclimaCool; - case stdAc::opmode_t::kHeat: - return kNeoclimaHeat; - case stdAc::opmode_t::kDry: - return kNeoclimaDry; - case stdAc::opmode_t::kFan: - return kNeoclimaFan; - default: - return kNeoclimaAuto; + case stdAc::opmode_t::kCool: return kNeoclimaCool; + case stdAc::opmode_t::kHeat: return kNeoclimaHeat; + case stdAc::opmode_t::kDry: return kNeoclimaDry; + case stdAc::opmode_t::kFan: return kNeoclimaFan; + default: return kNeoclimaAuto; } } @@ -211,9 +200,9 @@ stdAc::opmode_t IRNeoclimaAc::toCommonMode(const uint8_t mode) { switch (mode) { case kNeoclimaCool: return stdAc::opmode_t::kCool; case kNeoclimaHeat: return stdAc::opmode_t::kHeat; - case kNeoclimaDry: return stdAc::opmode_t::kDry; - case kNeoclimaFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kNeoclimaDry: return stdAc::opmode_t::kDry; + case kNeoclimaFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -226,13 +215,14 @@ void IRNeoclimaAc::setTemp(const uint8_t temp) { this->setButton(kNeoclimaButtonTempDown); else if (newtemp > oldtemp) this->setButton(kNeoclimaButtonTempUp); - remote_state[9] = (remote_state[9] & ~kNeoclimaTempMask) | - (newtemp - kNeoclimaMinTemp); + setBits(&remote_state[9], kNeoclimaTempOffset, kNeoclimaTempSize, + newtemp - kNeoclimaMinTemp); } // Return the set temp. in deg C uint8_t IRNeoclimaAc::getTemp(void) { - return (remote_state[9] & kNeoclimaTempMask) + kNeoclimaMinTemp; + return GETBITS8(remote_state[9], kNeoclimaTempOffset, kNeoclimaTempSize) + + kNeoclimaMinTemp; } // Set the speed of the fan, 0-3, 0 is auto, 1-3 is the speed @@ -247,8 +237,7 @@ void IRNeoclimaAc::setFan(const uint8_t speed) { } // FALL-THRU case kNeoclimaFanLow: - remote_state[7] &= ~kNeoclimaFanMask; - remote_state[7] |= (speed << 5); + setBits(&remote_state[7], kNeoclimaFanOffest, kNeoclimaFanSize, speed); this->setButton(kNeoclimaButtonFanSpeed); break; default: @@ -258,22 +247,18 @@ void IRNeoclimaAc::setFan(const uint8_t speed) { } uint8_t IRNeoclimaAc::getFan(void) { - return (remote_state[7] & kNeoclimaFanMask) >> 5; + return GETBITS8(remote_state[7], kNeoclimaFanOffest, kNeoclimaFanSize); } // Convert a standard A/C Fan speed into its native fan speed. uint8_t IRNeoclimaAc::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kNeoclimaFanLow; - case stdAc::fanspeed_t::kMedium: - return kNeoclimaFanMed; + case stdAc::fanspeed_t::kLow: return kNeoclimaFanLow; + case stdAc::fanspeed_t::kMedium: return kNeoclimaFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kNeoclimaFanHigh; - default: - return kNeoclimaFanAuto; + case stdAc::fanspeed_t::kMax: return kNeoclimaFanHigh; + default: return kNeoclimaFanAuto; } } @@ -281,106 +266,86 @@ uint8_t IRNeoclimaAc::convertFan(const stdAc::fanspeed_t speed) { stdAc::fanspeed_t IRNeoclimaAc::toCommonFanSpeed(const uint8_t speed) { switch (speed) { case kNeoclimaFanHigh: return stdAc::fanspeed_t::kMax; - case kNeoclimaFanMed: return stdAc::fanspeed_t::kMedium; - case kNeoclimaFanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kNeoclimaFanMed: return stdAc::fanspeed_t::kMedium; + case kNeoclimaFanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } void IRNeoclimaAc::setSleep(const bool on) { this->setButton(kNeoclimaButtonSleep); - if (on) - remote_state[7] |= kNeoclimaSleepMask; - else - remote_state[7] &= ~kNeoclimaSleepMask; + setBit(&remote_state[7], kNeoclimaSleepOffset, on); } bool IRNeoclimaAc::getSleep(void) { - return remote_state[7] & kNeoclimaSleepMask; + return GETBIT8(remote_state[7], kNeoclimaSleepOffset); } // A.k.a. Swing void IRNeoclimaAc::setSwingV(const bool on) { this->setButton(kNeoclimaButtonSwing); - remote_state[7] &= ~kNeoclimaSwingVMask; - remote_state[7] |= on ? kNeoclimaSwingVOn : kNeoclimaSwingVOff; + setBits(&remote_state[7], kNeoclimaSwingVOffset, kNeoclimaSwingVSize, + on ? kNeoclimaSwingVOn : kNeoclimaSwingVOff); } bool IRNeoclimaAc::getSwingV(void) { - return (remote_state[7] & kNeoclimaSwingVMask) == kNeoclimaSwingVOn; + return GETBITS8(remote_state[7], kNeoclimaSwingVOffset, + kNeoclimaSwingVSize) == kNeoclimaSwingVOn; } // A.k.a. Air Flow void IRNeoclimaAc::setSwingH(const bool on) { this->setButton(kNeoclimaButtonAirFlow); - if (on) - remote_state[7] &= ~kNeoclimaSwingHMask; - else - remote_state[7] |= kNeoclimaSwingHMask; + setBit(&remote_state[7], kNeoclimaSwingHOffset, !on); // Cleared when `on` } bool IRNeoclimaAc::getSwingH(void) { - return !(remote_state[7] & kNeoclimaSwingHMask); + return !GETBIT8(remote_state[7], kNeoclimaSwingHOffset); } void IRNeoclimaAc::setTurbo(const bool on) { this->setButton(kNeoclimaButtonTurbo); - if (on) - remote_state[3] |= kNeoclimaTurboMask; - else - remote_state[3] &= ~kNeoclimaTurboMask; + setBit(&remote_state[3], kNeoclimaTurboOffset, on); } bool IRNeoclimaAc::getTurbo(void) { - return remote_state[3] & kNeoclimaTurboMask; + return GETBIT8(remote_state[3], kNeoclimaTurboOffset); } void IRNeoclimaAc::setFresh(const bool on) { this->setButton(kNeoclimaButtonFresh); - if (on) - remote_state[5] |= kNeoclimaFreshMask; - else - remote_state[5] &= ~kNeoclimaFreshMask; + setBit(&remote_state[5], kNeoclimaFreshOffset, on); } bool IRNeoclimaAc::getFresh(void) { - return remote_state[5] & kNeoclimaFreshMask; + return GETBIT8(remote_state[5], kNeoclimaFreshOffset); } void IRNeoclimaAc::setHold(const bool on) { this->setButton(kNeoclimaButtonHold); - if (on) - remote_state[3] |= kNeoclimaHoldMask; - else - remote_state[3] &= ~kNeoclimaHoldMask; + setBit(&remote_state[3], kNeoclimaHoldOffset, on); } bool IRNeoclimaAc::getHold(void) { - return remote_state[3] & kNeoclimaHoldMask; + return GETBIT8(remote_state[3], kNeoclimaHoldOffset); } void IRNeoclimaAc::setIon(const bool on) { this->setButton(kNeoclimaButtonIon); - if (on) - remote_state[1] |= kNeoclimaIonMask; - else - remote_state[1] &= ~kNeoclimaIonMask; + setBit(&remote_state[1], kNeoclimaIonOffset, on); } bool IRNeoclimaAc::getIon(void) { - return remote_state[1] & kNeoclimaIonMask; + return GETBIT8(remote_state[1], kNeoclimaIonOffset); } void IRNeoclimaAc::setLight(const bool on) { this->setButton(kNeoclimaButtonLight); - if (on) - remote_state[3] |= kNeoclimaLightMask; - else - remote_state[3] &= ~kNeoclimaLightMask; + setBit(&remote_state[3], kNeoclimaLightOffset, on); } bool IRNeoclimaAc::getLight(void) { - return remote_state[3] & kNeoclimaLightMask; + return GETBIT8(remote_state[3], kNeoclimaLightOffset); } // This feature maintains the room temperature steadily at 8°C and prevents the @@ -388,26 +353,20 @@ bool IRNeoclimaAc::getLight(void) { // nobody is at home over a longer period during severe winter. void IRNeoclimaAc::set8CHeat(const bool on) { this->setButton(kNeoclimaButton8CHeat); - if (on) - remote_state[1] |= kNeoclima8CHeatMask; - else - remote_state[1] &= ~kNeoclima8CHeatMask; + setBit(&remote_state[1], kNeoclima8CHeatOffset, on); } bool IRNeoclimaAc::get8CHeat(void) { - return remote_state[1] & kNeoclima8CHeatMask; + return GETBIT8(remote_state[1], kNeoclima8CHeatOffset); } void IRNeoclimaAc::setEye(const bool on) { this->setButton(kNeoclimaButtonEye); - if (on) - remote_state[3] |= kNeoclimaEyeMask; - else - remote_state[3] &= ~kNeoclimaEyeMask; + setBit(&remote_state[3], kNeoclimaEyeOffset, on); } bool IRNeoclimaAc::getEye(void) { - return remote_state[3] & kNeoclimaEyeMask; + return GETBIT8(remote_state[3], kNeoclimaEyeOffset); } /* DISABLED @@ -456,44 +415,44 @@ stdAc::state_t IRNeoclimaAc::toCommon(void) { String IRNeoclimaAc::toString(void) { String result = ""; result.reserve(100); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kNeoclimaAuto, kNeoclimaCool, kNeoclimaHeat, kNeoclimaDry, kNeoclimaFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kNeoclimaFanHigh, kNeoclimaFanLow, kNeoclimaFanAuto, kNeoclimaFanAuto, kNeoclimaFanMed); - result += addBoolToString(getSwingV(), F("Swing(V)")); - result += addBoolToString(getSwingH(), F("Swing(H)")); - result += addBoolToString(getSleep(), F("Sleep")); - result += addBoolToString(getTurbo(), F("Turbo")); - result += addBoolToString(getHold(), F("Hold")); - result += addBoolToString(getIon(), F("Ion")); - result += addBoolToString(getEye(), F("Eye")); - result += addBoolToString(getLight(), F("Light")); - result += addBoolToString(getFollow(), F("Follow")); - result += addBoolToString(get8CHeat(), F("8C Heat")); - result += addBoolToString(getFresh(), F("Fresh")); - result += addIntToString(getButton(), F("Button")); - result += F(" ("); + result += addBoolToString(getSwingV(), kSwingVStr); + result += addBoolToString(getSwingH(), kSwingHStr); + result += addBoolToString(getSleep(), kSleepStr); + result += addBoolToString(getTurbo(), kTurboStr); + result += addBoolToString(getHold(), kHoldStr); + result += addBoolToString(getIon(), kIonStr); + result += addBoolToString(getEye(), kEyeStr); + result += addBoolToString(getLight(), kLightStr); + result += addBoolToString(getFollow(), kFollowStr); + result += addBoolToString(get8CHeat(), k8CHeatStr); + result += addBoolToString(getFresh(), kFreshStr); + result += addIntToString(getButton(), kButtonStr); + result += kSpaceLBraceStr; switch (this->getButton()) { - case kNeoclimaButtonPower: result += F("Power"); break; - case kNeoclimaButtonMode: result += F("Mode"); break; - case kNeoclimaButtonTempUp: result += F("Temp Up"); break; - case kNeoclimaButtonTempDown: result += F("Temp Down"); break; - case kNeoclimaButtonSwing: result += F("Swing"); break; - case kNeoclimaButtonFanSpeed: result += F("Speed"); break; - case kNeoclimaButtonAirFlow: result += F("Air Flow"); break; - case kNeoclimaButtonHold: result += F("Hold"); break; - case kNeoclimaButtonSleep: result += F("Sleep"); break; - case kNeoclimaButtonLight: result += F("Light"); break; - case kNeoclimaButtonEye: result += F("Eye"); break; - case kNeoclimaButtonFollow: result += F("Follow"); break; - case kNeoclimaButtonIon: result += F("Ion"); break; - case kNeoclimaButtonFresh: result += F("Fresh"); break; - case kNeoclimaButton8CHeat: result += F("8C Heat"); break; - case kNeoclimaButtonTurbo: result += F("Turbo"); break; + case kNeoclimaButtonPower: result += kPowerStr; break; + case kNeoclimaButtonMode: result += kModeStr; break; + case kNeoclimaButtonTempUp: result += kTempUpStr; break; + case kNeoclimaButtonTempDown: result += kTempDownStr; break; + case kNeoclimaButtonSwing: result += kSwingStr; break; + case kNeoclimaButtonFanSpeed: result += kFanStr; break; + case kNeoclimaButtonAirFlow: result += kAirFlowStr; break; + case kNeoclimaButtonHold: result += kHoldStr; break; + case kNeoclimaButtonSleep: result += kSleepStr; break; + case kNeoclimaButtonLight: result += kLightStr; break; + case kNeoclimaButtonEye: result += kEyeStr; break; + case kNeoclimaButtonFollow: result += kFollowStr; break; + case kNeoclimaButtonIon: result += kIonStr; break; + case kNeoclimaButtonFresh: result += kFreshStr; break; + case kNeoclimaButton8CHeat: result += k8CHeatStr; break; + case kNeoclimaButtonTurbo: result += kTurboStr; break; default: - result += F("Unknown"); + result += kUnknownStr; } result += ')'; return result; diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.h b/lib/IRremoteESP8266-2.7.0/src/ir_Neoclima.h old mode 100755 new mode 100644 similarity index 83% rename from lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Neoclima.h index 9e99c8a9e..360c665d6 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Neoclima.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Neoclima.h @@ -28,16 +28,17 @@ // Constants // state[1] -const uint8_t kNeoclima8CHeatMask = 0b00000010; -const uint8_t kNeoclimaIonMask = 0b00000100; +const uint8_t kNeoclima8CHeatOffset = 1; +const uint8_t kNeoclimaIonOffset = 2; // state[3] -const uint8_t kNeoclimaLightMask = 0b00000001; -const uint8_t kNeoclimaHoldMask = 0b00000100; -const uint8_t kNeoclimaTurboMask = 0b00001000; -const uint8_t kNeoclimaEyeMask = 0b01000000; +const uint8_t kNeoclimaLightOffset = 0; +const uint8_t kNeoclimaHoldOffset = 2; +const uint8_t kNeoclimaTurboOffset = 3; +const uint8_t kNeoclimaEyeOffset = 6; // state[5] -const uint8_t kNeoclimaFreshMask = 0b10000000; -const uint8_t kNeoclimaButtonMask = 0b00011111; +const uint8_t kNeoclimaFreshOffset = 7; +const uint8_t kNeoclimaButtonOffset = 0; +const uint8_t kNeoclimaButtonSize = 5; const uint8_t kNeoclimaButtonPower = 0x00; const uint8_t kNeoclimaButtonMode = 0x01; const uint8_t kNeoclimaButtonTempUp = 0x02; @@ -55,13 +56,15 @@ const uint8_t kNeoclimaButtonIon = 0x14; const uint8_t kNeoclimaButtonFresh = 0x15; const uint8_t kNeoclimaButton8CHeat = 0x1D; // state[7] -const uint8_t kNeoclimaSleepMask = 0b00000001; -const uint8_t kNeoclimaPowerMask = 0b00000010; -const uint8_t kNeoclimaSwingVMask = 0b00001100; -const uint8_t kNeoclimaSwingVOn = 0b00000100; -const uint8_t kNeoclimaSwingVOff = 0b00001000; -const uint8_t kNeoclimaSwingHMask = 0b00010000; -const uint8_t kNeoclimaFanMask = 0b01100000; +const uint8_t kNeoclimaSleepOffset = 0; +const uint8_t kNeoclimaPowerOffset = 1; +const uint8_t kNeoclimaSwingVOffset = 2; +const uint8_t kNeoclimaSwingVSize = 2; // Bits +const uint8_t kNeoclimaSwingVOn = 0b01; +const uint8_t kNeoclimaSwingVOff = 0b10; +const uint8_t kNeoclimaSwingHOffset = 4; +const uint8_t kNeoclimaFanOffest = 5; +const uint8_t kNeoclimaFanSize = 2; const uint8_t kNeoclimaFanAuto = 0b00; const uint8_t kNeoclimaFanHigh = 0b01; const uint8_t kNeoclimaFanMed = 0b10; @@ -69,10 +72,11 @@ const uint8_t kNeoclimaFanLow = 0b11; // state[8] const uint8_t kNeoclimaFollowMe = 0x5D; // Also 0x5F // state[9] -const uint8_t kNeoclimaTempMask = 0b00011111; +const uint8_t kNeoclimaTempOffset = 0; +const uint8_t kNeoclimaTempSize = 5; // Bits const uint8_t kNeoclimaMinTemp = 16; // 16C const uint8_t kNeoclimaMaxTemp = 32; // 32C -const uint8_t kNeoclimaModeMask = 0b11100000; +const uint8_t kNeoclimaModeOffset = 5; const uint8_t kNeoclimaAuto = 0b000; const uint8_t kNeoclimaCool = 0b001; const uint8_t kNeoclimaDry = 0b010; diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Nikai.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Nikai.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Nikai.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Nikai.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Panasonic.cpp old mode 100755 new mode 100644 similarity index 72% rename from lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Panasonic.cpp index 1a24ac41f..a25f4cb02 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Panasonic.cpp @@ -5,11 +5,13 @@ #include "ir_Panasonic.h" #include +#include #ifndef ARDUINO #include #endif #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Panasonic protocol originally added by Kristian Lauszus from: @@ -66,8 +68,11 @@ using irutils::addFanToString; using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; +using irutils::addModelToString; using irutils::addTempToString; using irutils::minsToString; +using irutils::setBit; +using irutils::setBits; #if (SEND_PANASONIC || SEND_DENON) // Send a Panasonic formatted message. @@ -165,13 +170,13 @@ bool IRrecv::decodePanasonic(decode_results *results, const uint16_t nbits, kPanasonicBitMark, kPanasonicEndGap, true)) return false; // Compliance uint32_t address = data >> 32; - uint32_t command = data & 0xFFFFFFFF; + uint32_t command = data; if (strict) { if (address != manufacturer) // Verify the Manufacturer code. return false; // Verify the checksum. - uint8_t checksumOrig = data & 0xFF; - uint8_t checksumCalc = ((data >> 24) ^ (data >> 16) ^ (data >> 8)) & 0xFF; + uint8_t checksumOrig = data; + uint8_t checksumCalc = (data >> 24) ^ (data >> 16) ^ (data >> 8); if (checksumOrig != checksumCalc) return false; } @@ -179,7 +184,7 @@ bool IRrecv::decodePanasonic(decode_results *results, const uint16_t nbits, results->value = data; results->address = address; results->command = command; - results->decode_type = PANASONIC; + results->decode_type = decode_type_t::PANASONIC; results->bits = nbits; return true; } @@ -228,8 +233,7 @@ IRPanasonicAc::IRPanasonicAc(const uint16_t pin, const bool inverted, : _irsend(pin, inverted, use_modulation) { this->stateReset(); } void IRPanasonicAc::stateReset(void) { - for (uint8_t i = 0; i < kPanasonicAcStateLength; i++) - remote_state[i] = kPanasonicKnownGoodState[i]; + memcpy(remote_state, kPanasonicKnownGoodState, kPanasonicAcStateLength); _temp = 25; // An initial saved desired temp. Completely made up. _swingh = kPanasonicAcSwingHMiddle; // A similar made up value for H Swing. } @@ -258,22 +262,20 @@ void IRPanasonicAc::fixChecksum(const uint16_t length) { #if SEND_PANASONIC_AC void IRPanasonicAc::send(const uint16_t repeat) { - this->fixChecksum(); - _irsend.sendPanasonicAC(remote_state, kPanasonicAcStateLength, repeat); + _irsend.sendPanasonicAC(getRaw(), kPanasonicAcStateLength, repeat); } #endif // SEND_PANASONIC_AC void IRPanasonicAc::setModel(const panasonic_ac_remote_model_t model) { switch (model) { - case kPanasonicDke: - case kPanasonicJke: - case kPanasonicLke: - case kPanasonicNke: - case kPanasonicCkp: - case kPanasonicRkr: - break; - default: // Only proceed if we know what to do. - return; + case panasonic_ac_remote_model_t::kPanasonicDke: + case panasonic_ac_remote_model_t::kPanasonicJke: + case panasonic_ac_remote_model_t::kPanasonicLke: + case panasonic_ac_remote_model_t::kPanasonicNke: + case panasonic_ac_remote_model_t::kPanasonicCkp: + case panasonic_ac_remote_model_t::kPanasonicRkr: break; + // Only proceed if we know what to do. + default: return; } // clear & set the various bits and bytes. remote_state[13] &= 0xF0; @@ -314,14 +316,17 @@ panasonic_ac_remote_model_t IRPanasonicAc::getModel(void) { if (remote_state[23] == 0x89) return kPanasonicRkr; if (remote_state[17] == 0x00) { if ((remote_state[21] & 0x10) && (remote_state[23] & 0x01)) - return kPanasonicCkp; - if (remote_state[23] & 0x80) return kPanasonicJke; + return panasonic_ac_remote_model_t::kPanasonicCkp; + if (remote_state[23] & 0x80) + return panasonic_ac_remote_model_t::kPanasonicJke; } if (remote_state[17] == 0x06 && (remote_state[13] & 0x0F) == 0x02) - return kPanasonicLke; - if (remote_state[23] == 0x01) return kPanasonicDke; - if (remote_state[17] == 0x06) return kPanasonicNke; - return kPanasonicUnknown; + return panasonic_ac_remote_model_t::kPanasonicLke; + if (remote_state[23] == 0x01) + return panasonic_ac_remote_model_t::kPanasonicDke; + if (remote_state[17] == 0x06) + return panasonic_ac_remote_model_t::kPanasonicNke; + return panasonic_ac_remote_model_t::kPanasonicUnknown; // Default } uint8_t *IRPanasonicAc::getRaw(void) { @@ -330,9 +335,7 @@ uint8_t *IRPanasonicAc::getRaw(void) { } void IRPanasonicAc::setRaw(const uint8_t state[]) { - for (uint8_t i = 0; i < kPanasonicAcStateLength; i++) { - remote_state[i] = state[i]; - } + memcpy(remote_state, state, kPanasonicAcStateLength); } // Control the power state of the A/C unit. @@ -347,24 +350,23 @@ void IRPanasonicAc::setRaw(const uint8_t state[]) { // For all other models, setPower(true) should set the internal state to // turn it on, and setPower(false) should turn it off. void IRPanasonicAc::setPower(const bool on) { - if (on) - this->on(); - else - this->off(); + setBit(&remote_state[13], kPanasonicAcPowerOffset, on); } // Return the A/C power state of the remote. // Except for CKP models, where it returns if the power state will be toggled // on the A/C unit when the next message is sent. bool IRPanasonicAc::getPower(void) { - return (remote_state[13] & kPanasonicAcPower) == kPanasonicAcPower; + return GETBIT8(remote_state[13], kPanasonicAcPowerOffset); } -void IRPanasonicAc::on(void) { remote_state[13] |= kPanasonicAcPower; } +void IRPanasonicAc::on(void) { setPower(true); } -void IRPanasonicAc::off(void) { remote_state[13] &= ~kPanasonicAcPower; } +void IRPanasonicAc::off(void) { setPower(false); } -uint8_t IRPanasonicAc::getMode(void) { return remote_state[13] >> 4; } +uint8_t IRPanasonicAc::getMode(void) { + return GETBITS8(remote_state[13], kHighNibble, kModeBitsSize); +} void IRPanasonicAc::setMode(const uint8_t desired) { uint8_t mode = kPanasonicAcAuto; // Default to Auto mode. @@ -384,10 +386,13 @@ void IRPanasonicAc::setMode(const uint8_t desired) { break; } remote_state[13] &= 0x0F; // Clear the previous mode bits. - remote_state[13] |= mode << 4; + setBits(&remote_state[13], kHighNibble, kModeBitsSize, mode); } -uint8_t IRPanasonicAc::getTemp(void) { return remote_state[14] >> 1; } +uint8_t IRPanasonicAc::getTemp(void) { + return GETBITS8(remote_state[14], kPanasonicAcTempOffset, + kPanasonicAcTempSize); +} // Set the desitred temperature in Celsius. // Args: @@ -399,25 +404,27 @@ void IRPanasonicAc::setTemp(const uint8_t celsius, const bool remember) { uint8_t temperature; temperature = std::max(celsius, kPanasonicAcMinTemp); temperature = std::min(temperature, kPanasonicAcMaxTemp); - remote_state[14] = temperature << 1; if (remember) _temp = temperature; + setBits(&remote_state[14], kPanasonicAcTempOffset, kPanasonicAcTempSize, + temperature); } uint8_t IRPanasonicAc::getSwingVertical(void) { - return remote_state[16] & 0x0F; + return GETBITS8(remote_state[16], kLowNibble, kNibbleSize); } void IRPanasonicAc::setSwingVertical(const uint8_t desired_elevation) { uint8_t elevation = desired_elevation; if (elevation != kPanasonicAcSwingVAuto) { - elevation = std::max(elevation, kPanasonicAcSwingVUp); - elevation = std::min(elevation, kPanasonicAcSwingVDown); + elevation = std::max(elevation, kPanasonicAcSwingVHighest); + elevation = std::min(elevation, kPanasonicAcSwingVLowest); } - remote_state[16] &= 0xF0; - remote_state[16] |= elevation; + setBits(&remote_state[16], kLowNibble, kNibbleSize, elevation); } -uint8_t IRPanasonicAc::getSwingHorizontal(void) { return remote_state[17]; } +uint8_t IRPanasonicAc::getSwingHorizontal(void) { + return GETBITS8(remote_state[17], kLowNibble, kNibbleSize); +} void IRPanasonicAc::setSwingHorizontal(const uint8_t desired_direction) { switch (desired_direction) { @@ -426,10 +433,9 @@ void IRPanasonicAc::setSwingHorizontal(const uint8_t desired_direction) { case kPanasonicAcSwingHFullLeft: case kPanasonicAcSwingHLeft: case kPanasonicAcSwingHRight: - case kPanasonicAcSwingHFullRight: - break; - default: // Ignore anything that isn't valid. - return; + case kPanasonicAcSwingHFullRight: break; + // Ignore anything that isn't valid. + default: return; } _swingh = desired_direction; // Store the direction for later. uint8_t direction = desired_direction; @@ -444,129 +450,120 @@ void IRPanasonicAc::setSwingHorizontal(const uint8_t desired_direction) { default: // Ignore everything else. return; } - remote_state[17] = direction; + setBits(&remote_state[17], kLowNibble, kNibbleSize, direction); } void IRPanasonicAc::setFan(const uint8_t speed) { - if (speed <= kPanasonicAcFanMax || speed == kPanasonicAcFanAuto) - remote_state[16] = - (remote_state[16] & 0x0F) | ((speed + kPanasonicAcFanOffset) << 4); + switch (speed) { + case kPanasonicAcFanMin: + case kPanasonicAcFanMed: + case kPanasonicAcFanMax: + case kPanasonicAcFanAuto: + setBits(&remote_state[16], kHighNibble, kNibbleSize, + speed + kPanasonicAcFanDelta); + break; + default: setFan(kPanasonicAcFanAuto); + } } uint8_t IRPanasonicAc::getFan(void) { - return (remote_state[16] >> 4) - kPanasonicAcFanOffset; + return GETBITS8(remote_state[16], kHighNibble, kNibbleSize) - + kPanasonicAcFanDelta; } bool IRPanasonicAc::getQuiet(void) { switch (this->getModel()) { case kPanasonicRkr: case kPanasonicCkp: - return remote_state[21] & kPanasonicAcQuietCkp; + return GETBIT8(remote_state[21], kPanasonicAcQuietCkpOffset); default: - return remote_state[21] & kPanasonicAcQuiet; + return GETBIT8(remote_state[21], kPanasonicAcQuietOffset); } } void IRPanasonicAc::setQuiet(const bool on) { - uint8_t quiet; + uint8_t offset; switch (this->getModel()) { case kPanasonicRkr: - case kPanasonicCkp: - quiet = kPanasonicAcQuietCkp; - break; - default: - quiet = kPanasonicAcQuiet; - } - - if (on) { - this->setPowerful(false); // Powerful is mutually exclusive. - remote_state[21] |= quiet; - } else { - remote_state[21] &= ~quiet; + case kPanasonicCkp: offset = kPanasonicAcQuietCkpOffset; break; + default: offset = kPanasonicAcQuietOffset; } + if (on) this->setPowerful(false); // Powerful is mutually exclusive. + setBit(&remote_state[21], offset, on); } bool IRPanasonicAc::getPowerful(void) { switch (this->getModel()) { case kPanasonicRkr: case kPanasonicCkp: - return remote_state[21] & kPanasonicAcPowerfulCkp; + return GETBIT8(remote_state[21], kPanasonicAcPowerfulCkpOffset); default: - return remote_state[21] & kPanasonicAcPowerful; + return GETBIT8(remote_state[21], kPanasonicAcPowerfulOffset); } } void IRPanasonicAc::setPowerful(const bool on) { - uint8_t powerful; + uint8_t offset; switch (this->getModel()) { case kPanasonicRkr: - case kPanasonicCkp: - powerful = kPanasonicAcPowerfulCkp; - break; - default: - powerful = kPanasonicAcPowerful; + case kPanasonicCkp: offset = kPanasonicAcPowerfulCkpOffset; break; + default: offset = kPanasonicAcPowerfulOffset; } - if (on) { - this->setQuiet(false); // Quiet is mutually exclusive. - remote_state[21] |= powerful; - } else { - remote_state[21] &= ~powerful; - } + if (on) this->setQuiet(false); // Quiet is mutually exclusive. + setBit(&remote_state[21], offset, on); } +// Convert standard (military/24hr) time to nr. of minutes since midnight. uint16_t IRPanasonicAc::encodeTime(const uint8_t hours, const uint8_t mins) { return std::min(hours, (uint8_t)23) * 60 + std::min(mins, (uint8_t)59); } -uint16_t IRPanasonicAc::getClock(void) { - uint16_t result = ((remote_state[25] & 0b00000111) << 8) + remote_state[24]; +uint16_t IRPanasonicAc::_getTime(const uint8_t ptr[]) { + uint16_t result = (GETBITS8( + ptr[1], kLowNibble, kPanasonicAcTimeOverflowSize) << + (kPanasonicAcTimeSize - kPanasonicAcTimeOverflowSize)) + ptr[0]; if (result == kPanasonicAcTimeSpecial) return 0; return result; } +uint16_t IRPanasonicAc::getClock(void) { return _getTime(&remote_state[24]); } + +void IRPanasonicAc::_setTime(uint8_t * const ptr, + const uint16_t mins_since_midnight, + const bool round_down) { + uint16_t corrected = std::min(mins_since_midnight, kPanasonicAcTimeMax); + if (round_down) corrected -= corrected % 10; + if (mins_since_midnight == kPanasonicAcTimeSpecial) + corrected = kPanasonicAcTimeSpecial; + ptr[0] = corrected; + setBits(&ptr[1], kLowNibble, kPanasonicAcTimeOverflowSize, + corrected >> (kPanasonicAcTimeSize - kPanasonicAcTimeOverflowSize)); +} + void IRPanasonicAc::setClock(const uint16_t mins_since_midnight) { - uint16_t corrected = std::min(mins_since_midnight, kPanasonicAcTimeMax); - if (mins_since_midnight == kPanasonicAcTimeSpecial) - corrected = kPanasonicAcTimeSpecial; - remote_state[24] = corrected & 0xFF; - remote_state[25] &= 0b11111000; - remote_state[25] |= (corrected >> 8); + _setTime(&remote_state[24], mins_since_midnight, false); } -uint16_t IRPanasonicAc::getOnTimer(void) { - uint16_t result = ((remote_state[19] & 0b00000111) << 8) + remote_state[18]; - if (result == kPanasonicAcTimeSpecial) return 0; - return result; -} +uint16_t IRPanasonicAc::getOnTimer(void) { return _getTime(&remote_state[18]); } void IRPanasonicAc::setOnTimer(const uint16_t mins_since_midnight, const bool enable) { - // Ensure it's on a 10 minute boundary and no overflow. - uint16_t corrected = std::min(mins_since_midnight, kPanasonicAcTimeMax); - corrected -= corrected % 10; - if (mins_since_midnight == kPanasonicAcTimeSpecial) - corrected = kPanasonicAcTimeSpecial; - - if (enable) - remote_state[13] |= kPanasonicAcOnTimer; // Set the Ontimer flag. - else - remote_state[13] &= ~kPanasonicAcOnTimer; // Clear the Ontimer flag. + // Set the timer flag. + setBit(&remote_state[13], kPanasonicAcOnTimerOffset, enable); // Store the time. - remote_state[18] = corrected & 0xFF; - remote_state[19] &= 0b11111000; - remote_state[19] |= (corrected >> 8); + _setTime(&remote_state[18], mins_since_midnight, true); } void IRPanasonicAc::cancelOnTimer(void) { this->setOnTimer(0, false); } bool IRPanasonicAc::isOnTimerEnabled(void) { - return remote_state[13] & kPanasonicAcOnTimer; + return GETBIT8(remote_state[13], kPanasonicAcOnTimerOffset); } uint16_t IRPanasonicAc::getOffTimer(void) { - uint16_t result = - ((remote_state[20] & 0b01111111) << 4) + (remote_state[19] >> 4); + uint16_t result = (GETBITS8(remote_state[20], 0, 7) << kNibbleSize) | + GETBITS8(remote_state[19], kHighNibble, kNibbleSize); if (result == kPanasonicAcTimeSpecial) return 0; return result; } @@ -578,55 +575,39 @@ void IRPanasonicAc::setOffTimer(const uint16_t mins_since_midnight, corrected -= corrected % 10; if (mins_since_midnight == kPanasonicAcTimeSpecial) corrected = kPanasonicAcTimeSpecial; - - if (enable) - remote_state[13] |= kPanasonicAcOffTimer; // Set the OffTimer flag. - else - remote_state[13] &= ~kPanasonicAcOffTimer; // Clear the OffTimer flag. + // Set the timer flag. + setBit(&remote_state[13], kPanasonicAcOffTimerOffset, enable); // Store the time. - remote_state[19] &= 0b00001111; - remote_state[19] |= (corrected & 0b00001111) << 4; - remote_state[20] &= 0b10000000; - remote_state[20] |= corrected >> 4; + setBits(&remote_state[19], kHighNibble, kNibbleSize, corrected); + setBits(&remote_state[20], 0, 7, corrected >> kNibbleSize); } void IRPanasonicAc::cancelOffTimer(void) { this->setOffTimer(0, false); } bool IRPanasonicAc::isOffTimerEnabled(void) { - return remote_state[13] & kPanasonicAcOffTimer; + return GETBIT8(remote_state[13], kPanasonicAcOffTimerOffset); } // Convert a standard A/C mode into its native mode. uint8_t IRPanasonicAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kPanasonicAcCool; - case stdAc::opmode_t::kHeat: - return kPanasonicAcHeat; - case stdAc::opmode_t::kDry: - return kPanasonicAcDry; - case stdAc::opmode_t::kFan: - return kPanasonicAcFan; - default: - return kPanasonicAcAuto; + case stdAc::opmode_t::kCool: return kPanasonicAcCool; + case stdAc::opmode_t::kHeat: return kPanasonicAcHeat; + case stdAc::opmode_t::kDry: return kPanasonicAcDry; + case stdAc::opmode_t::kFan: return kPanasonicAcFan; + default: return kPanasonicAcAuto; } } // Convert a standard A/C Fan speed into its native fan speed. uint8_t IRPanasonicAc::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { - case stdAc::fanspeed_t::kMin: - return kPanasonicAcFanMin; - case stdAc::fanspeed_t::kLow: - return kPanasonicAcFanMin + 1; - case stdAc::fanspeed_t::kMedium: - return kPanasonicAcFanMin + 2; - case stdAc::fanspeed_t::kHigh: - return kPanasonicAcFanMin + 3; - case stdAc::fanspeed_t::kMax: - return kPanasonicAcFanMax; - default: - return kPanasonicAcFanAuto; + case stdAc::fanspeed_t::kMin: return kPanasonicAcFanMin; + case stdAc::fanspeed_t::kLow: return kPanasonicAcFanMin + 1; + case stdAc::fanspeed_t::kMedium: return kPanasonicAcFanMin + 2; + case stdAc::fanspeed_t::kHigh: return kPanasonicAcFanMin + 3; + case stdAc::fanspeed_t::kMax: return kPanasonicAcFanMax; + default: return kPanasonicAcFanAuto; } } @@ -636,30 +617,21 @@ uint8_t IRPanasonicAc::convertSwingV(const stdAc::swingv_t position) { case stdAc::swingv_t::kHighest: case stdAc::swingv_t::kHigh: case stdAc::swingv_t::kMiddle: - return kPanasonicAcSwingVUp; case stdAc::swingv_t::kLow: - case stdAc::swingv_t::kLowest: - return kPanasonicAcSwingVDown; - default: - return kPanasonicAcSwingVAuto; + case stdAc::swingv_t::kLowest: return (uint8_t)position; + default: return kPanasonicAcSwingVAuto; } } // Convert a standard A/C horizontal swing into its native setting. uint8_t IRPanasonicAc::convertSwingH(const stdAc::swingh_t position) { switch (position) { - case stdAc::swingh_t::kLeftMax: - return kPanasonicAcSwingHFullLeft; - case stdAc::swingh_t::kLeft: - return kPanasonicAcSwingHLeft; - case stdAc::swingh_t::kMiddle: - return kPanasonicAcSwingHMiddle; - case stdAc::swingh_t::kRight: - return kPanasonicAcSwingHRight; - case stdAc::swingh_t::kRightMax: - return kPanasonicAcSwingHFullRight; - default: - return kPanasonicAcSwingHAuto; + case stdAc::swingh_t::kLeftMax: return kPanasonicAcSwingHFullLeft; + case stdAc::swingh_t::kLeft: return kPanasonicAcSwingHLeft; + case stdAc::swingh_t::kMiddle: return kPanasonicAcSwingHMiddle; + case stdAc::swingh_t::kRight: return kPanasonicAcSwingHRight; + case stdAc::swingh_t::kRightMax: return kPanasonicAcSwingHFullRight; + default: return kPanasonicAcSwingHAuto; } } @@ -668,43 +640,42 @@ stdAc::opmode_t IRPanasonicAc::toCommonMode(const uint8_t mode) { switch (mode) { case kPanasonicAcCool: return stdAc::opmode_t::kCool; case kPanasonicAcHeat: return stdAc::opmode_t::kHeat; - case kPanasonicAcDry: return stdAc::opmode_t::kDry; - case kPanasonicAcFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kPanasonicAcDry: return stdAc::opmode_t::kDry; + case kPanasonicAcFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } // Convert a native fan speed to it's common equivalent. stdAc::fanspeed_t IRPanasonicAc::toCommonFanSpeed(const uint8_t spd) { switch (spd) { - case kPanasonicAcFanMax: return stdAc::fanspeed_t::kMax; + case kPanasonicAcFanMax: return stdAc::fanspeed_t::kMax; case kPanasonicAcFanMin + 3: return stdAc::fanspeed_t::kHigh; case kPanasonicAcFanMin + 2: return stdAc::fanspeed_t::kMedium; case kPanasonicAcFanMin + 1: return stdAc::fanspeed_t::kLow; - case kPanasonicAcFanMin: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kPanasonicAcFanMin: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } // Convert a native vertical swing to it's common equivalent. stdAc::swingh_t IRPanasonicAc::toCommonSwingH(const uint8_t pos) { switch (pos) { - case kPanasonicAcSwingHFullLeft: return stdAc::swingh_t::kLeftMax; - case kPanasonicAcSwingHLeft: return stdAc::swingh_t::kLeft; - case kPanasonicAcSwingHMiddle: return stdAc::swingh_t::kMiddle; - case kPanasonicAcSwingHRight: return stdAc::swingh_t::kRight; + case kPanasonicAcSwingHFullLeft: return stdAc::swingh_t::kLeftMax; + case kPanasonicAcSwingHLeft: return stdAc::swingh_t::kLeft; + case kPanasonicAcSwingHMiddle: return stdAc::swingh_t::kMiddle; + case kPanasonicAcSwingHRight: return stdAc::swingh_t::kRight; case kPanasonicAcSwingHFullRight: return stdAc::swingh_t::kRightMax; - default: return stdAc::swingh_t::kAuto; + default: return stdAc::swingh_t::kAuto; } } // Convert a native vertical swing to it's common equivalent. stdAc::swingv_t IRPanasonicAc::toCommonSwingV(const uint8_t pos) { - switch (pos) { - case kPanasonicAcSwingVUp: return stdAc::swingv_t::kHighest; - case kPanasonicAcSwingVDown: return stdAc::swingv_t::kLowest; - default: return stdAc::swingv_t::kAuto; - } + if (pos >= kPanasonicAcSwingVHighest && pos <= kPanasonicAcSwingVLowest) + return (stdAc::swingv_t)pos; + else + return stdAc::swingv_t::kAuto; } // Convert the A/C state to it's common equivalent. @@ -736,95 +707,80 @@ stdAc::state_t IRPanasonicAc::toCommon(void) { String IRPanasonicAc::toString(void) { String result = ""; result.reserve(180); // Reserve some heap for the string to reduce fragging. - result += F("Model: "); - result += uint64ToString(getModel()); - switch (getModel()) { - case kPanasonicDke: - result += F(" (DKE)"); - break; - case kPanasonicJke: - result += F(" (JKE)"); - break; - case kPanasonicNke: - result += F(" (NKE)"); - break; - case kPanasonicLke: - result += F(" (LKE)"); - break; - case kPanasonicCkp: - result += F(" (CKP)"); - break; - case kPanasonicRkr: - result += F(" (RKR)"); - break; - default: - result += F(" (UNKNOWN)"); - } - result += addBoolToString(getPower(), F("Power")); + result += addModelToString(decode_type_t::PANASONIC_AC, getModel(), false); + result += addBoolToString(getPower(), kPowerStr); result += addModeToString(getMode(), kPanasonicAcAuto, kPanasonicAcCool, kPanasonicAcHeat, kPanasonicAcDry, kPanasonicAcFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kPanasonicAcFanMax, kPanasonicAcFanMin, kPanasonicAcFanAuto, kPanasonicAcFanAuto, kPanasonicAcFanMed); - result += addIntToString(getSwingVertical(), F("Swing (Vertical)")); + result += addIntToString(getSwingVertical(), kSwingVStr); + result += kSpaceLBraceStr; switch (getSwingVertical()) { case kPanasonicAcSwingVAuto: - result += F(" (AUTO)"); + result += kAutoStr; break; - case kPanasonicAcSwingVUp: - result += F(" (Full Up)"); + case kPanasonicAcSwingVHighest: + result += kHighestStr; break; - case kPanasonicAcSwingVDown: - result += F(" (Full Down)"); + case kPanasonicAcSwingVHigh: + result += kHighStr; break; - case 2: - case 3: - case 4: + case kPanasonicAcSwingVMiddle: + result += kMiddleStr; + break; + case kPanasonicAcSwingVLow: + result += kLowStr; + break; + case kPanasonicAcSwingVLowest: + result += kLowestStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; break; } + result += ')'; switch (getModel()) { case kPanasonicJke: case kPanasonicCkp: break; // No Horizontal Swing support. default: - result += addIntToString(getSwingHorizontal(), F("Swing (Horizontal)")); + result += addIntToString(getSwingHorizontal(), kSwingHStr); + result += kSpaceLBraceStr; switch (getSwingHorizontal()) { case kPanasonicAcSwingHAuto: - result += F(" (AUTO)"); + result += kAutoStr; break; case kPanasonicAcSwingHFullLeft: - result += F(" (Full Left)"); + result += kMaxLeftStr; break; case kPanasonicAcSwingHLeft: - result += F(" (Left)"); + result += kLeftStr; break; case kPanasonicAcSwingHMiddle: - result += F(" (Middle)"); + result += kMiddleStr; break; case kPanasonicAcSwingHFullRight: - result += F(" (Full Right)"); + result += kMaxRightStr; break; case kPanasonicAcSwingHRight: - result += F(" (Right)"); + result += kRightStr; break; default: - result += F(" (UNKNOWN)"); - break; + result += kUnknownStr; } + result += ')'; } - result += addBoolToString(getQuiet(), F("Quiet")); - result += addBoolToString(getPowerful(), F("Powerful")); - result += addLabeledString(minsToString(getClock()), F("Clock")); + result += addBoolToString(getQuiet(), kQuietStr); + result += addBoolToString(getPowerful(), kPowerfulStr); + result += addLabeledString(minsToString(getClock()), kClockStr); result += addLabeledString( - isOnTimerEnabled() ? minsToString(getOnTimer()) : F("Off"), - F("On Timer")); + isOnTimerEnabled() ? minsToString(getOnTimer()) : kOffStr, + kOnTimerStr); result += addLabeledString( - isOffTimerEnabled() ? minsToString(getOffTimer()) : F("Off"), - F("Off Timer")); + isOffTimerEnabled() ? minsToString(getOffTimer()) : kOffStr, + kOffTimerStr); return result; } @@ -894,7 +850,7 @@ bool IRrecv::decodePanasonicAC(decode_results *results, const uint16_t nbits, } // Success - results->decode_type = PANASONIC_AC; + results->decode_type = decode_type_t::PANASONIC_AC; results->bits = nbits; return true; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.h b/lib/IRremoteESP8266-2.7.0/src/ir_Panasonic.h old mode 100755 new mode 100644 similarity index 70% rename from lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Panasonic.h index 32899db9b..89c2e5395 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Panasonic.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Panasonic.h @@ -42,37 +42,45 @@ const uint16_t kPanasonicAcExcess = 0; // Much higher than usual. See issue #540. const uint16_t kPanasonicAcTolerance = 40; -const uint8_t kPanasonicAcAuto = 0; // 0b0000 -const uint8_t kPanasonicAcDry = 2; // 0b0010 -const uint8_t kPanasonicAcCool = 3; // 0b0011 -const uint8_t kPanasonicAcHeat = 4; // 0b0010 -const uint8_t kPanasonicAcFan = 6; // 0b0110 +const uint8_t kPanasonicAcAuto = 0; // 0b000 +const uint8_t kPanasonicAcDry = 2; // 0b010 +const uint8_t kPanasonicAcCool = 3; // 0b011 +const uint8_t kPanasonicAcHeat = 4; // 0b010 +const uint8_t kPanasonicAcFan = 6; // 0b110 const uint8_t kPanasonicAcFanMin = 0; const uint8_t kPanasonicAcFanMed = 2; const uint8_t kPanasonicAcFanMax = 4; const uint8_t kPanasonicAcFanAuto = 7; -const uint8_t kPanasonicAcFanOffset = 3; -const uint8_t kPanasonicAcPower = 1; // 0b1 +const uint8_t kPanasonicAcFanDelta = 3; +const uint8_t kPanasonicAcPowerOffset = 0; +const uint8_t kPanasonicAcTempOffset = 1; // Bits +const uint8_t kPanasonicAcTempSize = 5; // Bits const uint8_t kPanasonicAcMinTemp = 16; // Celsius const uint8_t kPanasonicAcMaxTemp = 30; // Celsius const uint8_t kPanasonicAcFanModeTemp = 27; // Celsius -const uint8_t kPanasonicAcQuiet = 1; // 0b1 -const uint8_t kPanasonicAcPowerful = 0x20; // 0b100000 +const uint8_t kPanasonicAcQuietOffset = 0; +const uint8_t kPanasonicAcPowerfulOffset = 5; // 0b100000 // CKP & RKR models have Powerful and Quiet bits swapped. -const uint8_t kPanasonicAcQuietCkp = 0x20; // 0b100000 -const uint8_t kPanasonicAcPowerfulCkp = 1; // 0b1 -const uint8_t kPanasonicAcSwingVAuto = 0xF; -const uint8_t kPanasonicAcSwingVUp = 0x1; -const uint8_t kPanasonicAcSwingVDown = 0x5; -const uint8_t kPanasonicAcSwingHAuto = 0xD; -const uint8_t kPanasonicAcSwingHMiddle = 0x6; -const uint8_t kPanasonicAcSwingHFullLeft = 0x9; -const uint8_t kPanasonicAcSwingHLeft = 0xA; -const uint8_t kPanasonicAcSwingHRight = 0xB; -const uint8_t kPanasonicAcSwingHFullRight = 0xC; +const uint8_t kPanasonicAcQuietCkpOffset = kPanasonicAcPowerfulOffset; +const uint8_t kPanasonicAcPowerfulCkpOffset = kPanasonicAcQuietOffset; +const uint8_t kPanasonicAcSwingVHighest = 0x1; // 0b0001 +const uint8_t kPanasonicAcSwingVHigh = 0x2; // 0b0010 +const uint8_t kPanasonicAcSwingVMiddle = 0x3; // 0b0011 +const uint8_t kPanasonicAcSwingVLow = 0x4; // 0b0100 +const uint8_t kPanasonicAcSwingVLowest = 0x5; // 0b0101 +const uint8_t kPanasonicAcSwingVAuto = 0xF; // 0b1111 + +const uint8_t kPanasonicAcSwingHMiddle = 0x6; // 0b0110 +const uint8_t kPanasonicAcSwingHFullLeft = 0x9; // 0b1001 +const uint8_t kPanasonicAcSwingHLeft = 0xA; // 0b1010 +const uint8_t kPanasonicAcSwingHRight = 0xB; // 0b1011 +const uint8_t kPanasonicAcSwingHFullRight = 0xC; // 0b1100 +const uint8_t kPanasonicAcSwingHAuto = 0xD; // 0b1101 const uint8_t kPanasonicAcChecksumInit = 0xF4; -const uint8_t kPanasonicAcOnTimer = 0b00000010; -const uint8_t kPanasonicAcOffTimer = 0b00000100; +const uint8_t kPanasonicAcOnTimerOffset = 1; +const uint8_t kPanasonicAcOffTimerOffset = 2; +const uint8_t kPanasonicAcTimeSize = 11; // Bits +const uint8_t kPanasonicAcTimeOverflowSize = 3; // Bits const uint16_t kPanasonicAcTimeMax = 23 * 60 + 59; // Mins since midnight. const uint16_t kPanasonicAcTimeSpecial = 0x600; @@ -81,15 +89,6 @@ const uint8_t kPanasonicKnownGoodState[kPanasonicAcStateLength] = { 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00}; -enum panasonic_ac_remote_model_t { - kPanasonicUnknown = 0, - kPanasonicLke = 1, - kPanasonicNke = 2, - kPanasonicDke = 3, - kPanasonicJke = 4, - kPanasonicCkp = 5, - kPanasonicRkr = 6, -}; class IRPanasonicAc { public: @@ -140,10 +139,10 @@ class IRPanasonicAc { const bool enable = true); void cancelOffTimer(void); bool isOffTimerEnabled(void); - uint8_t convertMode(const stdAc::opmode_t mode); - uint8_t convertFan(const stdAc::fanspeed_t speed); - uint8_t convertSwingV(const stdAc::swingv_t position); - uint8_t convertSwingH(const stdAc::swingh_t position); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + static uint8_t convertSwingV(const stdAc::swingv_t position); + static uint8_t convertSwingH(const stdAc::swingh_t position); static stdAc::opmode_t toCommonMode(const uint8_t mode); static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); static stdAc::swingv_t toCommonSwingV(const uint8_t pos); @@ -163,6 +162,9 @@ class IRPanasonicAc { void fixChecksum(const uint16_t length = kPanasonicAcStateLength); static uint8_t calcChecksum(const uint8_t *state, const uint16_t length = kPanasonicAcStateLength); + static uint16_t _getTime(const uint8_t ptr[]); + static void _setTime(uint8_t * const ptr, const uint16_t mins_since_midnight, + const bool round_down); }; #endif // IR_PANASONIC_H_ diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Pioneer.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Pioneer.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Pioneer.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Pioneer.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Pronto.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Pronto.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Pronto.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Pronto.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_RC5_RC6.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_RC5_RC6.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_RC5_RC6.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_RC5_RC6.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_RCMM.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_RCMM.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_RCMM.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_RCMM.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Samsung.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Samsung.cpp old mode 100755 new mode 100644 similarity index 80% rename from lib/IRremoteESP8266-2.6.5/src/ir_Samsung.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Samsung.cpp index 77985b1c4..1ca7a2b4a --- a/lib/IRremoteESP8266-2.6.5/src/ir_Samsung.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Samsung.cpp @@ -5,11 +5,13 @@ #include "ir_Samsung.h" #include +#include #ifndef ARDUINO #include #endif #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Samsung originally added from https://github.com/shirriff/Arduino-IRremote/ @@ -56,6 +58,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_SAMSUNG // Send a Samsung formatted message. @@ -285,7 +289,7 @@ void IRsend::sendSamsungAC(const uint8_t data[], const uint16_t nbytes, 38000, false, 0, 50); // Send in LSBF order } // Complete made up guess at inter-message gap. - space(100000 - kSamsungAcSectionGap); + space(kDefaultMessageGap - kSamsungAcSectionGap); } } #endif // SEND_SAMSUNG_AC @@ -296,20 +300,18 @@ IRSamsungAc::IRSamsungAc(const uint16_t pin, const bool inverted, this->stateReset(); } -void IRSamsungAc::stateReset(void) { - for (uint8_t i = 0; i < kSamsungAcExtendedStateLength; i++) - remote_state[i] = 0x0; - remote_state[0] = 0x02; - remote_state[1] = 0x92; - remote_state[2] = 0x0F; - remote_state[6] = 0xF0; - remote_state[7] = 0x01; - remote_state[8] = 0x02; - remote_state[9] = 0xAE; - remote_state[10] = 0x71; - remote_state[12] = 0x15; - remote_state[13] = 0xF0; - _sendpower = false; +// Reset the internal state of the emulation. +// Args: +// forcepower: A flag indicating if force sending a special power message +// with the first `send()` call. Default: true +void IRSamsungAc::stateReset(const bool forcepower, const bool initialPower) { + static const uint8_t kReset[kSamsungAcExtendedStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x02, 0xAE, 0x71, 0x00, + 0x15, 0xF0}; + memcpy(remote_state, kReset, kSamsungAcExtendedStateLength); + _forcepower = forcepower; + _lastsentpowerstate = initialPower; + setPower(initialPower); } void IRSamsungAc::begin(void) { _irsend.begin(); } @@ -323,10 +325,10 @@ uint8_t IRSamsungAc::calcChecksum(const uint8_t state[], // https://github.com/adafruit/Raw-IR-decoder-for-Arduino/pull/3/files // Count most of the '1' bits after the checksum location. sum += countBits(state[length - 7], 8); - sum -= countBits(state[length - 6] & 0xF, 8); - sum += countBits(state[length - 5] & 0b11111110, 8); + sum -= countBits(GETBITS8(state[length - 6], kLowNibble, kNibbleSize), 8); + sum += countBits(GETBITS8(state[length - 5], 1, 7), 8); sum += countBits(state + length - 4, 3); - return (28 - sum) & 0xF; + return GETBITS8(28 - sum, kLowNibble, kNibbleSize); } bool IRSamsungAc::validChecksum(const uint8_t state[], const uint16_t length) { @@ -334,19 +336,19 @@ bool IRSamsungAc::validChecksum(const uint8_t state[], const uint16_t length) { return true; // No checksum to compare with. Assume okay. uint8_t offset = 0; if (length >= kSamsungAcExtendedStateLength) offset = 7; - return ((state[length - 6] >> 4) == IRSamsungAc::calcChecksum(state, length) - && (state[length - (13 + offset)] >> 4) == IRSamsungAc::calcChecksum( - state, length - (7 + offset))); + return (GETBITS8(state[length - 6], kHighNibble, kNibbleSize) == + IRSamsungAc::calcChecksum(state, length)) && + (GETBITS8(state[length - (13 + offset)], kHighNibble, kNibbleSize) == + IRSamsungAc::calcChecksum(state, length - (7 + offset))); } // Update the checksum for the internal state. void IRSamsungAc::checksum(uint16_t length) { if (length < 13) return; - remote_state[length - 6] &= 0x0F; - remote_state[length - 6] |= (this->calcChecksum(remote_state, length) << 4); - remote_state[length - 13] &= 0x0F; - remote_state[length - 13] |= (this->calcChecksum(remote_state, - length - 7) << 4); + setBits(&remote_state[length - 6], kHighNibble, kNibbleSize, + this->calcChecksum(remote_state, length)); + setBits(&remote_state[length - 13], kHighNibble, kNibbleSize, + this->calcChecksum(remote_state, length - 7)); } #if SEND_SAMSUNG_AC @@ -354,12 +356,13 @@ void IRSamsungAc::checksum(uint16_t length) { // i.e. When the device is already running. void IRSamsungAc::send(const uint16_t repeat, const bool calcchecksum) { if (calcchecksum) this->checksum(); - if (_sendpower) { // Do we need to send a the special power on/off message? - _sendpower = false; // It will now been sent. + // Do we need to send a the special power on/off message? + if (this->getPower() != _lastsentpowerstate || _forcepower) { + _forcepower = false; // It will now been sent, so clear the flag if set. if (this->getPower()) { - this->sendOn(); + this->sendOn(repeat); } else { - this->sendOff(); + this->sendOff(repeat); return; // No point sending anything else if we are turning the unit off. } } @@ -395,6 +398,7 @@ void IRSamsungAc::sendOn(const uint16_t repeat) { 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; _irsend.sendSamsungAC(extended_state, kSamsungAcExtendedStateLength, repeat); + _lastsentpowerstate = true; // On } // Send the special extended "Off" message as the library can't seem to @@ -406,6 +410,7 @@ void IRSamsungAc::sendOff(const uint16_t repeat) { 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; _irsend.sendSamsungAC(extended_state, kSamsungAcExtendedStateLength, repeat); + _lastsentpowerstate = false; // Off } #endif // SEND_SAMSUNG_AC @@ -415,9 +420,8 @@ uint8_t *IRSamsungAc::getRaw(void) { } void IRSamsungAc::setRaw(const uint8_t new_code[], const uint16_t length) { - for (uint8_t i = 0; i < length && i < kSamsungAcExtendedStateLength; i++) { - remote_state[i] = new_code[i]; - } + memcpy(remote_state, new_code, std::min(length, + kSamsungAcExtendedStateLength)); // Shrink the extended state into a normal state. if (length > kSamsungAcStateLength) { for (uint8_t i = kSamsungAcStateLength; i < length; i++) @@ -425,48 +429,41 @@ void IRSamsungAc::setRaw(const uint8_t new_code[], const uint16_t length) { } } -void IRSamsungAc::on(void) { - remote_state[1] &= ~kSamsungAcPowerMask1; // Bit needs to be cleared. - remote_state[6] |= kSamsungAcPowerMask6; // Bit needs to be set. - _sendpower = true; // Flag that we need to send the special power message(s). -} +void IRSamsungAc::on(void) { setPower(true); } -void IRSamsungAc::off(void) { - remote_state[1] |= kSamsungAcPowerMask1; // Bit needs to be set. - remote_state[6] &= ~kSamsungAcPowerMask6; // Bit needs to be cleared. - _sendpower = true; // Flag that we need to send the special power message(s). -} +void IRSamsungAc::off(void) { setPower(false); } void IRSamsungAc::setPower(const bool on) { - if (on) - this->on(); - else - this->off(); + setBit(&remote_state[1], kSamsungAcPower1Offset, !on); // Cleared when on. + setBits(&remote_state[6], kSamsungAcPower6Offset, kSamsungAcPower6Size, + on ? 0b11 : 0b00); } bool IRSamsungAc::getPower(void) { - return (remote_state[6] & kSamsungAcPowerMask6) && - !(remote_state[1] & kSamsungAcPowerMask1); + return (GETBITS8(remote_state[6], kSamsungAcPower6Offset, + kSamsungAcPower6Size) == 0b11) && + !GETBIT8(remote_state[1], kSamsungAcPower1Offset); } // Set the temp. in deg C void IRSamsungAc::setTemp(const uint8_t temp) { uint8_t newtemp = std::max(kSamsungAcMinTemp, temp); newtemp = std::min(kSamsungAcMaxTemp, newtemp); - remote_state[11] = (remote_state[11] & ~kSamsungAcTempMask) | - ((newtemp - kSamsungAcMinTemp) << 4); + setBits(&remote_state[11], kHighNibble, kNibbleSize, + newtemp - kSamsungAcMinTemp); } // Return the set temp. in deg C uint8_t IRSamsungAc::getTemp(void) { - return ((remote_state[11] & kSamsungAcTempMask) >> 4) + kSamsungAcMinTemp; + return GETBITS8(remote_state[11], kHighNibble, kNibbleSize) + + kSamsungAcMinTemp; } void IRSamsungAc::setMode(const uint8_t mode) { // If we get an unexpected mode, default to AUTO. uint8_t newmode = mode; if (newmode > kSamsungAcHeat) newmode = kSamsungAcAuto; - remote_state[12] = (remote_state[12] & ~kSamsungAcModeMask) | (newmode << 4); + setBits(&remote_state[12], kSamsungAcModeOffset, kModeBitsSize, newmode); // Auto mode has a special fan setting valid only in auto mode. if (newmode == kSamsungAcAuto) { @@ -479,7 +476,7 @@ void IRSamsungAc::setMode(const uint8_t mode) { } uint8_t IRSamsungAc::getMode(void) { - return (remote_state[12] & kSamsungAcModeMask) >> 4; + return GETBITS8(remote_state[12], kSamsungAcModeOffset, kModeBitsSize); } void IRSamsungAc::setFan(const uint8_t speed) { @@ -497,89 +494,77 @@ void IRSamsungAc::setFan(const uint8_t speed) { default: return; } - remote_state[12] = (remote_state[12] & ~kSamsungAcFanMask) | (speed << 1); + setBits(&remote_state[12], kSamsungAcFanOffest, kSamsungAcFanSize, speed); } uint8_t IRSamsungAc::getFan(void) { - return ((remote_state[12] & kSamsungAcFanMask) >> 1); + return GETBITS8(remote_state[12], kSamsungAcFanOffest, kSamsungAcFanSize); } bool IRSamsungAc::getSwing(void) { // TODO(Hollako): Explain why sometimes the LSB of remote_state[9] is a 1. // e.g. 0xAE or 0XAF for swing move. - return ((remote_state[9] & kSamsungAcSwingMask) >> 4) == kSamsungAcSwingMove; + return GETBITS8(remote_state[9], kSamsungAcSwingOffset, + kSamsungAcSwingSize) == kSamsungAcSwingMove; } void IRSamsungAc::setSwing(const bool on) { // TODO(Hollako): Explain why sometimes the LSB of remote_state[9] is a 1. // e.g. 0xAE or 0XAF for swing move. - remote_state[9] &= ~kSamsungAcSwingMask; // Clear the previous swing state. - if (on) - remote_state[9] |= (kSamsungAcSwingMove << 4); - else - remote_state[9] |= (kSamsungAcSwingStop << 4); + setBits(&remote_state[9], kSamsungAcSwingOffset, kSamsungAcSwingSize, + on ? kSamsungAcSwingMove : kSamsungAcSwingStop); } bool IRSamsungAc::getBeep(void) { - return remote_state[13] & kSamsungAcBeepMask; + return GETBIT8(remote_state[13], kSamsungAcBeepOffset); } void IRSamsungAc::setBeep(const bool on) { - if (on) - remote_state[13] |= kSamsungAcBeepMask; - else - remote_state[13] &= ~kSamsungAcBeepMask; + setBit(&remote_state[13], kSamsungAcBeepOffset, on); } bool IRSamsungAc::getClean(void) { - return (remote_state[10] & kSamsungAcCleanMask10) && - (remote_state[11] & kSamsungAcCleanMask11); + return GETBIT8(remote_state[10], kSamsungAcClean10Offset) && + GETBIT8(remote_state[11], kSamsungAcClean11Offset); } void IRSamsungAc::setClean(const bool on) { - if (on) { - remote_state[10] |= kSamsungAcCleanMask10; - remote_state[11] |= kSamsungAcCleanMask11; - } else { - remote_state[10] &= ~kSamsungAcCleanMask10; - remote_state[11] &= ~kSamsungAcCleanMask11; - } + setBit(&remote_state[10], kSamsungAcClean10Offset, on); + setBit(&remote_state[11], kSamsungAcClean11Offset, on); } bool IRSamsungAc::getQuiet(void) { - return !(remote_state[1] & kSamsungAcQuietMask1) && - (remote_state[5] & kSamsungAcQuietMask5); + return !GETBIT8(remote_state[1], kSamsungAcQuiet1Offset) && + GETBIT8(remote_state[5], kSamsungAcQuiet5Offset); } void IRSamsungAc::setQuiet(const bool on) { + setBit(&remote_state[1], kSamsungAcQuiet1Offset, !on); // Cleared when on. + setBit(&remote_state[5], kSamsungAcQuiet5Offset, on); if (on) { - remote_state[1] &= ~kSamsungAcQuietMask1; // Bit needs to be cleared. - remote_state[5] |= kSamsungAcQuietMask5; // Bit needs to be set. // Quiet mode seems to set fan speed to auto. this->setFan(kSamsungAcFanAuto); this->setPowerful(false); // Quiet 'on' is mutually exclusive to Powerful. - } else { - remote_state[1] |= kSamsungAcQuietMask1; // Bit needs to be set. - remote_state[5] &= ~kSamsungAcQuietMask5; // Bit needs to be cleared. } } bool IRSamsungAc::getPowerful(void) { return !(remote_state[8] & kSamsungAcPowerfulMask8) && - (remote_state[10] & kSamsungAcPowerfulMask10) && - this->getFan() == kSamsungAcFanTurbo; + GETBITS8(remote_state[10], kSamsungAcPowerful10Offset, + kSamsungAcPowerful10Offset) && + (this->getFan() == kSamsungAcFanTurbo); } void IRSamsungAc::setPowerful(const bool on) { + setBits(&remote_state[10], kSamsungAcPowerful10Offset, + kSamsungAcPowerful10Offset, on ? 0b11: 0b00); if (on) { remote_state[8] &= ~kSamsungAcPowerfulMask8; // Bit needs to be cleared. - remote_state[10] |= kSamsungAcPowerfulMask10; // Bit needs to be set. // Powerful mode sets fan speed to Turbo. this->setFan(kSamsungAcFanTurbo); this->setQuiet(false); // Powerful 'on' is mutually exclusive to Quiet. } else { remote_state[8] |= kSamsungAcPowerfulMask8; // Bit needs to be set. - remote_state[10] &= ~kSamsungAcPowerfulMask10; // Bit needs to be cleared. // Turning off Powerful mode sets fan speed to Auto if we were in Turbo mode if (this->getFan() == kSamsungAcFanTurbo) this->setFan(kSamsungAcFanAuto); } @@ -588,16 +573,11 @@ void IRSamsungAc::setPowerful(const bool on) { // Convert a standard A/C mode into its native mode. uint8_t IRSamsungAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kSamsungAcCool; - case stdAc::opmode_t::kHeat: - return kSamsungAcHeat; - case stdAc::opmode_t::kDry: - return kSamsungAcDry; - case stdAc::opmode_t::kFan: - return kSamsungAcFan; - default: - return kSamsungAcAuto; + case stdAc::opmode_t::kCool: return kSamsungAcCool; + case stdAc::opmode_t::kHeat: return kSamsungAcHeat; + case stdAc::opmode_t::kDry: return kSamsungAcDry; + case stdAc::opmode_t::kFan: return kSamsungAcFan; + default: return kSamsungAcAuto; } } @@ -605,16 +585,11 @@ uint8_t IRSamsungAc::convertMode(const stdAc::opmode_t mode) { uint8_t IRSamsungAc::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kSamsungAcFanLow; - case stdAc::fanspeed_t::kMedium: - return kSamsungAcFanMed; - case stdAc::fanspeed_t::kHigh: - return kSamsungAcFanHigh; - case stdAc::fanspeed_t::kMax: - return kSamsungAcFanTurbo; - default: - return kSamsungAcFanAuto; + case stdAc::fanspeed_t::kLow: return kSamsungAcFanLow; + case stdAc::fanspeed_t::kMedium: return kSamsungAcFanMed; + case stdAc::fanspeed_t::kHigh: return kSamsungAcFanHigh; + case stdAc::fanspeed_t::kMax: return kSamsungAcFanTurbo; + default: return kSamsungAcFanAuto; } } @@ -623,9 +598,9 @@ stdAc::opmode_t IRSamsungAc::toCommonMode(const uint8_t mode) { switch (mode) { case kSamsungAcCool: return stdAc::opmode_t::kCool; case kSamsungAcHeat: return stdAc::opmode_t::kHeat; - case kSamsungAcDry: return stdAc::opmode_t::kDry; - case kSamsungAcFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kSamsungAcDry: return stdAc::opmode_t::kDry; + case kSamsungAcFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -633,10 +608,10 @@ stdAc::opmode_t IRSamsungAc::toCommonMode(const uint8_t mode) { stdAc::fanspeed_t IRSamsungAc::toCommonFanSpeed(const uint8_t spd) { switch (spd) { case kSamsungAcFanTurbo: return stdAc::fanspeed_t::kMax; - case kSamsungAcFanHigh: return stdAc::fanspeed_t::kHigh; - case kSamsungAcFanMed: return stdAc::fanspeed_t::kMedium; - case kSamsungAcFanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kSamsungAcFanHigh: return stdAc::fanspeed_t::kHigh; + case kSamsungAcFanMed: return stdAc::fanspeed_t::kMedium; + case kSamsungAcFanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } @@ -670,38 +645,40 @@ stdAc::state_t IRSamsungAc::toCommon(void) { String IRSamsungAc::toString(void) { String result = ""; result.reserve(100); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kSamsungAcAuto, kSamsungAcCool, kSamsungAcHeat, kSamsungAcDry, kSamsungAcFan); result += addTempToString(getTemp()); - result += addIntToString(getFan(), F("Fan")); + result += addIntToString(getFan(), kFanStr); + result += kSpaceLBraceStr; switch (getFan()) { case kSamsungAcFanAuto: case kSamsungAcFanAuto2: - result += F(" (Auto)"); + result += kAutoStr; break; case kSamsungAcFanLow: - result += F(" (Low)"); + result += kLowStr; break; case kSamsungAcFanMed: - result += F(" (Medium)"); + result += kMedStr; break; case kSamsungAcFanHigh: - result += F(" (High)"); + result += kHighStr; break; case kSamsungAcFanTurbo: - result += F(" (Turbo)"); + result += kTurboStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; break; } - result += addBoolToString(getSwing(), F("Swing")); - result += addBoolToString(getBeep(), F("Beep")); - result += addBoolToString(getClean(), F("Clean")); - result += addBoolToString(getQuiet(), F("Quiet")); - result += addBoolToString(getPowerful(), F("Powerful")); + result += ')'; + result += addBoolToString(getSwing(), kSwingStr); + result += addBoolToString(getBeep(), kBeepStr); + result += addBoolToString(getClean(), kCleanStr); + result += addBoolToString(getQuiet(), kQuietStr); + result += addBoolToString(getPowerful(), kPowerfulStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Samsung.h b/lib/IRremoteESP8266-2.7.0/src/ir_Samsung.h old mode 100755 new mode 100644 similarity index 77% rename from lib/IRremoteESP8266-2.6.5/src/ir_Samsung.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Samsung.h index 1a2be79bb..de2172444 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Samsung.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Samsung.h @@ -31,7 +31,9 @@ const uint8_t kSamsungAcCool = 1; const uint8_t kSamsungAcDry = 2; const uint8_t kSamsungAcFan = 3; const uint8_t kSamsungAcHeat = 4; -const uint8_t kSamsungAcModeMask = 0x70; // 0b01110000 +const uint8_t kSamsungAcModeOffset = 4; // Mask 0b01110000 +const uint8_t kSamsungAcFanOffest = 1; // Mask 0b00001110 +const uint8_t kSamsungAcFanSize = 3; // Bits const uint8_t kSamsungAcFanAuto = 0; const uint8_t kSamsungAcFanLow = 2; const uint8_t kSamsungAcFanMed = 4; @@ -41,20 +43,21 @@ const uint8_t kSamsungAcFanTurbo = 7; const uint8_t kSamsungAcMinTemp = 16; // 16C const uint8_t kSamsungAcMaxTemp = 30; // 30C const uint8_t kSamsungAcAutoTemp = 25; // 25C -const uint8_t kSamsungAcTempMask = 0xF0; // 0b11110000 -const uint8_t kSamsungAcPowerMask1 = 0x20; // 0b00100000 -const uint8_t kSamsungAcPowerMask6 = 0x30; // 0b00110000 -const uint8_t kSamsungAcFanMask = 0x0E; // 0b00001110 -const uint8_t kSamsungAcSwingMask = 0x70; // 0b01110000 +const uint8_t kSamsungAcPower1Offset = 5; +const uint8_t kSamsungAcPower6Offset = 4; // Mask 0b00110000 +const uint8_t kSamsungAcPower6Size = 2; // Bits +const uint8_t kSamsungAcSwingOffset = 4; // Mask 0b01110000 +const uint8_t kSamsungAcSwingSize = 3; // Bits const uint8_t kSamsungAcSwingMove = 0b010; const uint8_t kSamsungAcSwingStop = 0b111; -const uint8_t kSamsungAcBeepMask = 0x02; // 0b00000010 -const uint8_t kSamsungAcCleanMask10 = 0x80; // 0b10000000 -const uint8_t kSamsungAcCleanMask11 = 0x02; // 0b00000010 -const uint8_t kSamsungAcQuietMask1 = 0x10; // 0b00010000 -const uint8_t kSamsungAcQuietMask5 = 0x20; // 0b00100000 -const uint8_t kSamsungAcPowerfulMask8 = 0x50; // 0b01010000 -const uint8_t kSamsungAcPowerfulMask10 = 0x06; // 0b00000110 +const uint8_t kSamsungAcBeepOffset = 1; +const uint8_t kSamsungAcClean10Offset = 7; +const uint8_t kSamsungAcClean11Offset = 1; // 0b00000010 +const uint8_t kSamsungAcQuiet1Offset = 4; +const uint8_t kSamsungAcQuiet5Offset = 5; +const uint8_t kSamsungAcPowerfulMask8 = 0b01010000; +const uint8_t kSamsungAcPowerful10Offset = 1; // Mask 0b00000110 +const uint8_t kSamsungAcPowerful10Size = 1; // Mask 0b00000110 const uint16_t kSamsungACSectionLength = 7; const uint64_t kSamsungAcPowerSection = 0x1D20F00000000; @@ -65,7 +68,7 @@ class IRSamsungAc { explicit IRSamsungAc(const uint16_t pin, const bool inverted = false, const bool use_modulation = true); - void stateReset(void); + void stateReset(const bool forcepower = true, const bool initialPower = true); #if SEND_SAMSUNG_AC void send(const uint16_t repeat = kSamsungAcDefaultRepeat, const bool calcchecksum = true); @@ -118,7 +121,8 @@ class IRSamsungAc { #endif // The state of the IR remote in IR code form. uint8_t remote_state[kSamsungAcExtendedStateLength]; - bool _sendpower; // Hack to know when we need to send a special power mesg. + bool _forcepower; // Hack to know when we need to send a special power mesg. + bool _lastsentpowerstate; void checksum(const uint16_t length = kSamsungAcStateLength); }; diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Sanyo.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Sanyo.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Sanyo.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Sanyo.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Sharp.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Sharp.cpp old mode 100755 new mode 100644 similarity index 85% rename from lib/IRremoteESP8266-2.6.5/src/ir_Sharp.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Sharp.cpp index 250248554..abd93ecf6 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Sharp.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Sharp.cpp @@ -5,11 +5,13 @@ #include "ir_Sharp.h" #include +#include #ifndef ARDUINO #include #endif #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Equipment it seems compatible with: @@ -43,6 +45,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if (SEND_SHARP || SEND_DENON) // Send a (raw) Sharp message @@ -115,10 +119,10 @@ uint32_t IRsend::encodeSharp(const uint16_t address, const uint16_t command, const uint16_t expansion, const uint16_t check, const bool MSBfirst) { // Mask any unexpected bits. - uint16_t tempaddress = address & ((1 << kSharpAddressBits) - 1); - uint16_t tempcommand = command & ((1 << kSharpCommandBits) - 1); - uint16_t tempexpansion = expansion & 1; - uint16_t tempcheck = check & 1; + uint16_t tempaddress = GETBITS16(address, 0, kSharpAddressBits); + uint16_t tempcommand = GETBITS16(command, 0, kSharpCommandBits); + uint16_t tempexpansion = GETBITS16(expansion, 0, 1); + uint16_t tempcheck = GETBITS16(check, 0, 1); if (!MSBfirst) { // Correct bit order if needed. tempaddress = reverseBits(tempaddress, kSharpAddressBits); @@ -277,8 +281,7 @@ void IRSharpAc::begin(void) { _irsend.begin(); } #if SEND_SHARP_AC void IRSharpAc::send(const uint16_t repeat) { - this->checksum(); - _irsend.sendSharpAc(remote, kSharpAcStateLength, repeat); + _irsend.sendSharpAc(getRaw(), kSharpAcStateLength, repeat); } #endif // SEND_SHARP_AC @@ -290,9 +293,9 @@ void IRSharpAc::send(const uint16_t repeat) { // The 4 bit checksum. uint8_t IRSharpAc::calcChecksum(uint8_t state[], const uint16_t length) { uint8_t xorsum = xorBytes(state, length - 1); - xorsum ^= (state[length - 1] & 0xF); - xorsum ^= xorsum >> 4; - return xorsum & 0xF; + xorsum ^= GETBITS8(state[length - 1], kLowNibble, kNibbleSize); + xorsum ^= GETBITS8(xorsum, kHighNibble, kNibbleSize); + return GETBITS8(xorsum, kLowNibble, kNibbleSize); } // Verify the checksums are valid for a given state. @@ -302,20 +305,21 @@ uint8_t IRSharpAc::calcChecksum(uint8_t state[], const uint16_t length) { // Returns: // A boolean. bool IRSharpAc::validChecksum(uint8_t state[], const uint16_t length) { - return (state[length - 1] >> 4) == IRSharpAc::calcChecksum(state, length); + return GETBITS8(state[length - 1], kHighNibble, kNibbleSize) == + IRSharpAc::calcChecksum(state, length); } // Calculate and set the checksum values for the internal state. void IRSharpAc::checksum(void) { - remote[kSharpAcStateLength - 1] &= 0x0F; - remote[kSharpAcStateLength - 1] |= this->calcChecksum(remote) << 4; + setBits(&remote[kSharpAcStateLength - 1], kHighNibble, kNibbleSize, + this->calcChecksum(remote)); } void IRSharpAc::stateReset(void) { static const uint8_t reset[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0x00, 0x01, 0x00, 0x00, 0x08, 0x80, 0x00, 0xE0, 0x01}; - for (uint8_t i = 0; i < kSharpAcStateLength; i++) remote[i] = reset[i]; + memcpy(remote, reset, kSharpAcStateLength); } uint8_t *IRSharpAc::getRaw(void) { @@ -324,23 +328,19 @@ uint8_t *IRSharpAc::getRaw(void) { } void IRSharpAc::setRaw(const uint8_t new_code[], const uint16_t length) { - for (uint8_t i = 0; i < length && i < kSharpAcStateLength; i++) - remote[i] = new_code[i]; + memcpy(remote, new_code, std::min(length, kSharpAcStateLength)); } -void IRSharpAc::on(void) { remote[kSharpAcBytePower] |= kSharpAcBitPower; } +void IRSharpAc::on(void) { setPower(true); } -void IRSharpAc::off(void) { remote[kSharpAcBytePower] &= ~kSharpAcBitPower; } +void IRSharpAc::off(void) { setPower(false); } void IRSharpAc::setPower(const bool on) { - if (on) - this->on(); - else - this->off(); + setBit(&remote[kSharpAcBytePower], kSharpAcBitPowerOffset, on); } bool IRSharpAc::getPower(void) { - return remote[kSharpAcBytePower] & kSharpAcBitPower; + return GETBIT8(remote[kSharpAcBytePower], kSharpAcBitPowerOffset); } // Set the temp in deg C @@ -354,37 +354,34 @@ void IRSharpAc::setTemp(const uint8_t temp) { return; default: remote[kSharpAcByteTemp] = 0xC0; - remote[kSharpAcByteManual] |= kSharpAcBitTempManual; + setBit(&remote[kSharpAcByteManual], kSharpAcBitTempManualOffset); } uint8_t degrees = std::max(temp, kSharpAcMinTemp); degrees = std::min(degrees, kSharpAcMaxTemp); - remote[kSharpAcByteTemp] &= ~kSharpAcMaskTemp; - remote[kSharpAcByteTemp] |= (degrees - kSharpAcMinTemp); + setBits(&remote[kSharpAcByteTemp], kLowNibble, kNibbleSize, + degrees - kSharpAcMinTemp); } uint8_t IRSharpAc::getTemp(void) { - return (remote[kSharpAcByteTemp] & kSharpAcMaskTemp) + kSharpAcMinTemp; + return GETBITS8(remote[kSharpAcByteTemp], kLowNibble, kNibbleSize) + + kSharpAcMinTemp; } uint8_t IRSharpAc::getMode(void) { - return remote[kSharpAcByteMode] & kSharpAcMaskMode; + return GETBITS8(remote[kSharpAcByteMode], kLowNibble, kSharpAcModeSize); } void IRSharpAc::setMode(const uint8_t mode) { - const uint8_t special = 0x20; // Non-auto modes have this bit set. - remote[kSharpAcBytePower] |= special; + setBit(&remote[kSharpAcBytePower], kSharpAcBitModeNonAutoOffset, + mode != kSharpAcAuto); switch (mode) { case kSharpAcAuto: - remote[kSharpAcBytePower] &= ~special; // Auto has this bit cleared. - // FALLTHRU case kSharpAcDry: this->setTemp(0); // Dry/Auto have no temp setting. // FALLTHRU case kSharpAcCool: case kSharpAcHeat: - remote[kSharpAcByteMode] &= ~kSharpAcMaskMode; - remote[kSharpAcByteMode] |= mode; - + setBits(&remote[kSharpAcByteMode], kLowNibble, kSharpAcModeSize, mode); break; default: this->setMode(kSharpAcAuto); @@ -393,18 +390,16 @@ void IRSharpAc::setMode(const uint8_t mode) { // Set the speed of the fan void IRSharpAc::setFan(const uint8_t speed) { - remote[kSharpAcByteManual] |= kSharpAcBitFanManual; // Manual fan mode. switch (speed) { case kSharpAcFanAuto: - // Clear the manual fan bit. - remote[kSharpAcByteManual] &= ~kSharpAcBitFanManual; - // FALLTHRU case kSharpAcFanMin: case kSharpAcFanMed: case kSharpAcFanHigh: case kSharpAcFanMax: - remote[kSharpAcByteFan] &= ~kSharpAcMaskFan; - remote[kSharpAcByteFan] |= (speed << 4); + setBit(&remote[kSharpAcByteManual], kSharpAcBitFanManualOffset, + speed != kSharpAcFanAuto); + setBits(&remote[kSharpAcByteFan], kSharpAcFanOffset, kSharpAcFanSize, + speed); break; default: this->setFan(kSharpAcFanAuto); @@ -412,21 +407,17 @@ void IRSharpAc::setFan(const uint8_t speed) { } uint8_t IRSharpAc::getFan(void) { - return (remote[kSharpAcByteFan] & kSharpAcMaskFan) >> 4; + return GETBITS8(remote[kSharpAcByteFan], kSharpAcFanOffset, kSharpAcFanSize); } // Convert a standard A/C mode into its native mode. uint8_t IRSharpAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kSharpAcCool; - case stdAc::opmode_t::kHeat: - return kSharpAcHeat; - case stdAc::opmode_t::kDry: - return kSharpAcDry; + case stdAc::opmode_t::kCool: return kSharpAcCool; + case stdAc::opmode_t::kHeat: return kSharpAcHeat; + case stdAc::opmode_t::kDry: return kSharpAcDry; // No Fan mode. - default: - return kSharpAcAuto; + default: return kSharpAcAuto; } } @@ -434,16 +425,11 @@ uint8_t IRSharpAc::convertMode(const stdAc::opmode_t mode) { uint8_t IRSharpAc::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kSharpAcFanMin; - case stdAc::fanspeed_t::kMedium: - return kSharpAcFanMed; - case stdAc::fanspeed_t::kHigh: - return kSharpAcFanHigh; - case stdAc::fanspeed_t::kMax: - return kSharpAcFanMax; - default: - return kSharpAcFanAuto; + case stdAc::fanspeed_t::kLow: return kSharpAcFanMin; + case stdAc::fanspeed_t::kMedium: return kSharpAcFanMed; + case stdAc::fanspeed_t::kHigh: return kSharpAcFanHigh; + case stdAc::fanspeed_t::kMax: return kSharpAcFanMax; + default: return kSharpAcFanAuto; } } @@ -452,19 +438,19 @@ stdAc::opmode_t IRSharpAc::toCommonMode(const uint8_t mode) { switch (mode) { case kSharpAcCool: return stdAc::opmode_t::kCool; case kSharpAcHeat: return stdAc::opmode_t::kHeat; - case kSharpAcDry: return stdAc::opmode_t::kDry; - default: return stdAc::opmode_t::kAuto; + case kSharpAcDry: return stdAc::opmode_t::kDry; + default: return stdAc::opmode_t::kAuto; } } // Convert a native fan speed to it's common equivalent. stdAc::fanspeed_t IRSharpAc::toCommonFanSpeed(const uint8_t speed) { switch (speed) { - case kSharpAcFanMax: return stdAc::fanspeed_t::kMax; + case kSharpAcFanMax: return stdAc::fanspeed_t::kMax; case kSharpAcFanHigh: return stdAc::fanspeed_t::kHigh; - case kSharpAcFanMed: return stdAc::fanspeed_t::kMedium; - case kSharpAcFanMin: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kSharpAcFanMed: return stdAc::fanspeed_t::kMedium; + case kSharpAcFanMin: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } @@ -497,7 +483,7 @@ stdAc::state_t IRSharpAc::toCommon(void) { String IRSharpAc::toString(void) { String result = ""; result.reserve(60); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kSharpAcAuto, kSharpAcCool, kSharpAcHeat, kSharpAcDry, kSharpAcAuto); result += addTempToString(getTemp()); diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Sharp.h b/lib/IRremoteESP8266-2.7.0/src/ir_Sharp.h old mode 100755 new mode 100644 similarity index 87% rename from lib/IRremoteESP8266-2.6.5/src/ir_Sharp.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Sharp.h index e80c7cdde..e1c81c3a2 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Sharp.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Sharp.h @@ -37,16 +37,17 @@ const uint8_t kSharpAcFanMed = 0b011; // 3 (FAN2) const uint8_t kSharpAcFanHigh = 0b101; // 5 (FAN3) const uint8_t kSharpAcFanMax = 0b111; // 7 (FAN4) const uint8_t kSharpAcByteTemp = 4; -const uint8_t kSharpAcMaskTemp = 0b00001111; const uint8_t kSharpAcBytePower = 5; -const uint8_t kSharpAcBitPower = 0b00010000; +const uint8_t kSharpAcBitPowerOffset = 4; +const uint8_t kSharpAcBitModeNonAutoOffset = 5; // 0b00100000 const uint8_t kSharpAcByteMode = 6; -const uint8_t kSharpAcMaskMode = 0b00000011; +const uint8_t kSharpAcModeSize = 2; // Mask 0b00000011; const uint8_t kSharpAcByteFan = kSharpAcByteMode; -const uint8_t kSharpAcMaskFan = 0b01110000; +const uint8_t kSharpAcFanOffset = 4; // Mask 0b01110000 +const uint8_t kSharpAcFanSize = 3; // Nr. of Bits const uint8_t kSharpAcByteManual = 10; -const uint8_t kSharpAcBitFanManual = 0b00000001; -const uint8_t kSharpAcBitTempManual = 0b00000100; +const uint8_t kSharpAcBitFanManualOffset = 0; // 0b00000001 +const uint8_t kSharpAcBitTempManualOffset = 2; // 0b00000100 class IRSharpAc { diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Sherwood.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Sherwood.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Sherwood.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Sherwood.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Sony.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Sony.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Sony.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Sony.cpp diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Tcl.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Tcl.cpp old mode 100755 new mode 100644 similarity index 59% rename from lib/IRremoteESP8266-2.6.5/src/ir_Tcl.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Tcl.cpp index 0186f43e5..ff144e9c1 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Tcl.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Tcl.cpp @@ -2,10 +2,12 @@ #include "ir_Tcl.h" #include +#include #ifndef ARDUINO #include #endif #include "IRremoteESP8266.h" +#include "IRtext.h" #include "IRutils.h" // Constants @@ -16,6 +18,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_TCL112AC void IRsend::sendTcl112Ac(const unsigned char data[], const uint16_t nbytes, @@ -36,8 +40,7 @@ void IRTcl112Ac::begin(void) { this->_irsend.begin(); } #if SEND_TCL112AC void IRTcl112Ac::send(const uint16_t repeat) { - this->checksum(); - this->_irsend.sendTcl112Ac(remote_state, kTcl112AcStateLength, repeat); + this->_irsend.sendTcl112Ac(getRaw(), kTcl112AcStateLength, repeat); } #endif // SEND_TCL112AC @@ -47,8 +50,7 @@ void IRTcl112Ac::send(const uint16_t repeat) { // length: The size of the array. // Returns: // The 8 bit checksum value. -uint8_t IRTcl112Ac::calcChecksum(uint8_t state[], - const uint16_t length) { +uint8_t IRTcl112Ac::calcChecksum(uint8_t state[], const uint16_t length) { if (length) return sumBytes(state, length - 1); else @@ -73,18 +75,11 @@ bool IRTcl112Ac::validChecksum(uint8_t state[], const uint16_t length) { } void IRTcl112Ac::stateReset(void) { - for (uint8_t i = 0; i < kTcl112AcStateLength; i++) - remote_state[i] = 0x0; // A known good state. (On, Cool, 24C) - remote_state[0] = 0x23; - remote_state[1] = 0xCB; - remote_state[2] = 0x26; - remote_state[3] = 0x01; - remote_state[5] = 0x24; - remote_state[6] = 0x03; - remote_state[7] = 0x07; - remote_state[8] = 0x40; - remote_state[13] = 0x03; + static const uint8_t reset[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, 0x07, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x03}; + memcpy(remote_state, reset, kTcl112AcStateLength); } uint8_t* IRTcl112Ac::getRaw(void) { @@ -93,9 +88,7 @@ uint8_t* IRTcl112Ac::getRaw(void) { } void IRTcl112Ac::setRaw(const uint8_t new_code[], const uint16_t length) { - for (uint8_t i = 0; i < length && i < kTcl112AcStateLength; i++) { - remote_state[i] = new_code[i]; - } + memcpy(remote_state, new_code, std::min(length, kTcl112AcStateLength)); } // Set the requested power state of the A/C to on. @@ -106,15 +99,12 @@ void IRTcl112Ac::off(void) { this->setPower(false); } // Set the requested power state of the A/C. void IRTcl112Ac::setPower(const bool on) { - if (on) - remote_state[5] |= kTcl112AcPowerMask; - else - remote_state[5] &= ~kTcl112AcPowerMask; + setBit(&remote_state[5], kTcl112AcPowerOffset, on); } // Return the requested power state of the A/C. bool IRTcl112Ac::getPower(void) { - return remote_state[5] & kTcl112AcPowerMask; + return GETBIT8(remote_state[5], kTcl112AcPowerOffset); } // Get the requested climate operation mode of the a/c unit. @@ -137,8 +127,7 @@ void IRTcl112Ac::setMode(const uint8_t mode) { case kTcl112AcCool: case kTcl112AcHeat: case kTcl112AcDry: - remote_state[6] &= 0xF0; - remote_state[6] |= mode; + setBits(&remote_state[6], kLowNibble, kTcl112AcModeSize, mode); break; default: setMode(kTcl112AcAuto); @@ -151,17 +140,16 @@ void IRTcl112Ac::setTemp(const float celsius) { safecelsius = std::min(safecelsius, kTcl112AcTempMax); // Convert to integer nr. of half degrees. uint8_t nrHalfDegrees = safecelsius * 2; - if (nrHalfDegrees & 1) // Do we have a half degree celsius? - remote_state[12] |= kTcl112AcHalfDegree; // Add 0.5 degrees - else - remote_state[12] &= ~kTcl112AcHalfDegree; // Clear the half degree. - remote_state[7] &= 0xF0; // Clear temp bits. - remote_state[7] |= ((uint8_t)kTcl112AcTempMax - nrHalfDegrees / 2); + // Do we have a half degree celsius? + setBit(&remote_state[12], kTcl112AcHalfDegreeOffset, nrHalfDegrees & 1); + setBits(&remote_state[7], kLowNibble, kNibbleSize, + (uint8_t)kTcl112AcTempMax - nrHalfDegrees / 2); } float IRTcl112Ac::getTemp(void) { - float result = kTcl112AcTempMax - (remote_state[7] & 0xF); - if (remote_state[12] & kTcl112AcHalfDegree) result += 0.5; + float result = kTcl112AcTempMax - GETBITS8(remote_state[7], kLowNibble, + kNibbleSize); + if (GETBIT8(remote_state[12], kTcl112AcHalfDegreeOffset)) result += 0.5; return result; } @@ -173,8 +161,7 @@ void IRTcl112Ac::setFan(const uint8_t speed) { case kTcl112AcFanLow: case kTcl112AcFanMed: case kTcl112AcFanHigh: - remote_state[8] &= ~kTcl112AcFanMask; - remote_state[8] |= speed; + setBits(&remote_state[8], kLowNibble, kTcl112AcFanSize, speed); break; default: this->setFan(kTcl112AcFanAuto); @@ -183,103 +170,82 @@ void IRTcl112Ac::setFan(const uint8_t speed) { // Return the currect fan speed. uint8_t IRTcl112Ac::getFan(void) { - return remote_state[8] & kTcl112AcFanMask; + return GETBITS8(remote_state[8], kLowNibble, kTcl112AcFanSize); } // Control economy mode. void IRTcl112Ac::setEcono(const bool on) { - if (on) - remote_state[5] |= kTcl112AcBitEcono; - else - remote_state[5] &= ~kTcl112AcBitEcono; + setBit(&remote_state[5], kTcl112AcBitEconoOffset, on); } // Return the economy state of the A/C. bool IRTcl112Ac::getEcono(void) { - return remote_state[5] & kTcl112AcBitEcono; + return GETBIT8(remote_state[5], kTcl112AcBitEconoOffset); } // Control Health mode. void IRTcl112Ac::setHealth(const bool on) { - if (on) - remote_state[6] |= kTcl112AcBitHealth; - else - remote_state[6] &= ~kTcl112AcBitHealth; + setBit(&remote_state[6], kTcl112AcBitHealthOffset, on); } // Return the Health mode state of the A/C. bool IRTcl112Ac::getHealth(void) { - return remote_state[6] & kTcl112AcBitHealth; + return GETBIT8(remote_state[6], kTcl112AcBitHealthOffset); } // Control Light/Display mode. void IRTcl112Ac::setLight(const bool on) { - if (on) - remote_state[5] &= ~kTcl112AcBitLight; - else - remote_state[5] |= kTcl112AcBitLight; + setBit(&remote_state[5], kTcl112AcBitLightOffset, !on); // Cleared when on. } // Return the Light/Display mode state of the A/C. bool IRTcl112Ac::getLight(void) { - return !(remote_state[5] & kTcl112AcBitLight); + return !GETBIT8(remote_state[5], kTcl112AcBitLightOffset); } // Control Horizontal Swing. void IRTcl112Ac::setSwingHorizontal(const bool on) { - if (on) - remote_state[12] |= kTcl112AcBitSwingH; - else - remote_state[12] &= ~kTcl112AcBitSwingH; + setBit(&remote_state[12], kTcl112AcBitSwingHOffset, on); } // Return the Horizontal Swing state of the A/C. bool IRTcl112Ac::getSwingHorizontal(void) { - return remote_state[12] & kTcl112AcBitSwingH; + return GETBIT8(remote_state[12], kTcl112AcBitSwingHOffset); } // Control Vertical Swing. void IRTcl112Ac::setSwingVertical(const bool on) { - if (on) - remote_state[8] |= kTcl112AcBitSwingV; - else - remote_state[8] &= ~kTcl112AcBitSwingV; + setBits(&remote_state[8], kTcl112AcSwingVOffset, kTcl112AcSwingVSize, + on ? kTcl112AcSwingVOn : kTcl112AcSwingVOff); } // Return the Vertical Swing state of the A/C. bool IRTcl112Ac::getSwingVertical(void) { - return remote_state[8] & kTcl112AcBitSwingV; + return GETBITS8(remote_state[8], kTcl112AcSwingVOffset, kTcl112AcSwingVSize); } // Control the Turbo setting. void IRTcl112Ac::setTurbo(const bool on) { + setBit(&remote_state[6], kTcl112AcBitTurboOffset, on); if (on) { - remote_state[6] |= kTcl112AcBitTurbo; this->setFan(kTcl112AcFanHigh); this->setSwingVertical(true); - } else { - remote_state[6] &= ~kTcl112AcBitTurbo; } } // Return the Turbo setting state of the A/C. bool IRTcl112Ac::getTurbo(void) { - return remote_state[6] & kTcl112AcBitTurbo; + return GETBIT8(remote_state[6], kTcl112AcBitTurboOffset); } // Convert a standard A/C mode into its native mode. uint8_t IRTcl112Ac::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kTcl112AcCool; - case stdAc::opmode_t::kHeat: - return kTcl112AcHeat; - case stdAc::opmode_t::kDry: - return kTcl112AcDry; - case stdAc::opmode_t::kFan: - return kTcl112AcFan; - default: - return kTcl112AcAuto; + case stdAc::opmode_t::kCool: return kTcl112AcCool; + case stdAc::opmode_t::kHeat: return kTcl112AcHeat; + case stdAc::opmode_t::kDry: return kTcl112AcDry; + case stdAc::opmode_t::kFan: return kTcl112AcFan; + default: return kTcl112AcAuto; } } @@ -287,15 +253,11 @@ uint8_t IRTcl112Ac::convertMode(const stdAc::opmode_t mode) { uint8_t IRTcl112Ac::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kTcl112AcFanLow; - case stdAc::fanspeed_t::kMedium: - return kTcl112AcFanMed; + case stdAc::fanspeed_t::kLow: return kTcl112AcFanLow; + case stdAc::fanspeed_t::kMedium: return kTcl112AcFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kTcl112AcFanHigh; - default: - return kTcl112AcFanAuto; + case stdAc::fanspeed_t::kMax: return kTcl112AcFanHigh; + default: return kTcl112AcFanAuto; } } @@ -304,9 +266,9 @@ stdAc::opmode_t IRTcl112Ac::toCommonMode(const uint8_t mode) { switch (mode) { case kTcl112AcCool: return stdAc::opmode_t::kCool; case kTcl112AcHeat: return stdAc::opmode_t::kHeat; - case kTcl112AcDry: return stdAc::opmode_t::kDry; - case kTcl112AcFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kTcl112AcDry: return stdAc::opmode_t::kDry; + case kTcl112AcFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -314,9 +276,9 @@ stdAc::opmode_t IRTcl112Ac::toCommonMode(const uint8_t mode) { stdAc::fanspeed_t IRTcl112Ac::toCommonFanSpeed(const uint8_t spd) { switch (spd) { case kTcl112AcFanHigh: return stdAc::fanspeed_t::kMax; - case kTcl112AcFanMed: return stdAc::fanspeed_t::kMedium; - case kTcl112AcFanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kTcl112AcFanMed: return stdAc::fanspeed_t::kMedium; + case kTcl112AcFanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } @@ -351,61 +313,26 @@ stdAc::state_t IRTcl112Ac::toCommon(void) { String IRTcl112Ac::toString(void) { String result = ""; result.reserve(140); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kTcl112AcAuto, kTcl112AcCool, kTcl112AcHeat, kTcl112AcDry, kTcl112AcFan); uint16_t nrHalfDegrees = this->getTemp() * 2; - result += F(", Temp: "); - result += uint64ToString(nrHalfDegrees / 2); + result += addIntToString(nrHalfDegrees / 2, kTempStr); if (nrHalfDegrees & 1) result += F(".5"); result += 'C'; result += addFanToString(getFan(), kTcl112AcFanHigh, kTcl112AcFanLow, kTcl112AcFanAuto, kTcl112AcFanAuto, kTcl112AcFanMed); - result += addBoolToString(getEcono(), F("Econo")); - result += addBoolToString(getHealth(), F("Health")); - result += addBoolToString(getLight(), F("Light")); - result += addBoolToString(getTurbo(), F("Turbo")); - result += addBoolToString(getSwingHorizontal(), F("Swing (H)")); - result += addBoolToString(getSwingVertical(), F("Swing (V)")); + result += addBoolToString(getEcono(), kEconoStr); + result += addBoolToString(getHealth(), kHealthStr); + result += addBoolToString(getLight(), kLightStr); + result += addBoolToString(getTurbo(), kTurboStr); + result += addBoolToString(getSwingHorizontal(), kSwingHStr); + result += addBoolToString(getSwingVertical(), kSwingVStr); return result; } #if DECODE_TCL112AC -// Decode the supplied TCL112AC message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: The number of data bits to expect. Typically kTcl112AcBits. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / Appears to mostly work. -// -// Ref: -// https://github.com/crankyoldgit/IRremoteESP8266/issues/619 -bool IRrecv::decodeTcl112Ac(decode_results *results, const uint16_t nbits, - const bool strict) { - if (strict && nbits != kTcl112AcBits) return false; - - uint16_t offset = kStartOffset; - // Match Header + Data + Footer - if (!matchGeneric(results->rawbuf + offset, results->state, - results->rawlen - offset, nbits, - kTcl112AcHdrMark, kTcl112AcHdrSpace, - kTcl112AcBitMark, kTcl112AcOneSpace, - kTcl112AcBitMark, kTcl112AcZeroSpace, - kTcl112AcBitMark, kTcl112AcGap, true, - _tolerance + kTcl112AcTolerance, 0, false)) return false; - // Compliance - // Verify we got a valid checksum. - if (strict && !IRTcl112Ac::validChecksum(results->state)) return false; - // Success - results->decode_type = TCL112AC; - results->bits = nbits; - // No need to record the state as we stored it as we decoded it. - // As we use result->state, we don't record value, address, or command as it - // is a union data type. - return true; -} +// NOTE: There is no `decodedecodeTcl112Ac()`. +// It's the same as `decodeMitsubishi112()`. A shared routine is used. +// You can find it in: ir_Mitsubishi.cpp #endif // DECODE_TCL112AC diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Tcl.h b/lib/IRremoteESP8266-2.7.0/src/ir_Tcl.h old mode 100755 new mode 100644 similarity index 73% rename from lib/IRremoteESP8266-2.6.5/src/ir_Tcl.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Tcl.h index 1a1bc1d6b..21e64a55a --- a/lib/IRremoteESP8266-2.6.5/src/ir_Tcl.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Tcl.h @@ -23,30 +23,37 @@ const uint16_t kTcl112AcBitMark = 500; const uint16_t kTcl112AcOneSpace = 1050; const uint16_t kTcl112AcZeroSpace = 325; const uint32_t kTcl112AcGap = kDefaultMessageGap; // Just a guess. -const uint8_t kTcl112AcTolerance = 5; // Extra Percent +// Total tolerance percentage to use for matching the header mark. +const uint8_t kTcl112AcHdrMarkTolerance = 6; +const uint8_t kTcl112AcTolerance = 5; // Extra Percentage for the rest. const uint8_t kTcl112AcHeat = 1; const uint8_t kTcl112AcDry = 2; const uint8_t kTcl112AcCool = 3; const uint8_t kTcl112AcFan = 7; const uint8_t kTcl112AcAuto = 8; -const uint8_t kTcl112AcFanMask = 0b00000111; -const uint8_t kTcl112AcFanAuto = 0b00000000; -const uint8_t kTcl112AcFanLow = 0b00000010; -const uint8_t kTcl112AcFanMed = 0b00000011; -const uint8_t kTcl112AcFanHigh = 0b00000101; +const uint8_t kTcl112AcModeSize = 4; // Nr. of Bits -const uint8_t kTcl112AcHalfDegree = 0b00100000; +const uint8_t kTcl112AcFanSize = 3; // Nr. of Bits. Mask = 0b00000111 +const uint8_t kTcl112AcFanAuto = 0b000; +const uint8_t kTcl112AcFanLow = 0b010; +const uint8_t kTcl112AcFanMed = 0b011; +const uint8_t kTcl112AcFanHigh = 0b101; + +const uint8_t kTcl112AcHalfDegreeOffset = 5; const float kTcl112AcTempMax = 31.0; const float kTcl112AcTempMin = 16.0; -const uint8_t kTcl112AcPowerMask = 0b00000100; -const uint8_t kTcl112AcBitEcono = 0b10000000; -const uint8_t kTcl112AcBitLight = 0b01000000; -const uint8_t kTcl112AcBitHealth = 0b00010000; -const uint8_t kTcl112AcBitSwingH = 0b00001000; -const uint8_t kTcl112AcBitSwingV = 0b00111000; -const uint8_t kTcl112AcBitTurbo = 0b01000000; +const uint8_t kTcl112AcPowerOffset = 2; +const uint8_t kTcl112AcBitEconoOffset = 7; +const uint8_t kTcl112AcBitLightOffset = 6; +const uint8_t kTcl112AcBitHealthOffset = 4; +const uint8_t kTcl112AcBitSwingHOffset = 3; +const uint8_t kTcl112AcSwingVOffset = 3; // Mask 0b00111000 +const uint8_t kTcl112AcSwingVSize = 3; // Nr. of bits. +const uint8_t kTcl112AcSwingVOn = 0b111; +const uint8_t kTcl112AcSwingVOff = 0b000; +const uint8_t kTcl112AcBitTurboOffset = 6; class IRTcl112Ac { diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Teco.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Teco.cpp old mode 100755 new mode 100644 similarity index 60% rename from lib/IRremoteESP8266-2.6.5/src/ir_Teco.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Teco.cpp index 9967ccee1..200f1954d --- a/lib/IRremoteESP8266-2.6.5/src/ir_Teco.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Teco.cpp @@ -6,6 +6,7 @@ Node MCU/ESP8266 Sketch to emulate Teco #include "ir_Teco.h" #include #include "IRremoteESP8266.h" +#include "IRtext.h" #include "IRutils.h" #ifndef ARDUINO #include @@ -26,6 +27,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_TECO // Send a Teco A/C message. @@ -69,26 +72,23 @@ void IRTecoAc::on(void) { setPower(true); } void IRTecoAc::off(void) { setPower(false); } void IRTecoAc::setPower(const bool on) { - if (on) - remote_state |= kTecoPower; - else - remote_state &= ~kTecoPower; + setBit(&remote_state, kTecoPowerOffset, on); } -bool IRTecoAc::getPower(void) { return remote_state & kTecoPower; } +bool IRTecoAc::getPower(void) { + return GETBIT64(remote_state, kTecoPowerOffset); +} void IRTecoAc::setTemp(const uint8_t temp) { uint8_t newtemp = temp; newtemp = std::min(newtemp, kTecoMaxTemp); newtemp = std::max(newtemp, kTecoMinTemp); - newtemp -= kTecoMinTemp; // 16=0b000 - - remote_state &= ~kTecoTempMask; // reinit temp - remote_state |= (newtemp << 8); + setBits(&remote_state, kTecoTempOffset, kTecoTempSize, + newtemp - kTecoMinTemp); } uint8_t IRTecoAc::getTemp(void) { - return ((remote_state & kTecoTempMask) >> 8) + kTecoMinTemp; + return GETBITS64(remote_state, kTecoTempOffset, kTecoTempSize) + kTecoMinTemp; } // Set the speed of the fan @@ -98,16 +98,15 @@ void IRTecoAc::setFan(const uint8_t speed) { case kTecoFanAuto: case kTecoFanHigh: case kTecoFanMed: - case kTecoFanLow: - break; - default: - newspeed = kTecoFanAuto; + case kTecoFanLow: break; + default: newspeed = kTecoFanAuto; } - remote_state &= ~kTecoFanMask; // reinit fan - remote_state |= (newspeed << 4); + setBits(&remote_state, kTecoFanOffset, kTecoFanSize, newspeed); } -uint8_t IRTecoAc::getFan(void) { return (remote_state & kTecoFanMask) >> 4; } +uint8_t IRTecoAc::getFan(void) { + return GETBITS64(remote_state, kTecoFanOffset, kTecoFanSize); +} void IRTecoAc::setMode(const uint8_t mode) { uint8_t newmode = mode; @@ -116,75 +115,99 @@ void IRTecoAc::setMode(const uint8_t mode) { case kTecoCool: case kTecoDry: case kTecoFan: - case kTecoHeat: - break; - default: - newmode = kTecoAuto; + case kTecoHeat: break; + default: newmode = kTecoAuto; } - remote_state &= ~kTecoModeMask; // reinit mode - remote_state |= newmode; + setBits(&remote_state, kTecoModeOffset, kModeBitsSize, newmode); } -uint8_t IRTecoAc::getMode(void) { return remote_state & kTecoModeMask; } +uint8_t IRTecoAc::getMode(void) { + return GETBITS64(remote_state, kTecoModeOffset, kModeBitsSize); +} void IRTecoAc::setSwing(const bool on) { - if (on) - remote_state |= kTecoSwing; - else - remote_state &= ~kTecoSwing; + setBit(&remote_state, kTecoSwingOffset, on); } -bool IRTecoAc::getSwing(void) { return remote_state & kTecoSwing; } +bool IRTecoAc::getSwing(void) { + return GETBIT64(remote_state, kTecoSwingOffset); +} void IRTecoAc::setSleep(const bool on) { - if (on) - remote_state |= kTecoSleep; - else - remote_state &= ~kTecoSleep; + setBit(&remote_state, kTecoSleepOffset, on); } -bool IRTecoAc::getSleep(void) { return remote_state & kTecoSleep; } - -bool IRTecoAc::getLight(void) { return remote_state & kTecoLight; } +bool IRTecoAc::getSleep(void) { + return GETBIT64(remote_state, kTecoSleepOffset); +} void IRTecoAc::setLight(const bool on) { - if (on) - remote_state |= kTecoLight; - else - remote_state &= ~kTecoLight; + setBit(&remote_state, kTecoLightOffset, on); } -bool IRTecoAc::getHumid(void) { return remote_state & kTecoHumid; } +bool IRTecoAc::getLight(void) { + return GETBIT64(remote_state, kTecoLightOffset); +} void IRTecoAc::setHumid(const bool on) { - if (on) - remote_state |= kTecoHumid; - else - remote_state &= ~kTecoHumid; + setBit(&remote_state, kTecoHumidOffset, on); } -bool IRTecoAc::getSave(void) { return remote_state & kTecoSave; } +bool IRTecoAc::getHumid(void) { + return GETBIT64(remote_state, kTecoHumidOffset); +} void IRTecoAc::setSave(const bool on) { - if (on) - remote_state |= kTecoSave; - else - remote_state &= ~kTecoSave; + setBit(&remote_state, kTecoSaveOffset, on); +} + +bool IRTecoAc::getSave(void) { + return GETBIT64(remote_state, kTecoSaveOffset); +} + +bool IRTecoAc::getTimerEnabled(void) { + return GETBIT64(remote_state, kTecoTimerOnOffset); +} + +uint16_t IRTecoAc::getTimer(void) { + uint16_t mins = 0; + if (getTimerEnabled()) { + mins = GETBITS64(remote_state, kTecoTimerTensHoursOffset, + kTecoTimerTensHoursSize) * 60 * 10 + + GETBITS64(remote_state, kTecoTimerUnitHoursOffset, + kTecoTimerUnitHoursSize) * 60; + if (GETBIT64(remote_state, kTecoTimerHalfHourOffset)) mins += 30; + } + return mins; +} + +// Set the timer for when the A/C unit will switch power state. +// Args: +// nr_mins: Number of minutes before power state change. +// `0` will clear the timer. Max is 24 hrs. +// Time is stored internaly in increments of 30 mins. +void IRTecoAc::setTimer(const uint16_t nr_mins) { + uint16_t mins = std::min(nr_mins, (uint16_t)(24 * 60)); // Limit to 24 hrs. + uint8_t hours = mins / 60; + setBit(&remote_state, kTecoTimerOnOffset, mins); // Set the timer flag. + // Set the half hour bit. + setBit(&remote_state, kTecoTimerHalfHourOffset, (mins % 60) >= 30); + // Set the unit hours. + setBits(&remote_state, kTecoTimerUnitHoursOffset, kTecoTimerUnitHoursSize, + hours % 10); + // Set the tens of hours. + setBits(&remote_state, kTecoTimerTensHoursOffset, kTecoTimerTensHoursSize, + hours / 10); } // Convert a standard A/C mode into its native mode. uint8_t IRTecoAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kTecoCool; - case stdAc::opmode_t::kHeat: - return kTecoHeat; - case stdAc::opmode_t::kDry: - return kTecoDry; - case stdAc::opmode_t::kFan: - return kTecoFan; - default: - return kTecoAuto; + case stdAc::opmode_t::kCool: return kTecoCool; + case stdAc::opmode_t::kHeat: return kTecoHeat; + case stdAc::opmode_t::kDry: return kTecoDry; + case stdAc::opmode_t::kFan: return kTecoFan; + default: return kTecoAuto; } } @@ -192,15 +215,11 @@ uint8_t IRTecoAc::convertMode(const stdAc::opmode_t mode) { uint8_t IRTecoAc::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kTecoFanLow; - case stdAc::fanspeed_t::kMedium: - return kTecoFanMed; + case stdAc::fanspeed_t::kLow: return kTecoFanLow; + case stdAc::fanspeed_t::kMedium: return kTecoFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kTecoFanHigh; - default: - return kTecoFanAuto; + case stdAc::fanspeed_t::kMax: return kTecoFanHigh; + default: return kTecoFanAuto; } } @@ -209,9 +228,9 @@ stdAc::opmode_t IRTecoAc::toCommonMode(const uint8_t mode) { switch (mode) { case kTecoCool: return stdAc::opmode_t::kCool; case kTecoHeat: return stdAc::opmode_t::kHeat; - case kTecoDry: return stdAc::opmode_t::kDry; - case kTecoFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kTecoDry: return stdAc::opmode_t::kDry; + case kTecoFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -219,9 +238,9 @@ stdAc::opmode_t IRTecoAc::toCommonMode(const uint8_t mode) { stdAc::fanspeed_t IRTecoAc::toCommonFanSpeed(const uint8_t speed) { switch (speed) { case kTecoFanHigh: return stdAc::fanspeed_t::kMax; - case kTecoFanMed: return stdAc::fanspeed_t::kMedium; - case kTecoFanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kTecoFanMed: return stdAc::fanspeed_t::kMedium; + case kTecoFanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } @@ -255,18 +274,22 @@ stdAc::state_t IRTecoAc::toCommon(void) { String IRTecoAc::toString(void) { String result = ""; result.reserve(100); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kTecoAuto, kTecoCool, kTecoHeat, kTecoDry, kTecoFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kTecoFanHigh, kTecoFanLow, kTecoFanAuto, kTecoFanAuto, kTecoFanMed); - result += addBoolToString(getSleep(), F("Sleep")); - result += addBoolToString(getSwing(), F("Swing")); - result += addBoolToString(getLight(), F("Light")); - result += addBoolToString(getHumid(), F("Humid")); - result += addBoolToString(getSave(), F("Save")); - + result += addBoolToString(getSleep(), kSleepStr); + result += addBoolToString(getSwing(), kSwingStr); + result += addBoolToString(getLight(), kLightStr); + result += addBoolToString(getHumid(), kHumidStr); + result += addBoolToString(getSave(), kSaveStr); + if (getTimerEnabled()) + result += addLabeledString(irutils::minsToString(getTimer()), + kTimerStr); + else + result += addBoolToString(false, kTimerStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Teco.h b/lib/IRremoteESP8266-2.7.0/src/ir_Teco.h old mode 100755 new mode 100644 similarity index 70% rename from lib/IRremoteESP8266-2.6.5/src/ir_Teco.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Teco.h index 616fc5dfb..8bee1b72b --- a/lib/IRremoteESP8266-2.6.5/src/ir_Teco.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Teco.h @@ -16,32 +16,36 @@ // Brand: Alaska, Model: SAC9010QC A/C // Brand: Alaska, Model: SAC9010QC remote -// Constants. Using LSB to be able to send only 35bits. -const uint8_t kTecoAuto = 0; // 0b000 -const uint8_t kTecoCool = 1; // 0b001 -const uint8_t kTecoDry = 2; // 0b010 -const uint8_t kTecoFan = 3; // 0b110 -const uint8_t kTecoHeat = 4; // 0b001 +// Constants. +const uint8_t kTecoAuto = 0; +const uint8_t kTecoCool = 1; +const uint8_t kTecoDry = 2; +const uint8_t kTecoFan = 3; +const uint8_t kTecoHeat = 4; const uint8_t kTecoFanAuto = 0; // 0b00 +const uint8_t kTecoFanLow = 1; // 0b01 +const uint8_t kTecoFanMed = 2; // 0b10 const uint8_t kTecoFanHigh = 3; // 0b11 -const uint8_t kTecoFanMed = 2; // 0b10 -const uint8_t kTecoFanLow = 1; // 0b01 const uint8_t kTecoMinTemp = 16; // 16C const uint8_t kTecoMaxTemp = 30; // 30C -const uint64_t kTecoModeMask = 0b00000000000000000000000000000000111; -const uint64_t kTecoPower = 0b00000000000000000000000000000001000; -const uint64_t kTecoFanMask = 0b00000000000000000000000000000110000; -const uint64_t kTecoSwing = 0b00000000000000000000000000001000000; -const uint64_t kTecoSleep = 0b00000000000000000000000000010000000; -const uint64_t kTecoTempMask = 0b00000000000000000000000111100000000; -const uint64_t kTecoTimerHalfH = 0b00000000000000000000001000000000000; -const uint64_t kTecoTimerTenHr = 0b00000000000000000000110000000000000; -const uint64_t kTecoTimerOn = 0b00000000000000000001000000000000000; -const uint64_t kTecoTimerUniHr = 0b00000000000000011110000000000000000; -const uint64_t kTecoHumid = 0b00000000000000100000000000000000000; -const uint64_t kTecoLight = 0b00000000000001000000000000000000000; -const uint64_t kTecoSave = 0b00000000000100000000000000000000000; +const uint8_t kTecoModeOffset = 0; +const uint8_t kTecoPowerOffset = 3; +const uint8_t kTecoFanOffset = 4; +const uint8_t kTecoFanSize = 2; // Nr. of bits +const uint8_t kTecoSwingOffset = 6; +const uint8_t kTecoSleepOffset = 7; +const uint8_t kTecoTempOffset = 8; +const uint8_t kTecoTempSize = 4; // Nr. of bits +const uint8_t kTecoTimerHalfHourOffset = 12; +const uint8_t kTecoTimerTensHoursOffset = 13; +const uint8_t kTecoTimerTensHoursSize = 2; // Nr. of bits +const uint8_t kTecoTimerOnOffset = 15; +const uint8_t kTecoTimerUnitHoursOffset = 16; +const uint8_t kTecoTimerUnitHoursSize = 4; // Nr. of bits +const uint8_t kTecoHumidOffset = 20; +const uint8_t kTecoLightOffset = 21; +const uint8_t kTecoSaveOffset = 23; const uint64_t kTecoReset = 0b01001010000000000000010000000000000; /* (header mark and space) @@ -136,8 +140,8 @@ class IRTecoAc { void setSave(const bool on); bool getSave(void); - // void setTimer(uint8_t time); // To check unit - // uint8_t getTimer(uint8_t); + uint16_t getTimer(void); + void setTimer(const uint16_t mins); uint64_t getRaw(void); void setRaw(const uint64_t new_code); @@ -157,6 +161,7 @@ class IRTecoAc { #endif // The state of the IR remote in IR code form. uint64_t remote_state; + bool getTimerEnabled(void); }; #endif // IR_TECO_H_ diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Toshiba.cpp old mode 100755 new mode 100644 similarity index 80% rename from lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Toshiba.cpp index 4fa4c1075..ba1ca5424 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Toshiba.cpp @@ -5,11 +5,13 @@ #include "ir_Toshiba.h" #include +#include #ifndef ARDUINO #include #endif #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // @@ -37,6 +39,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_TOSHIBA_AC // Send a Toshiba A/C message. @@ -76,17 +80,10 @@ void IRToshibaAC::stateReset(void) { // The state of the IR remote in IR code form. // Known good state obtained from: // https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266T.ino#L103 - // Note: Can't use the following because it requires -std=c++11 - // uint8_t remote_state[kToshibaACStateLength] = { - // 0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00 }; - remote_state[0] = 0xF2; - remote_state[1] = 0x0D; - remote_state[2] = 0x03; - remote_state[3] = 0xFC; - remote_state[4] = 0x01; - for (uint8_t i = 5; i < kToshibaACStateLength; i++) remote_state[i] = 0; - mode_state = remote_state[6] & 0b00000011; - this->checksum(); // Calculate the checksum + static const uint8_t kReset[kToshibaACStateLength] = { + 0xF2, 0x0D, 0x03, 0xFC, 0x01}; + memcpy(remote_state, kReset, kToshibaACStateLength); + mode_state = getMode(true); } // Configure the pin for output. @@ -95,8 +92,7 @@ void IRToshibaAC::begin(void) { _irsend.begin(); } #if SEND_TOSHIBA_AC // Send the current desired state to the IR LED. void IRToshibaAC::send(const uint16_t repeat) { - this->checksum(); // Ensure correct checksum before sending. - _irsend.sendToshibaAC(remote_state, kToshibaACStateLength, repeat); + _irsend.sendToshibaAC(getRaw(), kToshibaACStateLength, repeat); } #endif // SEND_TOSHIBA_AC @@ -108,9 +104,7 @@ uint8_t* IRToshibaAC::getRaw(void) { // Override the internal state with the new state. void IRToshibaAC::setRaw(const uint8_t newState[]) { - for (uint8_t i = 0; i < kToshibaACStateLength; i++) { - remote_state[i] = newState[i]; - } + memcpy(remote_state, newState, kToshibaACStateLength); mode_state = this->getMode(true); } @@ -149,42 +143,39 @@ void IRToshibaAC::checksum(const uint16_t length) { length); } -// Set the requested power state of the A/C to off. -void IRToshibaAC::on(void) { - // state = ON; - remote_state[6] &= ~kToshibaAcPower; - setMode(mode_state); -} +// Set the requested power state of the A/C to on. +void IRToshibaAC::on(void) { setPower(true); } // Set the requested power state of the A/C to off. -void IRToshibaAC::off(void) { - // state = OFF; - remote_state[6] |= (kToshibaAcPower | 0b00000011); -} +void IRToshibaAC::off(void) { setPower(false); } // Set the requested power state of the A/C. void IRToshibaAC::setPower(const bool on) { + setBit(&remote_state[6], kToshibaAcPowerOffset, !on); // Cleared when on. if (on) - this->on(); + setMode(mode_state); else - this->off(); + setBits(&remote_state[6], kToshibaAcModeOffset, kToshibaAcModeSize, + kToshibaAcHeat); } // Return the requested power state of the A/C. bool IRToshibaAC::getPower(void) { - return ((remote_state[6] & kToshibaAcPower) == 0); + return !GETBIT8(remote_state[6], kToshibaAcPowerOffset); } // Set the temp. in deg C void IRToshibaAC::setTemp(const uint8_t degrees) { uint8_t temp = std::max((uint8_t)kToshibaAcMinTemp, degrees); temp = std::min((uint8_t)kToshibaAcMaxTemp, temp); - remote_state[5] = (temp - kToshibaAcMinTemp) << 4; + setBits(&remote_state[5], kToshibaAcTempOffset, kToshibaAcTempSize, + temp - kToshibaAcMinTemp); } // Return the set temp. in deg C uint8_t IRToshibaAC::getTemp(void) { - return ((remote_state[5] >> 4) + kToshibaAcMinTemp); + return GETBITS8(remote_state[5], kToshibaAcTempOffset, kToshibaAcTempSize) + + kToshibaAcMinTemp; } // Set the speed of the fan, 0-5. @@ -195,13 +186,13 @@ void IRToshibaAC::setFan(const uint8_t speed) { if (fan > kToshibaAcFanMax) fan = kToshibaAcFanMax; // Set the fan to maximum if out of range. if (fan > kToshibaAcFanAuto) fan++; - remote_state[6] &= 0b00011111; // Clear the previous fan state - remote_state[6] |= (fan << 5); + setBits(&remote_state[6], kToshibaAcFanOffset, kToshibaAcFanSize, fan); } // Return the requested state of the unit's fan. uint8_t IRToshibaAC::getFan(void) { - uint8_t fan = remote_state[6] >> 5; + uint8_t fan = GETBITS8(remote_state[6], kToshibaAcFanOffset, + kToshibaAcFanSize); if (fan == kToshibaAcFanAuto) return kToshibaAcFanAuto; return --fan; } @@ -213,7 +204,7 @@ uint8_t IRToshibaAC::getFan(void) { // A uint8_t containing the A/C mode. uint8_t IRToshibaAC::getMode(const bool useRaw) { if (useRaw) - return (remote_state[6] & 0b00000011); + return GETBITS8(remote_state[6], kToshibaAcModeOffset, kToshibaAcModeSize); else return mode_state; } @@ -228,47 +219,34 @@ void IRToshibaAC::setMode(const uint8_t mode) { case kToshibaAcHeat: mode_state = mode; // Only adjust the remote_state if we have power set to on. - if (getPower()) { - remote_state[6] &= 0b11111100; // Clear the previous mode. - remote_state[6] |= mode_state; - } + if (getPower()) + setBits(&remote_state[6], kToshibaAcModeOffset, kToshibaAcModeSize, + mode_state); return; - default: - // THere is no Fan mode. - this->setMode(kToshibaAcAuto); + default: this->setMode(kToshibaAcAuto); // There is no Fan mode. } } // Convert a standard A/C mode into its native mode. uint8_t IRToshibaAC::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kToshibaAcCool; - case stdAc::opmode_t::kHeat: - return kToshibaAcHeat; - case stdAc::opmode_t::kDry: - return kToshibaAcDry; + case stdAc::opmode_t::kCool: return kToshibaAcCool; + case stdAc::opmode_t::kHeat: return kToshibaAcHeat; + case stdAc::opmode_t::kDry: return kToshibaAcDry; // No Fan mode. - default: - return kToshibaAcAuto; + default: return kToshibaAcAuto; } } // Convert a standard A/C Fan speed into its native fan speed. uint8_t IRToshibaAC::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { - case stdAc::fanspeed_t::kMin: - return kToshibaAcFanMax - 4; - case stdAc::fanspeed_t::kLow: - return kToshibaAcFanMax - 3; - case stdAc::fanspeed_t::kMedium: - return kToshibaAcFanMax - 2; - case stdAc::fanspeed_t::kHigh: - return kToshibaAcFanMax - 1; - case stdAc::fanspeed_t::kMax: - return kToshibaAcFanMax; - default: - return kToshibaAcFanAuto; + case stdAc::fanspeed_t::kMin: return kToshibaAcFanMax - 4; + case stdAc::fanspeed_t::kLow: return kToshibaAcFanMax - 3; + case stdAc::fanspeed_t::kMedium: return kToshibaAcFanMax - 2; + case stdAc::fanspeed_t::kHigh: return kToshibaAcFanMax - 1; + case stdAc::fanspeed_t::kMax: return kToshibaAcFanMax; + default: return kToshibaAcFanAuto; } } @@ -277,20 +255,20 @@ stdAc::opmode_t IRToshibaAC::toCommonMode(const uint8_t mode) { switch (mode) { case kToshibaAcCool: return stdAc::opmode_t::kCool; case kToshibaAcHeat: return stdAc::opmode_t::kHeat; - case kToshibaAcDry: return stdAc::opmode_t::kDry; - default: return stdAc::opmode_t::kAuto; + case kToshibaAcDry: return stdAc::opmode_t::kDry; + default: return stdAc::opmode_t::kAuto; } } // Convert a native fan speed to it's common equivalent. stdAc::fanspeed_t IRToshibaAC::toCommonFanSpeed(const uint8_t spd) { switch (spd) { - case kToshibaAcFanMax: return stdAc::fanspeed_t::kMax; + case kToshibaAcFanMax: return stdAc::fanspeed_t::kMax; case kToshibaAcFanMax - 1: return stdAc::fanspeed_t::kHigh; case kToshibaAcFanMax - 2: return stdAc::fanspeed_t::kMedium; case kToshibaAcFanMax - 3: return stdAc::fanspeed_t::kLow; case kToshibaAcFanMax - 4: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + default: return stdAc::fanspeed_t::kAuto; } } @@ -323,7 +301,7 @@ stdAc::state_t IRToshibaAC::toCommon(void) { String IRToshibaAC::toString(void) { String result = ""; result.reserve(40); - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kToshibaAcAuto, kToshibaAcCool, kToshibaAcHeat, kToshibaAcDry, kToshibaAcAuto); result += addTempToString(getTemp()); diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.h b/lib/IRremoteESP8266-2.7.0/src/ir_Toshiba.h old mode 100755 new mode 100644 similarity index 84% rename from lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Toshiba.h index 6b06855bf..7a679ceda --- a/lib/IRremoteESP8266-2.6.5/src/ir_Toshiba.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Toshiba.h @@ -25,15 +25,21 @@ #endif // Constants +const uint8_t kToshibaAcModeOffset = 0; +const uint8_t kToshibaAcModeSize = 2; // Nr. of bits const uint8_t kToshibaAcAuto = 0; const uint8_t kToshibaAcCool = 1; const uint8_t kToshibaAcDry = 2; const uint8_t kToshibaAcHeat = 3; -const uint8_t kToshibaAcPower = 4; -const uint8_t kToshibaAcFanAuto = 0; -const uint8_t kToshibaAcFanMin = 1; -const uint8_t kToshibaAcFanMed = 3; -const uint8_t kToshibaAcFanMax = 5; +const uint8_t kToshibaAcPowerOffset = 2; +const uint8_t kToshibaAcFanOffset = 5; +const uint8_t kToshibaAcFanSize = 3; // Nr. of bits +const uint8_t kToshibaAcFanAuto = 0b000; +const uint8_t kToshibaAcFanMin = 0b001; +const uint8_t kToshibaAcFanMed = 0b011; +const uint8_t kToshibaAcFanMax = 0b101; +const uint8_t kToshibaAcTempOffset = 4; +const uint8_t kToshibaAcTempSize = 4; // Nr. of bits const uint8_t kToshibaAcMinTemp = 17; // 17C const uint8_t kToshibaAcMaxTemp = 30; // 30C diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Trotec.cpp old mode 100755 new mode 100644 similarity index 78% rename from lib/IRremoteESP8266-2.6.5/src/ir_Trotec.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Trotec.cpp index 281779f62..cb923b5fc --- a/lib/IRremoteESP8266-2.6.5/src/ir_Trotec.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Trotec.cpp @@ -3,10 +3,12 @@ #include "ir_Trotec.h" #include +#include #ifndef UNIT_TEST #include #endif #include "IRremoteESP8266.h" +#include "IRtext.h" #include "IRutils.h" // Constants @@ -24,6 +26,8 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::setBit; +using irutils::setBits; #if SEND_TROTEC @@ -31,6 +35,7 @@ void IRsend::sendTrotec(const unsigned char data[], const uint16_t nbytes, const uint16_t repeat) { if (nbytes < kTrotecStateLength) return; + enableIROut(36); for (uint16_t r = 0; r <= repeat; r++) { sendGeneric(kTrotecHdrMark, kTrotecHdrSpace, kTrotecBitMark, kTrotecOneSpace, kTrotecBitMark, kTrotecZeroSpace, @@ -38,7 +43,6 @@ void IRsend::sendTrotec(const unsigned char data[], const uint16_t nbytes, 0, // Repeats handled elsewhere 50); // More footer - enableIROut(36); mark(kTrotecBitMark); space(kTrotecGapEnd); } @@ -90,66 +94,57 @@ uint8_t* IRTrotecESP::getRaw(void) { } void IRTrotecESP::setRaw(const uint8_t state[]) { - for (uint16_t i = 0; i < kTrotecStateLength; i++) remote_state[i] = state[i]; + memcpy(remote_state, state, kTrotecStateLength); } void IRTrotecESP::setPower(const bool on) { - if (on) - remote_state[2] |= kTrotecPowerBit; - else - remote_state[2] &= ~kTrotecPowerBit; + setBit(&remote_state[2], kTrotecPowerBitOffset, on); } -bool IRTrotecESP::getPower(void) { return remote_state[2] & kTrotecPowerBit; } +bool IRTrotecESP::getPower(void) { + return GETBIT8(remote_state[2], kTrotecPowerBitOffset); +} void IRTrotecESP::setSpeed(const uint8_t fan) { uint8_t speed = std::min(fan, kTrotecFanHigh); - remote_state[2] = (remote_state[2] & 0b11001111) | (speed << 4); + setBits(&remote_state[2], kTrotecFanOffset, kTrotecFanSize, speed); } uint8_t IRTrotecESP::getSpeed(void) { - return (remote_state[2] & 0b00110000) >> 4; + return GETBITS8(remote_state[2], kTrotecFanOffset, kTrotecFanSize); } void IRTrotecESP::setMode(const uint8_t mode) { - switch (mode) { - case kTrotecAuto: - case kTrotecCool: - case kTrotecDry: - case kTrotecFan: - remote_state[2] = (remote_state[2] & 0b11111100) | mode; - return; - default: - this->setMode(kTrotecAuto); - } + setBits(&remote_state[2], kTrotecModeOffset, kTrotecModeSize, + (mode > kTrotecFan) ? kTrotecAuto : mode); } -uint8_t IRTrotecESP::getMode(void) { return remote_state[2] & 0b00000011; } +uint8_t IRTrotecESP::getMode(void) { + return GETBITS8(remote_state[2], kTrotecModeOffset, kTrotecModeSize); +} void IRTrotecESP::setTemp(const uint8_t celsius) { uint8_t temp = std::max(celsius, kTrotecMinTemp); temp = std::min(temp, kTrotecMaxTemp); - remote_state[3] = (remote_state[3] & 0x80) | (temp - kTrotecMinTemp); + setBits(&remote_state[3], kTrotecTempOffset, kTrotecTempSize, + temp - kTrotecMinTemp); } uint8_t IRTrotecESP::getTemp(void) { - return (remote_state[3] & 0b01111111) + kTrotecMinTemp; + return GETBITS8(remote_state[3], kTrotecTempOffset, kTrotecTempSize) + + kTrotecMinTemp; } void IRTrotecESP::setSleep(const bool on) { - if (on) - remote_state[3] |= kTrotecSleepBit; - else - remote_state[3] &= ~kTrotecSleepBit; + setBit(&remote_state[3], kTrotecSleepBitOffset, on); } -bool IRTrotecESP::getSleep(void) { return remote_state[3] & kTrotecSleepBit; } +bool IRTrotecESP::getSleep(void) { + return GETBIT8(remote_state[3], kTrotecSleepBitOffset); +} void IRTrotecESP::setTimer(const uint8_t timer) { - if (timer) - remote_state[5] |= kTrotecTimerBit; - else - remote_state[5] &= ~kTrotecTimerBit; + setBit(&remote_state[5], kTrotecTimerBitOffset, timer); remote_state[6] = (timer > kTrotecMaxTimer) ? kTrotecMaxTimer : timer; } @@ -158,15 +153,11 @@ uint8_t IRTrotecESP::getTimer(void) { return remote_state[6]; } // Convert a standard A/C mode into its native mode. uint8_t IRTrotecESP::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kTrotecCool; - case stdAc::opmode_t::kDry: - return kTrotecDry; - case stdAc::opmode_t::kFan: - return kTrotecFan; + case stdAc::opmode_t::kCool: return kTrotecCool; + case stdAc::opmode_t::kDry: return kTrotecDry; + case stdAc::opmode_t::kFan: return kTrotecFan; // Note: No Heat mode. - default: - return kTrotecAuto; + default: return kTrotecAuto; } } @@ -174,15 +165,11 @@ uint8_t IRTrotecESP::convertMode(const stdAc::opmode_t mode) { uint8_t IRTrotecESP::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kTrotecFanLow; - case stdAc::fanspeed_t::kMedium: - return kTrotecFanMed; + case stdAc::fanspeed_t::kLow: return kTrotecFanLow; + case stdAc::fanspeed_t::kMedium: return kTrotecFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kTrotecFanHigh; - default: - return kTrotecFanMed; + case stdAc::fanspeed_t::kMax: return kTrotecFanHigh; + default: return kTrotecFanMed; } } @@ -191,9 +178,9 @@ uint8_t IRTrotecESP::convertFan(const stdAc::fanspeed_t speed) { stdAc::opmode_t IRTrotecESP::toCommonMode(const uint8_t mode) { switch (mode) { case kTrotecCool: return stdAc::opmode_t::kCool; - case kTrotecDry: return stdAc::opmode_t::kDry; - case kTrotecFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kTrotecDry: return stdAc::opmode_t::kDry; + case kTrotecFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -201,9 +188,9 @@ stdAc::opmode_t IRTrotecESP::toCommonMode(const uint8_t mode) { stdAc::fanspeed_t IRTrotecESP::toCommonFanSpeed(const uint8_t spd) { switch (spd) { case kTrotecFanHigh: return stdAc::fanspeed_t::kMax; - case kTrotecFanMed: return stdAc::fanspeed_t::kMedium; - case kTrotecFanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kTrotecFanMed: return stdAc::fanspeed_t::kMedium; + case kTrotecFanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } @@ -236,13 +223,13 @@ stdAc::state_t IRTrotecESP::toCommon(void) { String IRTrotecESP::toString(void) { String result = ""; result.reserve(100); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kTrotecAuto, kTrotecCool, kTrotecAuto, kTrotecDry, kTrotecFan); result += addTempToString(getTemp()); result += addFanToString(getSpeed(), kTrotecFanHigh, kTrotecFanLow, kTrotecFanHigh, kTrotecFanHigh, kTrotecFanMed); - result += addBoolToString(getSleep(), F("Sleep")); + result += addBoolToString(getSleep(), kSleepStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Trotec.h b/lib/IRremoteESP8266-2.7.0/src/ir_Trotec.h old mode 100755 new mode 100644 similarity index 87% rename from lib/IRremoteESP8266-2.6.5/src/ir_Trotec.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Trotec.h index 98bf3795c..f836b2e5e --- a/lib/IRremoteESP8266-2.6.5/src/ir_Trotec.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Trotec.h @@ -21,26 +21,31 @@ const uint8_t kTrotecIntro1 = 0x12; const uint8_t kTrotecIntro2 = 0x34; // Byte 2 +const uint8_t kTrotecModeOffset = 0; +const uint8_t kTrotecModeSize = 2; // Nr. of bits const uint8_t kTrotecAuto = 0; const uint8_t kTrotecCool = 1; const uint8_t kTrotecDry = 2; const uint8_t kTrotecFan = 3; -const uint8_t kTrotecPowerBit = 0b00001000; +const uint8_t kTrotecPowerBitOffset = 3; +const uint8_t kTrotecFanOffset = 4; +const uint8_t kTrotecFanSize = 2; // Nr. of bits const uint8_t kTrotecFanLow = 1; const uint8_t kTrotecFanMed = 2; const uint8_t kTrotecFanHigh = 3; // Byte 3 +const uint8_t kTrotecTempOffset = 0; +const uint8_t kTrotecTempSize = 4; // Nr. of bits const uint8_t kTrotecMinTemp = 18; const uint8_t kTrotecDefTemp = 25; const uint8_t kTrotecMaxTemp = 32; - -const uint8_t kTrotecSleepBit = 0b10000000; +const uint8_t kTrotecSleepBitOffset = 7; // Byte 5 -const uint8_t kTrotecTimerBit = 0b01000000; +const uint8_t kTrotecTimerBitOffset = 6; // Byte 6 const uint8_t kTrotecMaxTimer = 23; diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Vestel.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Vestel.cpp old mode 100755 new mode 100644 similarity index 64% rename from lib/IRremoteESP8266-2.6.5/src/ir_Vestel.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Vestel.cpp index 1374c6b59..c54a262d7 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Vestel.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Vestel.cpp @@ -11,6 +11,7 @@ #include "IRrecv.h" #include "IRremoteESP8266.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" #include "ir_Haier.h" @@ -27,6 +28,8 @@ using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; using irutils::minsToString; +using irutils::setBit; +using irutils::setBits; #if SEND_VESTEL_AC // Send a Vestel message @@ -71,15 +74,7 @@ void IRVestelAc::begin(void) { #if SEND_VESTEL_AC // Send the current desired state to the IR LED. -void IRVestelAc::send(void) { - this->checksum(); // Ensure correct checksum before sending. - uint64_t code_to_send; - if (use_time_state) - code_to_send = remote_time_state; - else - code_to_send = remote_state; - _irsend.sendVestelAc(code_to_send); -} +void IRVestelAc::send(void) { _irsend.sendVestelAc(getRaw()); } #endif // SEND_VESTEL_AC // Return the internal state date of the remote. @@ -117,37 +112,32 @@ void IRVestelAc::off(void) { setPower(false); } // Set the requested power state of the A/C. void IRVestelAc::setPower(const bool on) { - remote_state &= ~((uint64_t)0xF << kVestelAcPowerOffset); - if (on) - remote_state |= ((uint64_t)0xF << kVestelAcPowerOffset); - else - remote_state |= ((uint64_t)0xC << kVestelAcPowerOffset); + setBits(&remote_state, kVestelAcPowerOffset, kVestelAcPowerSize, + on ? 0b11 : 0b00); use_time_state = false; } // Return the requested power state of the A/C. bool IRVestelAc::getPower(void) { - return (remote_state >> kVestelAcPowerOffset == 0xF); + return GETBITS64(remote_state, kVestelAcPowerOffset, kVestelAcPowerSize); } // Set the temperature in Celsius degrees. void IRVestelAc::setTemp(const uint8_t temp) { - uint8_t new_temp = temp; - new_temp = std::max(kVestelAcMinTempC, new_temp); - // new_temp = std::max(kVestelAcMinTempH, new_temp); Check MODE + uint8_t new_temp = std::max(kVestelAcMinTempC, temp); new_temp = std::min(kVestelAcMaxTemp, new_temp); - remote_state &= ~((uint64_t)0xF << kVestelAcTempOffset); - remote_state |= (uint64_t)(new_temp - 16) << kVestelAcTempOffset; + setBits(&remote_state, kVestelAcTempOffset, kNibbleSize, + new_temp - kVestelAcMinTempH); use_time_state = false; } // Return the set temperature. uint8_t IRVestelAc::getTemp(void) { - return ((remote_state >> kVestelAcTempOffset) & 0xF) + 16; + return GETBITS64(remote_state, kVestelAcTempOffset, kNibbleSize) + + kVestelAcMinTempH; } // Set the speed of the fan, -// 1-3 set the fan speed, 0 or anything else set it to auto. void IRVestelAc::setFan(const uint8_t fan) { switch (fan) { case kVestelAcFanLow: @@ -156,8 +146,7 @@ void IRVestelAc::setFan(const uint8_t fan) { case kVestelAcFanAutoCool: case kVestelAcFanAutoHot: case kVestelAcFanAuto: - remote_state &= ~((uint64_t)0xF << kVestelAcFanOffset); - remote_state |= (uint64_t)fan << kVestelAcFanOffset; + setBits(&remote_state, kVestelAcFanOffset, kVestelAcFanSize, fan); break; default: setFan(kVestelAcFanAuto); @@ -167,14 +156,14 @@ void IRVestelAc::setFan(const uint8_t fan) { // Return the requested state of the unit's fan. uint8_t IRVestelAc::getFan(void) { - return (remote_state >> kVestelAcFanOffset) & 0xF; + return GETBITS64(remote_state, kVestelAcFanOffset, kVestelAcFanSize); } // Get the requested climate operation mode of the a/c unit. // Returns: // A uint8_t containing the A/C mode. uint8_t IRVestelAc::getMode(void) { - return (remote_state >> kVestelAcModeOffset) & 0xF; + return GETBITS64(remote_state, kVestelAcModeOffset, kModeBitsSize); } // Set the requested climate operation mode of the a/c unit. @@ -186,8 +175,7 @@ void IRVestelAc::setMode(const uint8_t mode) { case kVestelAcHeat: case kVestelAcDry: case kVestelAcFan: - remote_state &= ~((uint64_t)0xF << kVestelAcModeOffset); - remote_state |= (uint64_t)mode << kVestelAcModeOffset; + setBits(&remote_state, kVestelAcModeOffset, kModeBitsSize, mode); break; default: setMode(kVestelAcAuto); @@ -213,15 +201,12 @@ void IRVestelAc::setAuto(const int8_t autoLevel) { } void IRVestelAc::setTimerActive(const bool on) { - if (on) // activation - remote_time_state |= ((uint64_t)1 << kVestelAcTimerFlagOffset); - else // deactivate - remote_time_state &= ~((uint64_t)1 << kVestelAcTimerFlagOffset); + setBit(&remote_time_state, kVestelAcTimerFlagOffset, on); use_time_state = true; } bool IRVestelAc::isTimerActive(void) { - return (remote_time_state >> kVestelAcTimerFlagOffset) & 1; + return GETBIT64(remote_time_state, kVestelAcTimerFlagOffset); } // Set Timer option of AC. @@ -244,125 +229,119 @@ uint16_t IRVestelAc::getTimer(void) { return getOffTimer(); } // Set the AC's internal clock void IRVestelAc::setTime(const uint16_t minutes) { - remote_time_state &= ~((uint64_t)0x1F << kVestelAcHourOffset); - remote_time_state |= (uint64_t)((minutes / 60) & 0x1F) - << kVestelAcHourOffset; - remote_time_state &= ~((uint64_t)0xFF << kVestelAcMinuteOffset); - remote_time_state |= (uint64_t)((minutes % 60) & 0xFF) - << kVestelAcMinuteOffset; + setBits(&remote_time_state, kVestelAcHourOffset, kVestelAcHourSize, + minutes / 60); + setBits(&remote_time_state, kVestelAcMinuteOffset, kVestelAcMinuteSize, + minutes % 60); use_time_state = true; } uint16_t IRVestelAc::getTime(void) { - return ((remote_time_state >> kVestelAcHourOffset) & 0x1F) * 60 + - ((remote_time_state >> kVestelAcMinuteOffset) & 0xFF); + return GETBITS64(remote_time_state, kVestelAcHourOffset, kVestelAcHourSize) * + 60 + GETBITS64(remote_time_state, kVestelAcMinuteOffset, + kVestelAcMinuteSize); } void IRVestelAc::setOnTimerActive(const bool on) { - if (on) // activation - remote_time_state |= ((uint64_t)1 << kVestelAcOnTimerFlagOffset); - else // deactivate - remote_time_state &= ~((uint64_t)1 << kVestelAcOnTimerFlagOffset); + setBit(&remote_time_state, kVestelAcOnTimerFlagOffset, on); use_time_state = true; } bool IRVestelAc::isOnTimerActive(void) { - return (remote_time_state >> kVestelAcOnTimerFlagOffset) & 1; + return GETBIT64(remote_time_state, kVestelAcOnTimerFlagOffset); } -// Set AC's wake up time. Takes time in minute. -void IRVestelAc::setOnTimer(const uint16_t minutes) { - remote_time_state &= ~((uint64_t)0xFF << kVestelAcOnTimeOffset); - remote_time_state |= (uint64_t)(((minutes / 60) << 3) + (minutes % 60) / 10) - << kVestelAcOnTimeOffset; - setOnTimerActive(minutes != 0); +// Set a given timer (via offset). Takes time in nr. of minutes. +void IRVestelAc::_setTimer(const uint16_t minutes, const uint8_t offset) { + setBits(&remote_time_state, offset, kVestelAcTimerSize, + ((minutes / 60) << 3) + (minutes % 60) / 10); setTimerActive(false); use_time_state = true; } +// Get the number of mins a timer is set for. +uint16_t IRVestelAc::_getTimer(const uint8_t offset) { + return GETBITS64(remote_time_state, offset + kVestelAcTimerMinsSize, + kVestelAcTimerHourSize) * 60 + // Hrs + GETBITS64(remote_time_state, offset, kVestelAcTimerMinsSize) * 10; // Min +} +// Set AC's wake up time. Takes time in minute. +void IRVestelAc::setOnTimer(const uint16_t minutes) { + setOnTimerActive(minutes); + _setTimer(minutes, kVestelAcOnTimeOffset); +} + uint16_t IRVestelAc::getOnTimer(void) { - uint8_t ontime = (remote_time_state >> kVestelAcOnTimeOffset) & 0xFF; - return (ontime >> 3) * 60 + (ontime & 0x7) * 10; + return _getTimer(kVestelAcOnTimeOffset); } void IRVestelAc::setOffTimerActive(const bool on) { - if (on) // activation - remote_time_state |= ((uint64_t)1 << kVestelAcOffTimerFlagOffset); - else // deactivate - remote_time_state &= ~((uint64_t)1 << kVestelAcOffTimerFlagOffset); + setBit(&remote_time_state, kVestelAcOffTimerFlagOffset, on); use_time_state = true; } bool IRVestelAc::isOffTimerActive(void) { - return (remote_time_state >> kVestelAcOffTimerFlagOffset) & 1; + return GETBIT64(remote_time_state, kVestelAcOffTimerFlagOffset); } // Set AC's turn off time. Takes time in minute. void IRVestelAc::setOffTimer(const uint16_t minutes) { - remote_time_state &= ~((uint64_t)0xFF << kVestelAcOffTimeOffset); - remote_time_state |= - (uint64_t)((((minutes / 60) << 3) + (minutes % 60) / 10) & 0xFF) - << kVestelAcOffTimeOffset; - setOffTimerActive(minutes != 0); - setTimerActive(false); - use_time_state = true; + setOffTimerActive(minutes); + _setTimer(minutes, kVestelAcOffTimeOffset); } uint16_t IRVestelAc::getOffTimer(void) { - uint8_t offtime = (remote_time_state >> kVestelAcOffTimeOffset) & 0xFF; - return (offtime >> 3) * 60 + (offtime & 0x7) * 10; + return _getTimer(kVestelAcOffTimeOffset); } // Set the Sleep state of the A/C. void IRVestelAc::setSleep(const bool on) { - remote_state &= ~((uint64_t)0xF << kVestelAcTurboSleepOffset); - remote_state |= (uint64_t)(on ? kVestelAcSleep : kVestelAcNormal) - << kVestelAcTurboSleepOffset; + setBits(&remote_state, kVestelAcTurboSleepOffset, kNibbleSize, + on ? kVestelAcSleep : kVestelAcNormal); use_time_state = false; } // Return the Sleep state of the A/C. bool IRVestelAc::getSleep(void) { - return ((remote_state >> kVestelAcTurboSleepOffset) & 0xF) == kVestelAcSleep; + return GETBITS64(remote_state, kVestelAcTurboSleepOffset, kNibbleSize) == + kVestelAcSleep; } // Set the Turbo state of the A/C. void IRVestelAc::setTurbo(const bool on) { - remote_state &= ~((uint64_t)0xF << kVestelAcTurboSleepOffset); - remote_state |= (uint64_t)(on ? kVestelAcTurbo : kVestelAcNormal) - << kVestelAcTurboSleepOffset; + setBits(&remote_state, kVestelAcTurboSleepOffset, kNibbleSize, + on ? kVestelAcTurbo : kVestelAcNormal); use_time_state = false; } // Return the Turbo state of the A/C. bool IRVestelAc::getTurbo(void) { - return ((remote_state >> kVestelAcTurboSleepOffset) & 0xF) == kVestelAcTurbo; + return GETBITS64(remote_state, kVestelAcTurboSleepOffset, kNibbleSize) == + kVestelAcTurbo; } // Set the Ion state of the A/C. void IRVestelAc::setIon(const bool on) { - remote_state &= ~((uint64_t)0x1 << kVestelAcIonOffset); - - remote_state |= (uint64_t)(on ? 1 : 0) << kVestelAcIonOffset; + setBit(&remote_state, kVestelAcIonOffset, on); use_time_state = false; } // Return the Ion state of the A/C. bool IRVestelAc::getIon(void) { - return (remote_state >> kVestelAcIonOffset) & 1; + return GETBIT64(remote_state, kVestelAcIonOffset); } // Set the Swing Roaming state of the A/C. void IRVestelAc::setSwing(const bool on) { - remote_state &= ~((uint64_t)0xF << kVestelAcSwingOffset); - - remote_state |= (uint64_t)(on ? kVestelAcSwing : 0xF) << kVestelAcSwingOffset; + setBits(&remote_state, kVestelAcSwingOffset, kNibbleSize, + on ? kVestelAcSwing : 0xF); use_time_state = false; } // Return the Swing Roaming state of the A/C. bool IRVestelAc::getSwing(void) { - return ((remote_state >> kVestelAcSwingOffset) & 0xF) == kVestelAcSwing; + return GETBITS64(remote_state, kVestelAcSwingOffset, kNibbleSize) == + kVestelAcSwing; } // Calculate the checksum for a given array. @@ -372,13 +351,7 @@ bool IRVestelAc::getSwing(void) { // The 8 bit checksum value. uint8_t IRVestelAc::calcChecksum(const uint64_t state) { // Just counts the set bits +1 on stream and take inverse after mask - uint8_t sum = 0; - uint64_t temp_state = state & kVestelAcCRCMask; - for (; temp_state; temp_state >>= 1) - if (temp_state & 1) sum++; - sum += 2; - sum = 0xff - sum; - return sum; + return 0xFF - countBits(GETBITS64(state, 20, 44), 44, true, 2); } // Verify the checksum is valid for a given state. @@ -387,40 +360,32 @@ uint8_t IRVestelAc::calcChecksum(const uint64_t state) { // Returns: // A boolean. bool IRVestelAc::validChecksum(const uint64_t state) { - return (((state >> kVestelAcChecksumOffset) & 0xFF) == - IRVestelAc::calcChecksum(state)); + return GETBITS64(state, kVestelAcChecksumOffset, kVestelAcChecksumSize) == + IRVestelAc::calcChecksum(state); } // Calculate & set the checksum for the current internal state of the remote. void IRVestelAc::checksum(void) { // Stored the checksum value in the last byte. - remote_state &= ~((uint64_t)0xFF << kVestelAcChecksumOffset); - remote_state |= (uint64_t)this->calcChecksum(remote_state) - << kVestelAcChecksumOffset; - - remote_time_state &= ~((uint64_t)0xFF << kVestelAcChecksumOffset); - remote_time_state |= (uint64_t)this->calcChecksum(remote_time_state) - << kVestelAcChecksumOffset; + setBits(&remote_state, kVestelAcChecksumOffset, kVestelAcChecksumSize, + this->calcChecksum(remote_state)); + setBits(&remote_time_state, kVestelAcChecksumOffset, kVestelAcChecksumSize, + this->calcChecksum(remote_time_state)); } bool IRVestelAc::isTimeCommand(void) { - return (remote_state >> kVestelAcPowerOffset == 0x00 || use_time_state); + return !GETBITS64(remote_state, kVestelAcPowerOffset, kNibbleSize) || + use_time_state; } - // Convert a standard A/C mode into its native mode. uint8_t IRVestelAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kVestelAcCool; - case stdAc::opmode_t::kHeat: - return kVestelAcHeat; - case stdAc::opmode_t::kDry: - return kVestelAcDry; - case stdAc::opmode_t::kFan: - return kVestelAcFan; - default: - return kVestelAcAuto; + case stdAc::opmode_t::kCool: return kVestelAcCool; + case stdAc::opmode_t::kHeat: return kVestelAcHeat; + case stdAc::opmode_t::kDry: return kVestelAcDry; + case stdAc::opmode_t::kFan: return kVestelAcFan; + default: return kVestelAcAuto; } } @@ -428,15 +393,11 @@ uint8_t IRVestelAc::convertMode(const stdAc::opmode_t mode) { uint8_t IRVestelAc::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kVestelAcFanLow; - case stdAc::fanspeed_t::kMedium: - return kVestelAcFanMed; + case stdAc::fanspeed_t::kLow: return kVestelAcFanLow; + case stdAc::fanspeed_t::kMedium: return kVestelAcFanMed; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kVestelAcFanHigh; - default: - return kVestelAcFanAuto; + case stdAc::fanspeed_t::kMax: return kVestelAcFanHigh; + default: return kVestelAcFanAuto; } } @@ -445,9 +406,9 @@ stdAc::opmode_t IRVestelAc::toCommonMode(const uint8_t mode) { switch (mode) { case kVestelAcCool: return stdAc::opmode_t::kCool; case kVestelAcHeat: return stdAc::opmode_t::kHeat; - case kVestelAcDry: return stdAc::opmode_t::kDry; - case kVestelAcFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kVestelAcDry: return stdAc::opmode_t::kDry; + case kVestelAcFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -455,9 +416,9 @@ stdAc::opmode_t IRVestelAc::toCommonMode(const uint8_t mode) { stdAc::fanspeed_t IRVestelAc::toCommonFanSpeed(const uint8_t spd) { switch (spd) { case kVestelAcFanHigh: return stdAc::fanspeed_t::kMax; - case kVestelAcFanMed: return stdAc::fanspeed_t::kMedium; - case kVestelAcFanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kVestelAcFanMed: return stdAc::fanspeed_t::kMedium; + case kVestelAcFanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } @@ -492,51 +453,53 @@ String IRVestelAc::toString(void) { String result = ""; result.reserve(100); // Reserve some heap for the string to reduce fragging. if (this->isTimeCommand()) { - result += addLabeledString(minsToString(getTime()), F("Time"), false); + result += addLabeledString(minsToString(getTime()), kClockStr, false); result += addLabeledString( - isTimerActive() ? minsToString(getTimer()) : F("Off"), - F("Timer")); + isTimerActive() ? minsToString(getTimer()) : kOffStr, + kTimerStr); result += addLabeledString( (isOnTimerActive() && !isTimerActive()) ? - minsToString(this->getOnTimer()) : F("Off"), - F("On Timer")); + minsToString(this->getOnTimer()) : kOffStr, + kOnTimerStr); result += addLabeledString( - isOffTimerActive() ? minsToString(getOffTimer()) : F("Off"), - F("Off Timer")); + isOffTimerActive() ? minsToString(getOffTimer()) : kOffStr, + kOffTimerStr); return result; } // Not a time command, it's a normal command. - result += addBoolToString(getPower(), F("Power"), false); + result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kVestelAcAuto, kVestelAcCool, kVestelAcHeat, kVestelAcDry, kVestelAcFan); result += addTempToString(getTemp()); - result += addIntToString(getFan(), F("Fan")); + result += addIntToString(getFan(), kFanStr); + result += kSpaceLBraceStr; switch (this->getFan()) { case kVestelAcFanAuto: - result += F(" (Auto)"); + result += kAutoStr; break; case kVestelAcFanLow: - result += F(" (Low)"); + result += kLowStr; break; case kVestelAcFanMed: - result += F(" (Medium)"); + result += kMedStr; break; case kVestelAcFanHigh: - result += F(" (High)"); + result += kHighStr; break; case kVestelAcFanAutoCool: - result += F(" (Auto Cool)"); + result += kAutoStr + ' ' + kCoolStr; break; case kVestelAcFanAutoHot: - result += F(" (Auto Hot)"); + result += kAutoStr + ' ' + kHeatStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; } - result += addBoolToString(getSleep(), F("Sleep")); - result += addBoolToString(getTurbo(), F("Turbo")); - result += addBoolToString(getIon(), F("Ion")); - result += addBoolToString(getSwing(), F("Swing")); + result += ')'; + result += addBoolToString(getSleep(), kSleepStr); + result += addBoolToString(getTurbo(), kTurboStr); + result += addBoolToString(getIon(), kIonStr); + result += addBoolToString(getSwing(), kSwingStr); return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Vestel.h b/lib/IRremoteESP8266-2.7.0/src/ir_Vestel.h old mode 100755 new mode 100644 similarity index 89% rename from lib/IRremoteESP8266-2.6.5/src/ir_Vestel.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Vestel.h index f60c031aa..38727b805 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Vestel.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Vestel.h @@ -61,8 +61,6 @@ const uint8_t kVestelAcMinTempH = 16; const uint8_t kVestelAcMinTempC = 18; const uint8_t kVestelAcMaxTemp = 30; -const uint64_t kVestelAcCRCMask = 0xFFFFFFFFFFF00000; - const uint8_t kVestelAcAuto = 0; const uint8_t kVestelAcCool = 1; const uint8_t kVestelAcDry = 2; @@ -83,21 +81,30 @@ const uint8_t kVestelAcIon = 4; const uint8_t kVestelAcSwing = 0xA; const uint8_t kVestelAcChecksumOffset = 12; +const uint8_t kVestelAcChecksumSize = 8; // Nr. of bits const uint8_t kVestelAcSwingOffset = 20; const uint8_t kVestelAcTurboSleepOffset = 24; const uint8_t kVestelAcTempOffset = 36; const uint8_t kVestelAcFanOffset = 40; +const uint8_t kVestelAcFanSize = 4; // Nr. of bits const uint8_t kVestelAcModeOffset = 44; const uint8_t kVestelAcIonOffset = 50; const uint8_t kVestelAcPowerOffset = 52; +const uint8_t kVestelAcPowerSize = 2; // Nr. of bits const uint8_t kVestelAcOffTimeOffset = 20; const uint8_t kVestelAcOnTimeOffset = 28; +const uint8_t kVestelAcTimerHourSize = 5; // Nr. of bits +const uint8_t kVestelAcTimerMinsSize = 3; // Nr. of bits +const uint8_t kVestelAcTimerSize = kVestelAcTimerHourSize + + kVestelAcTimerMinsSize; // Nr. of bits const uint8_t kVestelAcHourOffset = 36; // 5 bits +const uint8_t kVestelAcHourSize = 5; // Nr. of bits const uint8_t kVestelAcOnTimerFlagOffset = kVestelAcHourOffset + 5; const uint8_t kVestelAcOffTimerFlagOffset = kVestelAcHourOffset + 6; const uint8_t kVestelAcTimerFlagOffset = kVestelAcHourOffset + 7; const uint8_t kVestelAcMinuteOffset = 44; - +const uint8_t kVestelAcMinuteSize = 8; // Nr. of bits +// Default states const uint64_t kVestelAcStateDefault = 0x0F00D9001FEF201ULL; const uint64_t kVestelAcTimeStateDefault = 0x201ULL; @@ -168,6 +175,8 @@ class IRVestelAc { uint64_t remote_time_state; bool use_time_state; void checksum(void); + void _setTimer(const uint16_t minutes, const uint8_t offset); + uint16_t _getTimer(const uint8_t offset); }; #endif // IR_VESTEL_H_ diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Whirlpool.cpp old mode 100755 new mode 100644 similarity index 76% rename from lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Whirlpool.cpp index 92a9b2bb3..b9bef9120 --- a/lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.cpp +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Whirlpool.cpp @@ -16,12 +16,14 @@ #include "ir_Whirlpool.h" #include +#include #ifndef ARDUINO #include #endif #include "IRrecv.h" #include "IRremoteESP8266.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" // Constants @@ -40,8 +42,11 @@ using irutils::addFanToString; using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; +using irutils::addModelToString; using irutils::addTempToString; using irutils::minsToString; +using irutils::setBit; +using irutils::setBits; #if SEND_WHIRLPOOL_AC // Send a Whirlpool A/C message. @@ -143,12 +148,11 @@ uint8_t *IRWhirlpoolAc::getRaw(const bool calcchecksum) { } void IRWhirlpoolAc::setRaw(const uint8_t new_code[], const uint16_t length) { - for (uint8_t i = 0; i < length && i < kWhirlpoolAcStateLength; i++) - remote_state[i] = new_code[i]; + memcpy(remote_state, new_code, std::min(length, kWhirlpoolAcStateLength)); } whirlpool_ac_remote_model_t IRWhirlpoolAc::getModel(void) { - if (remote_state[kWhirlpoolAcAltTempPos] & kWhirlpoolAcAltTempMask) + if (GETBIT8(remote_state[kWhirlpoolAcAltTempPos], kWhirlpoolAcAltTempOffset)) return DG11J191; else return DG11J13A; @@ -157,12 +161,13 @@ whirlpool_ac_remote_model_t IRWhirlpoolAc::getModel(void) { void IRWhirlpoolAc::setModel(const whirlpool_ac_remote_model_t model) { switch (model) { case DG11J191: - remote_state[kWhirlpoolAcAltTempPos] |= kWhirlpoolAcAltTempMask; + setBit(&remote_state[kWhirlpoolAcAltTempPos], kWhirlpoolAcAltTempOffset); break; case DG11J13A: // FALL THRU default: - remote_state[kWhirlpoolAcAltTempPos] &= ~kWhirlpoolAcAltTempMask; + setBit(&remote_state[kWhirlpoolAcAltTempPos], kWhirlpoolAcAltTempOffset, + false); } this->_setTemp(_desiredtemp); // Different models have different temp values. } @@ -170,11 +175,8 @@ void IRWhirlpoolAc::setModel(const whirlpool_ac_remote_model_t model) { // Return the temp. offset in deg C for the current model. int8_t IRWhirlpoolAc::getTempOffset(void) { switch (this->getModel()) { - case whirlpool_ac_remote_model_t::DG11J191: - return -2; - break; - default: - return 0; + case whirlpool_ac_remote_model_t::DG11J191: return -2; + default: return 0; } } @@ -184,9 +186,8 @@ void IRWhirlpoolAc::_setTemp(const uint8_t temp, const bool remember) { int8_t offset = this->getTempOffset(); // Cache the min temp for the model. uint8_t newtemp = std::max((uint8_t)(kWhirlpoolAcMinTemp + offset), temp); newtemp = std::min((uint8_t)(kWhirlpoolAcMaxTemp + offset), newtemp); - remote_state[kWhirlpoolAcTempPos] = - (remote_state[kWhirlpoolAcTempPos] & ~kWhirlpoolAcTempMask) | - ((newtemp - (kWhirlpoolAcMinTemp + offset)) << 4); + setBits(&remote_state[kWhirlpoolAcTempPos], kHighNibble, kNibbleSize, + newtemp - (kWhirlpoolAcMinTemp + offset)); } // Set the temp. in deg C @@ -198,8 +199,8 @@ void IRWhirlpoolAc::setTemp(const uint8_t temp) { // Return the set temp. in deg C uint8_t IRWhirlpoolAc::getTemp(void) { - return ((remote_state[kWhirlpoolAcTempPos] & kWhirlpoolAcTempMask) >> 4) + - + kWhirlpoolAcMinTemp + this->getTempOffset(); + return GETBITS8(remote_state[kWhirlpoolAcTempPos], kHighNibble, kNibbleSize) + + kWhirlpoolAcMinTemp + this->getTempOffset(); } void IRWhirlpoolAc::_setMode(const uint8_t mode) { @@ -213,8 +214,8 @@ void IRWhirlpoolAc::_setMode(const uint8_t mode) { case kWhirlpoolAcCool: case kWhirlpoolAcDry: case kWhirlpoolAcFan: - remote_state[kWhirlpoolAcModePos] &= ~kWhirlpoolAcModeMask; - remote_state[kWhirlpoolAcModePos] |= mode; + setBits(&remote_state[kWhirlpoolAcModePos], kWhirlpoolAcModeOffset, + kModeBitsSize, mode); this->setCommand(kWhirlpoolAcCommandMode); break; default: @@ -229,7 +230,8 @@ void IRWhirlpoolAc::setMode(const uint8_t mode) { } uint8_t IRWhirlpoolAc::getMode(void) { - return remote_state[kWhirlpoolAcModePos] & kWhirlpoolAcModeMask; + return GETBITS8(remote_state[kWhirlpoolAcModePos], kWhirlpoolAcModeOffset, + kModeBitsSize); } void IRWhirlpoolAc::setFan(const uint8_t speed) { @@ -238,8 +240,8 @@ void IRWhirlpoolAc::setFan(const uint8_t speed) { case kWhirlpoolAcFanLow: case kWhirlpoolAcFanMedium: case kWhirlpoolAcFanHigh: - remote_state[kWhirlpoolAcFanPos] = - (remote_state[kWhirlpoolAcFanPos] & ~kWhirlpoolAcFanMask) | speed; + setBits(&remote_state[kWhirlpoolAcFanPos], kWhirlpoolAcFanOffset, + kWhirlpoolAcFanSize, speed); this->setSuper(false); // Changing fan speed cancels Super/Jet mode. this->setCommand(kWhirlpoolAcCommandFanSpeed); break; @@ -247,60 +249,54 @@ void IRWhirlpoolAc::setFan(const uint8_t speed) { } uint8_t IRWhirlpoolAc::getFan(void) { - return remote_state[kWhirlpoolAcFanPos] & kWhirlpoolAcFanMask; + return GETBITS8(remote_state[kWhirlpoolAcFanPos], kWhirlpoolAcFanOffset, + kWhirlpoolAcFanSize); } void IRWhirlpoolAc::setSwing(const bool on) { - if (on) { - remote_state[kWhirlpoolAcFanPos] |= kWhirlpoolAcSwing1Mask; - remote_state[kWhirlpoolAcOffTimerPos] |= kWhirlpoolAcSwing2Mask; - } else { - remote_state[kWhirlpoolAcFanPos] &= ~kWhirlpoolAcSwing1Mask; - remote_state[kWhirlpoolAcOffTimerPos] &= ~kWhirlpoolAcSwing2Mask; - } + setBit(&remote_state[kWhirlpoolAcFanPos], kWhirlpoolAcSwing1Offset, on); + setBit(&remote_state[kWhirlpoolAcOffTimerPos], kWhirlpoolAcSwing2Offset, on); setCommand(kWhirlpoolAcCommandSwing); } bool IRWhirlpoolAc::getSwing(void) { - return (remote_state[kWhirlpoolAcFanPos] & kWhirlpoolAcSwing1Mask) && - (remote_state[kWhirlpoolAcOffTimerPos] & kWhirlpoolAcSwing2Mask); + return GETBIT8(remote_state[kWhirlpoolAcFanPos], kWhirlpoolAcSwing1Offset) && + GETBIT8(remote_state[kWhirlpoolAcOffTimerPos], + kWhirlpoolAcSwing2Offset); } void IRWhirlpoolAc::setLight(const bool on) { - if (on) - remote_state[kWhirlpoolAcClockPos] &= ~kWhirlpoolAcLightMask; - else - remote_state[kWhirlpoolAcClockPos] |= kWhirlpoolAcLightMask; + // Cleared when on. + setBit(&remote_state[kWhirlpoolAcClockPos], kWhirlpoolAcLightOffset, !on); } bool IRWhirlpoolAc::getLight(void) { - return !(remote_state[kWhirlpoolAcClockPos] & kWhirlpoolAcLightMask); + return !GETBIT8(remote_state[kWhirlpoolAcClockPos], kWhirlpoolAcLightOffset); } void IRWhirlpoolAc::setTime(const uint16_t pos, const uint16_t minspastmidnight) { // Hours - remote_state[pos] &= ~kWhirlpoolAcHourMask; - remote_state[pos] |= (minspastmidnight / 60) % 24; + setBits(&remote_state[pos], kWhirlpoolAcHourOffset, kWhirlpoolAcHourSize, + (minspastmidnight / 60) % 24); // Minutes - remote_state[pos + 1] &= ~kWhirlpoolAcMinuteMask; - remote_state[pos + 1] |= minspastmidnight % 60; + setBits(&remote_state[pos + 1], kWhirlpoolAcMinuteOffset, + kWhirlpoolAcMinuteSize, minspastmidnight % 60); } uint16_t IRWhirlpoolAc::getTime(const uint16_t pos) { - return (remote_state[pos] & kWhirlpoolAcHourMask) * 60 + - (remote_state[pos + 1] & kWhirlpoolAcMinuteMask); + return GETBITS8(remote_state[pos], kWhirlpoolAcHourOffset, + kWhirlpoolAcHourSize) * 60 + + GETBITS8(remote_state[pos + 1], kWhirlpoolAcMinuteOffset, + kWhirlpoolAcMinuteSize); } bool IRWhirlpoolAc::isTimerEnabled(const uint16_t pos) { - return remote_state[pos - 1] & kWhirlpoolAcTimerEnableMask; + return GETBIT8(remote_state[pos - 1], kWhirlpoolAcTimerEnableOffset); } void IRWhirlpoolAc::enableTimer(const uint16_t pos, const bool on) { - if (on) - remote_state[pos - 1] |= kWhirlpoolAcTimerEnableMask; - else - remote_state[pos - 1] &= ~kWhirlpoolAcTimerEnableMask; + setBit(&remote_state[pos - 1], kWhirlpoolAcTimerEnableOffset, on); } void IRWhirlpoolAc::setClock(const uint16_t minspastmidnight) { @@ -346,16 +342,15 @@ void IRWhirlpoolAc::enableOnTimer(const bool on) { } void IRWhirlpoolAc::setPowerToggle(const bool on) { - if (on) - remote_state[kWhirlpoolAcPowerTogglePos] |= kWhirlpoolAcPowerToggleMask; - else - remote_state[kWhirlpoolAcPowerTogglePos] &= ~kWhirlpoolAcPowerToggleMask; + setBit(&remote_state[kWhirlpoolAcPowerTogglePos], + kWhirlpoolAcPowerToggleOffset, on); this->setSuper(false); // Changing power cancels Super/Jet mode. this->setCommand(kWhirlpoolAcCommandPower); } bool IRWhirlpoolAc::getPowerToggle(void) { - return remote_state[kWhirlpoolAcPowerTogglePos] & kWhirlpoolAcPowerToggleMask; + return GETBIT8(remote_state[kWhirlpoolAcPowerTogglePos], + kWhirlpoolAcPowerToggleOffset); } uint8_t IRWhirlpoolAc::getCommand(void) { @@ -363,17 +358,14 @@ uint8_t IRWhirlpoolAc::getCommand(void) { } void IRWhirlpoolAc::setSleep(const bool on) { - if (on) { - remote_state[kWhirlpoolAcSleepPos] |= kWhirlpoolAcSleepMask; - this->setFan(kWhirlpoolAcFanLow); - } else { - remote_state[kWhirlpoolAcSleepPos] &= ~kWhirlpoolAcSleepMask; - } + setBit(&remote_state[kWhirlpoolAcSleepPos], + kWhirlpoolAcSleepOffset, on); + if (on) this->setFan(kWhirlpoolAcFanLow); this->setCommand(kWhirlpoolAcCommandSleep); } bool IRWhirlpoolAc::getSleep(void) { - return remote_state[kWhirlpoolAcSleepPos] & kWhirlpoolAcSleepMask; + return GETBIT8(remote_state[kWhirlpoolAcSleepPos], kWhirlpoolAcSleepOffset); } // AKA Jet/Turbo mode. @@ -408,16 +400,11 @@ void IRWhirlpoolAc::setCommand(const uint8_t code) { // Convert a standard A/C mode into its native mode. uint8_t IRWhirlpoolAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { - case stdAc::opmode_t::kCool: - return kWhirlpoolAcCool; - case stdAc::opmode_t::kHeat: - return kWhirlpoolAcHeat; - case stdAc::opmode_t::kDry: - return kWhirlpoolAcDry; - case stdAc::opmode_t::kFan: - return kWhirlpoolAcFan; - default: - return kWhirlpoolAcAuto; + case stdAc::opmode_t::kCool: return kWhirlpoolAcCool; + case stdAc::opmode_t::kHeat: return kWhirlpoolAcHeat; + case stdAc::opmode_t::kDry: return kWhirlpoolAcDry; + case stdAc::opmode_t::kFan: return kWhirlpoolAcFan; + default: return kWhirlpoolAcAuto; } } @@ -425,15 +412,11 @@ uint8_t IRWhirlpoolAc::convertMode(const stdAc::opmode_t mode) { uint8_t IRWhirlpoolAc::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kWhirlpoolAcFanLow; - case stdAc::fanspeed_t::kMedium: - return kWhirlpoolAcFanMedium; + case stdAc::fanspeed_t::kLow: return kWhirlpoolAcFanLow; + case stdAc::fanspeed_t::kMedium: return kWhirlpoolAcFanMedium; case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kWhirlpoolAcFanHigh; - default: - return kWhirlpoolAcFanAuto; + case stdAc::fanspeed_t::kMax: return kWhirlpoolAcFanHigh; + default: return kWhirlpoolAcFanAuto; } } @@ -442,19 +425,19 @@ stdAc::opmode_t IRWhirlpoolAc::toCommonMode(const uint8_t mode) { switch (mode) { case kWhirlpoolAcCool: return stdAc::opmode_t::kCool; case kWhirlpoolAcHeat: return stdAc::opmode_t::kHeat; - case kWhirlpoolAcDry: return stdAc::opmode_t::kDry; - case kWhirlpoolAcFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kWhirlpoolAcDry: return stdAc::opmode_t::kDry; + case kWhirlpoolAcFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } // Convert a native fan speed to it's common equivalent. stdAc::fanspeed_t IRWhirlpoolAc::toCommonFanSpeed(const uint8_t speed) { switch (speed) { - case kWhirlpoolAcFanHigh: return stdAc::fanspeed_t::kMax; + case kWhirlpoolAcFanHigh: return stdAc::fanspeed_t::kMax; case kWhirlpoolAcFanMedium: return stdAc::fanspeed_t::kMedium; - case kWhirlpoolAcFanLow: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kWhirlpoolAcFanLow: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } @@ -488,78 +471,69 @@ stdAc::state_t IRWhirlpoolAc::toCommon(void) { String IRWhirlpoolAc::toString(void) { String result = ""; result.reserve(200); // Reserve some heap for the string to reduce fragging. - result += F("Model: "); - result += uint64ToString(this->getModel()); - switch (this->getModel()) { - case DG11J191: - result += F(" (DG11J191)"); - break; - case DG11J13A: - result += F(" (DG11J13A)"); - break; - default: - result += F(" (UNKNOWN)"); - } - result += addBoolToString(getPowerToggle(), F("Power toggle")); + result += addModelToString(decode_type_t::WHIRLPOOL_AC, getModel(), false); + result += addBoolToString(getPowerToggle(), kPowerStr + ' ' + kToggleStr); result += addModeToString(getMode(), kWhirlpoolAcAuto, kWhirlpoolAcCool, kWhirlpoolAcHeat, kWhirlpoolAcDry, kWhirlpoolAcFan); result += addTempToString(getTemp()); result += addFanToString(getFan(), kWhirlpoolAcFanHigh, kWhirlpoolAcFanLow, kWhirlpoolAcFanAuto, kWhirlpoolAcFanAuto, kWhirlpoolAcFanMedium); - result += addBoolToString(getSwing(), F("Swing")); - result += addBoolToString(getLight(), F("Light")); - result += addLabeledString(minsToString(getClock()), F("Clock")); + result += addBoolToString(getSwing(), kSwingStr); + result += addBoolToString(getLight(), kLightStr); + result += addLabeledString(minsToString(getClock()), kClockStr); result += addLabeledString( - isOnTimerEnabled() ? minsToString(getOnTimer()) : F("Off"), - F("On Timer")); + isOnTimerEnabled() ? minsToString(getOnTimer()) : kOffStr, + kOnTimerStr); result += addLabeledString( - isOffTimerEnabled() ? minsToString(getOffTimer()) : F("Off"), - F("Off Timer")); - result += addBoolToString(getSleep(), F("Sleep")); - result += addBoolToString(getSuper(), F("Super")); - result += addIntToString(getCommand(), F("Command")); + isOffTimerEnabled() ? minsToString(getOffTimer()) : kOffStr, + kOffTimerStr); + result += addBoolToString(getSleep(), kSleepStr); + result += addBoolToString(getSuper(), kSuperStr); + result += addIntToString(getCommand(), kCommandStr); + result += kSpaceLBraceStr; switch (this->getCommand()) { case kWhirlpoolAcCommandLight: - result += F(" (LIGHT)"); + result += kLightStr; break; case kWhirlpoolAcCommandPower: - result += F(" (POWER)"); + result += kPowerStr; break; case kWhirlpoolAcCommandTemp: - result += F(" (TEMP)"); + result += kTempStr; break; case kWhirlpoolAcCommandSleep: - result += F(" (SLEEP)"); + result += kSleepStr; break; case kWhirlpoolAcCommandSuper: - result += F(" (SUPER)"); + result += kSuperStr; break; case kWhirlpoolAcCommandOnTimer: - result += F(" (ONTIMER)"); + result += kOnTimerStr; break; case kWhirlpoolAcCommandMode: - result += F(" (MODE)"); + result += kModeStr; break; case kWhirlpoolAcCommandSwing: - result += F(" (SWING)"); + result += kSwingStr; break; case kWhirlpoolAcCommandIFeel: - result += F(" (IFEEL)"); + result += kIFeelStr; break; case kWhirlpoolAcCommandFanSpeed: - result += F(" (FANSPEED)"); + result += kFanStr; break; case kWhirlpoolAcCommand6thSense: - result += F(" (6THSENSE)"); + result += k6thSenseStr; break; case kWhirlpoolAcCommandOffTimer: - result += F(" (OFFTIMER)"); + result += kOffTimerStr; break; default: - result += F(" (UNKNOWN)"); + result += kUnknownStr; break; } + result += ')'; return result; } diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.h b/lib/IRremoteESP8266-2.7.0/src/ir_Whirlpool.h old mode 100755 new mode 100644 similarity index 87% rename from lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.h rename to lib/IRremoteESP8266-2.7.0/src/ir_Whirlpool.h index 156c4b631..11fd6949e --- a/lib/IRremoteESP8266-2.6.5/src/ir_Whirlpool.h +++ b/lib/IRremoteESP8266-2.7.0/src/ir_Whirlpool.h @@ -37,31 +37,33 @@ const uint8_t kWhirlpoolAcAuto = 1; const uint8_t kWhirlpoolAcCool = 2; const uint8_t kWhirlpoolAcDry = 3; const uint8_t kWhirlpoolAcFan = 4; -const uint8_t kWhirlpoolAcModeMask = 0b00000111; +const uint8_t kWhirlpoolAcModeOffset = 0; const uint8_t kWhirlpoolAcModePos = 3; +const uint8_t kWhirlpoolAcFanOffset = 0; // Mask 0b00000011 +const uint8_t kWhirlpoolAcFanSize = 2; // Nr. of bits const uint8_t kWhirlpoolAcFanAuto = 0; const uint8_t kWhirlpoolAcFanHigh = 1; const uint8_t kWhirlpoolAcFanMedium = 2; const uint8_t kWhirlpoolAcFanLow = 3; -const uint8_t kWhirlpoolAcFanMask = 0b00000011; const uint8_t kWhirlpoolAcFanPos = 2; const uint8_t kWhirlpoolAcMinTemp = 18; // 18C (DG11J1-3A), 16C (DG11J1-91) const uint8_t kWhirlpoolAcMaxTemp = 32; // 32C (DG11J1-3A), 30C (DG11J1-91) const uint8_t kWhirlpoolAcAutoTemp = 23; // 23C -const uint8_t kWhirlpoolAcTempMask = 0b11110000; const uint8_t kWhirlpoolAcTempPos = 3; -const uint8_t kWhirlpoolAcSwing1Mask = 0b10000000; -const uint8_t kWhirlpoolAcSwing2Mask = 0b01000000; -const uint8_t kWhirlpoolAcLightMask = 0b00100000; -const uint8_t kWhirlpoolAcPowerToggleMask = 0b00000100; +const uint8_t kWhirlpoolAcSwing1Offset = 7; +const uint8_t kWhirlpoolAcSwing2Offset = 6; +const uint8_t kWhirlpoolAcLightOffset = 5; +const uint8_t kWhirlpoolAcPowerToggleOffset = 2; // 0b00000100 const uint8_t kWhirlpoolAcPowerTogglePos = 2; -const uint8_t kWhirlpoolAcSleepMask = 0b00001000; +const uint8_t kWhirlpoolAcSleepOffset = 3; const uint8_t kWhirlpoolAcSleepPos = 2; const uint8_t kWhirlpoolAcSuperMask = 0b10010000; const uint8_t kWhirlpoolAcSuperPos = 5; -const uint8_t kWhirlpoolAcHourMask = 0b00011111; -const uint8_t kWhirlpoolAcMinuteMask = 0b00111111; -const uint8_t kWhirlpoolAcTimerEnableMask = 0b10000000; +const uint8_t kWhirlpoolAcHourOffset = 0; // Mask 0b00011111 +const uint8_t kWhirlpoolAcHourSize = 5; // Nr. of bits +const uint8_t kWhirlpoolAcMinuteOffset = 0; // Mask 0b00111111 +const uint8_t kWhirlpoolAcMinuteSize = 6; // Nr. of bits +const uint8_t kWhirlpoolAcTimerEnableOffset = 7; // 0b10000000 const uint8_t kWhirlpoolAcClockPos = 6; const uint8_t kWhirlpoolAcOffTimerPos = 8; const uint8_t kWhirlpoolAcOnTimerPos = 10; @@ -78,14 +80,9 @@ const uint8_t kWhirlpoolAcCommandIFeel = 0x0D; const uint8_t kWhirlpoolAcCommandFanSpeed = 0x11; const uint8_t kWhirlpoolAcCommand6thSense = 0x17; const uint8_t kWhirlpoolAcCommandOffTimer = 0x1D; -const uint8_t kWhirlpoolAcAltTempMask = 0b00001000; +const uint8_t kWhirlpoolAcAltTempOffset = 3; const uint8_t kWhirlpoolAcAltTempPos = 18; -enum whirlpool_ac_remote_model_t { - DG11J13A = 1, // DG11J1-04 too - DG11J191, -}; - // Classes class IRWhirlpoolAc { public: diff --git a/lib/IRremoteESP8266-2.6.5/src/ir_Whynter.cpp b/lib/IRremoteESP8266-2.7.0/src/ir_Whynter.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/src/ir_Whynter.cpp rename to lib/IRremoteESP8266-2.7.0/src/ir_Whynter.cpp diff --git a/lib/IRremoteESP8266-2.7.0/src/locale/README.md b/lib/IRremoteESP8266-2.7.0/src/locale/README.md new file mode 100644 index 000000000..6b55571bf --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/locale/README.md @@ -0,0 +1,97 @@ +# Internationalisation (I18N) & Locale Files + +This directory contains the files used by the library to store the text it uses. If you want to add support for a language, this is the +correct place. If you are adding text strings to a routine, you should use the ones here. + +## Changing the language/locale used by the library. +There are several ways to change which locale file is used by the library. Use which ever one suits your needs best. +To keep the space used by the library to a minimum, all methods require the change to happen at compile time. +There is _no_ runtime option to change locales. + +### Change `_IR_LOCALE_` in the `src/IRremoteESP8266.h` file. +In the [IRremoteESP8266.h](../IRremoteESP8266.h#L57-L59) file, find and locate the lines that look like: +``` +#ifndef _IR_LOCALE_ +#define _IR_LOCALE_ en-AU +#endif // _IR_LOCALE_ +``` + +Change `en-AU` to the language & country that best suits your needs. e.g. `de-DE` for Germany/German. + +### Use a compile-time build flag. +Use the compiler flag: `-D_IR_LOCALE_=en-AU` when compiling the library. Especially when compiling the `IRtext.cpp` file. +Change `en-AU` to a value which matches one of the file names in this directory. e.g. `de-DE` for Germany/German, which will use +the `de_DE.h` file. + +### Use the appropriate pre-prepared build environment. _(PlatformIO only)_ +If you examine the `platformio.ini` file located in the same directory as the example code you may find pre-setup compile environments +for the different supported locales. +Choose the appropriate one for you language by asking PlatformIO to build or upload using that environment. +e.g. See `IRrecvDumpV2`'s [platformio.ini](../../examples/IRrecvDumpV2/platformio.ini) + +### Use a custom `build_flags`. _(PlatformIO only)_ +Edit the `platformio.ini` file in the directory containing your example/source code. +Either in the default PlatformIO environment (`[env]`), or in which ever PlatformIO environment you using, +change or add the following line: +``` +build_flags = -D_IR_LOCALE_=en-AU ; Or use which ever locale variable you want. +``` + +Every time you change that line, you should do a `pio clean` or choose the `clean` option from the build menu, to ensure a fresh copy +of `IRtext.o` is created. + +## Adding support for a new locale/language. + +Only [ASCII](https://en.wikipedia.org/wiki/ASCII#8-bit_codes)/[UTF-8](https://en.wikipedia.org/wiki/UTF-8) 8-bit characters are supported. +[Unicode](https://en.wikipedia.org/wiki/Unicode) is **not** supported. Unicode may work. It may not. It's just not supported. +i.e. If Arduino's `Serial.print()` can handle it, it will probably work. + +### Copy/create a new locale file in this directory. +Copy [en-AU.h](en-AU.h) or which every is a closer fit for your language to `xx-YY.h` where `xx` is the [ISO code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) for the language. +e.g. `en` is English. `de` is German etc. and `YY` is the ISO country code. e.g. `AU` is Australia. +Modify the comments and all `LOCALE_EN_AU_H_`s in the file to `LOCALE_XX_YY_H_` for your locale. + + +### Override any `#define` values that reside in `defaults.h` +Go through the [defaults.h](defaults.h) file, and find any `#define` lines that define a macro starting with `D_` that has text +that needs to change for your locale. +Copy or create a corresponding `#define D_STR_HELLOWORLD "Hello World"` in your `xx-YY.h` file, and translate the text appropriately +e.g. `#define D_STR_HELLOWORLD "Bonjour le monde"` (French) + +Any values you `#define` in `xx-YY.h` will override the corresponding value in the [defaults.h](defaults.h) file. + +### Supporting a dialect/regional varient of another _existing_ language/locale. +Similar to the previous step, if you only need to modify a small subset of the strings used in another locale file, then include the +other locale file and then make sure to `#undef` any strings that need to be (re-)changed. +See the [Swiss-German](de-CH.h) for an example of how to do this. i.e. It `#include "locale/de-DE.h"`s the German locale, and +redefines any strings that are not standard [German](de-DE.h). + +## Adding new text strings to the library. +If you need to add an entirely new string to the library to support some feature etc. e.g. _"Widget"_. +You should first understand how the library tries to do this such that it is easy to support different languages for it. + +1. Use a constant named `kWidgetStr` in the appropriate statement in the `.cpp` file. +2. Edit [IRtext.cpp](IRtext.cpp), and add the appropriate line for your new constant. e.g. +``` +String kWidgetStr = D_STR_WIDGET; +``` +The `kWidgetStr` variable will house the sole copy of the string for the entire library. This limits any duplication. +The `D_STR_WIDGET` macro will be what is targeted by the different language / locales files. + +3. Edit [locale/defaults.h](defaults.h), and add the appropriate stanza for your new string. e.g. +``` +#ifndef D_STR_WIDGET +#define D_STR_WIDGET "Turbo" +#endif // D_STR_WIDGET +``` + + +4. _(Manual)_ Update [IRtext.h](../IRtext.h), and add the appropriate line for your new constant. e.g. +``` +extern const String kWidgetStr; +``` +For any file that `#include `s this file, it will tell it that the string is stored elsewhere, +and to look for it elsewhere at the object linking stage of the build. This is what makes the string be referenced from a central location. + +4. _(Automatic)_ Run `tools/generate_irtext_h.sh` to update [IRtext.h](../IRtext.h). +In the [src/locale](../locale) directory. Run the `../../tools/generate_irtext_h.sh` command. It will update the file for you automatically. diff --git a/lib/IRremoteESP8266-2.7.0/src/locale/de-CH.h b/lib/IRremoteESP8266-2.7.0/src/locale/de-CH.h new file mode 100644 index 000000000..2c34ca97b --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/locale/de-CH.h @@ -0,0 +1,158 @@ +// Copyright 2019 - Martin (@finfinack) +// Locale/language file for German / Switzerland. +// This file will override the default values located in `defaults.h`. +#ifndef LOCALE_DE_CH_H_ +#define LOCALE_DE_CH_H_ + +// Import German / Germany as default overrides. +#include "locale/de-DE.h" + +// As we have loaded another language, we need to #undef anything we need +// to update/change. + +#undef D_STR_ON +#define D_STR_ON "Ii" +#undef D_STR_OFF +#define D_STR_OFF "Us" +#undef D_STR_TOGGLE +#define D_STR_TOGGLE "Umschalte" +#undef D_STR_SLEEP +#define D_STR_SLEEP "Schlafe" +#undef D_STR_LIGHT +#define D_STR_LIGHT "Liecht" +#undef D_STR_POWERFUL +#define D_STR_POWERFUL "Starch" +#undef D_STR_QUIET +#define D_STR_QUIET "Liislig" +#undef D_STR_CLEAN +#define D_STR_CLEAN "Reinige" +#undef D_STR_PURIFY +#define D_STR_PURIFY "Frische" +#undef D_STR_HEALTH +#define D_STR_HEALTH "Gsundheit" +#undef D_STR_HUMID +#define D_STR_HUMID "Füecht" +#undef D_STR_SAVE +#define D_STR_SAVE "Speichere" +#undef D_STR_EYE +#define D_STR_EYE "Aug" +#undef D_STR_FOLLOW +#define D_STR_FOLLOW "Folge" +#undef D_STR_HOLD +#define D_STR_HOLD "Halte" +#undef D_STR_BUTTON +#define D_STR_BUTTON "Chnopf" +#undef D_STR_UP +#define D_STR_UP "Ufe" +#undef D_STR_TEMPUP +#define D_STR_TEMPUP D_STR_TEMP " " D_STR_UP +#undef D_STR_DOWN +#define D_STR_DOWN "Abe" +#undef D_STR_TEMPDOWN +#define D_STR_TEMPDOWN D_STR_TEMP " " D_STR_DOWN +#undef D_STR_CHANGE +#define D_STR_CHANGE "Wechsele" +#undef D_STR_MOVE +#define D_STR_MOVE "Verschiebe" +#undef D_STR_SET +#define D_STR_SET "Setze" +#undef D_STR_CANCEL +#define D_STR_CANCEL "Abbreche" +#undef D_STR_WEEKLY +#define D_STR_WEEKLY "Wüchentlich" +#undef D_STR_WEEKLYTIMER +#define D_STR_WEEKLYTIMER D_STR_WEEKLY " " D_STR_TIMER +#undef D_STR_OUTSIDE +#define D_STR_OUTSIDE "Dusse" +#undef D_STR_LOUD +#define D_STR_LOUD "Luut" +#undef D_STR_UPPER +#define D_STR_UPPER "Obe" +#undef D_STR_LOWER +#define D_STR_LOWER "Une" +#undef D_STR_CIRCULATE +#define D_STR_CIRCULATE "Zirkuliere" +#undef D_STR_CEILING +#define D_STR_CEILING "Decki" +#undef D_STR_6THSENSE +#define D_STR_6THSENSE "6te Sinn" + +#undef D_STR_COOL +#define D_STR_COOL "Chüehle" +#undef D_STR_HEAT +#define D_STR_HEAT "Heize" +#undef D_STR_DRY +#define D_STR_DRY "Tröchne" + +#undef D_STR_MED +#define D_STR_MED "Mit" +#undef D_STR_MEDIUM +#define D_STR_MEDIUM "Mittel" + +#undef D_STR_HIGHEST +#define D_STR_HIGHEST "Höchscht" +#undef D_STR_HIGH +#define D_STR_HIGH "Höch" +#undef D_STR_HI +#define D_STR_HI "H" +#undef D_STR_MID +#define D_STR_MID "M" +#undef D_STR_MIDDLE +#define D_STR_MIDDLE "Mittel" +#undef D_STR_LOW +#define D_STR_LOW "Tüüf" +#undef D_STR_LO +#define D_STR_LO "T" +#undef D_STR_LOWEST +#define D_STR_LOWEST "Tüfschte" +#undef D_STR_MAXRIGHT +#define D_STR_MAXRIGHT D_STR_MAX " " D_STR_RIGHT +#undef D_STR_RIGHTMAX_NOSPACE +#define D_STR_RIGHTMAX_NOSPACE D_STR_RIGHT D_STR_MAX +#undef D_STR_MAXLEFT +#define D_STR_MAXLEFT D_STR_MAX " " D_STR_LEFT +#undef D_STR_LEFTMAX_NOSPACE +#define D_STR_LEFTMAX_NOSPACE D_STR_LEFT D_STR_MAX +#undef D_STR_CENTRE +#define D_STR_CENTRE "Mitti" +#undef D_STR_TOP +#define D_STR_TOP "Obe" +#undef D_STR_BOTTOM +#define D_STR_BOTTOM "Une" + +#undef D_STR_DAY +#define D_STR_DAY "Tag" +#undef D_STR_DAYS +#define D_STR_DAYS "Täg" +#undef D_STR_HOUR +#define D_STR_HOUR "Stund" +#undef D_STR_HOURS +#define D_STR_HOURS D_STR_HOUR "e" +#undef D_STR_MINUTE +#define D_STR_MINUTE "Minute" +#undef D_STR_MINUTES +#define D_STR_MINUTES D_STR_MINUTE +#undef D_STR_SECONDS +#define D_STR_SECONDS D_STR_SECOND +#undef D_STR_NOW +#define D_STR_NOW "Jetz" + +#undef D_STR_NO +#define D_STR_NO "Nei" + +#undef D_STR_REPEAT +#define D_STR_REPEAT "Wiederhole" + +// IRrecvDumpV2 +#undef D_STR_TIMESTAMP +#define D_STR_TIMESTAMP "Ziitstämpfel" +#undef D_STR_IRRECVDUMP_STARTUP +#define D_STR_IRRECVDUMP_STARTUP \ + "IRrecvDumpV2 lauft und wartet uf IR Iigab ufem Pin %d" +#undef D_WARN_BUFFERFULL +#define D_WARN_BUFFERFULL \ + "WARNUNG: IR Code isch zgross für de Buffer (>= %d). " \ + "Dem Resultat sött mer nöd vertraue bevor das behobe isch. " \ + "Bearbeite & vergrössere `kCaptureBufferSize`." + +#endif // LOCALE_DE_CH_H_ diff --git a/lib/IRremoteESP8266-2.7.0/src/locale/de-DE.h b/lib/IRremoteESP8266-2.7.0/src/locale/de-DE.h new file mode 100644 index 000000000..f366936b0 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/locale/de-DE.h @@ -0,0 +1,126 @@ +// Copyright 2019 - Martin (@finfinack) +// Locale/language file for German / Germany. +// This file will override the default values located in `defaults.h`. +#ifndef LOCALE_DE_DE_H_ +#define LOCALE_DE_DE_H_ + +#define D_STR_UNKNOWN "UNBEKANNT" +#define D_STR_PROTOCOL "Protokoll" +#define D_STR_ON "Ein" +#define D_STR_OFF "Aus" +#define D_STR_MODE "Modus" +#define D_STR_TOGGLE "Umschalten" +#define D_STR_SLEEP "Schlafen" +#define D_STR_LIGHT "Licht" +#define D_STR_POWERFUL "Stark" +#define D_STR_QUIET "Ruhig" +#define D_STR_ECONO "Eco" +#define D_STR_BEEP "Piep" +#define D_STR_MOULD "Schimmel" +#define D_STR_CLEAN "Reinigen" +#define D_STR_PURIFY "Frischen" +#define D_STR_TIMER "Timer" +#define D_STR_ONTIMER D_STR_ON " " D_STR_TIMER +#define D_STR_OFFTIMER D_STR_OFF " " D_STR_TIMER +#define D_STR_CLOCK "Uhr" +#define D_STR_COMMAND "Befehl" +#define D_STR_HEALTH "Gesundheit" +#define D_STR_TEMP "Temp" +#define D_STR_HUMID "Feucht" +#define D_STR_SAVE "Speichern" +#define D_STR_EYE "Auge" +#define D_STR_FOLLOW "Folgen" +#define D_STR_FRESH "Frisch" +#define D_STR_HOLD "Halten" +#define D_STR_BUTTON "Knopf" +#define D_STR_NIGHT "Nacht" +#define D_STR_SILENT "Ruhig" +#define D_STR_UP "Hinauf" +#define D_STR_TEMPUP D_STR_TEMP " " D_STR_UP +#define D_STR_DOWN "Hinunter" +#define D_STR_TEMPDOWN D_STR_TEMP " " D_STR_DOWN +#define D_STR_CHANGE "Wechseln" +#define D_STR_MOVE "Verschieben" +#define D_STR_SET "Setzen" +#define D_STR_CANCEL "Abbrechen" +#define D_STR_COMFORT "Komfort" +#define D_STR_WEEKLY "Wöchentlich" +#define D_STR_WEEKLYTIMER D_STR_WEEKLY " " D_STR_TIMER +#define D_STR_FAST "Schnell" +#define D_STR_SLOW "Langsam" +#define D_STR_AIRFLOW "Luftzug" +#define D_STR_STEP "Schritt" +#define D_STR_NA "N/A" +#define D_STR_OUTSIDE "Draussen" +#define D_STR_LOUD "Laut" +#define D_STR_UPPER "Oben" +#define D_STR_LOWER "Unten" +#define D_STR_BREEZE "Brise" +#define D_STR_CIRCULATE "Zirkulieren" +#define D_STR_CEILING "Decke" +#define D_STR_WALL "Wand" +#define D_STR_ROOM "Raum" +#define D_STR_6THSENSE "6ter Sinn" +#define D_STR_FIXED "Fixiert" + +#define D_STR_AUTOMATIC "Automatisch" +#define D_STR_MANUAL "Manuell" +#define D_STR_COOL "Kühlen" +#define D_STR_HEAT "Heizen" +#define D_STR_FAN "Lüfter" +#define D_STR_FANONLY "nur_lüfter" +#define D_STR_DRY "Trocken" + +#define D_STR_MED "Mit" +#define D_STR_MEDIUM "Mittel" + +#define D_STR_HIGHEST "Höchste" +#define D_STR_HIGH "Hoch" +#define D_STR_HI "H" +#define D_STR_MID "M" +#define D_STR_MIDDLE "Mittel" +#define D_STR_LOW "Tief" +#define D_STR_LO "T" +#define D_STR_LOWEST "Tiefste" +#define D_STR_RIGHT "Rechts" +#define D_STR_MAXRIGHT D_STR_MAX " " D_STR_RIGHT +#define D_STR_RIGHTMAX_NOSPACE D_STR_RIGHT D_STR_MAX +#define D_STR_LEFT "Links" +#define D_STR_MAXLEFT D_STR_MAX " " D_STR_LEFT +#define D_STR_LEFTMAX_NOSPACE D_STR_LEFT D_STR_MAX +#define D_STR_WIDE "Breit" +#define D_STR_CENTRE "Mitte" +#define D_STR_TOP "Oben" +#define D_STR_BOTTOM "Unten" + +#define D_STR_DAY "Tag" +#define D_STR_DAYS D_STR_DAY "e" +#define D_STR_HOUR "Stunde" +#define D_STR_HOURS D_STR_HOUR "n" +#define D_STR_MINUTES D_STR_MINUTE "n" +#define D_STR_SECOND "Sekunde" +#define D_STR_SECONDS D_STR_SECOND "n" +#define D_STR_NOW "Jetzt" +// These don't translate well to German as typically only 2 letter +// abbreviations are used. Hence, this is an approximation. +#define D_STR_THREELETTERDAYS "SonMonDieMitDonFreSam" + +#define D_STR_YES "Ja" +#define D_STR_NO "Nein" +#define D_STR_TRUE "Wahr" +#define D_STR_FALSE "Falsch" + +#define D_STR_REPEAT "Wiederholen" + +// IRrecvDumpV2 +#define D_STR_TIMESTAMP "Zeitstempel" +#define D_STR_LIBRARY "Bibliothek" +#define D_STR_MESGDESC "Nachr. Beschr." +#define D_STR_IRRECVDUMP_STARTUP \ + "IRrecvDumpV2 läuft und wartet auf IR Eingabe auf Pin %d" +#define D_WARN_BUFFERFULL \ + "WARNUNG: IR Code ist zu gross für Buffer (>= %d). " \ + "Dem Resultat sollte nicht vertraut werden bevor das behoben ist. " \ + "Bearbeite & vergrössere `kCaptureBufferSize`." + +#endif // LOCALE_DE_DE_H_ diff --git a/lib/IRremoteESP8266-2.7.0/src/locale/defaults.h b/lib/IRremoteESP8266-2.7.0/src/locale/defaults.h new file mode 100644 index 000000000..57d2d9d5b --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/locale/defaults.h @@ -0,0 +1,440 @@ +// Copyright 2019 - David Conran (@crankyoldgit) +// The default text to use throughout the library. +// The library will use this text if no locale (_IR_LOCALE_) is set or if +// the locale doesn't define particular values. +// If they are defined, this file should NOT override them. +// +// This file should contain a #define for every translateable/locale dependant +// string used by the library. Language specific files don't have to include +// everything. +// +// NOTE: ASCII/UTF-8 characters only. Unicode is NOT supported. +// +// The defaults are English (AU) / en-AU. Australia (AU) is pretty much the same +// as English (UK) for this libraries use case. +#ifndef LOCALE_DEFAULTS_H_ +#define LOCALE_DEFAULTS_H_ + +#ifndef D_STR_UNKNOWN +#define D_STR_UNKNOWN "UNKNOWN" +#endif // D_STR_UNKNOWN +#ifndef D_STR_PROTOCOL +#define D_STR_PROTOCOL "Protocol" +#endif // D_STR_PROTOCOL +#ifndef D_STR_POWER +#define D_STR_POWER "Power" +#endif // D_STR_POWER +#ifndef D_STR_ON +#define D_STR_ON "On" +#endif // D_STR_ON +#ifndef D_STR_OFF +#define D_STR_OFF "Off" +#endif // D_STR_OFF +#ifndef D_STR_MODE +#define D_STR_MODE "Mode" +#endif // D_STR_MODE +#ifndef D_STR_TOGGLE +#define D_STR_TOGGLE "Toggle" +#endif // D_STR_TOGGLE +#ifndef D_STR_TURBO +#define D_STR_TURBO "Turbo" +#endif // D_STR_TURBO +#ifndef D_STR_SUPER +#define D_STR_SUPER "Super" +#endif // D_STR_SUPER +#ifndef D_STR_SLEEP +#define D_STR_SLEEP "Sleep" +#endif // D_STR_SLEEP +#ifndef D_STR_LIGHT +#define D_STR_LIGHT "Light" +#endif // D_STR_LIGHT +#ifndef D_STR_POWERFUL +#define D_STR_POWERFUL "Powerful" +#endif // D_STR_POWERFUL +#ifndef D_STR_QUIET +#define D_STR_QUIET "Quiet" +#endif // D_STR_QUIET +#ifndef D_STR_ECONO +#define D_STR_ECONO "Econo" +#endif // D_STR_ECONO +#ifndef D_STR_SWING +#define D_STR_SWING "Swing" +#endif // D_STR_SWING +#ifndef D_STR_SWINGH +#define D_STR_SWINGH D_STR_SWING"(H)" // Set `D_STR_SWING` first! +#endif // D_STR_SWINGH +#ifndef D_STR_SWINGV +#define D_STR_SWINGV D_STR_SWING"(V)" // Set `D_STR_SWING` first! +#endif // D_STR_SWINGV +#ifndef D_STR_BEEP +#define D_STR_BEEP "Beep" +#endif // D_STR_BEEP +#ifndef D_STR_MOULD +#define D_STR_MOULD "Mould" +#endif // D_STR_MOULD +#ifndef D_STR_CLEAN +#define D_STR_CLEAN "Clean" +#endif // D_STR_CLEAN +#ifndef D_STR_PURIFY +#define D_STR_PURIFY "Purify" +#endif // D_STR_PURIFY +#ifndef D_STR_TIMER +#define D_STR_TIMER "Timer" +#endif // D_STR_TIMER +#ifndef D_STR_ONTIMER +#define D_STR_ONTIMER D_STR_ON " " D_STR_TIMER // Set `D_STR_ON` first! +#endif // D_STR_ONTIMER +#ifndef D_STR_OFFTIMER +#define D_STR_OFFTIMER D_STR_OFF " " D_STR_TIMER // Set `D_STR_OFF` first! +#endif // D_STR_OFFTIMER +#ifndef D_STR_CLOCK +#define D_STR_CLOCK "Clock" +#endif // D_STR_CLOCK +#ifndef D_STR_COMMAND +#define D_STR_COMMAND "Command" +#endif // D_STR_COMMAND +#ifndef D_STR_XFAN +#define D_STR_XFAN "XFan" +#endif // D_STR_XFAN +#ifndef D_STR_HEALTH +#define D_STR_HEALTH "Health" +#endif // D_STR_HEALTH +#ifndef D_STR_MODEL +#define D_STR_MODEL "Model" +#endif // D_STR_MODEL +#ifndef D_STR_TEMP +#define D_STR_TEMP "Temp" +#endif // D_STR_TEMP +#ifndef D_STR_IFEEL +#define D_STR_IFEEL "IFeel" +#endif // D_STR_IFEEL +#ifndef D_STR_HUMID +#define D_STR_HUMID "Humid" +#endif // D_STR_HUMID +#ifndef D_STR_SAVE +#define D_STR_SAVE "Save" +#endif // D_STR_SAVE +#ifndef D_STR_EYE +#define D_STR_EYE "Eye" +#endif // D_STR_EYE +#ifndef D_STR_FOLLOW +#define D_STR_FOLLOW "Follow" +#endif // D_STR_FOLLOW +#ifndef D_STR_ION +#define D_STR_ION "Ion" +#endif // D_STR_ION +#ifndef D_STR_FRESH +#define D_STR_FRESH "Fresh" +#endif // D_STR_FRESH +#ifndef D_STR_HOLD +#define D_STR_HOLD "Hold" +#endif // D_STR_HOLD +#ifndef D_STR_8C_HEAT +#define D_STR_8C_HEAT "8C " D_STR_HEAT // Set `D_STR_HEAT` first! +#endif // D_STR_8C_HEAT +#ifndef D_STR_BUTTON +#define D_STR_BUTTON "Button" +#endif // D_STR_BUTTON +#ifndef D_STR_NIGHT +#define D_STR_NIGHT "Night" +#endif // D_STR_NIGHT +#ifndef D_STR_SILENT +#define D_STR_SILENT "Silent" +#endif // D_STR_SILENT +#ifndef D_STR_FILTER +#define D_STR_FILTER "Filter" +#endif // D_STR_FILTER +#ifndef D_STR_3D +#define D_STR_3D "3D" +#endif // D_STR_3D +#ifndef D_STR_CELSIUS +#define D_STR_CELSIUS "Celsius" +#endif // D_STR_CELSIUS +#ifndef D_STR_UP +#define D_STR_UP "Up" +#endif // D_STR_UP +#ifndef D_STR_TEMPUP +#define D_STR_TEMPUP D_STR_TEMP " " D_STR_UP // Set `D_STR_TEMP` first! +#endif // D_STR_TEMPUP +#ifndef D_STR_DOWN +#define D_STR_DOWN "Down" +#endif // D_STR_DOWN +#ifndef D_STR_TEMPDOWN +#define D_STR_TEMPDOWN D_STR_TEMP " " D_STR_DOWN // Set `D_STR_TEMP` first! +#endif // D_STR_TEMPDOWN +#ifndef D_STR_CHANGE +#define D_STR_CHANGE "Change" +#endif // D_STR_CHANGE +#ifndef D_STR_START +#define D_STR_START "Start" +#endif // D_STR_START +#ifndef D_STR_STOP +#define D_STR_STOP "Stop" +#endif // D_STR_STOP +#ifndef D_STR_MOVE +#define D_STR_MOVE "Move" +#endif // D_STR_MOVE +#ifndef D_STR_SET +#define D_STR_SET "Set" +#endif // D_STR_SET +#ifndef D_STR_CANCEL +#define D_STR_CANCEL "Cancel" +#endif // D_STR_CANCEL +#ifndef D_STR_COMFORT +#define D_STR_COMFORT "Comfort" +#endif // D_STR_COMFORT +#ifndef D_STR_SENSOR +#define D_STR_SENSOR "Sensor" +#endif // D_STR_SENSOR +#ifndef D_STR_WEEKLY +#define D_STR_WEEKLY "Weekly" +#endif // D_STR_WEEKLY +#ifndef D_STR_WEEKLYTIMER +#define D_STR_WEEKLYTIMER D_STR_WEEKLY " " D_STR_TIMER // Needs `D_STR_WEEKLY`! +#endif // D_STR_WEEKLYTIMER +#ifndef D_STR_WIFI +#define D_STR_WIFI "WiFi" +#endif // D_STR_WIFI +#ifndef D_STR_LAST +#define D_STR_LAST "Last" +#endif // D_STR_LAST +#ifndef D_STR_FAST +#define D_STR_FAST "Fast" +#endif // D_STR_FAST +#ifndef D_STR_SLOW +#define D_STR_SLOW "Slow" +#endif // D_STR_SLOW +#ifndef D_STR_AIRFLOW +#define D_STR_AIRFLOW "Air Flow" +#endif // D_STR_AIRFLOW +#ifndef D_STR_STEP +#define D_STR_STEP "Step" +#endif // D_STR_STEP +#ifndef D_STR_NA +#define D_STR_NA "N/A" +#endif // D_STR_NA +#ifndef D_STR_OUTSIDE +#define D_STR_OUTSIDE "Outside" +#endif // D_STR_OUTSIDE +#ifndef D_STR_LOUD +#define D_STR_LOUD "Loud" +#endif // D_STR_LOUD +#ifndef D_STR_UPPER +#define D_STR_UPPER "Upper" +#endif // D_STR_UPPER +#ifndef D_STR_LOWER +#define D_STR_LOWER "Lower" +#endif // D_STR_LOWER +#ifndef D_STR_BREEZE +#define D_STR_BREEZE "Breeze" +#endif // D_STR_BREEZE +#ifndef D_STR_CIRCULATE +#define D_STR_CIRCULATE "Circulate" +#endif // D_STR_CIRCULATE +#ifndef D_STR_CEILING +#define D_STR_CEILING "Ceiling" +#endif // D_STR_CEILING +#ifndef D_STR_WALL +#define D_STR_WALL "Wall" +#endif // D_STR_WALL +#ifndef D_STR_ROOM +#define D_STR_ROOM "Room" +#endif // D_STR_ROOM +#ifndef D_STR_6THSENSE +#define D_STR_6THSENSE "6th Sense" +#endif // D_STR_6THSENSE +#ifndef D_STR_ZONEFOLLOW +#define D_STR_ZONEFOLLOW "Zone Follow" +#endif // D_STR_ZONEFOLLOW +#ifndef D_STR_FIXED +#define D_STR_FIXED "Fixed" +#endif // D_STR_FIXED + +#ifndef D_STR_AUTO +#define D_STR_AUTO "Auto" +#endif // D_STR_AUTO +#ifndef D_STR_AUTOMATIC +#define D_STR_AUTOMATIC "Automatic" +#endif // D_STR_AUTOMATIC +#ifndef D_STR_MANUAL +#define D_STR_MANUAL "Manual" +#endif // D_STR_MANUAL +#ifndef D_STR_COOL +#define D_STR_COOL "Cool" +#endif // D_STR_COOL +#ifndef D_STR_HEAT +#define D_STR_HEAT "Heat" +#endif // D_STR_HEAT +#ifndef D_STR_FAN +#define D_STR_FAN "Fan" +#endif // D_STR_FAN +#ifndef D_STR_FANONLY +#define D_STR_FANONLY "fan_only" +#endif // D_STR_FANONLY +#ifndef D_STR_DRY +#define D_STR_DRY "Dry" +#endif // D_STR_DRY + +#ifndef D_STR_MAX +#define D_STR_MAX "Max" +#endif // D_STR_MAX +#ifndef D_STR_MAXIMUM +#define D_STR_MAXIMUM "Maximum" +#endif // D_STR_MAXIMUM +#ifndef D_STR_MIN +#define D_STR_MIN "Min" +#endif // D_STR_MIN +#ifndef D_STR_MINIMUM +#define D_STR_MINIMUM "Minimum" +#endif // D_STR_MINIMUM +#ifndef D_STR_MED +#define D_STR_MED "Med" +#endif // D_STR_MED +#ifndef D_STR_MEDIUM +#define D_STR_MEDIUM "Medium" +#endif // D_STR_MEDIUM + +#ifndef D_STR_HIGHEST +#define D_STR_HIGHEST "Highest" +#endif // D_STR_HIGHEST +#ifndef D_STR_HIGH +#define D_STR_HIGH "High" +#endif // D_STR_HIGH +#ifndef D_STR_HI +#define D_STR_HI "Hi" +#endif // D_STR_HI +#ifndef D_STR_MID +#define D_STR_MID "Mid" +#endif // D_STR_MID +#ifndef D_STR_MIDDLE +#define D_STR_MIDDLE "Middle" +#endif // D_STR_MIDDLE +#ifndef D_STR_LOW +#define D_STR_LOW "Low" +#endif // D_STR_LOW +#ifndef D_STR_LO +#define D_STR_LO "Lo" +#endif // D_STR_LO +#ifndef D_STR_LOWEST +#define D_STR_LOWEST "Lowest" +#endif // D_STR_LOWEST +#ifndef D_STR_RIGHT +#define D_STR_RIGHT "Right" +#endif // D_STR_RIGHT +#ifndef D_STR_MAXRIGHT +#define D_STR_MAXRIGHT D_STR_MAX " " D_STR_RIGHT // Set `D_STR_MAX` first! +#endif // D_STR_MAXRIGHT +#ifndef D_STR_RIGHTMAX_NOSPACE +#define D_STR_RIGHTMAX_NOSPACE D_STR_RIGHT D_STR_MAX // Set `D_STR_MAX` first! +#endif // D_STR_RIGHTMAX_NOSPACE +#ifndef D_STR_LEFT +#define D_STR_LEFT "Left" +#endif // D_STR_LEFT +#ifndef D_STR_MAXLEFT +#define D_STR_MAXLEFT D_STR_MAX " " D_STR_LEFT // Set `D_STR_MAX` first! +#endif // D_STR_MAXLEFT +#ifndef D_STR_LEFTMAX_NOSPACE +#define D_STR_LEFTMAX_NOSPACE D_STR_LEFT D_STR_MAX // Set `D_STR_MAX` first! +#endif // D_STR_LEFTMAX_NOSPACE +#ifndef D_STR_WIDE +#define D_STR_WIDE "Wide" +#endif // D_STR_WIDE +#ifndef D_STR_CENTRE +#define D_STR_CENTRE "Centre" +#endif // D_STR_CENTRE +#ifndef D_STR_TOP +#define D_STR_TOP "Top" +#endif // D_STR_TOP +#ifndef D_STR_BOTTOM +#define D_STR_BOTTOM "Bottom" +#endif // D_STR_BOTTOM + +#ifndef D_STR_SPACELBRACE +#define D_STR_SPACELBRACE " (" +#endif // D_STR_SPACELBRACE +#ifndef D_STR_COMMASPACE +#define D_STR_COMMASPACE ", " +#endif // D_STR_COMMASPACE +#ifndef D_STR_COLONSPACE +#define D_STR_COLONSPACE ": " +#endif // D_STR_COLONSPACE + +#ifndef D_CHR_TIME_SEP +#define D_CHR_TIME_SEP ':' +#endif // D_CHR_TIME_SEP +#ifndef D_STR_DAY +#define D_STR_DAY "Day" +#endif // D_STR_DAY +#ifndef D_STR_DAYS +#define D_STR_DAYS D_STR_DAY "s" +#endif // D_STR_DAYS +#ifndef D_STR_HOUR +#define D_STR_HOUR "Hour" +#endif // D_STR_HOUR +#ifndef D_STR_HOURS +#define D_STR_HOURS D_STR_HOUR "s" +#endif // D_STR_HOURS +#ifndef D_STR_MINUTE +#define D_STR_MINUTE "Minute" +#endif // D_STR_MINUTE +#ifndef D_STR_MINUTES +#define D_STR_MINUTES D_STR_MINUTE "s" +#endif // D_STR_MINUTES +#ifndef D_STR_SECOND +#define D_STR_SECOND "Second" +#endif // D_STR_SECOND +#ifndef D_STR_SECONDS +#define D_STR_SECONDS D_STR_SECOND "s" +#endif // D_STR_SECONDS +#ifndef D_STR_NOW +#define D_STR_NOW "Now" +#endif // D_STR_NOW +#ifndef D_STR_THREELETTERDAYS +#define D_STR_THREELETTERDAYS "SunMonTueWedThuFriSat" +#endif // D_STR_THREELETTERDAYS + +#ifndef D_STR_YES +#define D_STR_YES "Yes" +#endif // D_STR_YES +#ifndef D_STR_NO +#define D_STR_NO "No" +#endif // D_STR_NO +#ifndef D_STR_TRUE +#define D_STR_TRUE "True" +#endif // D_STR_TRUE +#ifndef D_STR_FALSE +#define D_STR_FALSE "False" +#endif // D_STR_FALSE + +#ifndef D_STR_REPEAT +#define D_STR_REPEAT "Repeat" +#endif // D_STR_REPEAT +#ifndef D_STR_CODE +#define D_STR_CODE "Code" +#endif // D_STR_CODE +#ifndef D_STR_BITS +#define D_STR_BITS "Bits" +#endif // D_STR_BITS + +// IRrecvDumpV2 +#ifndef D_STR_TIMESTAMP +#define D_STR_TIMESTAMP "Timestamp" +#endif // D_STR_TIMESTAMP +#ifndef D_STR_LIBRARY +#define D_STR_LIBRARY "Library" +#endif // D_STR_LIBRARY +#ifndef D_STR_MESGDESC +#define D_STR_MESGDESC "Mesg Desc." +#endif // D_STR_MESGDESC +#ifndef D_STR_IRRECVDUMP_STARTUP +#define D_STR_IRRECVDUMP_STARTUP \ + "IRrecvDumpV2 is now running and waiting for IR input on Pin %d" +#endif // D_STR_IRRECVDUMP_STARTUP +#ifndef D_WARN_BUFFERFULL +#define D_WARN_BUFFERFULL \ + "WARNING: IR code is too big for buffer (>= %d). " \ + "This result shouldn't be trusted until this is resolved. " \ + "Edit & increase `kCaptureBufferSize`." +#endif // D_WARN_BUFFERFULL + +#endif // LOCALE_DEFAULTS_H_ diff --git a/lib/IRremoteESP8266-2.7.0/src/locale/en-AU.h b/lib/IRremoteESP8266-2.7.0/src/locale/en-AU.h new file mode 100644 index 000000000..63ecf2282 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/locale/en-AU.h @@ -0,0 +1,8 @@ +// Copyright 2019 - David Conran (@crankyoldgit) +// Locale/language file for English / Australia. +// This file will override the default values located in `defaults.h`. +#ifndef LOCALE_EN_AU_H_ +#define LOCALE_EN_AU_H_ +// Nothing should really need to be set here, as en-AU is the default +// locale/language. +#endif // LOCALE_EN_AU_H__ diff --git a/lib/IRremoteESP8266-2.7.0/src/locale/en-IE.h b/lib/IRremoteESP8266-2.7.0/src/locale/en-IE.h new file mode 100644 index 000000000..6a0304bca --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/locale/en-IE.h @@ -0,0 +1,8 @@ +// Copyright 2019 - David Conran (@crankyoldgit) +// Locale/language file for English / Ireland. +// This file will override the default values located in `defaults.h`. +#ifndef LOCALE_EN_IE_H_ +#define LOCALE_EN_IE_H_ +// Nothing should really need to be set here, as en-IE is the same as en-AU, +// which is the default locale/language. +#endif // LOCALE_EN_IE_H__ diff --git a/lib/IRremoteESP8266-2.7.0/src/locale/en-UK.h b/lib/IRremoteESP8266-2.7.0/src/locale/en-UK.h new file mode 100644 index 000000000..2aa57f5ce --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/locale/en-UK.h @@ -0,0 +1,8 @@ +// Copyright 2019 - David Conran (@crankyoldgit) +// Locale/language file for English / United Kingdom. +// This file will override the default values located in `defaults.h`. +#ifndef LOCALE_EN_UK_H_ +#define LOCALE_EN_UK_H_ +// Nothing should really need to be set here, as en-UK is the same as en-AU, +// which is the default locale/language. +#endif // LOCALE_EN_UK_H__ diff --git a/lib/IRremoteESP8266-2.7.0/src/locale/en-US.h b/lib/IRremoteESP8266-2.7.0/src/locale/en-US.h new file mode 100644 index 000000000..7dda393bf --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/locale/en-US.h @@ -0,0 +1,13 @@ +// Copyright 2019 - David Conran (@crankyoldgit) +// Locale/language file for English / United States of America. +// This file will override the default values located in `defaults.h`. +#ifndef LOCALE_EN_US_H_ +#define LOCALE_EN_US_H_ +// Not much should really need to be set here, as English is the default +// locale/language. + +// Overrides to the default. +#define D_STR_CENTRE "Center" +#define D_STR_MOULD "Mold" + +#endif // LOCALE_EN_US_H__ diff --git a/lib/IRremoteESP8266-2.7.0/src/locale/es-ES.h b/lib/IRremoteESP8266-2.7.0/src/locale/es-ES.h new file mode 100644 index 000000000..821186141 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/locale/es-ES.h @@ -0,0 +1,134 @@ +// Copyright 2019 - Carlos (@charlieyv) +// Locale/language file for Spanish / Spain. +// This file will override the default values located in `defaults.h`. +#ifndef LOCALE_ES_ES_H_ +#define LOCALE_ES_ES_H_ + +#define D_STR_UNKNOWN "DESCONOCIDO" +#define D_STR_PROTOCOL "Protocolo" +#define D_STR_POWER "Poder" +#define D_STR_ON "Encendido" +#define D_STR_OFF "Apagado" +#define D_STR_MODE "Modo" +#define D_STR_TOGGLE "Palanca" +#define D_STR_SLEEP "Dormir" +#define D_STR_LIGHT "Luz" +#define D_STR_POWERFUL "Poderoso" +#define D_STR_QUIET "Silencio" +#define D_STR_ECONO "Econo" +#define D_STR_SWING "Oscilar" +#define D_STR_SWINGH D_STR_SWING"(H)" +#define D_STR_SWINGV D_STR_SWING"(V)" +#define D_STR_BEEP "Bip" +#define D_STR_MOULD "Molde" +#define D_STR_CLEAN "Limpiar" +#define D_STR_PURIFY "Purificar" +#define D_STR_TIMER "Temporizador" +#define D_STR_ONTIMER D_STR_ON " " D_STR_TIMER +#define D_STR_OFFTIMER D_STR_OFF " " D_STR_TIMER +#define D_STR_CLOCK "Reloj" +#define D_STR_COMMAND "Comando" +#define D_STR_HEALTH "Salud" +#define D_STR_MODEL "Modelo" +#define D_STR_TEMP "Temperatura" +#define D_STR_HUMID "Humedo" +#define D_STR_SAVE "Guardar" +#define D_STR_EYE "Ojo" +#define D_STR_FOLLOW "Seguir" +#define D_STR_FRESH "Fresco" +#define D_STR_HOLD "Mantener" +#define D_STR_8C_HEAT "8C " D_STR_HEAT +#define D_STR_BUTTON "Boton" +#define D_STR_NIGHT "Noche" +#define D_STR_SILENT "Silencio" +#define D_STR_FILTER "Filtro" +#define D_STR_UP "Arriba" +#define D_STR_TEMPUP D_STR_TEMP " " D_STR_UP +#define D_STR_DOWN "Abajo" +#define D_STR_TEMPDOWN D_STR_TEMP " " D_STR_DOWN +#define D_STR_CHANGE "Cambiar" +#define D_STR_START "Comenzar" +#define D_STR_STOP "Parar" +#define D_STR_MOVE "Mover" +#define D_STR_SET "Fijar" +#define D_STR_CANCEL "Cancelar" +#define D_STR_COMFORT "Comodo" +#define D_STR_WEEKLY "Semanal" +#define D_STR_WEEKLYTIMER D_STR_WEEKLY " " D_STR_TIMER +#define D_STR_LAST "Ultimo" +#define D_STR_FAST "Rapido" +#define D_STR_SLOW "Lento" +#define D_STR_AIRFLOW "Flujo de Aire" +#define D_STR_STEP "Paso" +#define D_STR_OUTSIDE "Afuera" +#define D_STR_LOUD "Ruidoso" +#define D_STR_UPPER "Superior" +#define D_STR_LOWER "Inferior" +#define D_STR_BREEZE "Brisa" +#define D_STR_CIRCULATE "Circular" +#define D_STR_CEILING "Techo" +#define D_STR_WALL "Pared" +#define D_STR_ROOM "Cuarto" +#define D_STR_6THSENSE "6to. Sentido" +#define D_STR_ZONEFOLLOW "Zona Seguir" +#define D_STR_FIXED "Fijo" +#define D_STR_AUTOMATIC "Automatico" +#define D_STR_COOL "Frio" +#define D_STR_HEAT "Calor" +#define D_STR_FAN "Ventilador" +#define D_STR_FANONLY "ventilador_solamente" +#define D_STR_DRY "Seco" +#define D_STR_MAX "Max" +#define D_STR_MAXIMUM "Maximo" +#define D_STR_MIN "Min" +#define D_STR_MINIMUM "Minimo" +#define D_STR_MED "Med" +#define D_STR_MEDIUM "Medio" +#define D_STR_HIGHEST "Mas Alto" +#define D_STR_HIGH "Alto" +#define D_STR_HI D_STR_HIGH +#define D_STR_MIDDLE "Medio" +#define D_STR_MID D_STR_MIDDLE +#define D_STR_LOW "Bajo" +#define D_STR_LO D_STR_LOW +#define D_STR_LOWEST "Mas Bajo" +#define D_STR_RIGHT "Derecha" +#define D_STR_MAXRIGHT D_STR_MAX " " D_STR_RIGHT +#define D_STR_RIGHTMAX_NOSPACE D_STR_RIGHT D_STR_MAX +#define D_STR_LEFT "Izquierda" +#define D_STR_MAXLEFT D_STR_MAX " " D_STR_LEFT +#define D_STR_LEFTMAX_NOSPACE D_STR_LEFT D_STR_MAX +#define D_STR_WIDE "Ancho" +#define D_STR_CENTRE "Centro" +#define D_STR_TOP "Tope" +#define D_STR_BOTTOM "Fondo" +#define D_STR_DAY "Dia" +#define D_STR_DAYS D_STR_DAY "s" +#define D_STR_HOUR "Hora" +#define D_STR_HOURS D_STR_HOUR "s" +#define D_STR_MINUTE "Minuto" +#define D_STR_MINUTES D_STR_MINUTE "s" +#define D_STR_SECOND "Segundo" +#define D_STR_SECONDS D_STR_SECOND "s" +#define D_STR_NOW "Ahora" +#define D_STR_THREELETTERDAYS "DomLunMarMieJueVieSab" +#define D_STR_YES "Si" +#define D_STR_NO "No" +#define D_STR_TRUE "Cierto" +#define D_STR_FALSE "Falso" +#define D_STR_REPEAT "Repetir" +#define D_STR_CODE "Codigo" + +// IRrecvDumpV2 +#define D_STR_TIMESTAMP "marca de tiempo" +#define D_STR_LIBRARY "Libreria" +#define D_STR_IRRECVDUMP_STARTUP \ + "IRrecvDumpV2 esta ahora corriendo y esperando por comando IR en Pin %d" +#ifndef D_WARN_BUFFERFULL +#define D_WARN_BUFFERFULL \ + "WARNING: Codigo IR es muy grande para el buffer (>= %d). "\ + "Este resultando no debe ser reconocido hasta que esto sea resuelto." \ + "Edite & incremente `kCaptureBufferSize`." +#endif // D_WARN_BUFFERFULL + +#endif // LOCALE_ES_ES_H_ diff --git a/lib/IRremoteESP8266-2.7.0/src/locale/fr-FR.h b/lib/IRremoteESP8266-2.7.0/src/locale/fr-FR.h new file mode 100644 index 000000000..5ab10cb62 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/src/locale/fr-FR.h @@ -0,0 +1,115 @@ +// Copyright 2019 - Mathieu D(@Knackie) +// Locale/language file for French / Quebec. +// This file will override the default values located in `defaults.h`. +#ifndef LOCALE_FR_FR_H_ +#define LOCALE_FR_FR_H_ + +#define D_STR_UNKNOWN "INCONNU" +#define D_STR_PROTOCOL "Protocole" +#define D_STR_TOGGLE "Bascule" +#define D_STR_SLEEP "Pause" +#define D_STR_LIGHT "Lumière" +#define D_STR_POWERFUL "Puissance" +#define D_STR_QUIET "Silence" +#define D_STR_ECONO "Economie" +#define D_STR_BEEP "Bip" +#define D_STR_MOULD "Moule" +#define D_STR_CLEAN "Nettoyer" +#define D_STR_PURIFY "Purifier" +#define D_STR_ON "On" +#define D_STR_OFF "Off" +#define D_STR_ONTIMER D_STR_ON " " D_STR_TIMER +#define D_STR_OFFTIMER D_STR_OFF " " D_STR_TIMER +#define D_STR_CLOCK "Heure" +#define D_STR_COMMAND "Commandement" +#define D_STR_HEALTH "Santé" +#define D_STR_TEMP "Temporaire" +#define D_STR_HUMID "Humidité" +#define D_STR_SAVE "Sauvegarder" +#define D_STR_EYE "Oeil" +#define D_STR_FOLLOW "Suivre" +#define D_STR_FRESH "Frais" +#define D_STR_HOLD "Maintenir" +#define D_STR_BUTTON "Bouton" +#define D_STR_NIGHT "Nuit" +#define D_STR_SILENT "Silence" +#define D_STR_UP "En haut" +#define D_STR_TEMPUP D_STR_TEMP " " D_STR_UP +#define D_STR_DOWN "En bas" +#define D_STR_TEMPDOWN D_STR_TEMP " " D_STR_DOWN +#define D_STR_CHANGE "Changement" +#define D_STR_SET "Mettre" +#define D_STR_CANCEL "Annuler" +#define D_STR_COMFORT "Confort" +#define D_STR_WEEKLY "Chaque semaine" +#define D_STR_WEEKLYTIMER D_STR_WEEKLY " " D_STR_TIMER +#define D_STR_FAST "Rapide" +#define D_STR_SLOW "Lent" +#define D_STR_AIRFLOW "Ebauche" +#define D_STR_STEP "Etape" +#define D_STR_OUTSIDE "Plein air" +#define D_STR_LOUD "Fort" +#define D_STR_UPPER "Au dessus" +#define D_STR_LOWER "En dessous" +#define D_STR_BREEZE "Brise" +#define D_STR_CIRCULATE "Faire circuler" +#define D_STR_CEILING "Plafond" +#define D_STR_WALL "Mur" +#define D_STR_ROOM "Pièce" +#define D_STR_6THSENSE "6ter Sens" +#define D_STR_FIXED "Fixer" + +#define D_STR_AUTOMATIC "Automatique" +#define D_STR_MANUAL "Manuel" +#define D_STR_COOL "Frais" +#define D_STR_HEAT "Chaleur" +#define D_STR_FAN "Ventillateur" +#define D_STR_FANONLY "Seul_fan" +#define D_STR_DRY "Sec" + +#define D_STR_MEDIUM "Moyen" + +#define D_STR_HIGHEST "Le plus haut" +#define D_STR_HIGH "Haut" +#define D_STR_HI "H" +#define D_STR_MID "M" +#define D_STR_MIDDLE "Moitié" +#define D_STR_LOW "Bas" +#define D_STR_LO "B" +#define D_STR_LOWEST "Le plus bas" +#define D_STR_RIGHT "Droite" +#define D_STR_MAX "Max" +#define D_STR_MAXRIGHT D_STR_MAX " " D_STR_RIGHT +#define D_STR_RIGHTMAX_NOSPACE D_STR_RIGHT D_STR_MAX +#define D_STR_LEFT "Gauche" +#define D_STR_MAXLEFT D_STR_MAX " " D_STR_LEFT +#define D_STR_LEFTMAX_NOSPACE D_STR_LEFT D_STR_MAX +#define D_STR_WIDE "Large" +#define D_STR_TOP "Au-dessus" +#define D_STR_BOTTOM "En-dessous" + +#define D_STR_DAY "Jour" +#define D_STR_HOUR "Heure" +#define D_STR_SECOND "Seconde" +#define D_STR_NOW "Maintenant" +#define D_STR_THREELETTERDAYS "LunMarMerJeuVenSamDim" + +#define D_STR_YES "Oui" +#define D_STR_NO "Non" +#define D_STR_TRUE "Vrai" +#define D_STR_FALSE "Faux" + +#define D_STR_REPEAT "Répetition" + +// IRrecvDumpV2 +#define D_STR_TIMESTAMP "Horodatage" +#define D_STR_LIBRARY "Bibliothèque" +#define D_STR_MESGDESC "Rèférence" +#define D_STR_IRRECVDUMP_STARTUP \ + "IRrecvDumpV2 fonctionne et attend l’entrée IR sur la broche %d" +#define D_WARN_BUFFERFULL \ + "ATTENTION: IR Code est trop gros pour le buffer (>= %d). " \ + "Le résultat ne doit pas être approuvé avant que cela soit résolu. " \ + "Modifier et agrandir `kCaptureBufferSize`." + +#endif // LOCALE_FR_FR_H_ diff --git a/lib/IRremoteESP8266-2.6.5/test/IRac_test.cpp b/lib/IRremoteESP8266-2.7.0/test/IRac_test.cpp old mode 100755 new mode 100644 similarity index 83% rename from lib/IRremoteESP8266-2.6.5/test/IRac_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/IRac_test.cpp index 3afc89c6e..dfe808db4 --- a/lib/IRremoteESP8266-2.6.5/test/IRac_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/IRac_test.cpp @@ -39,7 +39,7 @@ TEST(TestIRac, Amcor) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 5 (AUTO), Fan: 3 (High), Temp: 19C, Max: Off"; + "Power: On, Mode: 5 (Auto), Fan: 3 (High), Temp: 19C, Max: Off"; ac.begin(); irac.amcor(&ac, @@ -81,8 +81,8 @@ TEST(TestIRac, Coolix) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 3 (HEAT), Fan: 1 (MAX), Temp: 21C, Zone Follow: Off, " - "Sensor Temp: Ignored"; + "Power: On, Mode: 3 (Heat), Fan: 1 (Max), Temp: 21C, Zone Follow: Off, " + "Sensor Temp: Off"; ac.begin(); irac.coolix(&ac, @@ -140,11 +140,11 @@ TEST(TestIRac, Daikin) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 3 (COOL), Temp: 19C, Fan: 5 (High), Powerful: Off, " - "Quiet: Off, Sensor: Off, Mold: On, Comfort: Off, " - "Swing (Horizontal): Off, Swing (Vertical): Off, " - "Current Time: 00:00, Current Day: (UNKNOWN), On Time: Off, " - "Off Time: Off, Weekly Timer: On"; + "Power: On, Mode: 3 (Cool), Temp: 19C, Fan: 5 (High), Powerful: Off, " + "Quiet: Off, Sensor: Off, Mould: On, Comfort: Off, " + "Swing(H): Off, Swing(V): Off, " + "Clock: 00:00, Day: 0 (UNKNOWN), On Timer: Off, " + "Off Timer: Off, Weekly Timer: On"; ac.begin(); irac.daikin(&ac, @@ -171,10 +171,10 @@ TEST(TestIRac, Daikin128) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power Toggle: On, Mode: 8 (HEAT), Temp: 27C, Fan: 9 (Quiet), " - "Powerful: Off, Quiet: On, Swing (V): On, Sleep: On, " - "Econo: Off, Clock: 21:57, On Timer: Off, On Time: 00:00, " - "Off Timer: Off, Off Time: 00:00, Light Toggle: 8 (Wall)"; + "Power Toggle: On, Mode: 8 (Heat), Temp: 27C, Fan: 9 (Quiet), " + "Powerful: Off, Quiet: On, Swing(V): On, Sleep: On, " + "Econo: Off, Clock: 21:57, On Timer: Off, On Timer: 00:00, " + "Off Timer: Off, Off Timer: 00:00, Light Toggle: 8 (Wall)"; ac.begin(); irac.daikin128(&ac, @@ -197,13 +197,39 @@ TEST(TestIRac, Daikin128) { ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); } +TEST(TestIRac, Daikin152) { + IRDaikin152 ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 3 (Cool), Temp: 27C, Fan: 3 (Medium), Swing(V): On, " + "Powerful: Off, Quiet: Off, Econo: On, Sensor: Off, Comfort: Off"; + + ac.begin(); + irac.daikin152(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 27, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kAuto, // Veritcal swing + false, // Quiet + false, // Turbo + true); // Econo + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(DAIKIN152, ac._irsend.capture.decode_type); + ASSERT_EQ(kDaikin152Bits, ac._irsend.capture.bits); + ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); +} + TEST(TestIRac, Daikin160) { IRDaikin160 ac(0); IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 2 (DRY), Temp: 23C, Fan: 1 (Low), " - "Vent Position (V): 3 (Middle)"; + "Power: On, Mode: 2 (Dry), Temp: 23C, Fan: 1 (Low), " + "Swing(V): 3 (Middle)"; ac.begin(); irac.daikin160(&ac, @@ -225,7 +251,7 @@ TEST(TestIRac, Daikin176) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 7 (COOL), Temp: 26C, Fan: 1 (Low), Swing (H): 5 (Auto)"; + "Power: On, Mode: 7 (Cool), Temp: 26C, Fan: 1 (Low), Swing(H): 5 (Auto)"; ac.begin(); irac.daikin176(&ac, @@ -247,11 +273,11 @@ TEST(TestIRac, Daikin2) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 3 (COOL), Temp: 19C, Fan: 1 (Low), " - "Swing (V): 14 (Auto), Swing (H): 0, Clock: 00:00, On Time: Off, " - "Off Time: Off, Sleep Time: Off, Beep: 1 (Quiet), Light: 1 (Bright), " - "Mold: On, Clean: Off, Fresh Air: Off, Eye: Off, Eye Auto: Off, " - "Quiet: Off, Powerful: Off, Purify: On, Econo: Off"; + "Power: On, Mode: 3 (Cool), Temp: 19C, Fan: 1 (Low), " + "Swing(V): 14 (Auto), Swing(H): 170 (UNKNOWN), Clock: 00:00, " + "On Timer: Off, Off Timer: Off, Sleep Timer: Off, Beep: 2 (Loud), " + "Light: 1 (High), Mould: On, Clean: On, Fresh: Off, Eye: Off, " + "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off"; ac.begin(); irac.daikin2(&ac, @@ -260,13 +286,14 @@ TEST(TestIRac, Daikin2) { 19, // Celsius stdAc::fanspeed_t::kLow, // Fan speed stdAc::swingv_t::kOff, // Veritcal swing - stdAc::swingh_t::kOff, // Horizontal swing + stdAc::swingh_t::kMiddle, // Horizontal swing false, // Quiet false, // Turbo true, // Light false, // Econo - true, // Filter + true, // Filter (aka Purify) true, // Clean (aka Mold) + true, // Beep (Loud) -1, // Sleep time -1); // Current time ASSERT_EQ(expected, ac.toString()); @@ -282,8 +309,8 @@ TEST(TestIRac, Daikin216) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 4 (HEAT), Temp: 31C, Fan: 11 (Quiet), " - "Swing (Horizontal): On, Swing (Vertical): On, Quiet: On, Powerful: Off"; + "Power: On, Mode: 4 (Heat), Temp: 31C, Fan: 11 (Quiet), " + "Swing(H): On, Swing(V): On, Quiet: On, Powerful: Off"; ac.begin(); irac.daikin216(&ac, @@ -308,7 +335,7 @@ TEST(TestIRac, Electra) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 6 (FAN), Temp: 26C, Fan: 1 (High), " + "Power: On, Mode: 6 (Fan), Temp: 26C, Fan: 1 (High), " "Swing(V): On, Swing(H): On"; ac.begin(); @@ -333,12 +360,14 @@ TEST(TestIRac, Fujitsu) { IRac irac(0); IRrecv capture(0); std::string ardb1_expected = - "Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 19C, " + "Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 19C, " "Fan: 2 (Medium), Command: N/A"; std::string arrah2e_expected = - "Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 19C, " - "Fan: 2 (Medium), Swing: Off, Command: N/A"; - + "Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 19C, " + "Fan: 2 (Medium), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A"; + std::string arry4_expected = + "Model: 5 (ARRY4), Power: On, Mode: 1 (Cool), Temp: 19C, " + "Fan: 2 (Medium), Clean: On, Filter: On, Swing: 0 (Off), Command: N/A"; ac.begin(); irac.fujitsu(&ac, ARDB1, // Model @@ -350,7 +379,9 @@ TEST(TestIRac, Fujitsu) { stdAc::swingh_t::kOff, // Horizontal swing false, // Quiet false, // Turbo (Powerful) - false); // Econo + false, // Econo + true, // Filter + true); // Clean ASSERT_EQ(ardb1_expected, ac.toString()); ac._irsend.makeDecodeResult(); EXPECT_TRUE(capture.decode(&ac._irsend.capture)); @@ -369,13 +400,35 @@ TEST(TestIRac, Fujitsu) { stdAc::swingh_t::kOff, // Horizontal swing false, // Quiet false, // Turbo (Powerful) - false); // Econo + false, // Econo + true, // Filter + true); // Clean ASSERT_EQ(arrah2e_expected, ac.toString()); ac._irsend.makeDecodeResult(); EXPECT_TRUE(capture.decode(&ac._irsend.capture)); ASSERT_EQ(FUJITSU_AC, ac._irsend.capture.decode_type); ASSERT_EQ(kFujitsuAcBits, ac._irsend.capture.bits); ASSERT_EQ(arrah2e_expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); + ac._irsend.reset(); + irac.fujitsu(&ac, + fujitsu_ac_remote_model_t::ARRY4, // Model + true, // Power + stdAc::opmode_t::kCool, // Mode + 19, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + stdAc::swingh_t::kOff, // Horizontal swing + false, // Quiet + false, // Turbo (Powerful) + false, // Econo + true, // Filter + true); // Clean + ASSERT_EQ(arry4_expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(FUJITSU_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits, ac._irsend.capture.bits); + ASSERT_EQ(arry4_expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); } TEST(TestIRac, Goodweather) { @@ -383,7 +436,7 @@ TEST(TestIRac, Goodweather) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 2 (Medium), Turbo: Toggle, " + "Power: On, Mode: 1 (Cool), Temp: 19C, Fan: 2 (Medium), Turbo: Toggle, " "Light: Toggle, Sleep: Toggle, Swing: 1 (Slow), Command: 0 (Power)"; ac.begin(); @@ -409,10 +462,10 @@ TEST(TestIRac, Gree) { IRac irac(0); IRrecv capture(0); char expected[] = - "Model: 1 (YAW1F), Power: On, Mode: 1 (COOL), Temp: 22C, " + "Model: 1 (YAW1F), Power: On, Mode: 1 (Cool), Temp: 22C, " "Fan: 2 (Medium), Turbo: Off, IFeel: Off, WiFi: Off, XFan: On, " - "Light: On, Sleep: On, Swing Vertical Mode: Manual, " - "Swing Vertical Pos: 3, Timer: Off"; + "Light: On, Sleep: On, Swing(V) Mode: Manual, " + "Swing(V): 3 (UNKNOWN), Timer: Off"; ac.begin(); irac.gree(&ac, @@ -439,8 +492,8 @@ TEST(TestIRac, Haier) { IRac irac(0); IRrecv capture(0); char expected[] = - "Command: 1 (On), Mode: 1 (COOL), Temp: 24C, Fan: 2 (Medium), " - "Swing: 1 (Up), Sleep: On, Health: On, Current Time: 13:45, " + "Command: 1 (On), Mode: 1 (Cool), Temp: 24C, Fan: 2 (Medium), " + "Swing: 1 (Up), Sleep: On, Health: On, Clock: 13:45, " "On Timer: Off, Off Timer: Off"; ac.begin(); @@ -467,8 +520,9 @@ TEST(TestIRac, HaierYrwo2) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Button: 5 (Power), Mode: 2 (COOL), Temp: 23C, " - "Fan: 4 (Medium), Turbo: 1 (High), Swing: 1 (Top), Sleep: On, Health: On"; + "Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 23C, " + "Fan: 2 (Medium), Turbo: 1 (High), Swing: 1 (Highest), Sleep: On, " + "Health: On"; ac.begin(); irac.haierYrwo2(&ac, @@ -493,8 +547,8 @@ TEST(TestIRac, Hitachi) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 2 (AUTO), Temp: 22C, Fan: 3 (Medium), " - "Swing (Vertical): Off, Swing (Horizontal): On"; + "Power: On, Mode: 2 (Auto), Temp: 22C, Fan: 3 (Medium), " + "Swing(V): Off, Swing(H): On"; ac.begin(); irac.hitachi(&ac, @@ -513,14 +567,36 @@ TEST(TestIRac, Hitachi) { ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); } +TEST(TestIRac, Hitachi424) { + IRHitachiAc424 ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 6 (Heat), Temp: 25C, Fan: 6 (Max)"; + + ac.begin(); + irac.hitachi424(&ac, + true, // Power + stdAc::opmode_t::kHeat, // Mode + 25, // Celsius + stdAc::fanspeed_t::kMax); // Fan speed + + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(HITACHI_AC424, ac._irsend.capture.decode_type); + ASSERT_EQ(kHitachiAc424Bits, ac._irsend.capture.bits); + ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); +} + TEST(TestIRac, Kelvinator) { IRKelvinatorAC ac(0); IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 3 (Medium), Turbo: Off, " - "Quiet: Off, XFan: On, IonFilter: On, Light: On, " - "Swing (Horizontal): Off, Swing (Vertical): Off"; + "Power: On, Mode: 1 (Cool), Temp: 19C, Fan: 3 (Medium), Turbo: Off, " + "Quiet: Off, XFan: On, Ion: On, Light: On, " + "Swing(H): Off, Swing(V): Off"; ac.begin(); irac.kelvinator(&ac, @@ -549,7 +625,7 @@ TEST(TestIRac, Midea) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 1 (DRY), Celsius: On, Temp: 27C/80F, Fan: 2 (Medium), " + "Power: On, Mode: 1 (Dry), Celsius: On, Temp: 27C/80F, Fan: 2 (Medium), " "Sleep: On, Swing(V) Toggle: Off"; ac.begin(); @@ -559,7 +635,7 @@ TEST(TestIRac, Midea) { true, // Celsius 27, // Degrees stdAc::fanspeed_t::kMedium, // Fan speed - stdAc::swingv_t::kOff, // Swing (V) + stdAc::swingv_t::kOff, // Swing(V) 8 * 60 + 0); // Sleep time ASSERT_EQ(expected, ac.toString()); @@ -575,8 +651,9 @@ TEST(TestIRac, Mitsubishi) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 24 (COOL), Temp: 20C, Fan: 2 (Medium), Vane: AUTO, " - "Wide Vane: 3, Time: 14:30, On timer: 00:00, Off timer: 00:00, Timer: -"; + "Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 2 (Medium), " + "Swing(V): 0 (Auto), Swing(H): 3 (UNKNOWN), " + "Clock: 14:30, On Timer: 00:00, Off Timer: 00:00, Timer: -"; ac.begin(); irac.mitsubishi(&ac, @@ -596,13 +673,37 @@ TEST(TestIRac, Mitsubishi) { ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); } +TEST(TestIRac, Mitsubishi136) { + IRMitsubishi136 ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 5 (Dry), Temp: 22C, Fan: 3 (High), " + "Swing(V): 3 (Highest), Quiet: Off"; + + ac.begin(); + irac.mitsubishi136(&ac, + true, // Power + stdAc::opmode_t::kDry, // Mode + 22, // Celsius + stdAc::fanspeed_t::kMax, // Fan speed + stdAc::swingv_t::kHighest, // Veritcal swing + false); // Quiet + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(MITSUBISHI136, ac._irsend.capture.decode_type); + ASSERT_EQ(kMitsubishi136Bits, ac._irsend.capture.bits); + ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); +} + TEST(TestIRac, MitsubishiHeavy88) { IRMitsubishiHeavy88Ac ac(0); IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (Medium), " - "Swing (V): 16 (Auto), Swing (H): 0 (Off), Turbo: Off, Econo: Off, " + "Power: On, Mode: 1 (Cool), Temp: 21C, Fan: 3 (Med), " + "Swing(V): 4 (Auto), Swing(H): 0 (Off), Turbo: Off, Econo: Off, " "3D: Off, Clean: On"; ac.begin(); @@ -629,8 +730,8 @@ TEST(TestIRac, MitsubishiHeavy152) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 6 (Econo), " - "Swing (V): 6 (Off), Swing (H): 0 (Auto), Silent: On, Turbo: Off, " + "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 6 (Econo), " + "Swing(V): 6 (Off), Swing(H): 0 (Auto), Silent: On, Turbo: Off, " "Econo: On, Night: On, Filter: On, 3D: Off, Clean: Off"; ac.begin(); @@ -660,7 +761,7 @@ TEST(TestIRac, Neoclima) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 3 (Low), " + "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 3 (Low), " "Swing(V): Off, Swing(H): On, Sleep: On, Turbo: Off, Hold: Off, Ion: On, " "Eye: Off, Light: On, Follow: Off, 8C Heat: Off, Fresh: Off, " "Button: 0 (Power)"; @@ -690,8 +791,8 @@ TEST(TestIRac, Panasonic) { IRac irac(0); IRrecv capture(0); char expected_nke[] = - "Model: 2 (NKE), Power: On, Mode: 4 (HEAT), Temp: 28C, Fan: 2 (Medium), " - "Swing (Vertical): 15 (AUTO), Swing (Horizontal): 6 (Middle), Quiet: On, " + "Model: 2 (NKE), Power: On, Mode: 4 (Heat), Temp: 28C, Fan: 2 (Medium), " + "Swing(V): 15 (Auto), Swing(H): 6 (Middle), Quiet: On, " "Powerful: Off, Clock: 19:17, On Timer: Off, Off Timer: Off"; ac.begin(); @@ -714,8 +815,8 @@ TEST(TestIRac, Panasonic) { ASSERT_EQ(expected_nke, IRAcUtils::resultAcToString(&ac._irsend.capture)); char expected_dke[] = - "Model: 3 (DKE), Power: On, Mode: 3 (COOL), Temp: 18C, Fan: 4 (High), " - "Swing (Vertical): 1 (Full Up), Swing (Horizontal): 6 (Middle), " + "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"; ac._irsend.reset(); irac.panasonic(&ac, @@ -742,7 +843,7 @@ TEST(TestIRac, Samsung) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 0 (AUTO), Temp: 28C, Fan: 6 (Auto), Swing: On, " + "Power: On, Mode: 0 (Auto), Temp: 28C, Fan: 6 (Auto), Swing: On, " "Beep: On, Clean: On, Quiet: On, Powerful: Off"; ac.begin(); @@ -756,6 +857,7 @@ TEST(TestIRac, Samsung) { false, // Turbo true, // Clean true, // Beep + true, // Previous power state false); // with dopower Off ASSERT_EQ(expected, ac.toString()); ac._irsend.makeDecodeResult(); @@ -775,6 +877,7 @@ TEST(TestIRac, Samsung) { false, // Turbo true, // Clean true, // Beep + true, // Previous power state true); // with dopower On ASSERT_EQ(expected, ac.toString()); // Class should be in the desired mode. ac._irsend.makeDecodeResult(); @@ -784,7 +887,7 @@ TEST(TestIRac, Samsung) { // However, we expect a plain "on" state as it should be sent before the // desired state. char expected_on[] = - "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (Auto), Swing: Off, " + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off"; ASSERT_EQ(expected_on, IRAcUtils::resultAcToString(&ac._irsend.capture)); } @@ -794,7 +897,7 @@ TEST(TestIRac, Sharp) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 3 (Medium)"; + "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 3 (Medium)"; ac.begin(); irac.sharp(&ac, @@ -815,8 +918,8 @@ TEST(TestIRac, Tcl112) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 3 (Medium), Econo: On, " - "Health: On, Light: On, Turbo: Off, Swing (H): On, Swing (V): Off"; + "Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 3 (Medium), Econo: On, " + "Health: On, Light: On, Turbo: Off, Swing(H): On, Swing(V): Off"; ac.begin(); irac.tcl112(&ac, @@ -843,8 +946,8 @@ TEST(TestIRac, Teco) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 0 (AUTO), Temp: 21C, Fan: 2 (Medium), Sleep: On, " - "Swing: On, Light: On, Humid: Off, Save: Off"; + "Power: On, Mode: 0 (Auto), Temp: 21C, Fan: 2 (Medium), Sleep: On, " + "Swing: On, Light: On, Humid: Off, Save: Off, Timer: Off"; ac.begin(); irac.teco(&ac, @@ -867,7 +970,7 @@ TEST(TestIRac, Toshiba) { IRToshibaAC ac(0); IRac irac(0); IRrecv capture(0); - char expected[] = "Power: On, Mode: 2 (DRY), Temp: 29C, Fan: 2 (UNKNOWN)"; + char expected[] = "Power: On, Mode: 2 (Dry), Temp: 29C, Fan: 2 (UNKNOWN)"; ac.begin(); irac.toshiba(&ac, @@ -888,7 +991,7 @@ TEST(TestIRac, Trotec) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 3 (High), Sleep: On"; + "Power: On, Mode: 1 (Cool), Temp: 18C, Fan: 3 (High), Sleep: On"; ac.begin(); irac.trotec(&ac, @@ -915,7 +1018,7 @@ TEST(TestIRac, Vestel) { IRac irac(0); IRrecv capture(0); char expected[] = - "Power: On, Mode: 0 (AUTO), Temp: 22C, Fan: 5 (Low), Sleep: On, " + "Power: On, Mode: 0 (Auto), Temp: 22C, Fan: 5 (Low), Sleep: On, " "Turbo: Off, Ion: On, Swing: On"; ac.begin(); @@ -938,7 +1041,7 @@ TEST(TestIRac, Vestel) { ac._irsend.reset(); char expected_clocks[] = - "Time: 13:45, Timer: Off, On Timer: Off, Off Timer: Off"; + "Clock: 13:45, Timer: Off, On Timer: Off, Off Timer: Off"; ac.begin(); irac.vestel(&ac, @@ -1003,9 +1106,9 @@ TEST(TestIRac, Whirlpool) { IRac irac(0); IRrecv capture(0); char expected[] = - "Model: 1 (DG11J13A), Power toggle: On, Mode: 1 (AUTO), Temp: 21C, " + "Model: 1 (DG11J13A), Power Toggle: On, Mode: 1 (Auto), Temp: 21C, " "Fan: 3 (Low), Swing: On, Light: On, Clock: 23:58, On Timer: Off, " - "Off Timer: Off, Sleep: On, Super: Off, Command: 1 (POWER)"; + "Off Timer: Off, Sleep: On, Super: Off, Command: 1 (Power)"; ac.begin(); irac.whirlpool(&ac, @@ -1215,36 +1318,36 @@ TEST(TestIRac, strToModel) { } TEST(TestIRac, boolToString) { - EXPECT_EQ("on", IRac::boolToString(true)); - EXPECT_EQ("off", IRac::boolToString(false)); + EXPECT_EQ("On", IRac::boolToString(true)); + EXPECT_EQ("Off", IRac::boolToString(false)); } TEST(TestIRac, opmodeToString) { - EXPECT_EQ("off", IRac::opmodeToString(stdAc::opmode_t::kOff)); - EXPECT_EQ("auto", IRac::opmodeToString(stdAc::opmode_t::kAuto)); - EXPECT_EQ("cool", IRac::opmodeToString(stdAc::opmode_t::kCool)); - EXPECT_EQ("unknown", IRac::opmodeToString((stdAc::opmode_t)500)); + EXPECT_EQ("Off", IRac::opmodeToString(stdAc::opmode_t::kOff)); + EXPECT_EQ("Auto", IRac::opmodeToString(stdAc::opmode_t::kAuto)); + EXPECT_EQ("Cool", IRac::opmodeToString(stdAc::opmode_t::kCool)); + EXPECT_EQ("UNKNOWN", IRac::opmodeToString((stdAc::opmode_t)500)); } TEST(TestIRac, fanspeedToString) { - EXPECT_EQ("low", IRac::fanspeedToString(stdAc::fanspeed_t::kLow)); - EXPECT_EQ("auto", IRac::fanspeedToString(stdAc::fanspeed_t::kAuto)); - EXPECT_EQ("unknown", IRac::fanspeedToString((stdAc::fanspeed_t)500)); + EXPECT_EQ("Low", IRac::fanspeedToString(stdAc::fanspeed_t::kLow)); + EXPECT_EQ("Auto", IRac::fanspeedToString(stdAc::fanspeed_t::kAuto)); + EXPECT_EQ("UNKNOWN", IRac::fanspeedToString((stdAc::fanspeed_t)500)); } TEST(TestIRac, swingvToString) { - EXPECT_EQ("off", IRac::swingvToString(stdAc::swingv_t::kOff)); - EXPECT_EQ("low", IRac::swingvToString(stdAc::swingv_t::kLow)); - EXPECT_EQ("auto", IRac::swingvToString(stdAc::swingv_t::kAuto)); - EXPECT_EQ("unknown", IRac::swingvToString((stdAc::swingv_t)500)); + EXPECT_EQ("Off", IRac::swingvToString(stdAc::swingv_t::kOff)); + EXPECT_EQ("Low", IRac::swingvToString(stdAc::swingv_t::kLow)); + EXPECT_EQ("Auto", IRac::swingvToString(stdAc::swingv_t::kAuto)); + EXPECT_EQ("UNKNOWN", IRac::swingvToString((stdAc::swingv_t)500)); } TEST(TestIRac, swinghToString) { - EXPECT_EQ("off", IRac::swinghToString(stdAc::swingh_t::kOff)); - EXPECT_EQ("left", IRac::swinghToString(stdAc::swingh_t::kLeft)); - EXPECT_EQ("auto", IRac::swinghToString(stdAc::swingh_t::kAuto)); - EXPECT_EQ("wide", IRac::swinghToString(stdAc::swingh_t::kWide)); - EXPECT_EQ("unknown", IRac::swinghToString((stdAc::swingh_t)500)); + EXPECT_EQ("Off", IRac::swinghToString(stdAc::swingh_t::kOff)); + EXPECT_EQ("Left", IRac::swinghToString(stdAc::swingh_t::kLeft)); + EXPECT_EQ("Auto", IRac::swinghToString(stdAc::swingh_t::kAuto)); + EXPECT_EQ("Wide", IRac::swinghToString(stdAc::swingh_t::kWide)); + EXPECT_EQ("UNKNOWN", IRac::swinghToString((stdAc::swingh_t)500)); } // Check that we keep the previous state info if the message is a special @@ -1324,7 +1427,7 @@ TEST(TestIRac, Issue821) { EXPECT_TRUE(capture.decode(&ac._irsend.capture)); ASSERT_EQ(COOLIX, ac._irsend.capture.decode_type); ASSERT_EQ(kCoolixBits, ac._irsend.capture.bits); - ASSERT_EQ("Power: On, Led: Toggle", + ASSERT_EQ("Power: On, Light: Toggle", IRAcUtils::resultAcToString(&ac._irsend.capture)); EXPECT_EQ( "f38000d50m" diff --git a/lib/IRremoteESP8266-2.6.5/test/IRrecv_test.cpp b/lib/IRremoteESP8266-2.7.0/test/IRrecv_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/IRrecv_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/IRrecv_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/IRrecv_test.h b/lib/IRremoteESP8266-2.7.0/test/IRrecv_test.h old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/IRrecv_test.h rename to lib/IRremoteESP8266-2.7.0/test/IRrecv_test.h diff --git a/lib/IRremoteESP8266-2.6.5/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.7.0/test/IRsend_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/IRsend_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/IRsend_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/IRsend_test.h b/lib/IRremoteESP8266-2.7.0/test/IRsend_test.h old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/IRsend_test.h rename to lib/IRremoteESP8266-2.7.0/test/IRsend_test.h diff --git a/lib/IRremoteESP8266-2.6.5/test/IRutils_test.cpp b/lib/IRremoteESP8266-2.7.0/test/IRutils_test.cpp old mode 100755 new mode 100644 similarity index 77% rename from lib/IRremoteESP8266-2.6.5/test/IRutils_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/IRutils_test.cpp index 366deba32..b079893cd --- a/lib/IRremoteESP8266-2.6.5/test/IRutils_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/IRutils_test.cpp @@ -308,8 +308,8 @@ TEST(TestResultToHumanReadableBasic, SimpleCodes) { ASSERT_EQ(NEC, irsend.capture.decode_type); ASSERT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ( - "Encoding : NEC\n" - "Code : 8F704FB (32 bits)\n", + "Protocol : NEC\n" + "Code : 0x8F704FB (32 Bits)\n", resultToHumanReadableBasic(&irsend.capture)); } @@ -328,8 +328,8 @@ TEST(TestResultToHumanReadableBasic, ComplexCodes) { ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); ASSERT_EQ(kToshibaACBits, irsend.capture.bits); EXPECT_EQ( - "Encoding : TOSHIBA_AC\n" - "Code : F20D03FC0100000001 (72 bits)\n", + "Protocol : TOSHIBA_AC\n" + "Code : 0xF20D03FC0100000001 (72 Bits)\n", resultToHumanReadableBasic(&irsend.capture)); } @@ -540,3 +540,182 @@ TEST(TestUtils, BCD) { EXPECT_EQ(255, irutils::bcdToUint8(0x9A)); EXPECT_EQ(255, irutils::uint8ToBcd(100)); } + +TEST(TestUtils, getBit) { + // uint8_t method. + EXPECT_FALSE(irutils::getBit((uint8_t)0, 0)); + EXPECT_TRUE(irutils::getBit((uint8_t)1, 0)); + EXPECT_FALSE(irutils::getBit((uint8_t)0b01, 1)); + EXPECT_TRUE(irutils::getBit((uint8_t)0b10, 1)); + EXPECT_FALSE(irutils::getBit((uint8_t)0b01111111, 7)); + EXPECT_TRUE(irutils::getBit((uint8_t)0b10000000, 7)); + // 8-bit macro method + EXPECT_FALSE(GETBIT8((uint8_t)0, 0)); + EXPECT_TRUE(GETBIT8((uint8_t)1, 0)); + EXPECT_FALSE(GETBIT8((uint8_t)0b01, 1)); + EXPECT_TRUE(GETBIT8((uint8_t)0b10, 1)); + EXPECT_FALSE(GETBIT8((uint8_t)0b01111111, 7)); + EXPECT_TRUE(GETBIT8((uint8_t)0b10000000, 7)); + // uint64_t method. + EXPECT_FALSE(irutils::getBit((uint64_t)0, 0)); + EXPECT_TRUE(irutils::getBit((uint64_t)1, 0)); + EXPECT_FALSE(irutils::getBit((uint64_t)0b01, 1)); + EXPECT_TRUE(irutils::getBit((uint64_t)0b10, 1)); + EXPECT_FALSE(irutils::getBit((uint64_t)0b01111111, 7)); + EXPECT_TRUE(irutils::getBit((uint64_t)0b10000000, 7)); +} + +TEST(TestUtils, setBit) { + // uint8_t method. + EXPECT_EQ(0, irutils::setBit((uint8_t)0, 0, false)); + EXPECT_EQ(0, irutils::setBit((uint8_t)1, 0, false)); + EXPECT_EQ(1, irutils::setBit((uint8_t)0, 0, true)); + EXPECT_EQ(1, irutils::setBit((uint8_t)1, 0, true)); + EXPECT_EQ(0b101, irutils::setBit((uint8_t)0b101, 1, false)); + EXPECT_EQ(0b100, irutils::setBit((uint8_t)0b110, 1, false)); + EXPECT_EQ(0b111, irutils::setBit((uint8_t)0b101, 1, true)); + EXPECT_EQ(0b110, irutils::setBit((uint8_t)0b110, 1, true)); + EXPECT_EQ(0b11111111, irutils::setBit((uint8_t)0b01111111, 7, true)); + EXPECT_EQ(0, irutils::setBit((uint8_t)0b10000000, 7, false)); + // uint64_t method. + EXPECT_EQ(0, irutils::setBit((uint64_t)0, 0, false)); + EXPECT_EQ(0, irutils::setBit((uint64_t)1, 0, false)); + EXPECT_EQ(1, irutils::setBit((uint64_t)0, 0, true)); + EXPECT_EQ(1, irutils::setBit((uint64_t)1, 0, true)); + EXPECT_EQ(0b101, irutils::setBit((uint64_t)0b101, 1, false)); + EXPECT_EQ(0b100, irutils::setBit((uint64_t)0b110, 1, false)); + EXPECT_EQ(0b111, irutils::setBit((uint64_t)0b101, 1, true)); + EXPECT_EQ(0b110, irutils::setBit((uint64_t)0b110, 1, true)); + EXPECT_EQ(0b11111111, irutils::setBit((uint64_t)0b01111111, 7, true)); + EXPECT_EQ(0, irutils::setBit((uint64_t)0b10000000, 7, false)); + // uint8_t Pointer method. + uint8_t data = 0; + irutils::setBit(&data, 0, false); + EXPECT_EQ(0, data); + data = 1; + irutils::setBit(&data, 0, false); + ASSERT_EQ(0, data); + irutils::setBit(&data, 0, true); + ASSERT_EQ(1, data); + irutils::setBit(&data, 0, true); + ASSERT_EQ(1, data); + // uint64_t Pointer method. + uint64_t data64 = 0; + irutils::setBit(&data64, 38, true); + ASSERT_EQ(1ULL << 38, data64); + irutils::setBit(&data64, 38, true); + ASSERT_EQ(1ULL << 38, data64); +} + +TEST(TestUtils, setBits8Bit) { + uint8_t data = 0b00000001; + // Trivial/corner cases. + irutils::setBits(&data, 0, 0, 0); + EXPECT_EQ(1, data); + irutils::setBits(&data, 0, 0, 17); + EXPECT_EQ(1, data); + irutils::setBits(&data, 22, 0, 22); + EXPECT_EQ(1, data); + irutils::setBits(&data, 8, 23, 3); + EXPECT_EQ(1, data); + irutils::setBits(&data, 8, 0, 3); + EXPECT_EQ(1, data); + // Single bit. + irutils::setBits(&data, 0, 1, 0); + EXPECT_EQ(0, data); + irutils::setBits(&data, 0, 1, 1); + EXPECT_EQ(0b1, data); + irutils::setBits(&data, 1, 1, 0); + EXPECT_EQ(0b1, data); + irutils::setBits(&data, 1, 1, 1); + EXPECT_EQ(0b11, data); + irutils::setBits(&data, 1, 1, 0); + EXPECT_EQ(0b1, data); + irutils::setBits(&data, 2, 1, 1); + EXPECT_EQ(0b101, data); + irutils::setBits(&data, 7, 1, 1); + EXPECT_EQ(0b10000101, data); + // Larger value than bits desired to be set. + irutils::setBits(&data, 5, 1, 255); + EXPECT_EQ(0b10100101, data); + // Set multiple bits + data = 0; + irutils::setBits(&data, 0, 8, 255); + EXPECT_EQ(0b11111111, data); + irutils::setBits(&data, 0, 8, 0); + EXPECT_EQ(0, data); + irutils::setBits(&data, 0, 4, 0xF); + EXPECT_EQ(0xF, data); + irutils::setBits(&data, 4, 4, 0xF); + EXPECT_EQ(0xFF, data); + irutils::setBits(&data, 4, 4, 0x3); + EXPECT_EQ(0x3F, data); + irutils::setBits(&data, 3, 4, 0x3); + EXPECT_EQ(0x1F, data); + irutils::setBits(&data, 1, 4, 0x3); + EXPECT_EQ(0b00000111, data); + irutils::setBits(&data, 1, 4, 0b1001); + EXPECT_EQ(0b00010011, data); + // Partial overrun. + irutils::setBits(&data, 6, 4, 0b1001); + EXPECT_EQ(0b01010011, data); + irutils::setBits(&data, 7, 4, 0b1001); + EXPECT_EQ(0b11010011, data); +} + +TEST(TestUtils, setBits64Bit) { + uint64_t data = 1; + // Trivial/corner cases. + irutils::setBits(&data, 0, 0, 0); + EXPECT_EQ(1, data); + irutils::setBits(&data, 0, 0, 17); + EXPECT_EQ(1, data); + irutils::setBits(&data, 100, 0, 22); + EXPECT_EQ(1, data); + irutils::setBits(&data, 64, 23, 3); + EXPECT_EQ(1, data); + irutils::setBits(&data, 64, 0, 3); + EXPECT_EQ(1, data); + // Single bit. + irutils::setBits(&data, 0, 1, 0); + EXPECT_EQ(0, data); + irutils::setBits(&data, 0, 1, 1); + EXPECT_EQ(0b1, data); + irutils::setBits(&data, 1, 1, 0); + EXPECT_EQ(0b1, data); + irutils::setBits(&data, 1, 1, 1); + EXPECT_EQ(0b11, data); + irutils::setBits(&data, 1, 1, 0); + EXPECT_EQ(0b1, data); + irutils::setBits(&data, 2, 1, 1); + EXPECT_EQ(0b101, data); + irutils::setBits(&data, 7, 1, 1); + EXPECT_EQ(0b10000101, data); + // Larger value than bits desired to be set. + irutils::setBits(&data, 5, 1, 255); + EXPECT_EQ(0b10100101, data); + // Set multiple bits + data = 0; + irutils::setBits(&data, 0, 8, 255); + EXPECT_EQ(0b11111111, data); + irutils::setBits(&data, 0, 8, 0); + EXPECT_EQ(0, data); + irutils::setBits(&data, 0, 4, 0xF); + EXPECT_EQ(0xF, data); + irutils::setBits(&data, 4, 4, 0xF); + EXPECT_EQ(0xFF, data); + irutils::setBits(&data, 4, 4, 0x3); + EXPECT_EQ(0x3F, data); + irutils::setBits(&data, 3, 4, 0x3); + EXPECT_EQ(0x1F, data); + irutils::setBits(&data, 1, 4, 0x3); + EXPECT_EQ(0b00000111, data); + irutils::setBits(&data, 1, 4, 0b1001); + EXPECT_EQ(0b00010011, data); + // Partial overrun. + irutils::setBits(&data, 62, 4, 0b1001); + EXPECT_EQ(0x4000000000000013, data); + // General + irutils::setBits(&data, 32, 4, 0b1001); + EXPECT_EQ(0x4000000900000013, data); +} diff --git a/lib/IRremoteESP8266-2.6.5/test/Makefile b/lib/IRremoteESP8266-2.7.0/test/Makefile old mode 100755 new mode 100644 similarity index 96% rename from lib/IRremoteESP8266-2.6.5/test/Makefile rename to lib/IRremoteESP8266-2.7.0/test/Makefile index 0e721d58c..0235042f7 --- a/lib/IRremoteESP8266-2.6.5/test/Makefile +++ b/lib/IRremoteESP8266-2.7.0/test/Makefile @@ -21,7 +21,7 @@ INCLUDES = -I$(USER_DIR) -I. # Flags passed to the preprocessor. # Set Google Test's header directory as a system directory, such that # the compiler doesn't generate warnings in Google Test headers. -CPPFLAGS += -isystem $(GTEST_DIR)/include -DUNIT_TEST +CPPFLAGS += -isystem $(GTEST_DIR)/include -DUNIT_TEST -D_IR_LOCALE_=en-AU # Flags passed to the C++ compiler. CXXFLAGS += -g -Wall -Wextra -pthread -std=gnu++11 @@ -95,6 +95,7 @@ PROTOCOLS_H = $(USER_DIR)/ir_Amcor.h \ $(USER_DIR)/ir_Coolix.h \ $(USER_DIR)/ir_Electra.h \ $(USER_DIR)/ir_Haier.h \ + $(USER_DIR)/ir_Hitachi.h \ $(USER_DIR)/ir_Midea.h \ $(USER_DIR)/ir_Toshiba.h \ $(USER_DIR)/ir_Daikin.h \ @@ -117,11 +118,12 @@ PROTOCOLS_H = $(USER_DIR)/ir_Amcor.h \ $(USER_DIR)/ir_Trotec.h # Common object files COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o IRac.o ir_GlobalCache.o \ - $(PROTOCOLS) gtest_main.a + IRtext.o $(PROTOCOLS) gtest_main.a # Common dependencies COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \ $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h \ - $(USER_DIR)/IRac.h $(PROTOCOLS_H) + $(USER_DIR)/IRac.h $(USER_DIR)/i18n.h $(USER_DIR)/IRtext.h \ + $(PROTOCOLS_H) # Common test dependencies COMMON_TEST_DEPS = $(COMMON_DEPS) IRrecv_test.h IRsend_test.h @@ -148,8 +150,11 @@ gtest_main.a : gtest-all.o gtest_main.o # gtest_main.a, depending on whether it defines its own main() # function. -IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRutils.cpp +IRtext.o : $(USER_DIR)/IRtext.cpp $(USER_DIR)/IRtext.h $(USER_DIR)/IRremoteESP8266.h $(USER_DIR)/i18n.h $(USER_DIR)/locale/*.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/IRtext.cpp + +IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h $(USER_DIR)/i18n.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/IRutils.cpp IRutils_test.o : IRutils_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c IRutils_test.cpp @@ -421,7 +426,7 @@ ir_Toshiba_test.o : ir_Toshiba_test.cpp $(USER_DIR)/ir_Toshiba.h $(COMMON_TEST_D ir_Toshiba_test : $(COMMON_OBJ) ir_Toshiba_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ -ir_Midea.o : $(USER_DIR)/ir_Midea.cpp $(GTEST_HEADERS) +ir_Midea.o : $(USER_DIR)/ir_Midea.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Midea.cpp ir_Midea_test.o : ir_Midea_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) @@ -430,7 +435,7 @@ ir_Midea_test.o : ir_Midea_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) ir_Midea_test : $(COMMON_OBJ) ir_Midea_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ -ir_Magiquest.o : $(USER_DIR)/ir_Magiquest.cpp $(GTEST_HEADERS) +ir_Magiquest.o : $(USER_DIR)/ir_Magiquest.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Magiquest.cpp ir_Magiquest_test.o : ir_Magiquest_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) @@ -466,7 +471,7 @@ ir_Haier_test.o : ir_Haier_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) ir_Haier_test : $(COMMON_OBJ) ir_Haier_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ -ir_Hitachi.o : $(USER_DIR)/ir_Hitachi.cpp $(COMMON_DEPS) $(GTEST_HEADERS) +ir_Hitachi.o : $(USER_DIR)/ir_Hitachi.cpp $(USER_DIR)/ir_Hitachi.h $(COMMON_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Hitachi.cpp ir_Hitachi_test.o : ir_Hitachi_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Aiwa_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Aiwa_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Aiwa_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Aiwa_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Amcor_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Amcor_test.cpp old mode 100755 new mode 100644 similarity index 98% rename from lib/IRremoteESP8266-2.6.5/test/ir_Amcor_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Amcor_test.cpp index 265c61500..787769516 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Amcor_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Amcor_test.cpp @@ -69,7 +69,7 @@ TEST(TestDecodeAmcor, SyntheticSelfDecode) { EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Fan: 4 (Auto), Temp: 24C, Max: Off", + "Power: On, Mode: 1 (Cool), Fan: 4 (Auto), Temp: 24C, Max: Off", ac.toString()); } @@ -343,9 +343,9 @@ TEST(TestAmcorAcClass, Max) { uint8_t hi[kAmcorStateLength] = { 0x01, 0x12, 0x40, 0x00, 0x00, 0x30, 0x03, 0x0E}; ac.setRaw(lo); - EXPECT_EQ("Power: On, Mode: 1 (COOL), Fan: 4 (Auto), Temp: 12C, Max: On", + EXPECT_EQ("Power: On, Mode: 1 (Cool), Fan: 4 (Auto), Temp: 12C, Max: On", ac.toString()); ac.setRaw(hi); - EXPECT_EQ("Power: On, Mode: 2 (HEAT), Fan: 1 (Low), Temp: 32C, Max: On", + EXPECT_EQ("Power: On, Mode: 2 (Heat), Fan: 1 (Low), Temp: 32C, Max: On", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Argo_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Argo_test.cpp old mode 100755 new mode 100644 similarity index 95% rename from lib/IRremoteESP8266-2.6.5/test/ir_Argo_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Argo_test.cpp index 7932416e0..d5a5d17ad --- a/lib/IRremoteESP8266-2.6.5/test/ir_Argo_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Argo_test.cpp @@ -53,8 +53,8 @@ TEST(TestArgoACClass, MessageConstructon) { 0xAC, 0xF5, 0x00, 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xD6, 0x01}; EXPECT_STATE_EQ(expected, ac.getRaw(), kArgoBits); EXPECT_EQ( - "Power: On, Mode: 0 (COOL), Fan: 0 (AUTO), Temp: 20C, Room Temp: 21C, " - "Max: On, iFeel: On, Night: On", + "Power: On, Mode: 0 (Cool), Fan: 0 (Auto), Temp: 20C, Room Temp: 21C, " + "Max: On, IFeel: On, Night: On", ac.toString()); } @@ -128,12 +128,12 @@ TEST(TestArgoACClass, SetAndGetRoomTemp) { ac.setRoomTemp(25); EXPECT_EQ(25, ac.getRoomTemp()); - ac.setRoomTemp(kArgoTempOffset); - EXPECT_EQ(kArgoTempOffset, ac.getRoomTemp()); + ac.setRoomTemp(kArgoTempDelta); + EXPECT_EQ(kArgoTempDelta, ac.getRoomTemp()); ac.setRoomTemp(kArgoMaxRoomTemp); EXPECT_EQ(kArgoMaxRoomTemp, ac.getRoomTemp()); - ac.setRoomTemp(kArgoTempOffset - 1); - EXPECT_EQ(kArgoTempOffset, ac.getRoomTemp()); + ac.setRoomTemp(kArgoTempDelta - 1); + EXPECT_EQ(kArgoTempDelta, ac.getRoomTemp()); ac.setRoomTemp(kArgoMaxRoomTemp + 1); EXPECT_EQ(kArgoMaxRoomTemp, ac.getRoomTemp()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Carrier_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Carrier_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Carrier_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Carrier_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Coolix_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Coolix_test.cpp old mode 100755 new mode 100644 similarity index 96% rename from lib/IRremoteESP8266-2.6.5/test/ir_Coolix_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Coolix_test.cpp index 618d825a0..2a3367765 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Coolix_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Coolix_test.cpp @@ -352,12 +352,11 @@ TEST(TestDecodeCoolix, FailToDecodeNonCoolixExample) { } // Tests for the IRCoolixAC class. - TEST(TestCoolixACClass, SetAndGetRaw) { IRCoolixAC ircoolix(0); - ircoolix.setRaw(kCoolixOff); - EXPECT_EQ(kCoolixOff, ircoolix.getRaw()); + ircoolix.setRaw(0xB21F28); + EXPECT_EQ(0xB21F28, ircoolix.getRaw()); ircoolix.setRaw(kCoolixDefaultState); EXPECT_EQ(kCoolixDefaultState, ircoolix.getRaw()); } @@ -480,19 +479,20 @@ TEST(TestCoolixACClass, SpecialModesAndReset) { TEST(TestCoolixACClass, HumanReadable) { IRCoolixAC ircoolix(0); + ircoolix.begin(); + ircoolix.setPower(true); // Initial starting point. EXPECT_EQ( - "Power: On, Mode: 2 (AUTO), Fan: 5 (AUTO), Temp: 25C, " - "Zone Follow: Off, Sensor Temp: Ignored", + "Power: On, Mode: 2 (Auto), Fan: 0 (Auto0), Temp: 25C, " + "Zone Follow: Off, Sensor Temp: Off", ircoolix.toString()); - ircoolix.setSensorTemp(24); ircoolix.setTemp(22); ircoolix.setMode(kCoolixCool); ircoolix.setFan(kCoolixFanMin); EXPECT_EQ( - "Power: On, Mode: 0 (COOL), Fan: 4 (MIN), Temp: 22C, " + "Power: On, Mode: 0 (Cool), Fan: 4 (Min), Temp: 22C, " "Zone Follow: On, Sensor Temp: 24C", ircoolix.toString()); ircoolix.setSwing(); @@ -503,26 +503,28 @@ TEST(TestCoolixACClass, HumanReadable) { TEST(TestCoolixACClass, KnownExamples) { IRCoolixAC ircoolix(0); - + ircoolix.begin(); + ircoolix.setPower(true); ircoolix.setRaw(0b101100101011111111100100); EXPECT_EQ( - "Power: On, Mode: 4 (FAN), Fan: 5 (AUTO), Zone Follow: Off, " - "Sensor Temp: Ignored", + "Power: On, Mode: 4 (Fan), Fan: 5 (Auto), Zone Follow: Off, " + "Sensor Temp: Off", ircoolix.toString()); ircoolix.setRaw(0b101100101001111100000000); EXPECT_EQ( - "Power: On, Mode: 0 (COOL), Fan: 4 (MIN), Temp: 17C, " - "Zone Follow: Off, Sensor Temp: Ignored", + "Power: On, Mode: 0 (Cool), Fan: 4 (Min), Temp: 17C, " + "Zone Follow: Off, Sensor Temp: Off", ircoolix.toString()); } TEST(TestCoolixACClass, Issue579FanAuto0) { IRCoolixAC ircoolix(0); - + ircoolix.begin(); + ircoolix.setPower(true); ircoolix.setRaw(0xB21F28); EXPECT_EQ( - "Power: On, Mode: 2 (AUTO), Fan: 0 (AUTO0), Temp: 20C, " - "Zone Follow: Off, Sensor Temp: Ignored", + "Power: On, Mode: 2 (Auto), Fan: 0 (Auto0), Temp: 20C, " + "Zone Follow: Off, Sensor Temp: Off", ircoolix.toString()); } @@ -570,20 +572,20 @@ TEST(TestCoolixACClass, RealCaptureExample) { TEST(TestCoolixACClass, Issue624HandleSpecialStatesBetter) { IRCoolixAC ac(0); ac.begin(); + ac.setPower(true); // Default EXPECT_EQ( - "Power: On, Mode: 2 (AUTO), Fan: 5 (AUTO), Temp: 25C, Zone Follow: Off, " - "Sensor Temp: Ignored", + "Power: On, Mode: 2 (Auto), Fan: 0 (Auto0), Temp: 25C, Zone Follow: Off, " + "Sensor Temp: Off", ac.toString()); - EXPECT_EQ(0xB2BFC8, ac.getRaw()); + EXPECT_EQ(0xB21FC8, ac.getRaw()); // Change of settings. - ac.setPower(true); ac.setTemp(24); ac.setMode(kCoolixCool); ac.setFan(kCoolixFanAuto); EXPECT_EQ( - "Power: On, Mode: 0 (COOL), Fan: 5 (AUTO), Temp: 24C, Zone Follow: Off, " - "Sensor Temp: Ignored", + "Power: On, Mode: 0 (Cool), Fan: 5 (Auto), Temp: 24C, Zone Follow: Off, " + "Sensor Temp: Off", ac.toString()); EXPECT_EQ(0xB2BF40, ac.getRaw()); // Turn the unit off. @@ -598,27 +600,25 @@ TEST(TestCoolixACClass, Issue624HandleSpecialStatesBetter) { ac.setMode(kCoolixCool); ac.setFan(kCoolixFanAuto); EXPECT_EQ( - "Power: On, Mode: 0 (COOL), Fan: 5 (AUTO), Temp: 24C, Zone Follow: Off, " - "Sensor Temp: Ignored", + "Power: On, Mode: 0 (Cool), Fan: 5 (Auto), Temp: 24C, Zone Follow: Off, " + "Sensor Temp: Off", ac.toString()); EXPECT_EQ(0xB2BF40, ac.getRaw()); - // Now test if we setRaw() a special state first. - ac.setRaw(kCoolixSwing); // Repeat change of settings. - ac.setPower(true); ac.setTemp(24); ac.setMode(kCoolixCool); ac.setFan(kCoolixFanAuto); EXPECT_EQ( - "Power: On, Mode: 0 (COOL), Fan: 5 (AUTO), Temp: 24C, Zone Follow: Off, " - "Sensor Temp: Ignored", + "Power: On, Mode: 0 (Cool), Fan: 5 (Auto), Temp: 24C, Zone Follow: Off, " + "Sensor Temp: Off", ac.toString()); EXPECT_EQ(0xB2BF40, ac.getRaw()); } TEST(TestCoolixACClass, toCommon) { IRCoolixAC ac(0); + ac.begin(); ac.setPower(true); ac.setMode(kCoolixCool); ac.setTemp(20); @@ -666,6 +666,7 @@ TEST(TestCoolixACClass, Issue722) { // ON Auto Temp 18C uint32_t on_auto_18c_fan_auto0 = 0xB21F18; + ac.on(); ac.setTemp(18); EXPECT_EQ(on_auto_18c_fan_auto0, ac.getRaw()); diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Daikin_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Daikin_test.cpp old mode 100755 new mode 100644 similarity index 85% rename from lib/IRremoteESP8266-2.6.5/test/ir_Daikin_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Daikin_test.cpp index 774109c3a..9fcaabcb0 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Daikin_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Daikin_test.cpp @@ -691,11 +691,11 @@ TEST(TestDaikinClass, HumanReadable) { IRDaikinESP ac(0); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 15C, Fan: 11 (Quiet), " - "Powerful: Off, Quiet: Off, Sensor: Off, Mold: Off, " - "Comfort: Off, Swing (Horizontal): Off, Swing (Vertical): Off, " - "Current Time: 00:00, Current Day: (UNKNOWN), On Time: Off, " - "Off Time: Off, Weekly Timer: On", + "Power: On, Mode: 4 (Heat), Temp: 15C, Fan: 11 (Quiet), " + "Powerful: Off, Quiet: Off, Sensor: Off, Mould: Off, " + "Comfort: Off, Swing(H): Off, Swing(V): Off, " + "Clock: 00:00, Day: 0 (UNKNOWN), On Timer: Off, " + "Off Timer: Off, Weekly Timer: On", ac.toString()); ac.setMode(kDaikinAuto); ac.setTemp(25); @@ -713,10 +713,10 @@ TEST(TestDaikinClass, HumanReadable) { ac.setWeeklyTimerEnable(false); ac.off(); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 10 (Auto), " - "Powerful: Off, Quiet: On, Sensor: On, Mold: On, Comfort: On, " - "Swing (Horizontal): On, Swing (Vertical): On, " - "Current Time: 09:15, Current Day: WED, On Time: 08:00, Off Time: 17:30, " + "Power: Off, Mode: 0 (Auto), Temp: 25C, Fan: 10 (Auto), " + "Powerful: Off, Quiet: On, Sensor: On, Mould: On, Comfort: On, " + "Swing(H): On, Swing(V): On, " + "Clock: 09:15, Day: 4 (Wed), On Timer: 08:00, Off Timer: 17:30, " "Weekly Timer: Off", ac.toString()); } @@ -866,11 +866,11 @@ TEST(TestDecodeDaikin, RealExample) { EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (Auto), Powerful: On, " - "Quiet: Off, Sensor: Off, Mold: Off, Comfort: Off, " - "Swing (Horizontal): Off, Swing (Vertical): Off, " - "Current Time: 22:18, Current Day: (UNKNOWN), " - "On Time: 21:30, Off Time: 06:10, Weekly Timer: On", ac.toString()); + "Power: On, Mode: 3 (Cool), Temp: 29C, Fan: 10 (Auto), Powerful: On, " + "Quiet: Off, Sensor: Off, Mould: Off, Comfort: Off, " + "Swing(H): Off, Swing(V): Off, " + "Clock: 22:18, Day: 0 (UNKNOWN), " + "On Timer: 21:30, Off Timer: 06:10, Weekly Timer: On", ac.toString()); } // Decoding a message we entirely constructed based solely on a given state. @@ -899,11 +899,11 @@ TEST(TestDecodeDaikin, ShortSyntheticExample) { EXPECT_STATE_EQ(longState, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (Auto), Powerful: On, " - "Quiet: Off, Sensor: Off, Mold: Off, Comfort: Off, " - "Swing (Horizontal): Off, Swing (Vertical): Off, " - "Current Time: 22:18, Current Day: (UNKNOWN), " - "On Time: 21:30, Off Time: 06:10, Weekly Timer: On", ac.toString()); + "Power: On, Mode: 3 (Cool), Temp: 29C, Fan: 10 (Auto), Powerful: On, " + "Quiet: Off, Sensor: Off, Mould: Off, Comfort: Off, " + "Swing(H): Off, Swing(V): Off, " + "Clock: 22:18, Day: 0 (UNKNOWN), " + "On Timer: 21:30, Off Timer: 06:10, Weekly Timer: On", ac.toString()); } // Decoding a message we entirely constructed based solely on a given state. @@ -928,11 +928,11 @@ TEST(TestDecodeDaikin, LongSyntheticExample) { EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (Auto), Powerful: On, " - "Quiet: Off, Sensor: Off, Mold: Off, Comfort: Off, " - "Swing (Horizontal): Off, Swing (Vertical): Off, " - "Current Time: 22:18, Current Day: (UNKNOWN), " - "On Time: 21:30, Off Time: 06:10, Weekly Timer: On", ac.toString()); + "Power: On, Mode: 3 (Cool), Temp: 29C, Fan: 10 (Auto), Powerful: On, " + "Quiet: Off, Sensor: Off, Mould: Off, Comfort: Off, " + "Swing(H): Off, Swing(V): Off, " + "Clock: 22:18, Day: 0 (UNKNOWN), " + "On Timer: 21:30, Off Timer: 06:10, Weekly Timer: On", ac.toString()); } // Test decoding a message captured from a real IR remote. @@ -1032,10 +1032,10 @@ TEST(TestDecodeDaikin2, SyntheticExample) { EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), " - "Swing (V): 5, Swing (H): 190 (Auto), " - "Clock: 14:50, On Time: Off, Off Time: Off, Sleep Time: Off, " - "Beep: 1 (Quiet), Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, " + "Power: Off, Mode: 0 (Auto), Temp: 19C, Fan: 10 (Auto), " + "Swing(V): 5 (Low), Swing(H): 190 (Auto), " + "Clock: 14:50, On Timer: Off, Off Timer: Off, Sleep Timer: Off, " + "Beep: 1 (Quiet), Light: 3 (Off), Mould: On, Clean: On, Fresh: Off, " "Eye: Off, Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: Off, " "Econo: Off", ac.toString()); @@ -1348,11 +1348,13 @@ TEST(TestDaikin2Class, Swing) { ASSERT_EQ(kDaikin2SwingVBreeze, ac.getSwingVertical()); ac.setSwingVertical(kDaikin2SwingVCirculate); ASSERT_EQ(kDaikin2SwingVCirculate, ac.getSwingVertical()); + ac.setSwingVertical(kDaikin2SwingVSwing); + ASSERT_EQ(kDaikin2SwingVSwing, ac.getSwingVertical()); ac.setSwingVertical(kDaikin2SwingVAuto); ASSERT_EQ(kDaikin2SwingVAuto, ac.getSwingVertical()); ac.setSwingVertical(0); ASSERT_EQ(kDaikin2SwingVAuto, ac.getSwingVertical()); - ac.setSwingVertical(7); + ac.setSwingVertical(20); ASSERT_EQ(kDaikin2SwingVAuto, ac.getSwingVertical()); ac.setSwingVertical(255); ASSERT_EQ(kDaikin2SwingVAuto, ac.getSwingVertical()); @@ -1442,10 +1444,10 @@ TEST(TestDaikin2Class, HumanReadable) { ac.setPurify(true); ac.setEcono(false); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 21C, Fan: 5 (High), " - "Swing (V): 14 (Auto), Swing (H): 191 (Swing), Clock: 12:34, " - "On Time: Off, Off Time: 20:00, Sleep Time: 04:00, Beep: 2 (Loud), " - "Light: 2 (Dim), Mold: On, Clean: Off, Fresh Air: On, Eye: On, " + "Power: On, Mode: 3 (Cool), Temp: 21C, Fan: 5 (High), " + "Swing(V): 14 (Auto), Swing(H): 191 (Swing), Clock: 12:34, " + "On Timer: Off, Off Timer: 20:00, Sleep Timer: 04:00, Beep: 2 (Loud), " + "Light: 2 (Low), Mould: On, Clean: Off, Fresh: On, Eye: On, " "Eye Auto: On, Quiet: Off, Powerful: On, Purify: On, Econo: Off", ac.toString()); ac.setQuiet(true); @@ -1457,10 +1459,10 @@ TEST(TestDaikin2Class, HumanReadable) { ac.setCurrentTime(23 * 60 + 45); // 23:45 ac.enableOnTimer(9 * 60 + 11); // 9:11 EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 32C, Fan: 1 (Low), " - "Swing (V): 14 (Auto), Swing (H): 191 (Swing), Clock: 23:45, " - "On Time: 09:11, Off Time: 20:00, Sleep Time: Off, Beep: 1 (Quiet), " - "Light: 1 (Bright), Mold: On, Clean: Off, Fresh Air: On, Eye: On, " + "Power: On, Mode: 4 (Heat), Temp: 32C, Fan: 1 (Low), " + "Swing(V): 14 (Auto), Swing(H): 191 (Swing), Clock: 23:45, " + "On Timer: 09:11, Off Timer: 20:00, Sleep Timer: Off, Beep: 1 (Quiet), " + "Light: 1 (High), Mould: On, Clean: Off, Fresh: On, Eye: On, " "Eye Auto: On, Quiet: On, Powerful: Off, Purify: On, Econo: Off", ac.toString()); } @@ -1498,10 +1500,10 @@ TEST(TestDaikin2Class, KnownConstruction) { ac.setPurify(false); ac.setEcono(false); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), " - "Swing (V): 5, Swing (H): 190 (Auto), " - "Clock: 14:50, On Time: Off, Off Time: Off, Sleep Time: Off, " - "Beep: 1 (Quiet), Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, " + "Power: Off, Mode: 0 (Auto), Temp: 19C, Fan: 10 (Auto), " + "Swing(V): 5 (Low), Swing(H): 190 (Auto), " + "Clock: 14:50, On Timer: Off, Off Timer: Off, Sleep Timer: Off, " + "Beep: 1 (Quiet), Light: 3 (Off), Mould: On, Clean: On, Fresh: Off, " "Eye: Off, Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: Off, " "Econo: Off", ac.toString()); @@ -1522,7 +1524,7 @@ TEST(TestUtils, Housekeeping) { ASSERT_EQ("DAIKIN152", typeToString(decode_type_t::DAIKIN152)); ASSERT_EQ(decode_type_t::DAIKIN152, strToDecodeType("DAIKIN152")); ASSERT_TRUE(hasACState(decode_type_t::DAIKIN152)); - ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::DAIKIN152)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::DAIKIN152)); ASSERT_EQ("DAIKIN160", typeToString(decode_type_t::DAIKIN160)); ASSERT_EQ(decode_type_t::DAIKIN160, strToDecodeType("DAIKIN160")); @@ -1560,10 +1562,10 @@ TEST(TestDecodeDaikin2, Issue582DeepDecodeExample) { ASSERT_TRUE(ac.getEye()); ASSERT_TRUE(ac.getPurify()); EXPECT_EQ( - "Power: On, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), " - "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 09:20, " - "On Time: Off, Off Time: Off, Sleep Time: Off, Beep: 3 (Off), " - "Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, Eye: On, " + "Power: On, Mode: 0 (Auto), Temp: 19C, Fan: 10 (Auto), " + "Swing(V): 14 (Auto), Swing(H): 190 (Auto), Clock: 09:20, " + "On Timer: Off, Off Timer: Off, Sleep Timer: Off, Beep: 3 (Off), " + "Light: 3 (Off), Mould: On, Clean: On, Fresh: Off, Eye: On, " "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off", ac.toString()); } @@ -1585,19 +1587,19 @@ TEST(TestDecodeDaikin2, Issue582PowerfulEconoFix) { ac.setRaw(PowerfulOn); ASSERT_TRUE(ac.getPowerful()); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 10 (Auto), " - "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 13:46, " - "On Time: Off, Off Time: Off, Sleep Time: Off, Beep: 3 (Off), " - "Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, Eye: Off, " + "Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 10 (Auto), " + "Swing(V): 14 (Auto), Swing(H): 190 (Auto), Clock: 13:46, " + "On Timer: Off, Off Timer: Off, Sleep Timer: Off, Beep: 3 (Off), " + "Light: 3 (Off), Mould: On, Clean: On, Fresh: Off, Eye: Off, " "Eye Auto: Off, Quiet: Off, Powerful: On, Purify: On, Econo: Off", ac.toString()); ac.setRaw(PowerfulOff); ASSERT_FALSE(ac.getPowerful()); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 10 (Auto), " - "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 13:46, " - "On Time: Off, Off Time: Off, Sleep Time: Off, Beep: 3 (Off), " - "Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, Eye: Off, " + "Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 10 (Auto), " + "Swing(V): 14 (Auto), Swing(H): 190 (Auto), Clock: 13:46, " + "On Timer: Off, Off Timer: Off, Sleep Timer: Off, Beep: 3 (Off), " + "Light: 3 (Off), Mould: On, Clean: On, Fresh: Off, Eye: Off, " "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off", ac.toString()); @@ -1614,19 +1616,19 @@ TEST(TestDecodeDaikin2, Issue582PowerfulEconoFix) { ac.setRaw(EconoOn); ASSERT_TRUE(ac.getEcono()); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 10 (Auto), " - "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 13:47, " - "On Time: Off, Off Time: Off, Sleep Time: Off, Beep: 3 (Off), " - "Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, Eye: Off, " + "Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 10 (Auto), " + "Swing(V): 14 (Auto), Swing(H): 190 (Auto), Clock: 13:47, " + "On Timer: Off, Off Timer: Off, Sleep Timer: Off, Beep: 3 (Off), " + "Light: 3 (Off), Mould: On, Clean: On, Fresh: Off, Eye: Off, " "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: On", ac.toString()); ac.setRaw(EconoOff); ASSERT_FALSE(ac.getEcono()); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 10 (Auto), " - "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 13:47, " - "On Time: Off, Off Time: Off, Sleep Time: Off, Beep: 3 (Off), " - "Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, Eye: Off, " + "Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 10 (Auto), " + "Swing(V): 14 (Auto), Swing(H): 190 (Auto), Clock: 13:47, " + "On Timer: Off, Off Timer: Off, Sleep Timer: Off, Beep: 3 (Off), " + "Light: 3 (Off), Mould: On, Clean: On, Fresh: Off, Eye: Off, " "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off", ac.toString()); } @@ -1823,8 +1825,8 @@ TEST(TestDaikin216Class, ExampleStates) { 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x53}; ac.setRaw(state); EXPECT_EQ( - "Power: On, Mode: 2 (DRY), Temp: 32C, Fan: 10 (Auto), " - "Swing (Horizontal): Off, Swing (Vertical): Off, " + "Power: On, Mode: 2 (Dry), Temp: 32C, Fan: 10 (Auto), " + "Swing(H): Off, Swing(V): Off, " "Quiet: Off, Powerful: Off", ac.toString()); } @@ -1845,8 +1847,8 @@ TEST(TestDaikin216Class, ReconstructKnownState) { ac.setSwingVertical(false); ac.setQuiet(false); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), " - "Swing (Horizontal): Off, Swing (Vertical): Off, " + "Power: Off, Mode: 0 (Auto), Temp: 19C, Fan: 10 (Auto), " + "Swing(H): Off, Swing(V): Off, " "Quiet: Off, Powerful: Off", ac.toString()); @@ -1909,8 +1911,8 @@ TEST(TestDecodeDaikin216, RealExample) { IRDaikin216 ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), " - "Swing (Horizontal): Off, Swing (Vertical): Off, " + "Power: Off, Mode: 0 (Auto), Temp: 19C, Fan: 10 (Auto), " + "Swing(H): Off, Swing(V): Off, " "Quiet: Off, Powerful: Off", ac.toString()); } @@ -2003,7 +2005,7 @@ TEST(TestDaikin2Class, toCommon) { ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode); ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed); ASSERT_EQ(stdAc::swingv_t::kMiddle, ac.toCommon().swingv); - ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh); + ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh); ASSERT_EQ(6 * 60, ac.toCommon().sleep); // Unsupported. ASSERT_EQ(-1, ac.toCommon().clock); @@ -2088,8 +2090,8 @@ TEST(TestDecodeDaikin160, RealExample) { EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); IRDaikin160 ac(0); ac.setRaw(irsend.capture.state); - EXPECT_EQ("Power: Off, Mode: 3 (COOL), Temp: 25C, Fan: 10 (Auto), " - "Vent Position (V): 1 (Lowest)", ac.toString()); + EXPECT_EQ("Power: Off, Mode: 3 (Cool), Temp: 25C, Fan: 10 (Auto), " + "Swing(V): 1 (Lowest)", ac.toString()); } TEST(TestDecodeDaikin160, SyntheticExample) { @@ -2290,8 +2292,8 @@ TEST(TestDaikin160Class, HumanReadable) { IRDaikin160 ac(0); EXPECT_EQ( - "Power: Off, Mode: 3 (COOL), Temp: 25C, Fan: 10 (Auto), " - "Vent Position (V): 1 (Lowest)", + "Power: Off, Mode: 3 (Cool), Temp: 25C, Fan: 10 (Auto), " + "Swing(V): 1 (Lowest)", ac.toString()); ac.setMode(kDaikinAuto); ac.setTemp(19); @@ -2299,8 +2301,8 @@ TEST(TestDaikin160Class, HumanReadable) { ac.setSwingVertical(kDaikin160SwingVAuto); ac.setPower(true); EXPECT_EQ( - "Power: On, Mode: 0 (AUTO), Temp: 19C, Fan: 1 (Low), " - "Vent Position (V): 15 (Auto)", + "Power: On, Mode: 0 (Auto), Temp: 19C, Fan: 1 (Low), " + "Swing(V): 15 (Auto)", ac.toString()); } @@ -2308,20 +2310,20 @@ TEST(TestDaikin176Class, FanControl) { IRDaikin176 ac(0); EXPECT_EQ( - "Power: Off, Mode: 7 (COOL), Temp: 9C, Fan: 1 (Low), Swing (H): 6 (Off)", + "Power: Off, Mode: 7 (Cool), Temp: 9C, Fan: 1 (Low), Swing(H): 6 (Off)", ac.toString()); ac.setFan(kDaikinFanMin); ac.setPower(true); EXPECT_EQ( - "Power: On, Mode: 7 (COOL), Temp: 9C, Fan: 1 (Low), Swing (H): 6 (Off)", + "Power: On, Mode: 7 (Cool), Temp: 9C, Fan: 1 (Low), Swing(H): 6 (Off)", ac.toString()); ac.setFan(kDaikinFanMin + 1); EXPECT_EQ( - "Power: On, Mode: 7 (COOL), Temp: 9C, Fan: 3 (High), Swing (H): 6 (Off)", + "Power: On, Mode: 7 (Cool), Temp: 9C, Fan: 3 (High), Swing(H): 6 (Off)", ac.toString()); ac.setFan(kDaikin176FanMax); EXPECT_EQ( - "Power: On, Mode: 7 (COOL), Temp: 9C, Fan: 3 (High), Swing (H): 6 (Off)", + "Power: On, Mode: 7 (Cool), Temp: 9C, Fan: 3 (High), Swing(H): 6 (Off)", ac.toString()); // Real state from remote @@ -2332,8 +2334,8 @@ TEST(TestDaikin176Class, FanControl) { 0x00, 0x20, 0x25}; ac.setRaw(state); EXPECT_EQ( - "Power: On, Mode: 7 (COOL), Temp: 26C, Fan: 3 (High), " - "Swing (H): 5 (Auto)", + "Power: On, Mode: 7 (Cool), Temp: 26C, Fan: 3 (High), " + "Swing(H): 5 (Auto)", ac.toString()); } @@ -2358,12 +2360,12 @@ TEST(TestDaikin176Class, SimulateIRacDaikin176) { ac.setFan(ac.convertFan(stdAc::fanspeed_t::kMax)); ac.setSwingHorizontal(kDaikin176SwingHOff); EXPECT_EQ( - "Power: On, Mode: 7 (COOL), Temp: 26C, Fan: 3 (High), Swing (H): 6 (Off)", + "Power: On, Mode: 7 (Cool), Temp: 26C, Fan: 3 (High), Swing(H): 6 (Off)", ac.toString()); ac.setSwingHorizontal(ac.convertSwingH(stdAc::swingh_t::kAuto)); EXPECT_EQ( - "Power: On, Mode: 7 (COOL), Temp: 26C, Fan: 3 (High), " - "Swing (H): 5 (Auto)", + "Power: On, Mode: 7 (Cool), Temp: 26C, Fan: 3 (High), " + "Swing(H): 5 (Auto)", ac.toString()); } @@ -2494,25 +2496,25 @@ TEST(TestDaikin176Class, ReconstructKnownStates) { // Data from: // https://github.com/crankyoldgit/IRremoteESP8266/pull/826#issuecomment-513531138 - // Power: On, Mode: 7 (COOL), Temp: 25C, Fan: 3 (MAX), Swing (H): 5 (Auto) + // Power: On, Mode: 7 (Cool), Temp: 25C, Fan: 3 (Max), Swing(H): 5 (Auto) // 11DA171804001E11DA17180073002100002035002023 uint8_t on_cool_25_max_auto[22] = { 0x11, 0xDA, 0x17, 0x18, 0x04, 0x00, 0x1E, 0x11, 0xDA, 0x17, 0x18, 0x00, 0x73, 0x00, 0x21, 0x00, 0x00, 0x20, 0x35, 0x00, 0x20, 0x23}; - // Power: On, Mode: 6 (FAN), Temp: 17C, Fan: 3 (MAX), Swing (H): 5 (Auto) + // Power: On, Mode: 6 (Fan), Temp: 17C, Fan: 3 (Max), Swing(H): 5 (Auto) // 11DA171804001E11DA171800630401000010350020E7 uint8_t on_fan_17_max_auto[22] = { 0x11, 0xDA, 0x17, 0x18, 0x04, 0x00, 0x1E, 0x11, 0xDA, 0x17, 0x18, 0x00, 0x63, 0x04, 0x01, 0x00, 0x00, 0x10, 0x35, 0x00, 0x20, 0xE7}; - // Power: On, Mode: 2 (DRY), Temp: 17C, Fan: 3 (MAX), Swing (H): 5 (Auto) + // Power: On, Mode: 2 (Dry), Temp: 17C, Fan: 3 (Max), Swing(H): 5 (Auto) // 11DA171804001E11DA17180023047100001035002017 uint8_t on_dry_17_max_auto[22] = { 0x11, 0xDA, 0x17, 0x18, 0x04, 0x00, 0x1E, 0x11, 0xDA, 0x17, 0x18, 0x00, 0x23, 0x04, 0x71, 0x00, 0x00, 0x10, 0x35, 0x00, 0x20, 0x17}; - // Power: On, Mode: 7 (COOL), Temp: 25C, Fan: 3 (MAX), Swing (H): 5 (Auto) + // Power: On, Mode: 7 (Cool), Temp: 25C, Fan: 3 (Max), Swing(H): 5 (Auto) // 11DA171804001E11DA17180073042100002035002027 uint8_t on_cool_25_max_auto_v2[22] = { 0x11, 0xDA, 0x17, 0x18, 0x04, 0x00, 0x1E, @@ -2573,10 +2575,10 @@ TEST(TestDecodeDaikin128, RealExample) { ASSERT_EQ(kDaikin128Bits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "Power Toggle: On, Mode: 2 (COOL), Temp: 26C, Fan: 1 (Auto), " - "Powerful: Off, Quiet: Off, Swing (V): On, Sleep: Off, " + "Power Toggle: On, Mode: 2 (Cool), Temp: 26C, Fan: 1 (Auto), " + "Powerful: Off, Quiet: Off, Swing(V): On, Sleep: Off, " "Econo: Off, Clock: 19:20, " - "On Timer: Off, On Time: 07:30, Off Timer: Off, Off Time: 22:00, " + "On Timer: Off, On Timer: 07:30, Off Timer: Off, Off Timer: 22:00, " "Light Toggle: 0 (Off)", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -2821,10 +2823,10 @@ TEST(TestDaikin128Class, HumanReadable) { ac.setEcono(false); ac.setSwingVertical(true); EXPECT_EQ( - "Power Toggle: Off, Mode: 10 (AUTO), Temp: 25C, Fan: 1 (Auto), " - "Powerful: Off, Quiet: Off, Swing (V): On, " + "Power Toggle: Off, Mode: 10 (Auto), Temp: 25C, Fan: 1 (Auto), " + "Powerful: Off, Quiet: Off, Swing(V): On, " "Sleep: Off, Econo: Off, Clock: 00:00, " - "On Timer: Off, On Time: 00:00, Off Timer: Off, Off Time: 00:00, " + "On Timer: Off, On Timer: 00:00, Off Timer: Off, Off Timer: 00:00, " "Light Toggle: 0 (Off)", ac.toString()); ac.setMode(kDaikin128Cool); @@ -2841,10 +2843,10 @@ TEST(TestDaikin128Class, HumanReadable) { ac.setOffTimerEnabled(true); ac.setLightToggle(kDaikin128BitWall); EXPECT_EQ( - "Power Toggle: On, Mode: 2 (COOL), Temp: 16C, Fan: 9 (Quiet), " - "Powerful: Off, Quiet: On, Swing (V): Off, " + "Power Toggle: On, Mode: 2 (Cool), Temp: 16C, Fan: 9 (Quiet), " + "Powerful: Off, Quiet: On, Swing(V): Off, " "Sleep: On, Econo: On, Clock: 18:33, " - "On Timer: On, On Time: 10:00, Off Timer: On, Off Time: 21:30, " + "On Timer: On, On Timer: 10:00, Off Timer: On, Off Timer: 21:30, " "Light Toggle: 8 (Wall)", ac.toString()); } @@ -2965,6 +2967,10 @@ TEST(TestDecodeDaikin152, RealExample) { ASSERT_EQ(DAIKIN152, irsend.capture.decode_type); ASSERT_EQ(kDaikin152Bits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "Power: Off, Mode: 0 (Auto), Temp: 26C, Fan: 2 (UNKNOWN), Swing(V): Off, " + "Powerful: Off, Quiet: On, Econo: Off, Sensor: Off, Comfort: Off", + IRAcUtils::resultAcToString(&irsend.capture)); } // https://github.com/crankyoldgit/IRremoteESP8266/issues/873 @@ -2983,4 +2989,378 @@ TEST(TestDecodeDaikin152, SyntheticExample) { ASSERT_EQ(DAIKIN152, irsend.capture.decode_type); ASSERT_EQ(kDaikin152Bits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + irsend.reset(); + // Data from: + // https://github.com/crankyoldgit/IRremoteESP8266/issues/873#issuecomment-525166905 + uint8_t expectedState2[kDaikin152StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x31, 0x28, 0x00, 0x3F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x6F}; + irsend.sendDaikin152(expectedState2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN152, irsend.capture.decode_type); + ASSERT_EQ(kDaikin152Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState2, irsend.capture.state, irsend.capture.bits); + EXPECT_EQ( + "Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 1 (Low), Swing(V): On, " + "Powerful: Off, Quiet: Off, Econo: Off, Sensor: Off, Comfort: Off", + IRAcUtils::resultAcToString(&irsend.capture)); +} + +TEST(TestDaikin2ClassNew, Issue908) { + IRDaikin2 ac(0); + // https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit#gid=236366525&range=I8 + uint8_t fanMedium[kDaikin2StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x4A, 0x42, 0xB0, 0x28, 0x0C, 0x80, 0x04, + 0xB0, 0x16, 0x24, 0x00, 0x00, 0xAA, 0xC3, 0x5E, 0x11, 0xDA, 0x27, 0x00, + 0x00, 0x09, 0x3C, 0x00, 0x50, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, + 0x90, 0x60, 0xBE}; + ac.setRaw(fanMedium); + EXPECT_EQ( + "Power: On, Mode: 0 (Auto), Temp: 30C, Fan: 3 (Medium), " + "Swing(V): 3 (UpperMiddle), Swing(H): 170 (UNKNOWN), Clock: 09:46, " + "On Timer: Off, Off Timer: Off, Sleep Timer: Off, Beep: 2 (Loud), " + "Light: 3 (Off), Mould: On, Clean: On, Fresh: Off, Eye: Off, " + "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off", + ac.toString()); + ASSERT_EQ(kDaikinFanMed, ac.getFan()); + ASSERT_EQ(stdAc::fanspeed_t::kMedium, ac.toCommon().fanspeed); + ASSERT_EQ(kDaikinFanMed, ac.convertFan(stdAc::fanspeed_t::kMedium)); + + // https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit#gid=236366525&range=I17 + uint8_t swingvMiddle[kDaikin2StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x55, 0x42, 0xB0, 0x28, 0x0C, 0x80, 0x04, + 0xB0, 0x16, 0x24, 0x00, 0x00, 0xAA, 0xC3, 0x69, 0x11, 0xDA, 0x27, 0x00, + 0x00, 0x09, 0x3C, 0x00, 0xB0, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, + 0x90, 0x60, 0x1E}; + ac.setRaw(swingvMiddle); + EXPECT_EQ( + "Power: On, Mode: 0 (Auto), Temp: 30C, Fan: 11 (Quiet), " + "Swing(V): 3 (UpperMiddle), Swing(H): 170 (UNKNOWN), Clock: 09:57, " + "On Timer: Off, Off Timer: Off, Sleep Timer: Off, Beep: 2 (Loud), " + "Light: 3 (Off), Mould: On, Clean: On, Fresh: Off, Eye: Off, " + "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off", + ac.toString()); + ASSERT_EQ(3, ac.getSwingVertical()); + ASSERT_EQ(stdAc::swingv_t::kMiddle, ac.toCommon().swingv); + ac.setSwingVertical(4); + ASSERT_EQ(4, ac.getSwingVertical()); + ASSERT_EQ(stdAc::swingv_t::kMiddle, ac.toCommon().swingv); + // Either 3 or 4 is fine as they both map to stdAc::swingv_t::kMiddle. + ASSERT_EQ(4, ac.convertSwingV(stdAc::swingv_t::kMiddle)); + // Native "swing" should convert to common's "auto". + ac.setSwingVertical(kDaikin2SwingVSwing); + ASSERT_EQ(kDaikin2SwingVSwing, ac.getSwingVertical()); + ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv); + ASSERT_EQ(kDaikin2SwingVSwing, ac.convertSwingV(stdAc::swingv_t::kAuto)); + // Native "auto" should convert to common's "off". + ac.setSwingVertical(kDaikin2SwingVAuto); + ASSERT_EQ(kDaikin2SwingVAuto, ac.getSwingVertical()); + ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv); + ASSERT_EQ(kDaikin2SwingVAuto, ac.convertSwingV(stdAc::swingv_t::kOff)); +} + +// Tests for IRDaikin152 class. + +TEST(TestDaikin152Class, Power) { + IRDaikin152 ac(0); + ac.begin(); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestDaikin152Class, Temperature) { + IRDaikin152 ac(0); + ac.begin(); + ac.setMode(kDaikinHeat); // Heat has the widest temp range. + ac.setTemp(0); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(kDaikinMaxTemp); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp - 1); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(kDaikinMaxTemp + 1); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp + 1); + EXPECT_EQ(kDaikinMinTemp + 1, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + + ac.setTemp(29); + EXPECT_EQ(29, ac.getTemp()); + + // Special temps. + ac.setTemp(kDaikin152FanTemp); + EXPECT_EQ(kDaikin152FanTemp, ac.getTemp()); +} + +TEST(TestDaikin152Class, OperatingMode) { + IRDaikin152 ac(0); + ac.begin(); + + ac.setMode(kDaikinAuto); + EXPECT_EQ(kDaikinAuto, ac.getMode()); + + ac.setTemp(25); + + ac.setMode(kDaikinCool); + EXPECT_EQ(kDaikinCool, ac.getMode()); + + ac.setMode(kDaikinHeat); + EXPECT_EQ(kDaikinHeat, ac.getMode()); + + ac.setMode(kDaikinFan); + EXPECT_EQ(kDaikinFan, ac.getMode()); + EXPECT_EQ(kDaikin152FanTemp, ac.getTemp()); + + ac.setMode(kDaikinDry); + EXPECT_EQ(kDaikinDry, ac.getMode()); + EXPECT_EQ(kDaikin152DryTemp, ac.getTemp()); + + ac.setMode(kDaikinFan + 1); + EXPECT_EQ(kDaikinAuto, ac.getMode()); + + ac.setMode(kDaikinAuto + 1); + EXPECT_EQ(kDaikinAuto, ac.getMode()); + + ac.setMode(255); + EXPECT_EQ(kDaikinAuto, ac.getMode()); +} + +TEST(TestDaikin152Class, Swing) { + IRDaikin152 ac(0); + ac.begin(); + + ac.setSwingV(false); + EXPECT_FALSE(ac.getSwingV()); + + ac.setSwingV(true); + EXPECT_TRUE(ac.getSwingV()); + + ac.setSwingV(false); + EXPECT_FALSE(ac.getSwingV()); +} + +TEST(TestDaikin152Class, QuietMode) { + IRDaikin152 ac(0); + ac.begin(); + + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); + + ac.setQuiet(false); + EXPECT_FALSE(ac.getQuiet()); + + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); + + // Setting Econo mode should NOT change out of quiet mode. + ac.setEcono(true); + EXPECT_TRUE(ac.getQuiet()); + ac.setEcono(false); + EXPECT_TRUE(ac.getQuiet()); + + // But setting Powerful mode should exit out of quiet mode. + ac.setPowerful(true); + EXPECT_FALSE(ac.getQuiet()); +} + +TEST(TestDaikin152Class, PowerfulMode) { + IRDaikin152 ac(0); + ac.begin(); + + ac.setPowerful(true); + EXPECT_TRUE(ac.getPowerful()); + + ac.setPowerful(false); + EXPECT_FALSE(ac.getPowerful()); + + ac.setPowerful(true); + EXPECT_TRUE(ac.getPowerful()); + + ac.setQuiet(true); + EXPECT_FALSE(ac.getPowerful()); + + ac.setPowerful(true); + ac.setEcono(true); + EXPECT_FALSE(ac.getPowerful()); +} + +TEST(TestDaikin152Class, EconoMode) { + IRDaikin152 ac(0); + ac.begin(); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + + ac.setEcono(false); + EXPECT_FALSE(ac.getEcono()); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + + // Setting Quiet mode should NOT change out of Econo mode. + ac.setQuiet(true); + EXPECT_TRUE(ac.getEcono()); + ac.setQuiet(false); + EXPECT_TRUE(ac.getEcono()); + + // But setting Powerful mode should exit out of Econo mode. + ac.setPowerful(true); + EXPECT_FALSE(ac.getEcono()); +} + +TEST(TestDaikin152Class, FanSpeed) { + IRDaikin152 ac(0); + ac.begin(); + + // Unexpected value should default to Auto. + ac.setFan(0); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + // Unexpected value should default to Auto. + ac.setFan(255); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanMax); + EXPECT_EQ(kDaikinFanMax, ac.getFan()); + + // Beyond Max should default to Auto. + ac.setFan(kDaikinFanMax + 1); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanMax - 1); + EXPECT_EQ(kDaikinFanMax - 1, ac.getFan()); + + ac.setFan(kDaikinFanMin); + EXPECT_EQ(kDaikinFanMin, ac.getFan()); + + ac.setFan(kDaikinFanMin + 1); + EXPECT_EQ(kDaikinFanMin + 1, ac.getFan()); + + // Beyond Min should default to Auto. + ac.setFan(kDaikinFanMin - 1); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(3); + EXPECT_EQ(3, ac.getFan()); + + ac.setFan(kDaikinFanAuto); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanQuiet); + EXPECT_EQ(kDaikinFanQuiet, ac.getFan()); +} + +TEST(TestDaikin152Class, Comfort) { + IRDaikin152 ac(0); + ac.begin(); + + // Comfort mode should change these settings. + ac.setSwingV(true); + ac.setFan(kDaikinFanMax); + ac.setPowerful(true); + + ac.setComfort(false); + ASSERT_FALSE(ac.getComfort()); + + ac.setComfort(true); + ASSERT_TRUE(ac.getComfort()); + ASSERT_FALSE(ac.getSwingV()); + ASSERT_FALSE(ac.getPowerful()); + ASSERT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setComfort(false); + ASSERT_FALSE(ac.getComfort()); +} + +TEST(TestDaikin152Class, toCommon) { + IRDaikin152 ac(0); + ac.setPower(true); + ac.setMode(kDaikinCool); + ac.setTemp(20); + ac.setFan(kDaikinFanMax); + ac.setSwingV(true); + ac.setQuiet(false); + ac.setPowerful(true); + ac.setEcono(false); + // Now test it. + ASSERT_EQ(decode_type_t::DAIKIN152, ac.toCommon().protocol); + ASSERT_EQ(-1, ac.toCommon().model); + ASSERT_TRUE(ac.toCommon().power); + ASSERT_TRUE(ac.toCommon().celsius); + ASSERT_EQ(20, ac.toCommon().degrees); + ASSERT_TRUE(ac.toCommon().turbo); + ASSERT_FALSE(ac.toCommon().quiet); + ASSERT_FALSE(ac.toCommon().econo); + ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode); + ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed); + ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv); + // Unsupported. + ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh); + ASSERT_FALSE(ac.toCommon().filter); + ASSERT_FALSE(ac.toCommon().clean); + ASSERT_FALSE(ac.toCommon().light); + ASSERT_FALSE(ac.toCommon().beep); + ASSERT_EQ(-1, ac.toCommon().sleep); + ASSERT_EQ(-1, ac.toCommon().clock); +} + +TEST(TestDaikin152Class, convertFan) { + EXPECT_EQ(kDaikinFanQuiet, IRDaikin152::convertFan(stdAc::fanspeed_t::kMin)); + EXPECT_EQ(kDaikinFanMin, IRDaikin152::convertFan(stdAc::fanspeed_t::kLow)); + EXPECT_EQ(kDaikinFanMed, + IRDaikin152::convertFan(stdAc::fanspeed_t::kMedium)); + EXPECT_EQ(kDaikinFanMax - 1, + IRDaikin152::convertFan(stdAc::fanspeed_t::kHigh)); + EXPECT_EQ(kDaikinFanMax, IRDaikin152::convertFan(stdAc::fanspeed_t::kMax)); + EXPECT_EQ(kDaikinFanAuto, + IRDaikin152::convertFan(stdAc::fanspeed_t::kAuto)); +} + +TEST(TestDaikin152Class, BuildKnownState) { + IRDaikin152 ac(0); + ac.setPower(true); + ac.setMode(kDaikinCool); + ac.setTemp(20); + ac.setFan(kDaikinFanMin); + ac.setSwingV(true); + ac.setQuiet(false); + ac.setPowerful(false); + ac.setEcono(false); + ac.setSensor(false); + ac.setComfort(false); + EXPECT_EQ( + "Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 1 (Low), Swing(V): On, " + "Powerful: Off, Quiet: Off, Econo: Off, Sensor: Off, Comfort: Off", + ac.toString()); + uint8_t expectedState[kDaikin152StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x31, 0x28, 0x00, 0x3F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x6F}; + EXPECT_STATE_EQ(expectedState, ac.getRaw(), kDaikin152Bits); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Denon_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Denon_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Denon_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Denon_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Dish_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Dish_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Dish_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Dish_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Electra_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Electra_test.cpp old mode 100755 new mode 100644 similarity index 97% rename from lib/IRremoteESP8266-2.6.5/test/ir_Electra_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Electra_test.cpp index 581d40561..43ea456c6 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Electra_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Electra_test.cpp @@ -100,7 +100,7 @@ TEST(TestDecodeElectraAC, RealExampleDecode) { ASSERT_EQ(kElectraAcBits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 3 (Low), " + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " "Swing(V): Off, Swing(H): Off", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -231,20 +231,20 @@ TEST(TestIRElectraAcClass, HumanReadable) { 0x00, 0x00, 0x20, 0x00, 0x40, 0x8A}; ac.setRaw(on_cool_32C_auto_voff); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 32C, Fan: 5 (Auto), " + "Power: On, Mode: 1 (Cool), Temp: 32C, Fan: 5 (Auto), " "Swing(V): Off, Swing(H): Off", ac.toString()); uint8_t on_cool_16C_auto_voff[13] = { 0xC3, 0x47, 0xE0, 0x00, 0xA0, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x41, 0x0B}; ac.setRaw(on_cool_16C_auto_voff); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 5 (Auto), " + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 5 (Auto), " "Swing(V): Off, Swing(H): Off", ac.toString()); uint8_t on_cool_16C_low_voff[13] = { 0xC3, 0x47, 0xE0, 0x00, 0x60, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x41, 0xCB}; ac.setRaw(on_cool_16C_low_voff); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 3 (Low), " + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 3 (Low), " "Swing(V): Off, Swing(H): Off", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Fujitsu_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Fujitsu_test.cpp old mode 100755 new mode 100644 similarity index 81% rename from lib/IRremoteESP8266-2.6.5/test/ir_Fujitsu_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Fujitsu_test.cpp index b6613906f..2aead1e13 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Fujitsu_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Fujitsu_test.cpp @@ -21,8 +21,9 @@ TEST(TestIRFujitsuACClass, GetRawDefault) { 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD}; EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); - EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 24C, " - "Fan: 1 (High), Swing: Vert + Horiz, Command: N/A", + EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 24C, " + "Fan: 1 (High), Clean: Off, Filter: Off, " + "Swing: 3 (Swing(V)+Swing(H)), Command: N/A", ac.toString()); uint8_t expected_ardb1[15] = { @@ -31,7 +32,7 @@ TEST(TestIRFujitsuACClass, GetRawDefault) { ac.setModel(ARDB1); EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), 15 * 8); EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength()); - EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 24C, " + EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 24C, " "Fan: 1 (High), Command: N/A", ac.toString()); } @@ -43,15 +44,16 @@ TEST(TestIRFujitsuACClass, GetRawTurnOff) { uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD}; EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 7 * 8); EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); - EXPECT_EQ("Model: 1 (ARRAH2E), Power: Off, Mode: 1 (COOL), Temp: 24C, " - "Fan: 1 (High), Swing: Vert + Horiz, Command: N/A", + EXPECT_EQ("Model: 1 (ARRAH2E), Power: Off, Mode: 1 (Cool), Temp: 24C, " + "Fan: 1 (High), Clean: Off, Filter: Off, " + "Swing: 3 (Swing(V)+Swing(H)), Command: N/A", ac.toString()); ac.setModel(ARDB1); uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02}; EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), 6 * 8); EXPECT_EQ(kFujitsuAcStateLengthShort - 1, ac.getStateLength()); - EXPECT_EQ("Model: 2 (ARDB1), Power: Off, Mode: 1 (COOL), Temp: 24C, " + EXPECT_EQ("Model: 2 (ARDB1), Power: Off, Mode: 1 (Cool), Temp: 24C, " "Fan: 1 (High), Command: N/A", ac.toString()); } @@ -63,8 +65,9 @@ TEST(TestIRFujitsuACClass, GetRawStepHoriz) { EXPECT_STATE_EQ(expected, ac.getRaw(), 7 * 8); EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); EXPECT_EQ( - "Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 24C, " - "Fan: 1 (High), Swing: Vert + Horiz, Command: Step vane horizontally", + "Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 24C, " + "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 3 (Swing(V)+Swing(H)), " + "Command: Step Swing(H)", ac.toString()); } @@ -75,9 +78,11 @@ TEST(TestIRFujitsuACClass, GetRawStepVert) { uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C, 0x93}; EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 7 * 8); EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); - EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 24C, " - "Fan: 1 (High), Swing: Vert + Horiz, Command: Step vane vertically", - ac.toString()); + EXPECT_EQ( + "Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 24C, " + "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 3 (Swing(V)+Swing(H)), " + "Command: Step Swing(V)", + ac.toString()); ac.setModel(ARDB1); ac.stepVert(); @@ -85,8 +90,8 @@ TEST(TestIRFujitsuACClass, GetRawStepVert) { EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), 6 * 8); EXPECT_EQ(kFujitsuAcStateLengthShort - 1, ac.getStateLength()); - EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 24C, " - "Fan: 1 (High), Command: Step vane vertically", + EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 24C, " + "Fan: 1 (High), Command: Step Swing(V)", ac.toString()); } @@ -100,8 +105,9 @@ TEST(TestIRFujitsuACClass, GetRawWithSwingHoriz) { uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, 0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB}; EXPECT_STATE_EQ(expected, ac.getRaw(), 16 * 8); - EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 25C, " - "Fan: 4 (Quiet), Swing: Horiz, Command: N/A", + EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 25C, " + "Fan: 4 (Quiet), Clean: Off, Filter: Off, " + "Swing: 2 (Swing(H)), Command: N/A", ac.toString()); } @@ -119,8 +125,10 @@ TEST(TestIRFujitsuACClass, GetRawWithFan) { 0x40, 0x03, 0x22, 0x00, 0x00, 0x00, 0x20, 0x4B}; EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); - EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 3 (FAN), Temp: 20C, " - "Fan: 2 (Medium), Swing: Horiz, Command: N/A", ac.toString()); + EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 3 (Fan), Temp: 20C, " + "Fan: 2 (Medium), Clean: Off, Filter: Off, " + "Swing: 2 (Swing(H)), Command: N/A", + ac.toString()); ac.setModel(ARDB1); uint8_t expected_ardb1[15] = { @@ -128,7 +136,7 @@ TEST(TestIRFujitsuACClass, GetRawWithFan) { 0x40, 0x03, 0x02, 0x00, 0x00, 0x00, 0x8B}; EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength()); EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), ac.getStateLength() * 8); - EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 3 (FAN), Temp: 20C, " + EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 3 (Fan), Temp: 20C, " "Fan: 2 (Medium), Command: N/A", ac.toString()); } @@ -140,8 +148,9 @@ TEST(TestIRFujitsuACClass, SetRaw) { 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD}; EXPECT_STATE_EQ(expected_default_arrah2e, ac.getRaw(), ac.getStateLength() * 8); - EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 24C, " - "Fan: 1 (High), Swing: Vert + Horiz, Command: N/A", + EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 24C, " + "Fan: 1 (High), Clean: Off, Filter: Off, " + "Swing: 3 (Swing(V)+Swing(H)), Command: N/A", ac.toString()); // Now set a new state via setRaw(); // This state is a real state from an AR-DB1 remote. @@ -151,7 +160,7 @@ TEST(TestIRFujitsuACClass, SetRaw) { ac.setRaw(new_state1, kFujitsuAcStateLength - 1); EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength()); EXPECT_STATE_EQ(new_state1, ac.getRaw(), ac.getStateLength() * 8); - EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 19C, " + EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 19C, " "Fan: 0 (Auto), Command: N/A", ac.toString()); } @@ -347,8 +356,10 @@ TEST(TestDecodeFujitsuAC, SyntheticLongMessages) { EXPECT_STATE_EQ(expected_arrah2e, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); - EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 18C, " - "Fan: 4 (Quiet), Swing: Vert, Command: N/A", ac.toString()); + EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 18C, " + "Fan: 4 (Quiet), Clean: Off, Filter: Off, " + "Swing: 1 (Swing(V)), Command: N/A", + ac.toString()); irsend.reset(); @@ -364,7 +375,7 @@ TEST(TestDecodeFujitsuAC, SyntheticLongMessages) { EXPECT_STATE_EQ(expected_ardb1, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength()); - EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 18C, " + EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 18C, " "Fan: 4 (Quiet), Command: N/A", ac.toString()); } @@ -396,7 +407,7 @@ TEST(TestDecodeFujitsuAC, RealShortARDB1OffExample) { EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ(kFujitsuAcStateLengthShort - 1, ac.getStateLength()); - EXPECT_EQ("Model: 2 (ARDB1), Power: Off, Mode: 0 (AUTO), Temp: 16C, " + EXPECT_EQ("Model: 2 (ARDB1), Power: Off, Mode: 0 (Auto), Temp: 16C, " "Fan: 0 (Auto), Command: N/A", ac.toString()); } @@ -440,7 +451,7 @@ TEST(TestDecodeFujitsuAC, RealLongARDB1Example) { EXPECT_STATE_EQ(expected1, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength()); - EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 18C, " + EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 18C, " "Fan: 4 (Quiet), Command: N/A", ac.toString()); irsend.reset(); @@ -477,7 +488,7 @@ TEST(TestDecodeFujitsuAC, RealLongARDB1Example) { EXPECT_STATE_EQ(expected2, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength()); - EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (COOL), Temp: 19C, " + EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 19C, " "Fan: 0 (Auto), Command: N/A", ac.toString()); } @@ -519,8 +530,10 @@ TEST(TestDecodeFujitsuAC, Issue414) { EXPECT_STATE_EQ(state, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); - EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 4 (HEAT), Temp: 24C, " - "Fan: 0 (Auto), Swing: Off, Command: N/A", ac.toString()); + EXPECT_EQ( + "Model: 1 (ARRAH2E), Power: On, Mode: 4 (Heat), Temp: 24C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A", + ac.toString()); // Resend it using the state this time. irsend.reset(); @@ -594,8 +607,9 @@ TEST(TestIRFujitsuACClass, toCommon) { // Now test it. EXPECT_EQ( // Off mode technically has no temp, mode, fan, etc. - "Model: 1 (ARRAH2E), Power: Off, Mode: 0 (AUTO), Temp: 16C, " - "Fan: 0 (Auto), Swing: Off, Command: N/A", ac.toString()); + "Model: 1 (ARRAH2E), Power: Off, Mode: 0 (Auto), Temp: 16C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A", + ac.toString()); ASSERT_EQ(decode_type_t::FUJITSU_AC, ac.toCommon().protocol); ASSERT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.toCommon().model); ASSERT_FALSE(ac.toCommon().power); @@ -648,8 +662,9 @@ TEST(TestDecodeFujitsuAC, Issue716) { ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ(fujitsu_ac_remote_model_t::ARREB1E, ac.getModel()); EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); - EXPECT_EQ("Model: 3 (ARREB1E), Power: On, Mode: 0 (AUTO), Temp: 16C, " - "Fan: 0 (Auto), Swing: Off, Command: Powerful, Outside Quiet: Off", + EXPECT_EQ("Model: 3 (ARREB1E), Power: On, Mode: 0 (Auto), Temp: 16C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), " + "Command: Powerful, Outside Quiet: Off", ac.toString()); // Economy (just from the state) @@ -662,8 +677,9 @@ TEST(TestDecodeFujitsuAC, Issue716) { ac.setRaw(econo, kFujitsuAcStateLengthShort); EXPECT_EQ(fujitsu_ac_remote_model_t::ARREB1E, ac.getModel()); EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); - EXPECT_EQ("Model: 3 (ARREB1E), Power: On, Mode: 0 (AUTO), Temp: 16C, " - "Fan: 0 (Auto), Swing: Off, Command: Economy, Outside Quiet: Off", + EXPECT_EQ("Model: 3 (ARREB1E), Power: On, Mode: 0 (Auto), Temp: 16C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), " + "Command: Econo, Outside Quiet: Off", ac.toString()); } @@ -693,12 +709,14 @@ TEST(TestIRFujitsuACClass, OutsideQuiet) { // We can really only tell the difference between ARRAH2E & ARREB1E if // the option is set. Otheriwse they appear the same. EXPECT_EQ( - "Model: 1 (ARRAH2E), Power: On, Mode: 1 (COOL), Temp: 24C, " - "Fan: 0 (Auto), Swing: Off, Command: N/A", ac.toString()); + "Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 24C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), " + "Command: N/A", ac.toString()); ac.setModel(fujitsu_ac_remote_model_t::ARREB1E); EXPECT_EQ( - "Model: 3 (ARREB1E), Power: On, Mode: 1 (COOL), Temp: 24C, " - "Fan: 0 (Auto), Swing: Off, Command: N/A, Outside Quiet: Off", + "Model: 3 (ARREB1E), Power: On, Mode: 1 (Cool), Temp: 24C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), " + "Command: N/A, Outside Quiet: Off", ac.toString()); // Make sure we can't accidentally inherit the correct model. @@ -708,8 +726,9 @@ TEST(TestIRFujitsuACClass, OutsideQuiet) { EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_TRUE(ac.getOutsideQuiet()); EXPECT_EQ( - "Model: 3 (ARREB1E), Power: On, Mode: 1 (COOL), Temp: 24C, " - "Fan: 0 (Auto), Swing: Off, Command: N/A, Outside Quiet: On", + "Model: 3 (ARREB1E), Power: On, Mode: 1 (Cool), Temp: 24C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), " + "Command: N/A, Outside Quiet: On", ac.toString()); ac.setOutsideQuiet(false); @@ -756,8 +775,8 @@ TEST(TestIRFujitsuACClass, toggleSwing) { EXPECT_EQ(kFujitsuAcSwingBoth, ac.getSwing()); EXPECT_EQ( - "Model: 4 (ARJW2), Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (High), " - "Command: Toggle horizontal swing", + "Model: 4 (ARJW2), Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 1 (High), " + "Command: Toggle Swing(H)", ac.toString()); // Test without the update set. @@ -792,7 +811,94 @@ TEST(TestDecodeFujitsuAC, Issue726) { ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.getModel()); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); - EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 0 (AUTO), Temp: 24C, " - "Fan: 0 (Auto), Swing: Off, Command: N/A", - ac.toString()); + EXPECT_EQ( + "Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 24C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A", + ac.toString()); +} + +TEST(TestIRFujitsuACClass, Clean) { + IRFujitsuAC ac(0); + // Data from: + // https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit#gid=646887633&range=A27:B30 + uint8_t clean_off[kFujitsuAcStateLength] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10}; + uint8_t clean_on[kFujitsuAcStateLength] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0xA0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08}; + ac.setRaw(clean_on, kFujitsuAcStateLength); + EXPECT_TRUE(ac.getClean()); + EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); + EXPECT_EQ( + "Model: 5 (ARRY4), Power: On, Mode: 0 (Auto), Temp: 26C, " + "Fan: 0 (Auto), Clean: On, Filter: Off, Swing: 0 (Off), Command: N/A", + ac.toString()); + ac.setClean(false); + EXPECT_FALSE(ac.getClean()); + EXPECT_STATE_EQ(clean_off, ac.getRaw(), ac.getStateLength() * 8) + ac.setClean(true); + EXPECT_TRUE(ac.getClean()); + EXPECT_STATE_EQ(clean_on, ac.getRaw(), ac.getStateLength() * 8) + ac.setRaw(clean_off, kFujitsuAcStateLength); + EXPECT_FALSE(ac.getClean()); + EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); + EXPECT_EQ( + "Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A", + ac.toString()); + // Now it is in ARRAH2E model mode, it shouldn't accept setting it on. + ac.setClean(true); + EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.getModel()); + EXPECT_EQ( + "Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A", + ac.toString()); + // But ARRY4 does. + ac.setModel(fujitsu_ac_remote_model_t::ARRY4); + EXPECT_TRUE(ac.getClean()); + EXPECT_EQ( + "Model: 5 (ARRY4), Power: On, Mode: 0 (Auto), Temp: 26C, " + "Fan: 0 (Auto), Clean: On, Filter: Off, Swing: 0 (Off), Command: N/A", + ac.toString()); +} + +TEST(TestIRFujitsuACClass, Filter) { + IRFujitsuAC ac(0); + // Data from: + // https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit#gid=646887633&range=A27:B30 + uint8_t filter_on[kFujitsuAcStateLength] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x07}; + uint8_t filter_off[kFujitsuAcStateLength] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10}; + ac.setRaw(filter_on, kFujitsuAcStateLength); + EXPECT_TRUE(ac.getFilter()); + EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); + EXPECT_EQ( + "Model: 5 (ARRY4), Power: On, Mode: 0 (Auto), Temp: 26C, " + "Fan: 0 (Auto), Clean: Off, Filter: On, Swing: 0 (Off), Command: N/A", + ac.toString()); + ac.setFilter(false); + EXPECT_FALSE(ac.getFilter()); + ac.setFilter(true); + EXPECT_TRUE(ac.getFilter()); + ac.setRaw(filter_off, kFujitsuAcStateLength); + EXPECT_FALSE(ac.getFilter()); + EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); + EXPECT_EQ( + "Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A", + ac.toString()); + // Now it is in ARRAH2E model mode, it shouldn't accept setting it on. + ac.setFilter(true); + EXPECT_FALSE(ac.getFilter()); + // But ARRY4 does. + ac.setModel(fujitsu_ac_remote_model_t::ARRY4); + EXPECT_TRUE(ac.getFilter()); + EXPECT_EQ( + "Model: 5 (ARRY4), Power: On, Mode: 0 (Auto), Temp: 26C, " + "Fan: 0 (Auto), Clean: Off, Filter: On, Swing: 0 (Off), Command: N/A", + ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_GICable_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_GICable_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_GICable_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_GICable_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_GlobalCache_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_GlobalCache_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_GlobalCache_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_GlobalCache_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Goodweather_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Goodweather_test.cpp old mode 100755 new mode 100644 similarity index 93% rename from lib/IRremoteESP8266-2.6.5/test/ir_Goodweather_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Goodweather_test.cpp index 58f42f0fe..6345d2398 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Goodweather_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Goodweather_test.cpp @@ -24,20 +24,20 @@ TEST(TestSendGoodweather, SendDataOnly) { irsend.sendGoodweather(0x0); EXPECT_EQ( "f38000d50" - "m6800s6800" - "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600" - "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580" - "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600" - "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580" - "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600" - "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580" - "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600" - "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580" - "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600" - "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580" - "m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600m640s1600" - "m640s580m640s580m640s580m640s580m640s580m640s580m640s580m640s580" - "m640s6800m640s100000", + "m6820s6820" + "m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860" + "m580s580m580s580m580s580m580s580m580s580m580s580m580s580m580s580" + "m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860" + "m580s580m580s580m580s580m580s580m580s580m580s580m580s580m580s580" + "m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860" + "m580s580m580s580m580s580m580s580m580s580m580s580m580s580m580s580" + "m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860" + "m580s580m580s580m580s580m580s580m580s580m580s580m580s580m580s580" + "m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860" + "m580s580m580s580m580s580m580s580m580s580m580s580m580s580m580s580" + "m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860m580s1860" + "m580s580m580s580m580s580m580s580m580s580m580s580m580s580m580s580" + "m580s6820m580s100000", irsend.outputStr()); irsend.reset(); @@ -113,7 +113,7 @@ TEST(TestDecodeGoodweather, RealExampleDecode) { EXPECT_FALSE(irsend.capture.repeat); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 3 (Low), " + "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 3 (Low), " "Turbo: -, Light: -, Sleep: -, Swing: 0 (Fast), Command: 0 (Power)", ac.toString()); @@ -146,7 +146,7 @@ uint16_t rawData_FAD2BE31[197] = { EXPECT_FALSE(irsend.capture.repeat); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: Off, Mode: 1 (COOL), Temp: 22C, Fan: 3 (Low), Turbo: -, " + "Power: Off, Mode: 1 (Cool), Temp: 22C, Fan: 3 (Low), Turbo: -, " "Light: -, Sleep: -, Swing: 2 (Off), Command: 0 (Power)", ac.toString()); @@ -179,7 +179,7 @@ uint16_t rawData_FAD2BE31[197] = { EXPECT_FALSE(irsend.capture.repeat); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 22C, Fan: 3 (Low), Turbo: -, " + "Power: On, Mode: 1 (Cool), Temp: 22C, Fan: 3 (Low), Turbo: -, " "Light: -, Sleep: -, Swing: 2 (Off), Command: 0 (Power)", ac.toString()); @@ -212,7 +212,7 @@ uint16_t rawData_FAD2BE31[197] = { EXPECT_FALSE(irsend.capture.repeat); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 3 (Low), Turbo: -, " + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), Turbo: -, " "Light: -, Sleep: -, Swing: 2 (Off), Command: 2 (Temp Up)", ac.toString()); @@ -245,7 +245,7 @@ uint16_t rawData_FAD2BE31[197] = { EXPECT_FALSE(irsend.capture.repeat); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 23C, Fan: 3 (Low), " + "Power: On, Mode: 1 (Cool), Temp: 23C, Fan: 3 (Low), " "Turbo: -, Light: -, Sleep: -, Swing: 2 (Off), Command: 3 (Temp Down)", ac.toString()); @@ -278,7 +278,7 @@ uint16_t rawData_FAD2BE31[197] = { EXPECT_FALSE(irsend.capture.repeat); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 22C, Fan: 3 (Low), Turbo: -, Light: -, " + "Power: On, Mode: 1 (Cool), Temp: 22C, Fan: 3 (Low), Turbo: -, Light: -, " "Sleep: -, Swing: 1 (Slow), Command: 4 (Swing)", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Gree_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Gree_test.cpp old mode 100755 new mode 100644 similarity index 97% rename from lib/IRremoteESP8266-2.6.5/test/ir_Gree_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Gree_test.cpp index d85df72b8..6c8672c77 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Gree_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Gree_test.cpp @@ -495,9 +495,9 @@ TEST(TestGreeClass, HumanReadable) { IRGreeAC irgree(0); EXPECT_EQ( - "Model: 1 (YAW1F), Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 0 (Auto), " + "Model: 1 (YAW1F), Power: Off, Mode: 0 (Auto), Temp: 25C, Fan: 0 (Auto), " "Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, " - "Swing Vertical Mode: Manual, Swing Vertical Pos: 0 (Last Pos), " + "Swing(V) Mode: Manual, Swing(V): 0 (Last), " "Timer: Off", irgree.toString()); irgree.on(); @@ -513,9 +513,9 @@ TEST(TestGreeClass, HumanReadable) { irgree.setSwingVertical(true, kGreeSwingAuto); irgree.setTimer(12 * 60 + 30); EXPECT_EQ( - "Model: 1 (YAW1F), Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 3 (High), " + "Model: 1 (YAW1F), Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 3 (High), " "Turbo: On, IFeel: On, WiFi: On, XFan: On, Light: Off, Sleep: On, " - "Swing Vertical Mode: Auto, Swing Vertical Pos: 1 (Auto), Timer: 12:30", + "Swing(V) Mode: Auto, Swing(V): 1 (Auto), Timer: 12:30", irgree.toString()); } @@ -573,9 +573,9 @@ TEST(TestDecodeGree, NormalRealExample) { EXPECT_STATE_EQ(gree_code, irsend.capture.state, kGreeBits); irgree.setRaw(irsend.capture.state); EXPECT_EQ( - "Model: 1 (YAW1F), Power: On, Mode: 1 (COOL), Temp: 26C, Fan: 1 (Low), " + "Model: 1 (YAW1F), Power: On, Mode: 1 (Cool), Temp: 26C, Fan: 1 (Low), " "Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, " - "Swing Vertical Mode: Manual, Swing Vertical Pos: 2, Timer: Off", + "Swing(V) Mode: Manual, Swing(V): 2 (UNKNOWN), Timer: Off", irgree.toString()); } @@ -628,9 +628,9 @@ TEST(TestGreeClass, Issue814Power) { EXPECT_TRUE(ac.getPower()); EXPECT_EQ(gree_ac_remote_model_t::YBOFB, ac.getModel()); EXPECT_EQ( - "Model: 2 (YBOFB), Power: On, Mode: 1 (COOL), Temp: 23C, Fan: 1 (Low), " + "Model: 2 (YBOFB), Power: On, Mode: 1 (Cool), Temp: 23C, Fan: 1 (Low), " "Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, " - "Swing Vertical Mode: Auto, Swing Vertical Pos: 1 (Auto), Timer: Off", + "Swing(V) Mode: Auto, Swing(V): 1 (Auto), Timer: Off", ac.toString()); ac.off(); EXPECT_STATE_EQ(off, ac.getRaw(), kGreeBits); diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Haier_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Haier_test.cpp old mode 100755 new mode 100644 similarity index 92% rename from lib/IRremoteESP8266-2.6.5/test/ir_Haier_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Haier_test.cpp index 03cc63f93..db824a28e --- a/lib/IRremoteESP8266-2.6.5/test/ir_Haier_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Haier_test.cpp @@ -131,6 +131,8 @@ TEST(TestHaierACClass, Command) { EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); haier.setCommand(kHaierAcCmdOn); EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + haier.setCommand(kHaierAcCmdOff); + EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); // Test unexpected values. haier.setCommand(0b00001110); @@ -347,50 +349,50 @@ TEST(TestHaierACClass, MessageConstuction) { IRHaierAC haier(0); EXPECT_EQ( - "Command: 1 (On), Mode: 0 (AUTO), Temp: 25C, Fan: 0 (Auto), " + "Command: 1 (On), Mode: 0 (Auto), Temp: 25C, Fan: 0 (Auto), " "Swing: 0 (Off), Sleep: Off, Health: Off, " - "Current Time: 00:00, On Timer: Off, Off Timer: Off", + "Clock: 00:00, On Timer: Off, Off Timer: Off", haier.toString()); haier.setMode(kHaierAcCool); haier.setTemp(21); haier.setFan(kHaierAcFanHigh); EXPECT_EQ( - "Command: 3 (Fan), Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), " + "Command: 3 (Fan), Mode: 1 (Cool), Temp: 21C, Fan: 3 (High), " "Swing: 0 (Off), Sleep: Off, Health: Off, " - "Current Time: 00:00, On Timer: Off, Off Timer: Off", + "Clock: 00:00, On Timer: Off, Off Timer: Off", haier.toString()); haier.setSwing(kHaierAcSwingChg); haier.setHealth(true); haier.setSleep(true); haier.setCurrTime(615); // 10:15am EXPECT_EQ( - "Command: 8 (Sleep), Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), " - "Swing: 3 (Chg), Sleep: On, Health: On, " - "Current Time: 10:15, On Timer: Off, Off Timer: Off", + "Command: 8 (Sleep), Mode: 1 (Cool), Temp: 21C, Fan: 3 (High), " + "Swing: 3 (Change), Sleep: On, Health: On, " + "Clock: 10:15, On Timer: Off, Off Timer: Off", haier.toString()); haier.setOnTimer(800); // 1:20pm haier.setOffTimer(1125); // 6:45pm haier.setCommand(kHaierAcCmdOn); EXPECT_EQ( - "Command: 1 (On), Mode: 1 (COOL), Temp: 21C, Fan: 2 (Medium), " - "Swing: 3 (Chg), Sleep: On, Health: On, " - "Current Time: 10:15, On Timer: 13:20, Off Timer: 18:45", + "Command: 1 (On), Mode: 1 (Cool), Temp: 21C, Fan: 2 (Medium), " + "Swing: 3 (Change), Sleep: On, Health: On, " + "Clock: 10:15, On Timer: 13:20, Off Timer: 18:45", haier.toString()); // Now change a few already set things. haier.setMode(kHaierAcHeat); EXPECT_EQ( - "Command: 2 (Mode), Mode: 3 (HEAT), Temp: 21C, Fan: 2 (Medium), " - "Swing: 3 (Chg), Sleep: On, Health: On, " - "Current Time: 10:15, On Timer: 13:20, Off Timer: 18:45", + "Command: 2 (Mode), Mode: 3 (Heat), Temp: 21C, Fan: 2 (Medium), " + "Swing: 3 (Change), Sleep: On, Health: On, " + "Clock: 10:15, On Timer: 13:20, Off Timer: 18:45", haier.toString()); haier.setTemp(25); EXPECT_EQ( - "Command: 6 (Temp Up), Mode: 3 (HEAT), Temp: 25C, Fan: 2 (Medium), " - "Swing: 3 (Chg), Sleep: On, Health: On, " - "Current Time: 10:15, On Timer: 13:20, Off Timer: 18:45", + "Command: 6 (Temp Up), Mode: 3 (Heat), Temp: 25C, Fan: 2 (Medium), " + "Swing: 3 (Change), Sleep: On, Health: On, " + "Clock: 10:15, On Timer: 13:20, Off Timer: 18:45", haier.toString()); uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x96, 0xEA, 0xCF, 0x32, @@ -406,9 +408,9 @@ TEST(TestHaierACClass, MessageConstuction) { EXPECT_FALSE(IRHaierAC::validChecksum(randomState)); haier.setRaw(randomState); EXPECT_EQ( - "Command: 9 (Timer Set), Mode: 3 (HEAT), Temp: 20C, Fan: 2 (Medium), " + "Command: 9 (Timer Set), Mode: 3 (Heat), Temp: 20C, Fan: 2 (Medium), " "Swing: 1 (Up), Sleep: On, Health: Off, " - "Current Time: 16:32, On Timer: Off, Off Timer: Off", + "Clock: 16:32, On Timer: Off, Off Timer: Off", haier.toString()); // getRaw() should correct the checksum. EXPECT_TRUE(IRHaierAC::validChecksum(haier.getRaw())); @@ -670,16 +672,16 @@ TEST(TestHaierACYRW02Class, MessageConstuction) { IRHaierACYRW02 haier(0); EXPECT_EQ( - "Power: On, Button: 5 (Power), Mode: 0 (AUTO), Temp: 25C," - " Fan: 10 (Auto), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," + "Power: On, Button: 5 (Power), Mode: 0 (Auto), Temp: 25C," + " Fan: 5 (Auto), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," " Health: On", haier.toString()); haier.setMode(kHaierAcYrw02Cool); haier.setTemp(21); haier.setFan(kHaierAcYrw02FanHigh); EXPECT_EQ( - "Power: On, Button: 4 (Fan), Mode: 2 (COOL), Temp: 21C," - " Fan: 2 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," + "Power: On, Button: 4 (Fan), Mode: 1 (Cool), Temp: 21C," + " Fan: 1 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," " Health: On", haier.toString()); @@ -688,8 +690,8 @@ TEST(TestHaierACYRW02Class, MessageConstuction) { haier.setSleep(true); haier.setTurbo(kHaierAcYrw02TurboHigh); EXPECT_EQ( - "Power: On, Button: 8 (Turbo), Mode: 2 (COOL), Temp: 21C," - " Fan: 2 (High), Turbo: 1 (High), Swing: 2 (Middle)," + "Power: On, Button: 8 (Turbo), Mode: 1 (Cool), Temp: 21C," + " Fan: 1 (High), Turbo: 1 (High), Swing: 2 (Middle)," " Sleep: On, Health: Off", haier.toString()); } @@ -703,8 +705,8 @@ TEST(TestHaierACYRW02Class, RealStates) { IRHaierACYRW02 haier(0); haier.setRaw(expectedState1); EXPECT_EQ( - "Power: On, Button: 7 (Health), Mode: 8 (HEAT), Temp: 30C," - " Fan: 2 (High), Turbo: 0 (Off), Swing: 1 (Top), Sleep: Off," + "Power: On, Button: 7 (Health), Mode: 4 (Heat), Temp: 30C," + " Fan: 1 (High), Turbo: 0 (Off), Swing: 1 (Highest), Sleep: Off," " Health: Off", haier.toString()); @@ -713,8 +715,8 @@ TEST(TestHaierACYRW02Class, RealStates) { 0x80, 0x00, 0x00, 0x00, 0x00, 0x05, 0x75}; haier.setRaw(expectedState2); EXPECT_EQ( - "Power: Off, Button: 5 (Power), Mode: 8 (HEAT), Temp: 30C," - " Fan: 2 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," + "Power: Off, Button: 5 (Power), Mode: 4 (Heat), Temp: 30C," + " Fan: 1 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," " Health: Off", haier.toString()); @@ -723,8 +725,8 @@ TEST(TestHaierACYRW02Class, RealStates) { 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2B}; haier.setRaw(expectedState3); EXPECT_EQ( - "Power: On, Button: 1 (Temp Down), Mode: 2 (COOL), Temp: 16C," - " Fan: 2 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off," + "Power: On, Button: 1 (Temp Down), Mode: 1 (Cool), Temp: 16C," + " Fan: 1 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off," " Health: On", haier.toString()); @@ -734,8 +736,8 @@ TEST(TestHaierACYRW02Class, RealStates) { 0x20, 0x80, 0x00, 0x00, 0x00, 0x0B, 0xD7}; haier.setRaw(expectedState4); EXPECT_EQ( - "Power: On, Button: 11 (Sleep), Mode: 2 (COOL), Temp: 25C," - " Fan: 10 (Auto), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On," + "Power: On, Button: 11 (Sleep), Mode: 1 (Cool), Temp: 25C," + " Fan: 5 (Auto), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On," " Health: On", haier.toString()); @@ -745,8 +747,8 @@ TEST(TestHaierACYRW02Class, RealStates) { 0x20, 0x80, 0x00, 0x00, 0x00, 0x04, 0x85}; haier.setRaw(expectedState5); EXPECT_EQ( - "Power: On, Button: 4 (Fan), Mode: 2 (COOL), Temp: 25C," - " Fan: 2 (High), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On," + "Power: On, Button: 4 (Fan), Mode: 1 (Cool), Temp: 25C," + " Fan: 1 (High), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On," " Health: On", haier.toString()); } @@ -818,9 +820,9 @@ TEST(TestDecodeHaierAC, RealExample1) { IRHaierAC haier(0); haier.setRaw(irsend.capture.state); EXPECT_EQ( - "Command: 1 (On), Mode: 1 (COOL), Temp: 16C, Fan: 0 (Auto), " + "Command: 1 (On), Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), " "Swing: 0 (Off), Sleep: Off, Health: Off, " - "Current Time: 00:01, On Timer: Off, Off Timer: Off", + "Clock: 00:01, On Timer: Off, Off Timer: Off", haier.toString()); } @@ -860,9 +862,9 @@ TEST(TestDecodeHaierAC, RealExample2) { IRHaierAC haier(0); haier.setRaw(irsend.capture.state); EXPECT_EQ( - "Command: 6 (Temp Up), Mode: 1 (COOL), Temp: 22C, Fan: 0 (Auto), " + "Command: 6 (Temp Up), Mode: 1 (Cool), Temp: 22C, Fan: 0 (Auto), " "Swing: 0 (Off), Sleep: Off, Health: Off, " - "Current Time: 00:01, On Timer: Off, Off Timer: Off", + "Clock: 00:01, On Timer: Off, Off Timer: Off", haier.toString()); } @@ -902,9 +904,9 @@ TEST(TestDecodeHaierAC, RealExample3) { IRHaierAC haier(0); haier.setRaw(irsend.capture.state); EXPECT_EQ( - "Command: 12 (Health), Mode: 1 (COOL), Temp: 30C, Fan: 0 (Auto), " + "Command: 12 (Health), Mode: 1 (Cool), Temp: 30C, Fan: 0 (Auto), " "Swing: 0 (Off), Sleep: Off, Health: On, " - "Current Time: 00:09, On Timer: Off, Off Timer: Off", + "Clock: 00:09, On Timer: Off, Off Timer: Off", haier.toString()); } @@ -972,8 +974,8 @@ TEST(TestDecodeHaierAC_YRW02, RealExample) { IRHaierACYRW02 haier(0); haier.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Button: 5 (Power), Mode: 2 (COOL), Temp: 17C," - " Fan: 2 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off," + "Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 17C," + " Fan: 1 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off," " Health: On", haier.toString()); } @@ -989,8 +991,8 @@ TEST(TestHaierAcIssues, Issue668) { // Turn on the AC. ac._irsend.reset(); char expected_on[] = - "Command: 1 (On), Mode: 1 (COOL), Temp: 25C, Fan: 0 (Auto), " - "Swing: 0 (Off), Sleep: Off, Health: Off, Current Time: 00:00, " + "Command: 1 (On), Mode: 1 (Cool), Temp: 25C, Fan: 0 (Auto), " + "Swing: 0 (Off), Sleep: Off, Health: Off, Clock: 00:00, " "On Timer: Off, Off Timer: Off"; // State taken from real capture: // https://github.com/crankyoldgit/IRremoteESP8266/issues/668#issuecomment-483531895 @@ -1027,8 +1029,8 @@ TEST(TestHaierAcIssues, Issue668) { // Increase the temp by 1. ac._irsend.reset(); char expected_temp_plus_one[] = - "Command: 6 (Temp Up), Mode: 1 (COOL), Temp: 26C, Fan: 0 (Auto), " - "Swing: 0 (Off), Sleep: Off, Health: Off, Current Time: 00:00, " + "Command: 6 (Temp Up), Mode: 1 (Cool), Temp: 26C, Fan: 0 (Auto), " + "Swing: 0 (Off), Sleep: Off, Health: Off, Clock: 00:00, " "On Timer: Off, Off Timer: Off"; // State taken from real capture: // https://github.com/crankyoldgit/IRremoteESP8266/issues/668#issuecomment-483531895 @@ -1051,8 +1053,8 @@ TEST(TestHaierAcIssues, Issue668) { // Decrease the temp by 1. ac._irsend.reset(); char expected_temp_minus_one[] = - "Command: 7 (Temp Down), Mode: 1 (COOL), Temp: 25C, Fan: 0 (Auto), " - "Swing: 0 (Off), Sleep: Off, Health: Off, Current Time: 00:00, " + "Command: 7 (Temp Down), Mode: 1 (Cool), Temp: 25C, Fan: 0 (Auto), " + "Swing: 0 (Off), Sleep: Off, Health: Off, Clock: 00:00, " "On Timer: Off, Off Timer: Off"; ASSERT_EQ(26, ac.getTemp()); ac.setTemp(ac.getTemp() - 1); diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Hitachi_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Hitachi_test.cpp old mode 100755 new mode 100644 similarity index 74% rename from lib/IRremoteESP8266-2.6.5/test/ir_Hitachi_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Hitachi_test.cpp index 7e7935638..e84897dc8 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Hitachi_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Hitachi_test.cpp @@ -1,6 +1,7 @@ // Copyright 2018 David Conran #include "ir_Hitachi.h" +#include "IRac.h" #include "IRrecv.h" #include "IRrecv_test.h" #include "IRremoteESP8266.h" @@ -300,8 +301,8 @@ TEST(TestIRHitachiAcClass, HumanReadable) { ac.setFan(kHitachiAcFanHigh); ac.setSwingVertical(true); EXPECT_EQ( - "Power: On, Mode: 3 (HEAT), Temp: 32C, Fan: 5 (High), " - "Swing (Vertical): On, Swing (Horizontal): Off", + "Power: On, Mode: 3 (Heat), Temp: 32C, Fan: 5 (High), " + "Swing(V): On, Swing(H): Off", ac.toString()); ac.setMode(kHitachiAcCool); ac.setTemp(kHitachiAcMinTemp); @@ -309,8 +310,8 @@ TEST(TestIRHitachiAcClass, HumanReadable) { ac.setSwingVertical(false); ac.setSwingHorizontal(true); EXPECT_EQ( - "Power: On, Mode: 4 (COOL), Temp: 16C, Fan: 2 (Low), " - "Swing (Vertical): Off, Swing (Horizontal): On", + "Power: On, Mode: 4 (Cool), Temp: 16C, Fan: 2 (Low), " + "Swing(V): Off, Swing(H): On", ac.toString()); } @@ -428,8 +429,8 @@ TEST(TestDecodeHitachiAC, NormalRealExample1) { IRHitachiAc ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 4 (COOL), Temp: 16C, Fan: 1 (Auto), " - "Swing (Vertical): Off, Swing (Horizontal): Off", + "Power: On, Mode: 4 (Cool), Temp: 16C, Fan: 1 (Auto), " + "Swing(V): Off, Swing(H): Off", ac.toString()); } @@ -496,8 +497,8 @@ TEST(TestDecodeHitachiAC, NormalRealExample2) { IRHitachiAc ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 3 (HEAT), Temp: 32C, Fan: 5 (High), " - "Swing (Vertical): Off, Swing (Horizontal): Off", + "Power: On, Mode: 3 (Heat), Temp: 32C, Fan: 5 (High), " + "Swing(V): Off, Swing(H): Off", ac.toString()); } @@ -798,3 +799,300 @@ TEST(TestIRHitachiAcClass, toCommon) { ASSERT_EQ(-1, ac.toCommon().sleep); ASSERT_EQ(-1, ac.toCommon().clock); } + +TEST(TestUtils, Housekeeping) { + ASSERT_EQ("HITACHI_AC", typeToString(decode_type_t::HITACHI_AC)); + ASSERT_EQ(decode_type_t::HITACHI_AC, strToDecodeType("HITACHI_AC")); + ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC)); + + ASSERT_EQ("HITACHI_AC1", typeToString(decode_type_t::HITACHI_AC1)); + ASSERT_EQ(decode_type_t::HITACHI_AC1, strToDecodeType("HITACHI_AC1")); + ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC1)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC1)); + + ASSERT_EQ("HITACHI_AC2", typeToString(decode_type_t::HITACHI_AC2)); + ASSERT_EQ(decode_type_t::HITACHI_AC2, strToDecodeType("HITACHI_AC2")); + ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC2)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC2)); + + ASSERT_EQ("HITACHI_AC424", typeToString(decode_type_t::HITACHI_AC424)); + ASSERT_EQ(decode_type_t::HITACHI_AC424, strToDecodeType("HITACHI_AC424")); + ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC424)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC424)); +} + +// Decode a 'real' HitachiAc424 message. +TEST(TestDecodeHitachiAc424, RealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t expected[kHitachiAc424StateLength] = { + 0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xCC, 0x33, 0x92, + 0x6D, 0x13, 0xEC, 0x5C, 0xA3, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x53, 0xAC, 0xF1, 0x0E, 0x00, + 0xFF, 0x00, 0xFF, 0x80, 0x7F, 0x03, 0xFC, 0x01, 0xFE, 0x88, + 0x77, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00}; + + // Ref: https://docs.google.com/spreadsheets/d/1TTRx7INyDlsJBn9UwebL2Q4Q0S0apq0DlKP6bfrVPQw/edit#gid=0&range=A2:B2 + uint16_t rawData[853] = { + // On Auto Cool 23 + 29784, 49290, 3416, 1604, 464, 1210, 468, 372, 460, 374, 462, 374, 466, + 368, 464, 372, 462, 374, 464, 374, 464, 368, 464, 370, 464, 370, 466, 370, + 464, 1208, 464, 374, 462, 372, 466, 374, 464, 370, 462, 372, 464, 370, + 466, 370, 464, 372, 462, 374, 462, 374, 462, 378, 460, 370, 460, 374, 464, + 372, 462, 372, 464, 374, 466, 368, 464, 1210, 464, 374, 466, 1202, 464, + 1206, 464, 1210, 466, 1206, 468, 1204, 464, 1210, 466, 370, 462, 1214, + 460, 1208, 464, 1206, 464, 1208, 466, 1208, 464, 1206, 466, 1208, 464, + 1206, 466, 1212, 464, 370, 464, 370, 462, 374, 462, 374, 462, 374, 462, + 374, 462, 372, 464, 376, 460, 372, 462, 374, 466, 1204, 464, 1210, 464, + 372, 460, 374, 462, 1208, 464, 1212, 464, 1202, 468, 1204, 464, 374, 460, + 374, 466, 1208, 462, 1210, 462, 374, 462, 376, 464, 368, 466, 1204, 462, + 374, 466, 372, 464, 1206, 462, 376, 460, 376, 464, 1210, 462, 1208, 462, + 372, 466, 1206, 464, 1208, 466, 372, 462, 1210, 462, 1210, 466, 374, 468, + 1202, 464, 1206, 466, 374, 462, 372, 464, 1208, 464, 374, 464, 372, 464, + 376, 462, 370, 466, 368, 464, 1208, 462, 1210, 460, 374, 464, 1208, 466, + 1206, 464, 1214, 464, 368, 462, 374, 462, 1212, 460, 1210, 466, 1206, 466, + 370, 462, 1210, 464, 416, 424, 1202, 466, 1220, 448, 376, 464, 372, 462, + 372, 462, 1212, 462, 374, 460, 1214, 468, 364, 468, 370, 462, 372, 462, + 376, 458, 374, 464, 372, 462, 376, 464, 376, 462, 1204, 464, 1210, 462, + 1210, 464, 1208, 466, 1208, 464, 1206, 462, 1210, 464, 1212, 464, 368, + 462, 372, 464, 372, 464, 372, 464, 372, 466, 370, 466, 370, 464, 376, + 464, 1202, 464, 1212, 464, 1204, 464, 1210, 462, 1208, 464, 1212, 462, + 1210, 464, 1212, 460, 372, 462, 374, 462, 374, 466, 370, 462, 374, 462, + 372, 464, 372, 462, 376, 462, 1206, 464, 1206, 466, 1210, 462, 1208, 464, + 1210, 466, 1204, 464, 1210, 462, 1214, 462, 368, 462, 374, 466, 370, 462, + 376, 466, 368, 466, 370, 462, 414, 424, 374, 464, 1206, 464, 1206, 464, + 1206, 468, 1206, 466, 1206, 466, 1210, 462, 1206, 464, 1214, 468, 364, + 466, 372, 466, 370, 462, 372, 462, 374, 464, 372, 462, 374, 460, 376, 466, + 1204, 464, 1208, 462, 1210, 464, 1206, 464, 1210, 464, 1208, 464, 1208, + 466, 1210, 462, 1206, 466, 1206, 466, 372, 462, 374, 466, 1206, 466, 370, + 464, 1206, 466, 376, 464, 368, 462, 372, 466, 1206, 464, 1206, 464, 374, + 466, 1204, 464, 374, 466, 1206, 466, 1204, 468, 368, 466, 370, 466, 370, + 462, 1212, 462, 1210, 462, 1210, 462, 1214, 464, 368, 464, 1206, 466, + 1206, 466, 1206, 464, 374, 464, 370, 466, 370, 462, 378, 466, 366, 464, + 372, 466, 368, 466, 370, 464, 370, 462, 372, 462, 374, 464, 374, 464, + 1202, 466, 1206, 462, 1208, 466, 1208, 466, 1208, 464, 1210, 462, 1206, + 464, 1212, 464, 368, 464, 372, 464, 370, 468, 368, 462, 376, 462, 372, + 466, 370, 464, 376, 462, 1206, 464, 1210, 462, 1212, 462, 1208, 464, 1208, + 462, 1212, 466, 1246, 424, 1212, 464, 368, 464, 372, 466, 370, 464, 372, + 462, 374, 464, 372, 464, 370, 462, 1212, 466, 1206, 462, 1206, 464, 1210, + 466, 1206, 462, 1208, 464, 1250, 422, 1208, 468, 372, 464, 1204, 466, + 1206, 466, 370, 462, 374, 462, 376, 460, 374, 466, 370, 462, 376, 464, + 368, 462, 376, 462, 1210, 462, 1208, 464, 1206, 466, 1206, 464, 1208, 468, + 1212, 460, 1206, 464, 372, 464, 372, 466, 370, 462, 374, 466, 370, 466, + 370, 466, 374, 464, 368, 462, 1210, 462, 1210, 464, 1210, 462, 1208, 462, + 1212, 464, 1206, 466, 1208, 466, 366, 464, 374, 460, 374, 462, 1208, 466, + 372, 462, 374, 462, 374, 464, 1212, 468, 1202, 464, 1208, 466, 1204, 464, + 376, 460, 1208, 468, 1208, 462, 1208, 464, 378, 460, 372, 460, 372, 462, + 376, 464, 372, 462, 374, 460, 374, 464, 370, 462, 378, 464, 1202, 468, + 1204, 468, 1204, 466, 1208, 466, 1208, 464, 1210, 460, 1212, 462, 1212, + 464, 366, 466, 370, 464, 372, 466, 370, 464, 372, 462, 414, 424, 372, 466, + 372, 460, 1206, 466, 1206, 466, 1206, 466, 1208, 466, 1206, 464, 1208, + 466, 1208, 462, 1212, 468, 1202, 466, 1204, 470, 1204, 468, 1204, 466, + 1206, 466, 1206, 464, 1210, 462, 1212, 468, 366, 464, 372, 462, 374, 460, + 374, 460, 374, 466, 410, 424, 372, 460, 378, 466, 1200, 464, 1212, 462, + 1210, 464, 1210, 466, 1206, 462, 1208, 464, 1210, 464, 1210, 464, 366, + 462, 376, 462, 374, 460, 376, 462, 372, 466, 374, 460, 372, 462, 378, 462, + 1202, 468, 1206, 464, 1208, 466, 1208, 462, 1208, 464, 1208, 468, 1204, + 464, 1212, 466, 368, 462, 374, 466, 372, 464, 370, 462, 374, 464, 370, + 462, 376, 464, 374, 462, 1206, 464, 1208, 462, 1210, 466, 1208, 460, 1210, + 468, 1206, 462, 1210, 464, 1212, 466, 366, 464, 374, 462, 372, 466, 370, + 462, 374, 464, 372, 464, 370, 464, 374, 462}; + + irsend.reset(); + irsend.sendRaw(rawData, 853, kHitachiAcFreq); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC424, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAc424Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expected, irsend.capture.state, kHitachiAc424Bits); + IRHitachiAc ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 3 (Cool), Temp: 23C, Fan: 5 (Auto)", + IRAcUtils::resultAcToString(&irsend.capture)); +} + +TEST(TestDecodeHitachiAc424, SyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t expected[kHitachiAc424StateLength] = { + 0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xCC, 0x33, 0x92, + 0x6D, 0x13, 0xEC, 0x5C, 0xA3, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x53, 0xAC, 0xF1, 0x0E, 0x00, + 0xFF, 0x00, 0xFF, 0x80, 0x7F, 0x03, 0xFC, 0x01, 0xFE, 0x88, + 0x77, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00}; + + irsend.reset(); + irsend.sendHitachiAc424(expected); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HITACHI_AC424, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAc424Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); +} + +// Tests for IRHitachiAc424 class. +TEST(TestIRHitachiAc424Class, SetInvertedStates) { + IRHitachiAc424 ac(0); + + uint8_t raw[kHitachiAc424StateLength] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + uint8_t expected[kHitachiAc424StateLength] = { + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF}; + + ac.setRaw(raw); + EXPECT_STATE_EQ(expected, ac.getRaw(), kHitachiAc424Bits); +} + +TEST(TestIRHitachiAc424Class, SetAndGetPower) { + IRHitachiAc424 ac(0); + ac.on(); + EXPECT_TRUE(ac.getPower()); + ac.off(); + EXPECT_FALSE(ac.getPower()); + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestIRHitachiAc424Class, SetAndGetTemp) { + IRHitachiAc424 ac(0); + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + ac.setTemp(kHitachiAc424MinTemp); + EXPECT_EQ(kHitachiAc424MinTemp, ac.getTemp()); + ac.setTemp(kHitachiAc424MinTemp - 1); + EXPECT_EQ(kHitachiAc424MinTemp, ac.getTemp()); + ac.setTemp(kHitachiAc424MaxTemp); + EXPECT_EQ(kHitachiAc424MaxTemp, ac.getTemp()); + ac.setTemp(kHitachiAc424MaxTemp + 1); + EXPECT_EQ(kHitachiAc424MaxTemp, ac.getTemp()); +} + +TEST(TestIRHitachiAc424Class, SetAndGetMode) { + IRHitachiAc424 ac(0); + ac.setMode(kHitachiAc424Cool); + ac.setFan(kHitachiAc424FanAuto); + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + EXPECT_EQ(kHitachiAc424Cool, ac.getMode()); + EXPECT_EQ(kHitachiAc424FanAuto, ac.getFan()); + ac.setMode(kHitachiAc424Fan); + EXPECT_EQ(kHitachiAc424Fan, ac.getMode()); + EXPECT_EQ(27, ac.getTemp()); + EXPECT_NE(kHitachiAc424FanAuto, ac.getFan()); + ac.setMode(kHitachiAc424Heat); + EXPECT_EQ(25, ac.getTemp()); + EXPECT_EQ(kHitachiAc424Heat, ac.getMode()); + ac.setMode(kHitachiAc424Dry); + EXPECT_EQ(kHitachiAc424Dry, ac.getMode()); + EXPECT_NE(kHitachiAc424FanAuto, ac.getFan()); +} + +TEST(TestIRHitachiAc424Class, SetAndGetFan) { + IRHitachiAc424 ac(0); + ac.setMode(kHitachiAc424Cool); // All fan options are available in this mode. + ac.setFan(kHitachiAc424FanAuto); + EXPECT_EQ(kHitachiAc424FanAuto, ac.getFan()); + ac.setFan(kHitachiAc424FanLow); + EXPECT_EQ(kHitachiAc424FanLow, ac.getFan()); + ac.setFan(kHitachiAc424FanHigh); + EXPECT_EQ(kHitachiAc424FanHigh, ac.getFan()); + ac.setFan(kHitachiAc424FanMax + 1); + EXPECT_EQ(kHitachiAc424FanMax, ac.getFan()); + ac.setFan(kHitachiAc424FanMin - 1); + EXPECT_EQ(kHitachiAc424FanMin, ac.getFan()); + + ac.setFan(kHitachiAc424FanAuto); + ac.setMode(kHitachiAc424Fan); // No auto-fan in Fan mode. + EXPECT_EQ(kHitachiAc424FanMin, ac.getFan()); + ac.setFan(kHitachiAc424FanMax); + EXPECT_EQ(kHitachiAc424FanMax, ac.getFan()); + + // Only min, low and auto fan settings in Dry mode. + ac.setMode(kHitachiAc424Dry); + EXPECT_EQ(kHitachiAc424FanLow, ac.getFan()); + ac.setFan(kHitachiAc424FanHigh); + EXPECT_EQ(kHitachiAc424FanLow, ac.getFan()); + ac.setFan(kHitachiAc424FanMin); + EXPECT_EQ(kHitachiAc424FanMin, ac.getFan()); + ac.setFan(kHitachiAc424FanAuto); + EXPECT_EQ(kHitachiAc424FanAuto, ac.getFan()); + + // Check additional bytes set by min & max fan + ac.setMode(kHitachiAc424Cool); + ac.setFan(kHitachiAc424FanMax); + EXPECT_EQ(ac.getRaw()[9], 0xA9); + EXPECT_EQ(ac.getRaw()[29], 0x30); + ac.setFan(kHitachiAc424FanMin); + EXPECT_EQ(ac.getRaw()[9], 0x98); + EXPECT_EQ(ac.getRaw()[29], 0x00); + ac.setFan(kHitachiAc424FanLow); + EXPECT_EQ(ac.getRaw()[9], 0x92); + EXPECT_EQ(ac.getRaw()[29], 0x00); +} + +TEST(TestIRHitachiAc424Class, HumanReadable) { + IRHitachiAc424 ac(0); + + ac.setMode(kHitachiAc424Heat); + ac.setTemp(kHitachiAc424MaxTemp); + ac.on(); + ac.setFan(kHitachiAc424FanHigh); + EXPECT_EQ( + "Power: On, Mode: 6 (Heat), Temp: 32C, Fan: 4 (High)", + ac.toString()); + ac.setMode(kHitachiAc424Cool); + ac.setTemp(kHitachiAc424MinTemp); + ac.setFan(kHitachiAc424FanMin); + EXPECT_EQ( + "Power: On, Mode: 3 (Cool), Temp: 16C, Fan: 1 (Min)", + ac.toString()); +} + +TEST(TestIRHitachiAcClass424, toCommon) { + IRHitachiAc424 ac(0); + ac.setPower(true); + ac.setMode(kHitachiAc424Cool); + ac.setTemp(20); + ac.setFan(kHitachiAc424FanMax); + // Now test it. + ASSERT_EQ(decode_type_t::HITACHI_AC424, ac.toCommon().protocol); + ASSERT_EQ(-1, ac.toCommon().model); + ASSERT_TRUE(ac.toCommon().power); + ASSERT_TRUE(ac.toCommon().celsius); + ASSERT_EQ(20, ac.toCommon().degrees); + ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode); + ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed); + // TODO(jamsinclair): Add support. + ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv); + // Unsupported. + ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh); + ASSERT_FALSE(ac.toCommon().turbo); + ASSERT_FALSE(ac.toCommon().clean); + ASSERT_FALSE(ac.toCommon().light); + ASSERT_FALSE(ac.toCommon().quiet); + ASSERT_FALSE(ac.toCommon().econo); + ASSERT_FALSE(ac.toCommon().filter); + ASSERT_FALSE(ac.toCommon().beep); + ASSERT_EQ(-1, ac.toCommon().sleep); + ASSERT_EQ(-1, ac.toCommon().clock); +} diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Inax_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Inax_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Inax_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Inax_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_JVC_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_JVC_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_JVC_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_JVC_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Kelvinator_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Kelvinator_test.cpp old mode 100755 new mode 100644 similarity index 98% rename from lib/IRremoteESP8266-2.6.5/test/ir_Kelvinator_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Kelvinator_test.cpp index 436336c04..e01a585bd --- a/lib/IRremoteESP8266-2.6.5/test/ir_Kelvinator_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Kelvinator_test.cpp @@ -422,9 +422,9 @@ TEST(TestKelvinatorClass, HumanReadable) { IRKelvinatorAC irkelv(0); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Turbo: Off, " - "Quiet: Off, XFan: Off, IonFilter: Off, Light: Off, " - "Swing (Horizontal): Off, Swing (Vertical): Off", + "Power: Off, Mode: 0 (Auto), Temp: 16C, Fan: 0 (Auto), Turbo: Off, " + "Quiet: Off, XFan: Off, Ion: Off, Light: Off, " + "Swing(H): Off, Swing(V): Off", irkelv.toString()); irkelv.on(); irkelv.setMode(kKelvinatorCool); @@ -435,9 +435,9 @@ TEST(TestKelvinatorClass, HumanReadable) { irkelv.setLight(true); irkelv.setSwingHorizontal(true); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 25C, Fan: 5 (High), Turbo: Off, " - "Quiet: Off, XFan: On, IonFilter: On, Light: On, " - "Swing (Horizontal): On, Swing (Vertical): Off", + "Power: On, Mode: 1 (Cool), Temp: 25C, Fan: 5 (High), Turbo: Off, " + "Quiet: Off, XFan: On, Ion: On, Light: On, " + "Swing(H): On, Swing(V): Off", irkelv.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_LG_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_LG_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_LG_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_LG_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Lasertag_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Lasertag_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Lasertag_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Lasertag_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Lego_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Lego_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Lego_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Lego_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Lutron_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Lutron_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Lutron_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Lutron_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_MWM_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_MWM_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_MWM_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_MWM_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Magiquest_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Magiquest_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Magiquest_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Magiquest_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Midea_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Midea_test.cpp old mode 100755 new mode 100644 similarity index 94% rename from lib/IRremoteESP8266-2.6.5/test/ir_Midea_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Midea_test.cpp index 319528e9c..ebe291048 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Midea_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Midea_test.cpp @@ -445,7 +445,7 @@ TEST(TestMideaACClass, HumanReadableOutput) { ac.setRaw(0xA1826FFFFF62); EXPECT_EQ( - "Power: On, Mode: 2 (AUTO), Celsius: Off, Temp: 25C/77F, Fan: 0 (Auto), " + "Power: On, Mode: 2 (Auto), Celsius: Off, Temp: 25C/77F, Fan: 0 (Auto), " "Sleep: Off, Swing(V) Toggle: Off", ac.toString()); ac.off(); ac.setTemp(25, true); @@ -453,16 +453,16 @@ TEST(TestMideaACClass, HumanReadableOutput) { ac.setMode(kMideaACDry); ac.setSleep(true); EXPECT_EQ( - "Power: Off, Mode: 1 (DRY), Celsius: Off, Temp: 25C/77F, Fan: 3 (High), " + "Power: Off, Mode: 1 (Dry), Celsius: Off, Temp: 25C/77F, Fan: 3 (High), " "Sleep: On, Swing(V) Toggle: Off", ac.toString()); ac.setUseCelsius(true); EXPECT_EQ( - "Power: Off, Mode: 1 (DRY), Celsius: On, Temp: 25C/77F, Fan: 3 (High), " + "Power: Off, Mode: 1 (Dry), Celsius: On, Temp: 25C/77F, Fan: 3 (High), " "Sleep: On, Swing(V) Toggle: Off", ac.toString()); ac.setRaw(0xA19867FFFF7E); EXPECT_EQ( - "Power: On, Mode: 0 (COOL), Celsius: Off, Temp: 21C/69F, Fan: 3 (High), " + "Power: On, Mode: 0 (Cool), Celsius: Off, Temp: 21C/69F, Fan: 3 (High), " "Sleep: Off, Swing(V) Toggle: Off", ac.toString()); } @@ -705,13 +705,13 @@ TEST(TestMideaACClass, CelsiusRemoteTemp) { EXPECT_TRUE(ac.getUseCelsius()); EXPECT_EQ(on_cool_low_17c, ac.getRaw()); EXPECT_EQ( - "Power: On, Mode: 0 (COOL), Celsius: On, Temp: 17C/62F, Fan: 1 (Low), " + "Power: On, Mode: 0 (Cool), Celsius: On, Temp: 17C/62F, Fan: 1 (Low), " "Sleep: Off, Swing(V) Toggle: Off", ac.toString()); ac.setRaw(on_cool_low_17c); EXPECT_EQ(17, ac.getTemp(true)); EXPECT_EQ(62, ac.getTemp(false)); EXPECT_EQ( - "Power: On, Mode: 0 (COOL), Celsius: On, Temp: 17C/62F, Fan: 1 (Low), " + "Power: On, Mode: 0 (Cool), Celsius: On, Temp: 17C/62F, Fan: 1 (Low), " "Sleep: Off, Swing(V) Toggle: Off", ac.toString()); ac.setTemp(17, true); EXPECT_EQ(17, ac.getTemp(true)); @@ -720,7 +720,7 @@ TEST(TestMideaACClass, CelsiusRemoteTemp) { ac.setRaw(on_cool_low_30c); EXPECT_EQ( - "Power: On, Mode: 0 (COOL), Celsius: On, Temp: 30C/86F, Fan: 1 (Low), " + "Power: On, Mode: 0 (Cool), Celsius: On, Temp: 30C/86F, Fan: 1 (Low), " "Sleep: Off, Swing(V) Toggle: Off", ac.toString()); } @@ -732,13 +732,44 @@ TEST(TestMideaACClass, SwingV) { ac.setSwingVToggle(true); ASSERT_TRUE(ac.getSwingVToggle()); EXPECT_EQ( - "Power: On, Mode: 2 (AUTO), Celsius: Off, Temp: 25C/77F, Fan: 0 (Auto), " + "Power: On, Mode: 2 (Auto), Celsius: Off, Temp: 25C/77F, Fan: 0 (Auto), " "Sleep: Off, Swing(V) Toggle: On", ac.toString()); ac.setSwingVToggle(false); ASSERT_FALSE(ac.getSwingVToggle()); EXPECT_EQ( - "Power: On, Mode: 2 (AUTO), Celsius: Off, Temp: 25C/77F, Fan: 0 (Auto), " + "Power: On, Mode: 2 (Auto), Celsius: Off, Temp: 25C/77F, Fan: 0 (Auto), " "Sleep: Off, Swing(V) Toggle: Off", ac.toString()); ac.setRaw(kMideaACToggleSwingV); EXPECT_EQ("Swing(V) Toggle: On", ac.toString()); } + +// Test abusing the protocol for sending 6 arbitary bytes. +// See https://github.com/crankyoldgit/IRremoteESP8266/issues/887 +TEST(TestDecodeMidea, Issue887) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + irsend.reset(); + + uint64_t hwaddr = 0x1234567890AB; // 48bits doen't conform to Midea checksum + + irsend.sendMidea(hwaddr); + irsend.makeDecodeResult(); + + // Test normal operation, it shouldn't match. + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_NE(MIDEA, irsend.capture.decode_type); + irsend.reset(); + irsend.sendMidea(hwaddr); + irsend.makeDecodeResult(); + EXPECT_FALSE(irrecv.decodeMidea(&irsend.capture)); + + // Now test it with Midea's strict processing turned off! + irsend.reset(); + irsend.sendMidea(hwaddr); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, false)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(hwaddr, irsend.capture.value); +} diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_MitsubishiHeavy_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_MitsubishiHeavy_test.cpp old mode 100755 new mode 100644 similarity index 91% rename from lib/IRremoteESP8266-2.6.5/test/ir_MitsubishiHeavy_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_MitsubishiHeavy_test.cpp index 0af6b5d07..a8226feb8 --- a/lib/IRremoteESP8266-2.6.5/test/ir_MitsubishiHeavy_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_MitsubishiHeavy_test.cpp @@ -293,8 +293,8 @@ TEST(TestMitsubishiHeavy152AcClass, HumanReadable) { IRMitsubishiHeavy152Ac ac(0); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (Auto), " - "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Power: Off, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), " + "Swing(V): 0 (Auto), Swing(H): 0 (Auto), Silent: Off, Turbo: Off, " "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", ac.toString()); ac.on(); @@ -310,8 +310,8 @@ TEST(TestMitsubishiHeavy152AcClass, HumanReadable) { ac.setSwingVertical(kMitsubishiHeavy152SwingVAuto); ac.setSwingHorizontal(kMitsubishiHeavy152SwingHAuto); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 17C, Fan: 4 (Max), " - "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: On, Turbo: Off, " + "Power: On, Mode: 1 (Cool), Temp: 17C, Fan: 4 (Max), " + "Swing(V): 0 (Auto), Swing(H): 0 (Auto), Silent: On, Turbo: Off, " "Econo: Off, Night: On, Filter: On, 3D: On, Clean: Off", ac.toString()); @@ -327,8 +327,8 @@ TEST(TestMitsubishiHeavy152AcClass, HumanReadable) { ac.setSwingHorizontal(kMitsubishiHeavy152SwingHLeftMax); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 31C, Fan: 8 (Turbo), " - "Swing (V): 5 (Lowest), Swing (H): 1 (Max Left), Silent: Off, Turbo: On, " + "Power: On, Mode: 4 (Heat), Temp: 31C, Fan: 8 (Turbo), " + "Swing(V): 5 (Lowest), Swing(H): 1 (Max Left), Silent: Off, Turbo: On, " "Econo: Off, Night: Off, Filter: On, 3D: Off, Clean: Off", ac.toString()); @@ -338,8 +338,8 @@ TEST(TestMitsubishiHeavy152AcClass, HumanReadable) { ac.setSwingVertical(kMitsubishiHeavy152SwingVOff); EXPECT_EQ( - "Power: On, Mode: 0 (AUTO), Temp: 31C, Fan: 6 (Econo), " - "Swing (V): 6 (Off), Swing (H): 1 (Max Left), Silent: Off, " + "Power: On, Mode: 0 (Auto), Temp: 31C, Fan: 6 (Econo), " + "Swing(V): 6 (Off), Swing(H): 1 (Max Left), Silent: Off, " "Turbo: Off, Econo: On, Night: Off, Filter: On, 3D: Off, Clean: On", ac.toString()); @@ -349,8 +349,8 @@ TEST(TestMitsubishiHeavy152AcClass, HumanReadable) { ac.setMode(kMitsubishiHeavyDry); ac.setSwingHorizontal(kMitsubishiHeavy152SwingHLeftRight); EXPECT_EQ( - "Power: On, Mode: 2 (DRY), Temp: 25C, Fan: 0 (Auto), " - "Swing (V): 6 (Off), Swing (H): 7 (Left Right), Silent: Off, " + "Power: On, Mode: 2 (Dry), Temp: 25C, Fan: 0 (Auto), " + "Swing(V): 6 (Off), Swing(H): 7 (Left Right), Silent: Off, " "Turbo: Off, Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", ac.toString()); } @@ -359,8 +359,8 @@ TEST(TestMitsubishiHeavy152AcClass, ReconstructKnownExample) { IRMitsubishiHeavy152Ac ac(0); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (Auto), " - "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Power: Off, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), " + "Swing(V): 0 (Auto), Swing(H): 0 (Auto), Silent: Off, Turbo: Off, " "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", ac.toString()); ac.on(); @@ -377,8 +377,8 @@ TEST(TestMitsubishiHeavy152AcClass, ReconstructKnownExample) { ac.setSwingVertical(kMitsubishiHeavy152SwingVAuto); ac.setSwingHorizontal(kMitsubishiHeavy152SwingHAuto); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 24C, Fan: 4 (Max), " - "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Power: On, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), " + "Swing(V): 0 (Auto), Swing(H): 0 (Auto), Silent: Off, Turbo: Off, " "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", ac.toString()); @@ -572,10 +572,10 @@ TEST(TestMitsubishiHeavy88AcClass, VerticalSwing) { ac.setSwingVertical(kMitsubishiHeavy88SwingVOff); EXPECT_EQ(kMitsubishiHeavy88SwingVOff, ac.getSwingVertical()); - ac.setSwingVertical(kMitsubishiHeavy88SwingVHighest + 1); + ac.setSwingVertical(kMitsubishiHeavy88SwingVLowest + 1); EXPECT_EQ(kMitsubishiHeavy88SwingVOff, ac.getSwingVertical()); - ac.setSwingVertical(kMitsubishiHeavy88SwingVOff + 1); + ac.setSwingVertical(kMitsubishiHeavy88SwingVHigh + 1); EXPECT_EQ(kMitsubishiHeavy88SwingVOff, ac.getSwingVertical()); // Out of bounds. @@ -592,19 +592,19 @@ TEST(TestMitsubishiHeavy88AcClass, HorizontalSwing) { ac.setSwingHorizontal(kMitsubishiHeavy88SwingHLeftMax); EXPECT_EQ(kMitsubishiHeavy88SwingHLeftMax, ac.getSwingHorizontal()); - ac.setSwingHorizontal(kMitsubishiHeavy88SwingHLeftMax + 1); + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHRightMax + 1); EXPECT_EQ(kMitsubishiHeavy88SwingHOff, ac.getSwingHorizontal()); ac.setSwingHorizontal(kMitsubishiHeavy88SwingHRightMax); EXPECT_EQ(kMitsubishiHeavy88SwingHRightMax, ac.getSwingHorizontal()); - ac.setSwingHorizontal(kMitsubishiHeavy88SwingHRightMax - 1); + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHRightMax + 1); EXPECT_EQ(kMitsubishiHeavy88SwingHOff, ac.getSwingHorizontal()); ac.setSwingHorizontal(kMitsubishiHeavy88SwingHOff); EXPECT_EQ(kMitsubishiHeavy88SwingHOff, ac.getSwingHorizontal()); - ac.setSwingHorizontal(kMitsubishiHeavy88SwingHOff + 1); + ac.setSwingHorizontal(kMitsubishiHeavy88SwingH3D + 1); EXPECT_EQ(kMitsubishiHeavy88SwingHOff, ac.getSwingHorizontal()); // Out of bounds. @@ -635,8 +635,8 @@ TEST(TestMitsubishiHeavy88AcClass, HumanReadable) { IRMitsubishiHeavy88Ac ac(0); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (Auto), " - "Swing (V): 0 (Off), Swing (H): 0 (Off), " + "Power: Off, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), " + "Swing(V): 0 (Off), Swing(H): 0 (Off), " "Turbo: Off, Econo: Off, 3D: Off, Clean: Off", ac.toString()); ac.on(); @@ -648,8 +648,8 @@ TEST(TestMitsubishiHeavy88AcClass, HumanReadable) { ac.set3D(true); ac.setSwingVertical(kMitsubishiHeavy88SwingVAuto); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 17C, Fan: 4 (High), " - "Swing (V): 16 (Auto), Swing (H): 200 (3D), " + "Power: On, Mode: 1 (Cool), Temp: 17C, Fan: 4 (High), " + "Swing(V): 4 (Auto), Swing(H): 14 (3D), " "Turbo: Off, Econo: Off, 3D: On, Clean: Off", ac.toString()); @@ -662,8 +662,8 @@ TEST(TestMitsubishiHeavy88AcClass, HumanReadable) { ac.setSwingHorizontal(kMitsubishiHeavy88SwingHLeftMax); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 31C, Fan: 6 (Turbo), " - "Swing (V): 26 (Lowest), Swing (H): 4 (Max Left), Turbo: On, Econo: Off, " + "Power: On, Mode: 4 (Heat), Temp: 31C, Fan: 6 (Turbo), " + "Swing(V): 7 (Lowest), Swing(H): 1 (Max Left), Turbo: On, Econo: Off, " "3D: Off, Clean: Off", ac.toString()); @@ -673,8 +673,8 @@ TEST(TestMitsubishiHeavy88AcClass, HumanReadable) { ac.setSwingVertical(kMitsubishiHeavy88SwingVOff); EXPECT_EQ( - "Power: On, Mode: 0 (AUTO), Temp: 31C, Fan: 7 (Econo), " - "Swing (V): 0 (Off), Swing (H): 4 (Max Left), Turbo: Off, Econo: On, " + "Power: On, Mode: 0 (Auto), Temp: 31C, Fan: 7 (Econo), " + "Swing(V): 0 (Off), Swing(H): 1 (Max Left), Turbo: Off, Econo: On, " "3D: Off, Clean: On", ac.toString()); @@ -684,8 +684,8 @@ TEST(TestMitsubishiHeavy88AcClass, HumanReadable) { ac.setMode(kMitsubishiHeavyDry); ac.setSwingHorizontal(kMitsubishiHeavy88SwingHLeftRight); EXPECT_EQ( - "Power: On, Mode: 2 (DRY), Temp: 25C, Fan: 0 (Auto), " - "Swing (V): 0 (Off), Swing (H): 72 (Left Right), Turbo: Off, Econo: Off, " + "Power: On, Mode: 2 (Dry), Temp: 25C, Fan: 0 (Auto), " + "Swing(V): 0 (Off), Swing(H): 6 (Left Right), Turbo: Off, Econo: Off, " "3D: Off, Clean: Off", ac.toString()); } @@ -739,8 +739,8 @@ TEST(TestDecodeMitsubishiHeavy, ZmsRealExample) { EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 24C, Fan: 4 (Max), " - "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Power: On, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), " + "Swing(V): 0 (Auto), Swing(H): 0 (Auto), Silent: Off, Turbo: Off, " "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", ac.toString()); } @@ -766,8 +766,8 @@ TEST(TestDecodeMitsubishiHeavy, ZmsSyntheticExample) { EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 24C, Fan: 4 (Max), " - "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Power: On, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), " + "Swing(V): 0 (Auto), Swing(H): 0 (Auto), Silent: Off, Turbo: Off, " "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", ac.toString()); } @@ -819,8 +819,8 @@ TEST(TestDecodeMitsubishiHeavy, ZmsRealExample2) { EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: Off, Mode: 4 (HEAT), Temp: 24C, Fan: 4 (Max), " - "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Power: Off, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), " + "Swing(V): 0 (Auto), Swing(H): 0 (Auto), Silent: Off, Turbo: Off, " "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", ac.toString()); } @@ -844,8 +844,8 @@ TEST(TestDecodeMitsubishiHeavy, ZjsSyntheticExample) { EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 2 (DRY), Temp: 25C, Fan: 0 (Auto), " - "Swing (V): 0 (Off), Swing (H): 72 (Left Right), Turbo: Off, Econo: Off, " + "Power: On, Mode: 2 (Dry), Temp: 25C, Fan: 0 (Auto), " + "Swing(V): 0 (Off), Swing(H): 6 (Left Right), Turbo: Off, Econo: Off, " "3D: Off, Clean: Off", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Mitsubishi_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Mitsubishi_test.cpp old mode 100755 new mode 100644 similarity index 72% rename from lib/IRremoteESP8266-2.6.5/test/ir_Mitsubishi_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Mitsubishi_test.cpp index 7d16ed91e..8236777b5 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Mitsubishi_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Mitsubishi_test.cpp @@ -1,7 +1,9 @@ -// Copyright 2017 David Conran +// Copyright 2017-2019 David Conran +// Copyright 2019 kuchel77 // Copyright 2018 denxhun #include "ir_Mitsubishi.h" +#include "IRac.h" #include "IRrecv_test.h" #include "IRsend.h" #include "IRsend_test.h" @@ -984,8 +986,9 @@ TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatNeededButError) { TEST(TestMitsubishiACClass, HumanReadable) { IRMitsubishiAC irMitsu(0); EXPECT_EQ( - "Power: On, Mode: 8 (HEAT), Temp: 22C, Fan: 6 (Quiet), Vane: AUTO, " - "Wide Vane: 3, Time: 17:10, On timer: 00:00, Off timer: 00:00, Timer: -", + "Power: On, Mode: 1 (Heat), Temp: 22C, Fan: 6 (Quiet), " + "Swing(V): 0 (Auto), Swing(H): 3 (UNKNOWN), " + "Clock: 17:10, On Timer: 00:00, Off Timer: 00:00, Timer: -", irMitsu.toString()); } @@ -1163,3 +1166,559 @@ TEST(TestMitsubishiACClass, toCommon) { ASSERT_EQ(-1, ac.toCommon().sleep); ASSERT_EQ(-1, ac.toCommon().clock); } + +// Decode a 'real' example. +// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/888 +TEST(TestDecodeMitsubishi136, DecodeRealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Mitsubishi Electric Ducted A/C - ON, 20C, Cooling, MaxFan. + uint16_t rawData[275] = { + 3324, 1474, 520, 1110, 492, 1110, 524, 314, 498, 318, 466, 336, 474, 1124, + 514, 322, 464, 338, 472, 1124, 516, 1112, 482, 342, 480, 1118, 488, 338, + 466, 344, 480, 1124, 480, 1124, 510, 328, 484, 1114, 480, 1132, 510, 330, + 456, 344, 464, 1134, 506, 334, 452, 346, 462, 1136, 504, 336, 450, 348, + 460, 350, 472, 338, 474, 1124, 472, 352, 472, 340, 474, 342, 446, 354, + 454, 354, 468, 344, 470, 344, 442, 356, 450, 358, 466, 346, 466, 348, 440, + 360, 448, 360, 462, 350, 464, 352, 438, 360, 434, 1162, 490, 350, 438, + 1148, 486, 350, 464, 352, 436, 362, 432, 376, 462, 352, 462, 1138, 448, + 376, 460, 1142, 462, 1150, 484, 1140, 462, 360, 446, 1152, 492, 1132, 460, + 362, 466, 348, 466, 348, 438, 360, 446, 1152, 492, 348, 436, 360, 434, + 374, 462, 350, 464, 350, 436, 362, 434, 376, 460, 352, 462, 352, 434, 364, + 432, 378, 458, 354, 460, 356, 434, 364, 430, 380, 456, 356, 458, 356, 432, + 366, 428, 382, 454, 358, 456, 358, 430, 1158, 476, 1146, 458, 1156, 478, + 1150, 454, 1154, 480, 1142, 460, 362, 434, 1164, 488, 352, 436, 1148, 488, + 1140, 462, 1144, 490, 1136, 466, 1142, 492, 346, 466, 1132, 462, 360, 466, + 348, 466, 350, 438, 1152, 482, 348, 464, 350, 438, 1144, 490, 1142, 462, + 1148, 486, 1138, 466, 354, 450, 1146, 496, 1132, 460, 1150, 494, 1130, + 464, 1146, 498, 1130, 464, 1144, 498, 1130, 462, 1144, 500, 1126, 468, + 1142, 502, 1122, 470, 1142, 502, 1130, 464, 1140, 504, 1124, 468, 1140, + 504, 1122, 472, 1142, 502, 1122, 472, 1138, 506}; // UNKNOWN 66B4490E + + irsend.sendRaw(rawData, 275, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(MITSUBISHI136, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishi136Bits, irsend.capture.bits); + uint8_t expected[kMitsubishi136StateLength] = { + 0x23, 0xCB, 0x26, 0x21, 0x00, 0x40, 0x41, 0x37, 0x04, + 0x00, 0x00, 0xBF, 0xBE, 0xC8, 0xFB, 0xFF, 0xFF}; + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishi136Bits); + EXPECT_EQ( + "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 3 (High), " + "Swing(V): 3 (Highest), Quiet: Off", + IRAcUtils::resultAcToString(&irsend.capture)); +} + +// Self decode a synthetic example. +// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/888 +TEST(TestDecodeMitsubishi136, SyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Mitsubishi Electric Ducted A/C - ON, 20C, Cooling, MaxFan. + uint8_t expected[kMitsubishi136StateLength] = { + 0x23, 0xCB, 0x26, 0x21, 0x00, 0x40, 0x41, 0x37, 0x04, + 0x00, 0x00, 0xBF, 0xBE, 0xC8, 0xFB, 0xFF, 0xFF}; + + irsend.sendMitsubishi136(expected); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(MITSUBISHI136, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishi136Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishi136Bits); +} + +// General housekeeping +TEST(TestMitsubishi, Housekeeping) { + ASSERT_EQ("MITSUBISHI", typeToString(decode_type_t::MITSUBISHI)); + ASSERT_FALSE(hasACState(decode_type_t::MITSUBISHI)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::MITSUBISHI)); + + ASSERT_EQ("MITSUBISHI2", typeToString(decode_type_t::MITSUBISHI2)); + ASSERT_FALSE(hasACState(decode_type_t::MITSUBISHI2)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::MITSUBISHI2)); + + ASSERT_EQ("MITSUBISHI_AC", typeToString(decode_type_t::MITSUBISHI_AC)); + ASSERT_TRUE(hasACState(decode_type_t::MITSUBISHI_AC)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::MITSUBISHI_AC)); + + ASSERT_EQ("MITSUBISHI136", typeToString(decode_type_t::MITSUBISHI136)); + ASSERT_TRUE(hasACState(decode_type_t::MITSUBISHI136)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::MITSUBISHI136)); +} + +// Tests for IRMitsubishi136 class. + +TEST(TestMitsubishi136Class, Power) { + IRMitsubishi136 ac(0); + ac.begin(); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestMitsubishi136Class, Temperature) { + IRMitsubishi136 ac(0); + ac.begin(); + + ac.setTemp(0); + EXPECT_EQ(kMitsubishi136MinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kMitsubishi136MaxTemp, ac.getTemp()); + + ac.setTemp(kMitsubishi136MinTemp); + EXPECT_EQ(kMitsubishi136MinTemp, ac.getTemp()); + + ac.setTemp(kMitsubishi136MaxTemp); + EXPECT_EQ(kMitsubishi136MaxTemp, ac.getTemp()); + + ac.setTemp(kMitsubishi136MinTemp - 1); + EXPECT_EQ(kMitsubishi136MinTemp, ac.getTemp()); + + ac.setTemp(kMitsubishi136MaxTemp + 1); + EXPECT_EQ(kMitsubishi136MaxTemp, ac.getTemp()); + + ac.setTemp(19); + EXPECT_EQ(19, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + + ac.setTemp(29); + EXPECT_EQ(29, ac.getTemp()); +} + +TEST(TestMitsubishi136Class, OperatingMode) { + IRMitsubishi136 ac(0); + ac.begin(); + + ac.setMode(kMitsubishi136Auto); + EXPECT_EQ(kMitsubishi136Auto, ac.getMode()); + + ac.setMode(kMitsubishi136Fan); + EXPECT_EQ(kMitsubishi136Fan, ac.getMode()); + + ac.setMode(kMitsubishi136Cool); + EXPECT_EQ(kMitsubishi136Cool, ac.getMode()); + + ac.setMode(kMitsubishi136Heat); + EXPECT_EQ(kMitsubishi136Heat, ac.getMode()); + + ac.setMode(kMitsubishi136Dry); + EXPECT_EQ(kMitsubishi136Dry, ac.getMode()); + + ac.setMode(kMitsubishi136Dry + 1); + EXPECT_EQ(kMitsubishi136Auto, ac.getMode()); + + ac.setMode(255); + EXPECT_EQ(kMitsubishi136Auto, ac.getMode()); +} + +TEST(TestMitsubishi136Class, FanSpeed) { + IRMitsubishi136 ac(0); + ac.begin(); + + ac.setFan(kMitsubishi136FanMax); + EXPECT_EQ(kMitsubishi136FanMax, ac.getFan()); + + ac.setFan(kMitsubishi136FanMin); + EXPECT_EQ(kMitsubishi136FanMin, ac.getFan()); + + ac.setFan(255); + EXPECT_EQ(kMitsubishi136FanMax, ac.getFan()); + + ac.setFan(kMitsubishi136FanMed); + EXPECT_EQ(kMitsubishi136FanMed, ac.getFan()); + + ac.setFan(kMitsubishi136FanLow); + EXPECT_EQ(kMitsubishi136FanLow, ac.getFan()); + + ac.setFan(kMitsubishi136FanQuiet); + EXPECT_EQ(kMitsubishi136FanQuiet, ac.getFan()); +} + +TEST(TestMitsubishi136Class, Quiet) { + IRMitsubishi136 ac(0); + ac.begin(); + + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); + ac.setQuiet(false); + EXPECT_FALSE(ac.getQuiet()); + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); +} + +TEST(TestMitsubishi136Class, SwingV) { + IRMitsubishi136 ac(0); + ac.begin(); + + ac.setSwingV(kMitsubishi136SwingVAuto); + EXPECT_EQ(kMitsubishi136SwingVAuto, ac.getSwingV()); + + ac.setSwingV(kMitsubishi136SwingVAuto + 1); + EXPECT_EQ(kMitsubishi136SwingVAuto, ac.getSwingV()); + + ac.setSwingV(kMitsubishi136SwingVLowest); + EXPECT_EQ(kMitsubishi136SwingVLowest, ac.getSwingV()); + + ac.setSwingV(kMitsubishi136SwingVLow); + EXPECT_EQ(kMitsubishi136SwingVLow, ac.getSwingV()); + + ac.setSwingV(kMitsubishi136SwingVHighest); + EXPECT_EQ(kMitsubishi136SwingVHighest, ac.getSwingV()); + + ac.setSwingV(kMitsubishi136SwingVHigh); + EXPECT_EQ(kMitsubishi136SwingVHigh, ac.getSwingV()); +} + +TEST(TestMitsubishi136Class, toCommon) { + IRMitsubishi136 ac(0); + ac.setPower(true); + ac.setMode(kMitsubishi136Dry); + ac.setTemp(22); + ac.setFan(kMitsubishi136FanQuiet); + ac.setSwingV(kMitsubishi136SwingVAuto); + // Now test it. + ASSERT_EQ(decode_type_t::MITSUBISHI136, ac.toCommon().protocol); + ASSERT_EQ(-1, ac.toCommon().model); + ASSERT_TRUE(ac.toCommon().power); + ASSERT_TRUE(ac.toCommon().celsius); + ASSERT_EQ(22, ac.toCommon().degrees); + ASSERT_EQ(stdAc::opmode_t::kDry, ac.toCommon().mode); + ASSERT_EQ(stdAc::fanspeed_t::kMin, ac.toCommon().fanspeed); + ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv); + ASSERT_TRUE(ac.toCommon().quiet); + // Unsupported. + ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh); + ASSERT_FALSE(ac.toCommon().turbo); + ASSERT_FALSE(ac.toCommon().clean); + ASSERT_FALSE(ac.toCommon().light); + ASSERT_FALSE(ac.toCommon().econo); + ASSERT_FALSE(ac.toCommon().filter); + ASSERT_FALSE(ac.toCommon().beep); + ASSERT_EQ(-1, ac.toCommon().sleep); + ASSERT_EQ(-1, ac.toCommon().clock); +} + +TEST(TestMitsubishi136Class, toCommonMode) { + ASSERT_EQ(stdAc::opmode_t::kCool, + IRMitsubishi136::toCommonMode(kMitsubishi136Cool)); + ASSERT_EQ(kMitsubishi136Cool, + IRMitsubishi136::convertMode(stdAc::opmode_t::kCool)); + ASSERT_EQ(stdAc::opmode_t::kDry, + IRMitsubishi136::toCommonMode(kMitsubishi136Dry)); + ASSERT_EQ(kMitsubishi136Dry, + IRMitsubishi136::convertMode(stdAc::opmode_t::kDry)); +} + +// https://github.com/crankyoldgit/IRremoteESP8266/issues/891#issuecomment-531484295 +TEST(TestDecodeMitsubishiAC, Issue891) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[583] = { + 3418, 1742, 386, 1342, 398, 1324, 366, 498, 342, 524, 384, 482, 366, 1354, + 340, 528, 366, 500, 396, 1328, 366, 1354, 340, 522, 340, 1384, 342, 528, + 366, 496, 340, 1382, 398, 1324, 386, 482, 338, 1386, 420, 1320, 340, 526, + 366, 500, 396, 1324, 398, 466, 384, 480, 340, 1382, 340, 530, 340, 526, + 380, 486, 366, 500, 384, 480, 424, 452, 398, 466, 380, 488, 366, 500, 396, + 470, 340, 526, 366, 496, 366, 502, 396, 468, 342, 522, 384, 482, 342, 530, + 386, 482, 340, 524, 396, 468, 366, 500, 382, 486, 366, 500, 366, 502, 396, + 468, 366, 502, 366, 1356, 340, 1380, 382, 484, 386, 482, 342, 526, 362, + 506, 340, 526, 338, 526, 340, 1388, 366, 500, 380, 486, 366, 500, 366, + 498, 380, 488, 416, 1308, 412, 1316, 368, 500, 384, 1338, 396, 1324, 382, + 488, 368, 498, 380, 488, 340, 524, 366, 502, 384, 480, 418, 452, 396, 468, + 340, 1382, 366, 498, 366, 500, 366, 496, 340, 528, 366, 506, 342, 528, + 340, 526, 340, 524, 412, 458, 340, 528, 366, 502, 340, 526, 338, 528, 396, + 466, 396, 466, 366, 496, 366, 500, 366, 502, 366, 498, 366, 500, 396, 470, + 396, 470, 386, 484, 366, 498, 382, 496, 396, 470, 368, 498, 366, 500, 396, + 474, 342, 524, 342, 524, 366, 500, 396, 470, 366, 502, 366, 498, 380, 488, + 340, 522, 412, 460, 396, 468, 396, 468, 366, 496, 340, 522, 366, 504, 396, + 466, 396, 470, 340, 526, 396, 468, 412, 470, 396, 470, 366, 502, 384, 482, + 366, 498, 418, 452, 424, 450, 366, 496, 342, 524, 340, 524, 366, 1356, + 396, 1326, 366, 496, 340, 1382, 396, 470, 366, 1356, 342, 526, 396, 1322, + 386, 17100, 3524, 1772, 366, 1358, 396, 1326, 364, 506, 366, 500, 384, + 482, 396, 1324, 340, 526, 340, 524, 342, 1380, 342, 1382, 342, 526, 338, + 1382, 386, 484, 428, 450, 364, 1356, 366, 1358, 366, 498, 412, 1312, 382, + 1346, 368, 500, 384, 482, 398, 1326, 366, 500, 396, 466, 412, 1314, 342, + 526, 380, 490, 340, 526, 384, 484, 396, 466, 366, 498, 340, 522, 342, 524, + 382, 488, 366, 494, 340, 524, 366, 496, 352, 520, 340, 522, 380, 486, 366, + 498, 340, 526, 340, 524, 382, 488, 366, 498, 396, 470, 342, 524, 340, 524, + 366, 500, 366, 498, 366, 498, 414, 1312, 366, 1354, 362, 508, 340, 524, + 340, 528, 422, 454, 422, 452, 396, 468, 384, 1340, 366, 502, 412, 460, + 426, 450, 396, 466, 382, 486, 366, 1358, 382, 1344, 414, 458, 366, 1356, + 382, 1342, 386, 482, 366, 494, 386, 482, 342, 524, 342, 524, 380, 484, + 366, 500, 384, 480, 428, 1306, 366, 502, 396, 472, 340, 526, 366, 496, + 420, 456, 380, 486, 366, 498, 366, 496, 398, 466, 340, 524, 382, 490, 366, + 494, 342, 524, 396, 466, 380, 490, 340, 524, 396, 470, 394, 478, 422, 452, + 396, 466, 362, 508, 396, 466, 396, 466, 364, 498, 340, 528, 412, 454, 342, + 522, 416, 450, 366, 498, 340, 530, 366, 498, 396, 466, 366, 500, 396, 468, + 340, 530, 366, 502, 412, 458, 396, 468, 384, 482, 366, 498, 340, 522, 380, + 488, 366, 498, 340, 528, 342, 534, 396, 472, 380, 484, 380, 486, 386, 484, + 342, 526, 396, 470, 366, 500, 396, 466, 366, 502, 412, 460, 426, 450, 396, + 468, 380, 1344, 340, 1380, 414, 460, 380, 1342, 386, 482, 366, 1354, 340, + 526, 340, 1386, 396}; // MITSUBISHI_AC + + irsend.sendRaw(rawData, 583, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(MITSUBISHI_AC, irsend.capture.decode_type); + ASSERT_EQ(kMitsubishiACBits, irsend.capture.bits); + uint8_t expected[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x00, 0x18, 0x08, 0x36, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB}; + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishiACBits); + IRMitsubishiAC ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: Off, Mode: 3 (Cool), Temp: 24C, Fan: 0 (Auto), " + "Swing(V): 0 (Auto), Swing(H): 3 (UNKNOWN), " + "Clock: 00:00, On Timer: 00:00, Off Timer: 00:00, Timer: -", + ac.toString()); +} + +// Tests for IRMitsubishi112 class. + +TEST(TestMitsubishi112Class, Power) { + IRMitsubishi112 ac(0); + ac.begin(); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestMitsubishi112Class, Temperature) { + IRMitsubishi112 ac(0); + ac.begin(); + + ac.setTemp(0); + EXPECT_EQ(kMitsubishi112MinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kMitsubishi112MaxTemp, ac.getTemp()); + + ac.setTemp(kMitsubishi112MinTemp); + EXPECT_EQ(kMitsubishi112MinTemp, ac.getTemp()); + + ac.setTemp(kMitsubishi112MaxTemp); + EXPECT_EQ(kMitsubishi112MaxTemp, ac.getTemp()); + + ac.setTemp(kMitsubishi112MinTemp - 1); + EXPECT_EQ(kMitsubishi112MinTemp, ac.getTemp()); + + ac.setTemp(kMitsubishi112MaxTemp + 1); + EXPECT_EQ(kMitsubishi112MaxTemp, ac.getTemp()); + + ac.setTemp(19); + EXPECT_EQ(19, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + + ac.setTemp(29); + EXPECT_EQ(29, ac.getTemp()); +} + +TEST(TestMitsubishi112Class, OperatingMode) { + IRMitsubishi112 ac(0); + ac.begin(); + + ac.setMode(kMitsubishi112Auto); + EXPECT_EQ(kMitsubishi112Auto, ac.getMode()); + + ac.setMode(kMitsubishi112Cool); + EXPECT_EQ(kMitsubishi112Cool, ac.getMode()); + + ac.setMode(kMitsubishi112Heat); + EXPECT_EQ(kMitsubishi112Heat, ac.getMode()); + + ac.setMode(kMitsubishi112Dry); + EXPECT_EQ(kMitsubishi112Dry, ac.getMode()); +} + +TEST(TestMitsubishi112Class, FanSpeed) { + IRMitsubishi112 ac(0); + ac.begin(); + + ac.setFan(kMitsubishi112FanMax); + EXPECT_EQ(kMitsubishi112FanMax, ac.getFan()); + + ac.setFan(kMitsubishi112FanMin); + EXPECT_EQ(kMitsubishi112FanMin, ac.getFan()); + + ac.setFan(255); + EXPECT_EQ(kMitsubishi112FanMax, ac.getFan()); + + ac.setFan(kMitsubishi112FanMed); + EXPECT_EQ(kMitsubishi112FanMed, ac.getFan()); + + ac.setFan(kMitsubishi112FanLow); + EXPECT_EQ(kMitsubishi112FanLow, ac.getFan()); + + ac.setFan(kMitsubishi112FanQuiet); + EXPECT_EQ(kMitsubishi112FanQuiet, ac.getFan()); +} + + +TEST(TestMitsubishi112Class, SwingV) { + IRMitsubishi112 ac(0); + ac.begin(); + + ac.setSwingV(kMitsubishi112SwingVAuto); + EXPECT_EQ(kMitsubishi112SwingVAuto, ac.getSwingV()); + + ac.setSwingV(kMitsubishi112SwingVAuto + 1); + EXPECT_EQ(kMitsubishi112SwingVAuto, ac.getSwingV()); + + ac.setSwingV(kMitsubishi112SwingVLowest); + EXPECT_EQ(kMitsubishi112SwingVLowest, ac.getSwingV()); + + ac.setSwingV(kMitsubishi112SwingVLow); + EXPECT_EQ(kMitsubishi112SwingVLow, ac.getSwingV()); + + ac.setSwingV(kMitsubishi112SwingVHighest); + EXPECT_EQ(kMitsubishi112SwingVHighest, ac.getSwingV()); + + ac.setSwingV(kMitsubishi112SwingVHigh); + EXPECT_EQ(kMitsubishi112SwingVHigh, ac.getSwingV()); +} + +TEST(TestMitsubishi112Class, toCommon) { + IRMitsubishi112 ac(0); + ac.setPower(true); + ac.setMode(kMitsubishi112Dry); + ac.setTemp(22); + ac.setFan(kMitsubishi112FanQuiet); + ac.setSwingV(kMitsubishi112SwingVAuto); + ac.setSwingH(kMitsubishi112SwingHAuto); + // Now test it. + ASSERT_EQ(decode_type_t::MITSUBISHI112, ac.toCommon().protocol); + ASSERT_EQ(-1, ac.toCommon().model); + ASSERT_TRUE(ac.toCommon().power); + ASSERT_TRUE(ac.toCommon().celsius); + ASSERT_EQ(22, ac.toCommon().degrees); + ASSERT_EQ(stdAc::opmode_t::kDry, ac.toCommon().mode); + ASSERT_EQ(stdAc::fanspeed_t::kMin, ac.toCommon().fanspeed); + ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv); + ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh); + ASSERT_TRUE(ac.toCommon().quiet); + // Unsupported. + ASSERT_FALSE(ac.toCommon().turbo); + ASSERT_FALSE(ac.toCommon().clean); + ASSERT_FALSE(ac.toCommon().light); + ASSERT_FALSE(ac.toCommon().econo); + ASSERT_FALSE(ac.toCommon().filter); + ASSERT_FALSE(ac.toCommon().beep); + ASSERT_EQ(-1, ac.toCommon().sleep); + ASSERT_EQ(-1, ac.toCommon().clock); +} + +TEST(TestMitsubishi112Class, toCommonMode) { + ASSERT_EQ(stdAc::opmode_t::kCool, + IRMitsubishi112::toCommonMode(kMitsubishi112Cool)); + ASSERT_EQ(kMitsubishi112Cool, + IRMitsubishi112::convertMode(stdAc::opmode_t::kCool)); + ASSERT_EQ(stdAc::opmode_t::kDry, + IRMitsubishi112::toCommonMode(kMitsubishi112Dry)); + ASSERT_EQ(kMitsubishi112Dry, + IRMitsubishi112::convertMode(stdAc::opmode_t::kDry)); +} + +// Decode a 'real' example. +TEST(TestDecodeMitsubishi112, DecodeRealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[227] = {3468, 1694, 464, 1248, 464, 1248, 466, 376, 468, + 422, 470, 380, 488, 1246, 464, 382, 462, 422, 470, 1248, 466, 1246, + 442, 420, 472, 1246, 466, 380, 488, 382, 486, 1248, 442, 1272, 440, + 422, 472, 1246, 464, 1248, 466, 378, 490, 382, 464, 1270, 466, 380, + 464, 420, 448, 1270, 440, 422, 472, 380, 488, 380, 490, 378, 490, + 376, 466, 424, 468, 386, 486, 380, 488, 382, 462, 422, 448, 422, + 448, 422, 472, 378, 464, 422, 472, 380, 488, 380, 490, 380, 486, + 1248, 466, 380, 488, 380, 490, 1246, 440, 424, 468, 382, 488, 1246, + 466, 1246, 466, 380, 490, 380, 464, 422, 472, 380, 464, 422, 472, + 380, 464, 424, 472, 376, 466, 422, 448, 1270, 444, 420, 448, 420, + 470, 384, 486, 380, 490, 380, 486, 1248, 442, 422, 474, 1244, 464, + 1246, 466, 1246, 466, 384, 462, 422, 472, 378, 490, 382, 486, 384, + 462, 422, 470, 382, 488, 380, 464, 420, 448, 420, 448, 422, 470, + 380, 466, 420, 472, 378, 490, 380, 490, 378, 490, 378, 466, 422, + 446, 422, 446, 422, 446, 422, 472, 378, 488, 380, 490, 380, 466, + 420, 472, 380, 490, 380, 486, 384, 462, 422, 472, 378, 466, 1270, + 466, 1246, 442, 422, 470, 380, 488, 384, 486, 1246, 466, 1246, 442, + 1270, 440, 420, 472, 1248, 466, 384, 462, 1270, 440}; // MITSUBISHI112 + + irsend.sendRaw(rawData, 227, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(MITSUBISHI112, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishi112Bits, irsend.capture.bits); + uint8_t expected[kMitsubishi112StateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, 0x08, 0x3A, 0x00, + 0x00, 0x00, 0x30, 0xAE}; + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishi112Bits); + EXPECT_EQ( + "Power: On, Mode: 3 (Cool), Temp: 23C, Fan: 2 (Quiet), " + "Swing(V): 7 (Auto), Swing(H): 12 (Auto), Quiet: On", + IRAcUtils::resultAcToString(&irsend.capture)); +} + +// Self decode a synthetic example. +TEST(TestDecodeMitsubishi112, SyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint8_t expected[kMitsubishi112StateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, 0x08, 0x3A, + 0x00, 0x00, 0x00, 0x30, 0xAE}; + + irsend.sendMitsubishi112(expected); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(MITSUBISHI112, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishi112Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishi112Bits); +} diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_NEC_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_NEC_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_NEC_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_NEC_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Neoclima_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Neoclima_test.cpp old mode 100755 new mode 100644 similarity index 99% rename from lib/IRremoteESP8266-2.6.5/test/ir_Neoclima_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Neoclima_test.cpp index 38747f276..c743e7ba5 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Neoclima_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Neoclima_test.cpp @@ -79,7 +79,7 @@ TEST(TestDecodeNeoclima, RealExample) { IRNeoclimaAc ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 26C, Fan: 3 (Low), " + "Power: On, Mode: 1 (Cool), Temp: 26C, Fan: 3 (Low), " "Swing(V): Off, Swing(H): On, Sleep: Off, Turbo: Off, Hold: Off, " "Ion: Off, Eye: Off, Light: Off, Follow: Off, 8C Heat: Off, Fresh: Off, " "Button: 0 (Power)", diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Nikai_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Nikai_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Nikai_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Nikai_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Panasonic_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Panasonic_test.cpp old mode 100755 new mode 100644 similarity index 94% rename from lib/IRremoteESP8266-2.6.5/test/ir_Panasonic_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Panasonic_test.cpp index 7f84c2a8a..471a324c8 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Panasonic_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Panasonic_test.cpp @@ -647,15 +647,17 @@ TEST(TestIRPanasonicAcClass, SetAndGetFan) { pana.setFan(kPanasonicAcFanMin); EXPECT_EQ(kPanasonicAcFanMin, pana.getFan()); pana.setFan(kPanasonicAcFanMin - 1); - EXPECT_EQ(kPanasonicAcFanMin, pana.getFan()); + EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan()); + pana.setFan(kPanasonicAcFanMed); + EXPECT_EQ(kPanasonicAcFanMed, pana.getFan()); pana.setFan(kPanasonicAcFanMin + 1); - EXPECT_EQ(kPanasonicAcFanMin + 1, pana.getFan()); + EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan()); pana.setFan(kPanasonicAcFanMax); EXPECT_EQ(kPanasonicAcFanMax, pana.getFan()); pana.setFan(kPanasonicAcFanMax + 1); - EXPECT_EQ(kPanasonicAcFanMax, pana.getFan()); + EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan()); pana.setFan(kPanasonicAcFanMax - 1); - EXPECT_EQ(kPanasonicAcFanMax - 1, pana.getFan()); + EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan()); } TEST(TestIRPanasonicAcClass, SetAndGetSwings) { @@ -665,19 +667,19 @@ TEST(TestIRPanasonicAcClass, SetAndGetSwings) { pana.setSwingVertical(kPanasonicAcSwingVAuto); EXPECT_EQ(kPanasonicAcSwingVAuto, pana.getSwingVertical()); - pana.setSwingVertical(kPanasonicAcSwingVUp); - EXPECT_EQ(kPanasonicAcSwingVUp, pana.getSwingVertical()); - pana.setSwingVertical(kPanasonicAcSwingVUp - 1); - EXPECT_EQ(kPanasonicAcSwingVUp, pana.getSwingVertical()); - pana.setSwingVertical(kPanasonicAcSwingVUp + 1); - EXPECT_EQ(kPanasonicAcSwingVUp + 1, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVHighest); + EXPECT_EQ(kPanasonicAcSwingVHighest, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVHighest - 1); + EXPECT_EQ(kPanasonicAcSwingVHighest, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVHighest + 1); + EXPECT_EQ(kPanasonicAcSwingVHighest + 1, pana.getSwingVertical()); - pana.setSwingVertical(kPanasonicAcSwingVDown); - EXPECT_EQ(kPanasonicAcSwingVDown, pana.getSwingVertical()); - pana.setSwingVertical(kPanasonicAcSwingVDown + 1); - EXPECT_EQ(kPanasonicAcSwingVDown, pana.getSwingVertical()); - pana.setSwingVertical(kPanasonicAcSwingVDown - 1); - EXPECT_EQ(kPanasonicAcSwingVDown - 1, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVLowest); + EXPECT_EQ(kPanasonicAcSwingVLowest, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVLowest + 1); + EXPECT_EQ(kPanasonicAcSwingVLowest, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVLowest - 1); + EXPECT_EQ(kPanasonicAcSwingVLowest - 1, pana.getSwingVertical()); pana.setSwingVertical(kPanasonicAcSwingVAuto); EXPECT_EQ(kPanasonicAcSwingVAuto, pana.getSwingVertical()); @@ -737,8 +739,8 @@ TEST(TestIRPanasonicAcClass, QuietAndPowerful) { TEST(TestIRPanasonicAcClass, HumanReadable) { IRPanasonicAc pana(0); EXPECT_EQ( - "Model: 4 (JKE), Power: Off, Mode: 0 (AUTO), Temp: 0C, " - "Fan: 253 (UNKNOWN), Swing (Vertical): 0 (UNKNOWN), Quiet: Off, " + "Model: 4 (JKE), Power: Off, Mode: 0 (Auto), Temp: 0C, " + "Fan: 253 (UNKNOWN), Swing(V): 0 (UNKNOWN), Quiet: Off, " "Powerful: Off, Clock: 00:00, On Timer: Off, Off Timer: Off", pana.toString()); pana.setPower(true); @@ -748,24 +750,24 @@ TEST(TestIRPanasonicAcClass, HumanReadable) { pana.setSwingVertical(kPanasonicAcSwingVAuto); pana.setPowerful(true); EXPECT_EQ( - "Model: 4 (JKE), Power: On, Mode: 4 (HEAT), Temp: 30C, " - "Fan: 4 (High), Swing (Vertical): 15 (AUTO), Quiet: Off, " + "Model: 4 (JKE), Power: On, Mode: 4 (Heat), Temp: 30C, " + "Fan: 4 (High), Swing(V): 15 (Auto), Quiet: Off, " "Powerful: On, Clock: 00:00, On Timer: Off, Off Timer: Off", pana.toString()); pana.setQuiet(true); pana.setModel(kPanasonicLke); EXPECT_EQ( - "Model: 1 (LKE), Power: Off, Mode: 4 (HEAT), Temp: 30C, " - "Fan: 4 (High), Swing (Vertical): 15 (AUTO), " - "Swing (Horizontal): 6 (Middle), Quiet: On, Powerful: Off, " + "Model: 1 (LKE), Power: Off, Mode: 4 (Heat), Temp: 30C, " + "Fan: 4 (High), Swing(V): 15 (Auto), " + "Swing(H): 6 (Middle), Quiet: On, Powerful: Off, " "Clock: 00:00, On Timer: 00:00, Off Timer: Off", pana.toString()); pana.setModel(kPanasonicDke); pana.setSwingHorizontal(kPanasonicAcSwingHRight); EXPECT_EQ( - "Model: 3 (DKE), Power: Off, Mode: 4 (HEAT), Temp: 30C, " - "Fan: 4 (High), Swing (Vertical): 15 (AUTO), " - "Swing (Horizontal): 11 (Right), Quiet: On, Powerful: Off, " + "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, " "Clock: 00:00, On Timer: Off, Off Timer: Off", pana.toString()); } @@ -856,8 +858,8 @@ TEST(TestDecodePanasonicAC, SyntheticExample) { IRPanasonicAc pana(0); pana.setRaw(irsend.capture.state); EXPECT_EQ( - "Model: 4 (JKE), Power: Off, Mode: 3 (COOL), Temp: 25C, " - "Fan: 7 (Auto), Swing (Vertical): 15 (AUTO), Quiet: Off, " + "Model: 4 (JKE), Power: Off, Mode: 3 (Cool), Temp: 25C, " + "Fan: 7 (Auto), Swing(V): 15 (Auto), Quiet: Off, " "Powerful: Off, Clock: 00:00, On Timer: Off, Off Timer: Off", pana.toString()); } @@ -935,9 +937,9 @@ TEST(TestDecodePanasonicAC, Issue540) { pana.setRaw(irsend.capture.state); // TODO(crankyoldgit): Try to figure out what model this should be. EXPECT_EQ( - "Model: 0 (UNKNOWN), Power: On, Mode: 3 (COOL), Temp: 26C, " - "Fan: 7 (Auto), Swing (Vertical): 15 (AUTO), " - "Swing (Horizontal): 13 (AUTO), Quiet: Off, Powerful: Off, " + "Model: 0 (UNKNOWN), Power: On, Mode: 3 (Cool), Temp: 26C, " + "Fan: 7 (Auto), Swing(V): 15 (Auto), " + "Swing(H): 13 (Auto), Quiet: Off, Powerful: Off, " "Clock: 00:00, On Timer: Off, Off Timer: Off", pana.toString()); } @@ -1115,8 +1117,8 @@ TEST(TestDecodePanasonicAC, CkpModelSpecifics) { IRPanasonicAc pana(0); pana.setRaw(irsend.capture.state); EXPECT_EQ( - "Model: 5 (CKP), Power: Off, Mode: 4 (HEAT), Temp: 23C, " - "Fan: 7 (Auto), Swing (Vertical): 15 (AUTO), Quiet: Off, " + "Model: 5 (CKP), Power: Off, Mode: 4 (Heat), Temp: 23C, " + "Fan: 7 (Auto), Swing(V): 15 (Auto), Quiet: Off, " "Powerful: On, Clock: 00:00, On Timer: 00:00, Off Timer: 00:00", pana.toString()); @@ -1164,4 +1166,17 @@ TEST(TestIRPanasonicAcClass, toCommon) { ASSERT_FALSE(ac.toCommon().beep); ASSERT_EQ(-1, ac.toCommon().sleep); ASSERT_EQ(-1, ac.toCommon().clock); + + // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/921#issuecomment-532267240 + ac.setSwingVertical(kPanasonicAcSwingVLow); + ASSERT_EQ(stdAc::swingv_t::kLow, ac.toCommon().swingv); + // Real data. + uint8_t swingVMiddle[27] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, 0x20, 0xE0, 0x04, + 0x00, 0x39, 0x32, 0x80, 0x73, 0x00, 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x89, + 0x00, 0x00, 0xDB}; + ac.setRaw(swingVMiddle); + ASSERT_EQ(stdAc::swingv_t::kMiddle, ac.toCommon().swingv); + ASSERT_EQ(kPanasonicAcSwingVMiddle, + IRPanasonicAc::convertSwingV(stdAc::swingv_t::kMiddle)); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Pioneer_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Pioneer_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Pioneer_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Pioneer_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Pronto_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Pronto_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Pronto_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Pronto_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_RC5_RC6_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_RC5_RC6_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_RC5_RC6_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_RC5_RC6_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_RCMM_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_RCMM_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_RCMM_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_RCMM_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Samsung_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Samsung_test.cpp old mode 100755 new mode 100644 similarity index 96% rename from lib/IRremoteESP8266-2.6.5/test/ir_Samsung_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Samsung_test.cpp index b928350b6..9a572c631 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Samsung_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Samsung_test.cpp @@ -548,7 +548,7 @@ TEST(TestIRSamsungAcClass, SetAndGetPowerful) { EXPECT_TRUE(ac.getPowerful()); EXPECT_EQ(kSamsungAcFanTurbo, ac.getFan()); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 7 (Turbo), Swing: Off, " + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 7 (Turbo), Swing: Off, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: On", ac.toString()); uint8_t off[kSamsungAcStateLength] = { @@ -558,7 +558,7 @@ TEST(TestIRSamsungAcClass, SetAndGetPowerful) { EXPECT_FALSE(ac.getPowerful()); EXPECT_NE(kSamsungAcFanTurbo, ac.getFan()); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 0 (Auto), Swing: Off, " + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", ac.toString()); } @@ -623,7 +623,7 @@ TEST(TestIRSamsungAcClass, ChecksumCalculation) { TEST(TestIRSamsungAcClass, HumanReadable) { IRSamsungAc samsung(0); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 2 (Low), Swing: On, " + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 2 (Low), Swing: On, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", samsung.toString()); samsung.setTemp(kSamsungAcMaxTemp); @@ -634,18 +634,18 @@ TEST(TestIRSamsungAcClass, HumanReadable) { samsung.setBeep(true); samsung.setClean(true); EXPECT_EQ( - "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 5 (High), Swing: Off, " + "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 5 (High), Swing: Off, " "Beep: On, Clean: On, Quiet: Off, Powerful: Off", samsung.toString()); samsung.setQuiet(true); EXPECT_EQ( - "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 0 (Auto), Swing: Off, " + "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 0 (Auto), Swing: Off, " "Beep: On, Clean: On, Quiet: On, Powerful: Off", samsung.toString()); samsung.setQuiet(false); samsung.setPowerful(true); EXPECT_EQ( - "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 7 (Turbo), Swing: Off, " + "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 7 (Turbo), Swing: Off, " "Beep: On, Clean: On, Quiet: Off, Powerful: On", samsung.toString()); } @@ -749,7 +749,7 @@ TEST(TestDecodeSamsungAC, DecodeRealExample) { IRSamsungAc samsung(0); samsung.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 2 (Low), Swing: On, " + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 2 (Low), Swing: On, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", samsung.toString()); } @@ -798,7 +798,7 @@ TEST(TestDecodeSamsungAC, DecodeRealExample2) { IRSamsungAc samsung(0); samsung.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (Auto), Swing: Off, " + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", samsung.toString()); } @@ -857,7 +857,7 @@ TEST(TestDecodeSamsungAC, DecodePowerOnSample) { IRSamsungAc samsung(0); samsung.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (Auto), Swing: Off, " + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", samsung.toString()); } @@ -917,7 +917,7 @@ TEST(TestDecodeSamsungAC, DecodePowerOffSample) { IRSamsungAc samsung(0); samsung.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength); EXPECT_EQ( - "Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 0 (Auto), Swing: Off, " + "Power: Off, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", samsung.toString()); } @@ -964,7 +964,7 @@ TEST(TestDecodeSamsungAC, DecodeHeatSample) { IRSamsungAc samsung(0); samsung.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 17C, Fan: 0 (Auto), Swing: On, " + "Power: On, Mode: 4 (Heat), Temp: 17C, Fan: 0 (Auto), Swing: On, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", samsung.toString()); } @@ -1011,7 +1011,7 @@ TEST(TestDecodeSamsungAC, DecodeCoolSample) { IRSamsungAc samsung(0); samsung.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 0 (Auto), Swing: Off, " + "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 0 (Auto), Swing: Off, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", samsung.toString()); } @@ -1069,7 +1069,7 @@ TEST(TestDecodeSamsungAC, Issue604DecodeExtended) { IRSamsungAc samsung(0); samsung.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ( - "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 0 (Auto), Swing: Off, " + "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 0 (Auto), Swing: Off, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", samsung.toString()); } @@ -1212,6 +1212,7 @@ TEST(TestDecodeSamsung36, SyntheticExample) { TEST(TestIRSamsungAcClass, Issue604SendPowerHack) { IRSamsungAc ac(0); ac.begin(); + ac.stateReset(false); // Disable the initial forced sending of a power mesg. std::string freqduty = "f38000d50"; @@ -1264,7 +1265,7 @@ TEST(TestIRSamsungAcClass, Issue604SendPowerHack) { "m586s1432m586s436m586s436m586s1432m586s1432m586s436m586s436m586s436" "m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432" "m586s100000"; - std::string text = "Power: On, Mode: 1 (COOL), Temp: 23C, Fan: 4 (Medium), " + std::string text = "Power: On, Mode: 1 (Cool), Temp: 23C, Fan: 4 (Med), " "Swing: On, Beep: Off, Clean: Off, Quiet: Off, " "Powerful: Off"; // Don't do a setPower()/on()/off() as that will trigger the special message. @@ -1275,23 +1276,46 @@ TEST(TestIRSamsungAcClass, Issue604SendPowerHack) { ac.send(); EXPECT_EQ(text, ac.toString()); EXPECT_EQ(freqduty + settings, ac._irsend.outputStr()); - ac._irsend.reset(); + // Ensure the power state is changed by changing it and sending it. + ac.off(); + ac.send(); + ac._irsend.reset(); // Clear the capture buffer. // Now trigger a special power message by using a power method. ac.on(); ac.send(); // This should result in two messages. 1 x extended + 1 x normal. EXPECT_EQ(text, ac.toString()); EXPECT_EQ(freqduty + poweron + settings, ac._irsend.outputStr()); - ac._irsend.reset(); + ac._irsend.reset(); // Clear the capture buffer. // Subsequent sending should be just the "settings" message. ac.send(); EXPECT_EQ(text, ac.toString()); EXPECT_EQ(freqduty + settings, ac._irsend.outputStr()); - ac._irsend.reset(); - // Now trigger a special power message by using a power method (again). - ac.setPower(true); - ac.send(); // This should result in two messages. 1 x extended + 1 x normal. + ac._irsend.reset(); // Clear the capture buffer. + ac.setPower(true); // Note: The power state hasn't changed from previous. + ac.send(); // This should result in a normal setting message. + EXPECT_EQ(text, ac.toString()); + EXPECT_EQ(freqduty + settings, ac._irsend.outputStr()); + + ac._irsend.reset(); // Clear the capture buffer. + ac.setPower(false); + ac.setPower(true); // Note: The power state hasn't changed from the last sent + ac.send(); // This should result in a normal setting message. + EXPECT_EQ(text, ac.toString()); + EXPECT_EQ(freqduty + settings, ac._irsend.outputStr()); + + ac.stateReset(); // Normal `stateReset` defaults to send the power message + // on first send. + ac._irsend.reset(); // Clear the capture buffer. + ac.setTemp(23); + ac.setMode(kSamsungAcCool); + ac.setFan(kSamsungAcFanMed); + ac.send(); EXPECT_EQ(text, ac.toString()); EXPECT_EQ(freqduty + poweron + settings, ac._irsend.outputStr()); + ac._irsend.reset(); // Clear the capture buffer. + ac.send(); // Subsequent send() should just be a settings message. + EXPECT_EQ(text, ac.toString()); + EXPECT_EQ(freqduty + settings, ac._irsend.outputStr()); } TEST(TestIRSamsungAcClass, toCommon) { @@ -1367,7 +1391,7 @@ TEST(TestDecodeSamsungAC, Issue734QuietSetting) { IRSamsungAc ac(0); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 0 (Auto), Swing: Off, " + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " "Beep: Off, Clean: Off, Quiet: On, Powerful: Off", ac.toString()); @@ -1389,7 +1413,7 @@ TEST(TestDecodeSamsungAC, Issue734QuietSetting) { ac.setClean(false); ac.setQuiet(true); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 0 (Auto), Swing: Off, " + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " "Beep: Off, Clean: Off, Quiet: On, Powerful: Off", ac.toString()); // Check it matches the known good/expected state. @@ -1439,7 +1463,7 @@ TEST(TestDecodeSamsungAC, Issue734PowerfulOff) { IRSamsungAc ac(0); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 0 (Auto), Swing: Off, " + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Sanyo_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Sanyo_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Sanyo_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Sanyo_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Sharp_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Sharp_test.cpp old mode 100755 new mode 100644 similarity index 96% rename from lib/IRremoteESP8266-2.6.5/test/ir_Sharp_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Sharp_test.cpp index 2949580ed..571e59859 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Sharp_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Sharp_test.cpp @@ -402,7 +402,7 @@ TEST(TestDecodeSharpAc, RealExample) { IRSharpAc ac(0); ac.begin(); ac.setRaw(irsend.capture.state); - EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 27C, Fan: 2 (Auto)", + EXPECT_EQ("Power: On, Mode: 2 (Cool), Temp: 27C, Fan: 2 (Auto)", ac.toString()); } @@ -584,7 +584,7 @@ TEST(TestSharpAcClass, ReconstructKnownState) { ac.setTemp(kSharpAcMinTemp); ac.setFan(kSharpAcFanAuto); EXPECT_STATE_EQ(on_auto_auto, ac.getRaw(), kSharpAcBits); - EXPECT_EQ("Power: On, Mode: 0 (AUTO), Temp: 15C, Fan: 2 (Auto)", + EXPECT_EQ("Power: On, Mode: 0 (Auto), Temp: 15C, Fan: 2 (Auto)", ac.toString()); uint8_t cool_auto_28[kSharpAcStateLength] = { @@ -595,7 +595,7 @@ TEST(TestSharpAcClass, ReconstructKnownState) { ac.setMode(kSharpAcCool); ac.setTemp(28); ac.setFan(kSharpAcFanAuto); - EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 2 (Auto)", + EXPECT_EQ("Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 2 (Auto)", ac.toString()); EXPECT_STATE_EQ(cool_auto_28, ac.getRaw(), kSharpAcBits); } @@ -610,49 +610,49 @@ TEST(TestSharpAcClass, KnownStates) { 0x31}; ASSERT_TRUE(ac.validChecksum(off_auto_auto)); ac.setRaw(off_auto_auto); - EXPECT_EQ("Power: Off, Mode: 0 (AUTO), Temp: 15C, Fan: 2 (Auto)", + EXPECT_EQ("Power: Off, Mode: 0 (Auto), Temp: 15C, Fan: 2 (Auto)", ac.toString()); uint8_t on_auto_auto[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0x00, 0x11, 0x20, 0x00, 0x08, 0x80, 0x00, 0xE0, 0x01}; ASSERT_TRUE(ac.validChecksum(on_auto_auto)); ac.setRaw(on_auto_auto); - EXPECT_EQ("Power: On, Mode: 0 (AUTO), Temp: 15C, Fan: 2 (Auto)", + EXPECT_EQ("Power: On, Mode: 0 (Auto), Temp: 15C, Fan: 2 (Auto)", ac.toString()); uint8_t cool_auto_28[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x22, 0x00, 0x08, 0x80, 0x04, 0xE0, 0x51}; ASSERT_TRUE(ac.validChecksum(cool_auto_28)); ac.setRaw(cool_auto_28); - EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 2 (Auto)", + EXPECT_EQ("Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 2 (Auto)", ac.toString()); uint8_t cool_fan1_28[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x42, 0x00, 0x08, 0x80, 0x05, 0xE0, 0x21}; ASSERT_TRUE(ac.validChecksum(cool_fan1_28)); ac.setRaw(cool_fan1_28); - EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 4 (Low)", + EXPECT_EQ("Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 4 (Low)", ac.toString()); uint8_t cool_fan2_28[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x32, 0x00, 0x08, 0x80, 0x05, 0xE0, 0x51}; ASSERT_TRUE(ac.validChecksum(cool_fan2_28)); ac.setRaw(cool_fan2_28); - EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 3 (Medium)", + EXPECT_EQ("Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 3 (Medium)", ac.toString()); uint8_t cool_fan3_28[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x52, 0x00, 0x08, 0x80, 0x05, 0xE0, 0x31}; ASSERT_TRUE(ac.validChecksum(cool_fan3_28)); ac.setRaw(cool_fan3_28); - EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 5 (UNKNOWN)", + EXPECT_EQ("Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 5 (UNKNOWN)", ac.toString()); uint8_t cool_fan4_28[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x72, 0x00, 0x08, 0x80, 0x05, 0xE0, 0x11}; ASSERT_TRUE(ac.validChecksum(cool_fan4_28)); ac.setRaw(cool_fan4_28); - EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 7 (High)", + EXPECT_EQ("Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 7 (High)", ac.toString()); /* Unsupported / Not yet reverse engineered. uint8_t cool_fan4_28_ion_on[kSharpAcStateLength] = { @@ -660,21 +660,21 @@ TEST(TestSharpAcClass, KnownStates) { 0xD1}; ASSERT_TRUE(ac.validChecksum(cool_fan4_28_ion_on)); ac.setRaw(cool_fan4_28_ion_on); - EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 7 (MAX)", + EXPECT_EQ("Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 7 (Max)", ac.toString()); uint8_t cool_fan4_28_eco1[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x61, 0x72, 0x18, 0x08, 0x80, 0x00, 0xE8, 0x01}; ASSERT_TRUE(ac.validChecksum(cool_fan4_28_eco1)); ac.setRaw(cool_fan4_28_eco1); - EXPECT_EQ("Power: On, Mode: 2 (COOL), Temp: 28C, Fan: 7 (MAX)", + EXPECT_EQ("Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 7 (Max)", ac.toString()); */ uint8_t dry_auto[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0x00, 0x31, 0x23, 0x00, 0x08, 0x80, 0x00, 0xE0, 0x11}; ASSERT_TRUE(ac.validChecksum(dry_auto)); ac.setRaw(dry_auto); - EXPECT_EQ("Power: On, Mode: 3 (DRY), Temp: 15C, Fan: 2 (Auto)", + EXPECT_EQ("Power: On, Mode: 3 (Dry), Temp: 15C, Fan: 2 (Auto)", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Sherwood_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Sherwood_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Sherwood_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Sherwood_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Sony_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Sony_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Sony_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Sony_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Tcl_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Tcl_test.cpp old mode 100755 new mode 100644 similarity index 89% rename from lib/IRremoteESP8266-2.6.5/test/ir_Tcl_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Tcl_test.cpp index 8432cf9ac..99a9e7de7 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Tcl_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Tcl_test.cpp @@ -65,8 +65,8 @@ TEST(TestDecodeTcl112Ac, DecodeRealExample) { IRTcl112Ac ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 24C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: On, Mode: 3 (Cool), Temp: 24C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); } @@ -107,23 +107,23 @@ TEST(TestTcl112AcClass, Temperature) { IRTcl112Ac ac(0); ac.setRaw(temp16C); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 16C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: On, Mode: 3 (Cool), Temp: 16C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); ac.setRaw(temp16point5C); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 16.5C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: On, Mode: 3 (Cool), Temp: 16.5C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); ac.setRaw(temp19point5C); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 19.5C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: On, Mode: 3 (Cool), Temp: 19.5C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); ac.setRaw(temp31C); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 31C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: On, Mode: 3 (Cool), Temp: 31C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); ac.setTemp(kTcl112AcTempMin); @@ -203,8 +203,8 @@ TEST(TestTcl112AcClass, OperatingMode) { 0x07, 0x00, 0x00, 0x00, 0x00, 0x80, 0x48}; ac.setRaw(automode); EXPECT_EQ( - "Power: On, Mode: 8 (AUTO), Temp: 24C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: On, Mode: 8 (Auto), Temp: 24C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); } @@ -232,8 +232,8 @@ TEST(TestTcl112AcClass, Power) { 0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xCB}; ac.setRaw(on); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 16C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: On, Mode: 3 (Cool), Temp: 16C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); const uint8_t off[kTcl112AcStateLength] = { @@ -241,8 +241,8 @@ TEST(TestTcl112AcClass, Power) { 0x07, 0x40, 0x00, 0x00, 0x00, 0x80, 0xCB}; ac.setRaw(off); EXPECT_EQ( - "Power: Off, Mode: 3 (COOL), Temp: 24C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: Off, Mode: 3 (Cool), Temp: 24C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); } @@ -257,13 +257,13 @@ TEST(TestTcl112AcClass, Checksum) { EXPECT_EQ(0xCB, ac.calcChecksum(temp16C)); ac.setRaw(temp16C); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 16C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: On, Mode: 3 (Cool), Temp: 16C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); ac.setRaw(temp31C); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 31C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: On, Mode: 3 (Cool), Temp: 31C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); EXPECT_EQ(0xBC, ac.calcChecksum(temp31C)); @@ -456,7 +456,7 @@ TEST(TestDecodeTcl112Ac, Issue744) { IRTcl112Ac ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 3 (COOL), Temp: 23C, Fan: 0 (Auto), Econo: Off, " - "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + "Power: On, Mode: 3 (Cool), Temp: 23C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing(H): Off, Swing(V): Off", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Teco_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Teco_test.cpp old mode 100755 new mode 100644 similarity index 82% rename from lib/IRremoteESP8266-2.6.5/test/ir_Teco_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Teco_test.cpp index 4ed7fbd9f..cb6c8bcd9 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Teco_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Teco_test.cpp @@ -243,12 +243,45 @@ TEST(TestTecoACClass, Save) { EXPECT_TRUE(ac.getSave()); } +// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/882 +TEST(TestTecoACClass, Timer) { + IRTecoAc ac(0); + ac.begin(); + + ac.setTimer(60); + EXPECT_TRUE(ac.getTimerEnabled()); + EXPECT_EQ(60, ac.getTimer()); + ac.setTimer(0); + EXPECT_EQ(false, ac.getTimerEnabled()); + EXPECT_EQ(0, ac.getTimer()); + ac.setTimer(17 * 60 + 59); + EXPECT_TRUE(ac.getTimerEnabled()); + EXPECT_EQ(17 * 60 + 30, ac.getTimer()); + ac.setTimer(24 * 60 + 31); + EXPECT_TRUE(ac.getTimerEnabled()); + EXPECT_EQ(24 * 60, ac.getTimer()); + + // Data from: https://github.com/crankyoldgit/IRremoteESP8266/issues/882#issuecomment-527079339 + ac.setRaw(0x250218A49); // Timer On 1hr + EXPECT_TRUE(ac.getTimerEnabled()); + EXPECT_EQ(60, ac.getTimer()); + ac.setRaw(0x250219A49); // Timer On 1.5hr + EXPECT_TRUE(ac.getTimerEnabled()); + EXPECT_EQ(60 + 30, ac.getTimer()); + ac.setRaw(0x250200A49); // Timer Off + EXPECT_FALSE(ac.getTimerEnabled()); + EXPECT_EQ(0, ac.getTimer()); + ac.setRaw(0x25023DA41); // Timer On 23.5hrs + EXPECT_TRUE(ac.getTimerEnabled()); + EXPECT_EQ(23 * 60 + 30, ac.getTimer()); +} + TEST(TestTecoACClass, MessageConstuction) { IRTecoAc ac(0); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Sleep: Off, " - "Swing: Off, Light: Off, Humid: Off, Save: Off", + "Power: Off, Mode: 0 (Auto), Temp: 16C, Fan: 0 (Auto), Sleep: Off, " + "Swing: Off, Light: Off, Humid: Off, Save: Off, Timer: Off", ac.toString()); ac.setPower(true); ac.setMode(kTecoCool); @@ -257,34 +290,35 @@ TEST(TestTecoACClass, MessageConstuction) { ac.setSwing(false); ac.setLight(false); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), Sleep: Off, " - "Swing: Off, Light: Off, Humid: Off, Save: Off", + "Power: On, Mode: 1 (Cool), Temp: 21C, Fan: 3 (High), Sleep: Off, " + "Swing: Off, Light: Off, Humid: Off, Save: Off, Timer: Off", ac.toString()); ac.setSwing(true); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), Sleep: Off, " - "Swing: On, Light: Off, Humid: Off, Save: Off", + "Power: On, Mode: 1 (Cool), Temp: 21C, Fan: 3 (High), Sleep: Off, " + "Swing: On, Light: Off, Humid: Off, Save: Off, Timer: Off", ac.toString()); ac.setSwing(false); ac.setFan(kTecoFanLow); ac.setSleep(true); ac.setMode(kTecoHeat); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 1 (Low), Sleep: On, " - "Swing: Off, Light: Off, Humid: Off, Save: Off", + "Power: On, Mode: 4 (Heat), Temp: 21C, Fan: 1 (Low), Sleep: On, " + "Swing: Off, Light: Off, Humid: Off, Save: Off, Timer: Off", ac.toString()); ac.setSleep(false); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 1 (Low), Sleep: Off, " - "Swing: Off, Light: Off, Humid: Off, Save: Off", + "Power: On, Mode: 4 (Heat), Temp: 21C, Fan: 1 (Low), Sleep: Off, " + "Swing: Off, Light: Off, Humid: Off, Save: Off, Timer: Off", ac.toString()); ac.setTemp(25); ac.setLight(true); ac.setSave(true); ac.setHumid(true); + ac.setTimer(18 * 60 + 37); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 25C, Fan: 1 (Low), Sleep: Off, " - "Swing: Off, Light: On, Humid: On, Save: On", + "Power: On, Mode: 4 (Heat), Temp: 25C, Fan: 1 (Low), Sleep: Off, " + "Swing: Off, Light: On, Humid: On, Save: On, Timer: 18:30", ac.toString()); } @@ -301,8 +335,8 @@ TEST(TestTecoACClass, ReconstructKnownMessage) { ac.setSwing(true); EXPECT_EQ(expected, ac.getRaw()); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 27C, Fan: 0 (Auto), Sleep: On, " - "Swing: On, Light: Off, Humid: Off, Save: Off", + "Power: On, Mode: 1 (Cool), Temp: 27C, Fan: 0 (Auto), Sleep: On, " + "Swing: On, Light: Off, Humid: Off, Save: Off, Timer: Off", ac.toString()); } @@ -343,8 +377,8 @@ TEST(TestDecodeTeco, NormalDecodeWithStrict) { ac.begin(); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Sleep: Off, " - "Swing: Off, Light: Off, Humid: Off, Save: Off", + "Power: Off, Mode: 0 (Auto), Temp: 16C, Fan: 0 (Auto), Sleep: Off, " + "Swing: Off, Light: Off, Humid: Off, Save: Off, Timer: Off", ac.toString()); } @@ -376,8 +410,8 @@ TEST(TestDecodeTeco, RealNormalExample) { ac.begin(); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 27C, Fan: 0 (Auto), Sleep: On, " - "Swing: On, Light: Off, Humid: Off, Save: Off", + "Power: On, Mode: 1 (Cool), Temp: 27C, Fan: 0 (Auto), Sleep: On, " + "Swing: On, Light: Off, Humid: Off, Save: Off, Timer: Off", ac.toString()); uint16_t rawData2[73] = { @@ -401,8 +435,8 @@ TEST(TestDecodeTeco, RealNormalExample) { ac.begin(); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: On, Mode: 2 (DRY), Temp: 21C, Fan: 2 (Medium), Sleep: Off, " - "Swing: On, Light: Off, Humid: Off, Save: Off", + "Power: On, Mode: 2 (Dry), Temp: 21C, Fan: 2 (Medium), Sleep: Off, " + "Swing: On, Light: Off, Humid: Off, Save: Off, Timer: Off", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Toshiba_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Toshiba_test.cpp old mode 100755 new mode 100644 similarity index 99% rename from lib/IRremoteESP8266-2.6.5/test/ir_Toshiba_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Toshiba_test.cpp index 15f8e6b90..66c258ae4 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Toshiba_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Toshiba_test.cpp @@ -352,16 +352,16 @@ TEST(TestToshibaACClass, HumanReadableOutput) { 0x00, 0xC1, 0x00, 0xC0}; toshiba.setRaw(initial_state); - EXPECT_EQ("Power: On, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (Auto)", + EXPECT_EQ("Power: On, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto)", toshiba.toString()); toshiba.setRaw(modified_state); - EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 17C, Fan: 5 (High)", + EXPECT_EQ("Power: On, Mode: 1 (Cool), Temp: 17C, Fan: 5 (High)", toshiba.toString()); toshiba.off(); toshiba.setTemp(25); toshiba.setFan(3); toshiba.setMode(kToshibaAcDry); - EXPECT_EQ("Power: Off, Mode: 2 (DRY), Temp: 25C, Fan: 3 (Medium)", + EXPECT_EQ("Power: Off, Mode: 2 (Dry), Temp: 25C, Fan: 3 (Medium)", toshiba.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Trotec_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Trotec_test.cpp old mode 100755 new mode 100644 similarity index 97% rename from lib/IRremoteESP8266-2.6.5/test/ir_Trotec_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Trotec_test.cpp index f9272f384..43cb3fc06 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Trotec_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Trotec_test.cpp @@ -48,7 +48,7 @@ TEST(TestTrotecESPClass, MessageConstructon) { 0x12, 0x34, 0x29, 0x82, 0x00, 0x00, 0x00, 0x00, 0xAB}; EXPECT_STATE_EQ(expected, ac.getRaw(), kTrotecBits); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 2 (Medium), Sleep: On", + "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 2 (Medium), Sleep: On", ac.toString()); } @@ -100,7 +100,7 @@ TEST(TestDecodeTrotec, SyntheticDecode) { IRTrotecESP ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 2 (Medium), Sleep: On", + "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 2 (Medium), Sleep: On", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Vestel_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Vestel_test.cpp old mode 100755 new mode 100644 similarity index 93% rename from lib/IRremoteESP8266-2.6.5/test/ir_Vestel_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Vestel_test.cpp index da95b57c4..4164386f7 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Vestel_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Vestel_test.cpp @@ -321,7 +321,7 @@ TEST(TestVestelAcClass, MessageConstuction) { IRVestelAc ac(0); EXPECT_EQ( - "Power: On, Mode: 0 (AUTO), Temp: 25C, Fan: 13 (Auto Hot), Sleep: Off, " + "Power: On, Mode: 0 (Auto), Temp: 25C, Fan: 13 (Auto Heat), Sleep: Off, " "Turbo: Off, Ion: Off, Swing: Off", ac.toString()); ac.setMode(kVestelAcCool); @@ -329,7 +329,7 @@ TEST(TestVestelAcClass, MessageConstuction) { ac.setFan(kVestelAcFanHigh); EXPECT_FALSE(ac.isTimeCommand()); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 11 (High), Sleep: Off, " + "Power: On, Mode: 1 (Cool), Temp: 21C, Fan: 11 (High), Sleep: Off, " "Turbo: Off, Ion: Off, Swing: Off", ac.toString()); ac.setSwing(true); @@ -337,7 +337,7 @@ TEST(TestVestelAcClass, MessageConstuction) { ac.setTurbo(true); EXPECT_FALSE(ac.isTimeCommand()); EXPECT_EQ( - "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 11 (High), Sleep: Off, " + "Power: On, Mode: 1 (Cool), Temp: 21C, Fan: 11 (High), Sleep: Off, " "Turbo: On, Ion: On, Swing: On", ac.toString()); @@ -345,7 +345,7 @@ TEST(TestVestelAcClass, MessageConstuction) { ac.setSleep(true); ac.setMode(kVestelAcHeat); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 11 (High), Sleep: On, " + "Power: On, Mode: 4 (Heat), Temp: 21C, Fan: 11 (High), Sleep: On, " "Turbo: Off, Ion: On, Swing: On", ac.toString()); EXPECT_FALSE(ac.isTimeCommand()); @@ -353,7 +353,7 @@ TEST(TestVestelAcClass, MessageConstuction) { ac.setTemp(25); ac.setPower(false); EXPECT_EQ( - "Power: Off, Mode: 4 (HEAT), Temp: 25C, Fan: 11 (High), Sleep: On, " + "Power: Off, Mode: 4 (Heat), Temp: 25C, Fan: 11 (High), Sleep: On, " "Turbo: Off, Ion: On, Swing: On", ac.toString()); EXPECT_FALSE(ac.isTimeCommand()); @@ -363,33 +363,33 @@ TEST(TestVestelAcClass, MessageConstuction) { ac.setTime(23 * 60 + 59); EXPECT_TRUE(ac.isTimeCommand()); EXPECT_EQ( - "Time: 23:59, Timer: Off, On Timer: Off, Off Timer: Off", + "Clock: 23:59, Timer: Off, On Timer: Off, Off Timer: Off", ac.toString()); ac.setTimer(8 * 60 + 0); EXPECT_TRUE(ac.isTimeCommand()); EXPECT_EQ( - "Time: 23:59, Timer: 08:00, On Timer: Off, Off Timer: Off", + "Clock: 23:59, Timer: 08:00, On Timer: Off, Off Timer: Off", ac.toString()); ac.setOnTimer(7 * 60 + 40); EXPECT_EQ( - "Time: 23:59, Timer: Off, On Timer: 07:40, Off Timer: Off", + "Clock: 23:59, Timer: Off, On Timer: 07:40, Off Timer: Off", ac.toString()); ac.setOffTimer(17 * 60 + 10); EXPECT_EQ( - "Time: 23:59, Timer: Off, On Timer: 07:40, Off Timer: 17:10", + "Clock: 23:59, Timer: Off, On Timer: 07:40, Off Timer: 17:10", ac.toString()); ac.setTimer(8 * 60 + 0); EXPECT_EQ( - "Time: 23:59, Timer: 08:00, On Timer: Off, Off Timer: Off", + "Clock: 23:59, Timer: 08:00, On Timer: Off, Off Timer: Off", ac.toString()); ac.setTimer(0); EXPECT_EQ( - "Time: 23:59, Timer: Off, On Timer: Off, Off Timer: Off", + "Clock: 23:59, Timer: Off, On Timer: Off, Off Timer: Off", ac.toString()); ac.on(); EXPECT_FALSE(ac.isTimeCommand()); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 25C, Fan: 11 (High), Sleep: On, " + "Power: On, Mode: 4 (Heat), Temp: 25C, Fan: 11 (High), Sleep: On, " "Turbo: Off, Ion: On, Swing: On", ac.toString()); } @@ -431,7 +431,7 @@ TEST(TestDecodeVestelAc, NormalDecodeWithStrict) { ac.begin(); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: On, Mode: 0 (AUTO), Temp: 25C, Fan: 13 (Auto Hot), Sleep: Off, " + "Power: On, Mode: 0 (Auto), Temp: 25C, Fan: 13 (Auto Heat), Sleep: Off, " "Turbo: Off, Ion: Off, Swing: Off", ac.toString()); } @@ -467,7 +467,7 @@ TEST(TestDecodeVestelAc, RealNormalExample) { ac.begin(); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 16C, Fan: 1 (Auto), Sleep: Off, " + "Power: On, Mode: 4 (Heat), Temp: 16C, Fan: 1 (Auto), Sleep: Off, " "Turbo: Off, Ion: On, Swing: Off", ac.toString()); } @@ -502,7 +502,7 @@ TEST(TestDecodeVestelAc, RealTimerExample) { ac.begin(); ac.setRaw(irsend.capture.value); EXPECT_EQ( - "Time: 05:45, Timer: Off, On Timer: 14:00, Off Timer: 23:00", + "Clock: 05:45, Timer: Off, On Timer: 14:00, Off Timer: 23:00", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Whirlpool_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Whirlpool_test.cpp old mode 100755 new mode 100644 similarity index 97% rename from lib/IRremoteESP8266-2.6.5/test/ir_Whirlpool_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Whirlpool_test.cpp index 6349a8154..901318326 --- a/lib/IRremoteESP8266-2.6.5/test/ir_Whirlpool_test.cpp +++ b/lib/IRremoteESP8266-2.7.0/test/ir_Whirlpool_test.cpp @@ -69,9 +69,9 @@ TEST(TestDecodeWhirlpoolAC, SyntheticDecode) { IRWhirlpoolAc ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Model: 1 (DG11J13A), Power toggle: Off, Mode: 1 (AUTO), Temp: 25C, " + "Model: 1 (DG11J13A), Power Toggle: Off, Mode: 1 (Auto), Temp: 25C, " "Fan: 0 (Auto), Swing: Off, Light: On, Clock: 17:31, On Timer: Off, " - "Off Timer: Off, Sleep: Off, Super: Off, Command: 2 (TEMP)", + "Off Timer: Off, Sleep: Off, Super: Off, Command: 2 (Temp)", ac.toString()); } @@ -93,9 +93,9 @@ TEST(TestDecodeWhirlpoolAC, Real26CFanAutoCoolingSwingOnClock1918) { IRWhirlpoolAc ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Model: 1 (DG11J13A), Power toggle: Off, Mode: 2 (COOL), Temp: 26C, " + "Model: 1 (DG11J13A), Power Toggle: Off, Mode: 2 (Cool), Temp: 26C, " "Fan: 0 (Auto), Swing: On, Light: On, Clock: 19:18, On Timer: Off, " - "Off Timer: Off, Sleep: Off, Super: Off, Command: 7 (SWING)", + "Off Timer: Off, Sleep: Off, Super: Off, Command: 7 (Swing)", ac.toString()); } @@ -148,9 +148,9 @@ TEST(TestDecodeWhirlpoolAC, RealTimerExample) { IRWhirlpoolAc ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Model: 1 (DG11J13A), Power toggle: Off, Mode: 3 (DRY), Temp: 25C, " + "Model: 1 (DG11J13A), Power Toggle: Off, Mode: 3 (Dry), Temp: 25C, " "Fan: 0 (Auto), Swing: Off, Light: On, Clock: 07:35, On Timer: 07:40, " - "Off Timer: 08:05, Sleep: Off, Super: Off, Command: 5 (ONTIMER)", + "Off Timer: 08:05, Sleep: Off, Super: Off, Command: 5 (On Timer)", ac.toString()); } @@ -206,9 +206,9 @@ TEST(TestDecodeWhirlpoolAC, RealExampleDecode) { IRWhirlpoolAc ac(0); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Model: 1 (DG11J13A), Power toggle: Off, Mode: 1 (AUTO), Temp: 25C, " + "Model: 1 (DG11J13A), Power Toggle: Off, Mode: 1 (Auto), Temp: 25C, " "Fan: 0 (Auto), Swing: Off, Light: On, Clock: 17:31, On Timer: Off, " - "Off Timer: Off, Sleep: Off, Super: Off, Command: 2 (TEMP)", + "Off Timer: Off, Sleep: Off, Super: Off, Command: 2 (Temp)", ac.toString()); } @@ -556,9 +556,9 @@ TEST(TestIRWhirlpoolAcClass, MessageConstruction) { ac.enableOnTimer(true); EXPECT_EQ( - "Model: 1 (DG11J13A), Power toggle: Off, Mode: 3 (DRY), Temp: 25C, " + "Model: 1 (DG11J13A), Power Toggle: Off, Mode: 3 (Dry), Temp: 25C, " "Fan: 0 (Auto), Swing: Off, Light: On, Clock: 07:35, On Timer: 07:40, " - "Off Timer: 08:05, Sleep: Off, Super: Off, Command: 5 (ONTIMER)", + "Off Timer: 08:05, Sleep: Off, Super: Off, Command: 5 (On Timer)", ac.toString()); EXPECT_STATE_EQ(expectedState, ac.getRaw(), kWhirlpoolAcBits); } diff --git a/lib/IRremoteESP8266-2.6.5/test/ir_Whynter_test.cpp b/lib/IRremoteESP8266-2.7.0/test/ir_Whynter_test.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/test/ir_Whynter_test.cpp rename to lib/IRremoteESP8266-2.7.0/test/ir_Whynter_test.cpp diff --git a/lib/IRremoteESP8266-2.6.5/tools/Makefile b/lib/IRremoteESP8266-2.7.0/tools/Makefile old mode 100755 new mode 100644 similarity index 94% rename from lib/IRremoteESP8266-2.6.5/tools/Makefile rename to lib/IRremoteESP8266-2.7.0/tools/Makefile index d2da05eb3..bf23fbce6 --- a/lib/IRremoteESP8266-2.6.5/tools/Makefile +++ b/lib/IRremoteESP8266-2.7.0/tools/Makefile @@ -18,7 +18,7 @@ INCLUDES = -I$(USER_DIR) -I$(TEST_DIR) # Flags passed to the preprocessor. # Set Google Test's header directory as a system directory, such that # the compiler doesn't generate warnings in Google Test headers. -CPPFLAGS += -DUNIT_TEST +CPPFLAGS += -DUNIT_TEST -D_IR_LOCALE_=en-AU # Flags passed to the C++ compiler. CXXFLAGS += -g -Wall -Wextra -pthread -std=gnu++11 @@ -54,12 +54,12 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \ ir_Trotec.o ir_Neoclima.o ir_Amcor.o # Common object files -COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o $(PROTOCOLS) +COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o IRtext.o IRac.o $(PROTOCOLS) # Common dependencies COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \ $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h \ - $(TEST_DIR)/IRsend_test.h + $(TEST_DIR)/IRsend_test.h $(USER_DIR)/IRtext.h $(USER_DIR)/i18n.h # Common test dependencies COMMON_TEST_DEPS = $(COMMON_DEPS) $(TEST_DIR)/IRsend_test.h @@ -75,6 +75,9 @@ mode2_decode.o : mode2_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) mode2_decode : $(COMMON_OBJ) mode2_decode.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ +IRtext.o : $(USER_DIR)/IRtext.cpp $(USER_DIR)/IRtext.h $(USER_DIR)/IRremoteESP8266.h $(USER_DIR)/i18n.h $(USER_DIR)/locale/*.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/IRtext.cpp + IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRutils.cpp @@ -230,3 +233,6 @@ ir_Neoclima.o : $(USER_DIR)/ir_Neoclima.cpp $(USER_DIR)/ir_Neoclima.h $(COMMON_D ir_Amcor.o : $(USER_DIR)/ir_Amcor.cpp $(USER_DIR)/ir_Amcor.h $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Amcor.cpp + +IRac.o : $(USER_DIR)/IRac.cpp $(USER_DIR)/IRac.h $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/IRac.cpp diff --git a/lib/IRremoteESP8266-2.6.5/tools/RawToGlobalCache.sh b/lib/IRremoteESP8266-2.7.0/tools/RawToGlobalCache.sh similarity index 100% rename from lib/IRremoteESP8266-2.6.5/tools/RawToGlobalCache.sh rename to lib/IRremoteESP8266-2.7.0/tools/RawToGlobalCache.sh diff --git a/lib/IRremoteESP8266-2.7.0/tools/auto_analyse_raw_data.py b/lib/IRremoteESP8266-2.7.0/tools/auto_analyse_raw_data.py new file mode 100755 index 000000000..d673d52d4 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/tools/auto_analyse_raw_data.py @@ -0,0 +1,729 @@ +#!/usr/bin/python +"""Attempt an automatic analysis of IRremoteESP8266's Raw data output. + Makes suggestions on key values and tried to break down the message + into likely chunks.""" +# +# Copyright 2018 David Conran +import argparse +import sys + + +class RawIRMessage(): + """Basic analyse functions & structure for raw IR messages.""" + + # pylint: disable=too-many-instance-attributes + + def __init__(self, margin, timings, output=sys.stdout, verbose=True): + self.ldr_mark = None + self.hdr_mark = None + self.hdr_space = None + self.bit_mark = None + self.zero_space = None + self.one_space = None + self.gaps = [] + self.margin = margin + self.marks = [] + self.mark_buckets = {} + self.spaces = [] + self.space_buckets = {} + self.output = output + self.verbose = verbose + self.section_count = 1 + self.rawlen = len(timings) + if self.rawlen <= 3: + raise ValueError("Too few message timings supplied.") + self.timings = timings + self._generate_timing_candidates() + self._calc_values() + + def _generate_timing_candidates(self): + """Determine the likely values from the given data.""" + count = 0 + for usecs in self.timings: + count = count + 1 + if count % 2: + self.marks.append(usecs) + else: + self.spaces.append(usecs) + self.marks, self.mark_buckets = self.reduce_list(self.marks) + self.spaces, self.space_buckets = self.reduce_list(self.spaces) + + def reduce_list(self, items): + """Reduce a list of numbers into buckets that are at least margin apart.""" + result = [] + last = -1 + buckets = {} + for item in sorted(items, reverse=True): + if last == -1 or item < last - self.margin: + result.append(item) + last = item + buckets[last] = [item] + else: + buckets[last].append(item) + return result, buckets + + def _usec_compare(self, seen, expected): + """Compare two usec values and see if they match within a + subtractive margin.""" + return expected - self.margin < seen <= expected + + def _usec_compares(self, usecs, expecteds): + """Compare a usec value to a list of values and return True + if they are within a subtractive margin.""" + for expected in expecteds: + if self._usec_compare(usecs, expected): + return True + return False + + def display_binary(self, binary_str): + """Display common representations of the suppied binary string.""" + num = int(binary_str, 2) + bits = len(binary_str) + rev_binary_str = binary_str[::-1] + rev_num = int(rev_binary_str, 2) + self.output.write("\n Bits: %d\n" + " Hex: %s (MSB first)\n" + " %s (LSB first)\n" + " Dec: %s (MSB first)\n" + " %s (LSB first)\n" + " Bin: 0b%s (MSB first)\n" + " 0b%s (LSB first)\n" % + (bits, ("0x{0:0%dX}" % (bits / 4)).format(num), + ("0x{0:0%dX}" % (bits / 4)).format(rev_num), num, + rev_num, binary_str, rev_binary_str)) + + def add_data_code(self, bin_str, name="", footer=True): + """Add the common "data" sequence of code to send the bulk of a message.""" + # pylint: disable=no-self-use + code = [] + nbits = len(bin_str) + code.append(" // Data Section #%d" % self.section_count) + code.append(" // e.g. data = 0x%X, nbits = %d" % (int(bin_str, 2), + nbits)) + code.append(" sendData(k%sBitMark, k%sOneSpace, k%sBitMark, " + "k%sZeroSpace, send_data, %d, true);" % + (name, name, name, name, nbits)) + code.append(" send_data >>= %d;" % nbits) + if footer: + code.append(" // Footer") + code.append(" mark(k%sBitMark);" % name) + return code + + def add_data_decode_code(self, bin_str, name="", footer=True): + """Add the common "data" sequence code to decode the bulk of a message.""" + # pylint: disable=no-self-use + code = [] + nbits = len(bin_str) + code.extend([ + "", + " // Data Section #%d" % self.section_count, + " // e.g. data_result.data = 0x%X, nbits = %d" % (int(bin_str, 2), + nbits), + " data_result = matchData(&(results->rawbuf[offset]), %s," % nbits, + " k%sBitMark, k%sOneSpace," % (name, name), + " k%sBitMark, k%sZeroSpace);" % (name, name), + " offset += data_result.used;", + " if (data_result.success == false) return false; // Fail", + " data <<= %s; // Make room for the new bits of data." % nbits, + " data |= data_result.data;"]) + if footer: + code.extend([ + "", + " // Footer", + " if (!matchMark(results->rawbuf[offset++], k%sBitMark))" % name, + " return false;"]) + return code + + def add_data_byte_code(self, bin_str, name="", ambles=None): + """Add the code to send the data from an array.""" + # pylint: disable=no-self-use + code = [] + nbits = len(bin_str) + nbytes = nbits / 8 + if ambles is None: + ambles = {} + firstmark = ambles.get("firstmark", 0) + firstspace = ambles.get("firstspace", 0) + lastmark = ambles.get("lastmark", "k%sBitMark" % name) + lastspace = ambles.get("lastspace", "kDefaultMessageGap") + code.append( + " // Data Section #%d" % self.section_count) + if nbits % 8: + code.append(" // DANGER: Nr. of bits is not a multiple of 8. " + "This section won't work!") + code.extend([ + " // e.g.", + " // bits = %d; bytes = %d;" % (nbits, nbytes), + " // *(data + pos) = {0x%s};" % ( + ", 0x".join("%02X" % int(bin_str[i:i + 8], 2) + for i in range(0, len(bin_str), 8))), + " sendGeneric(%s, %s," % (firstmark, firstspace), + " k%sBitMark, k%sOneSpace," % (name, name), + " k%sBitMark, k%sZeroSpace," % (name, name), + " %s, %s," % (lastmark, lastspace), + " data + pos, %d, // Bytes" % nbytes, + " k%sFreq, true, kNoRepeat, kDutyDefault);" % name, + " pos += %d; // Adjust by how many bytes of data we sent" % nbytes]) + return code + + def add_data_byte_decode_code(self, bin_str, name="", ambles=None): + """Add the common byte-wise "data" sequence decode code.""" + # pylint: disable=no-self-use + code = [] + nbits = len(bin_str) + nbytes = nbits / 8 + if nbits % 8: + code.append(" // WARNING: Nr. of bits is not a multiple of 8. " + "This section won't work!") + if ambles is None: + ambles = {} + firstmark = ambles.get("firstmark", 0) + firstspace = ambles.get("firstspace", 0) + lastmark = ambles.get("lastmark", "k%sBitMark" % name) + lastspace = ambles.get("lastspace", "kDefaultMessageGap") + + code.extend([ + "", + " // Data Section #%d" % self.section_count, + " // e.g.", + " // bits = %d; bytes = %d;" % (nbits, nbytes), + " // *(results->state + pos) = {0x%s};" % ( + ", 0x".join("%02X" % int(bin_str[i:i + 8], 2) + for i in range(0, len(bin_str), 8))), + " used = matchGeneric(results->rawbuf + offset, results->state + pos,", + " results->rawlen - offset, %d," % nbits, + " %s, %s," % (firstmark, firstspace), + " k%sBitMark, k%sOneSpace," % (name, name), + " k%sBitMark, k%sZeroSpace," % (name, name), + " %s, %s, true);" % (lastmark, lastspace), + " if (used == 0) return false; // We failed to find any data.", + " offset += used; // Adjust for how much of the message we read.", + " pos += %d; // Adjust by how many bytes of data we read" % nbytes]) + return code + + def _calc_values(self): + """Calculate the values which describe the standard timings + for the protocol.""" + if self.verbose: + self.output.write("Potential Mark Candidates:\n" + "%s\n" + "Potential Space Candidates:\n" + "%s\n" % (str(self.marks), str(self.spaces))) + # The bit mark is likely to be the smallest mark. + self.bit_mark = self.marks[-1] + if len(self.marks) > 2: # Possible leader mark? + self.ldr_mark = self.marks[0] + self.hdr_mark = self.marks[1] + else: + # Largest mark is likely the kHdrMark + self.hdr_mark = self.marks[0] + + if self.is_space_encoded() and len(self.spaces) >= 3: + 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() + # Rest are probably message gaps + self.gaps = spaces + + def is_space_encoded(self): + """Make an educated guess if the message is space encoded.""" + return len(self.spaces) > len(self.marks) + + def is_ldr_mark(self, usec): + """Is usec the leader mark?""" + if self.ldr_mark is None: + return False + return self._usec_compare(usec, self.ldr_mark) + + def is_hdr_mark(self, usec): + """Is usec the header mark?""" + return self._usec_compare(usec, self.hdr_mark) + + def is_hdr_space(self, usec): + """Is usec the header space?""" + return self._usec_compare(usec, self.hdr_space) + + def is_bit_mark(self, usec): + """Is usec the bit mark?""" + return self._usec_compare(usec, self.bit_mark) + + def is_one_space(self, usec): + """Is usec the one space?""" + return self._usec_compare(usec, self.one_space) + + def is_zero_space(self, usec): + """Is usec the zero_space?""" + return self._usec_compare(usec, self.zero_space) + + def is_gap(self, usec): + """Is usec the a space gap?""" + return self._usec_compares(usec, self.gaps) + + +def avg_list(items): + """Return the average of a list of numbers.""" + if items: + return int(sum(items) / len(items)) + return 0 + + +def add_bit(so_far, bit, output=sys.stdout): + """Add a bit to the end of the bits collected so far.""" + if bit == "reset": + return "" + output.write(str(bit)) # This effectively displays in LSB first order. + return so_far + str(bit) # Storing it in MSB first order. + + +def convert_rawdata(data_str): + """Parse a C++ rawdata declaration into a list of values.""" + start = data_str.find('{') + end = data_str.find('}') + if end == -1: + end = len(data_str) + if start > end: + raise ValueError("Raw Data not parsible due to parentheses placement.") + data_str = data_str[start + 1:end] + results = [] + for timing in [x.strip() for x in data_str.split(',')]: + try: + results.append(int(timing)) + except ValueError: + raise ValueError( + "Raw Data contains a non-numeric value of '%s'." % timing) + return results + + +def dump_constants(message, defines, name="", output=sys.stdout): + """Dump the key constants and generate the C++ #defines.""" + ldr_mark = None + 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]) + bit_mark = avg_list(message.mark_buckets[message.bit_mark]) + 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]) + + output.write("Guessing key value:\n" + "k%sHdrMark = %d\n" + "k%sHdrSpace = %d\n" + "k%sBitMark = %d\n" + "k%sOneSpace = %d\n" + "k%sZeroSpace = %d\n" % (name, hdr_mark, name, hdr_space, + name, bit_mark, name, one_space, + name, zero_space)) + defines.append("const uint16_t k%sHdrMark = %d;" % (name, hdr_mark)) + defines.append("const uint16_t k%sBitMark = %d;" % (name, bit_mark)) + defines.append("const uint16_t k%sHdrSpace = %d;" % (name, hdr_space)) + defines.append("const uint16_t k%sOneSpace = %d;" % (name, one_space)) + defines.append("const uint16_t k%sZeroSpace = %d;" % (name, zero_space)) + if ldr_mark: + output.write("k%sLdrMark = %d\n" % (name, ldr_mark)) + defines.append("const uint16_t k%sLdrMark = %d;" % (name, ldr_mark)) + + avg_gaps = [avg_list(message.space_buckets[x]) for x in message.gaps] + if len(message.gaps) == 1: + output.write("k%sSpaceGap = %d\n" % (name, avg_gaps[0])) + defines.append("const uint16_t k%sSpaceGap = %d;" % (name, avg_gaps[0])) + else: + count = 0 + for gap in avg_gaps: + # We probably (still) have a gap in the protocol. + count = count + 1 + output.write("k%sSpaceGap%d = %d\n" % (name, count, gap)) + defines.append("const uint16_t k%sSpaceGap%d = %d;" % (name, count, gap)) + defines.append("const uint16_t k%sFreq = 38000; " + "// Hz. (Guessing the most common frequency.)" % name) + + +def parse_and_report(rawdata_str, margin, gen_code=False, name="", + output=sys.stdout): + """Analyse the rawdata c++ definition of a IR message.""" + defines = [] + code = {} + code["send"] = [] + code["send64+"] = [] + code["recv"] = [] + code["recv64+"] = [] + + # Parse the input. + rawdata = convert_rawdata(rawdata_str) + + output.write("Found %d timing entries.\n" % len(rawdata)) + + message = RawIRMessage(margin, rawdata, output) + output.write("\nGuessing encoding type:\n") + if message.is_space_encoded(): + output.write("Looks like it uses space encoding. Yay!\n\n") + dump_constants(message, defines, name, output) + else: + output.write("Sorry, it looks like it is Mark encoded. " + "I can't do that yet. Exiting.\n") + sys.exit(1) + total_bits = decode_data(message, defines, code, name, output) + if gen_code: + generate_code(defines, code, total_bits, name, output) + + +def decode_data(message, defines, code, name="", output=sys.stdout): + """Decode the data sequence with the given values in mind.""" + # pylint: disable=too-many-branches,too-many-statements + + # Now we have likely candidates for the key values, go through the original + # sequence and break it up and indicate accordingly. + + output.write("\nDecoding protocol based on analysis so far:\n\n") + state = "" + code_info = {} + count = 1 + total_bits = "" + binary_value = binary64_value = add_bit("", "reset") + if name: + def_name = name + else: + def_name = "TBD" + + code["send"].extend([ + "#if SEND_%s" % def_name.upper(), + "// Function should be safe up to 64 bits.", + "void IRsend::send%s(const uint64_t data, const uint16_t" + " nbits, const uint16_t repeat) {" % def_name, + " enableIROut(k%sFreq);" % name, + " for (uint16_t r = 0; r <= repeat; r++) {", + " uint64_t send_data = data;"]) + code["send64+"].extend([ + "// Args:", + "// data: An array of bytes containing the IR command.", + "// It is assumed to be in MSB order for this code.\n" + "// nbytes: Nr. of bytes of data in the array." + " (>=k%sStateLength)" % name, + "// repeat: Nr. of times the message is to be repeated.", + "//", + "// Status: ALPHA / Untested.", + "void IRsend::send%s(const uint8_t data[], const uint16_t nbytes," + " const uint16_t repeat) {" % def_name, + " for (uint16_t r = 0; r <= repeat; r++) {", + " uint16_t pos = 0;"]) + code["recv"].extend([ + "#if DECODE_%s" % def_name.upper(), + "// Function should be safe up to 64 bits.", + "bool IRrecv::decode%s(decode_results *results, const uint16_t nbits," + " const bool strict) {" % def_name, + " if (results->rawlen < 2 * nbits + k%sOverhead)" % name, + " return false; // Too short a message to match.", + " if (strict && nbits != k%sBits)" % name, + " return false;", + "", + " uint16_t offset = kStartOffset;", + " uint64_t data = 0;", + " match_result_t data_result;"]) + code["recv64+"].extend([ + "#if DECODE_%s" % def_name.upper(), + "// Function should be safe over 64 bits.", + "bool IRrecv::decode%s(decode_results *results, const uint16_t nbits," + " const bool strict) {" % def_name, + " if (results->rawlen < 2 * nbits + k%sOverhead)" % name, + " return false; // Too short a message to match.", + " if (strict && nbits != k%sBits)" % name, + " return false;", + "", + " uint16_t offset = kStartOffset;", + " uint16_t pos = 0;", + " uint16_t used = 0;"]) + + # states are: + # HM: Header/Leader mark + # HS: Header space + # BM: Bit mark + # BS: Bit space + # GS: Gap space + # UNK: Unknown state. + for usec in message.timings: + # Handle header/leader marks. + if ((message.is_hdr_mark(usec) or message.is_ldr_mark(usec)) and + count % 2 and not message.is_bit_mark(usec)): + state = "HM" + if message.is_hdr_mark(usec): + mark_type = "H" # Header + else: + mark_type = "L" # Leader + if binary_value: + message.display_binary(binary_value) + code["send"].extend(message.add_data_code(binary_value, name, False)) + code["recv"].extend(message.add_data_decode_code(binary_value, name, + False)) + message.section_count = message.section_count + 1 + code_info["lastmark"] = "k%s%sdrMark" % (name, mark_type) + total_bits = total_bits + binary_value + code_info["firstmark"] = "k%s%sdrMark" % (name, mark_type) + binary_value = add_bit(binary_value, "reset") + output.write("k%s%sdrMark+" % (name, mark_type)) + code["send"].extend([" // %seader" % mark_type, + " mark(k%s%sdrMark);" % (name, mark_type)]) + code["recv"].extend([ + "", + " // %seader" % mark_type, + " if (!matchMark(results->rawbuf[offset++], k%s%sdrMark))" % ( + name, mark_type), + " return false;"]) + + # Handle header spaces. + elif message.is_hdr_space(usec) and not message.is_one_space(usec): + if binary64_value: + code_info["lastspace"] = "k%sHdrSpace" % name + message.section_count = message.section_count - 1 + code["send64+"].extend(message.add_data_byte_code(binary64_value, name, + code_info)) + code["recv64+"].extend(message.add_data_byte_decode_code(binary64_value, + name, + code_info)) + code_info.clear() + binary64_value = binary_value + message.section_count = message.section_count + 1 + if state != "HM": + if binary_value: # If we we are in a header and we have data, add it. + message.display_binary(binary_value) + total_bits = total_bits + binary_value + code["send"].extend(message.add_data_code(binary_value, name)) + code["recv"].extend(message.add_data_decode_code(binary_value, name)) + code_info["lastspace"] = "k%sHdrSpace" % name + message.section_count = message.section_count + 1 + binary_value = binary64_value = add_bit(binary_value, "reset") + output.write("UNEXPECTED->") + state = "HS" + output.write("k%sHdrSpace+" % name) + code["send"].append(" space(k%sHdrSpace);" % name) + code["recv"].extend([ + " if (!matchSpace(results->rawbuf[offset++], k%sHdrSpace))" % name, + " return false;"]) + code_info["firstspace"] = "k%sHdrSpace" % name + # Handle bit marks. + elif message.is_bit_mark(usec) and count % 2: + if state not in ("HS", "BS"): + output.write("k%sBitMark(UNEXPECTED)" % name) + state = "BM" + # Handle "zero" spaces + elif message.is_zero_space(usec): + if state != "BM": + output.write("k%sZeroSpace(UNEXPECTED)" % name) + state = "BS" + binary_value = binary64_value = add_bit(binary_value, 0, output) + # Handle "one" spaces + elif message.is_one_space(usec): + if state != "BM": + output.write("k%sOneSpace(UNEXPECTED)" % name) + state = "BS" + binary_value = binary64_value = add_bit(binary_value, 1, output) + elif message.is_gap(usec): + if state != "BM": + output.write("UNEXPECTED->") + output.write("GAP(%d)" % usec) + code_info["lastspace"] = "k%sSpaceGap" % name + if binary64_value: + code["send64+"].extend(message.add_data_byte_code(binary64_value, name, + code_info)) + code["recv64+"].extend(message.add_data_byte_decode_code(binary64_value, + name, + code_info)) + code_info.clear() + if binary_value: + message.display_binary(binary_value) + code["send"].extend(message.add_data_code(binary_value, name)) + code["recv"].extend(message.add_data_decode_code(binary_value, name)) + message.section_count = message.section_count + 1 + else: + code["recv"].extend(["", + " // Gap"]) + code["send"].extend([" // Gap"]) + if state == "BM": + code["send"].extend([" mark(k%sBitMark);" % name]) + code["recv"].extend([ + " if (!matchMark(results->rawbuf[offset++], k%sBitMark))" % name, + " return false;"]) + code["send"].append(" space(k%sSpaceGap);" % name) + code["recv"].extend([ + " if (!matchSpace(results->rawbuf[offset++], k%sSpaceGap))" % name, + " return false;"]) + total_bits = total_bits + binary_value + binary_value = binary64_value = add_bit(binary_value, "reset") + state = "GS" + else: + output.write("UNKNOWN(%d)" % usec) + state = "UNK" + count = count + 1 + if binary64_value: + code["send64+"].extend(message.add_data_byte_code(binary64_value, name, + code_info)) + code["recv64+"].extend(message.add_data_byte_decode_code(binary64_value, + name, code_info)) + code_info.clear() + if binary_value: + message.display_binary(binary_value) + code["send"].extend(message.add_data_code(binary_value, name)) + code["recv"].extend(message.add_data_decode_code(binary_value, name)) + message.section_count = message.section_count + 1 + code["send"].extend([ + " space(kDefaultMessageGap); // A 100% made up guess of the gap" + " between messages.", + " }", + "}", + "#endif // SEND_%s" % def_name.upper()]) + code["send64+"].extend([ + " }", + "}", + "#endif // SEND_%s" % def_name.upper()]) + code["recv"].extend([ + "", + " // Success", + " results->decode_type = decode_type_t::%s;" % def_name.upper(), + " results->bits = nbits;", + " results->value = data;", + " results->command = 0;", + " results->address = 0;", + " return true;", + "}", + "#endif // DECODE_%s" % def_name.upper()]) + code["recv64+"].extend([ + "", + " // Success", + " results->decode_type = decode_type_t::%s;" % def_name.upper(), + " results->bits = nbits;", + " return true;", + "}", + "#endif // DECODE_%s" % def_name.upper()]) + + total_bits = total_bits + binary_value + output.write("\nTotal Nr. of suspected bits: %d\n" % len(total_bits)) + defines.append("const uint16_t k%sBits = %d;" + " // Move to IRremoteESP8266.h" % (name, len(total_bits))) + if len(total_bits) > 64: + defines.append("const uint16_t k%sStateLength = %d;" + " // Move to IRremoteESP8266.h" % + (name, len(total_bits) / 8)) + defines.append("const uint16_t k%sOverhead = %d;" % + (name, message.rawlen - 2 * len(total_bits))) + return total_bits + + +def generate_code(defines, code, bits_str, name="", output=sys.stdout): + """Output the estimated C++ code to reproduce & decode the IR message.""" + if name: + def_name = name + else: + def_name = "TBD" + output.write("\nGenerating a VERY rough code outline:\n\n" + "// Copyright 2019 David Conran (crankyoldgit)\n" + "// Support for %s 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" % def_name) + for line in defines: + output.write("%s\n" % line) + + if len(bits_str) > 64: # Will it fit in a uint64_t? + output.write("// DANGER: More than 64 bits detected. A uint64_t for " + "'data' won't work!\n") + # Display the "normal" version's send code incase there are some + # oddities in it. + for line in code["send"]: + output.write("%s\n" % line) + + if len(bits_str) > 64: # Will it fit in a uint64_t? + code["send64+"] = [ + "", + "#if SEND_%s" % def_name.upper(), + "// Alternative >64bit function to send %s messages" % def_name.upper(), + "// Where data is:", + "// uint8_t data[k%sStateLength] = {0x%s};" % ( + name, ", 0x".join("%02X" % int(bits_str[i:i + 8], 2) + for i in range(0, len(bits_str), 8))), + "//"] + code["send64+"] + for line in code["send64+"]: + output.write("%s\n" % line) + output.write("\n") + if len(bits_str) > 64: # Will it fit in a uint64_t? + output.write("// DANGER: More than 64 bits detected. A uint64_t for " + "'data' won't work!\n") + # Display the "normal" version's decode code incase there are some + # oddities in it. + for line in code["recv"]: + output.write("%s\n" % line) + # Display the > 64bit version's decode code + if len(bits_str) > 64: # Is it too big for a uint64_t? + output.write("\n// Note: This should be 64+ bit safe.\n") + if len(bits_str) % 8: + output.write("\n// WARNING: Data is not a multiple of bytes. " + "This won't work!\n") + for line in code["recv64+"]: + output.write("%s\n" % line) + + +def main(): + """Parse the commandline arguments and call the method.""" + arg_parser = argparse.ArgumentParser( + description="Read an IRremoteESP8266 rawData declaration and tries to " + "analyse it.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + arg_parser.add_argument( + "-g", + "--code", + action="store_true", + default=False, + dest="gen_code", + help="Generate a C++ code outline to aid making an IRsend function.") + arg_parser.add_argument( + "-n", + "--name", + help="Name of the protocol/device to use in code generation. E.g. Onkyo", + dest="name", + default="") + arg_group = arg_parser.add_mutually_exclusive_group(required=True) + arg_group.add_argument( + "rawdata", + help="A rawData line from IRrecvDumpV2. e.g. 'uint16_t rawbuf[37] = {" + "7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, " + "520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, " + "494, 520, 520, 520, 494, 520, 494, 520, 494, 520, 494};'", + nargs="?") + arg_group.add_argument( + "-f", "--file", help="Read in a rawData line from the file.") + arg_parser.add_argument( + "-r", + "--range", + type=int, + help="Max number of micro-seconds difference between values to consider" + " it the same value.", + dest="margin", + default=200) + arg_group.add_argument( + "--stdin", + help="Read in a rawData line from STDIN.", + action="store_true", + default=False) + arg_options = arg_parser.parse_args() + + if arg_options.stdin: + data = sys.stdin.read() + elif arg_options.file: + with open(arg_options.file) as input_file: + data = input_file.read() + else: + data = arg_options.rawdata + parse_and_report(data, arg_options.margin, arg_options.gen_code, + arg_options.name) + + +if __name__ == '__main__': + main() diff --git a/lib/IRremoteESP8266-2.7.0/tools/auto_analyse_raw_data_test.py b/lib/IRremoteESP8266-2.7.0/tools/auto_analyse_raw_data_test.py new file mode 100755 index 000000000..c2fd7ba64 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/tools/auto_analyse_raw_data_test.py @@ -0,0 +1,1170 @@ +#!/usr/bin/python3 +"""Unit tests for auto_analyse_raw_data.py""" +from io import StringIO +import unittest +import auto_analyse_raw_data as analyse + +# pylint: disable=too-many-lines + +class TestRawIRMessage(unittest.TestCase): + """Unit tests for the RawIRMessage class.""" + + # pylint: disable=too-many-public-methods + + def test_display_binary(self): + """Test the display_binary() method.""" + output = StringIO() + message = analyse.RawIRMessage(100, [8000, 4000, 500, 500, 500], output, + False) + self.assertEqual(output.getvalue(), '') + message.display_binary("10101010") + message.display_binary("0000000000000000") + message.display_binary("00010010001101000101011001111000") + self.assertEqual( + output.getvalue(), '\n' + ' Bits: 8\n' + ' Hex: 0xAA (MSB first)\n' + ' 0x55 (LSB first)\n' + ' Dec: 170 (MSB first)\n' + ' 85 (LSB first)\n' + ' Bin: 0b10101010 (MSB first)\n' + ' 0b01010101 (LSB first)\n' + '\n' + ' Bits: 16\n' + ' Hex: 0x0000 (MSB first)\n' + ' 0x0000 (LSB first)\n' + ' Dec: 0 (MSB first)\n' + ' 0 (LSB first)\n' + ' Bin: 0b0000000000000000 (MSB first)\n' + ' 0b0000000000000000 (LSB first)\n' + '\n' + ' Bits: 32\n' + ' Hex: 0x12345678 (MSB first)\n' + ' 0x1E6A2C48 (LSB first)\n' + ' Dec: 305419896 (MSB first)\n' + ' 510274632 (LSB first)\n' + ' Bin: 0b00010010001101000101011001111000 (MSB first)\n' + ' 0b00011110011010100010110001001000 (LSB first)\n') + + +class TestAutoAnalyseRawData(unittest.TestCase): + """Unit tests for the functions in AutoAnalyseRawData.""" + + # pylint: disable=too-many-public-methods + + def test_avg_list(self): + """Tests for the avg_list method.""" + + self.assertEqual(0, analyse.avg_list([])) + self.assertEqual(23, analyse.avg_list([10, 20, 40])) + + def test_dump_constants_simple(self): + """Simple tests for the dump_constants() function.""" + ignore = StringIO() + output = StringIO() + defs = [] + message = analyse.RawIRMessage(200, [ + 7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, + 520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494, + 520, 520, 520, 494, 520, 494, 520, 494, 1482, 494 + ], ignore) + analyse.dump_constants(message, defs, "BAR", output) + self.assertEqual(defs, [ + 'const uint16_t kBARHdrMark = 7930;', + 'const uint16_t kBARBitMark = 496;', + 'const uint16_t kBARHdrSpace = 3965;', + 'const uint16_t kBAROneSpace = 1485;', + 'const uint16_t kBARZeroSpace = 520;', + 'const uint16_t kBARFreq = 38000; // Hz. (Guessing the most common ' + 'frequency.)' + ]) + self.assertEqual( + output.getvalue(), 'Guessing key value:\n' + 'kBARHdrMark = 7930\n' + 'kBARHdrSpace = 3965\n' + 'kBARBitMark = 496\n' + 'kBAROneSpace = 1485\n' + 'kBARZeroSpace = 520\n') + + def test_dump_constants_aircon(self): + """More complex tests for the dump_constants() function.""" + ignore = StringIO() + output = StringIO() + defs = [] + message = analyse.RawIRMessage(200, [ + 9008, 4496, 644, 1660, 676, 530, 648, 558, 672, 1636, 646, 1660, 644, + 556, 650, 584, 626, 560, 644, 580, 628, 1680, 624, 560, 648, 1662, 644, + 582, 648, 536, 674, 530, 646, 580, 628, 560, 670, 532, 646, 562, 644, + 556, 672, 536, 648, 1662, 646, 1660, 652, 554, 644, 558, 672, 538, 644, + 560, 668, 560, 648, 1638, 668, 536, 644, 1660, 668, 532, 648, 560, 648, + 1660, 674, 554, 622, 19990, 646, 580, 624, 1660, 648, 556, 648, 558, + 674, 556, 622, 560, 644, 564, 668, 536, 646, 1662, 646, 1658, 672, 534, + 648, 558, 644, 562, 648, 1662, 644, 584, 622, 558, 648, 562, 668, 534, + 670, 536, 670, 532, 672, 536, 646, 560, 646, 558, 648, 558, 670, 534, + 650, 558, 646, 560, 646, 560, 668, 1638, 646, 1662, 646, 1660, 646, + 1660, 648 + ], ignore) + analyse.dump_constants(message, defs, "TEST", output) + self.assertEqual(defs, [ + 'const uint16_t kTESTHdrMark = 9008;', + 'const uint16_t kTESTBitMark = 650;', + 'const uint16_t kTESTHdrSpace = 4496;', + 'const uint16_t kTESTOneSpace = 1657;', + 'const uint16_t kTESTZeroSpace = 554;', + 'const uint16_t kTESTSpaceGap = 19990;', + 'const uint16_t kTESTFreq = 38000; // Hz. (Guessing the most common ' + 'frequency.)' + ]) + self.assertEqual( + output.getvalue(), 'Guessing key value:\n' + 'kTESTHdrMark = 9008\n' + 'kTESTHdrSpace = 4496\n' + 'kTESTBitMark = 650\n' + 'kTESTOneSpace = 1657\n' + 'kTESTZeroSpace = 554\n' + 'kTESTSpaceGap = 19990\n') + + def test_convert_rawdata(self): + """Tests for the convert_rawdata() function.""" + # trivial cases + self.assertEqual(analyse.convert_rawdata("0"), [0]) + with self.assertRaises(ValueError) as context: + analyse.convert_rawdata("") + self.assertEqual( + str(context.exception), "Raw Data contains a non-numeric value of ''.") + + # Single parenthesis + self.assertEqual(analyse.convert_rawdata("foo {10"), [10]) + self.assertEqual(analyse.convert_rawdata("20} bar"), [20]) + + # No parentheses + self.assertEqual(analyse.convert_rawdata("10,20 , 30"), [10, 20, 30]) + + # Dual parentheses + self.assertEqual(analyse.convert_rawdata("{10,20 , 30}"), [10, 20, 30]) + self.assertEqual(analyse.convert_rawdata("foo{10,20}bar"), [10, 20]) + + # Many parentheses + self.assertEqual(analyse.convert_rawdata("foo{10,20}{bar}"), [10, 20]) + self.assertEqual(analyse.convert_rawdata("foo{10,20}{bar}}{"), [10, 20]) + + # Bad parentheses + with self.assertRaises(ValueError) as context: + analyse.convert_rawdata("}10{") + self.assertEqual( + str(context.exception), + "Raw Data not parsible due to parentheses placement.") + + # Non base-10 values + with self.assertRaises(ValueError) as context: + analyse.convert_rawdata("10, 20, foo, bar, 30") + self.assertEqual( + str(context.exception), + "Raw Data contains a non-numeric value of 'foo'.") + + # A messy usual "good" case. + input_str = """uint16_t rawbuf[6] = { + 9008, 4496, 644, + 1660, 676, + + 530} + ;""" + self.assertEqual( + analyse.convert_rawdata(input_str), [9008, 4496, 644, 1660, 676, 530]) + + def test_parse_and_report(self): + """Tests for the parse_and_report() function.""" + + # Without code generation. + output = StringIO() + input_str = """ + uint16_t rawbuf[139] = {9008, 4496, 644, 1660, 676, 530, 648, 558, 672, + 1636, 646, 1660, 644, 556, 650, 584, 626, 560, 644, 580, 628, 1680, + 624, 560, 648, 1662, 644, 582, 648, 536, 674, 530, 646, 580, 628, + 560, 670, 532, 646, 562, 644, 556, 672, 536, 648, 1662, 646, 1660, + 652, 554, 644, 558, 672, 538, 644, 560, 668, 560, 648, 1638, 668, + 536, 644, 1660, 668, 532, 648, 560, 648, 1660, 674, 554, 622, 19990, + 646, 580, 624, 1660, 648, 556, 648, 558, 674, 556, 622, 560, 644, + 564, 668, 536, 646, 1662, 646, 1658, 672, 534, 648, 558, 644, 562, + 648, 1662, 644, 584, 622, 558, 648, 562, 668, 534, 670, 536, 670, + 532, 672, 536, 646, 560, 646, 558, 648, 558, 670, 534, 650, 558, + 646, 560, 646, 560, 668, 1638, 646, 1662, 646, 1660, 646, 1660, + 648};""" + analyse.parse_and_report(input_str, 200, False, "FOO", output) + self.assertEqual( + output.getvalue(), 'Found 139 timing entries.\n' + 'Potential Mark Candidates:\n' + '[9008, 676]\n' + 'Potential Space Candidates:\n' + '[19990, 4496, 1680, 584]\n' + '\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kFOOHdrMark = 9008\n' + 'kFOOHdrSpace = 4496\n' + 'kFOOBitMark = 650\n' + 'kFOOOneSpace = 1657\n' + 'kFOOZeroSpace = 554\n' + 'kFOOSpaceGap = 19990\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kFOOHdrMark+kFOOHdrSpace+10011000010100000000011000001010010GAP(19990)' + '\n' + ' Bits: 35\n' + ' Hex: 0x4C2803052 (MSB first)\n' + ' 0x250600A19 (LSB first)\n' + ' Dec: 20443050066 (MSB first)\n' + ' 9938405913 (LSB first)\n' + ' Bin: 0b10011000010100000000011000001010010 (MSB first)\n' + ' 0b01001010000011000000000101000011001 (LSB first)\n' + 'kFOOBitMark(UNEXPECTED)01000000110001000000000000001111\n' + ' Bits: 32\n' + ' Hex: 0x40C4000F (MSB first)\n' + ' 0xF0002302 (LSB first)\n' + ' Dec: 1086586895 (MSB first)\n' + ' 4026540802 (LSB first)\n' + ' Bin: 0b01000000110001000000000000001111 (MSB first)\n' + ' 0b11110000000000000010001100000010 (LSB first)\n' + '\n' + 'Total Nr. of suspected bits: 67\n') + + # With code generation. + output = StringIO() + input_str = """ + uint16_t rawbuf[37] = {7930, 3952, 494, 1482, 520, 1482, 494, + 1508, 494, 520, 494, 1482, 494, 520, 494, 1482, 494, 1482, 494, + 3978, 494, 520, 494, 520, 494, 520, 494, 520, 520, 520, 494, 520, + 494, 520, 494, 1482, 494};""" + analyse.parse_and_report(input_str, 200, True, "FOO", output) + self.assertEqual( + output.getvalue(), 'Found 37 timing entries.\n' + 'Potential Mark Candidates:\n' + '[7930, 520]\n' + 'Potential Space Candidates:\n' + '[3978, 1508, 520]\n' + '\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kFOOHdrMark = 7930\n' + 'kFOOHdrSpace = 3965\n' + 'kFOOBitMark = 496\n' + 'kFOOOneSpace = 1485\n' + 'kFOOZeroSpace = 520\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kFOOHdrMark+kFOOHdrSpace+11101011\n' + ' Bits: 8\n' + ' Hex: 0xEB (MSB first)\n' + ' 0xD7 (LSB first)\n' + ' Dec: 235 (MSB first)\n' + ' 215 (LSB first)\n' + ' Bin: 0b11101011 (MSB first)\n' + ' 0b11010111 (LSB first)\n' + 'UNEXPECTED->kFOOHdrSpace+00000001\n' + ' Bits: 8\n' + ' Hex: 0x01 (MSB first)\n' + ' 0x80 (LSB first)\n' + ' Dec: 1 (MSB first)\n' + ' 128 (LSB first)\n' + ' Bin: 0b00000001 (MSB first)\n' + ' 0b10000000 (LSB first)\n' + '\n' + 'Total Nr. of suspected bits: 16\n' + '\n' + 'Generating a VERY rough code outline:\n' + '\n' + '// Copyright 2019 David Conran (crankyoldgit)\n' + '// Support for FOO 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 kFOOHdrMark = 7930;\n' + 'const uint16_t kFOOBitMark = 496;\n' + 'const uint16_t kFOOHdrSpace = 3965;\n' + 'const uint16_t kFOOOneSpace = 1485;\n' + 'const uint16_t kFOOZeroSpace = 520;\n' + 'const uint16_t kFOOFreq = 38000; // Hz. (Guessing the most common' + ' frequency.)\n' + 'const uint16_t kFOOBits = 16; // Move to IRremoteESP8266.h\n' + 'const uint16_t kFOOOverhead = 5;\n' + '#if SEND_FOO\n' + '// Function should be safe up to 64 bits.\n' + 'void IRsend::sendFOO(const uint64_t data, const uint16_t nbits,' + ' const uint16_t repeat) {\n' + ' enableIROut(kFOOFreq);\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' uint64_t send_data = data;\n' + ' // Header\n' + ' mark(kFOOHdrMark);\n' + ' space(kFOOHdrSpace);\n' + ' // Data Section #1\n' + ' // e.g. data = 0xEB, nbits = 8\n' + ' sendData(kFOOBitMark, kFOOOneSpace, kFOOBitMark, kFOOZeroSpace,' + ' send_data, 8, true);\n' + ' send_data >>= 8;\n' + ' // Footer\n' + ' mark(kFOOBitMark);\n' + ' space(kFOOHdrSpace);\n' + ' // Data Section #2\n' + ' // e.g. data = 0x1, nbits = 8\n' + ' sendData(kFOOBitMark, kFOOOneSpace, kFOOBitMark, kFOOZeroSpace,' + ' send_data, 8, true);\n' + ' send_data >>= 8;\n' + ' // Footer\n' + ' mark(kFOOBitMark);\n' + ' space(kDefaultMessageGap); // A 100% made up guess of the gap' + ' between messages.\n' + ' }\n' + '}\n' + '#endif // SEND_FOO\n' + '\n' + '#if DECODE_FOO\n' + '// Function should be safe up to 64 bits.\n' + 'bool IRrecv::decodeFOO(decode_results *results, const uint16_t nbits,' + ' const bool strict) {\n' + ' if (results->rawlen < 2 * nbits + kFOOOverhead)\n' + ' return false; // Too short a message to match.\n' + ' if (strict && nbits != kFOOBits)\n' + ' return false;\n' + '\n' + ' uint16_t offset = kStartOffset;\n' + ' uint64_t data = 0;\n' + ' match_result_t data_result;\n' + '\n' + ' // Header\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOHdrMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kFOOHdrSpace))\n' + ' return false;\n' + '\n' + ' // Data Section #1\n' + ' // e.g. data_result.data = 0xEB, nbits = 8\n' + ' data_result = matchData(&(results->rawbuf[offset]), 8,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace);\n' + ' offset += data_result.used;\n' + ' if (data_result.success == false) return false; // Fail\n' + ' data <<= 8; // Make room for the new bits of data.\n' + ' data |= data_result.data;\n' + '\n' + ' // Footer\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOBitMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kFOOHdrSpace))\n' + ' return false;\n' + '\n' + ' // Data Section #2\n' + ' // e.g. data_result.data = 0x1, nbits = 8\n' + ' data_result = matchData(&(results->rawbuf[offset]), 8,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace);\n' + ' offset += data_result.used;\n' + ' if (data_result.success == false) return false; // Fail\n' + ' data <<= 8; // Make room for the new bits of data.\n' + ' data |= data_result.data;\n' + '\n' + ' // Footer\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOBitMark))\n' + ' return false;\n' + '\n' + ' // Success\n' + ' results->decode_type = decode_type_t::FOO;\n' + ' results->bits = nbits;\n' + ' results->value = data;\n' + ' results->command = 0;\n' + ' results->address = 0;\n' + ' return true;\n' + '}\n' + '#endif // DECODE_FOO\n') + + def test_reduce_list(self): + """Tests for the reduce_list method.""" + + ignore = StringIO() + message = analyse.RawIRMessage(200, [ + 7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, + 520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494, + 520, 520, 520, 494, 520, 494, 520, 494, 1482, 494 + ], ignore) + test_space_data = [4496, 1660, 530, 558, 1636, 1660, 556] + result_list, result_dict = message.reduce_list(test_space_data) + self.assertEqual([4496, 1660, 558], result_list) + self.assertEqual({ + 558: [558, 556, 530], + 1660: [1660, 1660, 1636], + 4496: [4496] + }, result_dict) + + def test_leader_marks(self): + """Tests for leader-type marks in parse_and_report() function.""" + + # Ref Issue #973 + output = StringIO() + input_str = """ + uint16_t rawData[853] = { + 29784, 49290, 3416, 1604, 464, 1210, 468, 372, 460, 374, 462, 374, + 466, 368, 464, 372, 462, 374, 464, 374, 464, 368, 464, 370, 464, 370, + 466, 370, 464, 1208, 464, 374, 462, 372, 466, 374, 464, 370, 462, 372, + 464, 370, 466, 370, 464, 372, 462, 374, 462, 374, 462, 378, 460, 370, + 460, 374, 464, 372, 462, 372, 464, 374, 466, 368, 464, 1210, 464, 374, + 466, 1202, 464, 1206, 464, 1210, 466, 1206, 468, 1204, 464, 1210, 466, + 370, 462, 1214, 460, 1208, 464, 1206, 464, 1208, 466, 1208, 464, 1206, + 466, 1208, 464, 1206, 466, 1212, 464, 370, 464, 370, 462, 374, 462, + 374, 462, 374, 462, 374, 462, 372, 464, 376, 460, 372, 462, 374, 466, + 1204, 464, 1210, 464, 372, 460, 374, 462, 1208, 464, 1212, 464, 1202, + 468, 1204, 464, 374, 460, 374, 466, 1208, 462, 1210, 462, 374, 462, + 376, 464, 368, 466, 1204, 462, 374, 466, 372, 464, 1206, 462, 376, + 460, 376, 464, 1210, 462, 1208, 462, 372, 466, 1206, 464, 1208, 466, + 372, 462, 1210, 462, 1210, 466, 374, 468, 1202, 464, 1206, 466, 374, + 462, 372, 464, 1208, 464, 374, 464, 372, 464, 376, 462, 370, 466, 368, + 464, 1208, 462, 1210, 460, 374, 464, 1208, 466, 1206, 464, 1214, 464, + 368, 462, 374, 462, 1212, 460, 1210, 466, 1206, 466, 370, 462, 1210, + 464, 416, 424, 1202, 466, 1220, 448, 376, 464, 372, 462, 372, 462, + 1212, 462, 374, 460, 1214, 468, 364, 468, 370, 462, 372, 462, 376, + 458, 374, 464, 372, 462, 376, 464, 376, 462, 1204, 464, 1210, 462, + 1210, 464, 1208, 466, 1208, 464, 1206, 462, 1210, 464, 1212, 464, 368, + 462, 372, 464, 372, 464, 372, 464, 372, 466, 370, 466, 370, 464, 376, + 464, 1202, 464, 1212, 464, 1204, 464, 1210, 462, 1208, 464, 1212, 462, + 1210, 464, 1212, 460, 372, 462, 374, 462, 374, 466, 370, 462, 374, 462, + 372, 464, 372, 462, 376, 462, 1206, 464, 1206, 466, 1210, 462, 1208, + 464, 1210, 466, 1204, 464, 1210, 462, 1214, 462, 368, 462, 374, 466, + 370, 462, 376, 466, 368, 466, 370, 462, 414, 424, 374, 464, 1206, 464, + 1206, 464, 1206, 468, 1206, 466, 1206, 466, 1210, 462, 1206, 464, 1214, + 468, 364, 466, 372, 466, 370, 462, 372, 462, 374, 464, 372, 462, 374, + 460, 376, 466, 1204, 464, 1208, 462, 1210, 464, 1206, 464, 1210, 464, + 1208, 464, 1208, 466, 1210, 462, 1206, 466, 1206, 466, 372, 462, 374, + 466, 1206, 466, 370, 464, 1206, 466, 376, 464, 368, 462, 372, 466, + 1206, 464, 1206, 464, 374, 466, 1204, 464, 374, 466, 1206, 466, 1204, + 468, 368, 466, 370, 466, 370, 462, 1212, 462, 1210, 462, 1210, 462, + 1214, 464, 368, 464, 1206, 466, 1206, 466, 1206, 464, 374, 464, 370, + 466, 370, 462, 378, 466, 366, 464, 372, 466, 368, 466, 370, 464, 370, + 462, 372, 462, 374, 464, 374, 464, 1202, 466, 1206, 462, 1208, 466, + 1208, 466, 1208, 464, 1210, 462, 1206, 464, 1212, 464, 368, 464, 372, + 464, 370, 468, 368, 462, 376, 462, 372, 466, 370, 464, 376, 462, 1206, + 464, 1210, 462, 1212, 462, 1208, 464, 1208, 462, 1212, 466, 1246, 424, + 1212, 464, 368, 464, 372, 466, 370, 464, 372, 462, 374, 464, 372, 464, + 370, 462, 1212, 466, 1206, 462, 1206, 464, 1210, 466, 1206, 462, 1208, + 464, 1250, 422, 1208, 468, 372, 464, 1204, 466, 1206, 466, 370, 462, + 374, 462, 376, 460, 374, 466, 370, 462, 376, 464, 368, 462, 376, 462, + 1210, 462, 1208, 464, 1206, 466, 1206, 464, 1208, 468, 1212, 460, 1206, + 464, 372, 464, 372, 466, 370, 462, 374, 466, 370, 466, 370, 466, 374, + 464, 368, 462, 1210, 462, 1210, 464, 1210, 462, 1208, 462, 1212, 464, + 1206, 466, 1208, 466, 366, 464, 374, 460, 374, 462, 1208, 466, 372, + 462, 374, 462, 374, 464, 1212, 468, 1202, 464, 1208, 466, 1204, 464, + 376, 460, 1208, 468, 1208, 462, 1208, 464, 378, 460, 372, 460, 372, + 462, 376, 464, 372, 462, 374, 460, 374, 464, 370, 462, 378, 464, 1202, + 468, 1204, 468, 1204, 466, 1208, 466, 1208, 464, 1210, 460, 1212, 462, + 1212, 464, 366, 466, 370, 464, 372, 466, 370, 464, 372, 462, 414, 424, + 372, 466, 372, 460, 1206, 466, 1206, 466, 1206, 466, 1208, 466, 1206, + 464, 1208, 466, 1208, 462, 1212, 468, 1202, 466, 1204, 470, 1204, 468, + 1204, 466, 1206, 466, 1206, 464, 1210, 462, 1212, 468, 366, 464, 372, + 462, 374, 460, 374, 460, 374, 466, 410, 424, 372, 460, 378, 466, 1200, + 464, 1212, 462, 1210, 464, 1210, 466, 1206, 462, 1208, 464, 1210, 464, + 1210, 464, 366, 462, 376, 462, 374, 460, 376, 462, 372, 466, 374, 460, + 372, 462, 378, 462, 1202, 468, 1206, 464, 1208, 466, 1208, 462, 1208, + 464, 1208, 468, 1204, 464, 1212, 466, 368, 462, 374, 466, 372, 464, + 370, 462, 374, 464, 370, 462, 376, 464, 374, 462, 1206, 464, 1208, 462, + 1210, 466, 1208, 460, 1210, 468, 1206, 462, 1210, 464, 1212, 466, 366, + 464, 374, 462, 372, 466, 370, 462, 374, 464, 372, 464, 370, 464, 374, + 462};""" + analyse.parse_and_report(input_str, 200, True, "Hitachi", output) + self.assertEqual( + output.getvalue(), 'Found 853 timing entries.\n' + 'Potential Mark Candidates:\n' + '[29784, 3416, 470]\n' + 'Potential Space Candidates:\n' + '[49290, 1604, 1250, 416]\n' + 'DANGER: Unusual number of mark timings!\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kHitachiHdrMark = 3416\n' + 'kHitachiHdrSpace = 1604\n' + 'kHitachiBitMark = 463\n' + 'kHitachiOneSpace = 1208\n' + 'kHitachiZeroSpace = 372\n' + 'kHitachiLdrMark = 29784\n' + 'kHitachiSpaceGap = 49290\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kHitachiLdrMark+UNEXPECTED->GAP(49290)kHitachiHdrMark+' + 'kHitachiHdrSpace+100000000000100000000000000000101111110111111111' + '0000000000110011110011000100100110110110110010000011011100111010110001' + '010000000011111111000000001111111100000000111111110000000011111111' + '0000000011111111110010100011010110001111011100000000000011111111' + '0000000011111111000000011111111011000000001111111000000001111111' + '0001000111101110000000001111111100000000111111111111111100000000' + '111111110000000011111111000000001111111100000000\n' + ' Bits: 424\n' + ' Hex: 0x80080002FDFF0033CC49B6C8373AC500FF00FF00FF00FF00FFCA358F7000' + 'FF00FF01FEC03F807F11EE00FF00FFFF00FF00FF00FF00 (MSB first)\n' + ' 0x00FF00FF00FF00FFFF00FF007788FE01FC037F80FF00FF000EF1AC53FF00' + 'FF00FF00FF00FF00A35CEC136D9233CC00FFBF40001001 (LSB first)\n' + ' Dec: 21666770463250971033249250747302630158357464218891161163035832' + '525825434564377831675503794869126268735511944198247894513495375616' + ' (MSB first)\n' + ' 16857184424372658669179408622645041920057617761062334415219526' + '0950249734545225589859643087812860908833344117446370839379316737' + ' (LSB first)\n' + ' Bin: 0b100000000000100000000000000000101111110111111111000000000011' + '00111100110001001001101101101100100000110111001110101100010100000000' + '1111111100000000111111110000000011111111000000001111111100000000' + '1111111111001010001101011000111101110000000000001111111100000000' + '1111111100000001111111101100000000111111100000000111111100010001' + '1110111000000000111111110000000011111111111111110000000011111111' + '0000000011111111000000001111111100000000 (MSB first)\n' + ' 0b000000001111111100000000111111110000000011111111000000001111' + '11111111111100000000111111110000000001110111100010001111111000000001' + '1111110000000011011111111000000011111111000000001111111100000000' + '0000111011110001101011000101001111111111000000001111111100000000' + '1111111100000000111111110000000011111111000000001010001101011100' + '1110110000010011011011011001001000110011110011000000000011111111' + '1011111101000000000000000001000000000001 (LSB first)\n' + '\n' + 'Total Nr. of suspected bits: 424\n' + '\n' + 'Generating a VERY rough code outline:\n' + '\n' + '// Copyright 2019 David Conran (crankyoldgit)\n' + '// Support for Hitachi 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 kHitachiHdrMark = 3416;\n' + 'const uint16_t kHitachiBitMark = 463;\n' + 'const uint16_t kHitachiHdrSpace = 1604;\n' + 'const uint16_t kHitachiOneSpace = 1208;\n' + 'const uint16_t kHitachiZeroSpace = 372;\n' + 'const uint16_t kHitachiLdrMark = 29784;\n' + 'const uint16_t kHitachiSpaceGap = 49290;\n' + 'const uint16_t kHitachiFreq = 38000; // Hz. (Guessing the most' + ' common frequency.)\n' + 'const uint16_t kHitachiBits = 424; // Move to IRremoteESP8266.h\n' + 'const uint16_t kHitachiStateLength = 53; // Move to IRremoteESP8266.h' + '\n' + 'const uint16_t kHitachiOverhead = 5;\n' + "// DANGER: More than 64 bits detected. A uint64_t for 'data' won't" + ' work!\n' + '#if SEND_HITACHI\n' + '// Function should be safe up to 64 bits.\n' + 'void IRsend::sendHitachi(const uint64_t data, const uint16_t nbits,' + ' const uint16_t repeat) {\n' + ' enableIROut(kHitachiFreq);\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' uint64_t send_data = data;\n' + ' // Leader\n' + ' mark(kHitachiLdrMark);\n' + ' // Gap\n' + ' space(kHitachiSpaceGap);\n' + ' // Header\n' + ' mark(kHitachiHdrMark);\n' + ' space(kHitachiHdrSpace);\n' + ' // Data Section #1\n' + ' // e.g. data = 0x80080002FDFF0033CC49B6C8373AC500FF00FF00FF00FF00' + 'FFCA358F7000FF00FF01FEC03F807F11EE00FF00FFFF00FF00FF00FF00,' + ' nbits = 424\n' + ' sendData(kHitachiBitMark, kHitachiOneSpace, kHitachiBitMark,' + ' kHitachiZeroSpace, send_data, 424, true);\n' + ' send_data >>= 424;\n' + ' // Footer\n' + ' mark(kHitachiBitMark);\n' + ' space(kDefaultMessageGap); // A 100% made up guess of the gap' + ' between messages.\n' + ' }\n' + '}\n' + '#endif // SEND_HITACHI\n' + '\n' + '#if SEND_HITACHI\n' + '// Alternative >64bit function to send HITACHI messages\n' + '// Where data is:\n' + '// uint8_t data[kHitachiStateLength] = {0x80, 0x08, 0x00, 0x02,' + ' 0xFD, 0xFF, 0x00, 0x33, 0xCC, 0x49, 0xB6, 0xC8, 0x37, 0x3A, 0xC5,' + ' 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xCA,' + ' 0x35, 0x8F, 0x70, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0xFE, 0xC0, 0x3F,' + ' 0x80, 0x7F, 0x11, 0xEE, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF,' + ' 0x00, 0xFF, 0x00, 0xFF, 0x00};\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.' + ' (>=kHitachiStateLength)\n' + '// repeat: Nr. of times the message is to be repeated.\n' + '//\n' + '// Status: ALPHA / Untested.\n' + 'void IRsend::sendHitachi(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 = 424; bytes = 53;\n' + ' // *(data + pos) = {0x80, 0x08, 0x00, 0x02, 0xFD, 0xFF, 0x00,' + ' 0x33, 0xCC, 0x49, 0xB6, 0xC8, 0x37, 0x3A, 0xC5, 0x00, 0xFF, 0x00,' + ' 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xCA, 0x35, 0x8F, 0x70,' + ' 0x00, 0xFF, 0x00, 0xFF, 0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F, 0x11,' + ' 0xEE, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,' + ' 0xFF, 0x00};\n' + ' sendGeneric(kHitachiHdrMark, kHitachiHdrSpace,\n' + ' kHitachiBitMark, kHitachiOneSpace,\n' + ' kHitachiBitMark, kHitachiZeroSpace,\n' + ' kHitachiBitMark, kHitachiSpaceGap,\n' + ' data + pos, 53, // Bytes\n' + ' kHitachiFreq, true, kNoRepeat, kDutyDefault);\n' + ' pos += 53; // Adjust by how many bytes of data we sent\n' + ' }\n' + '}\n' + '#endif // SEND_HITACHI\n' + '\n' + "// DANGER: More than 64 bits detected. A uint64_t for 'data' won't" + ' work!\n' + '#if DECODE_HITACHI\n' + '// Function should be safe up to 64 bits.\n' + 'bool IRrecv::decodeHitachi(decode_results *results,' + ' const uint16_t nbits, const bool strict) {\n' + ' if (results->rawlen < 2 * nbits + kHitachiOverhead)\n' + ' return false; // Too short a message to match.\n' + ' if (strict && nbits != kHitachiBits)\n' + ' return false;\n' + '\n' + ' uint16_t offset = kStartOffset;\n' + ' uint64_t data = 0;\n' + ' match_result_t data_result;\n' + '\n' + ' // Leader\n' + ' if (!matchMark(results->rawbuf[offset++], kHitachiLdrMark))\n' + ' return false;\n' + '\n' + ' // Gap\n' + ' if (!matchSpace(results->rawbuf[offset++], kHitachiSpaceGap))\n' + ' return false;\n' + '\n' + ' // Header\n' + ' if (!matchMark(results->rawbuf[offset++], kHitachiHdrMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kHitachiHdrSpace))\n' + ' return false;\n' + '\n' + ' // Data Section #1\n' + ' // e.g. data_result.data = 0x80080002FDFF0033CC49B6C8373AC500FF00FF' + '00FF00FF00FFCA358F7000FF00FF01FEC03F807F11EE00FF00FFFF00FF00FF00FF00,' + ' nbits = 424\n' + ' data_result = matchData(&(results->rawbuf[offset]), 424,\n' + ' kHitachiBitMark, kHitachiOneSpace,\n' + ' kHitachiBitMark, kHitachiZeroSpace);\n' + ' offset += data_result.used;\n' + ' if (data_result.success == false) return false; // Fail\n' + ' data <<= 424; // Make room for the new bits of data.\n' + ' data |= data_result.data;\n' + '\n' + ' // Footer\n' + ' if (!matchMark(results->rawbuf[offset++], kHitachiBitMark))\n' + ' return false;\n' + '\n' + ' // Success\n' + ' results->decode_type = decode_type_t::HITACHI;\n' + ' results->bits = nbits;\n' + ' results->value = data;\n' + ' results->command = 0;\n' + ' results->address = 0;\n' + ' return true;\n' + '}\n' + '#endif // DECODE_HITACHI\n' + '\n' + '// Note: This should be 64+ bit safe.\n' + '#if DECODE_HITACHI\n' + '// Function should be safe over 64 bits.\n' + 'bool IRrecv::decodeHitachi(decode_results *results,' + ' const uint16_t nbits, const bool strict) {\n' + ' if (results->rawlen < 2 * nbits + kHitachiOverhead)\n' + ' return false; // Too short a message to match.\n' + ' if (strict && nbits != kHitachiBits)\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 = 424; bytes = 53;\n' + ' // *(results->state + pos) = {0x80, 0x08, 0x00, 0x02, 0xFD, 0xFF,' + ' 0x00, 0x33, 0xCC, 0x49, 0xB6, 0xC8, 0x37, 0x3A, 0xC5, 0x00, 0xFF,' + ' 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xCA, 0x35, 0x8F,' + ' 0x70, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F,' + ' 0x11, 0xEE, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF,' + ' 0x00, 0xFF, 0x00};\n' + ' used = matchGeneric(results->rawbuf + offset,' + ' results->state + pos,\n' + ' results->rawlen - offset, 424,\n' + ' kHitachiHdrMark, kHitachiHdrSpace,\n' + ' kHitachiBitMark, kHitachiOneSpace,\n' + ' kHitachiBitMark, kHitachiZeroSpace,\n' + ' kHitachiBitMark, kHitachiSpaceGap, 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 += 53; // Adjust by how many bytes of data we read\n' + '\n' + ' // Success\n' + ' results->decode_type = decode_type_t::HITACHI;\n' + ' results->bits = nbits;\n' + ' return true;\n' + '}\n' + '#endif // DECODE_HITACHI\n') + + def test_unusual_gaps(self): + """Tests for unusual Space Gaps in parse_and_report() function.""" + + # Tests for unusual Gaps. (Issue #482) + output = StringIO() + input_str = """ + uint16_t rawbuf[272] = {3485, 3512, 864, 864, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, + 864, 2620, 864, 864, 864, 2620, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, 864, 864, 864, 864, 864, 2620, 864, 864, + 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, + 3485, 3512, 864, 864, 864, 2620, 864, 864, 864, 2620, 864, 2620, + 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, 2620, 864, 864, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, + 3485, 3512, 864, 13996, + 3485, 3512, 864, 864, 864, 864, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 864, 864, 2620, + 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 864, + 864, 864, 864, 864, 864, 2620, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 864, 864, 864, + 3485, 3512, 864, 864, 864, 864, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 864, 864, 2620, + 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 864, + 864, 864, 864, 864, 864, 2620, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 864, 864, 864, 3485, 3512, 864, 13996};""" + analyse.parse_and_report(input_str, 200, True, "FOO", output) + self.assertEqual( + output.getvalue(), 'Found 272 timing entries.\n' + 'Potential Mark Candidates:\n' + '[3485, 864]\n' + 'Potential Space Candidates:\n' + '[13996, 3512, 2620, 864]\n' + '\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kFOOHdrMark = 3485\n' + 'kFOOHdrSpace = 3512\n' + 'kFOOBitMark = 864\n' + 'kFOOOneSpace = 2620\n' + 'kFOOZeroSpace = 864\n' + 'kFOOSpaceGap = 13996\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kFOOHdrMark+kFOOHdrSpace+01011111010111110100000001000000\n' + ' Bits: 32\n' + ' Hex: 0x5F5F4040 (MSB first)\n' + ' 0x0202FAFA (LSB first)\n' + ' Dec: 1600077888 (MSB first)\n' + ' 33749754 (LSB first)\n' + ' Bin: 0b01011111010111110100000001000000 (MSB first)\n' + ' 0b00000010000000101111101011111010 (LSB first)\n' + 'kFOOHdrMark+kFOOHdrSpace+01011111010111110100000001000000\n' + ' Bits: 32\n' + ' Hex: 0x5F5F4040 (MSB first)\n' + ' 0x0202FAFA (LSB first)\n' + ' Dec: 1600077888 (MSB first)\n' + ' 33749754 (LSB first)\n' + ' Bin: 0b01011111010111110100000001000000 (MSB first)\n' + ' 0b00000010000000101111101011111010 (LSB first)\n' + 'kFOOHdrMark+kFOOHdrSpace+GAP(13996)kFOOHdrMark+kFOOHdrSpace+0010111100' + '1011110110110001101100\n' + ' Bits: 32\n' + ' Hex: 0x2F2F6C6C (MSB first)\n' + ' 0x3636F4F4 (LSB first)\n' + ' Dec: 791637100 (MSB first)\n' + ' 909571316 (LSB first)\n' + ' Bin: 0b00101111001011110110110001101100 (MSB first)\n' + ' 0b00110110001101101111010011110100 (LSB first)\n' + 'kFOOHdrMark+kFOOHdrSpace+00101111001011110110110001101100\n' + ' Bits: 32\n' + ' Hex: 0x2F2F6C6C (MSB first)\n' + ' 0x3636F4F4 (LSB first)\n' + ' Dec: 791637100 (MSB first)\n' + ' 909571316 (LSB first)\n' + ' Bin: 0b00101111001011110110110001101100 (MSB first)\n' + ' 0b00110110001101101111010011110100 (LSB first)\n' + 'kFOOHdrMark+kFOOHdrSpace+GAP(13996)\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 FOO 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 kFOOHdrMark = 3485;\n' + 'const uint16_t kFOOBitMark = 864;\n' + 'const uint16_t kFOOHdrSpace = 3512;\n' + 'const uint16_t kFOOOneSpace = 2620;\n' + 'const uint16_t kFOOZeroSpace = 864;\n' + 'const uint16_t kFOOSpaceGap = 13996;\n' + 'const uint16_t kFOOFreq = 38000; // Hz. (Guessing the most common' + ' frequency.)\n' + 'const uint16_t kFOOBits = 128; // Move to IRremoteESP8266.h\n' + 'const uint16_t kFOOStateLength = 16; // Move to IRremoteESP8266.h\n' + 'const uint16_t kFOOOverhead = 16;\n' + "// DANGER: More than 64 bits detected. A uint64_t for 'data' won't" + ' work!\n' + '#if SEND_FOO\n' + '// Function should be safe up to 64 bits.\n' + 'void IRsend::sendFOO(const uint64_t data, const uint16_t nbits,' + ' const uint16_t repeat) {\n' + ' enableIROut(kFOOFreq);\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' uint64_t send_data = data;\n' + ' // Header\n' + ' mark(kFOOHdrMark);\n' + ' space(kFOOHdrSpace);\n' + ' // Data Section #1\n' + ' // e.g. data = 0x5F5F4040, nbits = 32\n' + ' sendData(kFOOBitMark, kFOOOneSpace, kFOOBitMark, kFOOZeroSpace,' + ' send_data, 32, true);\n' + ' send_data >>= 32;\n' + ' // Header\n' + ' mark(kFOOHdrMark);\n' + ' space(kFOOHdrSpace);\n' + ' // Data Section #2\n' + ' // e.g. data = 0x5F5F4040, nbits = 32\n' + ' sendData(kFOOBitMark, kFOOOneSpace, kFOOBitMark, kFOOZeroSpace,' + ' send_data, 32, true);\n' + ' send_data >>= 32;\n' + ' // Header\n' + ' mark(kFOOHdrMark);\n' + ' space(kFOOHdrSpace);\n' + ' // Gap\n' + ' mark(kFOOBitMark);\n' + ' space(kFOOSpaceGap);\n' + ' // Header\n' + ' mark(kFOOHdrMark);\n' + ' space(kFOOHdrSpace);\n' + ' // Data Section #3\n' + ' // e.g. data = 0x2F2F6C6C, nbits = 32\n' + ' sendData(kFOOBitMark, kFOOOneSpace, kFOOBitMark, kFOOZeroSpace,' + ' send_data, 32, true);\n' + ' send_data >>= 32;\n' + ' // Header\n' + ' mark(kFOOHdrMark);\n' + ' space(kFOOHdrSpace);\n' + ' // Data Section #4\n' + ' // e.g. data = 0x2F2F6C6C, nbits = 32\n' + ' sendData(kFOOBitMark, kFOOOneSpace, kFOOBitMark, kFOOZeroSpace,' + ' send_data, 32, true);\n' + ' send_data >>= 32;\n' + ' // Header\n' + ' mark(kFOOHdrMark);\n' + ' space(kFOOHdrSpace);\n' + ' // Gap\n' + ' mark(kFOOBitMark);\n' + ' space(kFOOSpaceGap);\n' + ' space(kDefaultMessageGap); // A 100% made up guess of the gap' + ' between messages.\n' + ' }\n' + '}\n' + '#endif // SEND_FOO\n' + '\n' + '#if SEND_FOO\n' + '// Alternative >64bit function to send FOO messages\n' + '// Where data is:\n' + '// uint8_t data[kFOOStateLength] = {0x5F, 0x5F, 0x40, 0x40, 0x5F,' + ' 0x5F, 0x40, 0x40, 0x2F, 0x2F, 0x6C, 0x6C, 0x2F, 0x2F, 0x6C, 0x6C};\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. (>=kFOOStateLength)\n' + '// repeat: Nr. of times the message is to be repeated.\n' + '//\n' + '// Status: ALPHA / Untested.\n' + 'void IRsend::sendFOO(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 = 32; bytes = 4;\n' + ' // *(data + pos) = {0x5F, 0x5F, 0x40, 0x40};\n' + ' sendGeneric(kFOOHdrMark, kFOOHdrSpace,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace,\n' + ' kFOOHdrMark, kFOOHdrSpace,\n' + ' data + pos, 4, // Bytes\n' + ' kFOOFreq, true, kNoRepeat, kDutyDefault);\n' + ' pos += 4; // Adjust by how many bytes of data we sent\n' + ' // Data Section #2\n' + ' // e.g.\n' + ' // bits = 32; bytes = 4;\n' + ' // *(data + pos) = {0x5F, 0x5F, 0x40, 0x40};\n' + ' sendGeneric(kFOOHdrMark, kFOOHdrSpace,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace,\n' + ' kFOOHdrMark, kFOOHdrSpace,\n' + ' data + pos, 4, // Bytes\n' + ' kFOOFreq, true, kNoRepeat, kDutyDefault);\n' + ' pos += 4; // Adjust by how many bytes of data we sent\n' + ' // Data Section #3\n' + ' // e.g.\n' + ' // bits = 32; bytes = 4;\n' + ' // *(data + pos) = {0x2F, 0x2F, 0x6C, 0x6C};\n' + ' sendGeneric(kFOOHdrMark, kFOOHdrSpace,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace,\n' + ' kFOOHdrMark, kFOOHdrSpace,\n' + ' data + pos, 4, // Bytes\n' + ' kFOOFreq, true, kNoRepeat, kDutyDefault);\n' + ' pos += 4; // Adjust by how many bytes of data we sent\n' + ' // Data Section #4\n' + ' // e.g.\n' + ' // bits = 32; bytes = 4;\n' + ' // *(data + pos) = {0x2F, 0x2F, 0x6C, 0x6C};\n' + ' sendGeneric(kFOOHdrMark, kFOOHdrSpace,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace,\n' + ' kFOOHdrMark, kFOOHdrSpace,\n' + ' data + pos, 4, // Bytes\n' + ' kFOOFreq, true, kNoRepeat, kDutyDefault);\n' + ' pos += 4; // Adjust by how many bytes of data we sent\n' + ' }\n' + '}\n' + '#endif // SEND_FOO\n' + '\n' + "// DANGER: More than 64 bits detected. A uint64_t for 'data' won't " + 'work!\n' + '#if DECODE_FOO\n' + '// Function should be safe up to 64 bits.\n' + 'bool IRrecv::decodeFOO(decode_results *results, const uint16_t nbits,' + ' const bool strict) {\n' + ' if (results->rawlen < 2 * nbits + kFOOOverhead)\n' + ' return false; // Too short a message to match.\n' + ' if (strict && nbits != kFOOBits)\n' + ' return false;\n' + '\n' + ' uint16_t offset = kStartOffset;\n' + ' uint64_t data = 0;\n' + ' match_result_t data_result;\n' + '\n' + ' // Header\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOHdrMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kFOOHdrSpace))\n' + ' return false;\n' + '\n' + ' // Data Section #1\n' + ' // e.g. data_result.data = 0x5F5F4040, nbits = 32\n' + ' data_result = matchData(&(results->rawbuf[offset]), 32,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace);\n' + ' offset += data_result.used;\n' + ' if (data_result.success == false) return false; // Fail\n' + ' data <<= 32; // Make room for the new bits of data.\n' + ' data |= data_result.data;\n' + '\n' + ' // Header\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOHdrMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kFOOHdrSpace))\n' + ' return false;\n' + '\n' + ' // Data Section #2\n' + ' // e.g. data_result.data = 0x5F5F4040, nbits = 32\n' + ' data_result = matchData(&(results->rawbuf[offset]), 32,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace);\n' + ' offset += data_result.used;\n' + ' if (data_result.success == false) return false; // Fail\n' + ' data <<= 32; // Make room for the new bits of data.\n' + ' data |= data_result.data;\n' + '\n' + ' // Header\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOHdrMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kFOOHdrSpace))\n' + ' return false;\n' + '\n' + ' // Gap\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOBitMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kFOOSpaceGap))\n' + ' return false;\n' + '\n' + ' // Header\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOHdrMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kFOOHdrSpace))\n' + ' return false;\n' + '\n' + ' // Data Section #3\n' + ' // e.g. data_result.data = 0x2F2F6C6C, nbits = 32\n' + ' data_result = matchData(&(results->rawbuf[offset]), 32,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace);\n' + ' offset += data_result.used;\n' + ' if (data_result.success == false) return false; // Fail\n' + ' data <<= 32; // Make room for the new bits of data.\n' + ' data |= data_result.data;\n' + '\n' + ' // Header\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOHdrMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kFOOHdrSpace))\n' + ' return false;\n' + '\n' + ' // Data Section #4\n' + ' // e.g. data_result.data = 0x2F2F6C6C, nbits = 32\n' + ' data_result = matchData(&(results->rawbuf[offset]), 32,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace);\n' + ' offset += data_result.used;\n' + ' if (data_result.success == false) return false; // Fail\n' + ' data <<= 32; // Make room for the new bits of data.\n' + ' data |= data_result.data;\n' + '\n' + ' // Header\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOHdrMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kFOOHdrSpace))\n' + ' return false;\n' + '\n' + ' // Gap\n' + ' if (!matchMark(results->rawbuf[offset++], kFOOBitMark))\n' + ' return false;\n' + ' if (!matchSpace(results->rawbuf[offset++], kFOOSpaceGap))\n' + ' return false;\n' + '\n' + ' // Success\n' + ' results->decode_type = decode_type_t::FOO;\n' + ' results->bits = nbits;\n' + ' results->value = data;\n' + ' results->command = 0;\n' + ' results->address = 0;\n' + ' return true;\n' + '}\n' + '#endif // DECODE_FOO\n' + '\n' + '// Note: This should be 64+ bit safe.\n' + '#if DECODE_FOO\n' + '// Function should be safe over 64 bits.\n' + 'bool IRrecv::decodeFOO(decode_results *results, const uint16_t nbits,' + ' const bool strict) {\n' + ' if (results->rawlen < 2 * nbits + kFOOOverhead)\n' + ' return false; // Too short a message to match.\n' + ' if (strict && nbits != kFOOBits)\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 = 32; bytes = 4;\n' + ' // *(results->state + pos) = {0x5F, 0x5F, 0x40, 0x40};\n' + ' used = matchGeneric(results->rawbuf + offset, results->state + pos,' + '\n' + ' results->rawlen - offset, 32,\n' + ' kFOOHdrMark, kFOOHdrSpace,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace,\n' + ' kFOOHdrMark, kFOOHdrSpace, 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 += 4; // Adjust by how many bytes of data we read\n' + '\n' + ' // Data Section #2\n' + ' // e.g.\n' + ' // bits = 32; bytes = 4;\n' + ' // *(results->state + pos) = {0x5F, 0x5F, 0x40, 0x40};\n' + ' used = matchGeneric(results->rawbuf + offset, results->state + pos,' + '\n' + ' results->rawlen - offset, 32,\n' + ' kFOOHdrMark, kFOOHdrSpace,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace,\n' + ' kFOOHdrMark, kFOOHdrSpace, 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 += 4; // Adjust by how many bytes of data we read\n' + '\n' + ' // Data Section #3\n' + ' // e.g.\n' + ' // bits = 32; bytes = 4;\n' + ' // *(results->state + pos) = {0x2F, 0x2F, 0x6C, 0x6C};\n' + ' used = matchGeneric(results->rawbuf + offset, results->state + pos,' + '\n' + ' results->rawlen - offset, 32,\n' + ' kFOOHdrMark, kFOOHdrSpace,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace,\n' + ' kFOOHdrMark, kFOOHdrSpace, 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 += 4; // Adjust by how many bytes of data we read\n' + '\n' + ' // Data Section #4\n' + ' // e.g.\n' + ' // bits = 32; bytes = 4;\n' + ' // *(results->state + pos) = {0x2F, 0x2F, 0x6C, 0x6C};\n' + ' used = matchGeneric(results->rawbuf + offset, results->state + pos,' + '\n' + ' results->rawlen - offset, 32,\n' + ' kFOOHdrMark, kFOOHdrSpace,\n' + ' kFOOBitMark, kFOOOneSpace,\n' + ' kFOOBitMark, kFOOZeroSpace,\n' + ' kFOOHdrMark, kFOOHdrSpace, 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 += 4; // Adjust by how many bytes of data we read\n' + '\n' + ' // Success\n' + ' results->decode_type = decode_type_t::FOO;\n' + ' results->bits = nbits;\n' + ' return true;\n' + '}\n' + '#endif // DECODE_FOO\n') + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/lib/IRremoteESP8266-2.6.5/tools/gc_decode.cpp b/lib/IRremoteESP8266-2.7.0/tools/gc_decode.cpp old mode 100755 new mode 100644 similarity index 65% rename from lib/IRremoteESP8266-2.6.5/tools/gc_decode.cpp rename to lib/IRremoteESP8266-2.7.0/tools/gc_decode.cpp index 52ffd17b7..a1d828d1c --- a/lib/IRremoteESP8266-2.6.5/tools/gc_decode.cpp +++ b/lib/IRremoteESP8266-2.7.0/tools/gc_decode.cpp @@ -1,4 +1,4 @@ -// Quick and dirty tool to decode GlobalCache (GC) codes +// Quick and dirty tool to decode Raw Codes, GlobalCache (GC) codes // and ProntoHex codes // Copyright 2017 Jorge Cisneros @@ -7,6 +7,7 @@ #include #include #include +#include "IRac.h" #include "IRsend.h" #include "IRsend_test.h" #include "IRutils.h" @@ -24,30 +25,38 @@ void str_to_uint16(char *str, uint16_t *res, uint8_t base) { } void usage_error(char *name) { - std::cerr << "Usage: " << name << " [-raw] " << std::endl - << "Usage: " << name << " -prontohex [-raw] " - << std::endl; + std::cerr << "Usage: " << name << " [-gc] [-rawdump] " + << std::endl + << "Usage: " << name << " -prontohex [-rawdump] " + << std::endl + << "Usage: " << name << " -raw [-rawdump] " << std::endl; } int main(int argc, char *argv[]) { int argv_offset = 1; bool dumpraw = false; - bool prontohex = false; - + enum decode_type_t input_type = GLOBALCACHE; + const uint16_t raw_freq = 38; // Check the invocation/calling usage. if (argc < 2 || argc > 4) { usage_error(argv[0]); return 1; } - if (strncmp("-prontohex", argv[argv_offset], 10) == 0) { - prontohex = true; + if (strncmp("-gc", argv[argv_offset], 3) == 0) { + argv_offset++; + } else if (strncmp("-prontohex", argv[argv_offset], 10) == 0) { + input_type = PRONTO; + argv_offset++; + } else if (strncmp("-raw", argv[argv_offset], 4) == 0) { + input_type = RAW; argv_offset++; } - if (strncmp("-raw", argv[argv_offset], 4) == 0) { + if (strncmp("-rawdump", argv[argv_offset], 7) == 0) { dumpraw = true; argv_offset++; } + if (argc - argv_offset != 1) { usage_error(argv[0]); return 1; @@ -59,8 +68,7 @@ int main(int argc, char *argv[]) { char *saveptr1; char *sep = const_cast(","); int codebase = 10; - - if (prontohex) { + if (input_type == PRONTO) { sep = const_cast(" "); codebase = 16; } @@ -77,10 +85,18 @@ int main(int argc, char *argv[]) { irsend.begin(); irsend.reset(); - if (prontohex) { - irsend.sendPronto(gc_test, index); - } else { - irsend.sendGC(gc_test, index); + switch (input_type) { + case GLOBALCACHE: + irsend.sendGC(gc_test, index); + break; + case PRONTO: + irsend.sendPronto(gc_test, index); + break; + case RAW: + irsend.sendRaw(gc_test, index, raw_freq); + break; + default: + break; } irsend.makeDecodeResult(); irrecv.decode(&irsend.capture); @@ -94,6 +110,10 @@ int main(int argc, char *argv[]) { for (uint16_t i = 0; i < irsend.capture.bits / 8; i++) printf("%02X", irsend.capture.state[i]); std::cout << std::endl; + String description = IRAcUtils::resultAcToString(&irsend.capture); + if (description.length()) { + std::cout << "Msg Description: " << description.c_str() << std::endl; + } } else { std::cout << "Code value 0x" << std::hex << irsend.capture.value << std::endl diff --git a/lib/IRremoteESP8266-2.7.0/tools/generate_irtext_h.sh b/lib/IRremoteESP8266-2.7.0/tools/generate_irtext_h.sh new file mode 100755 index 000000000..5b6e2e544 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.0/tools/generate_irtext_h.sh @@ -0,0 +1,36 @@ +#!/bin/bash +export INPUT="IRtext.cpp" +export OUTPUT="IRtext.h" + +if [[ ! -f ${INPUT} ]]; then + echo "Can't read file '${INPUT}'. Aborting!" + exit 1 +fi + +# Header +cat >${OUTPUT} << EOF +// Copyright 2019 - David Conran (@crankyoldgit) +// This header file is to be included in files **other than** 'IRtext.cpp'. +// +// WARNING: Do not edit this file! This file is automatically generated by +// 'tools/generate_irtext_h.sh'. + +#ifndef IRTEXT_H_ +#define IRTEXT_H_ + +#include "i18n.h" + +// Constant text to be shared across all object files. +// This means there is only one copy of the character/string/text etc. + +EOF + +# Parse and output contents of INPUT file. +egrep "^(String|char) " ${INPUT} | cut -f1 -d= | + sed 's/ PROGMEM//;s/ $/;/;s/^/extern const /' | sort -u >> ${OUTPUT} + +# Footer +cat >> ${OUTPUT} << EOF + +#endif // IRTEXT_H_ +EOF diff --git a/lib/IRremoteESP8266-2.6.5/tools/mkkeywords b/lib/IRremoteESP8266-2.7.0/tools/mkkeywords similarity index 100% rename from lib/IRremoteESP8266-2.6.5/tools/mkkeywords rename to lib/IRremoteESP8266-2.7.0/tools/mkkeywords diff --git a/lib/IRremoteESP8266-2.6.5/tools/mode2_decode.cpp b/lib/IRremoteESP8266-2.7.0/tools/mode2_decode.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/IRremoteESP8266-2.6.5/tools/mode2_decode.cpp rename to lib/IRremoteESP8266-2.7.0/tools/mode2_decode.cpp diff --git a/lib/IRremoteESP8266-2.6.5/tools/scrape_supported_devices.py b/lib/IRremoteESP8266-2.7.0/tools/scrape_supported_devices.py similarity index 100% rename from lib/IRremoteESP8266-2.6.5/tools/scrape_supported_devices.py rename to lib/IRremoteESP8266-2.7.0/tools/scrape_supported_devices.py diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 055d01a52..c6d7b75b5 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -8,6 +8,7 @@ * Fix better control of RGB/White when SetOption37 >128, added Dimmer1 and Dimmer2 commands (#6714) * Add hide Alexa objects with friendlyname starting with '$' (#6722, #6762) * Add command SetOption75 0/1 to switch between grouptopic (0) using fulltopic replacing %topic% or (1) is cmnd/ (#6779) + * Change Update IRremoteESP8266 to v2.7.0 * * 6.7.1.1 20191026 * Change ArduinoSlave to TasmotaSlave (Experimental) From 57e62b1e68a337ae78a6a1543e242cfec0bcccc5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 2 Nov 2019 13:25:23 +0100 Subject: [PATCH 087/196] Bump version 7.0.0.2 Add command WebColor19 to control color of Module and Name (#6811) --- tasmota/_changelog.ino | 3 +++ tasmota/settings.h | 11 +++++++---- tasmota/settings.ino | 4 ++++ tasmota/support.ino | 25 +++++++++++++++++++++---- tasmota/tasmota_version.h | 2 +- tasmota/xdrv_01_webserver.ino | 2 +- 6 files changed, 37 insertions(+), 10 deletions(-) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 055d01a52..f609f4c89 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -1,4 +1,7 @@ /*********************************************************************************************\ + * 7.0.0.2 20191102 + * Add command WebColor19 to control color of Module and Name (#6811) + * * 7.0.0.1 20191027 * Remove references to versions before 6.0 * Change default GUI to dark theme diff --git a/tasmota/settings.h b/tasmota/settings.h index 4f95e62b9..1eed62771 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -432,10 +432,13 @@ struct SYSCFG { uint16_t dimmer_hw_max; // E92 uint32_t deepsleep; // E94 uint16_t energy_power_delta; // E98 - uint8_t shutter_motordelay[MAX_SHUTTERS]; // E9A - uint8_t free_e9e[342]; // E9E - uint8_t web_color2[1][3]; // FF4 - uint8_t free_ff7 ; // FF7 + uint8_t shutter_motordelay[MAX_SHUTTERS]; // E9A + + uint8_t free_e9e[2]; // E9E + + uint8_t web_color2[2][3]; // EA0 - Needs to be on integer distance / 3 from web_color + + uint8_t free_ea4[338]; // EA6 uint32_t cfg_timestamp; // FF8 uint32_t cfg_crc32; // FFC diff --git a/tasmota/settings.ino b/tasmota/settings.ino index a9f686e50..b3baee256 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1115,6 +1115,10 @@ void SettingsDelta(void) } } + if (Settings.version < 0x07000002) { + char scolor[10]; + WebHexCode(18, GetTextIndexed(scolor, sizeof(scolor), 18, kWebColors)); + } Settings.version = VERSION; SettingsSave(1); } diff --git a/tasmota/support.ino b/tasmota/support.ino index 51147f502..2358d7f34 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -883,8 +883,9 @@ void WebHexCode(uint32_t i, const char* code) color = w | (w << 4); // 00112233 } */ - uint32_t j = sizeof(Settings.web_color)/3; // First area contains j=18 colors - if (i < j) { + uint32_t j = sizeof(Settings.web_color) / 3; // First area contains j = 18 colors +/* + if (i < j) { Settings.web_color[i][0] = (color >> 16) & 0xFF; // Red Settings.web_color[i][1] = (color >> 8) & 0xFF; // Green Settings.web_color[i][2] = color & 0xFF; // Blue @@ -892,14 +893,30 @@ void WebHexCode(uint32_t i, const char* code) Settings.web_color2[i-j][0] = (color >> 16) & 0xFF; // Red Settings.web_color2[i-j][1] = (color >> 8) & 0xFF; // Green Settings.web_color2[i-j][2] = color & 0xFF; // Blue - } + } +*/ + if (i >= j) { + // Calculate i to index in Settings.web_color2 - Dirty(!) but saves 128 bytes code + i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); + } + Settings.web_color[i][0] = (color >> 16) & 0xFF; // Red + Settings.web_color[i][1] = (color >> 8) & 0xFF; // Green + Settings.web_color[i][2] = color & 0xFF; // Blue } uint32_t WebColor(uint32_t i) { - uint32_t j = sizeof(Settings.web_color)/3; // First area contains j=18 colors + uint32_t j = sizeof(Settings.web_color) / 3; // First area contains j = 18 colors +/* uint32_t tcolor = (i= j) { + // Calculate i to index in Settings.web_color2 - Dirty(!) but saves 128 bytes code + i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); + } + uint32_t tcolor = (Settings.web_color[i][0] << 16) | (Settings.web_color[i][1] << 8) | Settings.web_color[i][2]; + return tcolor; } diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 12fa83147..892ebeba7 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07000001; +const uint32_t VERSION = 0x07000002; #endif // _TASMOTA_VERSION_H_ diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 0b2f1fdb3..c4e647d66 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2579,7 +2579,7 @@ bool JsonWebColor(const char* dataBuf) // Default (light) // {"WebColor":["#000000","#ffffff","#f2f2f2","#000000","#ffffff","#000000","#ffffff","#ff0000","#008000","#ffffff","#1fa3ec","#0e70a4","#d43535","#931f1f","#47c266","#5aaf6f","#ffffff","#999999","#000000"]} // Alternative (Dark) - // {"webcolor":["#eeeeee","#181818","#4f4f4f","#000000","#dddddd","#008000","#222222","#ff0000","#008000","#ffffff","#1fa3ec","#0e70a4","#d43535","#931f1f","#47c266","#5aaf6f","#ffffff","#999999","#000000"]} + // {"Webcolor":["#eeeeee","#181818","#4f4f4f","#000000","#dddddd","#6a9955","#1e1e1e","#ff0000","#008000","#ffffff","#1fa3ec","#0e70a4","#d43535","#931f1f","#47c266","#5aaf6f","#ffffff","#999999","#eeeeee"]} char dataBufLc[strlen(dataBuf) +1]; LowerCase(dataBufLc, dataBuf); From f9cb2b14a01ab5c4845dab33ebf3e7dffe43426b Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sat, 2 Nov 2019 14:45:45 +0200 Subject: [PATCH 088/196] TasmotaSlave: Bugfix --- tasmota/xdrv_31_tasmota_slave.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_31_tasmota_slave.ino b/tasmota/xdrv_31_tasmota_slave.ino index a19f9384f..e04255873 100644 --- a/tasmota/xdrv_31_tasmota_slave.ino +++ b/tasmota/xdrv_31_tasmota_slave.ino @@ -580,10 +580,13 @@ bool Xdrv31(uint8_t function) switch (function) { case FUNC_EVERY_100_MSECOND: - if ((TSlave.type) && (TSlaveSettings.features.func_every_100_msecond)) { + if (TSlave.type) { if (TasmotaSlave_Serial->available()) { TasmotaSlave_ProcessIn(); } + if (TSlaveSettings.features.func_every_100_msecond) { + TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_100_MSECOND, 0); + } } break; case FUNC_EVERY_SECOND: From b4e3b9703c75f9b51f5e42fad4e111aad4a34cdd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 2 Nov 2019 14:50:24 +0100 Subject: [PATCH 089/196] Fix default Title color --- tasmota/settings.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index b3baee256..35fd7f2fa 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1116,8 +1116,9 @@ void SettingsDelta(void) } if (Settings.version < 0x07000002) { - char scolor[10]; - WebHexCode(18, GetTextIndexed(scolor, sizeof(scolor), 18, kWebColors)); + Settings.web_color2[0][0] = Settings.web_color[0][0]; + Settings.web_color2[0][1] = Settings.web_color[0][1]; + Settings.web_color2[0][2] = Settings.web_color[0][2]; } Settings.version = VERSION; SettingsSave(1); From 6395db996396c5e394cafa05ef64b55cfb040840 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 2 Nov 2019 17:18:51 +0100 Subject: [PATCH 090/196] Add support for Honeywell I2C HIH series Add support for Honeywell I2C HIH series Humidity and Temperetaure sensor (#6808) --- tasmota/_changelog.ino | 1 + tasmota/my_user_config.h | 1 + tasmota/support_features.ino | 4 +- tasmota/tasmota_post.h | 1 + tasmota/xsns_55_hih_series.ino | 162 +++++++++++++++++++++++++++++++++ tools/decode-status.py | 2 +- 6 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 tasmota/xsns_55_hih_series.ino diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 39d230088..415761303 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -1,6 +1,7 @@ /*********************************************************************************************\ * 7.0.0.2 20191102 * Add command WebColor19 to control color of Module and Name (#6811) + * Add support for Honeywell I2C HIH series Humidity and Temperetaure sensor (#6808) * * 7.0.0.1 20191027 * Remove references to versions before 6.0 diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 69773b3d0..c225ddd86 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -402,6 +402,7 @@ // #define USE_CHIRP // Enable CHIRP soil moisture sensor (variable I2C address, default 0x20) // #define USE_PAJ7620 // Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) // #define USE_PCF8574 // Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x27 and 0x38 - 0x3F) (+1k9 code) +// #define USE_HIH6 // Enable Honeywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index e4f5c1044..ef1f23c84 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -480,7 +480,9 @@ void GetFeatures(void) #ifdef USE_ARDUINO_SLAVE feature5 |= 0x00010000; // xdrv_31_arduino_slave.ino #endif -// feature5 |= 0x00020000; +#ifdef USE_HIH6 + feature5 |= 0x00020000; // xsns_55_hih_series.ino +#endif // feature5 |= 0x00040000; // feature5 |= 0x00080000; diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index ff5513481..89098ed82 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -157,6 +157,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c //#define USE_CHIRP // Enable CHIRP soil moisture sensor (variable I2C address, default 0x20) //#define USE_PAJ7620 // Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) //#define USE_PCF8574 // Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x27 and 0x38 - 0x3F) (+1k9 code) +//#define USE_HIH6 // Enable Honywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) diff --git a/tasmota/xsns_55_hih_series.ino b/tasmota/xsns_55_hih_series.ino new file mode 100644 index 000000000..1793d31e2 --- /dev/null +++ b/tasmota/xsns_55_hih_series.ino @@ -0,0 +1,162 @@ +/* + xsns_55_hih_series.ino - Honeywell HIH series temperature and humidity sensor support for Tasmota + + Copyright (C) 2019 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_I2C +#ifdef USE_HIH6 +/*********************************************************************************************\ + * HIH6130 - Temperature and Humidity + * + * https://sensing.honeywell.com/HIH6130-021-001-humidity-sensors + * https://sensing.honeywell.com/i2c-comms-humidicon-tn-009061-2-en-final-07jun12.pdf + * https://github.com/ControlEverythingCommunity/HIH6130/blob/master/Arduino/HIH6130.ino + * + * I2C Address: 0x27 +\*********************************************************************************************/ + +#define XSNS_55 55 + +#define HIH6_ADDR 0x27 + +struct HIH6 { + float temperature = 0; + float humidity = 0; + uint8_t valid = 0; + uint8_t type = 0; + char types[4] = "HIH"; +} Hih6; + +bool Hih6Read(void) +{ + Wire.beginTransmission(HIH6_ADDR); + Wire.write(0x00); // Select data register + if (Wire.endTransmission() != 0) { return false; } // In case of error + +// delay(40); // Wait for Valid data or use Stale data + + uint8_t data[4]; + Wire.requestFrom(HIH6_ADDR, 4); + if (4 == Wire.available()) { + data[0] = Wire.read(); // Status and Humidity msb + data[1] = Wire.read(); // Humidity lsb + data[2] = Wire.read(); // Temp msb + data[3] = Wire.read(); // Temp lsb + } else { return false; } + +// uint8_t status = data[0] >> 6; // 0 = Valid data, 1 = Stale data, 2 = Command mode, 3 = Not used + + // Convert the data to 14-bits + int temp = ((data[2] * 256) + (data[3] & 0xFC)) / 4; + Hih6.temperature = ConvertTemp((temp / 16384.0) * 165.0 - 40.0); + Hih6.humidity = ConvertHumidity(((((data[0] & 0x3F) * 256) + data[1]) * 100.0) / 16383.0); + + Hih6.valid = SENSOR_MAX_MISS; + return true; +} + +/********************************************************************************************/ + +void Hih6Detect(void) +{ + if (Hih6.type) { return; } + + Hih6.type = Hih6Read(); + if (Hih6.type) { + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, Hih6.types, HIH6_ADDR); + } +} + +void Hih6EverySecond(void) +{ + if ((100 - XSNS_55) == (uptime %100)) { + // 1mS + Hih6Detect(); + } + else if (uptime &1) { + // HIH6130: 30mS + if (Hih6.type) { + if (!Hih6Read()) { + AddLogMissed(Hih6.types, Hih6.valid); +// if (!Hih6.valid) { Hih6.type = 0; } + } + } + } +} + +void Hih6Show(bool json) +{ + if (Hih6.valid) { + char temperature[33]; + dtostrfd(Hih6.temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Hih6.humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Hih6.types, 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, Hih6.temperature); + KnxSensor(KNX_HUMIDITY, Hih6.humidity); + } +#endif // USE_KNX +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Hih6.types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Hih6.types, humidity); +#endif // USE_WEBSERVER + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns55(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + Hih6EverySecond(); + break; + case FUNC_JSON_APPEND: + Hih6Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Hih6Show(0); + break; +#endif // USE_WEBSERVER + case FUNC_INIT: + Hih6Detect(); + break; + } + } + return result; +} + +#endif // USE_HIH6 +#endif // USE_I2C + diff --git a/tools/decode-status.py b/tools/decode-status.py index 2edc469db..c0680ef55 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -185,7 +185,7 @@ a_features = [[ "USE_INA226","USE_A4988_STEPPER","USE_DDS2382","USE_SM2135", "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER", - "USE_ARDUINO_SLAVE","","","", + "USE_ARDUINO_SLAVE","USE_HIH6","","", "","","","", "","","","", "","","","" From ba2439d9dab7b5d26ed4acc0783135fad8721a5e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 2 Nov 2019 17:37:50 +0100 Subject: [PATCH 091/196] Update RELEASENOTES.md --- RELEASENOTES.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ea4651445..edbe1f9de 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -14,7 +14,7 @@ See [wiki migration path](https://github.com/arendst/Tasmota/wiki/Upgrade#migrat ## Supported Core versions This release will be supported from ESP8266/Arduino library Core version **pre-2.6.0** due to reported security and stability issues on previous Core version. -Although it might still compile on previous Core versions all support will be removed starting in the next Release. +Although it might still compile on previous Core versions all support will be removed starting in the near future. ## Support of TLS To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. See full documentation on https://github.com/arendst/Tasmota/wiki/AWS-IoT @@ -219,6 +219,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_CHIRP | - | - | - | - | - | - | - | | USE_PAJ7620 | - | - | - | - | - | - | - | | USE_PCF8574 | - | - | - | - | - | - | - | +| USE_HIH6 | - | - | - | - | - | - | - | | | | | | | | | | | Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks | USE_SPI | - | - | - | - | - | - | x | @@ -261,6 +262,17 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog Version 7.1.0 Betty + * Remove support for versions before 6.0 * Change ArduinoSlave to TasmotaSlave (Experimental) * Change repository name from Sonoff-Tasmota to Tasmota and all code references from Sonoff to Tasmota + * Change default GUI to dark theme + * Change IRremoteESP8266 library to v2.7.0 + * Fix better control of RGB/White when SetOption37 >128, added Dimmer1 and Dimmer2 commands (#6714) * Add support for Tuya battery powered devices (#6735) + * Add support for Honeywell I2C HIH series Humidity and Temperetaure sensor (#6808) + * Add command WebColor19 to control color of Module and Name (#6811) + * Add command SetOption73 0/1 to re-enable HTTP Cross-Origin Resource Sharing (CORS) now default disabled (#6767) + * Add command SetOption74 0/1 to enable DS18x20 internal pull-up and remove define DS18B20_INTERNAL_PULLUP (#6795) + * Add command SetOption75 0/1 to switch between grouptopic (0) using fulltopic replacing %topic% or (1) is cmnd/ (#6779) + * Add frequency to ADE7953 energy monitor as used in Shelly 2.5 by ljakob (#6778) + * Add hide Alexa objects with friendlyname starting with '$' (#6722, #6762) From 3cb24fb5c945407343d8d999529b0ea0dd1e2a0d Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sat, 2 Nov 2019 17:43:16 +0100 Subject: [PATCH 092/196] Create VerifyFlash.bat --- tools/Esptool/VerifyFlash.bat | 1 + 1 file changed, 1 insertion(+) create mode 100644 tools/Esptool/VerifyFlash.bat diff --git a/tools/Esptool/VerifyFlash.bat b/tools/Esptool/VerifyFlash.bat new file mode 100644 index 000000000..fd98b4611 --- /dev/null +++ b/tools/Esptool/VerifyFlash.bat @@ -0,0 +1 @@ +esptool.py --port COM5 --baud 115200 verify_flash -fs 1MB -fm dout 0x000000 firmware.bin From 753a5577d60fa331861a236c26c5ed565458f1c5 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sat, 2 Nov 2019 17:44:30 +0100 Subject: [PATCH 093/196] Add files via upload --- tools/Esptool/EraseFlash.bat | 1 + tools/Esptool/ReadFlash.bat | 1 + tools/Esptool/VerifyFlash.bat | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 tools/Esptool/EraseFlash.bat create mode 100644 tools/Esptool/ReadFlash.bat diff --git a/tools/Esptool/EraseFlash.bat b/tools/Esptool/EraseFlash.bat new file mode 100644 index 000000000..fab2225b6 --- /dev/null +++ b/tools/Esptool/EraseFlash.bat @@ -0,0 +1 @@ +esptool.py --port COM5 --baud 115200 erase_flash \ No newline at end of file diff --git a/tools/Esptool/ReadFlash.bat b/tools/Esptool/ReadFlash.bat new file mode 100644 index 000000000..edd954502 --- /dev/null +++ b/tools/Esptool/ReadFlash.bat @@ -0,0 +1 @@ +esptool.py --port COM5 --baud 115200 read_flash 0x000000 0x100000 backup.bin \ No newline at end of file diff --git a/tools/Esptool/VerifyFlash.bat b/tools/Esptool/VerifyFlash.bat index fd98b4611..cf90453c2 100644 --- a/tools/Esptool/VerifyFlash.bat +++ b/tools/Esptool/VerifyFlash.bat @@ -1 +1 @@ -esptool.py --port COM5 --baud 115200 verify_flash -fs 1MB -fm dout 0x000000 firmware.bin +esptool.py --port COM5 --baud 115200 verify_flash -fs 1MB -fm dout 0x000000 firmware.bin From dada0bca2fc4290f40cbd92e41d22c52c2d600aa Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sat, 2 Nov 2019 17:44:58 +0100 Subject: [PATCH 094/196] Add files via upload --- tools/Esptool/WriteFlash.bat | 1 + 1 file changed, 1 insertion(+) create mode 100644 tools/Esptool/WriteFlash.bat diff --git a/tools/Esptool/WriteFlash.bat b/tools/Esptool/WriteFlash.bat new file mode 100644 index 000000000..61f3f55a4 --- /dev/null +++ b/tools/Esptool/WriteFlash.bat @@ -0,0 +1 @@ +esptool.py --port COM5 --baud 115200 write_flash -fs 1MB -fm dout 0x000000 firmware.bin From bfcd156ee0f9262de51241f9e56dc8f0c842cc5e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 2 Nov 2019 18:32:46 +0100 Subject: [PATCH 095/196] Fix wrong Dimmer behavior introduced with #6799 when SetOption37 < 128 --- tasmota/_changelog.ino | 1 + tasmota/xdrv_04_light.ino | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 415761303..5de8cf199 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -2,6 +2,7 @@ * 7.0.0.2 20191102 * Add command WebColor19 to control color of Module and Name (#6811) * Add support for Honeywell I2C HIH series Humidity and Temperetaure sensor (#6808) + * Fix wrong Dimmer behavior introduced with #6799 when SetOption37 < 128 * * 7.0.0.1 20191027 * Remove references to versions before 6.0 diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index f4fb6dbab..034ed005f 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2163,11 +2163,12 @@ void CmndColorTemperature(void) void CmndDimmer(void) { uint32_t dimmer; - - if ((1 == XdrvMailbox.index) || (2 == XdrvMailbox.index)) { // Dimmer1 is RGB, Dimmer 2 iw white - dimmer = light_state.getDimmer(XdrvMailbox.index); - } else { + if (XdrvMailbox.index > 2) { XdrvMailbox.index = 1; } + + if ((light_controller.isCTRGBLinked()) || (0 == XdrvMailbox.index)) { dimmer = light_state.getDimmer(); + } else { + dimmer = light_state.getDimmer(XdrvMailbox.index); } // Handle +/- special command if (1 == XdrvMailbox.data_len) { @@ -2179,10 +2180,17 @@ void CmndDimmer(void) } // If value is ok, change it, otherwise report old value if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - if ((1 == XdrvMailbox.index) || (2 == XdrvMailbox.index)) { - light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); - } else { + if (light_controller.isCTRGBLinked()) { + // normal state, linked RGB and CW light_controller.changeDimmer(XdrvMailbox.payload); + } else { + if (0 != XdrvMailbox.index) { + light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); + } else { + // change both dimmers + light_controller.changeDimmer(XdrvMailbox.payload, 1); + light_controller.changeDimmer(XdrvMailbox.payload, 2); + } } Light.update = true; LightPreparePower(); From a74f5eaa4d613d4ecc315f60cac919afce8a58f1 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 3 Nov 2019 10:52:44 +0100 Subject: [PATCH 096/196] Add DS18x20 support in Tasmota-IR --- tasmota/_changelog.ino | 1 + tasmota/tasmota_post.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 5de8cf199..c0cc8fd88 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -3,6 +3,7 @@ * Add command WebColor19 to control color of Module and Name (#6811) * Add support for Honeywell I2C HIH series Humidity and Temperetaure sensor (#6808) * Fix wrong Dimmer behavior introduced with #6799 when SetOption37 < 128 + * Change add DS18x20 support in Tasmota-IR * * 7.0.0.1 20191027 * Remove references to versions before 6.0 diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 89098ed82..eca4fc85c 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -356,7 +356,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #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_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) +//#undef USE_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) #undef USE_I2C // Disable all I2C sensors #undef USE_SPI // Disable all SPI devices From 5f4e38023d1b6ab1516082d5844b033546e5a513 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 3 Nov 2019 12:33:36 +0100 Subject: [PATCH 097/196] Add SetOption comments to code --- tasmota/settings.h | 10 ++--- tasmota/support.ino | 14 +++---- tasmota/support_command.ino | 28 +++++++------ tasmota/support_wifi.ino | 6 ++- tasmota/tasmota.ino | 63 ++++++++++++++++-------------- tasmota/xdrv_01_webserver.ino | 20 +++++----- tasmota/xdrv_02_mqtt.ino | 62 ++++++++++++++--------------- tasmota/xdrv_03_energy.ino | 4 +- tasmota/xdrv_04_light.ino | 36 ++++++++--------- tasmota/xdrv_05_irremote.ino | 2 +- tasmota/xdrv_05_irremote_full.ino | 2 +- tasmota/xdrv_06_snfbridge.ino | 4 +- tasmota/xdrv_07_domoticz.ino | 6 +-- tasmota/xdrv_10_scripter.ino | 6 +-- tasmota/xdrv_12_home_assistant.ino | 32 +++++++-------- tasmota/xdrv_15_pca9685.ino | 2 +- tasmota/xdrv_16_tuyamcu.ino | 2 +- tasmota/xdrv_17_rcswitch.ino | 2 +- tasmota/xdrv_19_ps16dz_dimmer.ino | 2 +- tasmota/xdrv_22_sonoff_ifan.ino | 2 +- tasmota/xdrv_27_shutter.ino | 6 +-- tasmota/xdrv_30_exs_dimmer.ino | 2 +- tasmota/xdsp_08_ILI9488.ino | 2 +- tasmota/xdsp_10_RA8876.ino | 2 +- tasmota/xlgt_01_ws2812.ino | 6 ++- tasmota/xlgt_05_sonoff_l1.ino | 2 +- tasmota/xsns_27_apds9960.ino | 2 +- tasmota/xsns_29_mcp230xx.ino | 12 +++--- tasmota/xsns_34_hx711.ino | 2 +- tasmota/xsns_36_mgc3130.ino | 2 +- tasmota/xsns_39_max31855.ino | 4 +- tasmota/xsns_40_pn532.ino | 2 +- tasmota/xsns_44_sps30.ino | 2 +- tasmota/xsns_50_paj7620.ino | 2 +- tasmota/xsns_51_rdm6300.ino | 2 +- tasmota/xsns_52_ibeacon.ino | 2 +- tasmota/xsns_53_sml.ino | 2 +- 37 files changed, 188 insertions(+), 171 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 1eed62771..43909e6ee 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -28,7 +28,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t save_state : 1; // bit 0 - SetOption0 - Save power state and use after restart uint32_t button_restrict : 1; // bit 1 - SetOption1 - Control button multipress uint32_t ex_value_units : 1; // bit 2 - SetOption2 - Add units to JSON status messages - removed 6.6.0.21 - uint32_t mqtt_enabled : 1; // bit 3 - SetOption3 - Control MQTT + uint32_t mqtt_enabled : 1; // bit 3 - SetOption3 - Enable MQTT uint32_t mqtt_response : 1; // bit 4 - SetOption4 - Switch between MQTT RESULT or COMMAND uint32_t mqtt_power_retain : 1; // bit 5 - CMND_POWERRETAIN uint32_t mqtt_button_retain : 1; // bit 6 - CMND_BUTTONRETAIN @@ -39,10 +39,10 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t button_swap : 1; // bit 11 (v5.1.6) - SetOption11 - Swap button single and double press functionality uint32_t stop_flash_rotate : 1; // bit 12 (v5.2.0) - SetOption12 - Switch between dynamic or fixed slot flash save location uint32_t button_single : 1; // bit 13 (v5.4.0) - SetOption13 - Support only single press to speed up button press recognition - uint32_t interlock : 1; // bit 14 (v5.6.0) - CMND_INTERLOCK + uint32_t interlock : 1; // bit 14 (v5.6.0) - CMND_INTERLOCK - Enable/disable interlock uint32_t pwm_control : 1; // bit 15 (v5.8.1) - SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL uint32_t ws_clock_reverse : 1; // bit 16 (v5.8.1) - SetOption16 - Switch between clockwise or counter-clockwise - uint32_t decimal_text : 1; // bit 17 (v5.8.1) - SetOption17 - Switch between decimal or hexadecimal output + uint32_t decimal_text : 1; // bit 17 (v5.8.1) - SetOption17 - Switch between decimal or hexadecimal output (0 = hexadecimal, 1 = decimal) uint32_t light_signal : 1; // bit 18 (v5.10.0c) - SetOption18 - Pair light signal with CO2 sensor uint32_t hass_discovery : 1; // bit 19 (v5.11.1a) - SetOption19 - Control Home Assistantautomatic discovery (See SetOption59) uint32_t not_power_linked : 1; // bit 20 (v5.11.1f) - SetOption20 - Control power in relation to Dimmer/Color/Ct changes @@ -53,8 +53,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t knx_enabled : 1; // bit 25 (v5.12.0l) - CMND_KNX_ENABLED uint32_t device_index_enable : 1; // bit 26 (v5.13.1a) - SetOption26 - Switch between POWER or POWER1 uint32_t knx_enable_enhancement : 1; // bit 27 (v5.14.0a) - CMND_KNX_ENHANCED - uint32_t rf_receive_decimal : 1; // bit 28 (v6.0.0a) - SetOption28 - RF receive data format - uint32_t ir_receive_decimal : 1; // bit 29 (v6.0.0a) - SetOption29 - IR receive data format + uint32_t rf_receive_decimal : 1; // bit 28 (v6.0.0a) - SetOption28 - RF receive data format (0 = hexadecimal, 1 = decimal) + uint32_t ir_receive_decimal : 1; // bit 29 (v6.0.0a) - SetOption29 - IR receive data format (0 = hexadecimal, 1 = decimal) uint32_t hass_light : 1; // bit 30 (v6.0.0b) - SetOption30 - Enforce HAss autodiscovery as light uint32_t global_state : 1; // bit 31 (v6.1.0) - SetOption31 - Control link led blinking }; diff --git a/tasmota/support.ino b/tasmota/support.ino index 2358d7f34..404acd3bc 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -619,8 +619,8 @@ float ConvertTemp(float c) global_update = uptime; global_temperature = c; - if (!isnan(c) && Settings.flag.temperature_conversion) { - result = c * 1.8 + 32; // Fahrenheit + if (!isnan(c) && Settings.flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit + result = c * 1.8 + 32; // Fahrenheit } return result; } @@ -629,15 +629,15 @@ float ConvertTempToCelsius(float c) { float result = c; - if (!isnan(c) && Settings.flag.temperature_conversion) { - result = (c - 32) / 1.8; // Celsius + if (!isnan(c) && Settings.flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit + result = (c - 32) / 1.8; // Celsius } return result; } char TempUnit(void) { - return (Settings.flag.temperature_conversion) ? 'F' : 'C'; + return (Settings.flag.temperature_conversion) ? 'F' : 'C'; // SetOption8 - Switch between Celsius or Fahrenheit } float ConvertHumidity(float h) @@ -655,8 +655,8 @@ float ConvertPressure(float p) global_update = uptime; global_pressure = p; - if (!isnan(p) && Settings.flag.pressure_conversion) { - result = p * 0.75006375541921; // mmHg + if (!isnan(p) && Settings.flag.pressure_conversion) { // SetOption24 - Switch between hPa or mmHg pressure unit + result = p * 0.75006375541921; // mmHg } return result; } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 47908e2d0..6b2d878b2 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -300,7 +300,7 @@ void CmndPower(void) if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_BLINK_STOP)) { XdrvMailbox.payload = POWER_SHOW_STATE; } -// Settings.flag.device_index_enable = XdrvMailbox.usridx; +// Settings.flag.device_index_enable = XdrvMailbox.usridx; // SetOption26 - Switch between POWER or POWER1 ExecuteCommandPower(XdrvMailbox.index, XdrvMailbox.payload, SRC_IGNORE); mqtt_data[0] = '\0'; } @@ -324,7 +324,7 @@ void CmndStatus(void) // Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) { option++; } // TELE - if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } + if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } // SetOption3 - Enable MQTT if (!energy_flg && (9 == payload)) { payload = 99; } if ((0 == payload) || (99 == payload)) { @@ -346,8 +346,14 @@ void CmndStatus(void) D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), ModuleNr(), stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, - Settings.ledmask, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, - stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_retain, Settings.flag.mqtt_power_retain); + Settings.ledmask, Settings.save_data, + Settings.flag.save_state, // SetOption0 - Save power state and use after restart + Settings.switch_topic, + stemp2, + Settings.flag.mqtt_button_retain, // CMND_BUTTONRETAIN + Settings.flag.mqtt_switch_retain, // CMND_SWITCHRETAIN + Settings.flag.mqtt_sensor_retain, // CMND_SENSORRETAIN + Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS)); } @@ -404,7 +410,7 @@ void CmndStatus(void) MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "5")); } - if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { + if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT #ifdef USE_MQTT_AWS_IOT Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), @@ -483,7 +489,7 @@ void CmndState(void) MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); } #ifdef USE_HOME_ASSISTANT - if (Settings.flag.hass_discovery) { + if (Settings.flag.hass_discovery) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59) HAssPublishStatus(); } #endif // USE_HOME_ASSISTANT @@ -526,7 +532,7 @@ void CmndOtaUrl(void) void CmndSeriallog(void) { if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { - Settings.flag.mqtt_serial = 0; + Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG SetSeriallog(XdrvMailbox.payload); } Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.seriallog_level, seriallog_level); @@ -1061,8 +1067,8 @@ void CmndSerialSend(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { SetSeriallog(LOG_LEVEL_NONE); - Settings.flag.mqtt_serial = 1; - Settings.flag.mqtt_serial_raw = (XdrvMailbox.index > 3) ? 1 : 0; + Settings.flag.mqtt_serial = 1; // CMND_SERIALSEND and CMND_SERIALLOG + Settings.flag.mqtt_serial_raw = (XdrvMailbox.index > 3) ? 1 : 0; // CMND_SERIALSEND3 if (XdrvMailbox.data_len > 0) { if (1 == XdrvMailbox.index) { Serial.printf("%s\n", XdrvMailbox.data); // "Hello Tiger\n" @@ -1290,7 +1296,7 @@ void CmndInterlock(void) if (minimal_bits < 2) { Settings.interlock[i] = 0; } // Discard single relay as interlock } } else { - Settings.flag.interlock = XdrvMailbox.payload &1; // Enable/disable interlock + Settings.flag.interlock = XdrvMailbox.payload &1; // CMND_INTERLOCK - Enable/disable interlock if (Settings.flag.interlock) { SetDevicePower(power, SRC_IGNORE); // Remove multiple relays if set } @@ -1320,7 +1326,7 @@ void CmndInterlock(void) } ResponseAppend_P(PSTR("\"}")); } else { - Settings.flag.interlock = 0; + Settings.flag.interlock = 0; // CMND_INTERLOCK - Enable/disable interlock ResponseCmndStateText(Settings.flag.interlock); } } diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index ba0e95eae..1d66928ea 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -520,7 +520,7 @@ void WifiCheck(uint8_t param) #endif // USE_WEBSERVER #ifdef USE_KNX - if (!knx_started && Settings.flag.knx_enabled) { + if (!knx_started && Settings.flag.knx_enabled) { // CMND_KNX_ENABLED KNXStart(); knx_started = true; } @@ -574,7 +574,9 @@ void WifiDisconnect(void) void EspRestart(void) { delay(100); // Allow time for message xfer - disabled v6.1.0b - if (Settings.flag.mqtt_enabled) MqttDisconnect(); + if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT + MqttDisconnect(); + } WifiDisconnect(); // ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 ESP.reset(); diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 1240a60de..811536b81 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -342,7 +342,7 @@ void SetDevicePower(power_t rpower, uint32_t source) rpower = power; } - if (Settings.flag.interlock) { // Allow only one or no relay set + if (Settings.flag.interlock) { // Allow only one or no relay set - CMND_INTERLOCK - Enable/disable interlock for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { power_t mask = 1; uint32_t count = 0; @@ -526,12 +526,12 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) char *tmp = (key) ? Settings.switch_topic : Settings.button_topic; Format(key_topic, tmp, sizeof(key_topic)); - if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { + if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { // SetOption3 - Enable MQTT if (!key && (device > devices_present)) { device = 1; // Only allow number of buttons up to number of devices } GetTopic_P(stopic, CMND, key_topic, - GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx + GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx - SetOption26 - Switch between POWER or POWER1 if (CLEAR_RETAIN == state) { mqtt_data[0] = '\0'; } else { @@ -542,10 +542,12 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) } #ifdef USE_DOMOTICZ if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { - MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); +#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 +#ifdef USE_DOMOTICZ } -#else - MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); #endif // USE_DOMOTICZ result = !Settings.flag3.button_switch_force_local; } else { @@ -577,7 +579,7 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { blink_mask &= 1; // No blinking on the fan relays - Settings.flag.interlock = 0; // No interlock mode as it is already done by the microcontroller + Settings.flag.interlock = 0; // No interlock mode as it is already done by the microcontroller - CMND_INTERLOCK - Enable/disable interlock Settings.pulse_timer[1] = 0; // No pulsetimers on the fan relays Settings.pulse_timer[2] = 0; Settings.pulse_timer[3] = 0; @@ -605,7 +607,7 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) MqttPublishPowerBlinkState(device); } - if (Settings.flag.interlock && + if (Settings.flag.interlock && // CMND_INTERLOCK - Enable/disable interlock !interlock_mutex && ((POWER_ON == state) || ((POWER_TOGGLE == state) && !(power & mask))) ) { @@ -722,7 +724,8 @@ void MqttShowState(void) if (i == LightDevice()) { LightState(1); } // call it only once } else { #endif - ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), GetStateText(bitRead(power, i-1))); + ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 + GetStateText(bitRead(power, i-1))); #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { ResponseAppend_P(PSTR(",\"" D_CMND_FANSPEED "\":%d"), GetFanspeed()); @@ -847,7 +850,7 @@ void PerformEverySecond(void) mqtt_data[0] = '\0'; if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN #if defined(USE_RULES) || defined(USE_SCRIPT) RulesTeleperiod(); // Allow rule based HA messages #endif // USE_RULES @@ -914,7 +917,7 @@ void Every250mSeconds(void) if (mqtt_cmnd_publish) mqtt_cmnd_publish--; // Clean up - if (!Settings.flag.global_state) { // Problem blinkyblinky enabled + 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) if (global_state.wifi_down) { blinkinterval = 3; } // Wifi problem so blink every second (slow) @@ -1027,7 +1030,7 @@ void Every250mSeconds(void) if (save_data_counter && BACKLOG_EMPTY) { save_data_counter--; if (save_data_counter <= 0) { - if (Settings.flag.save_state) { + if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart power_t mask = POWER_MASK; for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { if ((Settings.pulse_timer[i] > 0) && (Settings.pulse_timer[i] < 30)) { // 3 seconds @@ -1120,18 +1123,20 @@ void ArduinoOTAInit(void) ArduinoOTA.onStart([]() { - SettingsSave(1); // Free flash for OTA update + SettingsSave(1); // Free flash for OTA update #ifdef USE_WEBSERVER if (Settings.webserver) { StopWebserver(); } #endif // USE_WEBSERVER #ifdef USE_ARILUX_RF - AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine + AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine #endif // USE_ARILUX_RF - if (Settings.flag.mqtt_enabled) { MqttDisconnect(); } + if (Settings.flag.mqtt_enabled) { + MqttDisconnect(); // SetOption3 - Enable MQTT + } AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED)); arduino_ota_triggered = true; arduino_ota_progress_dot_count = 0; - delay(100); // Allow time for message xfer + delay(100); // Allow time for message xfer }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) @@ -1201,12 +1206,12 @@ void SerialInput(void) /*-------------------------------------------------------------------------------------------*/ - if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // Discard binary data above 127 if no raw reception allowed + if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // Discard binary data above 127 if no raw reception allowed - CMND_SERIALSEND3 serial_in_byte_counter = 0; Serial.flush(); return; } - if (!Settings.flag.mqtt_serial) { // SerialSend active + if (!Settings.flag.mqtt_serial) { // SerialSend active - CMND_SERIALSEND and CMND_SERIALLOG if (isprint(serial_in_byte)) { // Any char between 32 and 127 if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // Add char to string if it still fits serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; @@ -1215,11 +1220,11 @@ void SerialInput(void) } } } else { - if (serial_in_byte || Settings.flag.mqtt_serial_raw) { // Any char between 1 and 127 or any char (0 - 255) + if (serial_in_byte || Settings.flag.mqtt_serial_raw) { // Any char between 1 and 127 or any char (0 - 255) - CMND_SERIALSEND3 if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && // Add char to string if it still fits and ... ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || // Any char between 32 and 127 ((serial_in_byte != Settings.serial_delimiter) && (128 != Settings.serial_delimiter)) || // Any char between 1 and 127 and not being delimiter - Settings.flag.mqtt_serial_raw)) { // Any char between 0 and 255 + Settings.flag.mqtt_serial_raw)) { // Any char between 0 and 255 - CMND_SERIALSEND3 serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; serial_polling_window = millis(); } else { @@ -1245,7 +1250,7 @@ void SerialInput(void) #endif // USE_SONOFF_SC /*-------------------------------------------------------------------------------------------*/ - if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { + if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { // CMND_SERIALSEND and CMND_SERIALLOG serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings.seriallog_level; AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), serial_in_buffer); @@ -1257,7 +1262,7 @@ void SerialInput(void) } } - if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { + 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\"}"), @@ -1410,18 +1415,18 @@ void GpioInit(void) // devices_present = 1; } else if (SONOFF_DUAL == my_module_type) { - Settings.flag.mqtt_serial = 0; + Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG devices_present = 2; baudrate = 19200; } else if (CH4 == my_module_type) { - Settings.flag.mqtt_serial = 0; + Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG devices_present = 4; baudrate = 19200; } #ifdef USE_SONOFF_SC else if (SONOFF_SC == my_module_type) { - Settings.flag.mqtt_serial = 0; + Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG devices_present = 0; baudrate = 19200; } @@ -1524,7 +1529,7 @@ void setup(void) seriallog_level = Settings.seriallog_level; seriallog_timer = SERIALLOG_TIMER; syslog_level = Settings.syslog_level; - stop_flash_rotate = Settings.flag.stop_flash_rotate; + stop_flash_rotate = Settings.flag.stop_flash_rotate; // SetOption12 - Switch between dynamic or fixed slot flash save location save_data_counter = Settings.save_data; sleep = Settings.sleep; #ifndef USE_EMULATION @@ -1598,20 +1603,20 @@ void setup(void) break; case POWER_ALL_SAVED_TOGGLE: power = (Settings.power & ((1 << devices_present) -1)) ^ POWER_MASK; - if (Settings.flag.save_state) { + 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) { + 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) { + if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart SetDevicePower(power, SRC_RESTART); } } diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index c4e647d66..4dc07c44a 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -991,7 +991,7 @@ void HandleRoot(void) if (devices_present) { #ifdef USE_LIGHT if (light_type) { - if (!Settings.flag3.pwm_multi_channels) { + if (!Settings.flag3.pwm_multi_channels) { // SetOption68 0 if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { // Cold - Warm &t related to lb("t", value) and WebGetArg("t", tmp, sizeof(tmp)); WSContentSend_P(HTTP_MSG_SLIDER1, F(D_COLDLIGHT), F(D_WARMLIGHT), @@ -1000,7 +1000,7 @@ void HandleRoot(void) // Dark - Bright &d related to lb("d", value) and WebGetArg("d", tmp, sizeof(tmp)); WSContentSend_P(HTTP_MSG_SLIDER1, F(D_DARKLIGHT), F(D_BRIGHTLIGHT), 1, 100, Settings.light_dimmer, 'd'); - } else { // Settings.flag3.pwm_multi_channels + } else { // Settings.flag3.pwm_multi_channels - SetOption68 1 uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); for (uint32_t i = 0; i < pwm_channels; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("c%d"), i); @@ -1012,7 +1012,7 @@ void HandleRoot(void) } #endif #ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { + if (Settings.flag3.shutter_mode) { // SetOption80 1 for (uint32_t i = 0; i < shutters_present; i++) { WSContentSend_P(HTTP_MSG_SLIDER2, F(D_CLOSE), F(D_OPEN), 0, 100, Settings.shutter_position[i], 'u', i+1); @@ -1625,7 +1625,7 @@ void HandleLoggingConfiguration(void) char stemp2[32]; uint8_t dlevel[4] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE, LOG_LEVEL_NONE }; for (uint32_t idx = 0; idx < 4; idx++) { - if ((2==idx) && !Settings.flag.mqtt_enabled) { continue; } + if ((2==idx) && !Settings.flag.mqtt_enabled) { continue; } // SetOption3 - Enable MQTT uint32_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:(2==idx)?Settings.mqttlog_level:Settings.syslog_level; WSContentSend_P(PSTR("

      %s (%s)