IRremoteESP8266 library from v2.8.2 to v2.8.3

This commit is contained in:
Stephan Hadinger 2022-09-16 14:01:10 +02:00
parent 971b06ccdd
commit 914859ad48
59 changed files with 5020 additions and 400 deletions

View File

@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file.
### Changed
- ESP32 Increase number of button GPIOs from 8 to 28 (#16518)
- IRremoteESP8266 library from v2.8.2 to v2.8.3
### Fixed

View File

@ -10,8 +10,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.8.2 Now Available
Version 2.8.2 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
## v2.8.3 Now Available
Version 2.8.3 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
#### Upgrading from pre-v2.0
Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page.

View File

@ -11,8 +11,8 @@
Diese Programmbibliothek ermöglicht das **Senden _und_ Empfangen** von Infrarotsignalen mit [ESP8266](https://github.com/esp8266/Arduino)- und
[ESP32](https://github.com/espressif/arduino-esp32)-Mikrocontrollern mithilfe des [Arduino-Frameworks](https://www.arduino.cc/) und handelsüblichen 940nm Infrarot-LEDs undIR-Empfängermodulen, wie zum Beispiel TSOP{17,22,24,36,38,44,48}*-Demodulatoren.
## v2.8.2 jetzt verfügbar
Version 2.8.2 der Bibliothek ist nun [verfügbar](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Die [Versionshinweise](ReleaseNotes.md) enthalten alle wichtigen Neuerungen.
## v2.8.3 jetzt verfügbar
Version 2.8.3 der Bibliothek ist nun [verfügbar](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Die [Versionshinweise](ReleaseNotes.md) enthalten alle wichtigen Neuerungen.
#### Hinweis für Nutzer von Versionen vor v2.0
Die Benutzung der Bibliothek hat sich mit Version 2.0 leicht geändert. Einige Anpassungen im aufrufenden Code werden nötig sein, um mit Version ab 2.0 korrekt zu funktionieren. Mehr zu den Anpassungen finden sich auf unserer [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0)-Seite.

View File

@ -10,8 +10,8 @@
Cette librairie vous permetra de **recevoir et d'envoyer des signaux** infrarouge sur le protocole [ESP8266](https://github.com/esp8266/Arduino) ou sur le protocole
[ESP32](https://github.com/espressif/arduino-esp32) en utilisant le [Arduino framework](https://www.arduino.cc/) qui utilise la norme 940nm IR LEDs et le module basique de reception d'onde IR. Exemple : TSOP{17,22,24,36,38,44,48}* modules etc.
## v2.8.2 disponible
Version 2.8.2 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants.
## v2.8.3 disponible
Version 2.8.3 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants.
#### mise à jour depuis pre-v2.0
L'utilisation de la librairie à un peu changer depuis la version in v2.0. Si vous voulez l'utiliser vous devrez changer votre utilisation aussi. Vous pouvez vous renseigner sur les précondition d'utilisation ici : [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page.

View File

@ -1,5 +1,48 @@
# Release Notes
## _v2.8.3 (20220915)_
**[Bug Fixes]**
- Fix `#if` for DECODE_COOLIX48 (#1796)
- Add missing `prev`s to `decodeToState()` (#1783)
**[Features]**
- Add `pause()` function to ESP32 when receiving. (#1871)
- ARGO: Argo add `sendSensorTemp()` (#1858 #1859)
- HAIER_AC160: Experimental detail support. (#1852 #1804)
- BOSCH144: Add IRac class support (#1841)
- Mitsubishi_AC: update left vane in `IRac` class (#1837)
- Basic support for Daikin 312bit/39byte A/C protocol. (#1836 #1829)
- Experimental basic support for Sanyo AC 152 bit protocol. (#1828 #1826)
- GREE: Add model support for `YX1FSF`/Soleus Air Windown A/C (#1823 #1821)
- Experimental basic support for Bosch 144bit protocol. (#1822 #1787)
- Experimental basic support for TCL AC 96 bit protocol. (#1820 #1810)
- Add basic support for clima-butler (52bit) RCS-SD43UWI (#1815 #1812)
- TOTO: An experimental _(s)wipe_ at support for Toto Toilets. (#1811 #1806)
- CARRIER_AC128: Experimental Basic support for Carrier AC 128bit protocol. (#1798 #1797)
- HAIER_AC160: Add basic support for Haier 160bit protocol. (#1805 #1804)
- DAIKIN: Add basic support for 200-bit Daikin protocol. (#1803 #1802)
- FUJITSU: Improve handling of 10C Heat mode. (#1788 #1780)
- FUJITSU: Improve handling of short (command only) messages. (#1784 #1780)
**[Misc]**
- Improve the `_IRREMOTEESP8266_VERSION_VAL` macro (#1875 #1870)
- SONY: Update supported devices. (#1872)
- SAMSUNG: Update supported devices (#1873)
- NEC: Update supported devices (#1874)
- Give IRmacros.h smaller scope to avoid impacting projects using IRremoteESP8266 (#1857 #1853 #1851)
- Inhibit protocol names for not-included protocols (#1853 #1851)
- Test out codeql static analysis (#1842)
- Remove pylint disable=no-self-use (#1817)
- Fujitsu General: update supported devices (#1813)
- DAIKIN: Update supported devices (#1808 #1807)
- Fujitsu: Update supported remote info. (#1801 #1794)
- DAIKIN128: Update supported devices (#1754)
- Voltas: Add link to manual for 122LZF A/C. (#1800 #1799 #1238)
- Daikin128: Additional unit test. (#1795 #1754)
- MIDEA: Update supported devices (#1791 #1790)
## _v2.8.2 (20220314)_
**[Bug Fixes]**

View File

@ -1,6 +1,6 @@
<!--- WARNING: Do NOT edit this file directly.
It is generated by './tools/scrape_supported_devices.py'.
Last generated: Mon 14 Mar 2022 06:52:21 +0000 --->
Last generated: Thu 15 Sep 2022 12:54:42 +0000 --->
# IR Protocols supported by this library
| Protocol | Brand | Model | A/C Model | Detailed A/C Support |
@ -11,8 +11,11 @@
| [Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.cpp) | **[Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.h)** | ADR-853H A/C<BR>TAC-444 remote<BR>TAC-495 remote | | Yes |
| [Argo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Argo.cpp) | **[Argo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Argo.h)** | Ulisse 13 DCI Mobile Split A/C | | Yes |
| [Arris](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Arris.cpp) | **Arris** | 120A V1.0 A18 remote<BR>VIP1113M Set-top box | | - |
| [Bosch](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Bosch.cpp) | **[Bosch](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Bosch.h)** | CL3000i-Set 26 E A/C<BR>RG10A(G2S)BGEF remote | | Yes |
| [Bose](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Bose.cpp) | **Bose** | Bose TV Speaker | | - |
| [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **[Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.h)** | 40GKX0E2006 remote (CARRIER_AC128) | | Yes |
| [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **[Carrier/Surrey](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.h)** | 42QG5A55970 remote<BR>53NGK009/012 Inverter<BR>619EGX0090E0 A/C<BR>619EGX0120E0 A/C<BR>619EGX0180E0 A/C<BR>619EGX0220E0 A/C | | Yes |
| [ClimaButler](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_ClimaButler.cpp) | **Clima-Butler** | AR-715 remote<BR>RCS-SD43UWI A/C | | - |
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | RC08B remote | | Yes |
| [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<BR>RG57K7(B)/BGEF Remote | | Yes |
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Bosch](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | B1ZAI2441W/B1ZAO2441W A/C<BR>RG36B4/BGE remote | | Yes |
@ -22,7 +25,7 @@
| [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 | | Yes |
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | RAS-4M27YAV-E A/C<BR>RAS-M10YKV-E A/C<BR>RAS-M13YKV-E A/C<BR>WH-E1YE remote | | Yes |
| [Corona](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Corona.cpp) | **[Corona](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Corona.h)** | AR-01 remote<BR>CSH-N2211 A/C<BR>CSH-N2511 A/C<BR>CSH-N2811 A/C<BR>CSH-N4011 A/C | | 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 FTXB09AXVJU A/C (DAIKIN128)<BR>17 Series FTXB12AXVJU A/C (DAIKIN128)<BR>17 Series FTXB24AXVJU A/C (NOT SUPPORTED)<BR>ARC423A5 remote (DAIKIN160)<BR>ARC433** remote (DAIKIN)<BR>ARC433B69 remote (DAIKIN216)<BR>ARC466A33 remote (DAIKIN)<BR>ARC477A1 remote (DAIKIN2)<BR>ARC480A5 remote (DAIKIN152)<BR>ARC484A4 remote (DAIKIN216)<BR>BRC4C151 remote (DAIKIN176)<BR>BRC4C153 remote (DAIKIN176)<BR>BRC52B63 remote (DAIKIN128)<BR>DGS01 remote (DAIKIN64)<BR>FFN-C/FCN-F Series A/C (DAIKIN64)<BR>FFQ35B8V1B A/C (DAIKIN176)<BR>FTE12HV2S A/C<BR>FTQ60TV16U2 A/C (DAIKIN216)<BR>FTWX35AXV1 A/C (DAIKIN64)<BR>FTXM-M A/C (DAIKIN)<BR>FTXZ25NV1B A/C (DAIKIN2)<BR>FTXZ35NV1B A/C (DAIKIN2)<BR>FTXZ50NV1B A/C (DAIKIN2)<BR>M Series A/C (DAIKIN) | | 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 FTXB09AXVJU A/C (DAIKIN128)<BR>17 Series FTXB12AXVJU A/C (DAIKIN128)<BR>17 Series FTXB24AXVJU A/C (DAIKIN128)<BR>ARC423A5 remote (DAIKIN160)<BR>ARC433** remote (DAIKIN)<BR>ARC433B69 remote (DAIKIN216)<BR>ARC466A12 remote (DAIKIN)<BR>ARC466A33 remote (DAIKIN)<BR>ARC466A67 remote (DAIKIN312)<BR>ARC477A1 remote (DAIKIN2)<BR>ARC480A5 remote (DAIKIN152)<BR>ARC484A4 remote (DAIKIN216)<BR>BRC4C151 remote (DAIKIN176)<BR>BRC4C153 remote (DAIKIN176)<BR>BRC4M150W16 remote (DAIKIN200)<BR>BRC52B63 remote (DAIKIN128)<BR>DGS01 remote (DAIKIN64)<BR>FFN-C/FCN-F Series A/C (DAIKIN64)<BR>FFQ35B8V1B A/C (DAIKIN176)<BR>FTE12HV2S A/C<BR>FTQ60TV16U2 A/C (DAIKIN216)<BR>FTWX35AXV1 A/C (DAIKIN64)<BR>FTXM-M A/C (DAIKIN)<BR>FTXM20R5V1B A/C (DAIKIN312)<BR>FTXZ25NV1B A/C (DAIKIN2)<BR>FTXZ35NV1B A/C (DAIKIN2)<BR>FTXZ50NV1B A/C (DAIKIN2)<BR>M Series A/C (DAIKIN) | | Yes |
| [Delonghi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Delonghi.cpp) | **[Delonghi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Delonghi.h)** | PAC A95 | | Yes |
| [Denon](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Denon.cpp) | **Denon** | AVR-3801 A/V Receiver (probably) | | - |
| [Dish](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Dish.cpp) | **DISH NETWORK** | echostar 301 | | - |
@ -37,21 +40,23 @@
| [EliteScreens](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_EliteScreens.cpp) | **Elite Screens** | CineTension2 / CineTension3 series<BR>Home2 / Home3 series<BR>Spectrum series<BR>VMAX Plus4 series<BR>VMAX2 / VMAX2 Plus series<BR>ZSP-IR-B / ZSP-IR-W remote | | - |
| [EliteScreens](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_EliteScreens.cpp) | **Lumene Screens** | Embassy | | - |
| [Epson](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Epson.cpp) | **Epson** | EN-TW9100W Projector<BR>EX3220 Projector<BR>EX5220 Projector<BR>EX5230 Projector<BR>EX6220 Projector<BR>EX7220 Projector<BR>VS230 Projector<BR>VS330 Projector | | - |
| [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 (ARRAH2E)<BR>AR-DB1 remote (ARDB1)<BR>AR-DL10 remote (ARDB1)<BR>AR-RAC1E remote (ARRAH2E)<BR>AR-RAE1E remote (ARRAH2E)<BR>AR-RAH1U remote (ARREB1E)<BR>AR-RAH2E remote (ARRAH2E)<BR>AR-REB1E remote (ARREB1E)<BR>AR-REB4E remote (ARREB1E)<BR>AR-REW1E remote (ARREW4E)<BR>AR-REW4E remote (ARREW4E)<BR>AR-RY4 remote (ARRY4)<BR>AST9RSGCW A/C (ARDB1)<BR>ASTB09LBC A/C (ARRY4)<BR>ASTG09K A/C (ARREW4E)<BR>ASTG18K A/C (ARREW4E)<BR>ASU12RLF A/C (ARREB1E)<BR>ASU30C1 A/C (ARDB1)<BR>ASYG09KETA-B A/C (ARREW4E)<BR>ASYG30LFCA A/C (ARRAH2E)<BR>ASYG7LMCA A/C (ARREB1E) | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E<BR>ARREW4E<BR>ARRY4 | Yes |
| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AOHG09LLC A/C (ARRAH2E)<BR>AR-JW2 remote (ARJW2)<BR>AR-RCE1E remote (ARRAH2E)<BR>ASHG09LLCA A/C (ARRAH2E) | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E<BR>ARREW4E<BR>ARRY4 | 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 (ARRAH2E)<BR>AR-DB1 remote (ARDB1)<BR>AR-DL10 remote (ARDB1)<BR>AR-RAC1E remote (ARRAH2E)<BR>AR-RAE1E remote (ARRAH2E)<BR>AR-RAH1U remote (ARREB1E)<BR>AR-RAH2E remote (ARRAH2E)<BR>AR-RAH2U remote (ARRAH2E)<BR>AR-REB1E remote (ARREB1E)<BR>AR-REB4E remote (ARREB1E)<BR>AR-REG1U remote (ARRAH2E)<BR>AR-REW1E remote (ARREW4E)<BR>AR-REW4E remote (ARREW4E)<BR>AR-RY4 remote (ARRY4)<BR>AST9RSGCW A/C (ARDB1)<BR>ASTB09LBC A/C (ARRY4)<BR>ASTG09K A/C (ARREW4E)<BR>ASTG18K A/C (ARREW4E)<BR>ASU12RLF A/C (ARREB1E)<BR>ASU30C1 A/C (ARDB1)<BR>ASYG09KETA-B A/C (ARREW4E)<BR>ASYG30LFCA A/C (ARRAH2E)<BR>ASYG7LMCA A/C (ARREB1E) | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E<BR>ARREW4E<BR>ARRY4 | Yes |
| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AOHG09LLC A/C (ARRAH2E)<BR>AR-JW17 remote (ARDB1)<BR>AR-JW2 remote (ARJW2)<BR>AR-RCE1E remote (ARRAH2E)<BR>ASHG09LLCA A/C (ARRAH2E) | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E<BR>ARREW4E<BR>ARRY4 | Yes |
| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[OGeneral](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AR-RCL1E remote (ARRAH2E) | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E<BR>ARREW4E<BR>ARRY4 | Yes |
| [GICable](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GICable.cpp) | **G.I. Cable** | XRC-200 remote | | - |
| [GlobalCache](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GlobalCache.cpp) | **Global Cache** | Control Tower IR DB | | - |
| [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) | **[Amana](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | PBC093G00CC A/C<BR>YX1FF remote | YAW1F<BR>YBOFB | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Cooper & Hunter](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | CH-S09FTXG A/C<BR>YB1F2 remote | YAW1F<BR>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 | YAW1F<BR>YBOFB | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | VIR09HP115V1AH A/C<BR>VIR12HP230V1AH A/C<BR>YAA1FBF remote<BR>YAN1F1 remote<BR>YB1F2F remote | YAW1F<BR>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<BR>YBOFB2 remote | YAW1F<BR>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<BR>YAW1F remote | YAW1F<BR>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<BR>YBOFB | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Vailland](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | VAI5-035WNI A/C<BR>YACIFB remote | YAW1F<BR>YBOFB | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Amana](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | PBC093G00CC A/C<BR>YX1FF remote | YAW1F<BR>YBOFB<BR>YX1FSF | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Cooper & Hunter](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | CH-S09FTXG A/C<BR>YB1F2 remote | YAW1F<BR>YBOFB<BR>YX1FSF | 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<BR>YBOFB<BR>YX1FSF | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | VIR09HP115V1AH A/C<BR>VIR12HP230V1AH A/C<BR>YAA1FBF remote<BR>YAN1F1 remote<BR>YB1F2F remote<BR>YX1F2F remote (YX1FSF) | YAW1F<BR>YBOFB<BR>YX1FSF | 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<BR>YBOFB2 remote | YAW1F<BR>YBOFB<BR>YX1FSF | 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<BR>YAW1F remote | YAW1F<BR>YBOFB<BR>YX1FSF | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Soleus Air](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | window A/C (YX1FSF) | YAW1F<BR>YBOFB<BR>YX1FSF | 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<BR>YBOFB<BR>YX1FSF | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Vailland](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | VAI5-035WNI A/C<BR>YACIFB remote | YAW1F<BR>YBOFB<BR>YX1FSF | Yes |
| [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Daichi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | D-H A/C (HAIER_AC176) | | 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 (HAIER_AC_YRW02)<BR>HSU07-HEA03 remote (HAIER_AC)<BR>V9014557 M47 8D remote (HAIER_AC176)<BR>YR-W02 remote (HAIER_AC_YRW02) | | 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 (HAIER_AC_YRW02)<BR>HSU07-HEA03 remote (HAIER_AC)<BR>KFR-26GW/83@UI-Ge A/C (HAIER_AC160)<BR>V9014557 M47 8D remote (HAIER_AC176)<BR>YR-W02 remote (HAIER_AC_YRW02) | | Yes |
| [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Mabe](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | MMI18HDBWCA6MI8 A/C (HAIER_AC176)<BR>V12843 HJ200223 remote (HAIER_AC176) | | 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)** | KAZE-312KSDP A/C (HITACHI_AC1)<BR>LT0541-HTA remote (HITACHI_AC1)<BR>PC-LH3B (HITACHI_AC3)<BR>R-LT0541-HTA/Y.K.1.1-1 V2.3 remote (HITACHI_AC1)<BR>RAK-25NH5 A/C (HITACHI_AC264)<BR>RAR-2P2 remote (HITACHI_AC264)<BR>RAR-3U3 remote (HITACHI_AC296)<BR>RAR-8P2 remote (HITACHI_AC424)<BR>RAS-22NK A/C (HITACHI_AC344)<BR>RAS-35THA6 remote<BR>RAS-70YHA3 A/C (HITACHI_AC296)<BR>RAS-AJ25H A/C (HITACHI_AC424)<BR>RF11T1 remote (HITACHI_AC344)<BR>Series VI A/C (Circa 2007) (HITACHI_AC1) | | Yes |
| [Inax](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Inax.cpp) | **Lixil** | Inax DT-BA283 Toilet | | - |
@ -78,7 +83,7 @@
| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | FS40-7AR Stand Fan (MIDEA24) | | Yes |
| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[MrCool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG57A6/BGEFU1 remote (MIDEA) | | 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)** | RG66B6(B)/BGEFU1 remote (MIDEA)<BR>RUBO18GMFILCAD A/C (18K BTU) (MIDEA)<BR>RYBO12GMFILCAD A/C (12K BTU) (MIDEA)<BR>UB018GMFILCFHD A/C (12K BTU) (MIDEA)<BR>WS012GMFI22HLD A/C (12K BTU) (MIDEA)<BR>WS018GMFI22HLD A/C (12K BTU) (MIDEA) | | Yes |
| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG57H(B)/BGE remote (MIDEA)<BR>TROTEC PAC 3900 X (MIDEA) | | Yes |
| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG57H(B)/BGE remote (MIDEA)<BR>RG57H3(B)/BGCEF-M remote (MIDEA)<BR>TROTEC PAC 2100 X (MIDEA)<BR>TROTEC PAC 3900 X (MIDEA) | | Yes |
| [MilesTag2](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MilesTag2.cpp) | **Milestag2** | Various | | - |
| [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Maxell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | KKG9A-C1 remote<BR>MX-CH18CF A/C | KKG29AC1<BR>KKG9AC1 | Yes |
| [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | VLU series A/C | KKG29AC1<BR>KKG9AC1 | Yes |
@ -88,8 +93,10 @@
| [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 (88 bit)<BR>RLA502A700B remote (152 bit)<BR>SRKxxZJ-S A/C (88 bit)<BR>SRKxxZM-S A/C (152 bit)<BR>SRKxxZMXA-S A/C (152 bit) | | Yes |
| [Multibrackets](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Multibrackets.cpp) | **Multibrackets** | Motorized Swing mount large - 4500 | | - |
| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Aloka](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | SleepyLights LED Lamp | | - |
| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[BBK](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | SP550S 5.1 sound system | | - |
| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Duux](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | Blizzard Smart 10K / DXMA04 A/C<BR>YJ-A081 TR Remote | | - |
| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Silan Microelectronics](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | SC6121-001 IC | | - |
| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Tanix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | TX3 mini Android TV Box | | - |
| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | 42TL838 LCD TV | | - |
| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Yamaha](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | RAV561 remote<BR>RXV585B A/V Receiver | | - |
| [Neoclima](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Neoclima.cpp) | **[Neoclima](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Neoclima.h)** | NS-09AHTI A/C<BR>ZH/TY-01 remote | | Yes |
@ -101,11 +108,11 @@
| [RC5_RC6](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp) | **Philips** | RC-5X (RC5X)<BR>Standard RC-5 (RC5)<BR>Standard RC-6 (RC6) | | - |
| [RCMM](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RCMM.cpp) | **Microsoft** | XBOX 360 | | - |
| [Rhoss](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Rhoss.cpp) | **[Rhoss](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Rhoss.h)** | Idrowall MPCV 20-30-35-40 | | Yes |
| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AH59-02692E Soundbar remote (SAMSUNG36)<BR>AK59-00167A Bluray remote (SAMSUNG36)<BR>AR09FSSDAWKNFA A/C (SAMSUNG_AC)<BR>AR09HSFSBWKN A/C (SAMSUNG_AC)<BR>AR12HSSDBWKNEU A/C (SAMSUNG_AC)<BR>AR12KSFPEWQNET A/C (SAMSUNG_AC)<BR>AR12NXCXAWKXEU A/C (SAMSUNG_AC)<BR>AR12TXEAAWKNEU A/C (SAMSUNG_AC)<BR>BN59-01178B TV remote (SAMSUNG)<BR>DB63-03556X003 remote<BR>DB93-14195A remote (SAMSUNG_AC)<BR>DB93-16761C remote<BR>DB96-24901C remote (SAMSUNG_AC)<BR>HW-J551 Soundbar (SAMSUNG36)<BR>IEC-R03 remote<BR>UA55H6300 TV (SAMSUNG) | | Yes |
| [Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.cpp) | **[Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.h)** | LC7461 transmitter IC (SANYO_LC7461)<BR>RCS-2HS4E remote (SANYO_AC)<BR>RCS-2S4E remote (SANYO_AC)<BR>SA 8650B - disabled<BR>SAP-K121AHA A/C (SANYO_AC)<BR>SAP-K242AH A/C (SANYO_AC) | | Yes |
| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AH59-02692E Soundbar remote (SAMSUNG36)<BR>AK59-00167A Bluray remote (SAMSUNG36)<BR>AR09FSSDAWKNFA A/C (SAMSUNG_AC)<BR>AR09HSFSBWKN A/C (SAMSUNG_AC)<BR>AR12HSSDBWKNEU A/C (SAMSUNG_AC)<BR>AR12KSFPEWQNET A/C (SAMSUNG_AC)<BR>AR12NXCXAWKXEU A/C (SAMSUNG_AC)<BR>AR12TXEAAWKNEU A/C (SAMSUNG_AC)<BR>BN59-01178B TV remote (SAMSUNG)<BR>DB63-03556X003 remote<BR>DB93-14195A remote (SAMSUNG_AC)<BR>DB93-16761C remote<BR>DB96-24901C remote (SAMSUNG_AC)<BR>HW-J551 Soundbar (SAMSUNG36)<BR>IEC-R03 remote<BR>UA55H6300 TV (SAMSUNG)<BR>UE40K5510AUXRU TV (SAMSUNG) | | Yes |
| [Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.cpp) | **[Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.h)** | LC7461 transmitter IC (SANYO_LC7461)<BR>RCS-2HS4E remote (SANYO_AC)<BR>RCS-2S4E remote (SANYO_AC)<BR>RCS-4MHVPIS4EE remote (SANYO_AC152)<BR>SA 8650B - disabled<BR>SAP-K121AHA A/C (SANYO_AC)<BR>SAP-K242AH A/C (SANYO_AC)<BR>SAP-KMRV124EHE A/C (SANYO_AC152) | | Yes |
| [Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.cpp) | **[Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.h)** | AH-A12REVP-1 A/C (A903)<BR>AH-AxSAY A/C (A907)<BR>AH-PR13-GL A/C (A903)<BR>AH-XP10NRY A/C (A903)<BR>AY-ZP40KR A/C (A907)<BR>CRMC-820 JBEZ remote (A903)<BR>CRMC-A705 JBEZ remote (A705)<BR>CRMC-A863 JBEZ remote (A903)<BR>CRMC-A903JBEZ remote (A903)<BR>CRMC-A907 JBEZ remote (A907)<BR>CRMC-A950 JBEZ (A907)<BR>LC-52D62U TV | A705<BR>A903<BR>A907 | Yes |
| [Sherwood](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sherwood.cpp) | **Sherwood** | RC-138 remote<BR>RD6505(B) Receiver | | - |
| [Sony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sony.cpp) | **Sony** | HT-CT380 Soundbar (Uses 38kHz & 3 repeats) | | - |
| [Sony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sony.cpp) | **Sony** | HT-CT380 Soundbar (Uses 38kHz & 3 repeats)<BR>HT-SF150 Soundbar (Uses 38kHz & 3 repeats) | | - |
| [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Blyss** | Owen-SW-5 3 Fan<BR>WP-YK8 090218 remote | | - |
| [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **SamHop** | SM3015 Fan Remote Control<BR>SM5021 Encoder chip<BR>SM5032 Decoder chip | | - |
| [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Satellite Electronic** | ID6 Remote<BR>JY199I Fan driver<BR>JY199I-L Fan driver | | - |
@ -114,13 +121,14 @@
| [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Westinghouse** | 78095 Remote<BR>Ceiling fan | | - |
| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Daewoo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | DSB-F0934ELH-V A/C<BR>GYKQ-52E remote | GZ055BE1<BR>TAC09CHSD | Yes |
| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Leberg](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | LBS-TOR07 A/C (TAC09CHSD) | GZ055BE1<BR>TAC09CHSD | Yes |
| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[TCL](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | TAC-09CHSD/XA31I A/C (TAC09CHSD) | GZ055BE1<BR>TAC09CHSD | Yes |
| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[TCL](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | GYKQ-58(XM) remote (TCL96AC)<BR>TAC-09CHSD/XA31I A/C (TAC09CHSD) | GZ055BE1<BR>TAC09CHSD | Yes |
| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Teknopoint](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | Allegro SSA-09H A/C (GZ055BE1)<BR>GZ-055B-E1 remote (GZ055BE1) | GZ055BE1<BR>TAC09CHSD | Yes |
| [Technibel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Technibel.cpp) | **[Technibel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Technibel.h)** | IRO PLUS | | Yes |
| [Teco](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.cpp) | **[Alaska](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.h)** | SAC9010QC A/C<BR>SAC9010QC remote | | Yes |
| [Teknopoint](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teknopoint.cpp) | **Teknopoint** | Allegro SSA-09H A/C<BR>GZ-055B-E1 remote<BR>GZ01-BEJ0-000 remote | | - |
| [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | 42NQV025M2 / 38NYV025M2 A/C<BR>42NQV035M2 / 38NYV035M2 A/C<BR>42NQV050M2 / 38NYV050M2 A/C<BR>42NQV060M2 / 38NYV060M2 A/C | | Yes |
| [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | Akita EVO II<BR>RAS 18SKP-ES<BR>RAS-2558V A/C<BR>RAS-25SKVP2-ND A/C<BR>RAS-B13N3KV2<BR>RAS-B13N3KVP-E<BR>WC-L03SE<BR>WH-TA01JE remote<BR>WH-TA04NE<BR>WH-UB03NJ remote | | Yes |
| [Toto](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toto.cpp) | **Toto** | Washlet Toilet NJ | | - |
| [Transcold](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Transcold.cpp) | **[Transcold](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Transcold.h)** | M1-F-NO-6 A/C | | Yes |
| [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Duux](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | Blizzard Smart 10K / DXMA04 A/C (TROTEC) | | Yes |
| [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | PAC 3200 A/C (TROTEC)<BR>PAC 3550 Pro A/C (TROTEC_3550) | | Yes |
@ -150,10 +158,13 @@
- AMCOR
- ARGO
- ARRIS
- BOSCH144
- BOSE
- CARRIER_AC
- CARRIER_AC128
- CARRIER_AC40
- CARRIER_AC64
- CLIMABUTLER
- COOLIX
- COOLIX48
- CORONA_AC
@ -163,7 +174,9 @@
- DAIKIN160
- DAIKIN176
- DAIKIN2
- DAIKIN200
- DAIKIN216
- DAIKIN312
- DAIKIN64
- DELONGHI_AC
- DENON
@ -178,6 +191,7 @@
- GOODWEATHER
- GREE
- HAIER_AC
- HAIER_AC160
- HAIER_AC176
- HAIER_AC_YRW02
- HITACHI_AC
@ -231,6 +245,7 @@
- SAMSUNG_AC
- SANYO
- SANYO_AC
- SANYO_AC152
- SANYO_AC88
- SANYO_LC7461
- SHARP
@ -238,10 +253,12 @@
- SONY
- SYMPHONY
- TCL112AC
- TCL96AC
- TECHNIBEL_AC
- TECO
- TEKNOPOINT
- TOSHIBA_AC
- TOTO
- TRANSCOLD
- TROTEC
- TROTEC_3550

View File

@ -25,6 +25,7 @@ IRAirtonAc KEYWORD1
IRAirwellAc KEYWORD1
IRAmcorAc KEYWORD1
IRArgoAC KEYWORD1
IRBosch144AC KEYWORD1
IRCarrierAc64 KEYWORD1
IRCoolixAC KEYWORD1
IRCoronaAc KEYWORD1
@ -43,6 +44,7 @@ IRFujitsuAC KEYWORD1
IRGoodweatherAc KEYWORD1
IRGreeAC KEYWORD1
IRHaierAC KEYWORD1
IRHaierAC160 KEYWORD1
IRHaierAC176 KEYWORD1
IRHaierACYRW02 KEYWORD1
IRHitachiAc KEYWORD1
@ -159,6 +161,7 @@ argo KEYWORD2
bcdToUint8 KEYWORD2
begin KEYWORD2
boolToString KEYWORD2
bosch144 KEYWORD2
buildFromState KEYWORD2
calcBlockChecksum KEYWORD2
calcChecksum KEYWORD2
@ -213,11 +216,14 @@ decodeAiwaRCT501 KEYWORD2
decodeAmcor KEYWORD2
decodeArgo KEYWORD2
decodeArris KEYWORD2
decodeBosch144 KEYWORD2
decodeBose KEYWORD2
decodeCOOLIX KEYWORD2
decodeCarrierAC KEYWORD2
decodeCarrierAC128 KEYWORD2
decodeCarrierAC40 KEYWORD2
decodeCarrierAC64 KEYWORD2
decodeClimaButler KEYWORD2
decodeCoolix48 KEYWORD2
decodeCoronaAc KEYWORD2
decodeDISH KEYWORD2
@ -227,7 +233,9 @@ decodeDaikin152 KEYWORD2
decodeDaikin160 KEYWORD2
decodeDaikin176 KEYWORD2
decodeDaikin2 KEYWORD2
decodeDaikin200 KEYWORD2
decodeDaikin216 KEYWORD2
decodeDaikin312 KEYWORD2
decodeDaikin64 KEYWORD2
decodeDelonghiAc KEYWORD2
decodeDenon KEYWORD2
@ -241,6 +249,7 @@ decodeGICable KEYWORD2
decodeGoodweather KEYWORD2
decodeGree KEYWORD2
decodeHaierAC KEYWORD2
decodeHaierAC160 KEYWORD2
decodeHaierAC176 KEYWORD2
decodeHaierACYRW02 KEYWORD2
decodeHash KEYWORD2
@ -287,17 +296,20 @@ decodeSamsung36 KEYWORD2
decodeSamsungAC KEYWORD2
decodeSanyo KEYWORD2
decodeSanyoAc KEYWORD2
decodeSanyoAc152 KEYWORD2
decodeSanyoAc88 KEYWORD2
decodeSanyoLC7461 KEYWORD2
decodeSharp KEYWORD2
decodeSharpAc KEYWORD2
decodeSony KEYWORD2
decodeSymphony KEYWORD2
decodeTcl96Ac KEYWORD2
decodeTechnibelAc KEYWORD2
decodeTeco KEYWORD2
decodeTeknopoint KEYWORD2
decodeToState KEYWORD2
decodeToshibaAC KEYWORD2
decodeToto KEYWORD2
decodeTranscold KEYWORD2
decodeTrotec KEYWORD2
decodeTrotec3550 KEYWORD2
@ -351,6 +363,7 @@ get3D KEYWORD2
get8CHeat KEYWORD2
get8CHeatToggle KEYWORD2
getAbsenseDetect KEYWORD2
getAuxHeating KEYWORD2
getBeep KEYWORD2
getBit KEYWORD2
getBoost KEYWORD2
@ -490,6 +503,7 @@ getiFeel KEYWORD2
goodweather KEYWORD2
gree KEYWORD2
haier KEYWORD2
haier160 KEYWORD2
haier176 KEYWORD2
haierYrwo2 KEYWORD2
handleSpecialState KEYWORD2
@ -511,6 +525,7 @@ is8CHeatToggle KEYWORD2
isCleanToggle KEYWORD2
isEconoToggle KEYWORD2
isLightToggle KEYWORD2
isLongCode KEYWORD2
isOffCommand KEYWORD2
isOffTimerActive KEYWORD2
isOffTimerEnabled KEYWORD2
@ -569,6 +584,7 @@ on KEYWORD2
opmodeToString KEYWORD2
panasonic KEYWORD2
panasonic32 KEYWORD2
pause KEYWORD2
recoverSavedState KEYWORD2
reset KEYWORD2
resultAcToString KEYWORD2
@ -591,11 +607,14 @@ sendAiwaRCT501 KEYWORD2
sendAmcor KEYWORD2
sendArgo KEYWORD2
sendArris KEYWORD2
sendBosch144 KEYWORD2
sendBose KEYWORD2
sendCOOLIX KEYWORD2
sendCarrierAC KEYWORD2
sendCarrierAC128 KEYWORD2
sendCarrierAC40 KEYWORD2
sendCarrierAC64 KEYWORD2
sendClimaButler KEYWORD2
sendCoolix48 KEYWORD2
sendCoronaAc KEYWORD2
sendDISH KEYWORD2
@ -605,7 +624,9 @@ sendDaikin152 KEYWORD2
sendDaikin160 KEYWORD2
sendDaikin176 KEYWORD2
sendDaikin2 KEYWORD2
sendDaikin200 KEYWORD2
sendDaikin216 KEYWORD2
sendDaikin312 KEYWORD2
sendDaikin64 KEYWORD2
sendData KEYWORD2
sendDelonghiAc KEYWORD2
@ -623,6 +644,7 @@ sendGeneric KEYWORD2
sendGoodweather KEYWORD2
sendGree KEYWORD2
sendHaierAC KEYWORD2
sendHaierAC160 KEYWORD2
sendHaierAC176 KEYWORD2
sendHaierACYRW02 KEYWORD2
sendHitachiAC KEYWORD2
@ -680,8 +702,10 @@ sendSAMSUNG KEYWORD2
sendSamsung36 KEYWORD2
sendSamsungAC KEYWORD2
sendSanyoAc KEYWORD2
sendSanyoAc152 KEYWORD2
sendSanyoAc88 KEYWORD2
sendSanyoLC7461 KEYWORD2
sendSensorTemp KEYWORD2
sendSharp KEYWORD2
sendSharpAc KEYWORD2
sendSharpRaw KEYWORD2
@ -690,10 +714,12 @@ sendSony KEYWORD2
sendSony38 KEYWORD2
sendSymphony KEYWORD2
sendTcl112Ac KEYWORD2
sendTcl96Ac KEYWORD2
sendTechnibelAc KEYWORD2
sendTeco KEYWORD2
sendTeknopoint KEYWORD2
sendToshibaAC KEYWORD2
sendToto KEYWORD2
sendTranscold KEYWORD2
sendTrotec KEYWORD2
sendTrotec3550 KEYWORD2
@ -711,6 +737,7 @@ set8CHeat KEYWORD2
set8CHeatToggle KEYWORD2
setAbsenseDetect KEYWORD2
setAuto KEYWORD2
setAuxHeating KEYWORD2
setBeep KEYWORD2
setBit KEYWORD2
setBits KEYWORD2
@ -718,6 +745,7 @@ setBoost KEYWORD2
setBreeze KEYWORD2
setButton KEYWORD2
setCelsius KEYWORD2
setCheckSumS3 KEYWORD2
setClean KEYWORD2
setCleanToggle KEYWORD2
setClock KEYWORD2
@ -753,6 +781,7 @@ setIFeel KEYWORD2
setISave10C KEYWORD2
setISee KEYWORD2
setId KEYWORD2
setInvertBytes KEYWORD2
setInvertedStates KEYWORD2
setIon KEYWORD2
setIonFilter KEYWORD2
@ -927,11 +956,14 @@ ARREB1E LITERAL1
ARREW4E LITERAL1
ARRIS LITERAL1
ARRY4 LITERAL1
BOSCH144 LITERAL1
BOSE LITERAL1
CARRIER_AC LITERAL1
CARRIER_AC128 LITERAL1
CARRIER_AC40 LITERAL1
CARRIER_AC64 LITERAL1
CARRIER_AC_BITS LITERAL1
CLIMABUTLER LITERAL1
COOLIX LITERAL1
COOLIX48 LITERAL1
COOLIX_BITS LITERAL1
@ -942,7 +974,9 @@ DAIKIN152 LITERAL1
DAIKIN160 LITERAL1
DAIKIN176 LITERAL1
DAIKIN2 LITERAL1
DAIKIN200 LITERAL1
DAIKIN216 LITERAL1
DAIKIN312 LITERAL1
DAIKIN64 LITERAL1
DAIKIN_AUTO LITERAL1
DAIKIN_COMMAND_LENGTH LITERAL1
@ -963,10 +997,13 @@ DECODE_AIWA_RC_T501 LITERAL1
DECODE_AMCOR LITERAL1
DECODE_ARGO LITERAL1
DECODE_ARRIS LITERAL1
DECODE_BOSCH144 LITERAL1
DECODE_BOSE LITERAL1
DECODE_CARRIER_AC LITERAL1
DECODE_CARRIER_AC128 LITERAL1
DECODE_CARRIER_AC40 LITERAL1
DECODE_CARRIER_AC64 LITERAL1
DECODE_CLIMABUTLER LITERAL1
DECODE_COOLIX LITERAL1
DECODE_COOLIX48 LITERAL1
DECODE_CORONA_AC LITERAL1
@ -976,7 +1013,9 @@ DECODE_DAIKIN152 LITERAL1
DECODE_DAIKIN160 LITERAL1
DECODE_DAIKIN176 LITERAL1
DECODE_DAIKIN2 LITERAL1
DECODE_DAIKIN200 LITERAL1
DECODE_DAIKIN216 LITERAL1
DECODE_DAIKIN312 LITERAL1
DECODE_DAIKIN64 LITERAL1
DECODE_DELONGHI_AC LITERAL1
DECODE_DENON LITERAL1
@ -992,6 +1031,7 @@ DECODE_GLOBALCACHE LITERAL1
DECODE_GOODWEATHER LITERAL1
DECODE_GREE LITERAL1
DECODE_HAIER_AC LITERAL1
DECODE_HAIER_AC160 LITERAL1
DECODE_HAIER_AC176 LITERAL1
DECODE_HAIER_AC_YRW02 LITERAL1
DECODE_HASH LITERAL1
@ -1043,6 +1083,7 @@ DECODE_SAMSUNG36 LITERAL1
DECODE_SAMSUNG_AC LITERAL1
DECODE_SANYO LITERAL1
DECODE_SANYO_AC LITERAL1
DECODE_SANYO_AC152 LITERAL1
DECODE_SANYO_AC88 LITERAL1
DECODE_SHARP LITERAL1
DECODE_SHARP_AC LITERAL1
@ -1050,10 +1091,12 @@ DECODE_SHERWOOD LITERAL1
DECODE_SONY LITERAL1
DECODE_SYMPHONY LITERAL1
DECODE_TCL112AC LITERAL1
DECODE_TCL96AC LITERAL1
DECODE_TECHNIBEL_AC LITERAL1
DECODE_TECO LITERAL1
DECODE_TEKNOPOINT LITERAL1
DECODE_TOSHIBA_AC LITERAL1
DECODE_TOTO LITERAL1
DECODE_TRANSCOLD LITERAL1
DECODE_TROTEC LITERAL1
DECODE_TROTEC_3550 LITERAL1
@ -1133,6 +1176,7 @@ GREE_SWING_UP LITERAL1
GREE_SWING_UP_AUTO LITERAL1
GZ055BE1 LITERAL1
HAIER_AC LITERAL1
HAIER_AC160 LITERAL1
HAIER_AC176 LITERAL1
HAIER_AC_AUTO LITERAL1
HAIER_AC_CMD_FAN LITERAL1
@ -1289,6 +1333,7 @@ NEC_LIKE LITERAL1
NEOCLIMA LITERAL1
NIKAI LITERAL1
NIKAI_BITS LITERAL1
NOTHING LITERAL1
ONCE LITERAL1
PANASONIC LITERAL1
PANASONIC_AC LITERAL1
@ -1317,6 +1362,7 @@ SAMSUNG_AC LITERAL1
SAMSUNG_BITS LITERAL1
SANYO LITERAL1
SANYO_AC LITERAL1
SANYO_AC152 LITERAL1
SANYO_AC88 LITERAL1
SANYO_LC7461 LITERAL1
SANYO_LC7461_BITS LITERAL1
@ -1327,10 +1373,13 @@ SEND_AIWA_RC_T501 LITERAL1
SEND_AMCOR LITERAL1
SEND_ARGO LITERAL1
SEND_ARRIS LITERAL1
SEND_BOSCH144 LITERAL1
SEND_BOSE LITERAL1
SEND_CARRIER_AC LITERAL1
SEND_CARRIER_AC128 LITERAL1
SEND_CARRIER_AC40 LITERAL1
SEND_CARRIER_AC64 LITERAL1
SEND_CLIMABUTLER LITERAL1
SEND_COOLIX LITERAL1
SEND_COOLIX48 LITERAL1
SEND_CORONA_AC LITERAL1
@ -1340,7 +1389,9 @@ SEND_DAIKIN152 LITERAL1
SEND_DAIKIN160 LITERAL1
SEND_DAIKIN176 LITERAL1
SEND_DAIKIN2 LITERAL1
SEND_DAIKIN200 LITERAL1
SEND_DAIKIN216 LITERAL1
SEND_DAIKIN312 LITERAL1
SEND_DAIKIN64 LITERAL1
SEND_DELONGHI_AC LITERAL1
SEND_DENON LITERAL1
@ -1356,6 +1407,7 @@ SEND_GLOBALCACHE LITERAL1
SEND_GOODWEATHER LITERAL1
SEND_GREE LITERAL1
SEND_HAIER_AC LITERAL1
SEND_HAIER_AC160 LITERAL1
SEND_HAIER_AC176 LITERAL1
SEND_HAIER_AC_YRW02 LITERAL1
SEND_HITACHI_AC LITERAL1
@ -1407,6 +1459,7 @@ SEND_SAMSUNG36 LITERAL1
SEND_SAMSUNG_AC LITERAL1
SEND_SANYO LITERAL1
SEND_SANYO_AC LITERAL1
SEND_SANYO_AC152 LITERAL1
SEND_SANYO_AC88 LITERAL1
SEND_SHARP LITERAL1
SEND_SHARP_AC LITERAL1
@ -1414,10 +1467,12 @@ SEND_SHERWOOD LITERAL1
SEND_SONY LITERAL1
SEND_SYMPHONY LITERAL1
SEND_TCL112AC LITERAL1
SEND_TCL96AC LITERAL1
SEND_TECHNIBEL_AC LITERAL1
SEND_TECO LITERAL1
SEND_TEKNOPOINT LITERAL1
SEND_TOSHIBA_AC LITERAL1
SEND_TOTO LITERAL1
SEND_TRANSCOLD LITERAL1
SEND_TROTEC LITERAL1
SEND_TROTEC_3550 LITERAL1
@ -1441,6 +1496,7 @@ SONY_38K LITERAL1
SYMPHONY LITERAL1
TAC09CHSD LITERAL1
TCL112AC LITERAL1
TCL96AC LITERAL1
TECHNIBEL_AC LITERAL1
TECO LITERAL1
TEKNOPOINT LITERAL1
@ -1456,6 +1512,7 @@ TOSHIBA_AC_MAX_TEMP LITERAL1
TOSHIBA_AC_MIN_TEMP LITERAL1
TOSHIBA_AC_POWER LITERAL1
TOSHIBA_AC_STATE_LENGTH LITERAL1
TOTO LITERAL1
TRANSCOLD LITERAL1
TROTEC LITERAL1
TROTEC_3550 LITERAL1
@ -1484,6 +1541,7 @@ WHYNTER_BITS LITERAL1
XMP LITERAL1
YAW1F LITERAL1
YBOFB LITERAL1
YX1FSF LITERAL1
ZEPEAL LITERAL1
k0Str LITERAL1
k10CHeatStr LITERAL1
@ -1644,6 +1702,35 @@ kAutoStr LITERAL1
kAutomaticStr LITERAL1
kBeepStr LITERAL1
kBitsStr LITERAL1
kBosch144Auto LITERAL1
kBosch144Bits LITERAL1
kBosch144BytesPerSection LITERAL1
kBosch144Cool LITERAL1
kBosch144DefaultState LITERAL1
kBosch144Dry LITERAL1
kBosch144Fan LITERAL1
kBosch144Fan100 LITERAL1
kBosch144Fan20 LITERAL1
kBosch144Fan40 LITERAL1
kBosch144Fan60 LITERAL1
kBosch144Fan80 LITERAL1
kBosch144FanAuto LITERAL1
kBosch144FanAuto0 LITERAL1
kBosch144Heat LITERAL1
kBosch144NrOfSections LITERAL1
kBosch144Off LITERAL1
kBosch144StateLength LITERAL1
kBosch144TempMap LITERAL1
kBosch144TempMax LITERAL1
kBosch144TempMin LITERAL1
kBosch144TempRange LITERAL1
kBoschBitMark LITERAL1
kBoschFooterSpace LITERAL1
kBoschFreq LITERAL1
kBoschHdrMark LITERAL1
kBoschHdrSpace LITERAL1
kBoschOneSpace LITERAL1
kBoschZeroSpace LITERAL1
kBoseBitMark LITERAL1
kBoseBits LITERAL1
kBoseFreq LITERAL1
@ -1656,6 +1743,19 @@ kBottomStr LITERAL1
kBreezeStr LITERAL1
kButtonStr LITERAL1
kCancelStr LITERAL1
kCarrierAc128BitMark LITERAL1
kCarrierAc128Bits LITERAL1
kCarrierAc128Hdr2Mark LITERAL1
kCarrierAc128Hdr2Space LITERAL1
kCarrierAc128HdrMark LITERAL1
kCarrierAc128HdrSpace LITERAL1
kCarrierAc128InterSpace LITERAL1
kCarrierAc128MinRepeat LITERAL1
kCarrierAc128OneSpace LITERAL1
kCarrierAc128SectionBits LITERAL1
kCarrierAc128SectionGap LITERAL1
kCarrierAc128StateLength LITERAL1
kCarrierAc128ZeroSpace LITERAL1
kCarrierAc40BitMark LITERAL1
kCarrierAc40Bits LITERAL1
kCarrierAc40Gap LITERAL1
@ -1702,6 +1802,14 @@ kChangeStr LITERAL1
kCirculateStr LITERAL1
kCkpStr LITERAL1
kCleanStr LITERAL1
kClimaButlerBitMark LITERAL1
kClimaButlerBits LITERAL1
kClimaButlerFreq LITERAL1
kClimaButlerGap LITERAL1
kClimaButlerHdrMark LITERAL1
kClimaButlerHdrSpace LITERAL1
kClimaButlerOneSpace LITERAL1
kClimaButlerZeroSpace LITERAL1
kClockStr LITERAL1
kCodeStr LITERAL1
kColonSpaceStr LITERAL1
@ -1880,6 +1988,19 @@ kDaikin176StateLength LITERAL1
kDaikin176SwingHAuto LITERAL1
kDaikin176SwingHOff LITERAL1
kDaikin176ZeroSpace LITERAL1
kDaikin200BitMark LITERAL1
kDaikin200Bits LITERAL1
kDaikin200DefaultRepeat LITERAL1
kDaikin200Freq LITERAL1
kDaikin200Gap LITERAL1
kDaikin200HdrMark LITERAL1
kDaikin200HdrSpace LITERAL1
kDaikin200OneSpace LITERAL1
kDaikin200Section1Length LITERAL1
kDaikin200Section2Length LITERAL1
kDaikin200Sections LITERAL1
kDaikin200StateLength LITERAL1
kDaikin200ZeroSpace LITERAL1
kDaikin216BitMark LITERAL1
kDaikin216Bits LITERAL1
kDaikin216DefaultRepeat LITERAL1
@ -1940,6 +2061,19 @@ kDaikin2SwingVSwing LITERAL1
kDaikin2SwingVUpperMiddle LITERAL1
kDaikin2Tolerance LITERAL1
kDaikin2ZeroSpace LITERAL1
kDaikin312BitMark LITERAL1
kDaikin312Bits LITERAL1
kDaikin312DefaultRepeat LITERAL1
kDaikin312HdrGap LITERAL1
kDaikin312HdrMark LITERAL1
kDaikin312HdrSpace LITERAL1
kDaikin312OneSpace LITERAL1
kDaikin312Section1Length LITERAL1
kDaikin312Section2Length LITERAL1
kDaikin312SectionGap LITERAL1
kDaikin312Sections LITERAL1
kDaikin312StateLength LITERAL1
kDaikin312ZeroSpace LITERAL1
kDaikin64BitMark LITERAL1
kDaikin64Bits LITERAL1
kDaikin64ChecksumOffset LITERAL1
@ -2202,6 +2336,8 @@ kFujitsuAcMaxTemp LITERAL1
kFujitsuAcMaxTempF LITERAL1
kFujitsuAcMinBits LITERAL1
kFujitsuAcMinGap LITERAL1
kFujitsuAcMinHeat LITERAL1
kFujitsuAcMinHeatF LITERAL1
kFujitsuAcMinRepeat LITERAL1
kFujitsuAcMinTemp LITERAL1
kFujitsuAcMinTempF LITERAL1
@ -2290,6 +2426,7 @@ kGreeDisplayTempOff LITERAL1
kGreeDisplayTempOutside LITERAL1
kGreeDisplayTempSet LITERAL1
kGreeDry LITERAL1
kGreeEcono LITERAL1
kGreeFan LITERAL1
kGreeFanAuto LITERAL1
kGreeFanMax LITERAL1
@ -2325,12 +2462,27 @@ kGreeSwingUpAuto LITERAL1
kGreeTimerMax LITERAL1
kGreeZeroSpace LITERAL1
kGz055be1Str LITERAL1
kHaierAC160Bits LITERAL1
kHaierAC160StateLength LITERAL1
kHaierAC176Bits LITERAL1
kHaierAC176StateLength LITERAL1
kHaierACBits LITERAL1
kHaierACStateLength LITERAL1
kHaierACYRW02Bits LITERAL1
kHaierACYRW02StateLength LITERAL1
kHaierAc160ButtonAuxHeating LITERAL1
kHaierAc160ButtonClean LITERAL1
kHaierAc160ButtonLight LITERAL1
kHaierAc160DefaultRepeat LITERAL1
kHaierAc160Prefix LITERAL1
kHaierAc160SwingVAuto LITERAL1
kHaierAc160SwingVHigh LITERAL1
kHaierAc160SwingVHighest LITERAL1
kHaierAc160SwingVLow LITERAL1
kHaierAc160SwingVLowest LITERAL1
kHaierAc160SwingVMiddle LITERAL1
kHaierAc160SwingVOff LITERAL1
kHaierAc160SwingVTop LITERAL1
kHaierAc176DefaultRepeat LITERAL1
kHaierAc176Prefix LITERAL1
kHaierAcAuto LITERAL1
@ -3538,6 +3690,16 @@ kSamsungRptSpaceTicks LITERAL1
kSamsungTick LITERAL1
kSamsungZeroSpace LITERAL1
kSamsungZeroSpaceTicks LITERAL1
kSanyoAc152BitMark LITERAL1
kSanyoAc152Bits LITERAL1
kSanyoAc152ExtraTolerance LITERAL1
kSanyoAc152Freq LITERAL1
kSanyoAc152HdrMark LITERAL1
kSanyoAc152HdrSpace LITERAL1
kSanyoAc152MinRepeat LITERAL1
kSanyoAc152OneSpace LITERAL1
kSanyoAc152StateLength LITERAL1
kSanyoAc152ZeroSpace LITERAL1
kSanyoAc88Auto LITERAL1
kSanyoAc88BitMark LITERAL1
kSanyoAc88Bits LITERAL1
@ -3770,6 +3932,15 @@ kTcl112AcTimerMax LITERAL1
kTcl112AcTimerResolution LITERAL1
kTcl112AcTolerance LITERAL1
kTcl112AcZeroSpace LITERAL1
kTcl96AcBitMark LITERAL1
kTcl96AcBitSpaces LITERAL1
kTcl96AcBits LITERAL1
kTcl96AcDefaultRepeat LITERAL1
kTcl96AcGap LITERAL1
kTcl96AcHdrMark LITERAL1
kTcl96AcHdrSpace LITERAL1
kTcl96AcSpaceCount LITERAL1
kTcl96AcStateLength LITERAL1
kTechnibelAcBitMark LITERAL1
kTechnibelAcBits LITERAL1
kTechnibelAcCool LITERAL1
@ -3871,6 +4042,19 @@ kToshibaAcSwingToggle LITERAL1
kToshibaAcTurboOn LITERAL1
kToshibaAcUsualGap LITERAL1
kToshibaAcZeroSpace LITERAL1
kTotoBitMark LITERAL1
kTotoBits LITERAL1
kTotoDefaultRepeat LITERAL1
kTotoGap LITERAL1
kTotoHdrMark LITERAL1
kTotoHdrSpace LITERAL1
kTotoLongBits LITERAL1
kTotoOneSpace LITERAL1
kTotoPrefix LITERAL1
kTotoPrefixBits LITERAL1
kTotoShortBits LITERAL1
kTotoSpecialGap LITERAL1
kTotoZeroSpace LITERAL1
kTranscoldAuto LITERAL1
kTranscoldBitMark LITERAL1
kTranscoldBits LITERAL1
@ -4090,6 +4274,7 @@ kXmpWordSize LITERAL1
kYaw1fStr LITERAL1
kYbofbStr LITERAL1
kYesStr LITERAL1
kYx1fsfStr LITERAL1
kZepealBits LITERAL1
kZepealCommandOffOn LITERAL1
kZepealCommandOffTimer LITERAL1

View File

@ -1,6 +1,6 @@
{
"name": "IRremoteESP8266",
"version": "2.8.2",
"version": "2.8.3",
"keywords": "infrared, ir, remote, esp8266, esp32",
"description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)",
"repository":

View File

@ -1,5 +1,5 @@
name=IRremoteESP8266
version=2.8.2
version=2.8.3
author=David Conran, Sebastien Warin, Mark Szabo, Ken Shirriff
maintainer=David Conran, Mark Szabo, Sebastien Warin, Roi Dayan, Massimiliano Pinto, Christian Nilsson
sentence=Send and receive infrared signals with multiple protocols (ESP8266/ESP32)

View File

@ -20,6 +20,7 @@
#include "ir_Airwell.h"
#include "ir_Amcor.h"
#include "ir_Argo.h"
#include "ir_Bosch.h"
#include "ir_Carrier.h"
#include "ir_Coolix.h"
#include "ir_Corona.h"
@ -161,6 +162,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
#if SEND_ARGO
case decode_type_t::ARGO:
#endif
#if SEND_BOSCH144
case decode_type_t::BOSCH144:
#endif
#if SEND_CARRIER_AC64
case decode_type_t::CARRIER_AC64:
#endif // SEND_CARRIER_AC64
@ -215,6 +219,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
#if SEND_HAIER_AC
case decode_type_t::HAIER_AC:
#endif
#if SEND_HAIER_AC160
case decode_type_t::HAIER_AC160:
#endif // SEND_HAIER_AC160
#if SEND_HAIER_AC176
case decode_type_t::HAIER_AC176:
#endif // SEND_HAIER_AC176
@ -459,6 +466,47 @@ void IRac::argo(IRArgoAC *ac,
}
#endif // SEND_ARGO
#if SEND_BOSCH144
/// Send a Bosch144 A/C message with the supplied settings.
/// @note May result in multiple messages being sent.
/// @param[in, out] ac A Ptr to an IRBosch144AC object to use.
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] degrees The temperature setting in degrees.
/// @param[in] fan The speed setting for the fan.
/// @param[in] quiet Run the device in quiet/silent mode.
/// @note -1 is Off, >= 0 is on.
void IRac::bosch144(IRBosch144AC *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const bool quiet) {
ac->begin();
ac->setPower(on);
if (!on) {
// after turn off AC no more commands should
// be accepted
ac->send();
return;
}
ac->setTemp(degrees);
ac->setFan(ac->convertFan(fan));
ac->setMode(ac->convertMode(mode));
ac->setQuiet(quiet);
ac->send(); // Send the state, which will also power on the unit.
// The following are all options/settings that create their own special
// messages. Often they only make sense to be sent after the unit is turned
// on. For instance, assuming a person wants to have the a/c on and in turbo
// mode. If we send the turbo message, it is ignored if the unit is off.
// Hence we send the special mode/setting messages after a normal message
// which will turn on the device.
// No Filter setting available.
// No Beep setting available.
// No Clock setting available.
// No Econo setting available.
// No Sleep setting available.
}
#endif // SEND_BOSCH144
#if SEND_CARRIER_AC64
/// Send a Carrier 64-bit A/C message with the supplied settings.
/// @param[in, out] ac A Ptr to an IRCarrierAc64 object to use.
@ -1155,6 +1203,52 @@ void IRac::haier(IRHaierAC *ac,
}
#endif // SEND_HAIER_AC
#if SEND_HAIER_AC160
/// Send a Haier 160 bit A/C message with the supplied settings.
/// @param[in, out] ac A Ptr to an IRHaierAC160 object to use.
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] celsius Temperature units. True is Celsius, False is Fahrenheit.
/// @param[in] degrees The temperature setting in degrees.
/// @param[in] fan The speed setting for the fan.
/// @param[in] swingv The vertical swing setting.
/// @param[in] turbo Run the device in turbo/powerful mode.
/// @param[in] quiet Run the device in quiet mode.
/// @param[in] filter Turn on the (ion/pollen/etc) filter mode.
/// @param[in] clean Turn on the clean mode.
/// @param[in] light Turn on the LED/Display mode.
/// @param[in] prevlight Previous LED/Display mode.
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
void IRac::haier160(IRHaierAC160 *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 bool turbo, const bool quiet, const bool filter,
const bool clean, const bool light, const bool prevlight,
const int16_t sleep) {
ac->begin();
// No Model setting available.
ac->setMode(ac->convertMode(mode));
ac->setUseFahrenheit(!celsius);
ac->setTemp(degrees);
ac->setFan(ac->convertFan(fan));
ac->setSwingV(ac->convertSwingV(swingv));
// No Horizontal Swing setting available.
ac->setQuiet(quiet);
ac->setTurbo(turbo);
ac->setHealth(filter);
ac->setClean(clean);
// No Clean setting available.
// No Beep setting available.
ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
ac->setPower(on);
// Light needs to be sent last as the "button" value seems to control it.
ac->setLightToggle(light ^ prevlight);
ac->send();
}
#endif // SEND_HAIER_AC160
#if SEND_HAIER_AC176
/// Send a Haier 176 bit A/C message with the supplied settings.
/// @param[in, out] ac A Ptr to an IRHaierAC176 object to use.
@ -1642,6 +1736,7 @@ void IRac::mitsubishi(IRMitsubishiAC *ac,
ac->setTemp(degrees);
ac->setFan(ac->convertFan(fan));
ac->setVane(ac->convertSwingV(swingv));
ac->setVaneLeft(ac->convertSwingV(swingv));
ac->setWideVane(ac->convertSwingH(swingh));
if (quiet) ac->setFan(kMitsubishiAcFanSilent);
ac->setISave10C(false);
@ -2718,6 +2813,9 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
const stdAc::swingv_t prev_swingv = (prev != NULL) ? prev->swingv
: stdAc::swingv_t::kOff;
#endif // (SEND_LG || SEND_SHARP_AC)
#if (SEND_HAIER_AC160)
const bool prev_light = (prev != NULL) ? prev->light : !send.light;
#endif // (SEND_HAIER_AC160)
#if SEND_MIDEA
const bool prev_quiet = (prev != NULL) ? prev->quiet : !send.quiet;
#endif // SEND_MIDEA
@ -2758,6 +2856,14 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
break;
}
#endif // SEND_ARGO
#if SEND_BOSCH144
case BOSCH144:
{
IRBosch144AC ac(_pin, _inverted, _modulation);
bosch144(&ac, send.power, send.mode, degC, send.fanspeed, send.quiet);
break;
}
#endif // SEND_BOSCH144
#if SEND_CARRIER_AC64
case CARRIER_AC64:
{
@ -2924,6 +3030,16 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
break;
}
#endif // SEND_HAIER_AC
#if SEND_HAIER_AC160
case HAIER_AC160:
{
IRHaierAC160 ac(_pin, _inverted, _modulation);
haier160(&ac, send.power, send.mode, send.celsius, send.degrees,
send.fanspeed, send.swingv, send.turbo, send.filter, send.clean,
send.light, prev_light, send.sleep);
break;
}
#endif // SEND_HAIER_AC160
#if SEND_HAIER_AC176
case HAIER_AC176:
{
@ -3472,6 +3588,8 @@ int16_t IRac::strToModel(const char *str, const int16_t def) {
return gree_ac_remote_model_t::YAW1F;
} else if (!STRCASECMP(str, kYbofbStr)) {
return gree_ac_remote_model_t::YBOFB;
} else if (!STRCASECMP(str, kYx1fsfStr)) {
return gree_ac_remote_model_t::YX1FSF;
// Haier models
} else if (!STRCASECMP(str, kV9014557AStr)) {
return haier_ac176_remote_model_t::V9014557_A;
@ -3683,6 +3801,13 @@ namespace IRAcUtils {
return ac.toString();
}
#endif // DECODE_ARGO
#if DECODE_BOSCH144
case decode_type_t::BOSCH144: {
IRBosch144AC ac(kGpioUnused);
ac.setRaw(result->state);
return ac.toString();
}
#endif // DECODE_BOSCH144
#if DECODE_CARRIER_AC64
case decode_type_t::CARRIER_AC64: {
IRCarrierAc64 ac(kGpioUnused);
@ -3813,6 +3938,13 @@ namespace IRAcUtils {
return ac.toString();
}
#endif // DECODE_HAIER_AC
#if DECODE_HAIER_AC160
case decode_type_t::HAIER_AC160: {
IRHaierAC160 ac(kGpioUnused);
ac.setRaw(result->state);
return ac.toString();
}
#endif // DECODE_HAIER_AC160
#if DECODE_HAIER_AC176
case decode_type_t::HAIER_AC176: {
IRHaierAC176 ac(kGpioUnused);
@ -4132,6 +4264,14 @@ namespace IRAcUtils {
break;
}
#endif // DECODE_ARGO
#if DECODE_BOSCH144
case decode_type_t::BOSCH144: {
IRBosch144AC ac(kGpioUnused);
ac.setRaw(decode->state);
*result = ac.toCommon();
break;
}
#endif // DECODE_BOSCH144
#if DECODE_CARRIER_AC64
case decode_type_t::CARRIER_AC64: {
IRCarrierAc64 ac(kGpioUnused);
@ -4168,7 +4308,7 @@ namespace IRAcUtils {
case decode_type_t::DAIKIN128: {
IRDaikin128 ac(kGpioUnused);
ac.setRaw(decode->state);
*result = ac.toCommon();
*result = ac.toCommon(prev);
break;
}
#endif // DECODE_DAIKIN128
@ -4252,7 +4392,7 @@ namespace IRAcUtils {
case decode_type_t::FUJITSU_AC: {
IRFujitsuAC ac(kGpioUnused);
ac.setRaw(decode->state, decode->bits / 8);
*result = ac.toCommon();
*result = ac.toCommon(prev);
break;
}
#endif // DECODE_FUJITSU_AC
@ -4280,6 +4420,14 @@ namespace IRAcUtils {
break;
}
#endif // DECODE_HAIER_AC
#if DECODE_HAIER_AC160
case decode_type_t::HAIER_AC160: {
IRHaierAC160 ac(kGpioUnused);
ac.setRaw(decode->state);
*result = ac.toCommon(prev);
break;
}
#endif // DECODE_HAIER_AC160
#if DECODE_HAIER_AC176
case decode_type_t::HAIER_AC176: {
IRHaierAC176 ac(kGpioUnused);
@ -4348,7 +4496,7 @@ namespace IRAcUtils {
case decode_type_t::KELON: {
IRKelonAc ac(kGpioUnused);
ac.setRaw(decode->value);
*result = ac.toCommon();
*result = ac.toCommon(prev);
break;
}
#endif // DECODE_KELON

View File

@ -11,6 +11,7 @@
#include "ir_Airwell.h"
#include "ir_Amcor.h"
#include "ir_Argo.h"
#include "ir_Bosch.h"
#include "ir_Carrier.h"
#include "ir_Coolix.h"
#include "ir_Corona.h"
@ -134,6 +135,12 @@ class IRac {
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const bool turbo, const int16_t sleep = -1);
#endif // SEND_ARGO
#if SEND_BOSCH144
void bosch144(IRBosch144AC *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan,
const bool quiet);
#endif // SEND_COOLIX
#if SEND_CARRIER_AC64
void carrier64(IRCarrierAc64 *ac,
const bool on, const stdAc::opmode_t mode,
@ -268,6 +275,15 @@ void electra(IRElectraAc *ac,
const bool filter, const int16_t sleep = -1,
const int16_t clock = -1);
#endif // SEND_HAIER_AC
#if SEND_HAIER_AC160
void haier160(IRHaierAC160 *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 bool turbo, const bool quiet, const bool filter,
const bool clean, const bool light, const bool prevlight,
const int16_t sleep = -1);
#endif // SEND_HAIER_AC160
#if SEND_HAIER_AC176
void haier176(IRHaierAC176 *ac,
const haier_ac176_remote_model_t model, const bool on,

View File

@ -0,0 +1,32 @@
#ifndef IRMACROS_H_
#define IRMACROS_H_
/****************************************************************
* Copyright 2022 IRremoteESP8266 project and others
*/
/// @file IRmacros.h
/**
* COND() Set of macros to facilitate single-line conditional compilation
* argument checking.
* Found here: https://www.reddit.com/r/C_Programming/comments/ud3xrv/
* conditional_preprocessor_macro_anyone/
*
* Usage:
* COND(<define_to_test>[||/&&<more_define>...], <true_result>, <false_result>)
*/
/// @cond TEST
#define NOTHING
#define EXPAND(...) __VA_ARGS__
#define STUFF_P(a, ...) __VA_OPT__(a)
#define STUFF(...) STUFF_P(__VA_ARGS__)
#define VA_TEST_P(a, ...) __VA_OPT__(NO)##THING
#define VA_TEST(...) VA_TEST_P(__VA_ARGS__)
#define NEGATE(a) VA_TEST(a, a)
#define COND_P(cond, a, b) STUFF(a, cond)STUFF(b, NEGATE(cond))
#define COND(cond, a, b) EXPAND(COND_P(cond, a, b))
/// @endcond
/**
* end of COND() set of macros
*/
#endif // IRMACROS_H_

View File

@ -741,6 +741,11 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
DPRINTLN("Attempting Sharp decode");
if (decodeSharp(results, offset)) return true;
#endif
#if DECODE_BOSCH144
DPRINTLN("Attempting Bosch 144-bit decode");
// Bosch is similar to Coolix, so it must be attempted before decodeCOOLIX.
if (decodeBosch144(results, offset)) return true;
#endif // DECODE_BOSCH144
#if DECODE_COOLIX
DPRINTLN("Attempting Coolix 24-bit decode");
if (decodeCOOLIX(results, offset)) return true;
@ -1114,6 +1119,39 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
DPRINTLN("Attempting Coolix 48-bit decode");
if (decodeCoolix48(results, offset)) return true;
#endif // DECODE_COOLIX48
#if DECODE_DAIKIN200
DPRINTLN("Attempting Daikin 200-bit decode");
if (decodeDaikin200(results, offset)) return true;
#endif // DECODE_DAIKIN200
#if DECODE_HAIER_AC160
DPRINTLN("Attempting Haier AC 160 bit decode");
if (decodeHaierAC160(results, offset)) return true;
#endif // DECODE_HAIER_AC160
#if DECODE_CARRIER_AC128
DPRINTLN("Attempting Carrier AC 128-bit decode");
if (decodeCarrierAC128(results, offset)) return true;
#endif // DECODE_CARRIER_AC128
#if DECODE_TOTO
DPRINTLN("Attempting Toto 48/24-bit decode");
if (decodeToto(results, offset, kTotoLongBits) || // Long needs to be first
decodeToto(results, offset, kTotoShortBits)) return true;
#endif // DECODE_TOTO
#if DECODE_CLIMABUTLER
DPRINTLN("Attempting ClimaButler decode");
if (decodeClimaButler(results)) return true;
#endif // DECODE_CLIMABUTLER
#if DECODE_TCL96AC
DPRINTLN("Attempting TCL AC 96-bit decode");
if (decodeTcl96Ac(results, offset)) return true;
#endif // DECODE_TCL96AC
#if DECODE_SANYO_AC152
DPRINTLN("Attempting Sanyo AC 152-bit decode");
if (decodeSanyoAc152(results, offset)) return true;
#endif // DECODE_SANYO_AC152
#if DECODE_DAIKIN312
DPRINTLN("Attempting Daikin 312-bit decode");
if (decodeDaikin312(results, offset)) return true;
#endif // DECODE_DAIKIN312
// Typically new protocols are added above this line.
}
#if DECODE_HASH
@ -1128,7 +1166,7 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
if (!resumed) // Check if we have already resumed.
resume();
return false;
}
} // NOLINT(readability/fn_size)
/// Convert the tolerance percentage into something valid.
/// @param[in] percentage An integer percentage.

View File

@ -326,6 +326,12 @@ class IRrecv {
const uint16_t nbits = kSanyoAc88Bits,
const bool strict = true);
#endif // DECODE_SANYO_AC88
#if DECODE_SANYO_AC152
bool decodeSanyoAc152(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kSanyoAc152Bits,
const bool strict = true);
#endif // DECODE_SANYO_AC152
#if DECODE_MITSUBISHI
bool decodeMitsubishi(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kMitsubishiBits,
@ -508,11 +514,21 @@ class IRrecv {
const uint16_t nbits = kDaikin2Bits,
const bool strict = true);
#endif
#if DECODE_DAIKIN200
bool decodeDaikin200(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kDaikin200Bits,
const bool strict = true);
#endif // DECODE_DAIKIN200
#if DECODE_DAIKIN216
bool decodeDaikin216(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kDaikin216Bits,
const bool strict = true);
#endif
#endif // DECODE_DAIKIN216
#if DECODE_DAIKIN312
bool decodeDaikin312(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kDaikin312Bits,
const bool strict = true);
#endif // DECODE_DAIKIN312
#if DECODE_TOSHIBA_AC
bool decodeToshibaAC(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kToshibaACBits,
@ -570,6 +586,12 @@ class IRrecv {
const uint16_t nbits = kCarrierAc64Bits,
const bool strict = true);
#endif // DECODE_CARRIER_AC64
#if DECODE_CARRIER_AC128
bool decodeCarrierAC128(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kCarrierAc128Bits,
const bool strict = true);
#endif // DECODE_CARRIER_AC128
#if DECODE_GOODWEATHER
bool decodeGoodweather(decode_results *results,
uint16_t offset = kStartOffset,
@ -581,7 +603,8 @@ class IRrecv {
const uint16_t nbits = kGreeBits,
const bool strict = true);
#endif
#if (DECODE_HAIER_AC | DECODE_HAIER_AC_YRW02)
#if (DECODE_HAIER_AC | DECODE_HAIER_AC_YRW02 || DECODE_HAIER_AC160 || \
DECODE_HAIER_AC176)
bool decodeHaierAC(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kHaierACBits,
const bool strict = true);
@ -592,6 +615,12 @@ class IRrecv {
const uint16_t nbits = kHaierACYRW02Bits,
const bool strict = true);
#endif
#if DECODE_HAIER_AC160
bool decodeHaierAC160(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kHaierAC160Bits,
const bool strict = true);
#endif // DECODE_HAIER_AC160
#if DECODE_HAIER_AC176
bool decodeHaierAC176(decode_results *results,
uint16_t offset = kStartOffset,
@ -805,6 +834,29 @@ class IRrecv {
const uint16_t nbits = kAirtonBits,
const bool strict = true);
#endif // DECODE_AIRTON
#if DECODE_TOTO
bool decodeToto(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kTotoBits,
const bool strict = true);
#endif // DECODE_TOTO
#if DECODE_CLIMABUTLER
bool decodeClimaButler(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kClimaButlerBits,
const bool strict = true);
#endif // DECODE_CLIMABUTLER
#if DECODE_TCL96AC
bool decodeTcl96Ac(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kTcl96AcBits,
const bool strict = true);
#endif // DECODE_TCL96AC
#if DECODE_BOSCH144
bool decodeBosch144(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kBosch144Bits,
const bool strict = true);
#endif // DECODE_BOSCH144
};
#endif // IRRECV_H_

View File

@ -58,10 +58,10 @@
// Minor version number (x.X.x)
#define _IRREMOTEESP8266_VERSION_MINOR 8
// Patch version number (x.x.X)
#define _IRREMOTEESP8266_VERSION_PATCH 2
#define _IRREMOTEESP8266_VERSION_PATCH 3
// Macro to convert version info into an integer
#define _IRREMOTEESP8266_VERSION_VAL(major, minor, patch) \
((major << 16) | (minor << 8) | (patch))
(((major) << 16) | ((minor) << 8) | (patch))
// Macro to convert literal into a string
#define MKSTR_HELPER(x) #x
#define MKSTR(x) MKSTR_HELPER(x)
@ -238,6 +238,13 @@
#define SEND_SANYO_AC88 _IR_ENABLE_DEFAULT_
#endif // SEND_SANYO_AC88
#ifndef DECODE_SANYO_AC152
#define DECODE_SANYO_AC152 _IR_ENABLE_DEFAULT_
#endif // DECODE_SANYO_AC152
#ifndef SEND_SANYO_AC152
#define SEND_SANYO_AC152 _IR_ENABLE_DEFAULT_
#endif // SEND_SANYO_AC152
#ifndef DECODE_MITSUBISHI
#define DECODE_MITSUBISHI _IR_ENABLE_DEFAULT_
#endif // DECODE_MITSUBISHI
@ -455,6 +462,13 @@
#define SEND_CARRIER_AC64 _IR_ENABLE_DEFAULT_
#endif // SEND_CARRIER_AC64
#ifndef DECODE_CARRIER_AC128
#define DECODE_CARRIER_AC128 _IR_ENABLE_DEFAULT_
#endif // DECODE_CARRIER_AC128
#ifndef SEND_CARRIER_AC128
#define SEND_CARRIER_AC128 _IR_ENABLE_DEFAULT_
#endif // SEND_CARRIER_AC128
#ifndef DECODE_HAIER_AC
#define DECODE_HAIER_AC _IR_ENABLE_DEFAULT_
#endif // DECODE_HAIER_AC
@ -602,6 +616,13 @@
#define SEND_TECO _IR_ENABLE_DEFAULT_
#endif // SEND_TECO
#ifndef DECODE_TCL96AC
#define DECODE_TCL96AC _IR_ENABLE_DEFAULT_
#endif // DECODE_TCL96AC
#ifndef SEND_TCL96AC
#define SEND_TCL96AC _IR_ENABLE_DEFAULT_
#endif // SEND_TCL96AC
#ifndef DECODE_TCL112AC
#define DECODE_TCL112AC _IR_ENABLE_DEFAULT_
#endif // DECODE_TCL112AC
@ -861,6 +882,48 @@
#define SEND_KELON168 _IR_ENABLE_DEFAULT_
#endif // SEND_KELON168
#ifndef DECODE_DAIKIN200
#define DECODE_DAIKIN200 _IR_ENABLE_DEFAULT_
#endif // DECODE_DAIKIN200
#ifndef SEND_DAIKIN200
#define SEND_DAIKIN200 _IR_ENABLE_DEFAULT_
#endif // SEND_DAIKIN200
#ifndef DECODE_HAIER_AC160
#define DECODE_HAIER_AC160 _IR_ENABLE_DEFAULT_
#endif // DECODE_HAIER_AC160
#ifndef SEND_HAIER_AC160
#define SEND_HAIER_AC160 _IR_ENABLE_DEFAULT_
#endif // SEND_HAIER_AC160
#ifndef DECODE_TOTO
#define DECODE_TOTO _IR_ENABLE_DEFAULT_
#endif // DECODE_TOTO
#ifndef SEND_TOTO
#define SEND_TOTO _IR_ENABLE_DEFAULT_
#endif // SEND_TOTO
#ifndef DECODE_CLIMABUTLER
#define DECODE_CLIMABUTLER _IR_ENABLE_DEFAULT_
#endif // DECODE_CLIMABUTLER
#ifndef SEND_CLIMABUTLER
#define SEND_CLIMABUTLER _IR_ENABLE_DEFAULT_
#endif // SEND_CLIMABUTLER
#ifndef DECODE_BOSCH144
#define DECODE_BOSCH144 _IR_ENABLE_DEFAULT_
#endif // DECODE_BOSCH144
#ifndef SEND_BOSCH144
#define SEND_BOSCH144 _IR_ENABLE_DEFAULT_
#endif // SEND_BOSCH144
#ifndef DECODE_DAIKIN312
#define DECODE_DAIKIN312 _IR_ENABLE_DEFAULT_
#endif // DECODE_DAIKIN312
#ifndef SEND_DAIKIN312
#define SEND_DAIKIN312 _IR_ENABLE_DEFAULT_
#endif // SEND_DAIKIN312
#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \
DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \
DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \
@ -876,7 +939,9 @@
DECODE_VOLTAS || DECODE_MIRAGE || DECODE_HAIER_AC176 || \
DECODE_TEKNOPOINT || DECODE_KELON || DECODE_TROTEC_3550 || \
DECODE_SANYO_AC88 || DECODE_RHOSS || DECODE_HITACHI_AC264 || \
DECODE_KELON168 || DECODE_HITACHI_AC296 || \
DECODE_KELON168 || DECODE_HITACHI_AC296 || DECODE_CARRIER_AC128 || \
DECODE_DAIKIN200 || DECODE_HAIER_AC160 || DECODE_TCL96AC || \
DECODE_BOSCH144 || DECODE_SANYO_AC152 || DECODE_DAIKIN312 || \
false)
// Add any DECODE to the above if it uses result->state (see kStateSizeMax)
// you might also want to add the protocol to hasACState function
@ -1030,8 +1095,17 @@ enum decode_type_t {
HITACHI_AC264,
KELON168,
HITACHI_AC296,
DAIKIN200,
HAIER_AC160, // 115
CARRIER_AC128,
TOTO,
CLIMABUTLER,
TCL96AC,
BOSCH144, // 120
SANYO_AC152,
DAIKIN312,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = HITACHI_AC296,
kLastDecodeType = DAIKIN312,
};
// Message lengths & required repeat values
@ -1052,6 +1126,8 @@ const uint16_t kArgoStateLength = 12;
const uint16_t kArgoBits = kArgoStateLength * 8;
const uint16_t kArgoDefaultRepeat = kNoRepeat;
const uint16_t kArrisBits = 32;
const uint16_t kBosch144StateLength = 18;
const uint16_t kBosch144Bits = kBosch144StateLength * 8;
const uint16_t kCoolixBits = 24;
const uint16_t kCoolix48Bits = kCoolixBits * 2;
const uint16_t kCoolixDefaultRepeat = kSingleRepeat;
@ -1061,6 +1137,9 @@ const uint16_t kCarrierAc40Bits = 40;
const uint16_t kCarrierAc40MinRepeat = 2;
const uint16_t kCarrierAc64Bits = 64;
const uint16_t kCarrierAc64MinRepeat = kNoRepeat;
const uint16_t kCarrierAc128StateLength = 16;
const uint16_t kCarrierAc128Bits = kCarrierAc128StateLength * 8;
const uint16_t kCarrierAc128MinRepeat = kNoRepeat;
const uint16_t kCoronaAcStateLengthShort = 7;
const uint16_t kCoronaAcStateLength = kCoronaAcStateLengthShort * 3;
const uint16_t kCoronaAcBitsShort = kCoronaAcStateLengthShort * 8;
@ -1087,9 +1166,15 @@ const uint16_t kDaikin152DefaultRepeat = kNoRepeat;
const uint16_t kDaikin176StateLength = 22;
const uint16_t kDaikin176Bits = kDaikin176StateLength * 8;
const uint16_t kDaikin176DefaultRepeat = kNoRepeat;
const uint16_t kDaikin200StateLength = 25;
const uint16_t kDaikin200Bits = kDaikin200StateLength * 8;
const uint16_t kDaikin200DefaultRepeat = kNoRepeat;
const uint16_t kDaikin216StateLength = 27;
const uint16_t kDaikin216Bits = kDaikin216StateLength * 8;
const uint16_t kDaikin216DefaultRepeat = kNoRepeat;
const uint16_t kDaikin312StateLength = 39;
const uint16_t kDaikin312Bits = kDaikin312StateLength * 8;
const uint16_t kDaikin312DefaultRepeat = kNoRepeat;
const uint16_t kDelonghiAcBits = 64;
const uint16_t kDelonghiAcDefaultRepeat = kNoRepeat;
const uint16_t kTechnibelAcBits = 56;
@ -1127,6 +1212,9 @@ const uint16_t kHaierAcDefaultRepeat = kNoRepeat;
const uint16_t kHaierACYRW02StateLength = 14;
const uint16_t kHaierACYRW02Bits = kHaierACYRW02StateLength * 8;
const uint16_t kHaierAcYrw02DefaultRepeat = kNoRepeat;
const uint16_t kHaierAC160StateLength = 20;
const uint16_t kHaierAC160Bits = kHaierAC160StateLength * 8;
const uint16_t kHaierAc160DefaultRepeat = kNoRepeat;
const uint16_t kHaierAC176StateLength = 22;
const uint16_t kHaierAC176Bits = kHaierAC176StateLength * 8;
const uint16_t kHaierAc176DefaultRepeat = kNoRepeat;
@ -1230,6 +1318,9 @@ const uint16_t kSanyoAcBits = kSanyoAcStateLength * 8;
const uint16_t kSanyoAc88StateLength = 11;
const uint16_t kSanyoAc88Bits = kSanyoAc88StateLength * 8;
const uint16_t kSanyoAc88MinRepeat = 2;
const uint16_t kSanyoAc152StateLength = 19;
const uint16_t kSanyoAc152Bits = kSanyoAc152StateLength * 8;
const uint16_t kSanyoAc152MinRepeat = kNoRepeat;
const uint16_t kSanyoSA8650BBits = 12;
const uint16_t kSanyoLC7461AddressBits = 13;
const uint16_t kSanyoLC7461CommandBits = 8;
@ -1250,6 +1341,9 @@ const uint16_t kSonyMinBits = 12;
const uint16_t kSonyMinRepeat = 2;
const uint16_t kSymphonyBits = 12;
const uint16_t kSymphonyDefaultRepeat = 3;
const uint16_t kTcl96AcStateLength = 12;
const uint16_t kTcl96AcBits = kTcl96AcStateLength * 8;
const uint16_t kTcl96AcDefaultRepeat = kNoRepeat;
const uint16_t kTcl112AcStateLength = 14;
const uint16_t kTcl112AcBits = kTcl112AcStateLength * 8;
const uint16_t kTcl112AcDefaultRepeat = kNoRepeat;
@ -1264,6 +1358,10 @@ const uint16_t kToshibaACStateLengthShort = kToshibaACStateLength - 2;
const uint16_t kToshibaACBitsShort = kToshibaACStateLengthShort * 8;
const uint16_t kToshibaACStateLengthLong = kToshibaACStateLength + 1;
const uint16_t kToshibaACBitsLong = kToshibaACStateLengthLong * 8;
const uint16_t kTotoBits = 24;
const uint16_t kTotoShortBits = kTotoBits;
const uint16_t kTotoLongBits = kTotoShortBits * 2;
const uint16_t kTotoDefaultRepeat = kSingleRepeat;
const uint16_t kTranscoldBits = 24;
const uint16_t kTranscoldDefaultRepeat = kNoRepeat;
const uint16_t kTrotecStateLength = 9;
@ -1287,6 +1385,7 @@ const uint16_t kBoseBits = 16;
const uint16_t kRhossStateLength = 12;
const uint16_t kRhossBits = kRhossStateLength * 8;
const uint16_t kRhossDefaultRepeat = 0;
const uint16_t kClimaButlerBits = 52;
// Legacy defines. (Deprecated)

View File

@ -571,6 +571,7 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) {
case MULTIBRACKETS:
case SHERWOOD:
case TOSHIBA_AC:
case TOTO:
return kSingleRepeat;
// Special
case AIRWELL:
@ -633,6 +634,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
case MIDEA24:
case NIKAI:
case RCMM:
case TOTO:
case TRANSCOLD:
return 24;
case LG:
@ -668,6 +670,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
case MIDEA:
case PANASONIC:
return 48;
case CLIMABUTLER:
return kClimaButlerBits; // 52
case AIRTON:
case ECOCLIM:
case MAGIQUEST:
@ -682,8 +686,12 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return 64;
case ARGO:
return kArgoBits;
case BOSCH144:
return kBosch144Bits;
case CORONA_AC:
return kCoronaAcBits;
case CARRIER_AC128:
return kCarrierAc128Bits;
case DAIKIN:
return kDaikinBits;
case DAIKIN128:
@ -696,8 +704,12 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return kDaikin176Bits;
case DAIKIN2:
return kDaikin2Bits;
case DAIKIN200:
return kDaikin200Bits;
case DAIKIN216:
return kDaikin216Bits;
case DAIKIN312:
return kDaikin312Bits;
case DAIKIN64:
return kDaikin64Bits;
case ELECTRA_AC:
@ -708,6 +720,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return kHaierACBits;
case HAIER_AC_YRW02:
return kHaierACYRW02Bits;
case HAIER_AC160:
return kHaierAC160Bits;
case HAIER_AC176:
return kHaierAC176Bits;
case HITACHI_AC:
@ -756,8 +770,12 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return kSanyoAcBits;
case SANYO_AC88:
return kSanyoAc88Bits;
case SANYO_AC152:
return kSanyoAc152Bits;
case SHARP_AC:
return kSharpAcBits;
case TCL96AC:
return kTcl96AcBits;
case TCL112AC:
return kTcl112AcBits;
case TEKNOPOINT:
@ -833,6 +851,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
sendCarrierAC64(data, nbits, min_repeat);
break;
#endif // SEND_CARRIER_AC64
#if SEND_CLIMABUTLER
case CLIMABUTLER:
sendClimaButler(data, nbits, min_repeat);
break;
#endif // SEND_CLIMABUTLER
#if SEND_COOLIX
case COOLIX:
sendCOOLIX(data, nbits, min_repeat);
@ -1066,6 +1089,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
sendTeco(data, nbits, min_repeat);
break;
#endif // SEND_TECO
#if SEND_TOTO
case TOTO:
sendToto(data, nbits, min_repeat);
break;
#endif // SEND_TOTO
#if SEND_TRANSCOLD
case TRANSCOLD:
sendTranscold(data, nbits, min_repeat);
@ -1126,6 +1154,16 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state,
sendArgo(state, nbytes);
break;
#endif // SEND_ARGO
#if SEND_BOSCH144
case BOSCH144:
sendBosch144(state, nbytes);
break;
#endif // SEND_BOSCH144
#if SEND_CARRIER_AC128
case CARRIER_AC128:
sendCarrierAC128(state, nbytes);
break;
#endif // SEND_CARRIER_AC128
#if SEND_CORONA_AC
case CORONA_AC:
sendCoronaAc(state, nbytes);
@ -1161,11 +1199,21 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state,
sendDaikin2(state, nbytes);
break;
#endif // SEND_DAIKIN2
#if SEND_DAIKIN200
case DAIKIN200:
sendDaikin200(state, nbytes);
break;
#endif // SEND_DAIKIN200
#if SEND_DAIKIN216
case DAIKIN216:
sendDaikin216(state, nbytes);
break;
#endif // SEND_DAIKIN216
#if SEND_DAIKIN312
case DAIKIN312:
sendDaikin312(state, nbytes);
break;
#endif // SEND_DAIKIN312
#if SEND_ELECTRA_AC
case ELECTRA_AC:
sendElectraAC(state, nbytes);
@ -1191,6 +1239,11 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state,
sendHaierACYRW02(state, nbytes);
break;
#endif // SEND_HAIER_AC_YRW02
#if SEND_HAIER_AC160
case HAIER_AC160:
sendHaierAC160(state, nbytes);
break;
#endif // SEND_HAIER_AC160
#if SEND_HAIER_AC176
case HAIER_AC176:
sendHaierAC176(state, nbytes);
@ -1309,11 +1362,21 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state,
sendSanyoAc88(state, nbytes);
break;
#endif // SEND_SANYO_AC88
#if SEND_SANYO_AC152
case SANYO_AC152:
sendSanyoAc152(state, nbytes);
break;
#endif // SEND_SANYO_AC152
#if SEND_SHARP_AC
case SHARP_AC:
sendSharpAc(state, nbytes);
break;
#endif // SEND_SHARP_AC
#if SEND_TCL96AC
case TCL96AC:
sendTcl96Ac(state, nbytes);
break;
#endif // SEND_TCL96AC
#if SEND_TCL112AC
case TCL112AC:
sendTcl112Ac(state, nbytes);

View File

@ -118,7 +118,8 @@ struct state_t {
/// Fujitsu A/C model numbers
enum fujitsu_ac_remote_model_t {
ARRAH2E = 1, ///< (1) AR-RAH2E, AR-RAC1E, AR-RAE1E, AR-RCE1E (Default)
ARRAH2E = 1, ///< (1) AR-RAH2E, AR-RAC1E, AR-RAE1E, AR-RCE1E, AR-RAH2U,
///< AR-REG1U (Default)
///< Warning: Use on incorrect models can cause the A/C to lock
///< up, requring the A/C to be physically powered off to fix.
///< e.g. AR-RAH1U may lock up with a Swing command.
@ -133,7 +134,9 @@ enum fujitsu_ac_remote_model_t {
/// Gree A/C model numbers
enum gree_ac_remote_model_t {
YAW1F = 1, // (1) Ultimate, EKOKAI, RusClimate (Default)
YBOFB, // (2) Green, YBOFB2, YAPOF3
YBOFB, // (2) Green, YBOFB2, YAPOF3
YX1FSF, // (3) Soleus Air window unit (Similar to YAW1F, but with an
// Operation mode of Energy Saver (Econo))
};
/// HAIER_AC176 A/C model numbers
@ -343,6 +346,11 @@ class IRsend {
const uint16_t nbytes = kSanyoAc88StateLength,
const uint16_t repeat = kSanyoAc88MinRepeat);
#endif // SEND_SANYO_AC88
#if SEND_SANYO_AC152
void sendSanyoAc152(const uint8_t *data,
const uint16_t nbytes = kSanyoAc152StateLength,
const uint16_t repeat = kSanyoAc152MinRepeat);
#endif // SEND_SANYO_AC152
#if SEND_DISH
// sendDISH() should typically be called with repeat=3 as DISH devices
// expect the code to be sent at least 4 times. (code + 3 repeats = 4 codes)
@ -481,11 +489,21 @@ class IRsend {
const uint16_t nbytes = kDaikin2StateLength,
const uint16_t repeat = kDaikin2DefaultRepeat);
#endif
#if SEND_DAIKIN200
void sendDaikin200(const unsigned char data[],
const uint16_t nbytes = kDaikin200StateLength,
const uint16_t repeat = kDaikin200DefaultRepeat);
#endif // SEND_DAIKIN200
#if SEND_DAIKIN216
void sendDaikin216(const unsigned char data[],
const uint16_t nbytes = kDaikin216StateLength,
const uint16_t repeat = kDaikin216DefaultRepeat);
#endif
#endif // SEND_DAIKIN216
#if SEND_DAIKIN312
void sendDaikin312(const unsigned char data[],
const uint16_t nbytes = kDaikin312StateLength,
const uint16_t repeat = kDaikin312DefaultRepeat);
#endif // SEND_DAIKIN312
#if SEND_AIWA_RC_T501
void sendAiwaRCT501(uint64_t data, uint16_t nbits = kAiwaRcT501Bits,
uint16_t repeat = kAiwaRcT501MinRepeats);
@ -557,6 +575,11 @@ class IRsend {
void sendCarrierAC64(uint64_t data, uint16_t nbits = kCarrierAc64Bits,
uint16_t repeat = kCarrierAc64MinRepeat);
#endif
#if SEND_CARRIER_AC128
void sendCarrierAC128(const uint8_t data[],
uint16_t nbytes = kCarrierAc128StateLength,
uint16_t repeat = kCarrierAc128MinRepeat);
#endif // SEND_CARRIER_AC128
#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02 || SEND_HAIER_AC176)
void sendHaierAC(const unsigned char data[],
const uint16_t nbytes = kHaierACStateLength,
@ -567,6 +590,11 @@ class IRsend {
const uint16_t nbytes = kHaierACYRW02StateLength,
const uint16_t repeat = kHaierAcYrw02DefaultRepeat);
#endif // SEND_HAIER_AC_YRW02
#if SEND_HAIER_AC160
void sendHaierAC160(const unsigned char data[],
const uint16_t nbytes = kHaierAC160StateLength,
const uint16_t repeat = kHaierAc160DefaultRepeat);
#endif // SEND_HAIER_AC160
#if SEND_HAIER_AC176
void sendHaierAC176(const unsigned char data[],
const uint16_t nbytes = kHaierAC176StateLength,
@ -654,11 +682,16 @@ class IRsend {
void sendVestelAc(const uint64_t data, const uint16_t nbits = kVestelAcBits,
const uint16_t repeat = kNoRepeat);
#endif
#if SEND_TCL96AC
void sendTcl96Ac(const unsigned char data[],
const uint16_t nbytes = kTcl96AcStateLength,
const uint16_t repeat = kTcl96AcDefaultRepeat);
#endif // SEND_TCL96AC
#if SEND_TCL112AC
void sendTcl112Ac(const unsigned char data[],
const uint16_t nbytes = kTcl112AcStateLength,
const uint16_t repeat = kTcl112AcDefaultRepeat);
#endif
#endif // SEND_TCL112AC
#if SEND_TECO
void sendTeco(const uint64_t data, const uint16_t nbits = kTecoBits,
const uint16_t repeat = kNoRepeat);
@ -790,6 +823,20 @@ class IRsend {
void sendAirton(const uint64_t data, const uint16_t nbits = kAirtonBits,
const uint16_t repeat = kAirtonDefaultRepeat);
#endif // SEND_AIRTON
#if SEND_TOTO
void sendToto(const uint64_t data, const uint16_t nbits = kTotoBits,
const uint16_t repeat = kTotoDefaultRepeat);
#endif // SEND_TOTO
#if SEND_CLIMABUTLER
void sendClimaButler(const uint64_t data,
const uint16_t nbits = kClimaButlerBits,
const uint16_t repeat = kNoRepeat);
#endif // SEND_CLIMABUTLER
#if SEND_BOSCH144
void sendBosch144(const unsigned char data[],
const uint16_t nbytes = kBosch144StateLength,
const uint16_t repeat = kNoRepeat);
#endif // SEND_BOSCH144
protected:
#ifdef UNIT_TEST

View File

@ -11,6 +11,8 @@
#include "IRremoteESP8266.h"
#include "i18n.h"
#include "IRmacros.h"
#ifndef PROGMEM
#define PROGMEM // Pretend we have the PROGMEM macro even if we really don't.
#endif
@ -236,6 +238,7 @@ IRTEXT_CONST_STRING(kBitsStr, D_STR_BITS); ///< "Bits"
// Model Names
IRTEXT_CONST_STRING(kYaw1fStr, D_STR_YAW1F); ///< "YAW1F"
IRTEXT_CONST_STRING(kYbofbStr, D_STR_YBOFB); ///< "YBOFB"
IRTEXT_CONST_STRING(kYx1fsfStr, D_STR_YX1FSF); ///< "YX1FSF"
IRTEXT_CONST_STRING(kV9014557AStr, D_STR_V9014557_A); ///< "V9014557-A"
IRTEXT_CONST_STRING(kV9014557BStr, D_STR_V9014557_B); ///< "V9014557-B"
IRTEXT_CONST_STRING(kRlt0541htaaStr, D_STR_RLT0541HTA_A); ///< "R-LT0541-HTA-A"
@ -279,125 +282,258 @@ IRTEXT_CONST_STRING(kDg11j13aStr, D_STR_DG11J13A); ///< "DG11J13A"
IRTEXT_CONST_STRING(kDg11j104Str, D_STR_DG11J104); ///< "DG11J104"
IRTEXT_CONST_STRING(kDg11j191Str, D_STR_DG11J191); ///< "DG11J191"
#define D_STR_UNSUPPORTED "?" // Unsupported protocols will be showing as
// a question mark, check for length > 1
// to show only currently included protocols
// Protocol Names
// Needs to be in decode_type_t order.
IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
D_STR_UNUSED "\x0"
D_STR_RC5 "\x0"
D_STR_RC6 "\x0"
D_STR_NEC "\x0"
D_STR_SONY "\x0"
D_STR_PANASONIC "\x0"
D_STR_JVC "\x0"
D_STR_SAMSUNG "\x0"
D_STR_WHYNTER "\x0"
D_STR_AIWA_RC_T501 "\x0"
D_STR_LG "\x0"
D_STR_SANYO "\x0"
D_STR_MITSUBISHI "\x0"
D_STR_DISH "\x0"
D_STR_SHARP "\x0"
D_STR_COOLIX "\x0"
D_STR_DAIKIN "\x0"
D_STR_DENON "\x0"
D_STR_KELVINATOR "\x0"
D_STR_SHERWOOD "\x0"
D_STR_MITSUBISHI_AC "\x0"
D_STR_RCMM "\x0"
D_STR_SANYO_LC7461 "\x0"
D_STR_RC5X "\x0"
D_STR_GREE "\x0"
D_STR_PRONTO "\x0"
D_STR_NEC_LIKE "\x0"
D_STR_ARGO "\x0"
D_STR_TROTEC "\x0"
D_STR_NIKAI "\x0"
D_STR_RAW "\x0"
D_STR_GLOBALCACHE "\x0"
D_STR_TOSHIBA_AC "\x0"
D_STR_FUJITSU_AC "\x0"
D_STR_MIDEA "\x0"
D_STR_MAGIQUEST "\x0"
D_STR_LASERTAG "\x0"
D_STR_CARRIER_AC "\x0"
D_STR_HAIER_AC "\x0"
D_STR_MITSUBISHI2 "\x0"
D_STR_HITACHI_AC "\x0"
D_STR_HITACHI_AC1 "\x0"
D_STR_HITACHI_AC2 "\x0"
D_STR_GICABLE "\x0"
D_STR_HAIER_AC_YRW02 "\x0"
D_STR_WHIRLPOOL_AC "\x0"
D_STR_SAMSUNG_AC "\x0"
D_STR_LUTRON "\x0"
D_STR_ELECTRA_AC "\x0"
D_STR_PANASONIC_AC "\x0"
D_STR_PIONEER "\x0"
D_STR_LG2 "\x0"
D_STR_MWM "\x0"
D_STR_DAIKIN2 "\x0"
D_STR_VESTEL_AC "\x0"
D_STR_TECO "\x0"
D_STR_SAMSUNG36 "\x0"
D_STR_TCL112AC "\x0"
D_STR_LEGOPF "\x0"
D_STR_MITSUBISHI_HEAVY_88 "\x0"
D_STR_MITSUBISHI_HEAVY_152 "\x0"
D_STR_DAIKIN216 "\x0"
D_STR_SHARP_AC "\x0"
D_STR_GOODWEATHER "\x0"
D_STR_INAX "\x0"
D_STR_DAIKIN160 "\x0"
D_STR_NEOCLIMA "\x0"
D_STR_DAIKIN176 "\x0"
D_STR_DAIKIN128 "\x0"
D_STR_AMCOR "\x0"
D_STR_DAIKIN152 "\x0"
D_STR_MITSUBISHI136 "\x0"
D_STR_MITSUBISHI112 "\x0"
D_STR_HITACHI_AC424 "\x0"
D_STR_SONY_38K "\x0"
D_STR_EPSON "\x0"
D_STR_SYMPHONY "\x0"
D_STR_HITACHI_AC3 "\x0"
D_STR_DAIKIN64 "\x0"
D_STR_AIRWELL "\x0"
D_STR_DELONGHI_AC "\x0"
D_STR_DOSHISHA "\x0"
D_STR_MULTIBRACKETS "\x0"
D_STR_CARRIER_AC40 "\x0"
D_STR_CARRIER_AC64 "\x0"
D_STR_HITACHI_AC344 "\x0"
D_STR_CORONA_AC "\x0"
D_STR_MIDEA24 "\x0"
D_STR_ZEPEAL "\x0"
D_STR_SANYO_AC "\x0"
D_STR_VOLTAS "\x0"
D_STR_METZ "\x0"
D_STR_TRANSCOLD "\x0"
D_STR_TECHNIBEL_AC "\x0"
D_STR_MIRAGE "\x0"
D_STR_ELITESCREENS "\x0"
D_STR_PANASONIC_AC32 "\x0"
D_STR_MILESTAG2 "\x0"
D_STR_ECOCLIM "\x0"
D_STR_XMP "\x0"
D_STR_TRUMA "\x0"
D_STR_HAIER_AC176 "\x0"
D_STR_TEKNOPOINT "\x0"
D_STR_KELON "\x0"
D_STR_TROTEC_3550 "\x0"
D_STR_SANYO_AC88 "\x0"
D_STR_BOSE "\x0"
D_STR_ARRIS "\x0"
D_STR_RHOSS "\x0"
D_STR_AIRTON "\x0"
D_STR_COOLIX48 "\x0"
D_STR_HITACHI_AC264 "\x0"
D_STR_KELON168 "\x0"
D_STR_HITACHI_AC296 "\x0"
///< New protocol strings should be added just above this line.
COND(DECODE_RC5 || SEND_RC5,
D_STR_RC5, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_RC6 || SEND_RC6,
D_STR_RC6, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_NEC || SEND_NEC,
D_STR_NEC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SONY || SEND_SONY,
D_STR_SONY, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_PANASONIC || SEND_PANASONIC,
D_STR_PANASONIC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_JVC || SEND_JVC,
D_STR_JVC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SAMSUNG || SEND_SAMSUNG,
D_STR_SAMSUNG, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_WHYNTER || SEND_WHYNTER,
D_STR_WHYNTER, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_AIWA_RC_T501 || SEND_AIWA_RC_T501,
D_STR_AIWA_RC_T501, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_LG || SEND_LG,
D_STR_LG, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SANYO || SEND_SANYO,
D_STR_SANYO, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MITSUBISHI || SEND_MITSUBISHI,
D_STR_MITSUBISHI, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DISH || SEND_DISH,
D_STR_DISH, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SHARP || SEND_SHARP,
D_STR_SHARP, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_COOLIX || SEND_COOLIX,
D_STR_COOLIX, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN || SEND_DAIKIN,
D_STR_DAIKIN, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DENON || SEND_DENON,
D_STR_DENON, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_KELVINATOR || SEND_KELVINATOR,
D_STR_KELVINATOR, D_STR_UNSUPPORTED) "\x0"
COND(SEND_SHERWOOD,
D_STR_SHERWOOD, D_STR_UNSUPPORTED) "\x0" // SEND-ONLY
COND(DECODE_MITSUBISHI_AC || SEND_MITSUBISHI_AC,
D_STR_MITSUBISHI_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_RCMM || SEND_RCMM,
D_STR_RCMM, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SANYO || SEND_SANYO,
D_STR_SANYO_LC7461, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_RC5 || SEND_RC5,
D_STR_RC5X, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_GREE || SEND_GREE,
D_STR_GREE, D_STR_UNSUPPORTED) "\x0"
COND(SEND_PRONTO,
D_STR_PRONTO, D_STR_UNSUPPORTED) "\x0" // SEND-ONLY
COND(DECODE_NEC || SEND_NEC,
D_STR_NEC_LIKE, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_ARGO || SEND_ARGO,
D_STR_ARGO, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_TROTEC || SEND_TROTEC,
D_STR_TROTEC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_NIKAI || SEND_NIKAI,
D_STR_NIKAI, D_STR_UNSUPPORTED) "\x0"
COND(SEND_RAW,
D_STR_RAW, D_STR_UNSUPPORTED) "\x0" // SEND-ONLY
COND(SEND_GLOBALCACHE,
D_STR_GLOBALCACHE, D_STR_UNSUPPORTED) "\x0" // SEND
COND(DECODE_TOSHIBA_AC || SEND_TOSHIBA_AC,
D_STR_TOSHIBA_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_FUJITSU_AC || SEND_FUJITSU_AC,
D_STR_FUJITSU_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MIDEA || SEND_MIDEA,
D_STR_MIDEA, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MAGIQUEST || SEND_MAGIQUEST,
D_STR_MAGIQUEST, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_LASERTAG || SEND_LASERTAG,
D_STR_LASERTAG, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_CARRIER_AC || SEND_CARRIER_AC,
D_STR_CARRIER_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HAIER_AC || SEND_HAIER_AC,
D_STR_HAIER_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MITSUBISHI2 || SEND_MITSUBISHI2,
D_STR_MITSUBISHI2, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HITACHI_AC || SEND_HITACHI_AC,
D_STR_HITACHI_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HITACHI_AC1 || SEND_HITACHI_AC1,
D_STR_HITACHI_AC1, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HITACHI_AC2 || SEND_HITACHI_AC2,
D_STR_HITACHI_AC2, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_GICABLE || SEND_GICABLE,
D_STR_GICABLE, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HAIER_AC_YRW02 || SEND_HAIER_AC_YRW02,
D_STR_HAIER_AC_YRW02, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_WHIRLPOOL_AC || SEND_WHIRLPOOL_AC,
D_STR_WHIRLPOOL_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SAMSUNG_AC || SEND_SAMSUNG_AC,
D_STR_SAMSUNG_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_LUTRON || SEND_LUTRON,
D_STR_LUTRON, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_ELECTRA_AC || SEND_ELECTRA_AC,
D_STR_ELECTRA_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_PANASONIC_AC || SEND_PANASONIC_AC,
D_STR_PANASONIC_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_PIONEER || SEND_PIONEER,
D_STR_PIONEER, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_LG || SEND_LG,
D_STR_LG2, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MWM || SEND_MWM,
D_STR_MWM, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN2 || SEND_DAIKIN2,
D_STR_DAIKIN2, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_VESTEL_AC || SEND_VESTEL_AC,
D_STR_VESTEL_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_TECO || SEND_TECO,
D_STR_TECO, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SAMSUNG36 || SEND_SAMSUNG36,
D_STR_SAMSUNG36, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_TCL112AC || SEND_TCL112AC,
D_STR_TCL112AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_LEGOPF || SEND_LEGOPF,
D_STR_LEGOPF, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MITSUBISHIHEAVY || SEND_MITSUBISHIHEAVY,
D_STR_MITSUBISHI_HEAVY_88, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MITSUBISHIHEAVY || SEND_MITSUBISHIHEAVY,
D_STR_MITSUBISHI_HEAVY_152, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN216 || SEND_DAIKIN216,
D_STR_DAIKIN216, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SHARP_AC || SEND_SHARP_AC,
D_STR_SHARP_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_GOODWEATHER || SEND_GOODWEATHER,
D_STR_GOODWEATHER, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_INAX || SEND_INAX,
D_STR_INAX, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN160 || SEND_DAIKIN160,
D_STR_DAIKIN160, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_NEOCLIMA || SEND_NEOCLIMA,
D_STR_NEOCLIMA, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN176 || SEND_DAIKIN176,
D_STR_DAIKIN176, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN128 || SEND_DAIKIN128,
D_STR_DAIKIN128, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_AMCOR || SEND_AMCOR,
D_STR_AMCOR, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN152 || SEND_DAIKIN152,
D_STR_DAIKIN152, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MITSUBISHI136 || SEND_MITSUBISHI136,
D_STR_MITSUBISHI136, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MITSUBISHI112 || SEND_MITSUBISHI112,
D_STR_MITSUBISHI112, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HITACHI_AC424 || SEND_HITACHI_AC424,
D_STR_HITACHI_AC424, D_STR_UNSUPPORTED) "\x0"
COND(SEND_SONY,
D_STR_SONY_38K, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_EPSON || SEND_EPSON,
D_STR_EPSON, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SYMPHONY || SEND_SYMPHONY,
D_STR_SYMPHONY, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HITACHI_AC3 || SEND_HITACHI_AC3,
D_STR_HITACHI_AC3, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN64 || SEND_DAIKIN64,
D_STR_DAIKIN64, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_AIRWELL || SEND_AIRWELL,
D_STR_AIRWELL, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DELONGHI_AC || SEND_DELONGHI_AC,
D_STR_DELONGHI_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DOSHISHA || SEND_DOSHISHA,
D_STR_DOSHISHA, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MULTIBRACKETS || SEND_MULTIBRACKETS,
D_STR_MULTIBRACKETS, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_CARRIER_AC40 || SEND_CARRIER_AC40,
D_STR_CARRIER_AC40, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_CARRIER_AC64 || SEND_CARRIER_AC64,
D_STR_CARRIER_AC64, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HITACHI_AC344 || SEND_HITACHI_AC344,
D_STR_HITACHI_AC344, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_CORONA_AC || SEND_CORONA_AC,
D_STR_CORONA_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MIDEA24 || SEND_MIDEA24,
D_STR_MIDEA24, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_ZEPEAL || SEND_ZEPEAL,
D_STR_ZEPEAL, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SANYO_AC || SEND_SANYO_AC,
D_STR_SANYO_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_VOLTAS || SEND_VOLTAS,
D_STR_VOLTAS, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_METZ || SEND_METZ,
D_STR_METZ, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_TRANSCOLD || SEND_TRANSCOLD,
D_STR_TRANSCOLD, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_TECHNIBEL_AC || SEND_TECHNIBEL_AC,
D_STR_TECHNIBEL_AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MIRAGE || SEND_MIRAGE,
D_STR_MIRAGE, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_ELITESCREENS || SEND_ELITESCREENS,
D_STR_ELITESCREENS, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_PANASONIC_AC32 || SEND_PANASONIC_AC32,
D_STR_PANASONIC_AC32, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_MILESTAG2 || SEND_MILESTAG2,
D_STR_MILESTAG2, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_ECOCLIM || SEND_ECOCLIM,
D_STR_ECOCLIM, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_XMP || SEND_XMP,
D_STR_XMP, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_TRUMA || SEND_TRUMA,
D_STR_TRUMA, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HAIER_AC176 || SEND_HAIER_AC176,
D_STR_HAIER_AC176, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_TEKNOPOINT || SEND_TEKNOPOINT,
D_STR_TEKNOPOINT, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_KELON || SEND_KELON,
D_STR_KELON, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_TROTEC_3550 || SEND_TROTEC_3550,
D_STR_TROTEC_3550, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SANYO_AC88 || SEND_SANYO_AC88,
D_STR_SANYO_AC88, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_BOSE || SEND_BOSE,
D_STR_BOSE, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_ARRIS || SEND_ARRIS,
D_STR_ARRIS, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_RHOSS || SEND_RHOSS,
D_STR_RHOSS, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_AIRTON || SEND_AIRTON,
D_STR_AIRTON, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_COOLIX48 || SEND_COOLIX48,
D_STR_COOLIX48, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HITACHI_AC264 || SEND_HITACHI_AC264,
D_STR_HITACHI_AC264, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_KELON168 || SEND_KELON168,
D_STR_KELON168, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HITACHI_AC296 || SEND_HITACHI_AC296,
D_STR_HITACHI_AC296, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN200 || SEND_DAIKIN200,
D_STR_DAIKIN200, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_HAIER_AC160 || SEND_HAIER_AC160,
D_STR_HAIER_AC160, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_CARRIER_AC128 || SEND_CARRIER_AC128,
D_STR_CARRIER_AC128, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_TOTO || SEND_TOTO,
D_STR_TOTO, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_CLIMABUTLER || SEND_CLIMABUTLER,
D_STR_CLIMABUTLER, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_TCL96AC || SEND_TCL96AC,
D_STR_TCL96AC, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_BOSCH144 || SEND_BOSCH144,
D_STR_BOSCH144, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_SANYO_AC152 || SEND_SANYO_AC152,
D_STR_SANYO_AC152, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN312 || SEND_DAIKIN312,
D_STR_DAIKIN312, D_STR_UNSUPPORTED) "\x0"
///< New protocol (macro) strings should be added just above this line.
"\x0" ///< This string requires double null termination.
};
IRTEXT_CONST_BLOB_PTR(kAllProtocolNamesStr);

View File

@ -44,8 +44,8 @@ extern IRTEXT_CONST_PTR(kArrah2eStr);
extern IRTEXT_CONST_PTR(kArreb1eStr);
extern IRTEXT_CONST_PTR(kArrew4eStr);
extern IRTEXT_CONST_PTR(kArry4Str);
extern IRTEXT_CONST_PTR(kAutomaticStr);
extern IRTEXT_CONST_PTR(kAutoStr);
extern IRTEXT_CONST_PTR(kAutomaticStr);
extern IRTEXT_CONST_PTR(kBeepStr);
extern IRTEXT_CONST_PTR(kBitsStr);
extern IRTEXT_CONST_PTR(kBottomStr);
@ -64,13 +64,13 @@ extern IRTEXT_CONST_PTR(kClockStr);
extern IRTEXT_CONST_PTR(kCodeStr);
extern IRTEXT_CONST_PTR(kColonSpaceStr);
extern IRTEXT_CONST_PTR(kComfortStr);
extern IRTEXT_CONST_PTR(kCommandStr);
extern IRTEXT_CONST_PTR(kCommaSpaceStr);
extern IRTEXT_CONST_PTR(kCoolingStr);
extern IRTEXT_CONST_PTR(kCommandStr);
extern IRTEXT_CONST_PTR(kCoolStr);
extern IRTEXT_CONST_PTR(kCoolingStr);
extern IRTEXT_CONST_PTR(kDashStr);
extern IRTEXT_CONST_PTR(kDaysStr);
extern IRTEXT_CONST_PTR(kDayStr);
extern IRTEXT_CONST_PTR(kDaysStr);
extern IRTEXT_CONST_PTR(kDehumidifyStr);
extern IRTEXT_CONST_PTR(kDg11j104Str);
extern IRTEXT_CONST_PTR(kDg11j13aStr);
@ -80,18 +80,18 @@ extern IRTEXT_CONST_PTR(kDirectStr);
extern IRTEXT_CONST_PTR(kDisplayTempStr);
extern IRTEXT_CONST_PTR(kDkeStr);
extern IRTEXT_CONST_PTR(kDownStr);
extern IRTEXT_CONST_PTR(kDryingStr);
extern IRTEXT_CONST_PTR(kDryStr);
extern IRTEXT_CONST_PTR(kDryingStr);
extern IRTEXT_CONST_PTR(kEconoStr);
extern IRTEXT_CONST_PTR(kEconoToggleStr);
extern IRTEXT_CONST_PTR(kEyeAutoStr);
extern IRTEXT_CONST_PTR(kEyeStr);
extern IRTEXT_CONST_PTR(kFalseStr);
extern IRTEXT_CONST_PTR(kFanOnlyNoSpaceStr);
extern IRTEXT_CONST_PTR(kFan_OnlyStr);
extern IRTEXT_CONST_PTR(kFanOnlyStr);
extern IRTEXT_CONST_PTR(kFanOnlyWithSpaceStr);
extern IRTEXT_CONST_PTR(kFanStr);
extern IRTEXT_CONST_PTR(kFan_OnlyStr);
extern IRTEXT_CONST_PTR(kFastStr);
extern IRTEXT_CONST_PTR(kFilterStr);
extern IRTEXT_CONST_PTR(kFixedStr);
@ -100,21 +100,21 @@ extern IRTEXT_CONST_PTR(kFreshStr);
extern IRTEXT_CONST_PTR(kGe6711ar2853mStr);
extern IRTEXT_CONST_PTR(kGz055be1Str);
extern IRTEXT_CONST_PTR(kHealthStr);
extern IRTEXT_CONST_PTR(kHeatingStr);
extern IRTEXT_CONST_PTR(kHeatStr);
extern IRTEXT_CONST_PTR(kHighestStr);
extern IRTEXT_CONST_PTR(kHighStr);
extern IRTEXT_CONST_PTR(kHeatingStr);
extern IRTEXT_CONST_PTR(kHiStr);
extern IRTEXT_CONST_PTR(kHighStr);
extern IRTEXT_CONST_PTR(kHighestStr);
extern IRTEXT_CONST_PTR(kHoldStr);
extern IRTEXT_CONST_PTR(kHoursStr);
extern IRTEXT_CONST_PTR(kHourStr);
extern IRTEXT_CONST_PTR(kHoursStr);
extern IRTEXT_CONST_PTR(kHumidStr);
extern IRTEXT_CONST_PTR(kIdStr);
extern IRTEXT_CONST_PTR(kIFeelStr);
extern IRTEXT_CONST_PTR(kISeeStr);
extern IRTEXT_CONST_PTR(kIdStr);
extern IRTEXT_CONST_PTR(kIndirectStr);
extern IRTEXT_CONST_PTR(kInsideStr);
extern IRTEXT_CONST_PTR(kIonStr);
extern IRTEXT_CONST_PTR(kISeeStr);
extern IRTEXT_CONST_PTR(kJkeStr);
extern IRTEXT_CONST_PTR(kKkg29ac1Str);
extern IRTEXT_CONST_PTR(kKkg9ac1Str);
@ -126,29 +126,29 @@ extern IRTEXT_CONST_PTR(kLg6711a20083vStr);
extern IRTEXT_CONST_PTR(kLightStr);
extern IRTEXT_CONST_PTR(kLightToggleStr);
extern IRTEXT_CONST_PTR(kLkeStr);
extern IRTEXT_CONST_PTR(kLockStr);
extern IRTEXT_CONST_PTR(kLoStr);
extern IRTEXT_CONST_PTR(kLockStr);
extern IRTEXT_CONST_PTR(kLoudStr);
extern IRTEXT_CONST_PTR(kLowStr);
extern IRTEXT_CONST_PTR(kLowerStr);
extern IRTEXT_CONST_PTR(kLowestStr);
extern IRTEXT_CONST_PTR(kLowStr);
extern IRTEXT_CONST_PTR(kManualStr);
extern IRTEXT_CONST_PTR(kMaximumStr);
extern IRTEXT_CONST_PTR(kMaxLeftNoSpaceStr);
extern IRTEXT_CONST_PTR(kMaxLeftStr);
extern IRTEXT_CONST_PTR(kMaxRightNoSpaceStr);
extern IRTEXT_CONST_PTR(kMaxRightStr);
extern IRTEXT_CONST_PTR(kMaxStr);
extern IRTEXT_CONST_PTR(kMediumStr);
extern IRTEXT_CONST_PTR(kMaximumStr);
extern IRTEXT_CONST_PTR(kMedStr);
extern IRTEXT_CONST_PTR(kMiddleStr);
extern IRTEXT_CONST_PTR(kMediumStr);
extern IRTEXT_CONST_PTR(kMidStr);
extern IRTEXT_CONST_PTR(kMinimumStr);
extern IRTEXT_CONST_PTR(kMiddleStr);
extern IRTEXT_CONST_PTR(kMinStr);
extern IRTEXT_CONST_PTR(kMinutesStr);
extern IRTEXT_CONST_PTR(kMinimumStr);
extern IRTEXT_CONST_PTR(kMinuteStr);
extern IRTEXT_CONST_PTR(kModelStr);
extern IRTEXT_CONST_PTR(kMinutesStr);
extern IRTEXT_CONST_PTR(kModeStr);
extern IRTEXT_CONST_PTR(kModelStr);
extern IRTEXT_CONST_PTR(kMouldStr);
extern IRTEXT_CONST_PTR(kMoveStr);
extern IRTEXT_CONST_PTR(kNAStr);
@ -171,9 +171,9 @@ extern IRTEXT_CONST_PTR(kPanasonicPkrStr);
extern IRTEXT_CONST_PTR(kPanasonicRkrStr);
extern IRTEXT_CONST_PTR(kPkrStr);
extern IRTEXT_CONST_PTR(kPowerButtonStr);
extern IRTEXT_CONST_PTR(kPowerfulStr);
extern IRTEXT_CONST_PTR(kPowerStr);
extern IRTEXT_CONST_PTR(kPowerToggleStr);
extern IRTEXT_CONST_PTR(kPowerfulStr);
extern IRTEXT_CONST_PTR(kPreviousPowerStr);
extern IRTEXT_CONST_PTR(kProtocolStr);
extern IRTEXT_CONST_PTR(kPurifyStr);
@ -188,8 +188,8 @@ extern IRTEXT_CONST_PTR(kRlt0541htaaStr);
extern IRTEXT_CONST_PTR(kRlt0541htabStr);
extern IRTEXT_CONST_PTR(kRoomStr);
extern IRTEXT_CONST_PTR(kSaveStr);
extern IRTEXT_CONST_PTR(kSecondsStr);
extern IRTEXT_CONST_PTR(kSecondStr);
extern IRTEXT_CONST_PTR(kSecondsStr);
extern IRTEXT_CONST_PTR(kSensorStr);
extern IRTEXT_CONST_PTR(kSensorTempStr);
extern IRTEXT_CONST_PTR(kSetStr);
@ -222,8 +222,8 @@ extern IRTEXT_CONST_PTR(kTurboStr);
extern IRTEXT_CONST_PTR(kTurboToggleStr);
extern IRTEXT_CONST_PTR(kTypeStr);
extern IRTEXT_CONST_PTR(kUnknownStr);
extern IRTEXT_CONST_PTR(kUpperStr);
extern IRTEXT_CONST_PTR(kUpStr);
extern IRTEXT_CONST_PTR(kUpperStr);
extern IRTEXT_CONST_PTR(kV9014557AStr);
extern IRTEXT_CONST_PTR(kV9014557BStr);
extern IRTEXT_CONST_PTR(kVaneStr);
@ -235,6 +235,7 @@ extern IRTEXT_CONST_PTR(kXFanStr);
extern IRTEXT_CONST_PTR(kYaw1fStr);
extern IRTEXT_CONST_PTR(kYbofbStr);
extern IRTEXT_CONST_PTR(kYesStr);
extern IRTEXT_CONST_PTR(kYx1fsfStr);
extern IRTEXT_CONST_PTR(kZoneFollowStr);
extern IRTEXT_CONST_PTR(kAllProtocolNamesStr);

View File

@ -172,6 +172,8 @@ bool hasACState(const decode_type_t protocol) {
// This is kept sorted by name
case AMCOR:
case ARGO:
case BOSCH144:
case CARRIER_AC128:
case CORONA_AC:
case DAIKIN:
case DAIKIN128:
@ -179,12 +181,15 @@ bool hasACState(const decode_type_t protocol) {
case DAIKIN160:
case DAIKIN176:
case DAIKIN2:
case DAIKIN200:
case DAIKIN216:
case DAIKIN312:
case ELECTRA_AC:
case FUJITSU_AC:
case GREE:
case HAIER_AC:
case HAIER_AC_YRW02:
case HAIER_AC160:
case HAIER_AC176:
case HITACHI_AC:
case HITACHI_AC1:
@ -209,7 +214,9 @@ bool hasACState(const decode_type_t protocol) {
case SAMSUNG_AC:
case SANYO_AC:
case SANYO_AC88:
case SANYO_AC152:
case SHARP_AC:
case TCL96AC:
case TCL112AC:
case TEKNOPOINT:
case TOSHIBA_AC:
@ -605,9 +612,10 @@ namespace irutils {
break;
case decode_type_t::GREE:
switch (model) {
case gree_ac_remote_model_t::YAW1F: return kYaw1fStr;
case gree_ac_remote_model_t::YBOFB: return kYbofbStr;
default: return kUnknownStr;
case gree_ac_remote_model_t::YAW1F: return kYaw1fStr;
case gree_ac_remote_model_t::YBOFB: return kYbofbStr;
case gree_ac_remote_model_t::YX1FSF: return kYx1fsfStr;
default: return kUnknownStr;
}
break;
case decode_type_t::HAIER_AC176:

View File

@ -63,6 +63,28 @@ void IRArgoAC::begin(void) { _irsend.begin(); }
void IRArgoAC::send(const uint16_t repeat) {
_irsend.sendArgo(getRaw(), kArgoStateLength, repeat);
}
/// Send current room temperature for the iFeel feature as a silent IR
/// message (no acknowledgement from the device).
/// @param[in] temp The temperature in degrees celsius.
/// @param[in] repeat Nr. of times the message will be repeated.
void IRArgoAC::sendSensorTemp(const uint8_t temp, const uint16_t repeat) {
uint8_t tempc = temp - kArgoTempDelta;
uint8_t check = 52 + tempc;
uint8_t end = 0b011;
ArgoProtocol data;
data.raw[0] = 0b10101100;
data.raw[1] = 0b11110101;
data.raw[2] = (tempc << 3) | (check >> 5);
data.raw[3] = (check << 3) | end;
for (uint8_t i = 4; i < kArgoStateLength; i++) data.raw[i] = 0x0;
uint8_t sum = IRArgoAC::calcChecksum(data.raw, kArgoStateLength);
data.raw[10] = 0b00000010;
data.Sum = sum;
_irsend.sendArgo(data.raw, kArgoStateLength, repeat);
}
#endif // SEND_ARGO
/// Verify the checksum is valid for a given state.

View File

@ -131,6 +131,8 @@ class IRArgoAC {
#if SEND_ARGO
void send(const uint16_t repeat = kArgoDefaultRepeat);
void sendSensorTemp(const uint8_t temp,
const uint16_t repeat = kArgoDefaultRepeat);
/// Run the calibration to calculate uSec timing offsets for this platform.
/// @return The uSec timing offset needed per modulation of the IR Led.
/// @note This will produce a 65ms IR signal pulse at 38kHz.

View File

@ -0,0 +1,331 @@
// Copyright 2022 David Conran
// Copyright 2022 Nico Thien
/// @file
/// @brief Support for the Bosch A/C / heatpump protocol
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787
#include "ir_Bosch.h"
#if SEND_BOSCH144
/// Send a Bosch 144-bit / 18-byte message (96-bit message are also possible)
/// Status: BETA / Probably Working.
/// @param[in] data The message to be sent.
/// @param[in] nbytes The number of bytes of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
void IRsend::sendBosch144(const unsigned char data[], const uint16_t nbytes,
const uint16_t repeat) {
// nbytes is required to be a multiple of kBosch144BytesPerSection.
if (nbytes % kBosch144BytesPerSection != 0)return;
// Set IR carrier frequency
enableIROut(kBoschFreq);
for (uint16_t r = 0; r <= repeat; r++) {
for (uint16_t offset=0; offset < nbytes; offset += kBosch144BytesPerSection)
// Section Header + Data + Footer
sendGeneric(kBoschHdrMark, kBoschHdrSpace,
kBoschBitMark, kBoschOneSpace,
kBoschBitMark, kBoschZeroSpace,
kBoschBitMark, kBoschFooterSpace,
data + offset, kBosch144BytesPerSection,
kBoschFreq, true, 0, kDutyDefault);
space(kDefaultMessageGap); // Complete guess
}
}
#endif // SEND_BOSCH144
/// Class constructor.
/// @param[in] pin GPIO to be used when sending.
/// @param[in] inverted Is the output signal to be inverted?
/// @param[in] use_modulation Is frequency modulation to be used?
IRBosch144AC::IRBosch144AC(const uint16_t pin, const bool inverted,
const bool use_modulation)
: _irsend(pin, inverted, use_modulation) { stateReset(); }
/// Reset the internal state to a fixed known good state.
void IRBosch144AC::stateReset(void) {
setRaw(kBosch144DefaultState, kBosch144StateLength);
setPower(true);
}
/// Set up hardware to be able to send a message.
void IRBosch144AC::begin(void) { _irsend.begin(); }
#if SEND_BOSCH144
/// Send the current internal state as an IR message.
/// @param[in] repeat Nr. of times the message will be repeated.
void IRBosch144AC::send(const uint16_t repeat) {
if (!powerFlag) { // "Off" is a 96bit message
_irsend.sendBosch144(kBosch144Off, sizeof(kBosch144Off), repeat);
} else {
_irsend.sendBosch144(getRaw(), kBosch144StateLength, repeat);
} // other 96bit messages are not yet supported
}
#endif // SEND_BOSCH144
/// Get a copy of the internal state as a valid code for this protocol.
/// @return A valid code for this protocol based on the current internal state.
unsigned char* IRBosch144AC::getRaw(void) {
setInvertBytes();
setCheckSumS3();
return _.raw;
}
/// Set the internal state from a valid code for this protocol.
/// @param[in] new_code A valid code for this protocol.
/// @param[in] length Size of the array being passed in in bytes.
void IRBosch144AC::setRaw(const uint8_t new_code[], const uint16_t length) {
const uint16_t len = min(length, kBosch144StateLength);
const uint16_t lenOff = sizeof(kBosch144Off);
// Is it an off message?
if (memcmp(kBosch144Off, new_code, min(lenOff, len)) == 0)
setPower(false); // It is.
else
setPower(true);
memcpy(_.raw, new_code, len);
}
void IRBosch144AC::setPower(const bool on) {
powerFlag = on;
}
bool IRBosch144AC::getPower(void) const {
return powerFlag;
}
void IRBosch144AC::setTempRaw(const uint8_t code) {
_.TempS1 = _.TempS2 = code >> 1; // save 4 bits in S1 and S2
_.TempS3 = code & 1; // save 1 bit in Section3
}
/// Set the temperature.
/// @param[in] degrees The temperature in degrees celsius.
void IRBosch144AC::setTemp(const uint8_t degrees) {
uint8_t temp = max(kBosch144TempMin, degrees);
temp = min(kBosch144TempMax, temp);
setTempRaw(kBosch144TempMap[temp - kBosch144TempMin]);
}
uint8_t IRBosch144AC::getTemp(void) const {
uint8_t temp = (_.TempS1 << 1) + _.TempS3;
uint8_t retemp = 25;
for (uint8_t i = 0; i < kBosch144TempRange; i++) {
if (temp == kBosch144TempMap[i]) {
retemp = kBosch144TempMin + i;
}
}
return retemp;
}
/// Set the speed of the fan.
/// @param[in] speed The desired setting.
void IRBosch144AC::setFan(const uint16_t speed) {
_.FanS1 = _.FanS2 = speed >> 6; // save 3 bits in S1 and S2
_.FanS3 = speed & 0b111111; // save 6 bits in Section3
}
uint16_t IRBosch144AC::getFan(void) const {
return (_.FanS1 << 6) + _.FanS3;
}
/// Set the desired operation mode.
/// @param[in] mode The desired operation mode.
void IRBosch144AC::setMode(const uint8_t mode) {
_.ModeS1 = _.ModeS2 = mode >> 1; // save 2 bits in S1 and S2
_.ModeS3 = mode & 0b1; // save 1 bit in Section3
if (mode == kBosch144Auto || mode == kBosch144Dry) {
_.FanS1 = _.FanS2 = 0b000; // save 3 bits in S1 and S2
_.FanS3 = kBosch144FanAuto0; // save 6 bits in Section3
}
}
uint8_t IRBosch144AC::getMode(void) const {
return (_.ModeS1 << 1) + _.ModeS3;
}
/// Set the Quiet mode of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRBosch144AC::setQuiet(const bool on) {
_.Quiet = on; // save 1 bit in Section3
setFan(kBosch144FanAuto); // set Fan -> Auto
}
/// Get the Quiet mode of the A/C.
/// @return true, the setting is on. false, the setting is off.
bool IRBosch144AC::getQuiet(void) const { return _.Quiet; }
/// Convert a stdAc::opmode_t enum into its native mode.
/// @param[in] mode The enum to be converted.
/// @return The native equivalent of the enum.
uint8_t IRBosch144AC::convertMode(const stdAc::opmode_t mode) {
switch (mode) {
case stdAc::opmode_t::kCool:
return kBosch144Cool;
case stdAc::opmode_t::kHeat:
return kBosch144Heat;
case stdAc::opmode_t::kDry:
return kBosch144Dry;
case stdAc::opmode_t::kFan:
return kBosch144Fan;
default:
return kBosch144Auto;
}
}
/// Convert a stdAc::fanspeed_t enum into it's native speed.
/// @param[in] speed The enum to be converted.
/// @return The native equivalent of the enum.
uint16_t IRBosch144AC::convertFan(const stdAc::fanspeed_t speed) {
switch (speed) {
case stdAc::fanspeed_t::kMin:
return kBosch144Fan20;
case stdAc::fanspeed_t::kLow:
return kBosch144Fan40;
case stdAc::fanspeed_t::kMedium:
return kBosch144Fan60;
case stdAc::fanspeed_t::kHigh:
return kBosch144Fan80;
case stdAc::fanspeed_t::kMax:
return kBosch144Fan100;
default:
return kBosch144FanAuto;
}
}
/// Convert a native mode into its stdAc equivalent.
/// @param[in] mode The native setting to be converted.
/// @return The stdAc equivalent of the native setting.
stdAc::opmode_t IRBosch144AC::toCommonMode(const uint8_t mode) {
switch (mode) {
case kBosch144Cool: return stdAc::opmode_t::kCool;
case kBosch144Heat: return stdAc::opmode_t::kHeat;
case kBosch144Dry: return stdAc::opmode_t::kDry;
case kBosch144Fan: return stdAc::opmode_t::kFan;
default: return stdAc::opmode_t::kAuto;
}
}
/// Convert a native fan speed into its stdAc equivalent.
/// @param[in] speed The native setting to be converted.
/// @return The stdAc equivalent of the native setting.
stdAc::fanspeed_t IRBosch144AC::toCommonFanSpeed(const uint16_t speed) {
switch (speed) {
case kBosch144Fan100: return stdAc::fanspeed_t::kMax;
case kBosch144Fan80: return stdAc::fanspeed_t::kHigh;
case kBosch144Fan60: return stdAc::fanspeed_t::kMedium;
case kBosch144Fan40: return stdAc::fanspeed_t::kLow;
case kBosch144Fan20: return stdAc::fanspeed_t::kMin;
default: return stdAc::fanspeed_t::kAuto;
}
}
/// Convert the current internal state into its stdAc::state_t equivalent.
/// @return The stdAc equivalent of the native settings.
stdAc::state_t IRBosch144AC::toCommon(void) const {
stdAc::state_t result{};
result.protocol = decode_type_t::BOSCH144;
result.power = getPower();
result.mode = toCommonMode(getMode());
result.celsius = true;
result.degrees = getTemp();
result.fanspeed = toCommonFanSpeed(getFan());
result.quiet = getQuiet();
// Not supported.
result.model = -1;
result.turbo = false;
result.swingv = stdAc::swingv_t::kOff;
result.swingh = stdAc::swingh_t::kOff;
result.light = false;
result.filter = false;
result.econo = false;
result.clean = false;
result.beep = false;
result.clock = -1;
result.sleep = -1;
return result;
}
/// Convert the current internal state into a human readable string.
/// @return A human readable string.
String IRBosch144AC::toString(void) const {
uint8_t mode = getMode();
uint8_t fan = static_cast<int>(toCommonFanSpeed(getFan()));
String result = "";
result.reserve(70); // Reserve some heap for the string to reduce fragging.
result += addBoolToString(getPower(), kPowerStr, false);
result += addModeToString(mode, kBosch144Auto, kBosch144Cool,
kBosch144Heat, kBosch144Dry, kBosch144Fan);
result += addFanToString(fan, static_cast<int>(stdAc::fanspeed_t::kMax),
static_cast<int>(stdAc::fanspeed_t::kMin),
static_cast<int>(stdAc::fanspeed_t::kAuto),
static_cast<int>(stdAc::fanspeed_t::kAuto),
static_cast<int>(stdAc::fanspeed_t::kMedium));
result += addTempToString(getTemp());
result += addBoolToString(_.Quiet, kQuietStr);
return result;
}
void IRBosch144AC::setInvertBytes() {
for (uint8_t i = 0; i <= 10; i += 2) {
_.raw[i + 1] = ~_.raw[i];
}
}
void IRBosch144AC::setCheckSumS3() {
_.ChecksumS3 = sumBytes(&(_.raw[12]), 5);
}
#if DECODE_BOSCH144
/// Decode the supplied Bosch 144-bit / 18-byte A/C message.
/// Status: STABLE / Confirmed Working.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// result.
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
bool IRrecv::decodeBosch144(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < 2 * nbits +
kBosch144NrOfSections * (kHeader + kFooter) -
1 + offset)
return false; // Can't possibly be a valid BOSCH144 message.
if (strict && nbits != kBosch144Bits)
return false; // Not strictly a BOSCH144 message.
if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte.
return false;
if (nbits % kBosch144NrOfSections != 0)
return false; // nbits has to be a multiple of kBosch144NrOfSections.
const uint16_t kSectionBits = nbits / kBosch144NrOfSections;
const uint16_t kSectionBytes = kSectionBits / 8;
const uint16_t kNBytes = kSectionBytes * kBosch144NrOfSections;
// Capture each section individually
for (uint16_t pos = 0, section = 0;
pos < kNBytes;
pos += kSectionBytes, section++) {
uint16_t used = 0;
// Section Header + Section Data + Section Footer
used = matchGeneric(results->rawbuf + offset, results->state + pos,
results->rawlen - offset, kSectionBits,
kBoschHdrMark, kBoschHdrSpace,
kBoschBitMark, kBoschOneSpace,
kBoschBitMark, kBoschZeroSpace,
kBoschBitMark, kBoschFooterSpace,
section >= kBosch144NrOfSections - 1,
_tolerance, kMarkExcess, true);
if (!used) return false; // Didn't match.
offset += used;
}
// Compliance
// Success
results->decode_type = decode_type_t::BOSCH144;
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_BOSCH144

View File

@ -0,0 +1,193 @@
// Copyright 2022 Nico Thien
/// @file
/// @brief Support for Bosch A/C protocol
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787
// Supports:
// Brand: Bosch, Model: CL3000i-Set 26 E A/C
// Brand: Bosch, Model: RG10A(G2S)BGEF remote
#ifndef IR_BOSCH_H_
#define IR_BOSCH_H_
#define __STDC_LIMIT_MACROS
#include <stdint.h>
#include <algorithm>
#include <cstring>
#include "IRremoteESP8266.h"
#include "IRsend.h"
#include "IRrecv.h"
#include "IRtext.h"
#include "IRutils.h"
#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#ifdef UNIT_TEST
#include "IRsend_test.h"
#endif
// Constants
const uint16_t kBoschHdrMark = 4366;
const uint16_t kBoschBitMark = 502;
const uint16_t kBoschHdrSpace = 4415;
const uint16_t kBoschOneSpace = 1645;
const uint16_t kBoschZeroSpace = 571;
const uint16_t kBoschFooterSpace = 5235;
const uint16_t kBoschFreq = 38000; // Hz. (Guessing the most common frequency.)
const uint16_t kBosch144NrOfSections = 3;
const uint16_t kBosch144BytesPerSection = 6;
using irutils::addBoolToString;
using irutils::addModeToString;
using irutils::addFanToString;
using irutils::addTempToString;
using std::min;
using std::max;
using std::memcpy;
using std::memcmp;
// Modes Bit[0] to Section 3 Bit[1-2] to Section 1
// ModeS3 ModeS1
const uint8_t kBosch144Cool = 0b000;
const uint8_t kBosch144Dry = 0b011;
const uint8_t kBosch144Auto = 0b101;
const uint8_t kBosch144Heat = 0b110;
const uint8_t kBosch144Fan = 0b010;
// Fan Control Bit[0-5] to Section 3 Bit[6-8] to Section 1
// FanS3 FanS1
const uint16_t kBosch144Fan20 = 0b111001010;
const uint16_t kBosch144Fan40 = 0b100010100;
const uint16_t kBosch144Fan60 = 0b010011110;
const uint16_t kBosch144Fan80 = 0b001101000;
const uint16_t kBosch144Fan100 = 0b001110010;
const uint16_t kBosch144FanAuto = 0b101110011;
const uint16_t kBosch144FanAuto0 = 0b000110011;
// Temperature
const uint8_t kBosch144TempMin = 16; // Celsius
const uint8_t kBosch144TempMax = 30; // Celsius
const uint8_t kBosch144TempRange = kBosch144TempMax - kBosch144TempMin + 1;
const uint8_t kBosch144TempMap[kBosch144TempRange] = {
0b00001, // 16C // Bit[0] to Section 3 Bit[1-4] to Section 1
0b00000, // 17C // TempS3 TempS1
0b00010, // 18c
0b00110, // 19C
0b00100, // 20C
0b01100, // 21C
0b01110, // 22C
0b01010, // 23C
0b01000, // 24C
0b11000, // 25C
0b11010, // 26C
0b10010, // 27C
0b10000, // 28C
0b10100, // 29C
0b10110 // 30C
};
// "OFF" is a 96bit-message the same as Coolix protocol
const uint8_t kBosch144Off[] = {0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F,
0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F};
// On, 25C, Mode: Auto
const uint8_t kBosch144DefaultState[kBosch144StateLength] = {
0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37,
0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37,
0xD5, 0x65, 0x00, 0x00, 0x00, 0x3A};
union Bosch144Protocol {
uint8_t raw[kBosch144StateLength]; ///< The state in IR code form.
struct {
uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############
uint8_t InnvertS1_1:8; // Invert byte 0b01001101 / 0x4D #
uint8_t :5; // not used (without timer use) #
uint8_t FanS1 :3; // Fan speed bits in Section 1 #
uint8_t InnvertS1_2:8; // Invert byte # Section 1 =
uint8_t :2; // not used (without timer use) # Sektion 2
uint8_t ModeS1 :2; // Operation mode bits S1 #
uint8_t TempS1 :4; // Desired temperature (Celsius) S2 #
uint8_t InnvertS1_3:8; // Invert byte (without timer use) ############
uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############
uint8_t InnvertS2_1:8; // Invert byte 0b01001101 / 0x4D #
uint8_t :5; // not used (without timer use) #
uint8_t FanS2 :3; // Fan speed bits in Section 2 #
uint8_t InnvertS2_2:8; // Invert byte # Section 2 =
uint8_t :2; // not used (without timer use) # Sektion 1
uint8_t ModeS2 :2; // Operation mode bits S2 #
uint8_t TempS2 :4; // Desired temperature (Celsius) S2 #
uint8_t InnvertS2_3:8; // Invert byte (without timer use) ###########
uint8_t :8; // Fixed value 0b11010101 / 0xD5 ###########
uint8_t ModeS3 :1; // ModeBit in Section 3 #
uint8_t FanS3 :6; // Fan speed bits in Section 3 #
uint8_t :1; // Unknown #
uint8_t :7; // Unknown #
uint8_t Quiet :1; // Silent-Mode # Section 3
uint8_t :4; // Unknown #
uint8_t TempS3 :1; // Desired temp. Bit in Section3 #
uint8_t :3; // Unknown #
uint8_t :8; // Unknown #
uint8_t ChecksumS3 :8; // Checksum from byte 13-17 ###########
};
};
// Classes
/// Class for handling detailed Bosch144 A/C messages.
class IRBosch144AC {
public:
explicit IRBosch144AC(const uint16_t pin, const bool inverted = false,
const bool use_modulation = true);
void stateReset(void);
#if SEND_BOSCH144
void send(const uint16_t repeat = 0);
/// Run the calibration to calculate uSec timing offsets for this platform.
/// @return The uSec timing offset needed per modulation of the IR Led.
/// @note This will produce a 65ms IR signal pulse at 38kHz.
/// Only ever needs to be run once per object instantiation, if at all.
int8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_BOSCH144
void begin();
void setPower(const bool state);
bool getPower(void) const;
void setTemp(const uint8_t temp);
uint8_t getTemp(void) const;
void setFan(const uint16_t speed);
uint16_t getFan(void) const;
void setMode(const uint8_t mode);
uint8_t getMode(void) const;
void setQuiet(const bool on);
bool getQuiet(void) const;
uint8_t* getRaw(void);
void setRaw(const uint8_t new_code[],
const uint16_t length = kBosch144StateLength);
static uint8_t convertMode(const stdAc::opmode_t mode);
static uint16_t convertFan(const stdAc::fanspeed_t speed);
static stdAc::opmode_t toCommonMode(const uint8_t mode);
static stdAc::fanspeed_t toCommonFanSpeed(const uint16_t speed);
stdAc::state_t toCommon(void) const;
String toString(void) const;
#ifndef UNIT_TEST
private:
IRsend _irsend; ///< Instance of the IR send class
#else
/// @cond IGNORE
IRsendTest _irsend; ///< Instance of the testing IR send class
/// @endcond
#endif
Bosch144Protocol _; ///< The state of the IR remote in IR code form.
// Internal State settings
bool powerFlag;
void setInvertBytes();
void setCheckSumS3();
void setTempRaw(const uint8_t code);
uint8_t getTempRaw(void) const;
};
#endif // IR_BOSCH_H_

View File

@ -1,8 +1,9 @@
// Copyright 2018, 2020 David Conran
// Copyright 2018-2022 David Conran
/// @file
/// @brief Carrier protocols.
/// @see CarrierAc https://github.com/crankyoldgit/IRremoteESP8266/issues/385
/// @see CarrierAc64 https://github.com/crankyoldgit/IRremoteESP8266/issues/1127
/// @see CarrierAc128 https://github.com/crankyoldgit/IRremoteESP8266/issues/1797
#include "ir_Carrier.h"
#include <algorithm>
@ -45,6 +46,16 @@ const uint16_t kCarrierAc64OneSpace = 1736;
const uint16_t kCarrierAc64ZeroSpace = 615;
const uint32_t kCarrierAc64Gap = kDefaultMessageGap; // A guess.
const uint16_t kCarrierAc128HdrMark = 4600;
const uint16_t kCarrierAc128HdrSpace = 2600;
const uint16_t kCarrierAc128Hdr2Mark = 9300;
const uint16_t kCarrierAc128Hdr2Space = 5000;
const uint16_t kCarrierAc128BitMark = 340;
const uint16_t kCarrierAc128OneSpace = 1000;
const uint16_t kCarrierAc128ZeroSpace = 400;
const uint16_t kCarrierAc128SectionGap = 20600;
const uint16_t kCarrierAc128InterSpace = 6700;
const uint16_t kCarrierAc128SectionBits = kCarrierAc128Bits / 2;
#if SEND_CARRIER_AC
/// Send a Carrier HVAC formatted message.
@ -533,3 +544,104 @@ stdAc::state_t IRCarrierAc64::toCommon(void) const {
result.clock = -1;
return result;
}
#if SEND_CARRIER_AC128
/// Send a Carrier 128bit HVAC formatted message.
/// Status: BETA / Seems to work with tests. Needs testing agaisnt real devices.
/// @param[in] data The message to be sent.
/// @param[in] nbytes The byte size of the message being sent.
/// @param[in] repeat The number of times the message is to be repeated.
void IRsend::sendCarrierAC128(const uint8_t data[], const uint16_t nbytes,
const uint16_t repeat) {
// Min length check.
if (nbytes <= kCarrierAc128StateLength / 2) return;
enableIROut(kCarrierAcFreq);
// Handle repeats.
for (uint16_t r = 0; r <= repeat; r++) {
// First part of the message.
// Headers + Data + SectionGap
sendGeneric(kCarrierAc128HdrMark, kCarrierAc128HdrSpace,
kCarrierAc128BitMark, kCarrierAc128OneSpace,
kCarrierAc128BitMark, kCarrierAc128ZeroSpace,
kCarrierAc128BitMark, kCarrierAc128SectionGap,
data, nbytes / 2, kCarrierAcFreq, false, 0, kDutyDefault);
// Inter-message markers
mark(kCarrierAc128HdrMark);
space(kCarrierAc128InterSpace);
// Second part of the message
// Headers + Data + SectionGap
sendGeneric(kCarrierAc128Hdr2Mark, kCarrierAc128Hdr2Space,
kCarrierAc128BitMark, kCarrierAc128OneSpace,
kCarrierAc128BitMark, kCarrierAc128ZeroSpace,
kCarrierAc128BitMark, kCarrierAc128SectionGap,
data + (nbytes / 2), nbytes / 2, kCarrierAcFreq,
false, 0, kDutyDefault);
// Footer
mark(kCarrierAc128HdrMark);
space(kDefaultMessageGap);
}
}
#endif // SEND_CARRIER_AC128
#if DECODE_CARRIER_AC128
/// Decode the supplied Carrier 128-bit HVAC message.
/// Status: STABLE / Expected to work.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// result.
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
bool IRrecv::decodeCarrierAC128(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < 2 * (nbits + 2 * kHeader + kFooter) - 1 + offset)
return false; // Can't possibly be a valid Carrier message.
if (strict && nbits != kCarrierAc128Bits)
return false; // We expect Carrier to be 128 bits of message.
uint16_t used;
uint16_t pos = 0;
const uint16_t sectionbits = nbits / 2;
// Match the first section.
used = matchGeneric(results->rawbuf + offset, results->state,
results->rawlen - offset, sectionbits,
kCarrierAc128HdrMark, kCarrierAc128HdrSpace,
kCarrierAc128BitMark, kCarrierAc128OneSpace,
kCarrierAc128BitMark, kCarrierAc128ZeroSpace,
kCarrierAc128BitMark, kCarrierAc128SectionGap, true,
kUseDefTol, kMarkExcess, false);
if (used == 0) return false; // No match.
offset += used;
pos += sectionbits / 8;
// Look for the inter-message markers.
if (!matchMark(results->rawbuf[offset++], kCarrierAc128HdrMark))
return false;
if (!matchSpace(results->rawbuf[offset++], kCarrierAc128InterSpace))
return false;
// Now look for the second section.
used = matchGeneric(results->rawbuf + offset, results->state + pos,
results->rawlen - offset, sectionbits,
kCarrierAc128Hdr2Mark, kCarrierAc128Hdr2Space,
kCarrierAc128BitMark, kCarrierAc128OneSpace,
kCarrierAc128BitMark, kCarrierAc128ZeroSpace,
kCarrierAc128BitMark, kCarrierAc128SectionGap, true,
kUseDefTol, kMarkExcess, false);
if (used == 0) return false; // No match.
offset += used;
// Now check for the Footer.
if (!matchMark(results->rawbuf[offset++], kCarrierAc128HdrMark)) return false;
if (offset < results->rawlen &&
!matchAtLeast(results->rawbuf[offset], kDefaultMessageGap)) return false;
// Compliance
// if (strict && !IRCarrierAc128::validChecksum(results->value)) return false;
// Success
results->bits = nbits;
results->decode_type = CARRIER_AC128;
return true;
}
#endif // DECODE_CARRIER_AC128

View File

@ -1,8 +1,9 @@
// Copyright 2020 David Conran
// Copyright 2020-2022 David Conran
/// @file
/// @brief Carrier A/C
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1127
/// @see https://docs.google.com/spreadsheets/d/1EZy78L0cn1KDIX1aKq2biptejFqCjD5HO3tLiRvXf48/edit#gid=0
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1797
// Supports:
// Brand: Carrier/Surrey, Model: 42QG5A55970 remote
@ -11,6 +12,7 @@
// Brand: Carrier/Surrey, Model: 619EGX0180E0 A/C
// Brand: Carrier/Surrey, Model: 619EGX0220E0 A/C
// Brand: Carrier/Surrey, Model: 53NGK009/012 Inverter
// Brand: Carrier, Model: 40GKX0E2006 remote (CARRIER_AC128)
#ifndef IR_CARRIER_H_
#define IR_CARRIER_H_

View File

@ -0,0 +1,86 @@
// Copyright 2022 benjy3gg
// Copyright 2022 David Conran (crankyoldgit)
/// @file
/// @brief Support for Clima-Butler protocol
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1812
// Supports:
// Brand: Clima-Butler, Model: AR-715 remote
// Brand: Clima-Butler, Model: RCS-SD43UWI A/C
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
const uint16_t kClimaButlerBitMark = 511; // uSeconds
const uint16_t kClimaButlerHdrMark = kClimaButlerBitMark;
const uint16_t kClimaButlerHdrSpace = 3492; // uSeconds
const uint16_t kClimaButlerOneSpace = 1540; // uSeconds
const uint16_t kClimaButlerZeroSpace = 548; // uSeconds
const uint32_t kClimaButlerGap = kDefaultMessageGap; // uSeconds (A guess.)
const uint16_t kClimaButlerFreq = 38000; // Hz. (Guess.)
#if SEND_CLIMABUTLER
/// Send a ClimaButler formatted message.
/// Status: STABLE / Confirmed working.
/// @param[in] data containing the IR command.
/// @param[in] nbits Nr. of bits to send. usually kClimaButlerBits
/// @param[in] repeat Nr. of times the message is to be repeated.
void IRsend::sendClimaButler(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
enableIROut(kClimaButlerFreq);
for (uint16_t r = 0; r <= repeat; r++) {
// Header + Data
sendGeneric(kClimaButlerHdrMark, kClimaButlerHdrSpace,
kClimaButlerBitMark, kClimaButlerOneSpace,
kClimaButlerBitMark, kClimaButlerZeroSpace,
kClimaButlerBitMark, kClimaButlerHdrSpace,
data, nbits, kClimaButlerFreq, true, 0, kDutyDefault);
// Footer
mark(kClimaButlerBitMark);
space(kClimaButlerGap);
}
}
#endif // SEND_CLIMABUTLER
#if DECODE_CLIMABUTLER
/// Decode the supplied ClimaButler message.
/// Status: STABLE / Confirmed working.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
bool IRrecv::decodeClimaButler(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < 2 * nbits + kHeader + 2 * kFooter - offset)
return false; // Too short a message to match.
if (strict && nbits != kClimaButlerBits)
return false;
// Header + Data
uint16_t used = matchGeneric(results->rawbuf + offset, &(results->value),
results->rawlen - offset, nbits,
kClimaButlerHdrMark, kClimaButlerHdrSpace,
kClimaButlerBitMark, kClimaButlerOneSpace,
kClimaButlerBitMark, kClimaButlerZeroSpace,
kClimaButlerBitMark, kClimaButlerHdrSpace);
if (!used) return false; // Didn't matched.
offset += used;
// Footer
if (!matchMark(results->rawbuf[offset++], kClimaButlerBitMark))
return false;
if (results->rawlen <= offset && !matchAtLeast(results->rawbuf[offset],
kClimaButlerGap))
return false;
// Success
results->decode_type = decode_type_t::CLIMABUTLER;
results->bits = nbits;
results->command = 0;
results->address = 0;
return true;
}
#endif // DECODE_CLIMABUTLER

View File

@ -719,7 +719,7 @@ void IRsend::sendCoolix48(const uint64_t data, const uint16_t nbits,
}
#endif // SEND_COOLIX48
#if DECODE_COOLIX
#if DECODE_COOLIX48
/// Decode the supplied Coolix 48-bit A/C message.
/// Status: BETA / Probably Working.
/// @param[in,out] results Ptr to the data to decode & where to store the decode

View File

@ -1,6 +1,6 @@
// Copyright 2016 sillyfrog
// Copyright 2017 sillyfrog, crankyoldgit
// Copyright 2018-2021 crankyoldgit
// Copyright 2018-2022 crankyoldgit
// Copyright 2019 pasna (IRDaikin160 class / Daikin176 class)
/// @file
@ -21,6 +21,7 @@
/// @see Daikin216 https://github.com/crankyoldgit/IRremoteESP8266/issues/689
/// @see Daikin216 https://github.com/danny-source/Arduino_DY_IRDaikin
/// @see Daikin64 https://github.com/crankyoldgit/IRremoteESP8266/issues/1064
/// @see Daikin200 https://github.com/crankyoldgit/IRremoteESP8266/issues/1802
#include "ir_Daikin.h"
#include <algorithm>
@ -3733,3 +3734,193 @@ stdAc::state_t IRDaikin64::toCommon(const stdAc::state_t *prev) const {
result.light = false;
return result;
}
#if SEND_DAIKIN200
/// Send a Daikin200 (200-bit) A/C formatted message.
/// Status: BETA / Untested on a real device.
/// @param[in] data The message to be sent.
/// @param[in] nbytes The number of bytes of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1802
void IRsend::sendDaikin200(const unsigned char data[], const uint16_t nbytes,
const uint16_t repeat) {
if (nbytes < kDaikin200Section1Length)
return; // Not enough bytes to send a partial message.
for (uint16_t r = 0; r <= repeat; r++) {
// Section #1
sendGeneric(kDaikin200HdrMark, kDaikin200HdrSpace, kDaikin200BitMark,
kDaikin200OneSpace, kDaikin200BitMark, kDaikin200ZeroSpace,
kDaikin200BitMark, kDaikin200Gap, data,
kDaikin200Section1Length,
kDaikin200Freq, false, 0, kDutyDefault);
// Section #2
sendGeneric(kDaikin200HdrMark, kDaikin200HdrSpace, kDaikin200BitMark,
kDaikin200OneSpace, kDaikin200BitMark, kDaikin200ZeroSpace,
kDaikin200BitMark, kDaikin200Gap,
data + kDaikin200Section1Length,
nbytes - kDaikin200Section1Length,
kDaikin200Freq, false, 0, kDutyDefault);
}
}
#endif // SEND_DAIKIN200
#if DECODE_DAIKIN200
/// Decode the supplied Daikin 200-bit message. (DAIKIN200)
/// Status: STABLE / Known to be working.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// result.
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1802
bool IRrecv::decodeDaikin200(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1 + offset)
return false;
// Compliance
if (strict && nbits != kDaikin200Bits) return false;
const uint8_t ksectionSize[kDaikin200Sections] = {kDaikin200Section1Length,
kDaikin200Section2Length};
// Sections
uint16_t pos = 0;
for (uint8_t section = 0; section < kDaikin200Sections; section++) {
uint16_t used;
// Section Header + Section Data + Section Footer
used = matchGeneric(results->rawbuf + offset, results->state + pos,
results->rawlen - offset, ksectionSize[section] * 8,
kDaikin200HdrMark, kDaikin200HdrSpace,
kDaikin200BitMark, kDaikin200OneSpace,
kDaikin200BitMark, kDaikin200ZeroSpace,
kDaikin200BitMark, kDaikin200Gap,
section >= kDaikin200Sections - 1,
kDaikinTolerance, 0, false);
if (used == 0) return false;
offset += used;
pos += ksectionSize[section];
}
// Compliance
if (strict) {
if (pos * 8 != kDaikin200Bits) return false;
// Validate the checksum.
if (!IRDaikin176::validChecksum(results->state, pos)) return false;
}
// Success
results->decode_type = decode_type_t::DAIKIN200;
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_DAIKIN200
#if SEND_DAIKIN312
/// Send a Daikin312 (312-bit / 39 byte) A/C formatted message.
/// Status: BETA / Untested on a real device.
/// @param[in] data The message to be sent.
/// @param[in] nbytes The number of bytes of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1829
void IRsend::sendDaikin312(const unsigned char data[], const uint16_t nbytes,
const uint16_t repeat) {
if (nbytes < kDaikin312Section1Length)
return; // Not enough bytes to send a partial message.
for (uint16_t r = 0; r <= repeat; r++) {
// Send the header, 0b00000
sendGeneric(0, 0, // No header for the header
kDaikin312BitMark, kDaikin312OneSpace,
kDaikin312BitMark, kDaikin312ZeroSpace,
kDaikin312BitMark, kDaikin312HdrGap,
(uint64_t)0b00000, kDaikinHeaderLength,
kDaikin2Freq, false, 0, kDutyDefault);
// Section #1
sendGeneric(kDaikin312HdrMark, kDaikin312HdrSpace, kDaikin312BitMark,
kDaikin312OneSpace, kDaikin312BitMark, kDaikin312ZeroSpace,
kDaikin312BitMark, kDaikin312SectionGap, data,
kDaikin312Section1Length,
kDaikin2Freq, false, 0, kDutyDefault);
// Section #2
sendGeneric(kDaikin312HdrMark, kDaikin312HdrSpace, kDaikin312BitMark,
kDaikin312OneSpace, kDaikin312BitMark, kDaikin312ZeroSpace,
kDaikin312BitMark, kDaikin312SectionGap,
data + kDaikin312Section1Length,
nbytes - kDaikin312Section1Length,
kDaikin2Freq, false, 0, kDutyDefault);
}
}
#endif // SEND_DAIKIN312
#if DECODE_DAIKIN312
/// Decode the supplied Daikin 312-bit / 39-byte message. (DAIKIN312)
/// Status: STABLE / Confirmed working.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// result.
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1829
bool IRrecv::decodeDaikin312(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
// Is there enough data to match successfully?
if (results->rawlen < 2 * (nbits + kDaikinHeaderLength + kHeader + kFooter) +
kFooter - 1 + offset)
return false;
// Compliance
if (strict && nbits != kDaikin312Bits) return false;
const uint8_t ksectionSize[kDaikin312Sections] = {kDaikin312Section1Length,
kDaikin312Section2Length};
// Header/Leader Section
uint64_t leaderdata = 0;
uint16_t used = matchGeneric(results->rawbuf + offset, &leaderdata,
results->rawlen - offset, kDaikinHeaderLength,
0, 0, // No Header Mark or Space for the "header"
kDaikin312BitMark, kDaikin312OneSpace,
kDaikin312BitMark, kDaikin312ZeroSpace,
kDaikin312BitMark, kDaikin312HdrGap,
false, kDaikinTolerance, 0, false);
if (!used) return false; // Failed to match.
if (leaderdata) return false; // The header bits should all be zero.
offset += used;
// Data Sections
uint16_t pos = 0;
for (uint8_t section = 0; section < kDaikin312Sections; section++) {
// Section Header + Section Data + Section Footer
used = matchGeneric(results->rawbuf + offset, results->state + pos,
results->rawlen - offset, ksectionSize[section] * 8,
kDaikin312HdrMark, kDaikin312HdrSpace,
kDaikin312BitMark, kDaikin312OneSpace,
kDaikin312BitMark, kDaikin312ZeroSpace,
kDaikin312BitMark, kDaikin312SectionGap,
section >= kDaikin312Sections - 1,
kDaikinTolerance, 0, false);
if (used == 0) return false;
offset += used;
pos += ksectionSize[section];
}
// Compliance
if (strict) {
if (pos * 8 != kDaikin312Bits) return false;
}
// Success
results->decode_type = decode_type_t::DAIKIN312;
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_DAIKIN312

View File

@ -1,6 +1,6 @@
// Copyright 2016 sillyfrog
// Copyright 2017 sillyfrog, crankyoldgit
// Copyright 2018-2021 crankyoldgit
// Copyright 2018-2022 crankyoldgit
// Copyright 2019 pasna (IRDaikin160 class / Daikin176 class)
/// @file
@ -21,6 +21,8 @@
/// @see Daikin216 https://github.com/crankyoldgit/IRremoteESP8266/issues/689
/// @see Daikin216 https://github.com/danny-source/Arduino_DY_IRDaikin
/// @see Daikin64 https://github.com/crankyoldgit/IRremoteESP8266/issues/1064
/// @see Daikin200 https://github.com/crankyoldgit/IRremoteESP8266/issues/1802
/// @see Daikin312 https://github.com/crankyoldgit/IRremoteESP8266/issues/1829
// Supports:
// Brand: Daikin, Model: ARC433** remote (DAIKIN)
@ -36,17 +38,21 @@
// Brand: Daikin, Model: BRC4C151 remote (DAIKIN176)
// Brand: Daikin, Model: 17 Series FTXB09AXVJU A/C (DAIKIN128)
// Brand: Daikin, Model: 17 Series FTXB12AXVJU A/C (DAIKIN128)
// Brand: Daikin, Model: 17 Series FTXB24AXVJU A/C (NOT SUPPORTED)
// Brand: Daikin, Model: 17 Series FTXB24AXVJU A/C (DAIKIN128)
// Brand: Daikin, Model: BRC52B63 remote (DAIKIN128)
// Brand: Daikin, Model: ARC480A5 remote (DAIKIN152)
// Brand: Daikin, Model: FFN-C/FCN-F Series A/C (DAIKIN64)
// Brand: Daikin, Model: DGS01 remote (DAIKIN64)
// Brand: Daikin, Model: M Series A/C (DAIKIN)
// Brand: Daikin, Model: FTXM-M A/C (DAIKIN)
// Brand: Daikin, Model: ARC466A12 remote (DAIKIN)
// Brand: Daikin, Model: ARC466A33 remote (DAIKIN)
// Brand: Daikin, Model: FTWX35AXV1 A/C (DAIKIN64)
// Brand: Daikin, Model: ARC484A4 remote (DAIKIN216)
// Brand: Daikin, Model: FTQ60TV16U2 A/C (DAIKIN216)
// Brand: Daikin, Model: BRC4M150W16 remote (DAIKIN200)
// Brand: Daikin, Model: FTXM20R5V1B A/C (DAIKIN312)
// Brand: Daikin, Model: ARC466A67 remote (DAIKIN312)
#ifndef IR_DAIKIN_H_
#define IR_DAIKIN_H_
@ -676,6 +682,30 @@ const uint8_t kDaikin64MaxTemp = 30; // Celsius
const uint8_t kDaikin64ChecksumOffset = 60;
const uint8_t kDaikin64ChecksumSize = 4; // Mask 0b1111 << 59
const uint16_t kDaikin200Freq = 38000; // Modulation Frequency in Hz.
const uint16_t kDaikin200HdrMark = 4920;
const uint16_t kDaikin200HdrSpace = 2230;
const uint16_t kDaikin200BitMark = 290;
const uint16_t kDaikin200OneSpace = 1850;
const uint16_t kDaikin200ZeroSpace = 780;
const uint16_t kDaikin200Gap = 29400;
const uint16_t kDaikin200Sections = 2;
const uint16_t kDaikin200Section1Length = 7;
const uint16_t kDaikin200Section2Length = kDaikin200StateLength -
kDaikin200Section1Length;
const uint16_t kDaikin312HdrMark = 3518;
const uint16_t kDaikin312HdrSpace = 1688;
const uint16_t kDaikin312BitMark = 453;
const uint16_t kDaikin312ZeroSpace = 414;
const uint16_t kDaikin312OneSpace = 1275;
const uint16_t kDaikin312HdrGap = 25100;
const uint16_t kDaikin312SectionGap = 35512;
const uint16_t kDaikin312Sections = 2;
const uint16_t kDaikin312Section1Length = 20;
const uint16_t kDaikin312Section2Length = kDaikin312StateLength -
kDaikin312Section1Length;
// Legacy defines.
#define DAIKIN_COOL kDaikinCool
#define DAIKIN_HEAT kDaikinHeat

View File

@ -1,5 +1,5 @@
// Copyright 2017 Jonny Graham
// Copyright 2017-2021 David Conran
// Copyright 2017-2022 David Conran
// Copyright 2021 siriuslzx
/// @file
@ -116,6 +116,7 @@ void IRFujitsuAC::stateReset(void) {
_.longcode[1] = 0x63;
_.longcode[3] = 0x10;
_.longcode[4] = 0x10;
_rawstatemodified = true;
}
/// Set up hardware to be able to send a message.
@ -142,6 +143,7 @@ bool IRFujitsuAC::updateUseLongOrShort(void) {
case kFujitsuAcCmdStepHoriz: // 0x79
case kFujitsuAcCmdToggleSwingHoriz: // 0x7A
_.Cmd = _cmd;
_rawstatemodified = true;
break;
default:
switch (_model) {
@ -150,10 +152,12 @@ bool IRFujitsuAC::updateUseLongOrShort(void) {
case fujitsu_ac_remote_model_t::ARREB1E:
case fujitsu_ac_remote_model_t::ARREW4E:
_.Cmd = 0xFE;
_rawstatemodified = true;
break;
case fujitsu_ac_remote_model_t::ARDB1:
case fujitsu_ac_remote_model_t::ARJW2:
_.Cmd = 0xFC;
_rawstatemodified = true;
break;
}
fullCmd = true;
@ -164,7 +168,8 @@ bool IRFujitsuAC::updateUseLongOrShort(void) {
/// Calculate and set the checksum values for the internal state.
void IRFujitsuAC::checkSum(void) {
if (updateUseLongOrShort()) { // Is it a long code?
_rawstatemodified = true;
if (updateUseLongOrShort()) { // Is it going to be a long code?
// Nr. of bytes in the message after this byte.
_.RestLength = _state_length - 7;
_.Protocol = (_model == fujitsu_ac_remote_model_t::ARREW4E) ? 0x31 : 0x30;
@ -179,7 +184,13 @@ void IRFujitsuAC::checkSum(void) {
}
}
if (_model != fujitsu_ac_remote_model_t::ARRY4) {
if (_model != fujitsu_ac_remote_model_t::ARREW4E) _.Clean = false;
switch (_model) {
case fujitsu_ac_remote_model_t::ARRAH2E:
case fujitsu_ac_remote_model_t::ARREW4E:
break;
default:
_.Clean = false;
}
_.Filter = false;
}
// Set the On/Off/Sleep timer Nr of mins.
@ -235,13 +246,17 @@ uint8_t IRFujitsuAC::getStateLength(void) {
return updateUseLongOrShort() ? _state_length : _state_length_short;
}
/// Is the current binary state representation a long or a short code?
/// @return true, if long; false, if short.
bool IRFujitsuAC::isLongCode(void) const {
return _.Cmd == 0xFE || _.Cmd == 0xFC;
}
/// Get a PTR to the internal state/code for this protocol.
/// @return PTR to a code for this protocol based on the current internal state.
uint8_t* IRFujitsuAC::getRaw(void) {
checkSum();
if (_.Cmd == 0xFE || _.Cmd == 0xFC)
return _.longcode;
return _.shortcode;
return isLongCode() ? _.longcode : _.shortcode;
}
/// Build the internal state/config from the current (raw) A/C message.
@ -281,7 +296,8 @@ void IRFujitsuAC::buildFromState(const uint16_t length) {
setCmd(kFujitsuAcCmdStayOn);
// Currently the only way we know how to tell ARRAH2E & ARRY4 apart is if
// either the raw Filter or Clean setting is on.
if (_model == fujitsu_ac_remote_model_t::ARRAH2E && (_.Filter || _.Clean))
if (_model == fujitsu_ac_remote_model_t::ARRAH2E && (_.Filter || _.Clean) &&
!get10CHeat())
setModel(fujitsu_ac_remote_model_t::ARRY4);
if (_state_length == kFujitsuAcStateLength && _.OutsideQuiet)
setModel(fujitsu_ac_remote_model_t::ARREB1E);
@ -312,6 +328,7 @@ bool IRFujitsuAC::setRaw(const uint8_t newState[], const uint16_t length) {
_.longcode[i] = 0;
}
buildFromState(length);
_rawstatemodified = false;
return true;
}
@ -405,6 +422,7 @@ bool IRFujitsuAC::getPower(void) const { return _cmd != kFujitsuAcCmdTurnOff; }
/// @param[in] on true, the setting is on. false, the setting is off.
void IRFujitsuAC::setOutsideQuiet(const bool on) {
_.OutsideQuiet = on;
_rawstatemodified = true;
setCmd(kFujitsuAcCmdStayOn); // No special command involved.
}
@ -461,6 +479,7 @@ void IRFujitsuAC::setTemp(const float temp, const bool useCelsius) {
} else {
_.Temp = _temp - offset;
}
_rawstatemodified = true;
setCmd(kFujitsuAcCmdStayOn); // No special command involved.
}
@ -484,6 +503,7 @@ void IRFujitsuAC::setFanSpeed(const uint8_t fanSpeed) {
_.Fan = kFujitsuAcFanHigh; // Set the fan to maximum if out of range.
else
_.Fan = fanSpeed;
_rawstatemodified = true;
setCmd(kFujitsuAcCmdStayOn); // No special command involved.
}
@ -498,6 +518,7 @@ void IRFujitsuAC::setMode(const uint8_t mode) {
_.Mode = kFujitsuAcModeHeat; // Set the mode to maximum if out of range.
else
_.Mode = mode;
_rawstatemodified = true;
setCmd(kFujitsuAcCmdStayOn); // No special command involved.
}
@ -511,6 +532,7 @@ uint8_t IRFujitsuAC::getMode(void) const { return _.Mode; }
/// @note Not all models support all possible swing modes.
void IRFujitsuAC::setSwing(const uint8_t swingMode) {
_.Swing = swingMode;
_rawstatemodified = true;
switch (_model) {
// No Horizontal support.
case fujitsu_ac_remote_model_t::ARDB1:
@ -531,14 +553,13 @@ void IRFujitsuAC::setSwing(const uint8_t swingMode) {
/// Get the requested swing operation mode of the A/C unit.
/// @return The contents of the swing state/mode.
uint8_t IRFujitsuAC::getSwing(void) const {
return _.Swing;
}
uint8_t IRFujitsuAC::getSwing(void) const { return _.Swing; }
/// Set the Clean mode of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRFujitsuAC::setClean(const bool on) {
_.Clean = on;
_rawstatemodified = true;
setCmd(kFujitsuAcCmdStayOn); // No special command involved.
}
@ -555,6 +576,7 @@ bool IRFujitsuAC::getClean(void) const {
/// @param[in] on true, the setting is on. false, the setting is off.
void IRFujitsuAC::setFilter(const bool on) {
_.Filter = on;
_rawstatemodified = true;
setCmd(kFujitsuAcCmdStayOn); // No special command involved.
}
@ -563,7 +585,7 @@ void IRFujitsuAC::setFilter(const bool on) {
bool IRFujitsuAC::getFilter(void) const {
switch (_model) {
case fujitsu_ac_remote_model_t::ARRY4: return _.Filter;
default: return false;
default: return false;
}
}
@ -572,6 +594,7 @@ bool IRFujitsuAC::getFilter(void) const {
void IRFujitsuAC::set10CHeat(const bool on) {
switch (_model) {
// Only selected models support this.
case fujitsu_ac_remote_model_t::ARRAH2E:
case fujitsu_ac_remote_model_t::ARREW4E:
setClean(on); // 10C Heat uses the same bit as Clean
if (on) {
@ -579,6 +602,7 @@ void IRFujitsuAC::set10CHeat(const bool on) {
_.Power = true;
_.Fan = kFujitsuAcFanAuto;
_.Swing = kFujitsuAcSwingOff;
_rawstatemodified = true;
}
default:
break;
@ -589,6 +613,7 @@ void IRFujitsuAC::set10CHeat(const bool on) {
/// @return true, the setting is on. false, the setting is off.
bool IRFujitsuAC::get10CHeat(void) const {
switch (_model) {
case fujitsu_ac_remote_model_t::ARRAH2E:
case fujitsu_ac_remote_model_t::ARREW4E:
return (_.Clean && _.Power && _.Mode == kFujitsuAcModeFan &&
_.Fan == kFujitsuAcFanAuto && _.Swing == kFujitsuAcSwingOff);
@ -602,9 +627,8 @@ uint8_t IRFujitsuAC::getTimerType(void) const {
switch (_model) {
// These models seem to have timer support.
case fujitsu_ac_remote_model_t::ARRAH2E:
case fujitsu_ac_remote_model_t::ARREB1E:
return _.TimerType;
default: return kFujitsuAcStopTimers;
case fujitsu_ac_remote_model_t::ARREB1E: return _.TimerType;
default: return kFujitsuAcStopTimers;
}
}
@ -620,6 +644,7 @@ void IRFujitsuAC::setTimerType(const uint8_t timertype) {
break;
default: _.TimerType = kFujitsuAcStopTimers;
}
_rawstatemodified = true;
}
/// Get the On Timer setting of the A/C.
@ -634,6 +659,7 @@ uint16_t IRFujitsuAC::getOnTimer(void) const {
/// @param[in] nr_mins Nr. of minutes to set the timer to. 0 means disabled.
void IRFujitsuAC::setOnTimer(const uint16_t nr_mins) {
_.OnTimer = std::min(kFujitsuAcTimerMax, nr_mins); // Bounds check.
_rawstatemodified = true;
if (_.OnTimer) {
_.TimerType = kFujitsuAcOnTimer;
} else if (getTimerType() == kFujitsuAcOnTimer) {
@ -646,10 +672,8 @@ void IRFujitsuAC::setOnTimer(const uint16_t nr_mins) {
uint16_t IRFujitsuAC::getOffSleepTimer(void) const {
switch (getTimerType()) {
case kFujitsuAcOffTimer:
case kFujitsuAcSleepTimer:
return _.OffTimer;
default:
return 0;
case kFujitsuAcSleepTimer: return _.OffTimer;
default: return 0;
}
}
@ -657,12 +681,13 @@ uint16_t IRFujitsuAC::getOffSleepTimer(void) const {
/// @param[in] nr_mins Nr. of minutes to set the timer to. 0 means disabled.
inline void IRFujitsuAC::setOffSleepTimer(const uint16_t nr_mins) {
_.OffTimer = std::min(kFujitsuAcTimerMax, nr_mins); // Bounds check.
_rawstatemodified = true;
}
/// Set the Off Timer time for the A/C.
/// @param[in] nr_mins Nr. of minutes to set the timer to. 0 means disabled.
void IRFujitsuAC::setOffTimer(const uint16_t nr_mins) {
setOffSleepTimer(nr_mins);
setOffSleepTimer(nr_mins); // This will also set _rawstatemodified to true.
if (nr_mins)
_.TimerType = kFujitsuAcOffTimer;
else if (getTimerType() != kFujitsuAcOnTimer)
@ -672,7 +697,7 @@ void IRFujitsuAC::setOffTimer(const uint16_t nr_mins) {
/// Set the Sleep Timer time for the A/C.
/// @param[in] nr_mins Nr. of minutes to set the timer to. 0 means disabled.
void IRFujitsuAC::setSleepTimer(const uint16_t nr_mins) {
setOffSleepTimer(nr_mins);
setOffSleepTimer(nr_mins); // This will also set _rawstatemodified to true.
if (nr_mins)
_.TimerType = kFujitsuAcSleepTimer;
else if (getTimerType() != kFujitsuAcOnTimer)
@ -706,7 +731,10 @@ bool IRFujitsuAC::validChecksum(uint8_t state[], const uint16_t length) {
/// Set the device's remote ID number.
/// @param[in] num The ID for the remote. Valid number range is 0 to 3.
void IRFujitsuAC::setId(const uint8_t num) { _.Id = num; }
void IRFujitsuAC::setId(const uint8_t num) {
_.Id = num;
_rawstatemodified = true;
}
/// Get the current device's remote ID number.
/// @return The current device's remote ID number.
@ -714,7 +742,10 @@ uint8_t IRFujitsuAC::getId(void) const { return _.Id; }
/// Set the Temperature units for the A/C.
/// @param[in] on true, use Celsius. false, use Fahrenheit.
void IRFujitsuAC::setCelsius(const bool on) { _.Fahrenheit = !on; }
void IRFujitsuAC::setCelsius(const bool on) {
_.Fahrenheit = !on;
_rawstatemodified = true;
}
/// Get the Clean mode status of the A/C.
/// @return true, the setting is on. false, the setting is off.
@ -774,35 +805,45 @@ stdAc::fanspeed_t IRFujitsuAC::toCommonFanSpeed(const uint8_t speed) {
}
/// Convert the current internal state into its stdAc::state_t equivalent.
/// @param[in] prev Ptr to a previous state.
/// @return The stdAc equivalent of the native settings.
stdAc::state_t IRFujitsuAC::toCommon(void) const {
stdAc::state_t IRFujitsuAC::toCommon(const stdAc::state_t *prev) {
stdAc::state_t result{};
if (prev != NULL) result = *prev;
result.protocol = decode_type_t::FUJITSU_AC;
checkSum();
result.model = _model;
result.power = getPower();
result.mode = toCommonMode(_.Mode);
result.celsius = getCelsius();
result.degrees = getTemp();
result.fanspeed = toCommonFanSpeed(_.Fan);
uint8_t swing = _.Swing;
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
: stdAc::swingh_t::kOff;
break;
case fujitsu_ac_remote_model_t::ARDB1:
case fujitsu_ac_remote_model_t::ARJW2:
default:
result.swingv = stdAc::swingv_t::kOff;
result.swingh = stdAc::swingh_t::kOff;
// Only update these settings if it is a long message, or we have no previous
// state info for those settings.
if (isLongCode() || prev == NULL) {
result.mode = toCommonMode(_.Mode);
result.celsius = getCelsius();
{
const float minHeat = result.celsius ? kFujitsuAcMinHeat
: kFujitsuAcMinHeatF;
result.degrees = get10CHeat() ? minHeat : getTemp();
}
result.fanspeed = toCommonFanSpeed(_.Fan);
uint8_t swing = _.Swing;
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
: stdAc::swingh_t::kOff;
break;
case fujitsu_ac_remote_model_t::ARDB1:
case fujitsu_ac_remote_model_t::ARJW2:
default:
result.swingv = stdAc::swingv_t::kOff;
result.swingh = stdAc::swingh_t::kOff;
}
}
result.quiet = _.Fan == kFujitsuAcFanQuiet;
result.turbo = _cmd == kFujitsuAcCmdPowerful;
result.econo = _cmd == kFujitsuAcCmdEcono;
@ -820,54 +861,67 @@ stdAc::state_t IRFujitsuAC::toCommon(void) const {
/// @return A human readable string.
String IRFujitsuAC::toString(void) const {
String result = "";
result.reserve(100); // Reserve some heap for the string to reduce fragging.
result.reserve(180); // Reserve some heap for the string to reduce fragging.
fujitsu_ac_remote_model_t model = _model;
result += addModelToString(decode_type_t::FUJITSU_AC, model, false);
result += addIntToString(_.Id, kIdStr);
result += addBoolToString(getPower(), kPowerStr);
result += addModeToString(_.Mode, kFujitsuAcModeAuto, kFujitsuAcModeCool,
kFujitsuAcModeHeat, kFujitsuAcModeDry,
kFujitsuAcModeFan);
result += addTempFloatToString(getTemp(), getCelsius());
result += addFanToString(_.Fan, kFujitsuAcFanHigh, kFujitsuAcFanLow,
kFujitsuAcFanAuto, kFujitsuAcFanQuiet,
kFujitsuAcFanMed);
switch (model) {
// 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;
// These models have Clean & Filter, plus Swing (via fall thru)
case fujitsu_ac_remote_model_t::ARRAH2E:
case fujitsu_ac_remote_model_t::ARREB1E:
case fujitsu_ac_remote_model_t::ARRY4:
result += addBoolToString(getClean(), kCleanStr);
result += addBoolToString(getFilter(), kFilterStr);
// FALL THRU
default: // e.g. ARREW4E
if (model == fujitsu_ac_remote_model_t::ARREW4E)
result += addBoolToString(get10CHeat(), k10CHeatStr);
result += addIntToString(_.Swing, kSwingStr);
result += kSpaceLBraceStr;
switch (_.Swing) {
case kFujitsuAcSwingOff:
result += kOffStr;
break;
case kFujitsuAcSwingVert:
result += kSwingVStr;
break;
case kFujitsuAcSwingHoriz:
result += kSwingHStr;
break;
case kFujitsuAcSwingBoth:
result += kSwingVStr;
result += '+';
result += kSwingHStr;
break;
default:
result += kUnknownStr;
}
result += ')';
if (_rawstatemodified || isLongCode()) {
result += addModeToString(_.Mode, kFujitsuAcModeAuto, kFujitsuAcModeCool,
kFujitsuAcModeHeat, kFujitsuAcModeDry,
kFujitsuAcModeFan);
{
const bool isCelsius = getCelsius();
const float minHeat = isCelsius ? kFujitsuAcMinHeat : kFujitsuAcMinHeatF;
result += addTempFloatToString(get10CHeat() ? minHeat : getTemp(),
isCelsius);
}
result += addFanToString(_.Fan, kFujitsuAcFanHigh, kFujitsuAcFanLow,
kFujitsuAcFanAuto, kFujitsuAcFanQuiet,
kFujitsuAcFanMed);
switch (model) {
// 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;
// These models have Clean & Filter, plus Swing (via fall thru)
case fujitsu_ac_remote_model_t::ARRAH2E:
case fujitsu_ac_remote_model_t::ARREB1E:
case fujitsu_ac_remote_model_t::ARRY4:
result += addBoolToString(getClean(), kCleanStr);
result += addBoolToString(getFilter(), kFilterStr);
// FALL THRU
default: // e.g. ARREW4E
switch (model) {
case fujitsu_ac_remote_model_t::ARRAH2E:
case fujitsu_ac_remote_model_t::ARREW4E:
result += addBoolToString(get10CHeat(), k10CHeatStr);
break;
default:
break;
}
result += addIntToString(_.Swing, kSwingStr);
result += kSpaceLBraceStr;
switch (_.Swing) {
case kFujitsuAcSwingOff:
result += kOffStr;
break;
case kFujitsuAcSwingVert:
result += kSwingVStr;
break;
case kFujitsuAcSwingHoriz:
result += kSwingHStr;
break;
case kFujitsuAcSwingBoth:
result += kSwingVStr;
result += '+';
result += kSwingHStr;
break;
default:
result += kUnknownStr;
}
result += ')';
}
}
result += kCommaSpaceStr;
result += kCommandStr;
@ -902,33 +956,36 @@ String IRFujitsuAC::toString(void) const {
default:
result += kNAStr;
}
uint16_t mins = 0;
String type_str = kTimerStr;
switch (model) {
case fujitsu_ac_remote_model_t::ARREB1E:
case fujitsu_ac_remote_model_t::ARREW4E:
result += addBoolToString(getOutsideQuiet(), kOutsideQuietStr);
// FALL THRU
// These models seem to have timer support.
case fujitsu_ac_remote_model_t::ARRAH2E:
switch (getTimerType()) {
case kFujitsuAcOnTimer:
type_str = kOnTimerStr;
mins = getOnTimer();
break;
case kFujitsuAcOffTimer:
type_str = kOffTimerStr;
mins = getOffSleepTimer();
break;
case kFujitsuAcSleepTimer:
type_str = kSleepTimerStr;
mins = getOffSleepTimer();
break;
}
result += addLabeledString(mins ? minsToString(mins) : kOffStr, type_str);
break;
default:
break;
if (_rawstatemodified || isLongCode()) {
uint16_t mins = 0;
String type_str = kTimerStr;
switch (model) {
case fujitsu_ac_remote_model_t::ARREB1E:
case fujitsu_ac_remote_model_t::ARREW4E:
result += addBoolToString(getOutsideQuiet(), kOutsideQuietStr);
// FALL THRU
// These models seem to have timer support.
case fujitsu_ac_remote_model_t::ARRAH2E:
switch (getTimerType()) {
case kFujitsuAcOnTimer:
type_str = kOnTimerStr;
mins = getOnTimer();
break;
case kFujitsuAcOffTimer:
type_str = kOffTimerStr;
mins = getOffSleepTimer();
break;
case kFujitsuAcSleepTimer:
type_str = kSleepTimerStr;
mins = getOffSleepTimer();
break;
}
result += addLabeledString(mins ? minsToString(mins) : kOffStr,
type_str);
break;
default:
break;
}
}
return result;
}

View File

@ -1,5 +1,5 @@
// Copyright 2017 Jonny Graham
// Copyright 2018-2021 David Conran
// Copyright 2018-2022 David Conran
// Copyright 2021 siriuslzx
/// @file
@ -30,6 +30,7 @@
// Brand: Fujitsu, Model: AR-DL10 remote (ARDB1)
// Brand: Fujitsu, Model: ASU30C1 A/C (ARDB1)
// Brand: Fujitsu, Model: AR-RAH1U remote (ARREB1E)
// Brand: Fujitsu, Model: AR-RAH2U remote (ARRAH2E)
// Brand: Fujitsu, Model: ASU12RLF A/C (ARREB1E)
// Brand: Fujitsu, Model: AR-REW4E remote (ARREW4E)
// Brand: Fujitsu, Model: ASYG09KETA-B A/C (ARREW4E)
@ -37,6 +38,9 @@
// Brand: Fujitsu, Model: ASTG09K A/C (ARREW4E)
// Brand: Fujitsu, Model: ASTG18K A/C (ARREW4E)
// Brand: Fujitsu, Model: AR-REW1E remote (ARREW4E)
// Brand: Fujitsu, Model: AR-REG1U remote (ARRAH2E)
// Brand: OGeneral, Model: AR-RCL1E remote (ARRAH2E)
// Brand: Fujitsu General, Model: AR-JW17 remote (ARDB1)
#ifndef IR_FUJITSU_H_
#define IR_FUJITSU_H_
@ -128,9 +132,11 @@ const uint8_t kFujitsuAcFanMed = 0x02;
const uint8_t kFujitsuAcFanLow = 0x03;
const uint8_t kFujitsuAcFanQuiet = 0x04;
const float kFujitsuAcMinHeat = 10; // 10C
const float kFujitsuAcMinTemp = 16; // 16C
const float kFujitsuAcMaxTemp = 30; // 30C
const uint8_t kFujitsuAcTempOffsetC = kFujitsuAcMinTemp;
const float kFujitsuAcMinHeatF = 50; // 50F
const float kFujitsuAcMinTempF = 60; // 60F
const float kFujitsuAcMaxTempF = 88; // 88F
const uint8_t kFujitsuAcTempOffsetF = 44;
@ -206,6 +212,7 @@ class IRFujitsuAC {
bool setRaw(const uint8_t newState[], const uint16_t length);
uint8_t getStateLength(void);
static bool validChecksum(uint8_t* state, const uint16_t length);
bool isLongCode(void) const;
void setPower(const bool on);
void off(void);
void on(void);
@ -233,7 +240,7 @@ class IRFujitsuAC {
static uint8_t convertFan(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) const;
stdAc::state_t toCommon(const stdAc::state_t *prev = NULL);
String toString(void) const;
#ifndef UNIT_TEST
@ -249,6 +256,7 @@ class IRFujitsuAC {
fujitsu_ac_remote_model_t _model;
uint8_t _state_length;
uint8_t _state_length_short;
bool _rawstatemodified;
void checkSum(void);
bool updateUseLongOrShort(void);
void buildFromState(const uint16_t length);

View File

@ -162,6 +162,7 @@ void IRGreeAC::setRaw(const uint8_t new_code[]) {
else
_model = gree_ac_remote_model_t::YBOFB;
}
if (_.Mode == kGreeEcono) _model = gree_ac_remote_model_t::YX1FSF;
}
/// Calculate and set the checksum values for the internal state.
@ -186,7 +187,8 @@ bool IRGreeAC::validChecksum(const uint8_t state[], const uint16_t 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;
case gree_ac_remote_model_t::YBOFB:
case gree_ac_remote_model_t::YX1FSF: _model = model; break;
default: _model = gree_ac_remote_model_t::YAW1F;
}
}
@ -291,6 +293,7 @@ void IRGreeAC::setMode(const uint8_t new_mode) {
case kGreeDry: setFan(1); break;
case kGreeCool:
case kGreeFan:
case kGreeEcono:
case kGreeHeat: break;
// If we get an unexpected mode, default to AUTO.
default: mode = kGreeAuto;
@ -352,11 +355,17 @@ bool IRGreeAC::getTurbo(void) const { return _.Turbo; }
/// Set the Econo setting of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRGreeAC::setEcono(const bool on) { _.Econo = on; }
void IRGreeAC::setEcono(const bool on) {
_.Econo = on;
if (on && getModel() == gree_ac_remote_model_t::YX1FSF)
setMode(kGreeEcono);
}
/// Get the Econo setting of the A/C.
/// @return true, the setting is on. false, the setting is off.
bool IRGreeAC::getEcono(void) const { return _.Econo; }
bool IRGreeAC::getEcono(void) const {
return _.Econo || getMode() == kGreeEcono;
}
/// Set the Vertical Swing mode of the A/C.
/// @param[in] automatic Do we use the automatic setting?
@ -589,7 +598,7 @@ stdAc::state_t IRGreeAC::toCommon(void) {
result.swingv = toCommonSwingV(_.SwingV);
result.swingh = toCommonSwingH(_.SwingH);
result.turbo = _.Turbo;
result.econo = _.Econo;
result.econo = getEcono();
result.light = _.Light;
result.clean = _.Xfan;
result.sleep = _.Sleep ? 0 : -1;
@ -608,8 +617,15 @@ String IRGreeAC::toString(void) {
result.reserve(220); // Reserve some heap for the string to reduce fragging.
result += addModelToString(decode_type_t::GREE, _model, false);
result += addBoolToString(_.Power, kPowerStr);
result += addModeToString(_.Mode, kGreeAuto, kGreeCool, kGreeHeat,
kGreeDry, kGreeFan);
if (_model == gree_ac_remote_model_t::YX1FSF && _.Mode == kGreeEcono) {
result += addIntToString(_.Mode, kModeStr);
result += kSpaceLBraceStr;
result += kEconoStr;
result += ')';
} else {
result += addModeToString(_.Mode, kGreeAuto, kGreeCool, kGreeHeat,
kGreeDry, kGreeFan);
}
result += addTempToString(getTemp(), !_.UseFahrenheit);
result += addFanToString(_.Fan, kGreeFanMax, kGreeFanMin, kGreeFanAuto,
kGreeFanAuto, kGreeFanMed);

View File

@ -1,9 +1,10 @@
// Copyright 2016 David Conran
// Copyright 2016-2022 David Conran
/// @file
/// @brief Support for Gree A/C protocols.
/// @see https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.h
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1508
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1821
// Supports:
// Brand: Ultimate, Model: Heat Pump
@ -15,6 +16,7 @@
// Brand: Gree, Model: YAA1FBF remote
// Brand: Gree, Model: YB1F2F remote
// Brand: Gree, Model: YAN1F1 remote
// Brand: Gree, Model: YX1F2F remote (YX1FSF)
// Brand: Gree, Model: VIR09HP115V1AH A/C
// Brand: Gree, Model: VIR12HP230V1AH A/C
// Brand: Amana, Model: PBC093G00CC A/C
@ -23,6 +25,7 @@
// Brand: Cooper & Hunter, Model: CH-S09FTXG A/C
// Brand: Vailland, Model: YACIFB remote
// Brand: Vailland, Model: VAI5-035WNI A/C
// Brand: Soleus Air, Model: window A/C (YX1FSF)
#ifndef IR_GREE_H_
#define IR_GREE_H_
@ -86,11 +89,12 @@ union GreeProtocol{
// Constants
const uint8_t kGreeAuto = 0;
const uint8_t kGreeCool = 1;
const uint8_t kGreeDry = 2;
const uint8_t kGreeFan = 3;
const uint8_t kGreeHeat = 4;
const uint8_t kGreeAuto = 0;
const uint8_t kGreeCool = 1;
const uint8_t kGreeDry = 2;
const uint8_t kGreeFan = 3;
const uint8_t kGreeHeat = 4;
const uint8_t kGreeEcono = 5;
const uint8_t kGreeFanAuto = 0;
const uint8_t kGreeFanMin = 1;

View File

@ -46,7 +46,8 @@ using irutils::minsToString;
_.x##Mins = mins % 60;\
} while (0)
#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02 || SEND_HAIER_AC176)
#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02 || SEND_HAIER_AC160 || \
SEND_HAIER_AC176)
/// Send a Haier A/C formatted message. (HSU07-HEA03 remote)
/// Status: STABLE / Known to be working.
/// @param[in] data The message to be sent.
@ -93,6 +94,18 @@ void IRsend::sendHaierAC176(const unsigned char data[], const uint16_t nbytes,
}
#endif // SEND_HAIER_AC176
#if SEND_HAIER_AC160
/// Send a Haier 160 bit remote A/C formatted message.
/// Status: STABLE / Known to be working.
/// @param[in] data The message to be sent.
/// @param[in] nbytes The number of bytes of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
void IRsend::sendHaierAC160(const unsigned char data[], const uint16_t nbytes,
const uint16_t repeat) {
if (nbytes >= kHaierAC160StateLength) sendHaierAC(data, nbytes, repeat);
}
#endif // SEND_HAIER_AC160
/// Class constructor
/// @param[in] pin GPIO to be used when sending.
/// @param[in] inverted Is the output signal to be inverted?
@ -568,7 +581,7 @@ void IRHaierAC176::checksum(void) {
/// @return true, if the state has a valid checksum. Otherwise, false.
bool IRHaierAC176::validChecksum(const uint8_t state[], const uint16_t length) {
if (length < 2) return false; // 1 byte of data can't have a checksum.
if (length < kHaierAC176StateLength) { // Is it too short?
if (length < kHaierAC160StateLength) { // Is it too short?
// Then it is just a checksum of the whole thing.
return (state[length - 1] == sumBytes(state, length - 1));
} else { // It is long enough for two checksums.
@ -1323,7 +1336,8 @@ bool IRHaierACYRW02::validChecksum(const uint8_t state[],
}
// End of IRHaierACYRW02 class.
#if (DECODE_HAIER_AC || DECODE_HAIER_AC_YRW02)
#if (DECODE_HAIER_AC || DECODE_HAIER_AC_YRW02 || DECODE_HAIER_AC160 || \
DECODE_HAIER_AC176)
/// Decode the supplied Haier HSU07-HEA03 remote message.
/// Status: STABLE / Known to be working.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
@ -1435,3 +1449,721 @@ bool IRrecv::decodeHaierAC176(decode_results* results, uint16_t offset,
return true;
}
#endif // DECODE_HAIER_AC176
#if DECODE_HAIER_AC160
/// Decode the supplied Haier 160 bit remote A/C message.
/// Status: STABLE / Known to be working.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// result.
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
bool IRrecv::decodeHaierAC160(decode_results* results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (strict) {
if (nbits != kHaierAC160Bits)
return false; // Not strictly a HAIER_AC160 message.
}
// The protocol is almost exactly the same as HAIER_AC
if (!decodeHaierAC(results, offset, nbits, false)) return false;
// Compliance
if (strict) {
if (!IRHaierAC176::validChecksum(results->state, nbits / 8)) return false;
}
// Success
// It looks correct, but we haven't check the checksum etc.
results->decode_type = HAIER_AC160;
return true;
}
#endif // DECODE_HAIER_AC160
/// Class constructor
/// @param[in] pin GPIO to be used when sending.
/// @param[in] inverted Is the output signal to be inverted?
/// @param[in] use_modulation Is frequency modulation to be used?
IRHaierAC160::IRHaierAC160(const uint16_t pin, const bool inverted,
const bool use_modulation)
: _irsend(pin, inverted, use_modulation) { stateReset(); }
/// Set up hardware to be able to send a message.
void IRHaierAC160::begin(void) { _irsend.begin(); }
#if SEND_HAIER_AC160
/// Send the current internal state as an IR message.
/// @param[in] repeat Nr. of times the message will be repeated.
void IRHaierAC160::send(const uint16_t repeat) {
_irsend.sendHaierAC160(getRaw(), kHaierAC160StateLength, repeat);
}
#endif // SEND_HAIER_AC160
/// Calculate and set the checksum values for the internal state.
void IRHaierAC160::checksum(void) {
_.Sum = sumBytes(_.raw, kHaierACYRW02StateLength - 1);
_.Sum2 = sumBytes(_.raw + kHaierACYRW02StateLength,
kHaierAC160StateLength - kHaierACYRW02StateLength - 1);
}
/// Reset the internal state to a fixed known good state.
void IRHaierAC160::stateReset(void) {
std::memset(_.raw, 0, sizeof _.raw);
_.Model = kHaierAcYrw02ModelA;
_.Prefix = kHaierAc160Prefix;
_.Temp = kHaierAcYrw02DefTempC - kHaierAcYrw02MinTempC;
setClean(false);
setFan(kHaierAcYrw02FanAuto);
_.Power = true;
_.Button = kHaierAcYrw02ButtonPower;
}
/// Get a PTR to the internal state/code for this protocol.
/// @return PTR to a code for this protocol based on the current internal state.
uint8_t* IRHaierAC160::getRaw(void) {
checksum();
return _.raw;
}
/// Set the internal state from a valid code for this protocol.
/// @param[in] new_code A valid code for this protocol.
void IRHaierAC160::setRaw(const uint8_t new_code[]) {
memcpy(_.raw, new_code, kHaierAC160StateLength);
}
/// Set the Button/Command setting of the A/C.
/// @param[in] button The value of the button/command that was pressed.
void IRHaierAC160::setButton(uint8_t button) {
switch (button) {
case kHaierAcYrw02ButtonTempUp:
case kHaierAcYrw02ButtonTempDown:
case kHaierAcYrw02ButtonSwingV:
case kHaierAcYrw02ButtonSwingH:
case kHaierAcYrw02ButtonFan:
case kHaierAcYrw02ButtonPower:
case kHaierAcYrw02ButtonMode:
case kHaierAcYrw02ButtonHealth:
case kHaierAcYrw02ButtonTurbo:
case kHaierAcYrw02ButtonSleep:
case kHaierAcYrw02ButtonLock:
case kHaierAc160ButtonClean:
case kHaierAcYrw02ButtonCFAB:
_.Button = button;
}
}
/// Get the Button/Command setting of the A/C.
/// @return The value of the button/command that was pressed.
uint8_t IRHaierAC160::getButton(void) const { return _.Button; }
/// Set the operating mode of the A/C.
/// @param[in] mode The desired operating mode.
void IRHaierAC160::setMode(uint8_t mode) {
switch (mode) {
case kHaierAcYrw02Auto:
case kHaierAcYrw02Dry:
case kHaierAcYrw02Fan:
// Turbo & Quiet is only available in Cool/Heat mode.
_.Turbo = false;
_.Quiet = false;
// FALL-THRU
case kHaierAcYrw02Cool:
case kHaierAcYrw02Heat:
_.Button = kHaierAcYrw02ButtonMode;
_.Mode = mode;
break;
default:
setMode(kHaierAcYrw02Auto); // Unexpected, default to auto mode.
}
_.AuxHeating = (_.Mode == kHaierAcYrw02Heat); // Set only if heat mode.
}
/// Get the operating mode setting of the A/C.
/// @return The current operating mode setting.
uint8_t IRHaierAC160::getMode(void) const { return _.Mode; }
/// Set the default temperature units to use.
/// @param[in] on Use Fahrenheit as the units.
/// true is Fahrenheit, false is Celsius.
void IRHaierAC160::setUseFahrenheit(const bool on) { _.UseFahrenheit = on; }
/// Get the default temperature units in use.
/// @return true is Fahrenheit, false is Celsius.
bool IRHaierAC160::getUseFahrenheit(void) const { return _.UseFahrenheit; }
/// Set the temperature.
/// @param[in] degree The temperature in degrees.
/// @param[in] fahrenheit Use units of Fahrenheit and set that as units used.
void IRHaierAC160::setTemp(const uint8_t degree, const bool fahrenheit) {
uint8_t old_temp = getTemp();
if (old_temp == degree) return;
if (_.UseFahrenheit == fahrenheit) {
if (old_temp > degree)
_.Button = kHaierAcYrw02ButtonTempDown;
else
_.Button = kHaierAcYrw02ButtonTempUp;
} else {
_.Button = kHaierAcYrw02ButtonCFAB;
}
_.UseFahrenheit = fahrenheit;
uint8_t temp = degree;
if (fahrenheit) {
if (temp < kHaierAcYrw02MinTempF)
temp = kHaierAcYrw02MinTempF;
else if (temp > kHaierAcYrw02MaxTempF)
temp = kHaierAcYrw02MaxTempF;
if (degree >= 77) { temp++; }
if (degree >= 79) { temp++; }
// See at IRHaierAC160::getTemp() comments for clarification
_.ExtraDegreeF = temp % 2;
_.Temp = (temp - kHaierAcYrw02MinTempF -_.ExtraDegreeF) >> 1;
} else {
if (temp < kHaierAcYrw02MinTempC)
temp = kHaierAcYrw02MinTempC;
else if (temp > kHaierAcYrw02MaxTempC)
temp = kHaierAcYrw02MaxTempC;
_.Temp = temp - kHaierAcYrw02MinTempC;
}
}
/// Get the current temperature setting.
/// The unit of temperature is specified by UseFahrenheit value.
/// @return The current setting for temperature.
uint8_t IRHaierAC160::getTemp(void) const {
if (!_.UseFahrenheit) { return _.Temp + kHaierAcYrw02MinTempC; }
uint8_t degree = _.Temp*2 + kHaierAcYrw02MinTempF + _.ExtraDegreeF;
// The way of coding the temperature in degree Fahrenheit is
// kHaierAcYrw02MinTempF + Temp*2 + ExtraDegreeF, for example
// Temp = 0b0011, ExtraDegreeF = 0b1, temperature is 60 + 3*2 + 1 = 67F
// But around 78F there is unconsistency, see table below
//
// | Fahrenheit | Temp | ExtraDegreeF |
// | 60F | 0b0000 | 0b0 |
// | 61F | 0b0000 | 0b1 |
// | 62F | 0b0001 | 0b0 |
// | 63F | 0b0001 | 0b1 |
// | 64F | 0b0010 | 0b0 |
// | 65F | 0b0010 | 0b1 |
// | 66F | 0b0011 | 0b0 |
// | 67F | 0b0011 | 0b1 |
// | 68F | 0b0100 | 0b0 |
// | 69F | 0b0100 | 0b1 |
// | 70F | 0b0101 | 0b0 |
// | 71F | 0b0101 | 0b1 |
// | 72F | 0b0110 | 0b0 |
// | 73F | 0b0110 | 0b1 |
// | 74F | 0b0111 | 0b0 |
// | 75F | 0b0111 | 0b1 |
// | 76F | 0b1000 | 0b0 |
// | Not Used | 0b1000 | 0b1 |
// | 77F | 0b1001 | 0b0 |
// | Not Used | 0b1001 | 0b1 |
// | 78F | 0b1010 | 0b0 |
// | 79F | 0b1010 | 0b1 |
// | 80F | 0b1011 | 0b0 |
// | 81F | 0b1011 | 0b1 |
// | 82F | 0b1100 | 0b0 |
// | 83F | 0b1100 | 0b1 |
// | 84F | 0b1101 | 0b0 |
// | 86F | 0b1110 | 0b0 |
// | 85F | 0b1101 | 0b1 |
if (degree >= 77) { degree--; }
if (degree >= 79) { degree--; }
return degree;
}
/// Set the Clean setting of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRHaierAC160::setClean(const bool on) {
_.Button = kHaierAc160ButtonClean;
_.Clean = on;
_.Clean2 = on;
}
/// Get the Clean setting of the A/C.
/// @return true, the setting is on. false, the setting is off.
bool IRHaierAC160::getClean(void) const { return _.Clean && _.Clean2; }
/// Get the value of the current power setting.
/// @return true, the setting is on. false, the setting is off.
bool IRHaierAC160::getPower(void) const { return _.Power; }
/// Change the power setting.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRHaierAC160::setPower(const bool on) {
_.Button = kHaierAcYrw02ButtonPower;
_.Power = on;
}
/// Change the power setting to On.
void IRHaierAC160::on(void) { setPower(true); }
/// Change the power setting to Off.
void IRHaierAC160::off(void) { setPower(false); }
/// Get the Sleep setting of the A/C.
/// @return true, the setting is on. false, the setting is off.
bool IRHaierAC160::getSleep(void) const { return _.Sleep; }
/// Set the Sleep setting of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRHaierAC160::setSleep(const bool on) {
_.Button = kHaierAcYrw02ButtonSleep;
_.Sleep = on;
}
/// Get the Turbo setting of the A/C.
/// @return The current turbo setting.
bool IRHaierAC160::getTurbo(void) const { return _.Turbo; }
/// Set the Turbo setting of the A/C.
/// @param[in] on The desired turbo setting.
/// @note Turbo & Quiet can't be on at the same time, and only in Heat/Cool mode
void IRHaierAC160::setTurbo(const bool on) {
switch (getMode()) {
case kHaierAcYrw02Cool:
case kHaierAcYrw02Heat:
_.Turbo = on;
_.Button = kHaierAcYrw02ButtonTurbo;
if (on) _.Quiet = false;
}
}
/// Get the Quiet setting of the A/C.
/// @return The current Quiet setting.
bool IRHaierAC160::getQuiet(void) const { return _.Quiet; }
/// Set the Quiet setting of the A/C.
/// @param[in] on The desired Quiet setting.
/// @note Turbo & Quiet can't be on at the same time, and only in Heat/Cool mode
void IRHaierAC160::setQuiet(const bool on) {
switch (getMode()) {
case kHaierAcYrw02Cool:
case kHaierAcYrw02Heat:
_.Quiet = on;
_.Button = kHaierAcYrw02ButtonTurbo;
if (on) _.Turbo = false;
}
}
/// Get the value of the Aux Heating setting.
/// @return true, the setting is on. false, the setting is off.
bool IRHaierAC160::getAuxHeating(void) const { return _.AuxHeating; }
/// Change the Aux Heating setting.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRHaierAC160::setAuxHeating(const bool on) {
_.Button = kHaierAc160ButtonAuxHeating;
_.AuxHeating = on;
}
/// Get the value of the current Light toggle setting.
/// @return true, the setting is on. false, the setting is off.
/// @note This setting seems to be controlled just by the button setting.
bool IRHaierAC160::getLightToggle(void) const {
return _.Button == kHaierAc160ButtonLight;
}
/// Set the Light Toggle setting of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
/// @note This setting seems to be controlled just by the button setting.
void IRHaierAC160::setLightToggle(const bool on) {
_.Button = on ? kHaierAc160ButtonLight : kHaierAcYrw02ButtonPower;
}
/// Get the current fan speed setting.
/// @return The current fan speed.
uint8_t IRHaierAC160::getFan(void) const { return _.Fan; }
/// Set the speed of the fan.
/// @param[in] speed The desired setting.
void IRHaierAC160::setFan(uint8_t speed) {
switch (speed) {
case kHaierAcYrw02FanLow:
case kHaierAcYrw02FanMed:
case kHaierAcYrw02FanHigh:
case kHaierAcYrw02FanAuto:
_.Fan = speed;
_.Fan2 = (speed == kHaierAcYrw02FanAuto) ? 0 : speed;
_.Button = kHaierAcYrw02ButtonFan;
}
}
/// Set the Health (filter) setting of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRHaierAC160::setHealth(const bool on) {
_.Button = kHaierAcYrw02ButtonHealth;
_.Health = on;
}
/// Get the Health (filter) setting of the A/C.
/// @return true, the setting is on. false, the setting is off.
bool IRHaierAC160::getHealth(void) const { return _.Health; }
/// Get the Vertical Swing position setting of the A/C.
/// @return The native position/mode.
uint8_t IRHaierAC160::getSwingV(void) const { return _.SwingV; }
/// Set the Vertical Swing mode of the A/C.
/// @param[in] pos The position/mode to set the vanes to.
void IRHaierAC160::setSwingV(const uint8_t pos) {
switch (pos) {
case kHaierAc160SwingVOff:
case kHaierAc160SwingVAuto:
case kHaierAc160SwingVTop:
case kHaierAc160SwingVHighest:
case kHaierAc160SwingVHigh:
case kHaierAc160SwingVMiddle:
case kHaierAc160SwingVLow:
case kHaierAc160SwingVLowest:
_.Button = kHaierAcYrw02ButtonSwingV;
_.SwingV = pos;
break;
default: return; // If in doubt, Do nothing.
}
}
/// Set the Timer operating mode.
/// @param[in] mode The timer mode to use.
void IRHaierAC160::setTimerMode(const uint8_t mode) {
_.TimerMode = (mode > kHaierAcYrw02OffThenOnTimer) ? kHaierAcYrw02NoTimers
: mode;
switch (_.TimerMode) {
case kHaierAcYrw02NoTimers:
setOnTimer(0); // Disable the On timer.
setOffTimer(0); // Disable the Off timer.
break;
case kHaierAcYrw02OffTimer:
setOnTimer(0); // Disable the On timer.
break;
case kHaierAcYrw02OnTimer:
setOffTimer(0); // Disable the Off timer.
break;
}
}
/// Get the Timer operating mode.
/// @return The mode of the timer is currently configured to.
uint8_t IRHaierAC160::getTimerMode(void) const { return _.TimerMode; }
/// Set the number of minutes of the On Timer setting.
/// @param[in] mins Nr. of Minutes for the Timer. `0` means disable the timer.
void IRHaierAC160::setOnTimer(const uint16_t mins) {
const uint16_t nr_mins = std::min((uint16_t)(23 * 60 + 59), mins);
_.OnTimerHrs = nr_mins / 60;
_.OnTimerMins = nr_mins % 60;
const bool enabled = (nr_mins > 0);
uint8_t mode = getTimerMode();
switch (mode) {
case kHaierAcYrw02OffTimer:
mode = enabled ? kHaierAcYrw02OffThenOnTimer : mode;
break;
case kHaierAcYrw02OnThenOffTimer:
case kHaierAcYrw02OffThenOnTimer:
mode = enabled ? kHaierAcYrw02OffThenOnTimer : kHaierAcYrw02OffTimer;
break;
default:
// Enable/Disable the On timer for the simple case.
mode = enabled << 1;
}
_.TimerMode = mode;
}
/// Get the number of minutes of the On Timer setting.
/// @return Nr of minutes.
uint16_t IRHaierAC160::getOnTimer(void) const {
return _.OnTimerHrs * 60 + _.OnTimerMins;
}
/// Set the number of minutes of the Off Timer setting.
/// @param[in] mins Nr. of Minutes for the Timer. `0` means disable the timer.
void IRHaierAC160::setOffTimer(const uint16_t mins) {
const uint16_t nr_mins = std::min((uint16_t)(23 * 60 + 59), mins);
_.OffTimerHrs = nr_mins / 60;
_.OffTimerMins = nr_mins % 60;
const bool enabled = (nr_mins > 0);
uint8_t mode = getTimerMode();
switch (mode) {
case kHaierAcYrw02OnTimer:
mode = enabled ? kHaierAcYrw02OnThenOffTimer : mode;
break;
case kHaierAcYrw02OnThenOffTimer:
case kHaierAcYrw02OffThenOnTimer:
mode = enabled ? kHaierAcYrw02OnThenOffTimer : kHaierAcYrw02OnTimer;
break;
default:
// Enable/Disable the Off timer for the simple case.
mode = enabled;
}
_.TimerMode = mode;
}
/// Get the number of minutes of the Off Timer setting.
/// @return Nr of minutes.
uint16_t IRHaierAC160::getOffTimer(void) const {
return _.OffTimerHrs * 60 + _.OffTimerMins;
}
/// Get the Lock setting of the A/C.
/// @return true, the setting is on. false, the setting is off.
bool IRHaierAC160::getLock(void) const { return _.Lock; }
/// Set the Lock setting of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRHaierAC160::setLock(const bool on) {
_.Button = kHaierAcYrw02ButtonLock;
_.Lock = on;
}
/// Convert a stdAc::opmode_t enum into its native mode.
/// @param[in] mode The enum to be converted.
/// @return The native equivalent of the enum.
uint8_t IRHaierAC160::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;
}
}
/// Convert a stdAc::fanspeed_t enum into it's native speed.
/// @param[in] speed The enum to be converted.
/// @return The native equivalent of the enum.
uint8_t IRHaierAC160::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::kHigh:
case stdAc::fanspeed_t::kMax: return kHaierAcYrw02FanHigh;
default: return kHaierAcYrw02FanAuto;
}
}
/// Convert a stdAc::swingv_t enum into it's native setting.
/// @param[in] position The enum to be converted.
/// @return The native equivalent of the enum.
uint8_t IRHaierAC160::convertSwingV(const stdAc::swingv_t position) {
switch (position) {
case stdAc::swingv_t::kHighest: return kHaierAc160SwingVTop;
case stdAc::swingv_t::kHigh: return kHaierAc160SwingVHigh;
case stdAc::swingv_t::kMiddle: return kHaierAc160SwingVMiddle;
case stdAc::swingv_t::kLow: return kHaierAc160SwingVLow;
case stdAc::swingv_t::kLowest: return kHaierAc160SwingVLowest;
case stdAc::swingv_t::kOff: return kHaierAc160SwingVOff;
default: return kHaierAc160SwingVAuto;
}
}
/// Convert a native mode into its stdAc equivalent.
/// @param[in] mode The native setting to be converted.
/// @return The stdAc equivalent of the native setting.
stdAc::opmode_t IRHaierAC160::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;
}
}
/// Convert a native fan speed into its stdAc equivalent.
/// @param[in] speed The native setting to be converted.
/// @return The stdAc equivalent of the native setting.
stdAc::fanspeed_t IRHaierAC160::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;
}
}
/// Convert a stdAc::swingv_t enum into it's native setting.
/// @param[in] pos The enum to be converted.
/// @return The native equivalent of the enum.
stdAc::swingv_t IRHaierAC160::toCommonSwingV(const uint8_t pos) {
switch (pos) {
case kHaierAc160SwingVTop:
case kHaierAc160SwingVHighest: return stdAc::swingv_t::kHighest;
case kHaierAc160SwingVHigh: return stdAc::swingv_t::kHigh;
case kHaierAc160SwingVMiddle: return stdAc::swingv_t::kMiddle;
case kHaierAc160SwingVLow: return stdAc::swingv_t::kLow;
case kHaierAc160SwingVLowest: return stdAc::swingv_t::kLowest;
case kHaierAc160SwingVOff: return stdAc::swingv_t::kOff;
default: return stdAc::swingv_t::kAuto;
}
}
/// Convert the current internal state into its stdAc::state_t equivalent.
/// @param[in] prev Ptr to the previous state if required.
/// @return The stdAc equivalent of the native settings.
stdAc::state_t IRHaierAC160::toCommon(const stdAc::state_t *prev) const {
stdAc::state_t result{};
// Start with the previous state if given it.
if (prev != NULL) {
result = *prev;
} else {
// Set defaults for non-zero values that are not implicitly set for when
// there is no previous state.
// e.g. Any setting that toggles should probably go here.
result.light = false;
}
result.protocol = decode_type_t::HAIER_AC160;
result.power = _.Power;
result.mode = toCommonMode(_.Mode);
result.celsius = !_.UseFahrenheit;
result.degrees = getTemp();
result.fanspeed = toCommonFanSpeed(_.Fan);
result.swingv = toCommonSwingV(_.SwingV);
result.swingh = stdAc::swingh_t::kOff;
result.sleep = _.Sleep ? 0 : -1;
result.turbo = _.Turbo;
result.quiet = _.Quiet;
result.clean = _.Clean && _.Clean2;
result.light ^= getLightToggle();
result.filter = _.Health;
// Not supported.
result.model = -1;
result.econo = false;
result.beep = true;
result.clock = -1;
return result;
}
/// Convert the current internal state into a human readable string.
/// @return A human readable string.
String IRHaierAC160::toString(void) const {
String result = "";
result.reserve(280); // Reserve some heap for the string to reduce fragging.
result += addBoolToString(_.Power, kPowerStr, false);
uint8_t cmd = _.Button;
result += addIntToString(cmd, kButtonStr);
result += kSpaceLBraceStr;
switch (cmd) {
case kHaierAcYrw02ButtonPower:
result += kPowerStr;
break;
case kHaierAcYrw02ButtonMode:
result += kModeStr;
break;
case kHaierAcYrw02ButtonFan:
result += kFanStr;
break;
case kHaierAcYrw02ButtonTempUp:
result += kTempUpStr;
break;
case kHaierAcYrw02ButtonTempDown:
result += kTempDownStr;
break;
case kHaierAcYrw02ButtonSleep:
result += kSleepStr;
break;
case kHaierAcYrw02ButtonHealth:
result += kHealthStr;
break;
case kHaierAcYrw02ButtonSwingV:
result += kSwingVStr;
break;
case kHaierAcYrw02ButtonSwingH:
result += kSwingHStr;
break;
case kHaierAcYrw02ButtonTurbo:
result += kTurboStr;
break;
case kHaierAcYrw02ButtonTimer:
result += kTimerStr;
break;
case kHaierAcYrw02ButtonLock:
result += kLockStr;
break;
case kHaierAc160ButtonClean:
result += kCleanStr;
break;
case kHaierAc160ButtonLight:
result += kLightStr;
break;
case kHaierAc160ButtonAuxHeating:
result += kHeatingStr;
break;
case kHaierAcYrw02ButtonCFAB:
result += kCelsiusFahrenheitStr;
break;
default:
result += kUnknownStr;
}
result += ')';
result += addModeToString(_.Mode, kHaierAcYrw02Auto, kHaierAcYrw02Cool,
kHaierAcYrw02Heat, kHaierAcYrw02Dry,
kHaierAcYrw02Fan);
result += addTempToString(getTemp(), !_.UseFahrenheit);
result += addFanToString(_.Fan, kHaierAcYrw02FanHigh, kHaierAcYrw02FanLow,
kHaierAcYrw02FanAuto, kHaierAcYrw02FanAuto,
kHaierAcYrw02FanMed);
result += addBoolToString(_.Turbo, kTurboStr);
result += addBoolToString(_.Quiet, kQuietStr);
result += addBoolToString(_.Health, kHealthStr);
result += addIntToString(_.SwingV, kSwingVStr);
result += kSpaceLBraceStr;
switch (_.SwingV) {
case kHaierAc160SwingVOff: result += kOffStr; break;
case kHaierAc160SwingVAuto: result += kAutoStr; break;
case kHaierAc160SwingVTop: result += kTopStr; break;
case kHaierAc160SwingVHighest: result += kHighestStr; break;
case kHaierAc160SwingVHigh: result += kHighStr; break;
case kHaierAc160SwingVMiddle: result += kMiddleStr; break;
case kHaierAc160SwingVLow: result += kLowStr; break;
case kHaierAc160SwingVLowest: result += kLowestStr; break;
default: result += kUnknownStr;
}
result += ')';
result += addBoolToString(_.Sleep, kSleepStr);
result += addBoolToString(getClean(), kCleanStr);
const uint8_t tmode = getTimerMode();
result += addIntToString(tmode, kTimerModeStr);
result += kSpaceLBraceStr;
switch (tmode) {
case kHaierAcYrw02NoTimers:
result += kNAStr;
break;
case kHaierAcYrw02OnTimer:
result += kOnStr;
break;
case kHaierAcYrw02OffTimer:
result += kOffStr;
break;
case kHaierAcYrw02OnThenOffTimer:
result += kOnStr;
result += '-';
result += kOffStr;
break;
case kHaierAcYrw02OffThenOnTimer:
result += kOffStr;
result += '-';
result += kOnStr;
break;
default:
result += kUnknownStr;
}
result += ')';
result += addLabeledString((tmode != kHaierAcYrw02NoTimers &&
tmode != kHaierAcYrw02OffTimer) ?
minsToString(getOnTimer()) : kOffStr, kOnTimerStr);
result += addLabeledString((tmode != kHaierAcYrw02NoTimers &&
tmode != kHaierAcYrw02OnTimer) ?
minsToString(getOffTimer()) : kOffStr, kOffTimerStr);
result += addBoolToString(_.Lock, kLockStr);
result += addBoolToString(_.AuxHeating, kHeatingStr);
return result;
}
// End of IRHaierAC160 class.

View File

@ -8,6 +8,7 @@
/// @see https://www.dropbox.com/s/mecyib3lhdxc8c6/IR%20data%20reverse%20engineering.xlsx?dl=0
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/485
/// @see https://www.dropbox.com/sh/w0bt7egp0fjger5/AADRFV6Wg4wZskJVdFvzb8Z0a?dl=0&preview=haer2.ods
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1804
// Supports:
// Brand: Haier, Model: HSU07-HEA03 remote (HAIER_AC)
@ -17,6 +18,7 @@
// Brand: Mabe, Model: MMI18HDBWCA6MI8 A/C (HAIER_AC176)
// Brand: Mabe, Model: V12843 HJ200223 remote (HAIER_AC176)
// Brand: Daichi, Model: D-H A/C (HAIER_AC176)
// Brand: Haier, Model: KFR-26GW/83@UI-Ge A/C (HAIER_AC160)
#ifndef IR_HAIER_H_
#define IR_HAIER_H_
@ -144,6 +146,7 @@ const uint8_t kHaierAcYrw02DefTempC = 25;
const uint8_t kHaierAcYrw02ModelA = 0xA6;
const uint8_t kHaierAcYrw02ModelB = 0x59;
const uint8_t kHaierAc176Prefix = 0xB7;
const uint8_t kHaierAc160Prefix = 0xB5;
const uint8_t kHaierAcYrw02SwingVOff = 0x0;
const uint8_t kHaierAcYrw02SwingVTop = 0x1;
@ -152,6 +155,15 @@ const uint8_t kHaierAcYrw02SwingVBottom = 0x3; // Only available in heat mode.
const uint8_t kHaierAcYrw02SwingVDown = 0xA;
const uint8_t kHaierAcYrw02SwingVAuto = 0xC; // Airflow
const uint8_t kHaierAc160SwingVOff = 0b0000;
const uint8_t kHaierAc160SwingVTop = 0b0001;
const uint8_t kHaierAc160SwingVHighest = 0b0010;
const uint8_t kHaierAc160SwingVHigh = 0b0100;
const uint8_t kHaierAc160SwingVMiddle = 0b0110;
const uint8_t kHaierAc160SwingVLow = 0b1000;
const uint8_t kHaierAc160SwingVLowest = 0b0011;
const uint8_t kHaierAc160SwingVAuto = 0b1100; // Airflow
const uint8_t kHaierAcYrw02SwingHMiddle = 0x0;
const uint8_t kHaierAcYrw02SwingHLeftMax = 0x3;
const uint8_t kHaierAcYrw02SwingHLeft = 0x4;
@ -182,6 +194,9 @@ const uint8_t kHaierAcYrw02ButtonTurbo = 0b01000;
const uint8_t kHaierAcYrw02ButtonSleep = 0b01011;
const uint8_t kHaierAcYrw02ButtonTimer = 0b10000;
const uint8_t kHaierAcYrw02ButtonLock = 0b10100;
const uint8_t kHaierAc160ButtonLight = 0b10101;
const uint8_t kHaierAc160ButtonAuxHeating = 0b10110;
const uint8_t kHaierAc160ButtonClean = 0b11001;
const uint8_t kHaierAcYrw02ButtonCFAB = 0b11010;
const uint8_t kHaierAcYrw02NoTimers = 0b000;
@ -260,6 +275,75 @@ union HaierAc176Protocol{
};
};
/// Native representation of a Haier 160 bit A/C message.
union HaierAc160Protocol{
uint8_t raw[kHaierAC160StateLength]; ///< The state in native form
struct {
// Byte 0
uint8_t Model :8;
// Byte 1
uint8_t SwingV :4;
uint8_t Temp :4; // 16C~30C
// Byte 2
uint8_t :5;
uint8_t SwingH :3;
// Byte 3
uint8_t :1;
uint8_t Health :1;
uint8_t :3;
uint8_t TimerMode :3;
// Byte 4
uint8_t :6;
uint8_t Power :1;
uint8_t AuxHeating :1;
// Byte 5
uint8_t OffTimerHrs :5;
uint8_t Fan :3;
// Byte 6
uint8_t OffTimerMins:6;
uint8_t Turbo :1;
uint8_t Quiet :1;
// Byte 7
uint8_t OnTimerHrs :5;
uint8_t Mode :3;
// Byte 8
uint8_t OnTimerMins :6;
uint8_t :1;
uint8_t Sleep :1;
// Byte 9
uint8_t :8;
// Byte 10
uint8_t ExtraDegreeF :1;
uint8_t :3;
uint8_t Clean :1;
uint8_t UseFahrenheit:1;
uint8_t :2;
// Byte 11
uint8_t :8;
// Byte 12
uint8_t Button :5;
uint8_t Lock :1;
uint8_t :2;
// Byte 13
uint8_t Sum :8;
// Byte 14
uint8_t Prefix :8;
// Byte 15
uint8_t :6;
uint8_t Clean2 :1;
uint8_t :1;
// Byte 16
uint8_t :5;
uint8_t Fan2 :3;
// Byte 17
uint8_t :8;
// Byte 18
uint8_t :8;
// Byte 19
uint8_t Sum2 :8;
};
};
// Legacy Haier YRW02 remote defines.
#define HAIER_AC_YRW02_SWING_OFF kHaierAcYrw02SwingOff
#define HAIER_AC_YRW02_SWING_TOP kHaierAcYrw02SwingTop
@ -474,4 +558,96 @@ class IRHaierACYRW02 : public IRHaierAC176 {
const uint8_t state[],
const uint16_t length = kHaierACYRW02StateLength);
};
/// Class for handling detailed Haier 160 bit A/C messages.
class IRHaierAC160 {
public:
explicit IRHaierAC160(const uint16_t pin, const bool inverted = false,
const bool use_modulation = true);
#if SEND_HAIER_AC160
virtual void send(const uint16_t repeat = kHaierAc160DefaultRepeat);
/// Run the calibration to calculate uSec timing offsets for this platform.
/// @return The uSec timing offset needed per modulation of the IR Led.
/// @note This will produce a 65ms IR signal pulse at 38kHz.
/// Only ever needs to be run once per object instantiation, if at all.
int8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_HAIER_AC160
void begin(void);
void stateReset(void);
void setButton(const uint8_t button);
uint8_t getButton(void) const;
void setUseFahrenheit(const bool on);
bool getUseFahrenheit(void) const;
void setTemp(const uint8_t temp, const bool fahrenheit = false);
uint8_t getTemp(void) const;
void setFan(const uint8_t speed);
uint8_t getFan(void) const;
uint8_t getMode(void) const;
void setMode(const uint8_t mode);
bool getPower(void) const;
void setPower(const bool on);
void on(void);
void off(void);
bool getSleep(void) const;
void setSleep(const bool on);
bool getClean(void) const;
void setClean(const bool on);
bool getLightToggle(void) const;
void setLightToggle(const bool on);
bool getTurbo(void) const;
void setTurbo(const bool on);
bool getQuiet(void) const;
void setQuiet(const bool on);
bool getAuxHeating(void) const;
void setAuxHeating(const bool on);
uint8_t getSwingV(void) const;
void setSwingV(const uint8_t pos);
void setTimerMode(const uint8_t setting);
uint8_t getTimerMode(void) const;
void setOnTimer(const uint16_t mins);
uint16_t getOnTimer(void) const;
void setOffTimer(const uint16_t mins);
uint16_t getOffTimer(void) const;
bool getLock(void) const;
void setLock(const bool on);
bool getHealth(void) const;
void setHealth(const bool on);
uint8_t* getRaw(void);
virtual void setRaw(const uint8_t new_code[]);
static bool validChecksum(const uint8_t state[],
const uint16_t length = kHaierAC160StateLength);
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);
static bool toCommonTurbo(const uint8_t speed);
static bool toCommonQuiet(const uint8_t speed);
stdAc::state_t toCommon(const stdAc::state_t *prev = NULL) const;
String toString(void) const;
#ifndef UNIT_TEST
private:
IRsend _irsend; ///< Instance of the IR send class
#else // UNIT_TEST
/// @cond IGNORE
IRsendTest _irsend; ///< Instance of the testing IR send class
/// @endcond
#endif // UNIT_TEST
HaierAc160Protocol _;
void checksum(void);
};
#endif // IR_HAIER_H_

View File

@ -23,8 +23,10 @@
// Brand: Danby, Model: DAC100BGUWDB (MIDEA)
// Brand: Danby, Model: DAC120BGUWDB (MIDEA)
// Brand: Danby, Model: R09C/BCGE remote (MIDEA)
// Brand: Trotec, Model: TROTEC PAC 2100 X (MIDEA)
// Brand: Trotec, Model: TROTEC PAC 3900 X (MIDEA)
// Brand: Trotec, Model: RG57H(B)/BGE remote (MIDEA)
// Brand: Trotec, Model: RG57H3(B)/BGCEF-M remote (MIDEA)
// Brand: Lennox, Model: RG57A6/BGEFU1 remote (MIDEA)
// Brand: Lennox, Model: MWMA009S4-3P A/C (MIDEA)
// Brand: Lennox, Model: MWMA012S4-3P A/C (MIDEA)

View File

@ -14,6 +14,8 @@
// Brand: Duux, Model: Blizzard Smart 10K / DXMA04 A/C
// Brand: Duux, Model: YJ-A081 TR Remote
// Brand: Silan Microelectronics, Model: SC6121-001 IC
// Brand: BBK, Model: SP550S 5.1 sound system
// Brand: Tanix, Model: TX3 mini Android TV Box
#ifndef IR_NEC_H_
#define IR_NEC_H_

View File

@ -12,6 +12,7 @@
// Supports:
// Brand: Samsung, Model: UA55H6300 TV (SAMSUNG)
// Brand: Samsung, Model: BN59-01178B TV remote (SAMSUNG)
// Brand: Samsung, Model: UE40K5510AUXRU TV (SAMSUNG)
// Brand: Samsung, Model: DB63-03556X003 remote
// Brand: Samsung, Model: DB93-16761C remote
// Brand: Samsung, Model: IEC-R03 remote

View File

@ -77,6 +77,14 @@ const uint32_t kSanyoAc88Gap = 3675; ///< uSeconds
const uint16_t kSanyoAc88Freq = 38000; ///< Hz. (Guess only)
const uint8_t kSanyoAc88ExtraTolerance = 5; /// (%) Extra tolerance to use.
const uint16_t kSanyoAc152HdrMark = 3300; ///< uSeconds
const uint16_t kSanyoAc152BitMark = 440; ///< uSeconds
const uint16_t kSanyoAc152HdrSpace = 1725; ///< uSeconds
const uint16_t kSanyoAc152OneSpace = 1290; ///< uSeconds
const uint16_t kSanyoAc152ZeroSpace = 405; ///< uSeconds
const uint16_t kSanyoAc152Freq = 38000; ///< Hz. (Guess only)
const uint8_t kSanyoAc152ExtraTolerance = 13; /// (%) Extra tolerance to use.
#if SEND_SANYO
/// Construct a Sanyo LC7461 message.
/// @param[in] address The 13 bit value of the address(Custom) portion of the
@ -687,7 +695,7 @@ void IRsend::sendSanyoAc88(const uint8_t data[], const uint16_t nbytes,
#endif // SEND_SANYO_AC88
#if DECODE_SANYO_AC88
/// Decode the supplied SanyoAc message.
/// Decode the supplied SanyoAc88 message.
/// Status: ALPHA / Untested.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// @warning data's bit order may change. It is not yet confirmed.
@ -976,3 +984,61 @@ String IRSanyoAc88::toString(void) const {
result += addLabeledString(minsToString(getClock()), kClockStr);
return result;
}
#if SEND_SANYO_AC152
/// Send a SanyoAc152 formatted message.
/// Status: BETA / Probably works.
/// @param[in] data An array of bytes containing the IR command.
/// @warning data's bit order may change. It is not yet confirmed.
/// @param[in] nbytes Nr. of bytes of data in the array.
/// @param[in] repeat Nr. of times the message is to be repeated.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1826
void IRsend::sendSanyoAc152(const uint8_t data[], const uint16_t nbytes,
const uint16_t repeat) {
// (Header + Data + Footer) per repeat
sendGeneric(kSanyoAc152HdrMark, kSanyoAc152HdrSpace,
kSanyoAc152BitMark, kSanyoAc152OneSpace,
kSanyoAc152BitMark, kSanyoAc152ZeroSpace,
kSanyoAc152BitMark, kDefaultMessageGap,
data, nbytes, kSanyoAc152Freq, false, repeat, kDutyDefault);
space(kDefaultMessageGap); // Make a guess at a post message gap.
}
#endif // SEND_SANYO_AC152
#if DECODE_SANYO_AC152
/// Decode the supplied SanyoAc152 message.
/// Status: BETA / Probably works.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// @warning data's bit order may change. It is not yet confirmed.
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1503
bool IRrecv::decodeSanyoAc152(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (strict && nbits != kSanyoAc152Bits)
return false;
// Header + Data + Footer
if (!matchGeneric(results->rawbuf + offset, results->state,
results->rawlen - offset, nbits,
kSanyoAc152HdrMark, kSanyoAc152HdrSpace,
kSanyoAc152BitMark, kSanyoAc152OneSpace,
kSanyoAc152BitMark, kSanyoAc152ZeroSpace,
kSanyoAc152BitMark,
kDefaultMessageGap, // Just a guess.
false, _tolerance + kSanyoAc152ExtraTolerance,
kMarkExcess, false))
return false; // No match!
// Success
results->decode_type = decode_type_t::SANYO_AC152;
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_SANYO_AC152

View File

@ -13,6 +13,7 @@
/// @see https://docs.google.com/spreadsheets/d/1dYfLsnYvpjV-SgO8pdinpfuBIpSzm8Q1R5SabrLeskw/edit?usp=sharing
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1503
/// @see https://docs.google.com/spreadsheets/d/1weUmGAsEpfX38gg5rlDN69Uchnbr6gQl9FqHffLBIRk/edit#gid=0
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1826
// Supports:
// Brand: Sanyo, Model: SA 8650B - disabled
@ -21,6 +22,8 @@
// Brand: Sanyo, Model: RCS-2HS4E remote (SANYO_AC)
// Brand: Sanyo, Model: SAP-K242AH A/C (SANYO_AC)
// Brand: Sanyo, Model: RCS-2S4E remote (SANYO_AC)
// Brand: Sanyo, Model: RCS-4MHVPIS4EE remote (SANYO_AC152)
// Brand: Sanyo, Model: SAP-KMRV124EHE A/C (SANYO_AC152)
#ifndef IR_SANYO_H_
#define IR_SANYO_H_

View File

@ -11,6 +11,7 @@
// Supports:
// Brand: Sony, Model: HT-CT380 Soundbar (Uses 38kHz & 3 repeats)
// Brand: Sony, Model: HT-SF150 Soundbar (Uses 38kHz & 3 repeats)
#include <algorithm>
#include "IRrecv.h"

View File

@ -1,4 +1,4 @@
// Copyright 2019, 2021 David Conran
// Copyright 2019, 2021, 2022 David Conran
/// @file
/// @brief Support for TCL protocols.
@ -14,10 +14,19 @@
#include "IRutils.h"
// Constants
const uint8_t kTcl112AcTimerResolution = 20; // Minutes
const uint16_t kTcl112AcTimerMax = 720; // Minutes (12 hrs)
const uint16_t kTcl96AcHdrMark = 1056; // uSeconds.
const uint16_t kTcl96AcHdrSpace = 550; // uSeconds.
const uint16_t kTcl96AcBitMark = 600; // uSeconds.
const uint32_t kTcl96AcGap = kDefaultMessageGap; // Just a guess.
const uint8_t kTcl96AcSpaceCount = 4;
const uint16_t kTcl96AcBitSpaces[kTcl96AcSpaceCount] = {360, // 0b00
838, // 0b01
2182, // 0b10
1444}; // 0b11
using irutils::addBoolToString;
using irutils::addFanToString;
using irutils::addIntToString;
@ -527,3 +536,81 @@ String IRTcl112Ac::toString(void) const {
/// It's the same as `decodeMitsubishi112()`. A shared routine is used.
/// You can find it in: ir_Mitsubishi.cpp
#endif // DECODE_TCL112AC
#if SEND_TCL96AC
/// Send a TCL 96-bit A/C message.
/// Status: BETA / Untested on a real device working.
/// @param[in] data The message to be sent.
/// @param[in] nbytes The number of bytes of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
void IRsend::sendTcl96Ac(const unsigned char data[], const uint16_t nbytes,
const uint16_t repeat) {
enableIROut(38);
for (uint16_t r = 0; r <= repeat; r++) {
// Header
mark(kTcl96AcHdrMark);
space(kTcl96AcHdrSpace);
// Data
for (uint16_t pos = 0; pos < nbytes; pos++) {
uint8_t databyte = data[pos];
for (uint8_t bits = 0; bits < 8; bits += 2) {
mark(kTcl96AcBitMark);
space(kTcl96AcBitSpaces[GETBITS8(databyte, 8 - 2, 2)]);
databyte <<= 2;
}
}
// Footer
mark(kTcl96AcBitMark);
space(kTcl96AcGap);
}
}
#endif // SEND_TCL96AC
#if DECODE_TCL96AC
/// Decode the supplied Tcl96Ac message.
/// Status: ALPHA / Experimental.
/// @param[in,out] results Ptr to the data to decode & where to store the result
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return True if it can decode it, false if it can't.
bool IRrecv::decodeTcl96Ac(decode_results* results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < nbits + kHeader + kFooter - 1 + offset)
return false; // Message is smaller than we expected.
if (strict && nbits != kTcl96AcBits)
return false; // Not strictly a TCL96AC message.
uint8_t data = 0;
// Header.
if (!matchMark(results->rawbuf[offset++], kTcl96AcHdrMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kTcl96AcHdrSpace)) return false;
// Data (2 bits at a time)
for (uint16_t bits_so_far = 0; bits_so_far < nbits; bits_so_far += 2) {
if (bits_so_far % 8)
data <<= 2; // Make space for the new data bits.
else
data = 0;
if (!matchMark(results->rawbuf[offset++], kTcl96AcBitMark)) return false;
uint8_t value = 0;
while (value < kTcl96AcSpaceCount) {
if (matchSpace(results->rawbuf[offset], kTcl96AcBitSpaces[value])) {
data += value;
break;
}
value++;
}
if (value >= kTcl96AcSpaceCount) return false; // No matches.
offset++;
*(results->state + bits_so_far / 8) = data;
}
// Footer
if (!matchMark(results->rawbuf[offset++], kTcl96AcBitMark)) return false;
if (offset < results->rawlen &&
!matchAtLeast(results->rawbuf[offset], kTcl96AcGap)) return false;
// Success
results->decode_type = TCL96AC;
results->bits = nbits;
return true;
}
#endif // DECODE_TCL96AC

View File

@ -10,6 +10,7 @@
// Brand: Teknopoint, Model: GZ-055B-E1 remote (GZ055BE1)
// Brand: Daewoo, Model: DSB-F0934ELH-V A/C
// Brand: Daewoo, Model: GYKQ-52E remote
// Brand: TCL, Model: GYKQ-58(XM) remote (TCL96AC)
#ifndef IR_TCL_H_
#define IR_TCL_H_

View File

@ -0,0 +1,131 @@
// Copyright 2022 David Conran (crankyoldgit)
/// @file
/// @brief Support for the Toto Toilet IR protocols.
/// @see https://www.d-resi.jp/dt/nishi-shinjuku/limited/imgs/pdf/book6.pdf
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1806
// Supports:
// Brand: Toto, Model: Washlet Toilet NJ
#include <algorithm>
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
// Constants
const uint16_t kTotoHdrMark = 6197;
const uint16_t kTotoHdrSpace = 2754;
const uint16_t kTotoBitMark = 600;
const uint16_t kTotoOneSpace = 1634;
const uint16_t kTotoZeroSpace = 516;
const uint16_t kTotoGap = 38000;
const uint16_t kTotoSpecialGap = 42482;
const uint64_t kTotoPrefix = 0x0802;
const uint16_t kTotoPrefixBits = 15;
#if SEND_TOTO
/// Send a Toto Toilet formatted message.
/// Status: BETA / Seems to work.
/// @param[in] data The message to be sent.
/// @param[in] nbits The number of bits of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1806
void IRsend::sendToto(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
if (nbits <= kTotoShortBits) { // Short code message.
sendGeneric(kTotoHdrMark, kTotoHdrSpace,
kTotoBitMark, kTotoOneSpace,
kTotoBitMark, kTotoZeroSpace,
kTotoBitMark, kTotoGap,
(data << kTotoPrefixBits) | kTotoPrefix,
nbits + kTotoPrefixBits,
38, false, repeat, kDutyDefault);
} else { // Long code message
// This is really two messages sent at least one extra time each.
sendToto(data >> kTotoShortBits, nbits - kTotoShortBits, repeat + 1);
sendToto(GETBITS64(data, 0, kTotoShortBits), kTotoShortBits, repeat + 1);
}
}
#endif // SEND_TOTO
#if DECODE_TOTO
/// Decode the supplied Toto Toilet message.
/// Status: ALPHA / Untested.
/// @param[in,out] results Ptr to the data to decode & where to store the result
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return True if it can decode it, false if it can't.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1806
bool IRrecv::decodeToto(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (strict && nbits != kTotoShortBits && nbits != kTotoLongBits)
return false; // We expect Toto to be a certain sized messages.
const uint16_t repeats = (nbits > kTotoShortBits) ? kTotoDefaultRepeat + 1
: kTotoDefaultRepeat;
const uint16_t ksections = (nbits > kTotoShortBits) ? 2 : 1;
const uint16_t ksection_bits = nbits / ksections;
if (results->rawlen < (2 * (nbits + kTotoPrefixBits) + kHeader + kFooter) *
(repeats + 1) - 1 + offset)
return false; // We don't have enough entries to possibly match.
uint16_t used = 0;
// Long messages have two sections, short have only one.
for (uint16_t section = 1; section <= ksections; section++) {
results->value <<= ksection_bits;
uint64_t data = 0;
uint64_t repeat_data = 0;
for (uint16_t r = 0; r <= repeats; r++) { // We expect a repeat.
uint64_t prefix = 0;
// Header + Prefix
used = matchGeneric(results->rawbuf + offset, &prefix,
results->rawlen - offset, kTotoPrefixBits,
kTotoHdrMark, kTotoHdrSpace,
kTotoBitMark, kTotoOneSpace,
kTotoBitMark, kTotoZeroSpace,
0, 0, false, // No Footer
kUseDefTol, kMarkExcess, false);
if (!used) return false; // Didn't match, so fail.
offset += used;
if (strict && (prefix != kTotoPrefix)) return false;
// Data + Footer + Gap
used = matchGeneric(results->rawbuf + offset, &data,
results->rawlen - offset, ksection_bits,
0, 0, // No Header
kTotoBitMark, kTotoOneSpace,
kTotoBitMark, kTotoZeroSpace,
kTotoBitMark, kTotoGap, true,
kUseDefTol, kMarkExcess, false);
if (!used) return false; // Didn't match, so fail.
offset += used;
if (strict) {
if (r && data != repeat_data) return false; // Repeat didn't match.
// Integrity check.
uint8_t result = 0;
uint64_t check = data;
uint16_t bits = 0;
// Loop over the data 8 bits at a time.
while (bits < ksection_bits) {
result ^= (check & 0b111111111); // Xor with the last 8 bits.
bits += 8;
check >>= 8;
}
if (result) return false; // Intergrity check failed.
}
repeat_data = data;
}
results->value |= data;
}
// Success
results->bits = nbits;
results->decode_type = decode_type_t::TOTO;
results->command = GETBITS64(results->value, 0, ksection_bits - 8);
results->address = GETBITS64(results->value, ksection_bits,
ksection_bits - 8);
return true;
}
#endif // DECODE_TOTO

View File

@ -9,6 +9,7 @@
//
// Ref: https://docs.google.com/spreadsheets/d/1zzDEUQ52y7MZ7_xCU3pdjdqbRXOwZLsbTGvKWcicqCI/
// Ref: https://www.corona.co.jp/box/download.php?id=145060636229
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/files/8646964/Voltas.Window.AC.122LZF.Remote.Instructions.pdf
#ifndef IR_VOLTAS_H_
#define IR_VOLTAS_H_

View File

@ -566,6 +566,9 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_YBOFB
#define D_STR_YBOFB "YBOFB"
#endif // D_STR_YBOFB
#ifndef D_STR_YX1FSF
#define D_STR_YX1FSF "YX1FSF"
#endif // D_STR_YX1FSF
#ifndef D_STR_V9014557_A
#define D_STR_V9014557_A "V9014557-A"
#endif // D_STR_V9014557_A
@ -706,6 +709,12 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_ARRIS
#define D_STR_ARRIS "ARRIS"
#endif // D_STR_ARRIS
#ifndef D_STR_BOSCH
#define D_STR_BOSCH "BOSCH"
#endif // D_STR_BOSCH
#ifndef D_STR_BOSCH144
#define D_STR_BOSCH144 D_STR_BOSCH "144"
#endif // D_STR_BOSCH144
#ifndef D_STR_BOSE
#define D_STR_BOSE "BOSE"
#endif // D_STR_BOSE
@ -718,6 +727,12 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_CARRIER_AC64
#define D_STR_CARRIER_AC64 D_STR_CARRIER_AC "64"
#endif // D_STR_CARRIER_AC64
#ifndef D_STR_CARRIER_AC128
#define D_STR_CARRIER_AC128 D_STR_CARRIER_AC "128"
#endif // D_STR_CARRIER_AC128
#ifndef D_STR_CLIMABUTLER
#define D_STR_CLIMABUTLER "CLIMABUTLER"
#endif // D_STR_CLIMABUTLER
#ifndef D_STR_COOLIX
#define D_STR_COOLIX "COOLIX"
#endif // D_STR_COOLIX
@ -731,25 +746,31 @@ D_STR_INDIRECT " " D_STR_MODE
#define D_STR_DAIKIN "DAIKIN"
#endif // D_STR_DAIKIN
#ifndef D_STR_DAIKIN128
#define D_STR_DAIKIN128 "DAIKIN128"
#define D_STR_DAIKIN128 D_STR_DAIKIN "128"
#endif // D_STR_DAIKIN128
#ifndef D_STR_DAIKIN152
#define D_STR_DAIKIN152 "DAIKIN152"
#define D_STR_DAIKIN152 D_STR_DAIKIN "152"
#endif // D_STR_DAIKIN152
#ifndef D_STR_DAIKIN160
#define D_STR_DAIKIN160 "DAIKIN160"
#define D_STR_DAIKIN160 D_STR_DAIKIN "160"
#endif // D_STR_DAIKIN160
#ifndef D_STR_DAIKIN176
#define D_STR_DAIKIN176 "DAIKIN176"
#define D_STR_DAIKIN176 D_STR_DAIKIN "176"
#endif // D_STR_DAIKIN176
#ifndef D_STR_DAIKIN2
#define D_STR_DAIKIN2 "DAIKIN2"
#define D_STR_DAIKIN2 D_STR_DAIKIN "2"
#endif // D_STR_DAIKIN2
#ifndef D_STR_DAIKIN200
#define D_STR_DAIKIN200 D_STR_DAIKIN "200"
#endif // D_STR_DAIKIN200
#ifndef D_STR_DAIKIN216
#define D_STR_DAIKIN216 "DAIKIN216"
#define D_STR_DAIKIN216 D_STR_DAIKIN "216"
#endif // D_STR_DAIKIN216
#ifndef D_STR_DAIKIN312
#define D_STR_DAIKIN312 D_STR_DAIKIN "312"
#endif // D_STR_DAIKIN312
#ifndef D_STR_DAIKIN64
#define D_STR_DAIKIN64 "DAIKIN64"
#define D_STR_DAIKIN64 D_STR_DAIKIN "64"
#endif // D_STR_DAIKIN64
#ifndef D_STR_DELONGHI_AC
#define D_STR_DELONGHI_AC "DELONGHI_AC"
@ -794,10 +815,13 @@ D_STR_INDIRECT " " D_STR_MODE
#define D_STR_HAIER_AC "HAIER_AC"
#endif // D_STR_HAIER_AC
#ifndef D_STR_HAIER_AC_YRW02
#define D_STR_HAIER_AC_YRW02 "HAIER_AC_YRW02"
#define D_STR_HAIER_AC_YRW02 D_STR_HAIER_AC "_YRW02"
#endif // D_STR_HAIER_AC_YRW02
#ifndef D_STR_HAIER_AC160
#define D_STR_HAIER_AC160 D_STR_HAIER_AC "160"
#endif // D_STR_HAIER_AC160
#ifndef D_STR_HAIER_AC176
#define D_STR_HAIER_AC176 "HAIER_AC176"
#define D_STR_HAIER_AC176 D_STR_HAIER_AC "176"
#endif // D_STR_HAIER_AC176
#ifndef D_STR_HITACHI_AC
#define D_STR_HITACHI_AC "HITACHI_AC"
@ -959,13 +983,16 @@ D_STR_INDIRECT " " D_STR_MODE
#define D_STR_SANYO "SANYO"
#endif // D_STR_SANYO
#ifndef D_STR_SANYO_AC
#define D_STR_SANYO_AC "SANYO_AC"
#define D_STR_SANYO_AC D_STR_SANYO "_AC"
#endif // D_STR_SANYO_AC
#ifndef D_STR_SANYO_AC88
#define D_STR_SANYO_AC88 "SANYO_AC88"
#define D_STR_SANYO_AC88 D_STR_SANYO_AC "88"
#endif // D_STR_SANYO_AC88
#ifndef D_STR_SANYO_AC152
#define D_STR_SANYO_AC152 D_STR_SANYO_AC "152"
#endif // D_STR_SANYO_AC152
#ifndef D_STR_SANYO_LC7461
#define D_STR_SANYO_LC7461 "SANYO_LC7461"
#define D_STR_SANYO_LC7461 D_STR_SANYO "_LC7461"
#endif // D_STR_SANYO_LC7461
#ifndef D_STR_SHARP
#define D_STR_SHARP "SHARP"
@ -985,6 +1012,9 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_SYMPHONY
#define D_STR_SYMPHONY "SYMPHONY"
#endif // D_STR_SYMPHONY
#ifndef D_STR_TCL96AC
#define D_STR_TCL96AC "TCL96AC"
#endif // D_STR_TCL96AC
#ifndef D_STR_TCL112AC
#define D_STR_TCL112AC "TCL112AC"
#endif // D_STR_TCL112AC
@ -1000,6 +1030,9 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_TOSHIBA_AC
#define D_STR_TOSHIBA_AC "TOSHIBA_AC"
#endif // D_STR_TOSHIBA_AC
#ifndef D_STR_TOTO
#define D_STR_TOTO "TOTO"
#endif // D_STR_TOTO
#ifndef D_STR_TRANSCOLD
#define D_STR_TRANSCOLD "TRANSCOLD"
#endif // D_STR_TRANSCOLD

View File

@ -623,9 +623,9 @@ TEST(TestIRac, Fujitsu) {
"Model: 2 (ARDB1), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, "
"Fan: 2 (Medium), Command: N/A";
std::string arrah2e_expected =
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, "
"Fan: 2 (Medium), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Sleep Timer: 03:00";
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 10C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: On, "
"Swing: 0 (Off), Command: N/A, Sleep Timer: 03:00";
std::string arry4_expected =
"Model: 5 (ARRY4), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, "
"Fan: 2 (Medium), Clean: On, Filter: On, Swing: 0 (Off), Command: N/A";
@ -658,20 +658,21 @@ TEST(TestIRac, Fujitsu) {
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p));
ac._irsend.reset();
// Try to set the device to 10C Heat mode.
irac.fujitsu(&ac,
ARRAH2E, // Model
true, // Power
stdAc::opmode_t::kCool, // Mode
stdAc::opmode_t::kFan, // Mode (Fan needed for 10C Heat)
true, // Celsius
19, // Degrees
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
19, // Degrees (Ignored in 10C Heat)
stdAc::fanspeed_t::kAuto, // Fan speed (Auto needed for 10C)
stdAc::swingv_t::kOff, // Vertical swing (Ditto)
stdAc::swingh_t::kOff, // Horizontal swing (Ditto)
false, // Quiet
false, // Turbo (Powerful)
false, // Econo
true, // Filter
true, // Clean
true, // Clean (Needed for 10C Heat)
3 * 60); // Sleep
ASSERT_EQ(arrah2e_expected, ac.toString());
ac._irsend.makeDecodeResult();
@ -819,6 +820,41 @@ TEST(TestIRac, Haier) {
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p));
}
TEST(TestIRac, Haier160) {
IRHaierAC160 ac(kGpioUnused);
IRac irac(kGpioUnused);
IRrecv capture(kGpioUnused);
const char expected[] =
"Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 23C, "
"Fan: 2 (Medium), Turbo: On, Quiet: Off, Health: On, "
"Swing(V): 4 (High), Sleep: On, "
"Clean: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, "
"Lock: Off, Heating: Off";
ac.begin();
irac.haier160(&ac,
true, // Power
stdAc::opmode_t::kCool, // Mode
true, // Celsius
23, // Degrees
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kHigh, // Vertical swing
true, // Turbo
false, // Quiet
true, // Filter/Health
true, // Clean
true, // Light
true, // Light (prev)
8 * 60 + 0); // Sleep time
ASSERT_EQ(expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(HAIER_AC160, ac._irsend.capture.decode_type);
ASSERT_EQ(kHaierAC160Bits, ac._irsend.capture.bits);
ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
stdAc::state_t r, p;
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p));
}
TEST(TestIRac, Haier176) {
IRHaierAC176 ac(kGpioUnused);
IRac irac(kGpioUnused);

View File

@ -0,0 +1,100 @@
// Copyright 2022 David Conran
#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
TEST(TestUtils, Housekeeping) {
// Bosch144
ASSERT_EQ("BOSCH144", typeToString(decode_type_t::BOSCH144));
ASSERT_EQ(decode_type_t::BOSCH144, strToDecodeType("BOSCH144"));
ASSERT_TRUE(hasACState(decode_type_t::BOSCH144));
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::BOSCH144));
ASSERT_EQ(kBosch144Bits, IRsend::defaultBits(decode_type_t::BOSCH144));
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::BOSCH144));
}
// Tests for decodeBosch144().
// Decode normal Bosch144 messages.
TEST(TestDecodeBosch144, RealExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1787#issuecomment-1099993189
// Mode: Cool; Fan: 100% ; Temp: 16°C
const uint16_t rawData[299] = {
4380, 4400,
528, 1646, 504, 570, 504, 1646, 504, 1646, 504, 572, 502, 570, 504, 1646,
504, 570, 504, 572, 502, 1646, 504, 570, 502, 570, 502, 1648, 502, 1646,
502, 570, 502, 1646, 504, 572, 502, 572, 502, 1644, 504, 1646, 504, 1646,
504, 1646, 502, 1648, 500, 1646, 504, 1646, 504, 1646, 504, 572, 502, 570,
504, 570, 504, 570, 504, 570, 504, 570, 506, 570, 502, 572, 502, 570, 502,
572, 502, 572, 502, 572, 502, 572, 502, 572, 500, 1648, 502, 1644, 502,
1646, 504, 1646, 502, 1646, 504, 1646, 504, 1644, 504, 1646,
504, 5234,
4360, 4422,
504, 1646, 502, 596, 478, 1670, 478, 1646, 504, 570, 504, 572, 500, 1646,
502, 572, 502, 572, 502, 1644, 506, 570, 502, 570, 504, 1644, 506, 1644,
502, 574, 502, 1644, 504, 570, 504, 570, 504, 1644, 504, 1646, 504, 1644,
506, 1644, 504, 1646, 504, 1646, 504, 1644, 504, 1646, 502, 570, 504, 570,
504, 570, 504, 570, 502, 570, 504, 570, 502, 572, 502, 570, 504, 570, 504,
570, 504, 570, 502, 572, 502, 570, 506, 570, 504, 1646, 502, 1646, 504,
1646, 504, 1646, 504, 1646, 502, 1644, 504, 1644, 504, 1646,
502, 5236,
4360, 4424,
504, 1646, 504, 1646, 502, 572, 504, 1644, 504, 570, 504, 1646, 504, 570,
502, 1644, 504, 570, 504, 1644, 506, 1646, 502, 572, 502, 572, 502, 1646,
504, 570, 504, 570, 504, 570, 502, 572, 504, 570, 504, 570, 504, 570, 502,
572, 502, 570, 504, 570, 502, 570, 504, 572, 502, 572, 502, 1646, 504,
570, 504, 570, 504, 570, 502, 574, 502, 572, 502, 572, 502, 572, 502, 572,
502, 572, 502, 570, 504, 572, 502, 572, 502, 572, 502, 1646, 504, 572,
502, 570, 502, 1646, 504, 572, 504, 570, 504, 1644,
504}; // COOLIX B23F00
const uint8_t expectedState[kBosch144StateLength] = {
0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF,
0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF,
0xD5, 0x64, 0x00, 0x10, 0x00, 0x49};
irsend.begin();
irsend.reset();
irsend.sendRaw(rawData, 299, 38000);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::BOSCH144, irsend.capture.decode_type);
EXPECT_EQ(kBosch144Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"Power: On, Mode: 0 (Cool), Fan: 5 (High), Temp: 16C, Quiet: Off",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t result, prev;
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev));
}
TEST(TestDecodeBosch144, SyntheticSelfDecode) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
const uint8_t expectedState[kBosch144StateLength] = {
0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF,
0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF,
0xD5, 0x64, 0x00, 0x10, 0x00, 0x49};
irsend.sendBosch144(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::BOSCH144, irsend.capture.decode_type);
EXPECT_EQ(kBosch144Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"Power: On, Mode: 0 (Cool), Fan: 5 (High), Temp: 16C, Quiet: Off",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t result, prev;
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev));
}

View File

@ -1,8 +1,9 @@
// Copyright 2018, 2020 David Conran
// Copyright 2018-2022 David Conran
#include "ir_Carrier.h"
#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
@ -11,7 +12,7 @@
// Test sending typical data only.
TEST(TestSendCarrierAC, SendDataOnly) {
IRsendTest irsend(0);
IRsendTest irsend(kGpioUnused);
irsend.begin();
irsend.reset();
@ -88,7 +89,7 @@ TEST(TestSendCarrierAC, SendDataOnly) {
// Test sending typical data only.
TEST(TestSendCarrierAC, SendWithRepeats) {
IRsendTest irsend(0);
IRsendTest irsend(kGpioUnused);
irsend.begin();
irsend.reset();
@ -156,7 +157,7 @@ TEST(TestSendCarrierAC, SendWithRepeats) {
// Decode normal "synthetic" messages.
TEST(TestDecodeCarrierAC, NormalDecodeWithStrict) {
IRsendTest irsend(0);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(0);
irsend.begin();
@ -196,7 +197,7 @@ TEST(TestDecodeCarrierAC, NormalDecodeWithStrict) {
// Decode a "real" example message.
TEST(TestDecodeCarrierAC, RealExamples) {
IRsendTest irsend(0);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(0);
irsend.begin();
@ -262,6 +263,16 @@ TEST(TestUtils, Housekeeping) {
IRsend::defaultBits(decode_type_t::CARRIER_AC64));
ASSERT_EQ(kCarrierAc64MinRepeat,
IRsend::minRepeats(decode_type_t::CARRIER_AC64));
// CARRIER_AC128
ASSERT_EQ("CARRIER_AC128", typeToString(decode_type_t::CARRIER_AC128));
ASSERT_EQ(decode_type_t::CARRIER_AC128, strToDecodeType("CARRIER_AC128"));
ASSERT_TRUE(hasACState(decode_type_t::CARRIER_AC128));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::CARRIER_AC128));
ASSERT_EQ(kCarrierAc128Bits,
IRsend::defaultBits(decode_type_t::CARRIER_AC128));
ASSERT_EQ(kCarrierAc128MinRepeat,
IRsend::minRepeats(decode_type_t::CARRIER_AC128));
}
/// Decode a "real" example message.
@ -610,3 +621,75 @@ TEST(TestCarrierAc64Class, ReconstructKnownState) {
"Sleep: On, On Timer: Off, Off Timer: Off",
ac.toString());
}
// Decode a "real" Carrier 128bit example message.
TEST(TestDecodeCarrierAC128, RealExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
const uint8_t expected_state[kCarrierAc128StateLength] = {
0x16, 0x22, 0x48, 0x19, 0x10, 0x10, 0x16, 0x28,
0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x80};
irsend.begin();
irsend.reset();
// Data from:
// https://docs.google.com/spreadsheets/d/1lqs1UDAvUauzAyoVRAGhARKPaSk3pgOO7iHFw9M5HJE/edit#gid=0&range=F3
const uint16_t rawData[267] = {
4594, 2614,
336, 418, 336, 998, 330, 1002, 338, 416, 336, 998, 332, 424, 328, 426,
336, 416, 336, 418, 334, 1000, 332, 420, 330, 424, 338, 418, 336, 994,
334, 420, 332, 424, 328, 424, 338, 416, 336, 418, 336, 996, 332, 422, 330,
424, 338, 992, 338, 416, 336, 998, 332, 424, 336, 418, 336, 994, 336, 998,
332, 420, 340, 416, 338, 416, 334, 420, 334, 420, 332, 424, 328, 426, 336,
994, 336, 418, 334, 422, 330, 422, 332, 422, 338, 416, 338, 416, 336, 418,
332, 1000, 332, 424, 336, 416, 338, 418, 334, 420, 332, 1000, 332, 1002,
336, 416, 338, 994, 334, 422, 330, 424, 338, 416, 336, 416, 336, 420, 332,
422, 330, 1000, 342, 412, 338, 996, 334, 422, 332, 402,
338, 20636,
4604, 6724,
9296, 4976,
356, 426, 336, 418, 334, 420, 332, 420, 330, 424, 340, 414, 338, 416, 336,
420, 334, 418, 334, 420, 332, 422, 340, 416, 336, 418, 336, 416, 336, 420,
332, 420, 332, 424, 338, 416, 336, 418, 336, 994, 334, 422, 332, 422, 340,
412, 338, 418, 334, 418, 334, 420, 332, 422, 332, 424, 340, 414, 338, 414,
336, 420, 334, 420, 330, 424, 328, 426, 336, 416, 336, 418, 334, 420, 366,
388, 362, 392, 358, 392, 360, 394, 368, 386, 368, 388, 364, 388, 366, 390,
360, 394, 358, 394, 368, 388, 366, 386, 366, 390, 362, 392, 358, 394, 360,
394, 370, 384, 366, 388, 362, 390, 362, 390, 362, 392, 360, 396, 368, 384,
366, 390, 364, 390, 362, 392, 360, 954,
336, 20638,
4622};
irsend.sendRaw(rawData, 267, 38000);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(CARRIER_AC128, irsend.capture.decode_type);
EXPECT_EQ(kCarrierAc128Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expected_state, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
}
// Decode a synthetic Carrier AC 128-bit message.
TEST(TestDecodeCarrierAC128, SyntheticExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
const uint8_t expected_state[kCarrierAc128StateLength] = {
0x16, 0x22, 0x48, 0x19, 0x10, 0x10, 0x16, 0x28,
0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x80};
irsend.reset();
irsend.sendCarrierAC128(expected_state);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(CARRIER_AC128, irsend.capture.decode_type);
ASSERT_EQ(kCarrierAc128Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expected_state, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t r, p;
ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
}

View File

@ -0,0 +1,67 @@
// Copyright 2022 crankyoldgit
#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
// Tests for decodeClimaButler().
TEST(TestDecodeClimaButler, RealExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
const uint16_t rawData[109] = {
554, 3512,
558, 1488, 580, 496, 522, 494, 546, 558, 552, 494, 548, 496, 546, 500,
548, 558, 544, 504, 544, 502, 540, 506, 538, 570, 514, 530, 514, 532, 512,
534, 512, 592, 512, 536, 510, 532, 510, 536, 510, 598, 510, 536, 506, 536,
514, 534, 510, 594, 514, 534, 510, 536, 534, 510, 510, 598, 514, 534, 510,
536, 508, 536, 534, 572, 534, 500, 512, 1536, 512, 526, 510, 1588, 512,
1536, 510, 538, 512, 532, 510, 588, 510, 1536, 514, 532, 510, 536, 534,
570, 512, 534, 510, 536, 514, 528, 540, 568, 540, 506, 512, 524, 510,
1534, 516, 532,
536, 3396,
544}; // UNKNOWN E6CA5369 POWER OFF
irsend.begin();
irsend.reset();
irsend.sendRaw(rawData, 109, 38);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(decode_type_t::CLIMABUTLER, irsend.capture.decode_type);
ASSERT_EQ(kClimaButlerBits, irsend.capture.bits);
EXPECT_EQ(0x8000000058802, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t r, p;
ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
}
TEST(TestDecodeClimaButler, SyntheticExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
irsend.sendClimaButler(0x8000000058802);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(decode_type_t::CLIMABUTLER, irsend.capture.decode_type);
ASSERT_EQ(kClimaButlerBits, irsend.capture.bits);
EXPECT_EQ(0x8000000058802, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);
}
TEST(TestUtils, Housekeeping) {
ASSERT_EQ("CLIMABUTLER", typeToString(decode_type_t::CLIMABUTLER));
ASSERT_EQ(decode_type_t::CLIMABUTLER, strToDecodeType("CLIMABUTLER"));
ASSERT_FALSE(hasACState(decode_type_t::CLIMABUTLER));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::CLIMABUTLER));
ASSERT_EQ(kClimaButlerBits, IRsend::defaultBits(decode_type_t::CLIMABUTLER));
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::CLIMABUTLER));
}

View File

@ -1552,6 +1552,20 @@ TEST(TestUtils, Housekeeping) {
ASSERT_EQ(decode_type_t::DAIKIN64, strToDecodeType("DAIKIN64"));
ASSERT_FALSE(hasACState(decode_type_t::DAIKIN64));
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::DAIKIN64));
ASSERT_EQ("DAIKIN200", typeToString(decode_type_t::DAIKIN200));
ASSERT_EQ(decode_type_t::DAIKIN200, strToDecodeType("DAIKIN200"));
ASSERT_TRUE(hasACState(decode_type_t::DAIKIN200));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::DAIKIN200));
ASSERT_EQ(kDaikin200Bits, IRsend::defaultBits(decode_type_t::DAIKIN200));
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::DAIKIN200));
ASSERT_EQ("DAIKIN312", typeToString(decode_type_t::DAIKIN312));
ASSERT_EQ(decode_type_t::DAIKIN312, strToDecodeType("DAIKIN312"));
ASSERT_TRUE(hasACState(decode_type_t::DAIKIN312));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::DAIKIN312));
ASSERT_EQ(kDaikin312Bits, IRsend::defaultBits(decode_type_t::DAIKIN312));
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::DAIKIN312));
}
// https://github.com/crankyoldgit/IRremoteESP8266/issues/582#issuecomment-453863879
@ -3879,3 +3893,228 @@ TEST(TestDaikin176Class, UnitId) {
ASSERT_EQ(0, ac.getId());
EXPECT_STATE_EQ(unita, ac.getRaw(), kDaikin176Bits);
}
TEST(TestDaikin128Class, Issue1754_HeatMode) {
// Data from "MODE HEAT"
// Mesg Desc.: Power Toggle: Off, Mode: 8 (Heat), Temp: 19C, Fan: 4 (Medium),
// Powerful: Off, Quiet: Off, Swing(V): Off, Sleep: Off, Econo: Off,
// Clock: 20:22, On Timer: Off, On Timer: 10:00, Off Timer: Off,
// Off Timer: 16:30, Light Toggle: 0 (Off)
// Ref: https://docs.google.com/document/d/1bhPlwsUE4ppL1dlX6_aYmqCSxeE6HlOumYsR35S0CKA/edit#heading=h.luu34vdlzof1
const uint8_t heatmode[16] = { // As recorded from a real remote.
0x16, 0x48, 0x22, 0x20, 0x10, 0x56, 0x19, 0x34,
0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B};
IRDaikin128 ac(kGpioUnused);
// Try to reproduce the exact same state.
ac.setClock(20 * 60 + 22);
ac.setOnTimer(10 * 60);
ac.setOnTimerEnabled(false);
ac.setOffTimer(16 * 60 + 30);
ac.setOffTimerEnabled(false);
ac.setPowerToggle(false);
ac.setTemp(19);
ac.setFan(kDaikin128FanMed);
ac.setPowerful(false);
ac.setQuiet(false);
ac.setSwingVertical(false);
ac.setSleep(false);
ac.setEcono(false);
ac.setLightToggle(0);
ac.setMode(kDaikin128Heat);
EXPECT_EQ(
"Power Toggle: Off, Mode: 8 (Heat), Temp: 19C, Fan: 4 (Medium), "
"Powerful: Off, Quiet: Off, Swing(V): Off, Sleep: Off, Econo: Off, "
"Clock: 20:22, On Timer: Off, On Timer: 10:00, Off Timer: Off, "
"Off Timer: 16:30, Light Toggle: 0 (Off)",
ac.toString());
// Compare the synthetic state to the captured one.
EXPECT_STATE_EQ(heatmode, ac.getRaw(), kDaikin128Bits);
}
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1802
TEST(TestDecodeDaikin200, RealExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
const uint16_t rawData[407] = {
4852, 2298,
202, 1942, 202, 870, 200, 870, 202, 868, 202, 1942, 202, 870, 202, 870,
202, 870, 202, 870, 202, 1942, 202, 870, 202, 1942, 202, 1942, 202, 868,
202, 1942, 202, 1942, 202, 1912, 232, 1942, 202, 1942, 202, 868, 202,
1942, 202, 870, 202, 870, 202, 868, 202, 868, 204, 868, 202, 870, 202,
1942, 202, 868, 204, 868, 202, 1942, 202, 870, 202, 870, 200, 870, 202,
1942, 202, 868, 202, 870, 202, 870, 202, 870, 202, 870, 202, 870, 202,
870, 202, 870, 202, 868, 202, 868, 204, 868, 202, 870, 202, 870, 202, 870,
202, 1942, 202, 1942, 202, 1942, 202, 868, 202, 868, 204, 1942, 202, 870,
202, 29468,
4880, 2266,
256, 1888, 230, 844, 202, 868, 202, 870, 256, 1888, 230, 842, 228, 842,
230, 842, 256, 814, 232, 1914, 254, 816, 230, 1916, 256, 1888, 256, 814,
256, 1890, 254, 1888, 256, 1888, 256, 1888, 256, 1888, 256, 816, 230,
1912, 258, 814, 256, 816, 256, 816, 282, 790, 280, 790, 282, 790, 282,
1862, 258, 814, 280, 790, 282, 1862, 280, 792, 280, 790, 282, 788, 282,
790, 282, 790, 282, 790, 282, 790, 282, 788, 282, 790, 282, 1862, 282,
1862, 282, 790, 282, 788, 282, 1862, 282, 1864, 280, 1862, 282, 790, 280,
790, 282, 790, 282, 790, 282, 788, 284, 790, 282, 760, 310, 790, 282, 788,
282, 1862, 282, 788, 282, 790, 282, 788, 282, 788, 282, 1862, 284, 788,
282, 788, 284, 788, 282, 790, 282, 788, 284, 788, 282, 790, 282, 788, 284,
758, 312, 788, 284, 788, 282, 788, 284, 788, 282, 788, 284, 788, 282, 788,
284, 788, 284, 758, 314, 786, 284, 788, 284, 1860, 282, 790, 282, 790,
282, 1862, 282, 758, 312, 762, 310, 788, 284, 788, 282, 758, 314, 758,
314, 1862, 282, 760, 312, 1860, 284, 760, 310, 788, 282, 760, 312, 788,
284, 760, 312, 788, 282, 790, 282, 788, 284, 788, 282, 790, 282, 788, 282,
758, 314, 788, 282, 758, 314, 1862, 282, 758, 312, 788, 284, 758, 312,
758, 314, 788, 282, 758, 314, 758, 312, 788, 284, 788, 284, 758, 312, 760,
312, 762, 310, 790, 284, 788, 282, 758, 314, 758, 312, 788, 282, 760, 312,
760, 312, 760, 312, 788, 282, 758, 314, 788, 284, 788, 284, 758, 312, 788,
282, 790, 282, 1832, 310, 758, 316, 788, 284, 1862, 282, 1862, 282, 1832,
310, 788, 284}; // UNKNOWN 3BFB2888
const uint8_t expectedState[kDaikin200StateLength] = {
0x11, 0xDA, 0x17, 0x48, 0x04, 0x00, 0x4E, // Section 1
0x11, 0xDA, 0x17, 0x48, 0x00, 0x73, 0x00, 0x21, 0x00, // Section 2
0x00, 0x24, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00, 0x72};
irsend.begin();
irsend.reset();
irsend.sendRaw(rawData, 407, kDaikin64Freq);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(decode_type_t::DAIKIN200, irsend.capture.decode_type);
ASSERT_EQ(kDaikin200Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t result, prev;
ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev));
}
// Decoding a message we entirely constructed based solely on a given state.
TEST(TestDecodeDaikin200, SyntheticExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
const uint8_t expectedState[kDaikin200StateLength] = {
0x11, 0xDA, 0x17, 0x48, 0x04, 0x00, 0x4E, // Section 1
0x11, 0xDA, 0x17, 0x48, 0x00, 0x73, 0x00, 0x21, 0x00, // Section 2
0x00, 0x24, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00, 0x72};
irsend.reset();
irsend.sendDaikin200(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(DAIKIN200, irsend.capture.decode_type);
ASSERT_EQ(kDaikin200Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
}
/// https://github.com/crankyoldgit/IRremoteESP8266/issues/1829#issuecomment-1173077011
TEST(TestDecodeDaikin312, RealExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/files/9034763/on_coling_210_fan_auto.txt.out.txt
const uint16_t rawData[643] = {
508, 390, 452, 414, 452, 414, 452, 414, 452, 414,
452, 25104,
3518, 1688,
478, 1256, 478, 414, 452, 414, 452, 414, 452, 1282, 452, 414, 452, 414,
452, 414, 452, 414, 452, 1280, 454, 414, 452, 1256, 478, 1254, 478, 414,
452, 1280, 452, 1282, 452, 1282, 452, 1282, 478, 1256, 480, 386, 452, 414,
452, 1282, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414,
454, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 1280, 452, 414,
452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 1282,
452, 414, 452, 414, 452, 414, 452, 1280, 452, 1280, 452, 418, 450, 1280,
452, 1282, 452, 414, 452, 1282, 452, 414, 452, 416, 452, 1280, 454, 414,
452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452,
414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 454, 414,
452, 414, 452, 1282, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414,
452, 414, 454, 414, 452, 414, 452, 414, 452, 414, 452, 414, 478, 388, 452,
414, 452, 414, 452, 414, 452, 414, 452, 414, 454, 414, 452, 414, 452, 414,
452, 414, 452, 414, 452, 414, 452, 1282, 452, 414, 452, 414, 452, 414,
452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452,
414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414,
478, 388, 452, 414, 478, 388, 452, 414, 452, 414, 452, 414, 452, 414, 452,
414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414,
452, 414, 452, 414, 452, 414, 452, 414, 448, 418, 448, 418, 448, 418, 448,
418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418,
448, 418, 448, 418, 448, 418, 448, 418, 448, 420, 448, 418, 450, 418, 448,
1286, 448, 1286, 448, 420, 448, 418, 448, 418, 448, 418, 448, 1284, 448,
1286,
448, 35512,
3518, 1688,
478, 1282, 452, 414, 452, 414, 452, 414, 452, 1282, 452, 414, 452, 414,
452, 414, 452, 414, 452, 1280, 452, 414, 452, 1256, 478, 1254, 478, 414,
452, 1280, 452, 1282, 452, 1282, 452, 1282, 452, 1280, 452, 414, 452, 414,
452, 1280, 452, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418,
448, 418, 448, 418, 452, 414, 448, 418, 448, 418, 448, 418, 448, 418, 448,
418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 1286, 452, 414, 452,
414, 452, 1280, 452, 1282, 452, 1282, 452, 414, 452, 414, 452, 414, 452,
1256, 478, 414, 452, 1282, 452, 414, 452, 1256, 478, 414, 452, 414, 452,
414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414,
454, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 1282, 452, 414,
452, 1256, 478, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414,
452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452, 414, 452,
414, 452, 414, 452, 414, 452, 414, 452, 1286, 448, 1286, 448, 418, 448,
418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418,
448, 418, 448, 1286, 448, 1286, 448, 418, 448, 418, 448, 418, 448, 418,
448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 420, 448,
418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 1260, 474,
418, 448, 1264, 470, 418, 448, 418, 448, 418, 448, 1258, 474, 1260, 474,
418, 448, 418, 448, 418, 448, 418, 448, 418, 448, 418, 452, 414, 452, 414,
452, 414, 452, 416, 452, 414, 448, 1264, 478, 384, 474, 418, 448, 418,
448, 418, 448, 418, 448, 418, 448, 418, 448, 1260, 504, 362, 474, 418,
448, 1260, 478, 388, 474}; // UNKNOWN 34EEF8FF
const uint8_t expectedState[kDaikin312StateLength] = {
// Section 1
0x11, 0xDA, 0x27, 0x00, 0x02, 0x62, 0x4B, 0x00, 0x00, 0x01,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3,
// Section 2
0x11, 0xDA, 0x27, 0x00, 0x00, 0x39, 0x2A, 0x00, 0xA0, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0xC5, 0x00, 0x08, 0x48};
irsend.begin();
irsend.reset();
irsend.sendRaw(rawData, 643, kDaikin64Freq);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(decode_type_t::DAIKIN312, irsend.capture.decode_type);
ASSERT_EQ(kDaikin312Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t result, prev;
ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev));
}
// Decoding a message we entirely constructed based solely on a given state.
TEST(TestDecodeDaikin312, SyntheticExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
const uint8_t expectedState[kDaikin312StateLength] = {
// Section 1
0x11, 0xDA, 0x27, 0x00, 0x02, 0x62, 0x4B, 0x00, 0x00, 0x01,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3,
// Section 2
0x11, 0xDA, 0x27, 0x00, 0x00, 0x39, 0x2A, 0x00, 0xA0, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0xC5, 0x00, 0x08, 0x48};
irsend.reset();
irsend.sendDaikin312(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(DAIKIN312, irsend.capture.decode_type);
ASSERT_EQ(kDaikin312Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
}

View File

@ -22,7 +22,7 @@ TEST(TestIRFujitsuACClass, GetRawDefault) {
EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8);
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Clean: Off, Filter: Off, "
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 3 (Swing(V)+Swing(H)), Command: N/A, Timer: Off",
ac.toString());
@ -45,7 +45,7 @@ TEST(TestIRFujitsuACClass, GetRawTurnOff) {
EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 7 * 8);
EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: Off, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Clean: Off, Filter: Off, "
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 3 (Swing(V)+Swing(H)), Command: N/A, Timer: Off",
ac.toString());
@ -66,8 +66,8 @@ TEST(TestIRFujitsuACClass, GetRawStepHoriz) {
EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 3 (Swing(V)+Swing(H)), "
"Command: Step Swing(H), Timer: Off",
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 3 (Swing(V)+Swing(H)), Command: Step Swing(H), Timer: Off",
ac.toString());
}
@ -80,8 +80,8 @@ TEST(TestIRFujitsuACClass, GetRawStepVert) {
EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 3 (Swing(V)+Swing(H)), "
"Command: Step Swing(V), Timer: Off",
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 3 (Swing(V)+Swing(H)), Command: Step Swing(V), Timer: Off",
ac.toString());
ac.setModel(ARDB1);
@ -106,7 +106,7 @@ TEST(TestIRFujitsuACClass, GetRawWithSwingHoriz) {
0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB};
EXPECT_STATE_EQ(expected, ac.getRaw(), 16 * 8);
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 25C, "
"Fan: 4 (Quiet), Clean: Off, Filter: Off, "
"Fan: 4 (Quiet), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 2 (Swing(H)), Command: N/A, Timer: Off",
ac.toString());
}
@ -126,7 +126,7 @@ TEST(TestIRFujitsuACClass, GetRawWithFan) {
EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8);
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 20C, "
"Fan: 2 (Medium), Clean: Off, Filter: Off, "
"Fan: 2 (Medium), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 2 (Swing(H)), Command: N/A, Timer: Off",
ac.toString());
@ -149,7 +149,7 @@ TEST(TestIRFujitsuACClass, SetRaw) {
EXPECT_STATE_EQ(expected_default_arrah2e, ac.getRaw(),
ac.getStateLength() * 8);
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Clean: Off, Filter: Off, "
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 3 (Swing(V)+Swing(H)), Command: N/A, "
"Timer: Off",
ac.toString());
@ -318,9 +318,7 @@ TEST(TestDecodeFujitsuAC, SyntheticShortMessages) {
uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD};
EXPECT_STATE_EQ(expected_arrah2e, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: Off, Mode: 0 (Auto), Temp: 16C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
"Model: 1 (ARRAH2E), Id: 0, Power: Off, Command: N/A",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t r, p;
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
@ -365,7 +363,7 @@ TEST(TestDecodeFujitsuAC, SyntheticLongMessages) {
ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 18C, "
"Fan: 4 (Quiet), Clean: Off, Filter: Off, "
"Fan: 4 (Quiet), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 1 (Swing(V)), Command: N/A, "
"Timer: Off",
ac.toString());
@ -541,8 +539,8 @@ TEST(TestDecodeFujitsuAC, Issue414) {
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 4 (Heat), Temp: 24C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
"Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), "
"Command: N/A, Timer: Off",
ac.toString());
// Resend it using the state this time.
@ -617,9 +615,7 @@ TEST(TestIRFujitsuACClass, toCommon) {
// Now test it.
EXPECT_EQ( // Off mode technically has no temp, mode, fan, etc.
"Model: 1 (ARRAH2E), Id: 0, Power: Off, Mode: 0 (Auto), Temp: 16C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
"Model: 1 (ARRAH2E), Id: 0, Power: 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);
@ -723,7 +719,7 @@ TEST(TestIRFujitsuACClass, OutsideQuiet) {
// the option is set. Otheriwse they appear the same.
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), "
"Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), "
"Command: N/A, Timer: Off", ac.toString());
ac.setModel(fujitsu_ac_remote_model_t::ARREB1E);
EXPECT_EQ(
@ -826,8 +822,8 @@ TEST(TestDecodeFujitsuAC, Issue726) {
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 24C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
"Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), "
"Command: N/A, Timer: Off",
ac.toString());
}
@ -859,16 +855,16 @@ TEST(TestIRFujitsuACClass, Clean) {
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
"Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), "
"Command: N/A, Timer: Off",
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), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
"Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), "
"Command: N/A, Timer: Off",
ac.toString());
// But ARRY4 does.
ac.setModel(fujitsu_ac_remote_model_t::ARRY4);
@ -905,8 +901,8 @@ TEST(TestIRFujitsuACClass, Filter) {
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
"Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), "
"Command: N/A, Timer: Off",
ac.toString());
// Now it is in ARRAH2E model mode, it shouldn't accept setting it on.
ac.setFilter(true);
@ -934,8 +930,8 @@ TEST(TestIRFujitsuACClass, Timers) {
EXPECT_EQ(0, ac.getOffSleepTimer());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"On Timer: 12:00",
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), "
"Command: N/A, On Timer: 12:00",
ac.toString());
const uint8_t timer_on_8h30m[kFujitsuAcStateLength] = {
@ -948,8 +944,8 @@ TEST(TestIRFujitsuACClass, Timers) {
EXPECT_EQ(0, ac.getOffSleepTimer());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"On Timer: 08:30",
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 0 (Off), Command: N/A, On Timer: 08:30",
ac.toString());
// TIMER OFF 11H
@ -963,8 +959,8 @@ TEST(TestIRFujitsuACClass, Timers) {
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Off Timer: 11:00",
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 0 (Off), Command: N/A, Off Timer: 11:00",
ac.toString());
// TIMER OFF 0.5H
@ -978,8 +974,8 @@ TEST(TestIRFujitsuACClass, Timers) {
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Off Timer: 00:30",
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 0 (Off), Command: N/A, Off Timer: 00:30",
ac.toString());
// TIMER SLEEP 3H
@ -993,8 +989,8 @@ TEST(TestIRFujitsuACClass, Timers) {
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Sleep Timer: 03:00",
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 0 (Off), Command: N/A, Sleep Timer: 03:00",
ac.toString());
// Re-construct a known timer state from scratch.
@ -1011,8 +1007,8 @@ TEST(TestIRFujitsuACClass, Timers) {
ac.setOffTimer(30);
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Off Timer: 00:30",
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 0 (Off), Command: N/A, Off Timer: 00:30",
ac.toString());
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_STATE_EQ(timer_off_30m, ac.getRaw(), ac.getStateLength() * 8);
@ -1020,8 +1016,8 @@ TEST(TestIRFujitsuACClass, Timers) {
ac.setOnTimer(12 * 60);
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"On Timer: 12:00",
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 0 (Off), Command: N/A, On Timer: 12:00",
ac.toString());
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(12 * 60, ac.getOnTimer());
@ -1033,8 +1029,8 @@ TEST(TestIRFujitsuACClass, Timers) {
ac.setSleepTimer(3 * 60);
EXPECT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Sleep Timer: 03:00",
"Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, "
"Swing: 0 (Off), Command: N/A, Sleep Timer: 03:00",
ac.toString());
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_STATE_EQ(timer_sleep_3h, ac.getRaw(), ac.getStateLength() * 8);
@ -1122,7 +1118,7 @@ TEST(TestIRFujitsuACClass, Heat10Deg) {
0x69, 0x0B, 0x00, 0x23, 0x06, 0x23, 0x20, 0xEF};
ac.setRaw(heat_on, kFujitsuAcStateLength);
EXPECT_EQ(
"Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 21C, "
"Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 10C, "
"Fan: 0 (Auto), 10C Heat: On, Swing: 0 (Off), Command: N/A, "
"Outside Quiet: Off, Timer: Off",
ac.toString());
@ -1138,7 +1134,7 @@ TEST(TestIRFujitsuACClass, Heat10Deg) {
ac.set10CHeat(true);
EXPECT_TRUE(ac.get10CHeat());
EXPECT_EQ(
"Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 21C, "
"Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 10C, "
"Fan: 0 (Auto), 10C Heat: On, Swing: 0 (Off), Command: N/A, "
"Outside Quiet: Off, Timer: Off",
ac.toString());
@ -1361,3 +1357,92 @@ TEST(TestIRFujitsuACClass, Discussion1701) {
EXPECT_EQ(expected_raw_output, ac._irsend.outputStr());
// Success.
}
TEST(TestIRFujitsuACClass, toCommon_Issue1780HandlePrev) {
IRFujitsuAC ac(kGpioUnused);
ac.setMode(kFujitsuAcModeCool);
ac.setTemp(20);
ac.setFanSpeed(kFujitsuAcFanQuiet);
ac.setSwing(kFujitsuAcSwingBoth);
ac.on();
ASSERT_TRUE(ac.toCommon().power);
stdAc::state_t prev = ac.toCommon(); // Copy in the state.
ac.off();
ASSERT_FALSE(ac.toCommon().power);
ac.send(); // This should send a short code.
prev.degrees = 27;
ac.stateReset();
IRrecv irrecv(kGpioUnused);
ac._irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&ac._irsend.capture));
ASSERT_EQ(FUJITSU_AC, ac._irsend.capture.decode_type);
ac.setRaw(ac._irsend.capture.state, ac._irsend.capture.bits / 8);
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);
ASSERT_TRUE(ac.toCommon().celsius);
ASSERT_EQ(16, ac.toCommon().degrees);
ASSERT_EQ(27, ac.toCommon(&prev).degrees);
ASSERT_FALSE(ac.toCommon().quiet);
ASSERT_EQ(stdAc::opmode_t::kAuto, ac.toCommon().mode);
ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon(&prev).mode);
ASSERT_EQ(stdAc::fanspeed_t::kAuto, ac.toCommon().fanspeed);
ASSERT_EQ(stdAc::fanspeed_t::kMin, ac.toCommon(&prev).fanspeed);
ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv);
ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
// Unsupported.
ASSERT_FALSE(ac.toCommon().filter);
ASSERT_FALSE(ac.toCommon().clean);
ASSERT_FALSE(ac.toCommon().turbo);
ASSERT_FALSE(ac.toCommon().light);
ASSERT_FALSE(ac.toCommon().econo);
ASSERT_FALSE(ac.toCommon().beep);
ASSERT_EQ(-1, ac.toCommon().sleep);
ASSERT_EQ(-1, ac.toCommon().clock);
stdAc::state_t result_inc_prev;
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &result_inc_prev,
&prev));
ASSERT_EQ(27, result_inc_prev.degrees);
ASSERT_EQ(stdAc::opmode_t::kCool, result_inc_prev.mode);
ASSERT_EQ(stdAc::fanspeed_t::kMin, result_inc_prev.fanspeed);
}
TEST(TestIRFujitsuACClass, Improve10CHeat) {
IRFujitsuAC ac(kGpioUnused);
// Data from https://docs.google.com/spreadsheets/d/1RdmJdOZ3zxYlLXzluKTp4L6VVdjDXKgizwwIyTTG8MA/edit#gid=0&range=G2
const uint8_t Arrah2u_10CHeatOn[16] = {
0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
0x41, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x20, 0x64};
ASSERT_FALSE(ac.get10CHeat());
ac.setRaw(Arrah2u_10CHeatOn, 16);
ASSERT_TRUE(ac.get10CHeat());
ASSERT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 10C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: On, Swing: 0 (Off), "
"Command: N/A, Timer: Off",
ac.toString());
EXPECT_EQ(decode_type_t::FUJITSU_AC, ac.toCommon().protocol);
ASSERT_TRUE(ac.get10CHeat());
EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.toCommon().model);
EXPECT_EQ(kFujitsuAcMinHeat, ac.toCommon().degrees);
ac.stateReset();
// Data from https://docs.google.com/spreadsheets/d/1RdmJdOZ3zxYlLXzluKTp4L6VVdjDXKgizwwIyTTG8MA/edit#gid=0&range=G8
const uint8_t Arreg1u_10CHeatOn[16] = {
0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
0x61, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x20, 0x44};
ASSERT_FALSE(ac.get10CHeat());
ac.setRaw(Arreg1u_10CHeatOn, 16);
ASSERT_TRUE(ac.get10CHeat());
ASSERT_EQ(
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 10C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: On, Swing: 0 (Off), "
"Command: N/A, Timer: Off",
ac.toString());
EXPECT_EQ(decode_type_t::FUJITSU_AC, ac.toCommon().protocol);
ASSERT_TRUE(ac.get10CHeat());
EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.toCommon().model);
EXPECT_EQ(kFujitsuAcMinHeat, ac.toCommon().degrees);
}

View File

@ -326,6 +326,9 @@ TEST(TestGreeClass, OperatingMode) {
ac.setMode(kGreeHeat);
EXPECT_EQ(kGreeHeat, ac.getMode());
ac.setMode(kGreeEcono);
EXPECT_EQ(kGreeEcono, ac.getMode());
ASSERT_NE(kGreeFanMax, 1);
ac.setFan(kGreeFanMax);
ac.setMode(kGreeDry); // Dry should lock the fan to speed 1.
@ -337,7 +340,7 @@ TEST(TestGreeClass, OperatingMode) {
ac.setMode(kGreeFan);
EXPECT_EQ(kGreeFan, ac.getMode());
ac.setMode(kGreeHeat + 1);
ac.setMode(kGreeEcono + 1);
EXPECT_EQ(kGreeAuto, ac.getMode());
ac.setMode(255);
@ -798,3 +801,40 @@ TEST(TestGreeClass, DisplayTempSource) {
ac.setRaw(state);
EXPECT_EQ(2, ac.getDisplayTempSource());
}
TEST(TestUtils, Housekeeping) {
ASSERT_EQ("GREE", typeToString(decode_type_t::GREE));
ASSERT_EQ(decode_type_t::GREE, strToDecodeType("GREE"));
ASSERT_TRUE(hasACState(decode_type_t::GREE));
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::GREE));
ASSERT_EQ(kGreeBits, IRsend::defaultBits(decode_type_t::GREE));
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::GREE));
ASSERT_EQ(gree_ac_remote_model_t::YAW1F, IRac::strToModel("YAW1F"));
ASSERT_EQ(irutils::modelToStr(decode_type_t::GREE,
gree_ac_remote_model_t::YAW1F), "YAW1F");
ASSERT_EQ(gree_ac_remote_model_t::YBOFB, IRac::strToModel("YBOFB"));
ASSERT_EQ(irutils::modelToStr(decode_type_t::GREE,
gree_ac_remote_model_t::YBOFB), "YBOFB");
ASSERT_EQ(gree_ac_remote_model_t::YX1FSF, IRac::strToModel("YX1FSF"));
ASSERT_EQ(irutils::modelToStr(decode_type_t::GREE,
gree_ac_remote_model_t::YX1FSF), "YX1FSF");
}
TEST(TestGreeClass, Issue1821EnergySaver) {
IRGreeAC ac(kGpioUnused);
ac.begin();
// https://github.com/crankyoldgit/IRremoteESP8266/issues/1821#issue-1271458457
const uint8_t energy[8] = {0x1D, 0x09, 0x60, 0x58, 0x00, 0x20, 0x00, 0xA0};
ac.setRaw(energy);
EXPECT_EQ(kGreeEcono, ac.getMode());
EXPECT_TRUE(ac.getEcono());
EXPECT_EQ(gree_ac_remote_model_t::YX1FSF, ac.getModel());
EXPECT_EQ(
"Model: 3 (YX1FSF), Power: On, Mode: 5 (Econo), Temp: 77F, Fan: 1 (Low), "
"Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, "
"Sleep: Off, Swing(V) Mode: Manual, Swing(V): 0 (Last), "
"Swing(H): 0 (Off), Timer: Off, Display Temp: 0 (Off)",
ac.toString());
}

View File

@ -1357,6 +1357,13 @@ TEST(TestUtils, Housekeeping) {
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::HAIER_AC176));
ASSERT_EQ(kHaierAC176Bits, IRsend::defaultBits(decode_type_t::HAIER_AC176));
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::HAIER_AC176));
ASSERT_EQ("HAIER_AC160", typeToString(decode_type_t::HAIER_AC160));
ASSERT_EQ(decode_type_t::HAIER_AC160, strToDecodeType("HAIER_AC160"));
ASSERT_TRUE(hasACState(decode_type_t::HAIER_AC160));
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::HAIER_AC160));
ASSERT_EQ(kHaierAC160Bits, IRsend::defaultBits(decode_type_t::HAIER_AC160));
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::HAIER_AC160));
}
TEST(TestHaierAC176Class, BuildKnownState) {
@ -1535,3 +1542,492 @@ TEST(TestHaierAC176Class, Models) {
"Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off",
ac.toString());
}
TEST(TestDecodeHaierAC160, RealExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1804#issue-1236115063
const uint16_t rawData[325] = {
3078, 3002,
3058, 4338,
590, 1612, 588, 516, 584, 1588, 586, 542, 560, 540, 560, 1590, 584, 1618,
584, 542, 558, 1592, 584, 542, 582, 1594, 584, 542, 582, 1592, 560, 1642,
560, 516, 558, 544, 558, 542, 558, 542, 582, 518, 558, 542, 558, 516, 558,
542, 558, 542, 582, 520, 558, 542, 558, 542, 564, 510, 608, 492, 558, 542,
582, 520, 558, 542, 558, 544, 582, 492, 608, 1594, 558, 544, 558, 542,
582, 494, 608, 494, 558, 544, 558, 542, 558, 544, 558, 1616, 582, 1620,
560, 542, 558, 542, 582, 494, 558, 542, 558, 542, 558, 544, 556, 542, 582,
520, 580, 494, 582, 520, 582, 520, 558, 542, 558, 542, 582, 520, 582, 492,
608, 1592, 582, 520, 558, 544, 558, 516, 584, 518, 558, 542, 582, 520,
580, 520, 582, 520, 580, 492, 584, 516, 556, 544, 582, 518, 580, 520, 580,
520, 580, 494, 606, 494, 580, 520, 580, 520, 582, 520, 580, 520, 556, 518,
608, 492, 580, 520, 556, 544, 580, 520, 580, 520, 580, 494, 606, 494, 580,
520, 580, 520, 580, 520, 580, 520, 580, 494, 606, 496, 578, 522, 580, 520,
580, 520, 580, 520, 580, 494, 606, 494, 580, 520, 580, 520, 580, 1594,
608, 494, 580, 1620, 580, 522, 580, 520, 580, 494, 578, 1620, 582, 520,
580, 1596, 582, 1620, 582, 1594, 608, 1594, 582, 522, 580, 1594, 582,
1620, 582, 520, 580, 1596, 582, 520, 580, 1620, 582, 494, 606, 496, 580,
522, 580, 522, 580, 520, 580, 520, 580, 496, 604, 496, 580, 520, 580,
1620, 582, 1594, 582, 522, 578, 522, 580, 522, 578, 522, 580, 496, 580,
522, 578, 522, 578, 522, 578, 524, 578, 522, 578, 496, 578, 522, 578, 522,
578, 546, 554, 522, 578, 522, 578, 520, 556, 546, 554, 546, 554, 546, 556,
544, 556, 546, 554, 520, 554, 544, 556, 1620, 582, 544, 556, 1594, 580,
546, 556, 1594, 580}; // UNKNOWN B6B57D85
const uint8_t expectedState[kHaierAC160StateLength] = {
0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x05, 0x17, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15};
irsend.sendRaw(rawData, 325, 38000);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(HAIER_AC160, irsend.capture.decode_type);
ASSERT_EQ(kHaierAC160Bits, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 26C, Fan: 3 (Low), "
"Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), Sleep: Off, "
"Clean: Off, "
"Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off, "
"Heating: Off",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t result, prev;
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev));
}
// Decoding a message we entirely constructed based solely on a given state.
TEST(TestDecodeHaierAC160, SyntheticExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
const uint8_t expectedState[kHaierAC160StateLength] = {
0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x05, 0x17, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15};
irsend.reset();
irsend.sendHaierAC160(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(HAIER_AC160, irsend.capture.decode_type);
ASSERT_EQ(kHaierAC160Bits, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 26C, Fan: 3 (Low), "
"Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), Sleep: Off, "
"Clean: Off, "
"Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off, "
"Heating: Off",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t result, prev;
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev));
}
// Tests for the IRHaierAC160 class.
TEST(TestHaierAC160Class, Button) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setButton(kHaierAcYrw02ButtonPower);
EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonMode);
EXPECT_EQ(kHaierAcYrw02ButtonMode, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonSleep);
EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonFan);
// Test unexpected values.
ac.setButton(0xFF);
EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton());
ac.setButton(0x10);
EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton());
}
TEST(TestHaierAC160Class, OperatingMode) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setButton(kHaierAcYrw02ButtonPower);
ac.setMode(kHaierAcYrw02Auto);
EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode());
EXPECT_EQ(kHaierAcYrw02ButtonMode, ac.getButton());
ac.setMode(kHaierAcYrw02Cool);
EXPECT_EQ(kHaierAcYrw02Cool, ac.getMode());
EXPECT_FALSE(ac.getAuxHeating());
ac.setMode(kHaierAcYrw02Heat);
EXPECT_EQ(kHaierAcYrw02Heat, ac.getMode());
EXPECT_TRUE(ac.getAuxHeating());
ac.setMode(kHaierAcYrw02Fan);
EXPECT_EQ(kHaierAcYrw02Fan, ac.getMode());
EXPECT_FALSE(ac.getAuxHeating());
ac.setMode(kHaierAcYrw02Dry);
EXPECT_EQ(kHaierAcYrw02Dry, ac.getMode());
ac.setMode(kHaierAcYrw02Auto - 1);
EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode());
ac.setMode(kHaierAcYrw02Cool);
EXPECT_EQ(kHaierAcYrw02Cool, ac.getMode());
ac.setMode(kHaierAcYrw02Fan + 1);
EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode());
ac.setMode(255);
EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode());
}
TEST(TestHaierAC160Class, Temperature) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setTemp(kHaierAcYrw02MinTempC);
EXPECT_EQ(kHaierAcYrw02MinTempC, ac.getTemp());
ac.setButton(kHaierAcYrw02ButtonPower);
ac.setTemp(kHaierAcYrw02MinTempC + 1);
EXPECT_EQ(kHaierAcYrw02MinTempC + 1, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton());
ac.setTemp(kHaierAcYrw02MaxTempC);
EXPECT_EQ(kHaierAcYrw02MaxTempC, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton());
ac.setTemp(kHaierAcYrw02MinTempC - 1);
EXPECT_EQ(kHaierAcYrw02MinTempC, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton());
ac.setTemp(kHaierAcYrw02MaxTempC + 1);
EXPECT_EQ(kHaierAcYrw02MaxTempC, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton());
ac.setTemp(23);
EXPECT_EQ(23, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonPower);
ac.setTemp(23);
EXPECT_EQ(23, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton());
ac.setTemp(kHaierAcYrw02MinTempF, true);
EXPECT_EQ(kHaierAcYrw02MinTempF, ac.getTemp());
ac.setButton(kHaierAcYrw02ButtonPower);
ac.setTemp(kHaierAcYrw02MinTempF + 1, true);
EXPECT_EQ(kHaierAcYrw02MinTempF + 1, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton());
ac.setTemp(kHaierAcYrw02MaxTempF, true);
EXPECT_EQ(kHaierAcYrw02MaxTempF, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton());
ac.setTemp(kHaierAcYrw02MinTempF - 1, true);
EXPECT_EQ(kHaierAcYrw02MinTempF, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton());
ac.setTemp(kHaierAcYrw02MaxTempF + 1, true);
EXPECT_EQ(kHaierAcYrw02MaxTempF, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton());
ac.setTemp(66, true);
EXPECT_EQ(66, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonPower);
ac.setTemp(66, true);
EXPECT_EQ(66, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton());
// Test specific cases for converting to Fahrenheit
ac.setTemp(76, true);
EXPECT_EQ(76, ac.getTemp());
ac.setTemp(77, true);
EXPECT_EQ(77, ac.getTemp());
ac.setTemp(78, true);
EXPECT_EQ(78, ac.getTemp());
ac.setTemp(24);
EXPECT_EQ(kHaierAcYrw02ButtonCFAB, ac.getButton());
ac.setTemp(0);
EXPECT_EQ(kHaierAcYrw02MinTempC, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton());
ac.setTemp(255);
EXPECT_EQ(kHaierAcMaxTemp, ac.getTemp());
EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton());
}
TEST(TestHaierAC160Class, CleanMode) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setClean(true);
EXPECT_TRUE(ac.getClean());
EXPECT_EQ(kHaierAc160ButtonClean, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setClean(false);
EXPECT_FALSE(ac.getClean());
EXPECT_EQ(kHaierAc160ButtonClean, ac.getButton());
ac.setClean(true);
EXPECT_TRUE(ac.getClean());
EXPECT_EQ(kHaierAc160ButtonClean, ac.getButton());
ac.stateReset();
EXPECT_FALSE(ac.getClean());
// clean button pressed.
// https://docs.google.com/spreadsheets/d/1RNJ7esbArS5fy1lmiM-i1PekXSNojCMad4WuuyunsC8/edit#gid=2048081808&range=FR22
const uint8_t clean_on[kHaierAC160StateLength] = {
0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00,
0x10, 0x00, 0x19, 0x3B, 0xB5, 0x40, 0x60, 0x00, 0x00, 0x55};
ac.setRaw(clean_on);
EXPECT_TRUE(ac.getClean());
EXPECT_EQ(
"Power: On, Button: 25 (Clean), Mode: 1 (Cool), Temp: 26C, "
"Fan: 3 (Low), Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), "
"Sleep: Off, Clean: On, Timer Mode: 0 (N/A), "
"On Timer: Off, Off Timer: Off, Lock: Off, Heating: Off",
ac.toString());
// No clean set.
// https://docs.google.com/spreadsheets/d/1RNJ7esbArS5fy1lmiM-i1PekXSNojCMad4WuuyunsC8/edit#gid=2048081808&range=FR4
const uint8_t clean_off[kHaierAC160StateLength] = {
0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x05, 0x17, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15};
ac.setRaw(clean_off);
EXPECT_FALSE(ac.getClean());
EXPECT_EQ(
"Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 26C, "
"Fan: 3 (Low), Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), "
"Sleep: Off, Clean: Off, Timer Mode: 0 (N/A), "
"On Timer: Off, Off Timer: Off, Lock: Off, Heating: Off",
ac.toString());
}
TEST(TestHaierAC160Class, Power) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setPower(true);
EXPECT_TRUE(ac.getPower());
EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setPower(false);
EXPECT_FALSE(ac.getPower());
EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton());
ac.setPower(true);
EXPECT_TRUE(ac.getPower());
EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton());
ac.off();
EXPECT_FALSE(ac.getPower());
ac.on();
EXPECT_TRUE(ac.getPower());
}
TEST(TestHaierAC160Class, SleepMode) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setSleep(true);
EXPECT_TRUE(ac.getSleep());
EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setSleep(false);
EXPECT_FALSE(ac.getSleep());
EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton());
ac.setSleep(true);
EXPECT_TRUE(ac.getSleep());
EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton());
}
TEST(TestHaierAC160Class, Health) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setHealth(true);
EXPECT_TRUE(ac.getHealth());
EXPECT_EQ(kHaierAcYrw02ButtonHealth, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setHealth(false);
EXPECT_FALSE(ac.getHealth());
EXPECT_EQ(kHaierAcYrw02ButtonHealth, ac.getButton());
ac.setHealth(true);
EXPECT_TRUE(ac.getHealth());
EXPECT_EQ(kHaierAcYrw02ButtonHealth, ac.getButton());
}
TEST(TestHaierAC160Class, TurboAndQuiet) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setMode(kHaierAcYrw02Cool); // Turbo & Quiet is allowed in this mode.
ac.setTurbo(false);
ac.setQuiet(false);
EXPECT_FALSE(ac.getTurbo());
EXPECT_FALSE(ac.getQuiet());
EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setTurbo(true);
EXPECT_TRUE(ac.getTurbo());
EXPECT_FALSE(ac.getQuiet());
EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton());
ac.setQuiet(true);
EXPECT_FALSE(ac.getTurbo());
EXPECT_TRUE(ac.getQuiet());
EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton());
ac.setTurbo(false);
ac.setQuiet(false);
EXPECT_FALSE(ac.getTurbo());
EXPECT_FALSE(ac.getQuiet());
EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton());
ac.setMode(kHaierAcYrw02Auto); // Turbo & Quiet is not allowed in this mode.
EXPECT_FALSE(ac.getTurbo());
EXPECT_FALSE(ac.getQuiet());
ac.setTurbo(true);
EXPECT_FALSE(ac.getTurbo());
EXPECT_NE(kHaierAcYrw02ButtonTurbo, ac.getButton());
ac.setQuiet(true);
EXPECT_FALSE(ac.getQuiet());
EXPECT_NE(kHaierAcYrw02ButtonTurbo, ac.getButton());
}
TEST(TestHaierAC160Class, Fan) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setFan(kHaierAcYrw02FanAuto);
EXPECT_EQ(kHaierAcYrw02FanAuto, ac.getFan());
EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setFan(kHaierAcYrw02FanLow);
EXPECT_EQ(kHaierAcYrw02FanLow, ac.getFan());
EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton());
ac.setFan(kHaierAcYrw02FanHigh);
EXPECT_EQ(kHaierAcYrw02FanHigh, ac.getFan());
EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton());
ac.setFan(kHaierAcYrw02FanMed);
EXPECT_EQ(kHaierAcYrw02FanMed, ac.getFan());
EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton());
// Test unexpected values.
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setFan(0x00);
EXPECT_EQ(kHaierAcYrw02FanMed, ac.getFan());
EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton());
}
TEST(TestHaierAC160Class, SwingV) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setSwingV(kHaierAc160SwingVOff);
EXPECT_EQ(kHaierAc160SwingVOff, ac.getSwingV());
EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setSwingV(kHaierAc160SwingVAuto);
EXPECT_EQ(kHaierAc160SwingVAuto, ac.getSwingV());
EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton());
ac.setSwingV(kHaierAc160SwingVTop);
EXPECT_EQ(kHaierAc160SwingVTop, ac.getSwingV());
EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton());
ac.setSwingV(kHaierAc160SwingVLow);
EXPECT_EQ(kHaierAc160SwingVLow, ac.getSwingV());
EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton());
// Test unexpected values.
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setSwingV(0xFF);
EXPECT_EQ(kHaierAc160SwingVLow, ac.getSwingV());
EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton());
}
TEST(TestHaierAC160Class, Light) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setLightToggle(true);
EXPECT_TRUE(ac.getLightToggle());
EXPECT_EQ(kHaierAc160ButtonLight, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setLightToggle(false);
EXPECT_FALSE(ac.getLightToggle());
EXPECT_NE(kHaierAc160ButtonLight, ac.getButton());
ac.setLightToggle(true);
EXPECT_TRUE(ac.getLightToggle());
EXPECT_EQ(kHaierAc160ButtonLight, ac.getButton());
const uint8_t light_press[kHaierAC160StateLength] = {
0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x15, 0x27, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15};
ac.setRaw(light_press);
EXPECT_TRUE(ac.getLightToggle());
EXPECT_EQ(kHaierAc160ButtonLight, ac.getButton());
EXPECT_EQ(
"Power: On, Button: 21 (Light), Mode: 1 (Cool), Temp: 26C, "
"Fan: 3 (Low), Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), "
"Sleep: Off, Clean: Off, Timer Mode: 0 (N/A), "
"On Timer: Off, Off Timer: Off, Lock: Off, Heating: Off",
ac.toString());
}
TEST(TestHaierAC160Class, AuxHeating) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();
ac.setAuxHeating(true);
EXPECT_TRUE(ac.getAuxHeating());
EXPECT_EQ(kHaierAc160ButtonAuxHeating, ac.getButton());
ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setAuxHeating(false);
EXPECT_FALSE(ac.getAuxHeating());
EXPECT_EQ(kHaierAc160ButtonAuxHeating, ac.getButton());
ac.setAuxHeating(true);
EXPECT_TRUE(ac.getAuxHeating());
EXPECT_EQ(kHaierAc160ButtonAuxHeating, ac.getButton());
// https://docs.google.com/spreadsheets/d/1RNJ7esbArS5fy1lmiM-i1PekXSNojCMad4WuuyunsC8/edit#gid=2048081808&range=A124:W143
const uint8_t aux_button_off[kHaierAC160StateLength] = {
0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0x16, 0x88, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15};
ac.setRaw(aux_button_off);
EXPECT_FALSE(ac.getAuxHeating());
EXPECT_EQ(kHaierAc160ButtonAuxHeating, ac.getButton());
EXPECT_EQ(
"Power: On, Button: 22 (Heating), Mode: 4 (Heat), Temp: 26C, "
"Fan: 3 (Low), Turbo: Off, Quiet: Off, Health: Off, Swing(V): 12 (Auto), "
"Sleep: Off, Clean: Off, Timer Mode: 0 (N/A), "
"On Timer: Off, Off Timer: Off, Lock: Off, Heating: Off",
ac.toString());
}

View File

@ -284,6 +284,14 @@ TEST(TestUtils, Housekeeping) {
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::SANYO_AC88));
ASSERT_EQ(kSanyoAc88Bits, IRsend::defaultBits(decode_type_t::SANYO_AC88));
ASSERT_EQ(kSanyoAc88MinRepeat, IRsend::minRepeats(decode_type_t::SANYO_AC88));
// Sanyo A/C 152 Bit.
ASSERT_EQ("SANYO_AC152", typeToString(decode_type_t::SANYO_AC152));
ASSERT_EQ(decode_type_t::SANYO_AC152, strToDecodeType("SANYO_AC152"));
ASSERT_TRUE(hasACState(decode_type_t::SANYO_AC152));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::SANYO_AC152));
ASSERT_EQ(kSanyoAc152Bits, IRsend::defaultBits(decode_type_t::SANYO_AC152));
ASSERT_EQ(kSanyoAc152MinRepeat,
IRsend::minRepeats(decode_type_t::SANYO_AC152));
}
TEST(TestDecodeSanyoAc, DecodeRealExamples) {
@ -820,3 +828,70 @@ TEST(TestSanyoAc88Class, Clock) {
ac.setClock(25 * 60 + 61);
EXPECT_EQ(23 * 60 + 59, ac.getClock());
}
TEST(TestDecodeSanyoAc152, DecodeRealExamples) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
// Ref: "16c" from https://github.com/crankyoldgit/IRremoteESP8266/issues/1826#issuecomment-1160708653
const uint16_t rawData[307] = {
3294, 1726, 420, 330, 458, 462, 382, 452, 438, 330, 456, 458, 384, 454,
384, 1312, 422, 324, 512, 336, 454, 458, 384, 450, 438, 358, 436, 464,
424, 326, 458, 476, 372, 458, 430, 328, 458, 464, 382, 1308, 424, 326,
510, 1264, 424, 268, 520, 460, 380, 460, 436, 324, 462, 400, 436, 474,
372, 456, 430, 342, 452, 450, 388, 446, 442, 1262, 422, 266, 520, 1314,
372, 1306, 424, 1258, 370, 390, 448, 1314, 372, 1310, 426, 308, 522, 338,
454, 470, 370, 454, 438, 330, 456, 468, 370, 456, 384, 464, 384, 1306,
422, 328, 460, 472, 374, 448, 442, 1258, 426, 1256, 426, 268, 520, 464,
382, 460, 430, 328, 508, 1264, 426, 262, 572, 1262, 424, 228, 604, 1262,
372, 1312, 372, 1310, 426, 1256, 422, 1258, 424, 262, 524, 418, 428, 456,
382, 1308, 372, 456, 386, 456, 382, 464, 378, 1308, 424, 360, 436, 454,
430, 344, 450, 1306, 372, 1310, 424, 326, 510, 338, 452, 456, 384, 456,
436, 328, 510, 1258, 372, 1310, 422, 338, 454, 466, 424, 328, 460, 1310,
372, 1312, 424, 1258, 450, 262, 496, 1310, 372, 1310, 426, 1260, 424, 260,
526, 442, 442, 1264, 426, 268, 520, 458, 380, 450, 386, 462, 436, 320,
518, 1256, 372, 394, 446, 398, 494, 334, 506, 326, 510, 276, 518, 460,
430, 332, 508, 326, 510, 356, 440, 448, 444, 264, 572, 336, 456, 408, 434,
454, 438, 332, 506, 336, 454, 460, 384, 448, 444, 326, 510, 332, 456, 442,
400, 456, 384, 456, 386, 452, 388, 454, 440, 326, 512, 272, 518, 450, 440,
334, 454, 458, 440, 320, 516, 268, 570, 340, 452, 468, 424, 260, 574, 336,
456, 394, 444, 458, 438, 328, 508, 1258, 370, 1312, 372, 1312, 424, 314,
468, 1312, 450, 1232, 370, 1314, 420, 324, 514}; // UNKNOWN 584FBE80
const uint8_t expectedState[kSanyoAc152StateLength] = {
0x40, 0x00, 0x14, 0x80, 0x6E, 0x80, 0x18, 0xEA, 0x23, 0x62,
0x30, 0xEE, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77};
irsend.begin();
irsend.reset();
irsend.sendRaw(rawData, 307, 38000);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(SANYO_AC152, irsend.capture.decode_type);
EXPECT_EQ(kSanyoAc152Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
}
TEST(TestDecodeSanyoAc152, SyntheticSelfDecode) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
const uint8_t expectedState[kSanyoAc152StateLength] = {
0x40, 0x00, 0x14, 0x80, 0x6E, 0x80, 0x18, 0xEA, 0x23, 0x62,
0x30, 0xEE, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77};
irsend.begin();
irsend.reset();
irsend.sendSanyoAc152(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SANYO_AC152, irsend.capture.decode_type);
EXPECT_EQ(kSanyoAc152Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
}

View File

@ -1,4 +1,4 @@
// Copyright 2019 David Conran
// Copyright 2019-2022 David Conran
#include "ir_Tcl.h"
#include "IRac.h"
@ -22,6 +22,13 @@ TEST(TestTcl112Ac, Housekeeping) {
ASSERT_EQ(tcl_ac_remote_model_t::GZ055BE1, IRac::strToModel("GZ055BE1"));
ASSERT_EQ(irutils::modelToStr(decode_type_t::TCL112AC,
tcl_ac_remote_model_t::GZ055BE1), "GZ055BE1");
ASSERT_EQ("TCL96AC", typeToString(decode_type_t::TCL96AC));
ASSERT_EQ(decode_type_t::TCL96AC, strToDecodeType("TCL96AC"));
ASSERT_TRUE(hasACState(decode_type_t::TCL96AC));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::TCL96AC));
ASSERT_EQ(kTcl96AcBits, IRsend::defaultBits(decode_type_t::TCL96AC));
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::TCL96AC));
}
// Tests for decodeTcl112Ac().
@ -703,3 +710,64 @@ TEST(TestTcl112AcClass, Timers) {
"On Timer: Off, Off Timer: 02:00",
ac.toString());
}
// Decode a real Tcl96Ac A/C example from Issue #619
TEST(TestDecodeTcl96Ac, DecodeRealExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
// Tcl96Ac A/C example from Issue #1810 row_data.txt
const uint16_t rawData[99] = {
1056, 550,
608, 2182, 608, 1444, 606, 840, 608, 2182,
608, 360, 612, 2182, 608, 356, 616, 1446,
608, 354, 618, 366, 608, 366, 606, 356,
618, 356, 618, 838, 608, 364, 608, 364,
608, 2182, 608, 360, 612, 840, 608, 838,
610, 364, 608, 360, 612, 2182, 608, 838,
608, 838, 608, 2182, 608, 366, 606, 1444,
608, 358, 614, 1444, 608, 838, 608, 366,
606, 368, 606, 366, 606, 366, 606, 366,
608, 364, 608, 342, 632, 840, 606, 340,
606, 364, 634, 338, 634, 340, 632, 340,
634, 814, 632, 814, 632, 2156, 634, 2156,
634}; // UNKNOWN AE10E0CB
const uint8_t expectedState[kTcl96AcStateLength] = {
0xB6, 0x23, 0x00, 0x10, 0x85, 0x09, 0x63, 0x34, 0x00, 0x04, 0x00, 0x5A};
irsend.sendRaw(rawData, 99, 38000);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(TCL96AC, irsend.capture.decode_type);
EXPECT_EQ(kTcl96AcBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
}
// Decode a synthetic Tcl96Ac A/C message
TEST(TestDecodeTcl96Ac, SyntheticExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
const uint8_t expectedState[kTcl96AcStateLength] = {
0xB6, 0x23, 0x00, 0x10, 0x85, 0x09, 0x63, 0x34, 0x00, 0x04, 0x00, 0x5A};
irsend.sendTcl96Ac(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(TCL96AC, irsend.capture.decode_type);
EXPECT_EQ(kTcl96AcBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"",
IRAcUtils::resultAcToString(&irsend.capture));
}

View File

@ -0,0 +1,159 @@
// Copyright 2022 crankyoldgit (David Conran)
#include "IRac.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "IRutils.h"
#include "gtest/gtest.h"
// General housekeeping
TEST(TestToto, Housekeeping) {
ASSERT_EQ("TOTO", typeToString(TOTO));
ASSERT_FALSE(hasACState(TOTO));
ASSERT_EQ(kTotoBits, IRsend::defaultBits(decode_type_t::TOTO));
ASSERT_EQ(kSingleRepeat, IRsend::minRepeats(decode_type_t::TOTO));
}
// Tests for decodeToto().
// Decode normal Toto messages.
TEST(TestDecodeToto, SyntheticShortDecode) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
// Short Toto 24-bit message.
irsend.reset();
irsend.sendToto(0x0D0D00);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(TOTO, irsend.capture.decode_type);
EXPECT_EQ(kTotoBits, irsend.capture.bits);
EXPECT_EQ(0x0D0D00, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.address);
EXPECT_EQ(0x0D00, irsend.capture.command);
}
// Decode real example via Issue #1806
TEST(TestDecodeToto, RealShortDecode) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
// Toto Full Flush from Issue #1806
const uint16_t rawData[163] = {
6266, 2734,
598, 540, 598, 1626, 598, 512, 622, 516, 598, 514, 598, 510, 598, 514,
628, 512, 596, 514, 600, 512, 598, 538, 600, 1622, 600, 512, 598, 540,
602, 510, 598, 512, 598, 512, 624, 514, 598, 512, 598, 512, 598, 514,
624, 512, 598, 514, 598, 1652, 596, 514, 598, 1626, 598, 1650, 598, 514,
598, 512, 598, 540, 598, 514, 596, 1626, 626, 512, 574, 1648, 598, 1650,
598, 514, 598, 512, 594, 544, 596, 514,
598, 37996,
6182, 2764,
598, 514, 600, 1648, 600, 512, 596, 514, 598, 540, 598, 512, 600, 512,
598, 512, 624, 514, 598, 514, 598, 512, 596, 1652, 598, 514, 598, 512,
596, 540, 598, 514, 598, 512, 598, 512, 598, 540, 596, 516, 596, 514, 598,
512, 574, 564, 598, 1626, 568, 542, 624, 1624, 626, 1622, 598, 514, 596,
514, 598, 514, 596, 540, 600, 1622, 598, 512, 600, 1650, 598, 1624, 596,
540, 600, 512, 598, 514, 596, 514,
622}; // UNKNOWN 43BD67B3
irsend.sendRaw(rawData, 163, 38);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(TOTO, irsend.capture.decode_type);
EXPECT_EQ(kTotoBits, irsend.capture.bits);
EXPECT_EQ(0x0D0D00, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.address);
EXPECT_EQ(0x0D00, irsend.capture.command);
}
// Decode real example via Issue #1806
TEST(TestDecodeToto, RealLongDecode) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
// Oscillate Bidet Function from Issue #1806
const uint16_t rawData[491] = {
6262, 2738,
600, 538, 596, 1624, 598, 512, 652, 486, 628, 484, 600, 510, 596, 516,
650, 488, 622, 488, 626, 484, 598, 540, 600, 1624, 602, 510, 596, 540,
602, 510, 598, 514, 598, 512, 626, 512, 598, 512, 598, 512, 598, 514,
626, 510, 598, 514, 598, 512, 598, 1650, 600, 1622, 600, 538, 596, 514,
600, 510, 596, 514, 596, 542, 598, 514, 598, 1624, 626, 1622, 598, 512,
600, 512, 620, 516, 598, 512, 598, 514,
598, 40244,
6184, 2764,
598, 514, 598, 1650, 598, 514, 596, 516, 596, 542, 598, 512, 596, 516,
600, 510, 624, 512, 598, 512, 596, 516, 598, 1652, 600, 512, 598, 512,
598, 540, 596, 518, 594, 514, 598, 512, 596, 542, 598, 512, 596, 514,
598, 512, 598, 540, 598, 514, 598, 1622, 624, 1626, 598, 514, 598, 512,
626, 512, 596, 514, 596, 514, 596, 540, 598, 1624, 600, 1650, 600, 512,
600, 510, 598, 512, 596, 540, 598, 512,
600, 40244,
6186, 2760,
600, 512, 596, 1626, 624, 514, 598, 512, 600, 512, 598, 512, 626, 512,
598, 512, 598, 512, 596, 540, 600, 510, 600, 1622, 600, 538, 596, 514,
596, 514, 598, 514, 624, 514, 596, 516, 596, 514, 600, 512, 622, 514, 600,
512, 600, 510, 600, 538, 602, 1622, 600, 1648, 626, 512, 572, 512, 598,
514, 650, 488, 598, 512, 594, 516, 598, 1652, 598, 1626, 598, 514, 624,
514, 596, 512, 600, 512, 598, 540,
596, 40246,
6184, 2736,
598, 538, 598, 1624, 598, 512, 598, 540, 598, 512, 600, 512, 596, 514,
600, 538, 626, 486, 598, 514, 596, 514, 652, 1596, 594, 516, 624, 514,
594, 516, 598, 514, 622, 490, 596, 540, 596, 514, 624, 488, 594, 514, 598,
538, 598, 512, 598, 514, 594, 516, 596, 540, 600, 1622, 572, 566, 600,
512, 570, 542, 598, 512, 598, 540, 600, 512, 594, 516, 598, 1652, 600,
512, 598, 514, 596, 514, 624, 514,
598, 42468,
6182, 2764,
624, 490, 594, 1652, 600, 512, 596, 514, 596, 540, 600, 512, 598, 516,
596, 514, 598, 538, 598, 516, 598, 512, 570, 1678, 596, 514, 596, 514,
598, 512, 624, 512, 594, 516, 596, 514, 600, 510, 626, 512, 596, 516,
594, 516, 598, 538, 598, 512, 596, 514, 596, 514, 596, 1652, 600, 514,
594, 516, 622, 514, 600, 512, 598, 514, 596, 514, 624, 514, 596, 1626,
598, 514, 622, 516, 594, 516, 598, 514,
596, 42496,
6184, 2764,
596, 516, 598, 1624, 626, 512, 598, 512, 596, 516, 600, 512, 624, 514,
598, 514, 594, 516, 596, 516, 620, 516, 600, 1624, 596, 540, 598, 514,
600, 512, 596, 516, 596, 542, 594, 516, 598, 514, 594, 516, 624, 512, 598,
512, 596, 514, 596, 514, 624, 514, 596, 516, 598, 1650, 594, 518, 596,
514, 596, 516, 596, 542, 596, 514, 596, 516, 596, 514, 596, 1652, 598,
514, 596, 514, 624, 514, 622, 488, 596}; // UNKNOWN 4AC5E8B3
irsend.sendRaw(rawData, 491, 38);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(TOTO, irsend.capture.decode_type);
EXPECT_EQ(kTotoLongBits, irsend.capture.bits);
EXPECT_EQ(0x60600080800, irsend.capture.value);
EXPECT_EQ(0x0600, irsend.capture.address);
EXPECT_EQ(0x0800, irsend.capture.command);
}
TEST(TestDecodeToto, SyntheticLongDecode) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
// Long Toto 48-bit message.
irsend.reset();
irsend.sendToto(0x60600080800, kTotoLongBits);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(TOTO, irsend.capture.decode_type);
EXPECT_EQ(kTotoLongBits, irsend.capture.bits);
EXPECT_EQ(0x60600080800, irsend.capture.value);
EXPECT_EQ(0x0600, irsend.capture.address);
EXPECT_EQ(0x0800, irsend.capture.command);
}

View File

@ -100,7 +100,6 @@ class RawIRMessage():
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(f" // Data Section #{self.section_count}")
@ -115,7 +114,6 @@ class RawIRMessage():
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([
@ -139,7 +137,6 @@ class RawIRMessage():
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
@ -173,7 +170,6 @@ class RawIRMessage():
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