[IR] Updated library reduces memory consumption

This commit is contained in:
jimmys01
2019-11-12 10:19:30 +02:00
parent 510afb2553
commit b439ddd7e0
38 changed files with 2495 additions and 730 deletions
+2 -2
View File
@@ -9,8 +9,8 @@
This library enables you to **send _and_ receive** infra-red signals on an [ESP8266](https://github.com/esp8266/Arduino) or an
[ESP32](https://github.com/espressif/arduino-esp32) using the [Arduino framework](https://www.arduino.cc/) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* demodulators etc.
## v2.6.6 Now Available
Version 2.6.6 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
## v2.7.0 Now Available
Version 2.7.0 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
#### Upgrading from pre-v2.0
Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page.
+6 -6
View File
@@ -6,22 +6,22 @@
[![Percentage of issues still open](http://isitmaintained.com/badge/open/crankyoldgit/IRremoteESP8266.svg)](http://isitmaintained.com/project/crankyoldgit/IRremoteESP8266 "Percentage of issues still open")
[![GitLicense](https://gitlicense.com/badge/crankyoldgit/IRremoteESP8266)](https://gitlicense.com/license/crankyoldgit/IRremoteESP8266)
Cette librairie vous permetra de **recevoir et d'envoyer des signaux** infrarouge sur le protocole [ESP8266](https://github.com/esp8266/Arduino) ou sur le protocole
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.6.6 disponible
Version 2.6.6 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants.
## v2.7.0 disponible
Version 2.7.0 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants.
#### mise à jour depuis pre-v2.0
L'utilisation de la librairie à un peu changer depuis la version in v2.0. Si vous voulez l'utiliser vous devrez changer votre utilisation aussi. Vous pouvez vous renseigner sur les précondition d'utilisation ici : [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page.
#### Mise à jour depuis pre-v2.5
La librairie à changer, elle n'utilise plus les constantes déclarées comme `#define` mais comme :
[const](https://google.github.io/styleguide/cppguide.html#Constant_Names) avec le nom approprié par le langage
La librairie à changer, elle n'utilise plus les constantes déclarées comme `#define` mais comme :
[const](https://google.github.io/styleguide/cppguide.html#Constant_Names) avec le nom approprié par le langage
[C++ style guide](https://google.github.io/styleguide/cppguide.html).
Il se peut que d'ancien programme ne compile pas.
Le cas le plus utilisé de `#define`s à été remplacé par _aliased_ pour limiter
la compatibilité de revenir en arrière pour les vieux projet. En revenant en arrière seulement la
la compatibilité de revenir en arrière pour les vieux projet. En revenant en arrière seulement la
nouvelle `kConstantName` style est supporté.
Dans le cas peu probable, votre code serait cassé, alors vous avez peut-être fait référence à
+38
View File
@@ -1,5 +1,43 @@
# Release Notes
## _v2.7.0 (20191030)_
**[Bug Fixes]**
- auto_analyse: Fix > 64 bit send code generation. (#976)
- auto_analyse: Fix missing arguments in generated code for send64+ (#972)
- IRsendProntoDemo: Fix compile issue on ESP32 platform. (#938)
- IRMQTTServer: Fix compile error when `MQTT_ENABLE` is false. (#933)
**[Features]**
- Add Hitachi 424 bit A/C support. (#975, #980, #981)
- Experimental detailed support for `DAIKIN152` (#971)
- Mitsubishi 112bit A/C support (#947, #968)
- gc_decode: Adding Support for Decoding codes in raw code format (#963)
- Refactor to use common routines/macros to handle bit manipulation. (#934)
- Use centralised common strings. Saves ~1.5k of program space. (#946)
- Add Internationalisation (i18n) / Locale support. (#946, #955, #966)
- `de-CH`: Swiss German. (#949, #954)
- `de-DE`: German. (#946, #950, #952)
- `en-AU`: English/Australia (Default locale) (#946)
- `en-IE`: English/Ireland (#946)
- `en-UK`: English/United Kingdom (#946)
- `en-US`: English/United States (#946)
- `es-ES`: Spanish. (#953)
- `fr-FR`: French. (#962)
- Port CI pipeline to PlatformIO (#936)
**[Misc]**
- Add DAIKIN128 & DAIKIN152 to `decodeToState()` (#982)
- auto_analyse: Produce better code when leader is detected. (#977)
- Coolix A/C improvements (#944)
- A/C setRaw/getRaw/stateReset() cleanup. (#967)
- Add documentation on how to use & support the i18n aspects of the library.
- Make travis checks faster. (#957)
- Translate README.md to french (#959)
- Fixed Coolix kCoolixDefaultState (#941)
- Improve generation of list of pio projects. (#940)
## _v2.6.6 (20190923)_
**[Bug Fixes]**
+16 -12
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 Sep 23 17:11:00 2019 --->
Last generated: Wed Oct 30 13:41:10 2019 --->
# IR Protocols supported by this library
| Protocol | Brand | Model | A/C Model | Detailed A/C Support |
@@ -11,21 +11,22 @@
| [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **Carrier/Surrey** | 42QG5A55970 remote<BR>53NGK009/012 Inverter<BR>619EGX0090E0 A/C<BR>619EGX0120E0 A/C<BR>619EGX0180E0 A/C<BR>619EGX0220E0 A/C | | - |
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Beko](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | BINR 070/071 split-type A/C<BR>BINR 070/071 split-type A/C<BR>RG57K7(B)/BGEF Remote<BR>RG57K7(B)/BGEF Remote | | Yes |
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | MS12FU-10HRDN1-QRD0GW(B) A/C<BR>MS12FU-10HRDN1-QRD0GW(B) A/C<BR>MSABAU-07HRFN1-QRD0GW A/C (circa 2016)<BR>MSABAU-07HRFN1-QRD0GW A/C (circa 2016)<BR>RG52D/BGE Remote<BR>RG52D/BGE Remote | | Yes |
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Tokio](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | AATOEMF17-12CHR1SW split-type RG51|50/BGE Remote<BR>AATOEMF17-12CHR1SW split-type RG51|50/BGE Remote | | Yes |
| [Daikin](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Daikin.cpp) | **[Daikin](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Daikin.h)** | 17 Series A/C (DAIKIN128)<BR>ARC423A5 remote<BR>ARC433** remote<BR>ARC433B69 remote<BR>ARC477A1 remote<BR>ARC480A5 remote (DAIKIN152)<BR>BRC4C153 remote<BR>BRC52B63 remote (DAIKIN128)<BR>FTE12HV2S A/C<BR>FTXB09AXVJU A/C (DAIKIN128)<BR>FTXB12AXVJU A/C (DAIKIN128)<BR>FTXZ25NV1B A/C<BR>FTXZ35NV1B A/C<BR>FTXZ50NV1B A/C | | Yes |
| [Denon](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Denon.cpp) | **Unknown** | | | - |
| [Dish](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Dish.cpp) | **DISH NETWORK** | echostar 301 | | - |
| [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[AUX](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | KFR-35GW/BpNFW=3 A/C<BR>YKR-T/011 remote | | Yes |
| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AGTV14LAC A/C<BR>AR-DB1 remote<BR>AR-DL10 remote<BR>AR-RAC1E remote<BR>AR-RAE1E remote<BR>AR-RAH2E remote<BR>AR-REB1E remote<BR>AR-RY4 remote<BR>AST9RSGCW A/C<BR>ASTB09LBC A/C<BR>ASU30C1 A/C<BR>ASYG30LFCA A/C<BR>ASYG7LMCA A/C | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E<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)** | AR-JW2 remote | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E<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<BR>AR-DB1 remote<BR>AR-DL10 remote<BR>AR-RAC1E remote<BR>AR-RAE1E remote<BR>AR-RAH2E remote<BR>AR-REB1E remote<BR>AR-RY4 remote<BR>AST9RSGCW A/C<BR>ASTB09LBC A/C<BR>ASU30C1 A/C<BR>ASYG30LFCA A/C<BR>ASYG7LMCA A/C | | Yes |
| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AR-JW2 remote | | Yes |
| [GICable](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GICable.cpp) | **Unknown** | | | - |
| [GlobalCache](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GlobalCache.cpp) | **Unknown** | | | - |
| [Goodweather](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Goodweather.cpp) | **[Goodweather](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Goodweather.h)** | ZH/JT-03 remote | | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[EKOKAI](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | A/C | YAW1F<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) | **[EKOKAI](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | A/C | | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Green](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | YBOFB remote<BR>YBOFB2 remote | | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[RusClimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | EACS/I-09HAR_X/N3 A/C<BR>YAW1F remote | | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Ultimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | Heat Pump | | Yes |
| [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | HSU-09HMC203 A/C<BR>HSU07-HEA03 remote<BR>YR-W02 remote | | Yes |
| [Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.cpp) | **[Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.h)** | LT0541-HTA remote<BR>RAS-35THA6 remote<BR>Series VI A/C (Circa 2007) | | Yes |
| [Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.cpp) | **[Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.h)** | LT0541-HTA remote<BR>RAR-8P2 remote<BR>RAS-35THA6 remote<BR>RAS-AJ25H A/C<BR>Series VI A/C (Circa 2007) | | Yes |
| [Inax](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Inax.cpp) | **Lixil** | Inax DT-BA283 Toilet | | - |
| [JVC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_JVC.cpp) | **Unknown** | | | - |
| [Kelvinator](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.cpp) | **[Green](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.h)** | YAPOF3 remote | | Yes |
@@ -40,12 +41,12 @@
| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Keystone](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG57H4(B)BGEF remote | | Yes |
| [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Pioneer System](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RUBO18GMFILCAD A/C (18K BTU)<BR>RYBO12GMFILCAD A/C (12K BTU) | | Yes |
| [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | HC3000 Projector<BR>KM14A 0179213 remote<BR>MS-GK24VA A/C<BR>TV | | Yes |
| [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi Electric](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | 001CP T7WE10714 remote<BR>PEAD-RP71JAA Ducted A/C | | Yes |
| [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi Electric](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | 001CP T7WE10714 remote<BR>KPOA remote<BR>MSH-A24WV / MUH-A24WV A/C<BR>PEAD-RP71JAA Ducted A/C | | Yes |
| [MitsubishiHeavy](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.cpp) | **[Mitsubishi Heavy Industries](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.h)** | RKX502A001C remote<BR>RLA502A700B remote<BR>SRKxxZJ-S A/C<BR>SRKxxZM-S A/C<BR>SRKxxZMXA-S A/C | | Yes |
| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Yamaha](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | RAV561 remote<BR>RXV585B A/V Receiver | | Yes |
| [Neoclima](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Neoclima.cpp) | **[Neoclima](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Neoclima.h)** | NS-09AHTI A/C<BR>NS-09AHTI A/C<BR>ZH/TY-01 remote<BR>ZH/TY-01 remote | | Yes |
| [Nikai](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Nikai.cpp) | **Unknown** | | | - |
| [Panasonic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Panasonic.cpp) | **[Panasonic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Panasonic.h)** | A75C2311 remote (CKP)<BR>A75C3704 remote<BR>A75C3747 remote<BR>A75C3747 remote<BR>A75C3747 remote<BR>A75C3747 remote<BR>CKP series A/C<BR>CS-ME10CKPG A/C<BR>CS-ME12CKPG A/C<BR>CS-ME14CKPG A/C<BR>CS-YW9MKD A/C<BR>CS-Z9RKR A/C<BR>DKE series A/C<BR>JKE series A/C<BR>NKE series A/C<BR>RKR series A/C<BR>TV | CKP<BR>DKE<BR>JKE<BR>LKE<BR>NKE<BR>RKR | Yes |
| [Panasonic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Panasonic.cpp) | **[Panasonic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Panasonic.h)** | A75C2311 remote (CKP)<BR>A75C3704 remote<BR>A75C3747 remote<BR>A75C3747 remote<BR>A75C3747 remote<BR>A75C3747 remote<BR>CKP series A/C<BR>CS-ME10CKPG A/C<BR>CS-ME12CKPG A/C<BR>CS-ME14CKPG A/C<BR>CS-YW9MKD A/C<BR>CS-Z9RKR A/C<BR>DKE series A/C<BR>JKE series A/C<BR>NKE series A/C<BR>RKR series A/C<BR>TV | | Yes |
| [Pioneer](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Pioneer.cpp) | **Unknown** | | | - |
| [Pronto](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Pronto.cpp) | **Unknown** | | | - |
| [RC5_RC6](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp) | **Unknown** | | | - |
@@ -60,16 +61,18 @@
| [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | Akita EVO II<BR>RAS 18SKP-ES<BR>RAS-B13N3KV2<BR>RAS-B13N3KVP-E<BR>WC-L03SE<BR>WH-TA04NE | | Yes |
| [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Unknown](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | | | Yes |
| [Vestel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Vestel.cpp) | **[Vestel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Vestel.h)** | BIOX CXP-9 A/C (9K BTU) | | Yes |
| [Whirlpool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whirlpool.cpp) | **[Whirlpool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whirlpool.h)** | DG11J1-04 remote<BR>DG11J1-3A remote<BR>DG11J1-91 remote<BR>SPIS409L A/C<BR>SPIS412L A/C<BR>SPIW409L A/C<BR>SPIW412L A/C<BR>SPIW418L A/C | DG11J13A<BR>DG11J191 | Yes |
| [Whirlpool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whirlpool.cpp) | **[Whirlpool](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whirlpool.h)** | DG11J1-04 remote<BR>DG11J1-3A remote<BR>DG11J1-91 remote<BR>SPIS409L A/C<BR>SPIS412L A/C<BR>SPIW409L A/C<BR>SPIW412L A/C<BR>SPIW418L A/C | | Yes |
| [Whynter](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Whynter.cpp) | **Whynter** | ARC-110WD A/C | | - |
## Send only protocols:
- GLOBALCACHE
- MITSUBISHI112
- PRONTO
- RAW
- SHERWOOD
- TCL112AC
## Send & decodable protocols:
@@ -98,6 +101,7 @@
- HITACHI_AC
- HITACHI_AC1
- HITACHI_AC2
- HITACHI_AC424
- INAX
- JVC
- KELVINATOR
@@ -134,10 +138,10 @@
- SHARP
- SHARP_AC
- SONY
- TCL112AC
- TECO
- TOSHIBA_AC
- TROTEC
- VESTEL_AC
- WHIRLPOOL_AC
- WHYNTER
- typeguess
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "IRremoteESP8266",
"version": "2.6.6",
"version": "2.7.0",
"keywords": "infrared, ir, remote, esp8266, esp32",
"description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)",
"repository":
+1 -1
View File
@@ -1,5 +1,5 @@
name=IRremoteESP8266
version=2.6.6
version=2.7.0
author=David Conran, Sebastien Warin, Mark Szabo, Ken Shirriff
maintainer=Mark Szabo, David Conran, Sebastien Warin, Roi Dayan, Massimiliano Pinto
sentence=Send and receive infrared signals with multiple protocols (ESP8266/ESP32)
+140 -72
View File
@@ -95,7 +95,7 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
#if SEND_AMCOR
case decode_type_t::AMCOR:
#endif
#if SEND_AMCOR
#if SEND_ARGO
case decode_type_t::ARGO:
#endif
#if SEND_COOLIX
@@ -143,6 +143,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
#if SEND_HITACHI_AC
case decode_type_t::HITACHI_AC:
#endif
#if SEND_HITACHI_AC424
case decode_type_t::HITACHI_AC424:
#endif
#if SEND_KELVINATOR
case decode_type_t::KELVINATOR:
#endif
@@ -664,6 +667,31 @@ void IRac::hitachi(IRHitachiAc *ac,
}
#endif // SEND_HITACHI_AC
#if SEND_HITACHI_AC424
void IRac::hitachi424(IRHitachiAc424 *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv) {
ac->begin();
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
ac->setFan(ac->convertFan(fan));
ac->setPower(on);
// SwingVToggle is special. Needs to be last method called.
ac->setSwingVToggle(swingv != stdAc::swingv_t::kOff);
// No Swing(H) setting available.
// No Quiet setting available.
// No Turbo setting available.
// No Light setting available.
// No Filter setting available.
// No Clean setting available.
// No Beep setting available.
// No Sleep setting available.
// No Clock setting available.
ac->send();
}
#endif // SEND_HITACHI_AC424
#if SEND_KELVINATOR
void IRac::kelvinator(IRKelvinatorAC *ac,
const bool on, const stdAc::opmode_t mode,
@@ -1148,6 +1176,7 @@ stdAc::state_t IRac::handleToggles(const stdAc::state_t desired,
result.light = desired.light ^ prev->light;
break;
case decode_type_t::MIDEA:
case decode_type_t::HITACHI_AC424:
if ((desired.swingv == stdAc::swingv_t::kOff) ^
(prev->swingv == stdAc::swingv_t::kOff)) // It changed, so toggle.
result.swingv = stdAc::swingv_t::kAuto;
@@ -1383,6 +1412,14 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
break;
}
#endif // SEND_HITACHI_AC
#if SEND_HITACHI_AC424
case HITACHI_AC424:
{
IRHitachiAc424 ac(_pin, _inverted, _modulation);
hitachi424(&ac, on, send.mode, degC, send.fanspeed, send.swingv);
break;
}
#endif // SEND_HITACHI_AC424
#if SEND_KELVINATOR
case KELVINATOR:
{
@@ -1567,25 +1604,25 @@ bool IRac::hasStateChanged(void) { return cmpStates(next, _prev); }
stdAc::opmode_t IRac::strToOpmode(const char *str,
const stdAc::opmode_t def) {
if (!strcasecmp(str, kAutoStr.c_str()) ||
!strcasecmp(str, kAutomaticStr.c_str()))
if (!strcasecmp(str, kAutoStr) ||
!strcasecmp(str, kAutomaticStr))
return stdAc::opmode_t::kAuto;
else if (!strcasecmp(str, kOffStr.c_str()) ||
!strcasecmp(str, kStopStr.c_str()))
else if (!strcasecmp(str, kOffStr) ||
!strcasecmp(str, kStopStr))
return stdAc::opmode_t::kOff;
else if (!strcasecmp(str, kCoolStr.c_str()) ||
else if (!strcasecmp(str, kCoolStr) ||
!strcasecmp(str, "COOLING"))
return stdAc::opmode_t::kCool;
else if (!strcasecmp(str, kHeatStr.c_str()) ||
else if (!strcasecmp(str, kHeatStr) ||
!strcasecmp(str, "HEATING"))
return stdAc::opmode_t::kHeat;
else if (!strcasecmp(str, kDryStr.c_str()) ||
else if (!strcasecmp(str, kDryStr) ||
!strcasecmp(str, "DRYING") ||
!strcasecmp(str, "DEHUMIDIFY"))
return stdAc::opmode_t::kDry;
else if (!strcasecmp(str, kFanStr.c_str()) ||
else if (!strcasecmp(str, kFanStr) ||
!strcasecmp(str, "FANONLY") ||
!strcasecmp(str, kFanOnlyStr.c_str()))
!strcasecmp(str, kFanOnlyStr))
return stdAc::opmode_t::kFan;
else
return def;
@@ -1593,26 +1630,26 @@ stdAc::opmode_t IRac::strToOpmode(const char *str,
stdAc::fanspeed_t IRac::strToFanspeed(const char *str,
const stdAc::fanspeed_t def) {
if (!strcasecmp(str, kAutoStr.c_str()) ||
!strcasecmp(str, kAutomaticStr.c_str()))
if (!strcasecmp(str, kAutoStr) ||
!strcasecmp(str, kAutomaticStr))
return stdAc::fanspeed_t::kAuto;
else if (!strcasecmp(str, kMinStr.c_str()) ||
!strcasecmp(str, kMinimumStr.c_str()) ||
!strcasecmp(str, kLowestStr.c_str()))
else if (!strcasecmp(str, kMinStr) ||
!strcasecmp(str, kMinimumStr) ||
!strcasecmp(str, kLowestStr))
return stdAc::fanspeed_t::kMin;
else if (!strcasecmp(str, kLowStr.c_str()) ||
!strcasecmp(str, kLoStr.c_str()))
else if (!strcasecmp(str, kLowStr) ||
!strcasecmp(str, kLoStr))
return stdAc::fanspeed_t::kLow;
else if (!strcasecmp(str, kMedStr.c_str()) ||
!strcasecmp(str, kMediumStr.c_str()) ||
!strcasecmp(str, kMidStr.c_str()))
else if (!strcasecmp(str, kMedStr) ||
!strcasecmp(str, kMediumStr) ||
!strcasecmp(str, kMidStr))
return stdAc::fanspeed_t::kMedium;
else if (!strcasecmp(str, kHighStr.c_str()) ||
!strcasecmp(str, kHiStr.c_str()))
else if (!strcasecmp(str, kHighStr) ||
!strcasecmp(str, kHiStr))
return stdAc::fanspeed_t::kHigh;
else if (!strcasecmp(str, kMaxStr.c_str()) ||
!strcasecmp(str, kMaximumStr.c_str()) ||
!strcasecmp(str, kHighestStr.c_str()))
else if (!strcasecmp(str, kMaxStr) ||
!strcasecmp(str, kMaximumStr) ||
!strcasecmp(str, kHighestStr))
return stdAc::fanspeed_t::kMax;
else
return def;
@@ -1620,36 +1657,36 @@ stdAc::fanspeed_t IRac::strToFanspeed(const char *str,
stdAc::swingv_t IRac::strToSwingV(const char *str,
const stdAc::swingv_t def) {
if (!strcasecmp(str, kAutoStr.c_str()) ||
!strcasecmp(str, kAutomaticStr.c_str()) ||
!strcasecmp(str, kOnStr.c_str()) ||
!strcasecmp(str, kSwingStr.c_str()))
if (!strcasecmp(str, kAutoStr) ||
!strcasecmp(str, kAutomaticStr) ||
!strcasecmp(str, kOnStr) ||
!strcasecmp(str, kSwingStr))
return stdAc::swingv_t::kAuto;
else if (!strcasecmp(str, kOffStr.c_str()) ||
!strcasecmp(str, kStopStr.c_str()))
else if (!strcasecmp(str, kOffStr) ||
!strcasecmp(str, kStopStr))
return stdAc::swingv_t::kOff;
else if (!strcasecmp(str, kMinStr.c_str()) ||
!strcasecmp(str, kMinimumStr.c_str()) ||
!strcasecmp(str, kLowestStr.c_str()) ||
!strcasecmp(str, kBottomStr.c_str()) ||
!strcasecmp(str, kDownStr.c_str()))
else if (!strcasecmp(str, kMinStr) ||
!strcasecmp(str, kMinimumStr) ||
!strcasecmp(str, kLowestStr) ||
!strcasecmp(str, kBottomStr) ||
!strcasecmp(str, kDownStr))
return stdAc::swingv_t::kLowest;
else if (!strcasecmp(str, kLowStr.c_str()))
else if (!strcasecmp(str, kLowStr))
return stdAc::swingv_t::kLow;
else if (!strcasecmp(str, kMidStr.c_str()) ||
!strcasecmp(str, kMiddleStr.c_str()) ||
!strcasecmp(str, kMedStr.c_str()) ||
!strcasecmp(str, kMediumStr.c_str()) ||
!strcasecmp(str, kCentreStr.c_str()))
else if (!strcasecmp(str, kMidStr) ||
!strcasecmp(str, kMiddleStr) ||
!strcasecmp(str, kMedStr) ||
!strcasecmp(str, kMediumStr) ||
!strcasecmp(str, kCentreStr))
return stdAc::swingv_t::kMiddle;
else if (!strcasecmp(str, kHighStr.c_str()) ||
!strcasecmp(str, kHiStr.c_str()))
else if (!strcasecmp(str, kHighStr) ||
!strcasecmp(str, kHiStr))
return stdAc::swingv_t::kHigh;
else if (!strcasecmp(str, kHighestStr.c_str()) ||
!strcasecmp(str, kMaxStr.c_str()) ||
!strcasecmp(str, kMaximumStr.c_str()) ||
!strcasecmp(str, kTopStr.c_str()) ||
!strcasecmp(str, kUpStr.c_str()))
else if (!strcasecmp(str, kHighestStr) ||
!strcasecmp(str, kMaxStr) ||
!strcasecmp(str, kMaximumStr) ||
!strcasecmp(str, kTopStr) ||
!strcasecmp(str, kUpStr))
return stdAc::swingv_t::kHighest;
else
return def;
@@ -1657,34 +1694,34 @@ stdAc::swingv_t IRac::strToSwingV(const char *str,
stdAc::swingh_t IRac::strToSwingH(const char *str,
const stdAc::swingh_t def) {
if (!strcasecmp(str, kAutoStr.c_str()) ||
!strcasecmp(str, kAutomaticStr.c_str()) ||
!strcasecmp(str, kOnStr.c_str()) || !strcasecmp(str, kSwingStr.c_str()))
if (!strcasecmp(str, kAutoStr) ||
!strcasecmp(str, kAutomaticStr) ||
!strcasecmp(str, kOnStr) || !strcasecmp(str, kSwingStr))
return stdAc::swingh_t::kAuto;
else if (!strcasecmp(str, kOffStr.c_str()) ||
!strcasecmp(str, kStopStr.c_str()))
else if (!strcasecmp(str, kOffStr) ||
!strcasecmp(str, kStopStr))
return stdAc::swingh_t::kOff;
else if (!strcasecmp(str, kLeftMaxStr.c_str()) ||
else if (!strcasecmp(str, kLeftMaxStr) ||
!strcasecmp(str, D_STR_LEFT " " D_STR_MAX) ||
!strcasecmp(str, D_STR_MAX D_STR_LEFT) ||
!strcasecmp(str, kMaxLeftStr.c_str()))
!strcasecmp(str, kMaxLeftStr))
return stdAc::swingh_t::kLeftMax;
else if (!strcasecmp(str, kLeftStr.c_str()))
else if (!strcasecmp(str, kLeftStr))
return stdAc::swingh_t::kLeft;
else if (!strcasecmp(str, kMidStr.c_str()) ||
!strcasecmp(str, kMiddleStr.c_str()) ||
!strcasecmp(str, kMedStr.c_str()) ||
!strcasecmp(str, kMediumStr.c_str()) ||
!strcasecmp(str, kCentreStr.c_str()))
else if (!strcasecmp(str, kMidStr) ||
!strcasecmp(str, kMiddleStr) ||
!strcasecmp(str, kMedStr) ||
!strcasecmp(str, kMediumStr) ||
!strcasecmp(str, kCentreStr))
return stdAc::swingh_t::kMiddle;
else if (!strcasecmp(str, kRightStr.c_str()))
else if (!strcasecmp(str, kRightStr))
return stdAc::swingh_t::kRight;
else if (!strcasecmp(str, kRightMaxStr.c_str()) ||
else if (!strcasecmp(str, kRightMaxStr) ||
!strcasecmp(str, D_STR_MAX " " D_STR_RIGHT) ||
!strcasecmp(str, D_STR_MAX D_STR_RIGHT) ||
!strcasecmp(str, kMaxRightStr.c_str()))
!strcasecmp(str, kMaxRightStr))
return stdAc::swingh_t::kRightMax;
else if (!strcasecmp(str, kWideStr.c_str()))
else if (!strcasecmp(str, kWideStr))
return stdAc::swingh_t::kWide;
else
return def;
@@ -1737,15 +1774,15 @@ int16_t IRac::strToModel(const char *str, const int16_t def) {
}
bool IRac::strToBool(const char *str, const bool def) {
if (!strcasecmp(str, kOnStr.c_str()) ||
if (!strcasecmp(str, kOnStr) ||
!strcasecmp(str, "1") ||
!strcasecmp(str, kYesStr.c_str()) ||
!strcasecmp(str, kTrueStr.c_str()))
!strcasecmp(str, kYesStr) ||
!strcasecmp(str, kTrueStr))
return true;
else if (!strcasecmp(str, kOffStr.c_str()) ||
else if (!strcasecmp(str, kOffStr) ||
!strcasecmp(str, "0") ||
!strcasecmp(str, kNoStr.c_str()) ||
!strcasecmp(str, kFalseStr.c_str()))
!strcasecmp(str, kNoStr) ||
!strcasecmp(str, kFalseStr))
return false;
else
return def;
@@ -2057,6 +2094,13 @@ namespace IRAcUtils {
return ac.toString();
}
#endif // DECODE_HITACHI_AC
#if DECODE_HITACHI_AC424
case decode_type_t::HITACHI_AC424: {
IRHitachiAc424 ac(0);
ac.setRaw(result->state);
return ac.toString();
}
#endif // DECODE_HITACHI_AC424
#if DECODE_WHIRLPOOL_AC
case decode_type_t::WHIRLPOOL_AC: {
IRWhirlpoolAc ac(0);
@@ -2135,6 +2179,22 @@ namespace IRAcUtils {
break;
}
#endif // DECODE_DAIKIN
#if DECODE_DAIKIN128
case decode_type_t::DAIKIN128: {
IRDaikin128 ac(0);
ac.setRaw(decode->state);
*result = ac.toCommon();
break;
}
#endif // DECODE_DAIKIN128
#if DECODE_DAIKIN152
case decode_type_t::DAIKIN152: {
IRDaikin152 ac(0);
ac.setRaw(decode->state);
*result = ac.toCommon();
break;
}
#endif // DECODE_DAIKIN152
#if DECODE_DAIKIN160
case decode_type_t::DAIKIN160: {
IRDaikin160 ac(kGpioUnused);
@@ -2223,6 +2283,14 @@ namespace IRAcUtils {
break;
}
#endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC2)
#if DECODE_HITACHI_AC424
case decode_type_t::HITACHI_AC424: {
IRHitachiAc424 ac(kGpioUnused);
ac.setRaw(decode->state);
*result = ac.toCommon();
break;
}
#endif // DECODE_HITACHI_AC424
#if DECODE_KELVINATOR
case decode_type_t::KELVINATOR: {
IRKelvinatorAC ac(kGpioUnused);
+6
View File
@@ -216,6 +216,12 @@ void electra(IRElectraAc *ac,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh);
#endif // SEND_HITACHI_AC
#if SEND_HITACHI_AC424
void hitachi424(IRHitachiAc424 *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv);
#endif // SEND_HITACHI_AC424
#if SEND_KELVINATOR
void kelvinator(IRKelvinatorAC *ac,
const bool on, const stdAc::opmode_t mode,
+6 -1
View File
@@ -560,11 +560,16 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) {
DPRINTLN("Attempting Haier AC YR-W02 decode");
if (decodeHaierACYRW02(results)) return true;
#endif
#if DECODE_HITACHI_AC424
// HitachiAc424 should be checked before HitachiAC & HitachiAC2
DPRINTLN("Attempting Hitachi AC 424 decode");
if (decodeHitachiAc424(results, kHitachiAc424Bits)) return true;
#endif // DECODE_HITACHI_AC2
#if DECODE_HITACHI_AC2
// HitachiAC2 should be checked before HitachiAC
DPRINTLN("Attempting Hitachi AC2 decode");
if (decodeHitachiAC(results, kHitachiAc2Bits)) return true;
#endif
#endif // DECODE_HITACHI_AC2
#if DECODE_HITACHI_AC
DPRINTLN("Attempting Hitachi AC decode");
if (decodeHitachiAC(results, kHitachiAcBits)) return true;
+5
View File
@@ -446,6 +446,11 @@ class IRrecv {
const uint16_t nbits = kHitachiAc1Bits,
const bool strict = true);
#endif
#if DECODE_HITACHI_AC424
bool decodeHitachiAc424(decode_results *results,
const uint16_t nbits = kHitachiAc424Bits,
const bool strict = true);
#endif // DECODE_HITACHI_AC424
#if DECODE_GICABLE
bool decodeGICable(decode_results *results, uint16_t nbits = kGicableBits,
bool strict = true);
+9 -3
View File
@@ -52,7 +52,7 @@
#endif // UNIT_TEST
// Library Version
#define _IRREMOTEESP8266_VERSION_ "2.6.6"
#define _IRREMOTEESP8266_VERSION_ "2.7.0"
// Set the language & locale for the library. See the `locale` dir for options.
#ifndef _IR_LOCALE_
@@ -266,6 +266,9 @@
#define DECODE_DAIKIN152 true
#define SEND_DAIKIN152 true
#define DECODE_HITACHI_AC424 true
#define SEND_HITACHI_AC424 true
#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 || \
@@ -276,7 +279,7 @@
DECODE_DAIKIN216 || DECODE_SHARP_AC || DECODE_DAIKIN160 || \
DECODE_NEOCLIMA || DECODE_DAIKIN176 || DECODE_DAIKIN128 || \
DECODE_AMCOR || DECODE_DAIKIN152 || DECODE_MITSUBISHI136 || \
DECODE_MITSUBISHI112)
DECODE_MITSUBISHI112 || DECODE_HITACHI_AC424)
#define DECODE_AC true // We need some common infrastructure for decoding A/Cs.
#else
#define DECODE_AC false // We don't need that infrastructure.
@@ -368,8 +371,9 @@ enum decode_type_t {
DAIKIN152, // 70
MITSUBISHI136,
MITSUBISHI112,
HITACHI_AC424,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = MITSUBISHI112,
kLastDecodeType = HITACHI_AC424,
};
// Message lengths & required repeat values
@@ -444,6 +448,8 @@ const uint16_t kHitachiAc1StateLength = 13;
const uint16_t kHitachiAc1Bits = kHitachiAc1StateLength * 8;
const uint16_t kHitachiAc2StateLength = 53;
const uint16_t kHitachiAc2Bits = kHitachiAc2StateLength * 8;
const uint16_t kHitachiAc424StateLength = 53;
const uint16_t kHitachiAc424Bits = kHitachiAc424StateLength * 8;
const uint16_t kInaxBits = 24;
const uint16_t kInaxMinRepeat = kSingleRepeat;
const uint16_t kJvcBits = 16;
+7
View File
@@ -608,6 +608,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return kHitachiAc1Bits;
case HITACHI_AC2:
return kHitachiAc2Bits;
case HITACHI_AC424:
return kHitachiAc424Bits;
case KELVINATOR:
return kKelvinatorBits;
case MITSUBISHI_AC:
@@ -934,6 +936,11 @@ bool IRsend::send(const decode_type_t type, const unsigned char *state,
sendHitachiAC2(state, nbytes);
break;
#endif // SEND_HITACHI_AC2
#if SEND_HITACHI_AC424
case HITACHI_AC424:
sendHitachiAc424(state, nbytes);
break;
#endif // SEND_HITACHI_AC424
#if SEND_KELVINATOR
case KELVINATOR:
sendKelvinator(state, nbytes);
+7 -2
View File
@@ -457,13 +457,18 @@ class IRsend {
#if SEND_HITACHI_AC1
void sendHitachiAC1(const unsigned char data[],
const uint16_t nbytes = kHitachiAc1StateLength,
const uint16_t repeat = kNoRepeat);
const uint16_t repeat = kHitachiAcDefaultRepeat);
#endif
#if SEND_HITACHI_AC2
void sendHitachiAC2(const unsigned char data[],
const uint16_t nbytes = kHitachiAc2StateLength,
const uint16_t repeat = kNoRepeat);
const uint16_t repeat = kHitachiAcDefaultRepeat);
#endif
#if SEND_HITACHI_AC424
void sendHitachiAc424(const unsigned char data[],
const uint16_t nbytes = kHitachiAc424StateLength,
const uint16_t repeat = kHitachiAcDefaultRepeat);
#endif // SEND_HITACHI_AC424
#if SEND_GICABLE
void sendGICable(uint64_t data, uint16_t nbits = kGicableBits,
uint16_t repeat = kGicableMinRepeat);
+143 -129
View File
@@ -6,144 +6,158 @@
#include "IRremoteESP8266.h"
#include "i18n.h"
#ifndef PROGMEM
#define PROGMEM // Pretend we have the PROGMEM macro even if we really don't.
#endif
// Common
String kUnknownStr = D_STR_UNKNOWN;
String kProtocolStr = D_STR_PROTOCOL;
String kPowerStr = D_STR_POWER;
String kOnStr = D_STR_ON;
String kOffStr = D_STR_OFF;
String kModeStr = D_STR_MODE;
String kToggleStr = D_STR_TOGGLE;
String kTurboStr = D_STR_TURBO;
String kSuperStr = D_STR_SUPER;
String kSleepStr = D_STR_SLEEP;
String kLightStr = D_STR_LIGHT;
String kPowerfulStr = D_STR_POWERFUL;
String kQuietStr = D_STR_QUIET;
String kEconoStr = D_STR_ECONO;
String kSwingStr = D_STR_SWING;
String kSwingHStr = D_STR_SWINGH;
String kSwingVStr = D_STR_SWINGV;
String kBeepStr = D_STR_BEEP;
String kZoneFollowStr = D_STR_ZONEFOLLOW;
String kFixedStr = D_STR_FIXED;
String kMouldStr = D_STR_MOULD;
String kCleanStr = D_STR_CLEAN;
String kPurifyStr = D_STR_PURIFY;
String kTimerStr = D_STR_TIMER;
String kOnTimerStr = D_STR_ONTIMER;
String kOffTimerStr = D_STR_OFFTIMER;
String kClockStr = D_STR_CLOCK;
String kCommandStr = D_STR_COMMAND;
String kXFanStr = D_STR_XFAN;
String kHealthStr = D_STR_HEALTH;
String kModelStr = D_STR_MODEL;
String kTempStr = D_STR_TEMP;
String kIFeelStr = D_STR_IFEEL;
String kHumidStr = D_STR_HUMID;
String kSaveStr = D_STR_SAVE;
String kEyeStr = D_STR_EYE;
String kFollowStr = D_STR_FOLLOW;
String kIonStr = D_STR_ION;
String kFreshStr = D_STR_FRESH;
String kHoldStr = D_STR_HOLD;
String kButtonStr = D_STR_BUTTON;
String k8CHeatStr = D_STR_8C_HEAT;
String kNightStr = D_STR_NIGHT;
String kSilentStr = D_STR_SILENT;
String kFilterStr = D_STR_FILTER;
String k3DStr = D_STR_3D;
String kCelsiusStr = D_STR_CELSIUS;
String kTempUpStr = D_STR_TEMPUP;
String kTempDownStr = D_STR_TEMPDOWN;
String kStartStr = D_STR_START;
String kStopStr = D_STR_STOP;
String kMoveStr = D_STR_MOVE;
String kSetStr = D_STR_SET;
String kCancelStr = D_STR_CANCEL;
String kUpStr = D_STR_UP;
String kDownStr = D_STR_DOWN;
String kChangeStr = D_STR_CHANGE;
String kComfortStr = D_STR_COMFORT;
String kSensorStr = D_STR_SENSOR;
String kWeeklyTimerStr = D_STR_WEEKLYTIMER;
String kWifiStr = D_STR_WIFI;
String kLastStr = D_STR_LAST;
String kFastStr = D_STR_FAST;
String kSlowStr = D_STR_SLOW;
String kAirFlowStr = D_STR_AIRFLOW;
String kStepStr = D_STR_STEP;
String kNAStr = D_STR_NA;
String kOutsideStr = D_STR_OUTSIDE;
String kLoudStr = D_STR_LOUD;
String kLowerStr = D_STR_LOWER;
String kUpperStr = D_STR_UPPER;
String kBreezeStr = D_STR_BREEZE;
String kCirculateStr = D_STR_CIRCULATE;
String kCeilingStr = D_STR_CEILING;
String kWallStr = D_STR_WALL;
String kRoomStr = D_STR_ROOM;
String k6thSenseStr = D_STR_6THSENSE;
const PROGMEM char* kUnknownStr = D_STR_UNKNOWN;
const PROGMEM char* kProtocolStr = D_STR_PROTOCOL;
const PROGMEM char* kPowerStr = D_STR_POWER;
const PROGMEM char* kOnStr = D_STR_ON;
const PROGMEM char* kOffStr = D_STR_OFF;
const PROGMEM char* kModeStr = D_STR_MODE;
const PROGMEM char* kToggleStr = D_STR_TOGGLE;
const PROGMEM char* kTurboStr = D_STR_TURBO;
const PROGMEM char* kSuperStr = D_STR_SUPER;
const PROGMEM char* kSleepStr = D_STR_SLEEP;
const PROGMEM char* kLightStr = D_STR_LIGHT;
const PROGMEM char* kPowerfulStr = D_STR_POWERFUL;
const PROGMEM char* kQuietStr = D_STR_QUIET;
const PROGMEM char* kEconoStr = D_STR_ECONO;
const PROGMEM char* kSwingStr = D_STR_SWING;
const PROGMEM char* kSwingHStr = D_STR_SWINGH;
const PROGMEM char* kSwingVStr = D_STR_SWINGV;
const PROGMEM char* kBeepStr = D_STR_BEEP;
const PROGMEM char* kZoneFollowStr = D_STR_ZONEFOLLOW;
const PROGMEM char* kFixedStr = D_STR_FIXED;
const PROGMEM char* kMouldStr = D_STR_MOULD;
const PROGMEM char* kCleanStr = D_STR_CLEAN;
const PROGMEM char* kPurifyStr = D_STR_PURIFY;
const PROGMEM char* kTimerStr = D_STR_TIMER;
const PROGMEM char* kOnTimerStr = D_STR_ONTIMER;
const PROGMEM char* kOffTimerStr = D_STR_OFFTIMER;
const PROGMEM char* kClockStr = D_STR_CLOCK;
const PROGMEM char* kCommandStr = D_STR_COMMAND;
const PROGMEM char* kXFanStr = D_STR_XFAN;
const PROGMEM char* kHealthStr = D_STR_HEALTH;
const PROGMEM char* kModelStr = D_STR_MODEL;
const PROGMEM char* kTempStr = D_STR_TEMP;
const PROGMEM char* kIFeelStr = D_STR_IFEEL;
const PROGMEM char* kHumidStr = D_STR_HUMID;
const PROGMEM char* kSaveStr = D_STR_SAVE;
const PROGMEM char* kEyeStr = D_STR_EYE;
const PROGMEM char* kFollowStr = D_STR_FOLLOW;
const PROGMEM char* kIonStr = D_STR_ION;
const PROGMEM char* kFreshStr = D_STR_FRESH;
const PROGMEM char* kHoldStr = D_STR_HOLD;
const PROGMEM char* kButtonStr = D_STR_BUTTON;
const PROGMEM char* k8CHeatStr = D_STR_8C_HEAT;
const PROGMEM char* kNightStr = D_STR_NIGHT;
const PROGMEM char* kSilentStr = D_STR_SILENT;
const PROGMEM char* kFilterStr = D_STR_FILTER;
const PROGMEM char* k3DStr = D_STR_3D;
const PROGMEM char* kCelsiusStr = D_STR_CELSIUS;
const PROGMEM char* kTempUpStr = D_STR_TEMPUP;
const PROGMEM char* kTempDownStr = D_STR_TEMPDOWN;
const PROGMEM char* kStartStr = D_STR_START;
const PROGMEM char* kStopStr = D_STR_STOP;
const PROGMEM char* kMoveStr = D_STR_MOVE;
const PROGMEM char* kSetStr = D_STR_SET;
const PROGMEM char* kCancelStr = D_STR_CANCEL;
const PROGMEM char* kUpStr = D_STR_UP;
const PROGMEM char* kDownStr = D_STR_DOWN;
const PROGMEM char* kChangeStr = D_STR_CHANGE;
const PROGMEM char* kComfortStr = D_STR_COMFORT;
const PROGMEM char* kSensorStr = D_STR_SENSOR;
const PROGMEM char* kWeeklyTimerStr = D_STR_WEEKLYTIMER;
const PROGMEM char* kWifiStr = D_STR_WIFI;
const PROGMEM char* kLastStr = D_STR_LAST;
const PROGMEM char* kFastStr = D_STR_FAST;
const PROGMEM char* kSlowStr = D_STR_SLOW;
const PROGMEM char* kAirFlowStr = D_STR_AIRFLOW;
const PROGMEM char* kStepStr = D_STR_STEP;
const PROGMEM char* kNAStr = D_STR_NA;
const PROGMEM char* kOutsideStr = D_STR_OUTSIDE;
const PROGMEM char* kLoudStr = D_STR_LOUD;
const PROGMEM char* kLowerStr = D_STR_LOWER;
const PROGMEM char* kUpperStr = D_STR_UPPER;
const PROGMEM char* kBreezeStr = D_STR_BREEZE;
const PROGMEM char* kCirculateStr = D_STR_CIRCULATE;
const PROGMEM char* kCeilingStr = D_STR_CEILING;
const PROGMEM char* kWallStr = D_STR_WALL;
const PROGMEM char* kRoomStr = D_STR_ROOM;
const PROGMEM char* k6thSenseStr = D_STR_6THSENSE;
String kAutoStr = D_STR_AUTO;
String kAutomaticStr = D_STR_AUTOMATIC;
String kManualStr = D_STR_MANUAL;
String kCoolStr = D_STR_COOL;
String kHeatStr = D_STR_HEAT;
String kFanStr = D_STR_FAN;
String kDryStr = D_STR_DRY;
String kFanOnlyStr = D_STR_FANONLY;
const PROGMEM char* kAutoStr = D_STR_AUTO;
const PROGMEM char* kAutomaticStr = D_STR_AUTOMATIC;
const PROGMEM char* kManualStr = D_STR_MANUAL;
const PROGMEM char* kCoolStr = D_STR_COOL;
const PROGMEM char* kHeatStr = D_STR_HEAT;
const PROGMEM char* kFanStr = D_STR_FAN;
const PROGMEM char* kDryStr = D_STR_DRY;
const PROGMEM char* kFanOnlyStr = D_STR_FANONLY;
String kMaxStr = D_STR_MAX;
String kMaximumStr = D_STR_MAXIMUM;
String kMinStr = D_STR_MIN;
String kMinimumStr = D_STR_MINIMUM;
String kMedStr = D_STR_MED;
String kMediumStr = D_STR_MEDIUM;
const PROGMEM char* kMaxStr = D_STR_MAX;
const PROGMEM char* kMaximumStr = D_STR_MAXIMUM;
const PROGMEM char* kMinStr = D_STR_MIN;
const PROGMEM char* kMinimumStr = D_STR_MINIMUM;
const PROGMEM char* kMedStr = D_STR_MED;
const PROGMEM char* kMediumStr = D_STR_MEDIUM;
String kHighestStr = D_STR_HIGHEST;
String kHighStr = D_STR_HIGH;
String kHiStr = D_STR_HI;
String kMidStr = D_STR_MID;
String kMiddleStr = D_STR_MIDDLE;
String kLowStr = D_STR_LOW;
String kLoStr = D_STR_LO;
String kLowestStr = D_STR_LOWEST;
String kMaxRightStr = D_STR_MAXRIGHT;
String kRightMaxStr = D_STR_RIGHTMAX_NOSPACE;
String kRightStr = D_STR_RIGHT;
String kLeftStr = D_STR_LEFT;
String kMaxLeftStr = D_STR_MAXLEFT;
String kLeftMaxStr = D_STR_LEFTMAX_NOSPACE;
String kWideStr = D_STR_WIDE;
String kCentreStr = D_STR_CENTRE;
String kTopStr = D_STR_TOP;
String kBottomStr = D_STR_BOTTOM;
const PROGMEM char* kHighestStr = D_STR_HIGHEST;
const PROGMEM char* kHighStr = D_STR_HIGH;
const PROGMEM char* kHiStr = D_STR_HI;
const PROGMEM char* kMidStr = D_STR_MID;
const PROGMEM char* kMiddleStr = D_STR_MIDDLE;
const PROGMEM char* kLowStr = D_STR_LOW;
const PROGMEM char* kLoStr = D_STR_LO;
const PROGMEM char* kLowestStr = D_STR_LOWEST;
const PROGMEM char* kMaxRightStr = D_STR_MAXRIGHT;
const PROGMEM char* kRightMaxStr = D_STR_RIGHTMAX_NOSPACE;
const PROGMEM char* kRightStr = D_STR_RIGHT;
const PROGMEM char* kLeftStr = D_STR_LEFT;
const PROGMEM char* kMaxLeftStr = D_STR_MAXLEFT;
const PROGMEM char* kLeftMaxStr = D_STR_LEFTMAX_NOSPACE;
const PROGMEM char* kWideStr = D_STR_WIDE;
const PROGMEM char* kCentreStr = D_STR_CENTRE;
const PROGMEM char* kTopStr = D_STR_TOP;
const PROGMEM char* kBottomStr = D_STR_BOTTOM;
String kSpaceLBraceStr = D_STR_SPACELBRACE;
String kCommaSpaceStr = D_STR_COMMASPACE;
String kColonSpaceStr = D_STR_COLONSPACE;
const PROGMEM char* kSpaceLBraceStr = D_STR_SPACELBRACE;
const PROGMEM char* kCommaSpaceStr = D_STR_COMMASPACE;
const PROGMEM char* kColonSpaceStr = D_STR_COLONSPACE;
// IRutils
// - Time
char kTimeSep = D_CHR_TIME_SEP;
String kDayStr = D_STR_DAY;
String kDaysStr = D_STR_DAYS;
String kHourStr = D_STR_HOUR;
String kHoursStr = D_STR_HOURS;
String kMinuteStr = D_STR_MINUTE;
String kMinutesStr = D_STR_MINUTES;
String kSecondStr = D_STR_SECOND;
String kSecondsStr = D_STR_SECONDS;
String kNowStr = D_STR_NOW;
String kThreeLetterDayOfWeekStr = D_STR_THREELETTERDAYS;
const PROGMEM char* kDayStr = D_STR_DAY;
const PROGMEM char* kDaysStr = D_STR_DAYS;
const PROGMEM char* kHourStr = D_STR_HOUR;
const PROGMEM char* kHoursStr = D_STR_HOURS;
const PROGMEM char* kMinuteStr = D_STR_MINUTE;
const PROGMEM char* kMinutesStr = D_STR_MINUTES;
const PROGMEM char* kSecondStr = D_STR_SECOND;
const PROGMEM char* kSecondsStr = D_STR_SECONDS;
const PROGMEM char* kNowStr = D_STR_NOW;
const PROGMEM char* kThreeLetterDayOfWeekStr = D_STR_THREELETTERDAYS;
String kYesStr = D_STR_YES;
String kNoStr = D_STR_NO;
String kTrueStr = D_STR_TRUE;
String kFalseStr = D_STR_FALSE;
const PROGMEM char* kYesStr = D_STR_YES;
const PROGMEM char* kNoStr = D_STR_NO;
const PROGMEM char* kTrueStr = D_STR_TRUE;
const PROGMEM char* kFalseStr = D_STR_FALSE;
String kRepeatStr = D_STR_REPEAT;
String kCodeStr = D_STR_CODE;
String kBitsStr = D_STR_BITS;
const PROGMEM char* kRepeatStr = D_STR_REPEAT;
const PROGMEM char* kCodeStr = D_STR_CODE;
const PROGMEM char* kBitsStr = D_STR_BITS;
// Misc
const PROGMEM char* kEyeAutoStr = D_STR_EYE " " D_STR_AUTO;
const PROGMEM char* kLightToggleStr = D_STR_LIGHT " " D_STR_TOGGLE;
const PROGMEM char* kOutsideQuietStr = D_STR_OUTSIDE " " D_STR_QUIET;
const PROGMEM char* kPowerToggleStr = D_STR_POWER " " D_STR_TOGGLE;
const PROGMEM char* kSensorTempStr = D_STR_SENSOR " " D_STR_TEMP;
const PROGMEM char* kSleepTimerStr = D_STR_SLEEP " " D_STR_TIMER;
const PROGMEM char* kSwingVModeStr = D_STR_SWINGV " " D_STR_MODE;
const PROGMEM char* kSwingVToggleStr = D_STR_SWINGV " " D_STR_TOGGLE;
+138 -130
View File
@@ -12,135 +12,143 @@
// Constant text to be shared across all object files.
// This means there is only one copy of the character/string/text etc.
extern const char kTimeSep;
extern const String k3DStr;
extern const String k6thSenseStr;
extern const String k8CHeatStr;
extern const String kAirFlowStr;
extern const String kAutomaticStr;
extern const String kAutoStr;
extern const String kBeepStr;
extern const String kBitsStr;
extern const String kBottomStr;
extern const String kBreezeStr;
extern const String kButtonStr;
extern const String kCancelStr;
extern const String kCeilingStr;
extern const String kCelsiusStr;
extern const String kCentreStr;
extern const String kChangeStr;
extern const String kCirculateStr;
extern const String kCleanStr;
extern const String kClockStr;
extern const String kCodeStr;
extern const String kColonSpaceStr;
extern const String kComfortStr;
extern const String kCommandStr;
extern const String kCommaSpaceStr;
extern const String kCoolStr;
extern const String kDaysStr;
extern const String kDayStr;
extern const String kDownStr;
extern const String kDryStr;
extern const String kEconoStr;
extern const String kEyeStr;
extern const String kFalseStr;
extern const String kFanOnlyStr;
extern const String kFanStr;
extern const String kFastStr;
extern const String kFilterStr;
extern const String kFixedStr;
extern const String kFollowStr;
extern const String kFreshStr;
extern const String kHealthStr;
extern const String kHeatStr;
extern const String kHighestStr;
extern const String kHighStr;
extern const String kHiStr;
extern const String kHoldStr;
extern const String kHoursStr;
extern const String kHourStr;
extern const String kHumidStr;
extern const String kIFeelStr;
extern const String kIonStr;
extern const String kLastStr;
extern const String kLeftMaxStr;
extern const String kLeftStr;
extern const String kLightStr;
extern const String kLoStr;
extern const String kLoudStr;
extern const String kLowerStr;
extern const String kLowestStr;
extern const String kLowStr;
extern const String kManualStr;
extern const String kMaximumStr;
extern const String kMaxLeftStr;
extern const String kMaxRightStr;
extern const String kMaxStr;
extern const String kMediumStr;
extern const String kMedStr;
extern const String kMiddleStr;
extern const String kMidStr;
extern const String kMinimumStr;
extern const String kMinStr;
extern const String kMinutesStr;
extern const String kMinuteStr;
extern const String kModelStr;
extern const String kModeStr;
extern const String kMouldStr;
extern const String kMoveStr;
extern const String kNAStr;
extern const String kNightStr;
extern const String kNoStr;
extern const String kNowStr;
extern const String kOffStr;
extern const String kOffTimerStr;
extern const String kOnStr;
extern const String kOnTimerStr;
extern const String kOutsideStr;
extern const String kPowerfulStr;
extern const String kPowerStr;
extern const String kProtocolStr;
extern const String kPurifyStr;
extern const String kQuietStr;
extern const String kRepeatStr;
extern const String kRightMaxStr;
extern const String kRightStr;
extern const String kRoomStr;
extern const String kSaveStr;
extern const String kSecondsStr;
extern const String kSecondStr;
extern const String kSensorStr;
extern const String kSetStr;
extern const String kSilentStr;
extern const String kSleepStr;
extern const String kSlowStr;
extern const String kSpaceLBraceStr;
extern const String kStartStr;
extern const String kStepStr;
extern const String kStopStr;
extern const String kSuperStr;
extern const String kSwingHStr;
extern const String kSwingStr;
extern const String kSwingVStr;
extern const String kTempDownStr;
extern const String kTempStr;
extern const String kTempUpStr;
extern const String kThreeLetterDayOfWeekStr;
extern const String kTimerStr;
extern const String kToggleStr;
extern const String kTopStr;
extern const String kTrueStr;
extern const String kTurboStr;
extern const String kUnknownStr;
extern const String kUpperStr;
extern const String kUpStr;
extern const String kWallStr;
extern const String kWeeklyTimerStr;
extern const String kWideStr;
extern const String kWifiStr;
extern const String kXFanStr;
extern const String kYesStr;
extern const String kZoneFollowStr;
extern char kTimeSep;
extern const char* k3DStr;
extern const char* k6thSenseStr;
extern const char* k8CHeatStr;
extern const char* kAirFlowStr;
extern const char* kAutomaticStr;
extern const char* kAutoStr;
extern const char* kBeepStr;
extern const char* kBitsStr;
extern const char* kBottomStr;
extern const char* kBreezeStr;
extern const char* kButtonStr;
extern const char* kCancelStr;
extern const char* kCeilingStr;
extern const char* kCelsiusStr;
extern const char* kCentreStr;
extern const char* kChangeStr;
extern const char* kCirculateStr;
extern const char* kCleanStr;
extern const char* kClockStr;
extern const char* kCodeStr;
extern const char* kColonSpaceStr;
extern const char* kComfortStr;
extern const char* kCommandStr;
extern const char* kCommaSpaceStr;
extern const char* kCoolStr;
extern const char* kDaysStr;
extern const char* kDayStr;
extern const char* kDownStr;
extern const char* kDryStr;
extern const char* kEconoStr;
extern const char* kEyeAutoStr;
extern const char* kEyeStr;
extern const char* kFalseStr;
extern const char* kFanOnlyStr;
extern const char* kFanStr;
extern const char* kFastStr;
extern const char* kFilterStr;
extern const char* kFixedStr;
extern const char* kFollowStr;
extern const char* kFreshStr;
extern const char* kHealthStr;
extern const char* kHeatStr;
extern const char* kHighestStr;
extern const char* kHighStr;
extern const char* kHiStr;
extern const char* kHoldStr;
extern const char* kHoursStr;
extern const char* kHourStr;
extern const char* kHumidStr;
extern const char* kIFeelStr;
extern const char* kIonStr;
extern const char* kLastStr;
extern const char* kLeftMaxStr;
extern const char* kLeftStr;
extern const char* kLightStr;
extern const char* kLightToggleStr;
extern const char* kLoStr;
extern const char* kLoudStr;
extern const char* kLowerStr;
extern const char* kLowestStr;
extern const char* kLowStr;
extern const char* kManualStr;
extern const char* kMaximumStr;
extern const char* kMaxLeftStr;
extern const char* kMaxRightStr;
extern const char* kMaxStr;
extern const char* kMediumStr;
extern const char* kMedStr;
extern const char* kMiddleStr;
extern const char* kMidStr;
extern const char* kMinimumStr;
extern const char* kMinStr;
extern const char* kMinutesStr;
extern const char* kMinuteStr;
extern const char* kModelStr;
extern const char* kModeStr;
extern const char* kMouldStr;
extern const char* kMoveStr;
extern const char* kNAStr;
extern const char* kNightStr;
extern const char* kNoStr;
extern const char* kNowStr;
extern const char* kOffStr;
extern const char* kOffTimerStr;
extern const char* kOnStr;
extern const char* kOnTimerStr;
extern const char* kOutsideQuietStr;
extern const char* kOutsideStr;
extern const char* kPowerfulStr;
extern const char* kPowerStr;
extern const char* kPowerToggleStr;
extern const char* kProtocolStr;
extern const char* kPurifyStr;
extern const char* kQuietStr;
extern const char* kRepeatStr;
extern const char* kRightMaxStr;
extern const char* kRightStr;
extern const char* kRoomStr;
extern const char* kSaveStr;
extern const char* kSecondsStr;
extern const char* kSecondStr;
extern const char* kSensorStr;
extern const char* kSensorTempStr;
extern const char* kSetStr;
extern const char* kSilentStr;
extern const char* kSleepStr;
extern const char* kSleepTimerStr;
extern const char* kSlowStr;
extern const char* kSpaceLBraceStr;
extern const char* kStartStr;
extern const char* kStepStr;
extern const char* kStopStr;
extern const char* kSuperStr;
extern const char* kSwingHStr;
extern const char* kSwingStr;
extern const char* kSwingVModeStr;
extern const char* kSwingVStr;
extern const char* kSwingVToggleStr;
extern const char* kTempDownStr;
extern const char* kTempStr;
extern const char* kTempUpStr;
extern const char* kThreeLetterDayOfWeekStr;
extern const char* kTimerStr;
extern const char* kToggleStr;
extern const char* kTopStr;
extern const char* kTrueStr;
extern const char* kTurboStr;
extern const char* kUnknownStr;
extern const char* kUpperStr;
extern const char* kUpStr;
extern const char* kWallStr;
extern const char* kWeeklyTimerStr;
extern const char* kWideStr;
extern const char* kWifiStr;
extern const char* kXFanStr;
extern const char* kYesStr;
extern const char* kZoneFollowStr;
#endif // IRTEXT_H_
+29 -14
View File
@@ -91,7 +91,7 @@ void serialPrintUint64(uint64_t input, uint8_t base) {
// Returns:
// A decode_type_t enum.
decode_type_t strToDecodeType(const char * const str) {
if (!strcasecmp(str, kUnknownStr.c_str()))
if (!strcasecmp(str, kUnknownStr))
return decode_type_t::UNKNOWN;
else if (!strcasecmp(str, "UNUSED"))
return decode_type_t::UNUSED;
@@ -145,6 +145,8 @@ decode_type_t strToDecodeType(const char * const str) {
return decode_type_t::HITACHI_AC1;
else if (!strcasecmp(str, "HITACHI_AC2"))
return decode_type_t::HITACHI_AC2;
else if (!strcasecmp(str, "HITACHI_AC424"))
return decode_type_t::HITACHI_AC424;
else if (!strcasecmp(str, "INAX"))
return decode_type_t::INAX;
else if (!strcasecmp(str, "JVC"))
@@ -336,6 +338,9 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) {
case HITACHI_AC2:
result = F("HITACHI_AC2");
break;
case HITACHI_AC424:
result = F("HITACHI_AC424");
break;
case INAX:
result = F("INAX");
break;
@@ -482,7 +487,11 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) {
result = kUnknownStr;
break;
}
if (isRepeat) result += kSpaceLBraceStr + kRepeatStr + ')';
if (isRepeat) {
result += kSpaceLBraceStr;
result += kRepeatStr;
result += ')';
}
return result;
}
@@ -506,6 +515,7 @@ bool hasACState(const decode_type_t protocol) {
case HITACHI_AC:
case HITACHI_AC1:
case HITACHI_AC2:
case HITACHI_AC424:
case KELVINATOR:
case MITSUBISHI136:
case MITSUBISHI112:
@@ -677,16 +687,20 @@ String resultToHumanReadableBasic(const decode_results * const results) {
// Reserve some space for the string to reduce heap fragmentation.
output.reserve(2 * kStateSizeMax + 50); // Should cover most cases.
// Show Encoding standard
output += kProtocolStr + F(" : ");
output += kProtocolStr;
output += F(" : ");
output += typeToString(results->decode_type, results->repeat);
output += '\n';
// Show Code & length
output += kCodeStr + F(" : ");
output += kCodeStr;
output += F(" : ");
output += resultToHexidecimal(results);
output += kSpaceLBraceStr;
output += uint64ToString(results->bits);
output += ' ' + kBitsStr + F(")\n");
output += ' ';
output += kBitsStr;
output += F(")\n");
return output;
}
@@ -885,10 +899,10 @@ namespace irutils {
result += kSpaceLBraceStr;
if ((uint8_t)(day_of_week + offset) < 7)
#if UNIT_TEST
result += kThreeLetterDayOfWeekStr.substr(
result += String(kThreeLetterDayOfWeekStr).substr(
(day_of_week + offset) * 3, 3);
#else // UNIT_TEST
result += kThreeLetterDayOfWeekStr.substring(
result += String(kThreeLetterDayOfWeekStr).substring(
(day_of_week + offset) * 3, (day_of_week + offset) * 3 + 3);
#endif // UNIT_TEST
else
@@ -985,21 +999,22 @@ namespace irutils {
String result = "";
if (days)
result += uint64ToString(days) + ' ' + ((days > 1) ? kDaysStr : kDayStr);
result += uint64ToString(days) + ' ' + String((days > 1) ? kDaysStr
: kDayStr);
if (hours) {
if (result.length()) result += ' ';
result += uint64ToString(hours) + ' ' + ((hours > 1) ? kHoursStr
: kHourStr);
result += uint64ToString(hours) + ' ' + String((hours > 1) ? kHoursStr
: kHourStr);
}
if (minutes) {
if (result.length()) result += ' ';
result += uint64ToString(minutes) + ' ' + ((minutes > 1) ? kMinutesStr
: kMinuteStr);
result += uint64ToString(minutes) + ' ' + String(
(minutes > 1) ? kMinutesStr : kMinuteStr);
}
if (seconds) {
if (result.length()) result += ' ';
result += uint64ToString(seconds) + ' ' + ((seconds > 1) ? kSecondsStr
: kSecondStr);
result += uint64ToString(seconds) + ' ' + String(
(seconds > 1) ? kSecondsStr : kSecondStr);
}
return result;
}
+6 -2
View File
@@ -332,7 +332,9 @@ String IRArgoAC::toString(void) {
result += kDryStr;
break;
case kArgoHeatAuto:
result += kHeatStr + ' ' + kAutoStr;
result += kHeatStr;
result += ' ';
result += kAutoStr;
break;
case kArgoOff:
result += kOffStr;
@@ -361,7 +363,9 @@ String IRArgoAC::toString(void) {
}
result += ')';
result += addTempToString(getTemp());
result += kCommaSpaceStr + kRoomStr + ' ';
result += kCommaSpaceStr;
result += kRoomStr;
result += ' ';
result += addTempToString(getRoomTemp(), true, false);
result += addBoolToString(getMax(), kMaxStr);
result += addBoolToString(getiFeel(), kIFeelStr);
+35 -24
View File
@@ -132,15 +132,15 @@ uint32_t IRCoolixAC::getRaw() { return remote_state; }
void IRCoolixAC::setRaw(const uint32_t new_code) {
if (!handleSpecialState(new_code)) {
// it isn`t special so might afect Temp|mode|Fan
// it isn`t special so might affect Temp|mode|Fan
if (new_code == kCoolixCmdFan) {
setMode(kCoolixFan);
} else {
// must be a command changing Temp|Mode|Fan
// it is safe to just copy to remote var
remote_state = new_code;
return;
}
}
// must be a command changing Temp|Mode|Fan
// it is safe to just copy to remote var
remote_state = new_code;
}
// Return true if the current state is a special state.
@@ -243,17 +243,13 @@ bool IRCoolixAC::getPower() {
}
void IRCoolixAC::setPower(const bool on) {
if (powerFlag) {
if (!on) {
updateSavedState();
remote_state = kCoolixOff;
}
} else {
if (on) {
// at this point remote_state must be ready
// to be transmitted
recoverSavedState();
}
if (!on) {
updateSavedState();
remote_state = kCoolixOff;
} else if (!powerFlag) {
// at this point remote_state must be ready
// to be transmitted
recoverSavedState();
}
powerFlag = on;
}
@@ -500,23 +496,38 @@ String IRCoolixAC::toString(void) {
if (!getPower()) return result; // If it's off, there is no other info.
// Special modes.
if (getSwing()) {
result += kCommaSpaceStr + kSwingStr + kColonSpaceStr + kToggleStr;
result += kCommaSpaceStr;
result += kSwingStr;
result += kColonSpaceStr;
result += kToggleStr;
return result;
}
if (getSleep()) {
result += kCommaSpaceStr + kSleepStr + kColonSpaceStr + kToggleStr;
result += kCommaSpaceStr;
result += kSleepStr;
result += kColonSpaceStr;
result += kToggleStr;
return result;
}
if (getTurbo()) {
result += kCommaSpaceStr + kTurboStr + kColonSpaceStr + kToggleStr;
result += kCommaSpaceStr;
result += kTurboStr;
result += kColonSpaceStr;
result += kToggleStr;
return result;
}
if (getLed()) {
result += kCommaSpaceStr + kLightStr + kColonSpaceStr + kToggleStr;
result += kCommaSpaceStr;
result += kLightStr;
result += kColonSpaceStr;
result += kToggleStr;
return result;
}
if (getClean()) {
result += kCommaSpaceStr + kCleanStr + kColonSpaceStr + kToggleStr;
result += kCommaSpaceStr;
result += kCleanStr;
result += kColonSpaceStr;
result += kToggleStr;
return result;
}
result += addModeToString(getMode(), kCoolixAuto, kCoolixCool, kCoolixHeat,
@@ -528,7 +539,8 @@ String IRCoolixAC::toString(void) {
result += kAutoStr;
break;
case kCoolixFanAuto0:
result += kAutoStr + '0';
result += kAutoStr;
result += '0';
break;
case kCoolixFanMax:
result += kMaxStr;
@@ -554,8 +566,7 @@ String IRCoolixAC::toString(void) {
result += addBoolToString(getZoneFollow(), kZoneFollowStr);
result += addLabeledString(
(getSensorTemp() > kCoolixSensorTempMax)
? kOffStr : uint64ToString(getSensorTemp()) + F("C"),
kSensorStr + ' ' + kTempStr);
? kOffStr : uint64ToString(getSensorTemp()) + 'C', kSensorTempStr);
return result;
}
+17 -10
View File
@@ -1102,10 +1102,19 @@ String IRDaikin2::toString(void) {
case kDaikin2SwingVHigh:
result += kHighestStr;
break;
case 2: result += kHighStr; break;
case 3: result += kUpperStr + kMiddleStr; break;
case 4: result += kLowerStr + kMiddleStr; break;
case 5: result += kLowStr; break;
case 2:
result += kHighStr;
break;
case 3:
result += kUpperStr;
result += kMiddleStr;
break;
case 4:
result += kLowerStr;
result += kMiddleStr;
break;
case 5:
result += kLowStr;
break;
case kDaikin2SwingVLow:
result += kLowestStr;
@@ -1146,7 +1155,7 @@ String IRDaikin2::toString(void) {
kOffTimerStr);
result += addLabeledString(
getSleepTimerEnabled() ? minsToString(getSleepTime()) : kOffStr,
kSleepStr + ' ' + kTimerStr);
kSleepTimerStr);
result += addIntToString(getBeep(), kBeepStr);
result += kSpaceLBraceStr;
switch (getBeep()) {
@@ -1185,7 +1194,7 @@ String IRDaikin2::toString(void) {
getFreshAir() ? (getFreshAirHigh() ? kHighStr : kOnStr) : kOffStr,
kFreshStr);
result += addBoolToString(getEye(), kEyeStr);
result += addBoolToString(getEyeAuto(), kEyeStr + ' ' + kAutoStr);
result += addBoolToString(getEyeAuto(), kEyeAutoStr);
result += addBoolToString(getQuiet(), kQuietStr);
result += addBoolToString(getPowerful(), kPowerfulStr);
result += addBoolToString(getPurify(), kPurifyStr);
@@ -1373,7 +1382,6 @@ void IRDaikin216::setRaw(const uint8_t new_code[]) {
memcpy(remote_state, new_code, kDaikin216StateLength);
}
void IRDaikin216::on(void) { setPower(true); }
void IRDaikin216::off(void) { setPower(false); }
@@ -2694,8 +2702,7 @@ uint8_t IRDaikin128::getLightToggle(void) {
String IRDaikin128::toString(void) {
String result = "";
result.reserve(240); // Reserve some heap for the string to reduce fragging.
result += addBoolToString(getPowerToggle(), kPowerStr + ' ' + kToggleStr,
false);
result += addBoolToString(getPowerToggle(), kPowerToggleStr, false);
result += addModeToString(getMode(), kDaikin128Auto, kDaikin128Cool,
kDaikin128Heat, kDaikin128Dry, kDaikin128Fan);
result += addTempToString(getTemp());
@@ -2712,7 +2719,7 @@ String IRDaikin128::toString(void) {
result += addLabeledString(minsToString(getOnTimer()), kOnTimerStr);
result += addBoolToString(getOffTimerEnabled(), kOffTimerStr);
result += addLabeledString(minsToString(getOffTimer()), kOffTimerStr);
result += addIntToString(getLightToggle(), kLightStr + ' ' + kToggleStr);
result += addIntToString(getLightToggle(), kLightToggleStr);
result += kSpaceLBraceStr;
switch (getLightToggle()) {
case kDaikin128BitCeiling: result += kCeilingStr; break;
+19 -7
View File
@@ -632,26 +632,38 @@ String IRFujitsuAC::toString(void) {
result += kSwingHStr;
break;
case kFujitsuAcSwingBoth:
result += kSwingVStr + '+' + kSwingHStr;
result += kSwingVStr;
result += '+';
result += kSwingHStr;
break;
default:
result += kUnknownStr;
}
result += ')';
}
result += kCommaSpaceStr + kCommandStr + kColonSpaceStr;
result += kCommaSpaceStr;
result += kCommandStr;
result += kColonSpaceStr;
switch (this->getCmd()) {
case kFujitsuAcCmdStepHoriz:
result += kStepStr + ' ' + kSwingHStr;
result += kStepStr;
result += ' ';
result += kSwingHStr;
break;
case kFujitsuAcCmdStepVert:
result += kStepStr + ' ' + kSwingVStr;
result += kStepStr;
result += ' ';
result += kSwingVStr;
break;
case kFujitsuAcCmdToggleSwingHoriz:
result += kToggleStr + ' ' + kSwingHStr;
result += kToggleStr;
result += ' ';
result += kSwingHStr;
break;
case kFujitsuAcCmdToggleSwingVert:
result += kToggleStr + ' ' + kSwingVStr;
result += kToggleStr;
result += ' ';
result += kSwingVStr;
break;
case kFujitsuAcCmdEcono:
result += kEconoStr;
@@ -663,7 +675,7 @@ String IRFujitsuAC::toString(void) {
result += kNAStr;
}
if (this->getModel() == fujitsu_ac_remote_model_t::ARREB1E)
result += addBoolToString(getOutsideQuiet(), kOutsideStr + ' ' + kQuietStr);
result += addBoolToString(getOutsideQuiet(), kOutsideQuietStr);
return result;
}
+3 -3
View File
@@ -300,9 +300,9 @@ String IRGoodweatherAc::toString(void) {
result += addFanToString(getFan(), kGoodweatherFanHigh, kGoodweatherFanLow,
kGoodweatherFanAuto, kGoodweatherFanAuto,
kGoodweatherFanMed);
result += addLabeledString(getTurbo() ? kToggleStr : F("-"), kTurboStr);
result += addLabeledString(getLight() ? kToggleStr : F("-"), kLightStr);
result += addLabeledString(getSleep() ? kToggleStr : F("-"), kSleepStr);
result += addLabeledString(getTurbo() ? kToggleStr : "-", kTurboStr);
result += addLabeledString(getLight() ? kToggleStr : "-", kLightStr);
result += addLabeledString(getSleep() ? kToggleStr : "-", kSleepStr);
result += addIntToString(getSwing(), kSwingStr);
result += kSpaceLBraceStr;
switch (this->getSwing()) {
+1 -1
View File
@@ -490,7 +490,7 @@ String IRGreeAC::toString(void) {
result += addBoolToString(getLight(), kLightStr);
result += addBoolToString(getSleep(), kSleepStr);
result += addLabeledString(getSwingVerticalAuto() ? kAutoStr : kManualStr,
kSwingVStr + ' ' + kModeStr);
kSwingVModeStr);
result += addIntToString(getSwingVerticalPosition(), kSwingVStr);
result += kSpaceLBraceStr;
switch (getSwingVerticalPosition()) {
+6 -2
View File
@@ -414,10 +414,14 @@ String IRHaierAC::toString(void) {
result += kSleepStr;
break;
case kHaierAcCmdTimerSet:
result += kTimerStr + ' ' + kSetStr;
result += kTimerStr;
result += ' ';
result += kSetStr;
break;
case kHaierAcCmdTimerCancel:
result += kTimerStr + ' ' + kCancelStr;
result += kTimerStr;
result += ' ';
result += kCancelStr;
break;
case kHaierAcCmdHealth:
result += kHealthStr;
+378 -3
View File
@@ -1,4 +1,4 @@
// Copyright 2018 David Conran
// Copyright 2018-2019 David Conran
//
// Code to emulate Hitachi protocol compatible devices.
// Should be compatible with:
@@ -27,6 +27,15 @@ const uint16_t kHitachiAcBitMark = 400;
const uint16_t kHitachiAcOneSpace = 1250;
const uint16_t kHitachiAcZeroSpace = 500;
const uint32_t kHitachiAcMinGap = kDefaultMessageGap; // Just a guess.
// Support for HitachiAc424 protocol
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/973
const uint16_t kHitachiAc424LdrMark = 29784; // Leader
const uint16_t kHitachiAc424LdrSpace = 49290; // Leader
const uint16_t kHitachiAc424HdrMark = 3416; // Header
const uint16_t kHitachiAc424HdrSpace = 1604; // Header
const uint16_t kHitachiAc424BitMark = 463;
const uint16_t kHitachiAc424OneSpace = 1208;
const uint16_t kHitachiAc424ZeroSpace = 372;
using irutils::addBoolToString;
using irutils::addIntToString;
@@ -35,6 +44,7 @@ using irutils::addModeToString;
using irutils::addFanToString;
using irutils::addTempToString;
using irutils::setBit;
using irutils::setBits;
#if (SEND_HITACHI_AC || SEND_HITACHI_AC2)
// Send a Hitachi A/C message.
@@ -81,8 +91,8 @@ void IRsend::sendHitachiAC1(const unsigned char data[], const uint16_t nbytes,
return; // Not enough bytes to send a proper message.
sendGeneric(kHitachiAc1HdrMark, kHitachiAc1HdrSpace, kHitachiAcBitMark,
kHitachiAcOneSpace, kHitachiAcBitMark, kHitachiAcZeroSpace,
kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, 38, true,
repeat, 50);
kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, kHitachiAcFreq,
true, repeat, kDutyDefault);
}
#endif // SEND_HITACHI_AC1
@@ -423,3 +433,368 @@ bool IRrecv::decodeHitachiAC(decode_results *results, const uint16_t nbits,
return true;
}
#endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2)
#if SEND_HITACHI_AC424
// Send HITACHI_AC424 messages
//
// Note: This protocol is almost exactly the same as HitachiAC2 except this
// variant has a leader section as well, and subtle timing differences.
// It is also in LSBF order (per byte), rather than MSBF order.
//
// Args:
// data: An array of bytes containing the IR command.
// It is assumed to be in LSBF order for this code.
// nbytes: Nr. of bytes of data in the array. (>=kHitachiAc424StateLength)
// repeat: Nr. of times the message is to be repeated.
//
// Status: STABLE / Reported as working.
void IRsend::sendHitachiAc424(const uint8_t data[], const uint16_t nbytes,
const uint16_t repeat) {
enableIROut(kHitachiAcFreq);
for (uint16_t r = 0; r <= repeat; r++) {
// Leader
mark(kHitachiAc424LdrMark);
space(kHitachiAc424LdrSpace);
// Header + Data + Footer
sendGeneric(kHitachiAc424HdrMark, kHitachiAc424HdrSpace,
kHitachiAc424BitMark, kHitachiAc424OneSpace,
kHitachiAc424BitMark, kHitachiAc424ZeroSpace,
kHitachiAc424BitMark, kHitachiAcMinGap,
data, nbytes, // Bytes
kHitachiAcFreq, false, kNoRepeat, kDutyDefault);
}
}
#endif // SEND_HITACHI_AC424
#if DECODE_HITACHI_AC424
// Decode the supplied Hitachi 424 bit A/C message.
//
// Note: This protocol is almost exactly the same as HitachiAC2 except this
// variant has a leader section as well, and subtle timing differences.
// It is also in LSBF order (per byte), rather than MSBF order.
//
// Args:
// results: Ptr to the data to decode and where to store the decode result.
// nbits: The number of data bits to expect. Typically kHitachiAc424Bits.
// strict: Flag indicating if we should perform strict matching.
// Returns:
// boolean: True if it can decode it, false if it can't.
//
// Status: STABLE / Reported as working.
//
// Supported devices:
// Hitachi Shirokumakun / AC Model: RAS-AJ25H / AC Remote Model: RAR-8P2
// Manual (Japanese):
// https://kadenfan.hitachi.co.jp/support/raj/item/docs/ras_aj22h_a_tori.pdf
//
// Ref:
// https://github.com/crankyoldgit/IRremoteESP8266/issues/973
bool IRrecv::decodeHitachiAc424(decode_results *results, const uint16_t nbits,
const bool strict) {
if (results->rawlen < 2 * nbits + kHeader + kHeader + kFooter - 1)
return false; // Too short a message to match.
if (strict && nbits != kHitachiAc424Bits)
return false;
uint16_t offset = kStartOffset;
uint16_t used;
// Leader
if (!matchMark(results->rawbuf[offset++], kHitachiAc424LdrMark))
return false;
if (!matchSpace(results->rawbuf[offset++], kHitachiAc424LdrSpace))
return false;
// Header + Data + Footer
used = matchGeneric(results->rawbuf + offset, results->state,
results->rawlen - offset, nbits,
kHitachiAc424HdrMark, kHitachiAc424HdrSpace,
kHitachiAc424BitMark, kHitachiAc424OneSpace,
kHitachiAc424BitMark, kHitachiAc424ZeroSpace,
kHitachiAc424BitMark, kHitachiAcMinGap, true,
kUseDefTol, 0, false);
if (used == 0) return false; // We failed to find any data.
// Success
results->decode_type = decode_type_t::HITACHI_AC424;
results->bits = nbits;
return true;
}
#endif // DECODE_HITACHI_AC424
// Class for handling the remote control on a Hitachi_AC424 53 byte A/C message
IRHitachiAc424::IRHitachiAc424(const uint16_t pin, const bool inverted,
const bool use_modulation)
: _irsend(pin, inverted, use_modulation) { stateReset(); }
// Reset to auto fan, cooling, 23° Celcius
void IRHitachiAc424::stateReset(void) {
for (uint8_t i = 0; i < kHitachiAc424StateLength; i++)
remote_state[i] = 0x00;
remote_state[0] = 0x01;
remote_state[1] = 0x10;
remote_state[3] = 0x40;
remote_state[5] = 0xFF;
remote_state[7] = 0xCC;
remote_state[33] = 0x80;
remote_state[35] = 0x03;
remote_state[37] = 0x01;
remote_state[39] = 0x88;
remote_state[45] = 0xFF;
remote_state[47] = 0xFF;
remote_state[49] = 0xFF;
remote_state[51] = 0xFF;
setTemp(23);
setPower(true);
setMode(kHitachiAc424Cool);
setFan(kHitachiAc424FanAuto);
}
void IRHitachiAc424::setInvertedStates(void) {
for (uint8_t i = 3; i < kHitachiAc424StateLength - 1; i += 2)
remote_state[i + 1] = ~remote_state[i];
}
void IRHitachiAc424::begin(void) { _irsend.begin(); }
uint8_t *IRHitachiAc424::getRaw(void) {
setInvertedStates();
return remote_state;
}
void IRHitachiAc424::setRaw(const uint8_t new_code[], const uint16_t length) {
memcpy(remote_state, new_code, std::min(length, kHitachiAc424StateLength));
}
#if SEND_HITACHI_AC424
void IRHitachiAc424::send(const uint16_t repeat) {
_irsend.sendHitachiAc424(getRaw(), kHitachiAc424StateLength, repeat);
}
#endif // SEND_HITACHI_AC424
bool IRHitachiAc424::getPower(void) {
return remote_state[kHitachiAc424PowerByte] == kHitachiAc424PowerOn;
}
void IRHitachiAc424::setPower(const bool on) {
setButton(kHitachiAc424ButtonPowerMode);
remote_state[kHitachiAc424PowerByte] = on ? kHitachiAc424PowerOn
: kHitachiAc424PowerOff;
}
void IRHitachiAc424::on(void) { setPower(true); }
void IRHitachiAc424::off(void) { setPower(false); }
uint8_t IRHitachiAc424::getMode(void) {
return GETBITS8(remote_state[kHitachiAc424ModeByte], kLowNibble, kNibbleSize);
}
void IRHitachiAc424::setMode(const uint8_t mode) {
uint8_t newMode = mode;
switch (mode) {
// Fan mode sets a special temp.
case kHitachiAc424Fan: setTemp(kHitachiAc424FanTemp, false); break;
case kHitachiAc424Heat:
case kHitachiAc424Cool:
case kHitachiAc424Dry: break;
default: newMode = kHitachiAc424Cool;
}
setBits(&remote_state[kHitachiAc424ModeByte], kLowNibble, kNibbleSize,
newMode);
if (newMode != kHitachiAc424Fan) setTemp(_previoustemp);
setFan(getFan()); // Reset the fan speed after the mode change.
setButton(kHitachiAc424ButtonPowerMode);
}
uint8_t IRHitachiAc424::getTemp(void) {
return GETBITS8(remote_state[kHitachiAc424TempByte], kHitachiAc424TempOffset,
kHitachiAc424TempSize);
}
void IRHitachiAc424::setTemp(const uint8_t celsius, bool setPrevious) {
uint8_t temp;
temp = std::min(celsius, kHitachiAc424MaxTemp);
temp = std::max(temp, kHitachiAc424MinTemp);
setBits(&remote_state[kHitachiAc424TempByte], kHitachiAc424TempOffset,
kHitachiAc424TempSize, temp);
if (_previoustemp > temp)
setButton(kHitachiAc424ButtonTempDown);
else if (_previoustemp < temp)
setButton(kHitachiAc424ButtonTempUp);
if (setPrevious) _previoustemp = temp;
}
uint8_t IRHitachiAc424::getFan(void) {
return GETBITS8(remote_state[kHitachiAc424FanByte], kHighNibble, kNibbleSize);
}
void IRHitachiAc424::setFan(const uint8_t speed) {
uint8_t newSpeed = std::max(speed, kHitachiAc424FanMin);
uint8_t fanMax = kHitachiAc424FanMax;
// Only 2 x low speeds in Dry mode or Auto
if (getMode() == kHitachiAc424Dry && speed == kHitachiAc424FanAuto) {
fanMax = kHitachiAc424FanAuto;
} else if (getMode() == kHitachiAc424Dry) {
fanMax = kHitachiAc424FanMaxDry;
} else if (getMode() == kHitachiAc424Fan && speed == kHitachiAc424FanAuto) {
// Fan Mode does not have auto. Set to safe low
newSpeed = kHitachiAc424FanMin;
}
newSpeed = std::min(newSpeed, fanMax);
// Handle the setting the button value if we are going to change the value.
if (newSpeed != getFan()) setButton(kHitachiAc424ButtonFan);
// Set the values
setBits(&remote_state[kHitachiAc424FanByte], kHighNibble, kNibbleSize,
newSpeed);
remote_state[9] = 0x92;
remote_state[29] = 0x00;
// When fan is at min/max, additional bytes seem to be set
if (newSpeed == kHitachiAc424FanMin) remote_state[9] = 0x98;
if (newSpeed == kHitachiAc424FanMax) {
remote_state[9] = 0xA9;
remote_state[29] = 0x30;
}
}
uint8_t IRHitachiAc424::getButton(void) {
return remote_state[kHitachiAc424ButtonByte];
}
// The remote sends the type of button pressed on send
void IRHitachiAc424::setButton(const uint8_t button) {
remote_state[kHitachiAc424ButtonByte] = button;
}
// The remote does not keep state of the vertical swing.
// A byte is sent indicating the swing button is pressed on the remote
void IRHitachiAc424::setSwingVToggle(const bool on) {
uint8_t button = getButton(); // Get the current button value.
if (on)
button = kHitachiAc424ButtonSwingV; // Set the button to SwingV.
else if (button == kHitachiAc424ButtonSwingV) // Asked to unset it
// It was set previous, so use Power as a default
button = kHitachiAc424ButtonPowerMode;
setButton(button);
}
bool IRHitachiAc424::getSwingVToggle(void) {
return getButton() == kHitachiAc424ButtonSwingV;
}
// Convert a standard A/C mode into its native mode.
uint8_t IRHitachiAc424::convertMode(const stdAc::opmode_t mode) {
switch (mode) {
case stdAc::opmode_t::kCool: return kHitachiAc424Cool;
case stdAc::opmode_t::kHeat: return kHitachiAc424Heat;
case stdAc::opmode_t::kDry: return kHitachiAc424Dry;
case stdAc::opmode_t::kFan: return kHitachiAc424Fan;
default: return kHitachiAc424Cool;
}
}
// Convert a standard A/C Fan speed into its native fan speed.
uint8_t IRHitachiAc424::convertFan(const stdAc::fanspeed_t speed) {
switch (speed) {
case stdAc::fanspeed_t::kMin: return kHitachiAc424FanMin;
case stdAc::fanspeed_t::kLow: return kHitachiAc424FanLow;
case stdAc::fanspeed_t::kMedium: return kHitachiAc424FanMedium;
case stdAc::fanspeed_t::kHigh: return kHitachiAc424FanHigh;
case stdAc::fanspeed_t::kMax: return kHitachiAc424FanMax;
default: return kHitachiAc424FanAuto;
}
}
// Convert a native mode to it's common equivalent.
stdAc::opmode_t IRHitachiAc424::toCommonMode(const uint8_t mode) {
switch (mode) {
case kHitachiAc424Cool: return stdAc::opmode_t::kCool;
case kHitachiAc424Heat: return stdAc::opmode_t::kHeat;
case kHitachiAc424Dry: return stdAc::opmode_t::kDry;
case kHitachiAc424Fan: return stdAc::opmode_t::kFan;
default: return stdAc::opmode_t::kCool;
}
}
// Convert a native fan speed to it's common equivalent.
stdAc::fanspeed_t IRHitachiAc424::toCommonFanSpeed(const uint8_t speed) {
switch (speed) {
case kHitachiAc424FanMax: return stdAc::fanspeed_t::kMax;
case kHitachiAc424FanHigh: return stdAc::fanspeed_t::kHigh;
case kHitachiAc424FanMedium: return stdAc::fanspeed_t::kMedium;
case kHitachiAc424FanLow: return stdAc::fanspeed_t::kLow;
case kHitachiAc424FanMin: return stdAc::fanspeed_t::kMin;
default: return stdAc::fanspeed_t::kAuto;
}
}
// Convert the A/C state to it's common equivalent.
stdAc::state_t IRHitachiAc424::toCommon(void) {
stdAc::state_t result;
result.protocol = decode_type_t::HITACHI_AC424;
result.model = -1; // No models used.
result.power = this->getPower();
result.mode = this->toCommonMode(this->getMode());
result.celsius = true;
result.degrees = this->getTemp();
result.fanspeed = this->toCommonFanSpeed(this->getFan());
result.swingv = this->getSwingVToggle() ? stdAc::swingv_t::kAuto
: stdAc::swingv_t::kOff;
// Not supported.
result.swingh = stdAc::swingh_t::kOff;
result.quiet = false;
result.turbo = false;
result.clean = false;
result.econo = false;
result.filter = false;
result.light = false;
result.beep = false;
result.sleep = -1;
result.clock = -1;
return result;
}
// Convert the internal state into a human readable string.
String IRHitachiAc424::toString(void) {
String result = "";
result.reserve(100); // Reserve some heap for the string to reduce fragging.
result += addBoolToString(getPower(), kPowerStr, false);
result += addModeToString(getMode(), 0, kHitachiAc424Cool,
kHitachiAc424Heat, kHitachiAc424Dry,
kHitachiAc424Fan);
result += addTempToString(getTemp());
result += addIntToString(getFan(), kFanStr);
result += kSpaceLBraceStr;
switch (getFan()) {
case kHitachiAc424FanAuto: result += kAutoStr; break;
case kHitachiAc424FanMax: result += kMaxStr; break;
case kHitachiAc424FanHigh: result += kHighStr; break;
case kHitachiAc424FanMedium: result += kMedStr; break;
case kHitachiAc424FanLow: result += kLowStr; break;
case kHitachiAc424FanMin: result += kMinStr; break;
default: result += kUnknownStr;
}
result += ')';
result += addBoolToString(getSwingVToggle(), kSwingVToggleStr);
result += addIntToString(getButton(), kButtonStr);
result += kSpaceLBraceStr;
switch (getButton()) {
case kHitachiAc424ButtonPowerMode:
result += kPowerStr;
result += '/';
result += kModeStr;
break;
case kHitachiAc424ButtonFan: result += kFanStr; break;
case kHitachiAc424ButtonSwingV: result += kSwingVStr; break;
case kHitachiAc424ButtonTempDown: result += kTempDownStr; break;
case kHitachiAc424ButtonTempUp: result += kTempUpStr; break;
default: result += kUnknownStr;
}
result += ')';
return result;
}
+87 -1
View File
@@ -1,11 +1,13 @@
// Hitachi A/C
//
// Copyright 2018 David Conran
// Copyright 2018-2019 David Conran
// Supports:
// Brand: Hitachi, Model: RAS-35THA6 remote
// Brand: Hitachi, Model: LT0541-HTA remote
// Brand: Hitachi, Model: Series VI A/C (Circa 2007)
// Brand: Hitachi, Model: RAR-8P2 remote
// Brand: Hitachi, Model: RAS-AJ25H A/C
#ifndef IR_HITACHI_H_
#define IR_HITACHI_H_
@@ -22,6 +24,7 @@
#endif
// Constants
const uint16_t kHitachiAcFreq = 38000; // Hz.
const uint8_t kHitachiAcAuto = 2;
const uint8_t kHitachiAcHeat = 3;
const uint8_t kHitachiAcCool = 4;
@@ -37,6 +40,42 @@ const uint8_t kHitachiAcAutoTemp = 23; // 23C
const uint8_t kHitachiAcPowerOffset = 0;
const uint8_t kHitachiAcSwingOffset = 7;
// HitachiAc424
// Byte[11]
const uint8_t kHitachiAc424ButtonByte = 11;
const uint8_t kHitachiAc424ButtonPowerMode = 0x13;
const uint8_t kHitachiAc424ButtonFan = 0x42;
const uint8_t kHitachiAc424ButtonTempDown = 0x43;
const uint8_t kHitachiAc424ButtonTempUp = 0x44;
const uint8_t kHitachiAc424ButtonSwingV = 0x81;
// Byte[13]
const uint8_t kHitachiAc424TempByte = 13;
const uint8_t kHitachiAc424TempOffset = 2;
const uint8_t kHitachiAc424TempSize = 6;
const uint8_t kHitachiAc424MinTemp = 16; // 16C
const uint8_t kHitachiAc424MaxTemp = 32; // 32C
const uint8_t kHitachiAc424FanTemp = 27; // 27C
// Byte[25]
const uint8_t kHitachiAc424ModeByte = 25;
const uint8_t kHitachiAc424Fan = 1;
const uint8_t kHitachiAc424Cool = 3;
const uint8_t kHitachiAc424Dry = 5;
const uint8_t kHitachiAc424Heat = 6;
const uint8_t kHitachiAc424FanByte = kHitachiAc424ModeByte;
const uint8_t kHitachiAc424FanMin = 1;
const uint8_t kHitachiAc424FanLow = 2;
const uint8_t kHitachiAc424FanMedium = 3;
const uint8_t kHitachiAc424FanHigh = 4;
const uint8_t kHitachiAc424FanAuto = 5;
const uint8_t kHitachiAc424FanMax = 6;
const uint8_t kHitachiAc424FanMaxDry = 2;
// Byte[27]
const uint8_t kHitachiAc424PowerByte = 27;
const uint8_t kHitachiAc424PowerOn = 0xF1;
const uint8_t kHitachiAc424PowerOff = 0xE1;
// Classes
class IRHitachiAc {
public:
@@ -89,4 +128,51 @@ class IRHitachiAc {
uint8_t _previoustemp;
};
class IRHitachiAc424 {
public:
explicit IRHitachiAc424(const uint16_t pin, const bool inverted = false,
const bool use_modulation = true);
void stateReset(void);
#if SEND_HITACHI_AC424
void send(const uint16_t repeat = kHitachiAcDefaultRepeat);
uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_HITACHI_AC424
void begin(void);
void on(void);
void off(void);
void setPower(const bool on);
bool getPower(void);
void setTemp(const uint8_t temp, bool setPrevious = true);
uint8_t getTemp(void);
void setFan(const uint8_t speed);
uint8_t getFan(void);
uint8_t getButton(void);
void setButton(const uint8_t button);
void setSwingVToggle(const bool on);
bool getSwingVToggle(void);
void setMode(const uint8_t mode);
uint8_t getMode(void);
uint8_t* getRaw(void);
void setRaw(const uint8_t new_code[],
const uint16_t length = kHitachiAc424StateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
static stdAc::opmode_t toCommonMode(const uint8_t mode);
static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
stdAc::state_t toCommon(void);
String toString(void);
#ifndef UNIT_TEST
private:
IRsend _irsend;
#else
IRsendTest _irsend;
#endif
// The state of the IR remote in IR code form.
uint8_t remote_state[kHitachiAc424StateLength];
void setInvertedStates(void);
uint8_t _previoustemp;
};
#endif // IR_HITACHI_H_
+1 -1
View File
@@ -387,7 +387,7 @@ String IRMideaAC::toString(void) {
kMideaACFanAuto, kMideaACFanAuto, kMideaACFanMed);
result += addBoolToString(getSleep(), kSleepStr);
}
result += addBoolToString(getSwingVToggle(), kSwingVStr + ' ' + kToggleStr,
result += addBoolToString(getSwingVToggle(), kSwingVToggleStr,
!isSwingVToggle());
return result;
}
+16 -5
View File
@@ -745,9 +745,16 @@ String IRMitsubishiAC::toString(void) {
result += addIntToString(this->getVane(), kSwingVStr);
result += kSpaceLBraceStr;
switch (this->getVane()) {
case kMitsubishiAcVaneAuto: result += kAutoStr; break;
case kMitsubishiAcVaneAutoMove: result += kAutoStr + ' ' + kMoveStr; break;
default: result += kUnknownStr;
case kMitsubishiAcVaneAuto:
result += kAutoStr;
break;
case kMitsubishiAcVaneAutoMove:
result += kAutoStr;
result += ' ';
result += kMoveStr;
break;
default:
result += kUnknownStr;
}
result += ')';
result += addIntToString(this->getWideVane(), kSwingHStr);
@@ -760,7 +767,9 @@ String IRMitsubishiAC::toString(void) {
result += addLabeledString(minsToString(getClock() * 10), kClockStr);
result += addLabeledString(minsToString(getStartClock() * 10), kOnTimerStr);
result += addLabeledString(minsToString(getStopClock() * 10), kOffTimerStr);
result += kCommaSpaceStr + kTimerStr + kColonSpaceStr;
result += kCommaSpaceStr;
result += kTimerStr;
result += kColonSpaceStr;
switch (this->getTimer()) {
case kMitsubishiAcNoTimer:
result += '-';
@@ -772,7 +781,9 @@ String IRMitsubishiAC::toString(void) {
result += kStopStr;
break;
case kMitsubishiAcStartStopTimer:
result += kStartStr + '+' + kStopStr;
result += kStartStr;
result += '+';
result += kStopStr;
break;
default:
result += F("? (");
+12 -4
View File
@@ -501,10 +501,14 @@ String IRMitsubishiHeavy152Ac::toString(void) {
result += kMaxRightStr;
break;
case kMitsubishiHeavy152SwingHLeftRight:
result += kLeftStr + ' ' + kRightStr;
result += kLeftStr;
result += ' ';
result += kRightStr;
break;
case kMitsubishiHeavy152SwingHRightLeft:
result += kRightStr + ' ' + kLeftStr;
result += kRightStr;
result += ' ';
result += kLeftStr;
break;
case kMitsubishiHeavy152SwingHOff:
result += kOffStr;
@@ -924,10 +928,14 @@ String IRMitsubishiHeavy88Ac::toString(void) {
result += kMaxRightStr;
break;
case kMitsubishiHeavy88SwingHLeftRight:
result += kLeftStr + ' ' + kRightStr;
result += kLeftStr;
result += ' ';
result += kRightStr;
break;
case kMitsubishiHeavy88SwingHRightLeft:
result += kRightStr + ' ' + kLeftStr;
result += kRightStr;
result += ' ';
result += kLeftStr;
break;
case kMitsubishiHeavy88SwingH3D:
result += k3DStr;
+7 -3
View File
@@ -469,7 +469,7 @@ String IRVestelAc::toString(void) {
// Not a time command, it's a normal command.
result += addBoolToString(getPower(), kPowerStr, false);
result += addModeToString(getMode(), kVestelAcAuto, kVestelAcCool,
kVestelAcHeat, kVestelAcDry, kVestelAcFan);
kVestelAcHeat, kVestelAcDry, kVestelAcFan);
result += addTempToString(getTemp());
result += addIntToString(getFan(), kFanStr);
result += kSpaceLBraceStr;
@@ -487,10 +487,14 @@ String IRVestelAc::toString(void) {
result += kHighStr;
break;
case kVestelAcFanAutoCool:
result += kAutoStr + ' ' + kCoolStr;
result += kAutoStr;
result += ' ';
result += kCoolStr;
break;
case kVestelAcFanAutoHot:
result += kAutoStr + ' ' + kHeatStr;
result += kAutoStr;
result += ' ';
result += kHeatStr;
break;
default:
result += kUnknownStr;
+1 -1
View File
@@ -472,7 +472,7 @@ String IRWhirlpoolAc::toString(void) {
String result = "";
result.reserve(200); // Reserve some heap for the string to reduce fragging.
result += addModelToString(decode_type_t::WHIRLPOOL_AC, getModel(), false);
result += addBoolToString(getPowerToggle(), kPowerStr + ' ' + kToggleStr);
result += addBoolToString(getPowerToggle(), kPowerToggleStr);
result += addModeToString(getMode(), kWhirlpoolAcAuto, kWhirlpoolAcCool,
kWhirlpoolAcHeat, kWhirlpoolAcDry, kWhirlpoolAcFan);
result += addTempToString(getTemp());
+42
View File
@@ -567,6 +567,48 @@ TEST(TestIRac, Hitachi) {
ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Hitachi424) {
IRHitachiAc424 ac(0);
IRac irac(0);
IRrecv capture(0);
char expected[] =
"Power: On, Mode: 6 (Heat), Temp: 25C, Fan: 6 (Max), "
"Swing(V) Toggle: Off, Button: 19 (Power/Mode)";
char expected_swingv[] =
"Power: On, Mode: 3 (Cool), Temp: 26C, Fan: 1 (Min), "
"Swing(V) Toggle: On, Button: 129 (Swing(V))";
ac.begin();
irac.hitachi424(&ac,
true, // Power
stdAc::opmode_t::kHeat, // Mode
25, // Celsius
stdAc::fanspeed_t::kMax, // Fan speed
stdAc::swingv_t::kOff); // Swing(V)
ASSERT_EQ(expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(HITACHI_AC424, ac._irsend.capture.decode_type);
ASSERT_EQ(kHitachiAc424Bits, ac._irsend.capture.bits);
ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
ac._irsend.reset();
irac.hitachi424(&ac,
true, // Power
stdAc::opmode_t::kCool, // Mode
26, // Celsius
stdAc::fanspeed_t::kMin, // Fan speed
stdAc::swingv_t::kAuto); // Swing(V)
ASSERT_EQ(expected_swingv, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(HITACHI_AC424, ac._irsend.capture.decode_type);
ASSERT_EQ(kHitachiAc424Bits, ac._irsend.capture.bits);
ASSERT_EQ(expected_swingv, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Kelvinator) {
IRKelvinatorAC ac(0);
IRac irac(0);
+4 -4
View File
@@ -153,13 +153,13 @@ gtest_main.a : gtest-all.o gtest_main.o
IRtext.o : $(USER_DIR)/IRtext.cpp $(USER_DIR)/IRtext.h $(USER_DIR)/IRremoteESP8266.h $(USER_DIR)/i18n.h $(USER_DIR)/locale/*.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/IRtext.cpp
IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h $(USER_DIR)/i18n.h
IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h $(USER_DIR)/i18n.h $(USER_DIR)/IRtext.cpp $(USER_DIR)/IRtext.h $(USER_DIR)/locale/*.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/IRutils.cpp
IRutils_test.o : IRutils_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c IRutils_test.cpp
IRutils_test : IRutils_test.o ir_NEC.o ir_Nikai.o ir_Toshiba.o $(COMMON_OBJ) gtest_main.a
IRutils_test : IRutils_test.o ir_NEC.o ir_Nikai.o ir_Toshiba.o IRtext.o $(COMMON_OBJ) gtest_main.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
IRtimer.o : $(USER_DIR)/IRtimer.cpp $(USER_DIR)/IRtimer.h
@@ -390,7 +390,7 @@ ir_Daikin_test.o : ir_Daikin_test.cpp $(USER_DIR)/ir_Daikin.h $(COMMON_TEST_DEPS
ir_Daikin_test : $(COMMON_OBJ) ir_Daikin_test.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
ir_Gree.o : $(USER_DIR)/ir_Gree.cpp $(GTEST_HEADERS)
ir_Gree.o : $(USER_DIR)/ir_Gree.cpp $(GTEST_HEADERS) $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Gree.cpp
ir_Gree_test.o : ir_Gree_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
@@ -417,7 +417,7 @@ ir_Nikai_test.o : ir_Nikai_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
ir_Nikai_test : $(COMMON_OBJ) ir_Nikai_test.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
ir_Toshiba.o : $(USER_DIR)/ir_Toshiba.cpp $(USER_DIR)/ir_Toshiba.h $(GTEST_HEADERS)
ir_Toshiba.o : $(USER_DIR)/ir_Toshiba.cpp $(USER_DIR)/ir_Toshiba.h $(COMMON_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Toshiba.cpp
ir_Toshiba_test.o : ir_Toshiba_test.cpp $(USER_DIR)/ir_Toshiba.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
@@ -1,6 +1,7 @@
// Copyright 2017-2018 David Conran
#include "ir_Coolix.h"
#include "IRac.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
@@ -746,3 +747,56 @@ TEST(TestCoolixACClass, Issue722) {
// 564,1620,566,1618,562 // Raw data matches what is expected.
"m560s1680m560s1680m560s105040", ac._irsend.outputStr());
}
TEST(TestCoolixACClass, Issue985) {
IRrecv irrecv(0);
IRCoolixAC ac(0);
// Test that if we ONLY turn the power off, it only sends a "power off" mesg.
// i.e. Code from: https://github.com/crankyoldgit/IRremoteESP8266/issues/985#issue-516210106
// First block in the first code included.
ac.setPower(false);
ac.send();
ac._irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&ac._irsend.capture));
EXPECT_EQ(COOLIX, ac._irsend.capture.decode_type);
EXPECT_EQ(kCoolixBits, ac._irsend.capture.bits);
EXPECT_EQ(kCoolixOff, ac._irsend.capture.value);
EXPECT_EQ("Power: Off", IRAcUtils::resultAcToString(&ac._irsend.capture));
ac._irsend.reset();
// Turn the unit on, cool mode, and set the temp.
// Code from: https://github.com/crankyoldgit/IRremoteESP8266/issues/985#issue-516210106
// Second block in the first code included.
uint8_t aircon_temp = 20; // Random value chosen.
ac.setPower(true);
ac.setMode(kCoolixCool);
ac.setTemp(aircon_temp);
ac.send();
ac._irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&ac._irsend.capture));
EXPECT_EQ(COOLIX, ac._irsend.capture.decode_type);
EXPECT_EQ(kCoolixBits, ac._irsend.capture.bits);
EXPECT_NE(kCoolixOff, ac._irsend.capture.value);
EXPECT_EQ(
"Power: On, Mode: 0 (Cool), Fan: 5 (Auto), Temp: 20C, Zone Follow: Off, "
"Sensor Temp: Off", IRAcUtils::resultAcToString(&ac._irsend.capture));
ac._irsend.reset();
// Now repeat the first block again.
// i.e. Code from: https://github.com/crankyoldgit/IRremoteESP8266/issues/985#issue-516210106
// First block in the first code included.
ac.setPower(false);
ac.send();
ac._irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&ac._irsend.capture));
EXPECT_EQ(COOLIX, ac._irsend.capture.decode_type);
EXPECT_EQ(kCoolixBits, ac._irsend.capture.bits);
EXPECT_EQ(kCoolixOff, ac._irsend.capture.value);
EXPECT_EQ("Power: Off", IRAcUtils::resultAcToString(&ac._irsend.capture));
}
@@ -1,6 +1,7 @@
// Copyright 2018 David Conran
#include "ir_Hitachi.h"
#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRremoteESP8266.h"
@@ -798,3 +799,343 @@ TEST(TestIRHitachiAcClass, toCommon) {
ASSERT_EQ(-1, ac.toCommon().sleep);
ASSERT_EQ(-1, ac.toCommon().clock);
}
TEST(TestUtils, Housekeeping) {
ASSERT_EQ("HITACHI_AC", typeToString(decode_type_t::HITACHI_AC));
ASSERT_EQ(decode_type_t::HITACHI_AC, strToDecodeType("HITACHI_AC"));
ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC));
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC));
ASSERT_EQ("HITACHI_AC1", typeToString(decode_type_t::HITACHI_AC1));
ASSERT_EQ(decode_type_t::HITACHI_AC1, strToDecodeType("HITACHI_AC1"));
ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC1));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC1));
ASSERT_EQ("HITACHI_AC2", typeToString(decode_type_t::HITACHI_AC2));
ASSERT_EQ(decode_type_t::HITACHI_AC2, strToDecodeType("HITACHI_AC2"));
ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC2));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC2));
ASSERT_EQ("HITACHI_AC424", typeToString(decode_type_t::HITACHI_AC424));
ASSERT_EQ(decode_type_t::HITACHI_AC424, strToDecodeType("HITACHI_AC424"));
ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC424));
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC424));
}
// Decode a 'real' HitachiAc424 message.
TEST(TestDecodeHitachiAc424, RealExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
uint8_t expected[kHitachiAc424StateLength] = {
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xCC, 0x33, 0x92,
0x6D, 0x13, 0xEC, 0x5C, 0xA3, 0x00, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x53, 0xAC, 0xF1, 0x0E, 0x00,
0xFF, 0x00, 0xFF, 0x80, 0x7F, 0x03, 0xFC, 0x01, 0xFE, 0x88,
0x77, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0xFF, 0x00};
// Ref: https://docs.google.com/spreadsheets/d/1TTRx7INyDlsJBn9UwebL2Q4Q0S0apq0DlKP6bfrVPQw/edit#gid=0&range=A2:B2
uint16_t rawData[853] = {
// On Auto Cool 23
29784, 49290, 3416, 1604, 464, 1210, 468, 372, 460, 374, 462, 374, 466,
368, 464, 372, 462, 374, 464, 374, 464, 368, 464, 370, 464, 370, 466, 370,
464, 1208, 464, 374, 462, 372, 466, 374, 464, 370, 462, 372, 464, 370,
466, 370, 464, 372, 462, 374, 462, 374, 462, 378, 460, 370, 460, 374, 464,
372, 462, 372, 464, 374, 466, 368, 464, 1210, 464, 374, 466, 1202, 464,
1206, 464, 1210, 466, 1206, 468, 1204, 464, 1210, 466, 370, 462, 1214,
460, 1208, 464, 1206, 464, 1208, 466, 1208, 464, 1206, 466, 1208, 464,
1206, 466, 1212, 464, 370, 464, 370, 462, 374, 462, 374, 462, 374, 462,
374, 462, 372, 464, 376, 460, 372, 462, 374, 466, 1204, 464, 1210, 464,
372, 460, 374, 462, 1208, 464, 1212, 464, 1202, 468, 1204, 464, 374, 460,
374, 466, 1208, 462, 1210, 462, 374, 462, 376, 464, 368, 466, 1204, 462,
374, 466, 372, 464, 1206, 462, 376, 460, 376, 464, 1210, 462, 1208, 462,
372, 466, 1206, 464, 1208, 466, 372, 462, 1210, 462, 1210, 466, 374, 468,
1202, 464, 1206, 466, 374, 462, 372, 464, 1208, 464, 374, 464, 372, 464,
376, 462, 370, 466, 368, 464, 1208, 462, 1210, 460, 374, 464, 1208, 466,
1206, 464, 1214, 464, 368, 462, 374, 462, 1212, 460, 1210, 466, 1206, 466,
370, 462, 1210, 464, 416, 424, 1202, 466, 1220, 448, 376, 464, 372, 462,
372, 462, 1212, 462, 374, 460, 1214, 468, 364, 468, 370, 462, 372, 462,
376, 458, 374, 464, 372, 462, 376, 464, 376, 462, 1204, 464, 1210, 462,
1210, 464, 1208, 466, 1208, 464, 1206, 462, 1210, 464, 1212, 464, 368,
462, 372, 464, 372, 464, 372, 464, 372, 466, 370, 466, 370, 464, 376,
464, 1202, 464, 1212, 464, 1204, 464, 1210, 462, 1208, 464, 1212, 462,
1210, 464, 1212, 460, 372, 462, 374, 462, 374, 466, 370, 462, 374, 462,
372, 464, 372, 462, 376, 462, 1206, 464, 1206, 466, 1210, 462, 1208, 464,
1210, 466, 1204, 464, 1210, 462, 1214, 462, 368, 462, 374, 466, 370, 462,
376, 466, 368, 466, 370, 462, 414, 424, 374, 464, 1206, 464, 1206, 464,
1206, 468, 1206, 466, 1206, 466, 1210, 462, 1206, 464, 1214, 468, 364,
466, 372, 466, 370, 462, 372, 462, 374, 464, 372, 462, 374, 460, 376, 466,
1204, 464, 1208, 462, 1210, 464, 1206, 464, 1210, 464, 1208, 464, 1208,
466, 1210, 462, 1206, 466, 1206, 466, 372, 462, 374, 466, 1206, 466, 370,
464, 1206, 466, 376, 464, 368, 462, 372, 466, 1206, 464, 1206, 464, 374,
466, 1204, 464, 374, 466, 1206, 466, 1204, 468, 368, 466, 370, 466, 370,
462, 1212, 462, 1210, 462, 1210, 462, 1214, 464, 368, 464, 1206, 466,
1206, 466, 1206, 464, 374, 464, 370, 466, 370, 462, 378, 466, 366, 464,
372, 466, 368, 466, 370, 464, 370, 462, 372, 462, 374, 464, 374, 464,
1202, 466, 1206, 462, 1208, 466, 1208, 466, 1208, 464, 1210, 462, 1206,
464, 1212, 464, 368, 464, 372, 464, 370, 468, 368, 462, 376, 462, 372,
466, 370, 464, 376, 462, 1206, 464, 1210, 462, 1212, 462, 1208, 464, 1208,
462, 1212, 466, 1246, 424, 1212, 464, 368, 464, 372, 466, 370, 464, 372,
462, 374, 464, 372, 464, 370, 462, 1212, 466, 1206, 462, 1206, 464, 1210,
466, 1206, 462, 1208, 464, 1250, 422, 1208, 468, 372, 464, 1204, 466,
1206, 466, 370, 462, 374, 462, 376, 460, 374, 466, 370, 462, 376, 464,
368, 462, 376, 462, 1210, 462, 1208, 464, 1206, 466, 1206, 464, 1208, 468,
1212, 460, 1206, 464, 372, 464, 372, 466, 370, 462, 374, 466, 370, 466,
370, 466, 374, 464, 368, 462, 1210, 462, 1210, 464, 1210, 462, 1208, 462,
1212, 464, 1206, 466, 1208, 466, 366, 464, 374, 460, 374, 462, 1208, 466,
372, 462, 374, 462, 374, 464, 1212, 468, 1202, 464, 1208, 466, 1204, 464,
376, 460, 1208, 468, 1208, 462, 1208, 464, 378, 460, 372, 460, 372, 462,
376, 464, 372, 462, 374, 460, 374, 464, 370, 462, 378, 464, 1202, 468,
1204, 468, 1204, 466, 1208, 466, 1208, 464, 1210, 460, 1212, 462, 1212,
464, 366, 466, 370, 464, 372, 466, 370, 464, 372, 462, 414, 424, 372, 466,
372, 460, 1206, 466, 1206, 466, 1206, 466, 1208, 466, 1206, 464, 1208,
466, 1208, 462, 1212, 468, 1202, 466, 1204, 470, 1204, 468, 1204, 466,
1206, 466, 1206, 464, 1210, 462, 1212, 468, 366, 464, 372, 462, 374, 460,
374, 460, 374, 466, 410, 424, 372, 460, 378, 466, 1200, 464, 1212, 462,
1210, 464, 1210, 466, 1206, 462, 1208, 464, 1210, 464, 1210, 464, 366,
462, 376, 462, 374, 460, 376, 462, 372, 466, 374, 460, 372, 462, 378, 462,
1202, 468, 1206, 464, 1208, 466, 1208, 462, 1208, 464, 1208, 468, 1204,
464, 1212, 466, 368, 462, 374, 466, 372, 464, 370, 462, 374, 464, 370,
462, 376, 464, 374, 462, 1206, 464, 1208, 462, 1210, 466, 1208, 460, 1210,
468, 1206, 462, 1210, 464, 1212, 466, 366, 464, 374, 462, 372, 466, 370,
462, 374, 464, 372, 464, 370, 464, 374, 462};
irsend.reset();
irsend.sendRaw(rawData, 853, kHitachiAcFreq);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(HITACHI_AC424, irsend.capture.decode_type);
ASSERT_EQ(kHitachiAc424Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expected, irsend.capture.state, kHitachiAc424Bits);
IRHitachiAc ac(0);
ac.setRaw(irsend.capture.state);
EXPECT_EQ(
"Power: On, Mode: 3 (Cool), Temp: 23C, Fan: 5 (Auto), "
"Swing(V) Toggle: Off, Button: 19 (Power/Mode)",
IRAcUtils::resultAcToString(&irsend.capture));
}
TEST(TestDecodeHitachiAc424, SyntheticExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
uint8_t expected[kHitachiAc424StateLength] = {
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xCC, 0x33, 0x92,
0x6D, 0x13, 0xEC, 0x5C, 0xA3, 0x00, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x53, 0xAC, 0xF1, 0x0E, 0x00,
0xFF, 0x00, 0xFF, 0x80, 0x7F, 0x03, 0xFC, 0x01, 0xFE, 0x88,
0x77, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0xFF, 0x00};
irsend.reset();
irsend.sendHitachiAc424(expected);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(HITACHI_AC424, irsend.capture.decode_type);
ASSERT_EQ(kHitachiAc424Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
}
// Tests for IRHitachiAc424 class.
TEST(TestIRHitachiAc424Class, SetInvertedStates) {
IRHitachiAc424 ac(0);
uint8_t raw[kHitachiAc424StateLength] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00};
uint8_t expected[kHitachiAc424StateLength] = {
0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0x00, 0xFF};
ac.setRaw(raw);
EXPECT_STATE_EQ(expected, ac.getRaw(), kHitachiAc424Bits);
}
TEST(TestIRHitachiAc424Class, SetAndGetPower) {
IRHitachiAc424 ac(0);
ac.on();
EXPECT_TRUE(ac.getPower());
ac.off();
EXPECT_FALSE(ac.getPower());
ac.setPower(true);
EXPECT_TRUE(ac.getPower());
EXPECT_EQ(ac.getButton(), kHitachiAc424ButtonPowerMode);
ac.setPower(false);
EXPECT_FALSE(ac.getPower());
EXPECT_EQ(ac.getButton(), kHitachiAc424ButtonPowerMode);
}
TEST(TestIRHitachiAc424Class, SetAndGetTemp) {
IRHitachiAc424 ac(0);
ac.setTemp(25);
EXPECT_EQ(25, ac.getTemp());
ac.setTemp(kHitachiAc424MinTemp);
EXPECT_EQ(kHitachiAc424MinTemp, ac.getTemp());
ac.setTemp(kHitachiAc424MinTemp - 1);
EXPECT_EQ(kHitachiAc424MinTemp, ac.getTemp());
ac.setTemp(kHitachiAc424MaxTemp);
EXPECT_EQ(kHitachiAc424MaxTemp, ac.getTemp());
ac.setTemp(kHitachiAc424MaxTemp + 1);
EXPECT_EQ(kHitachiAc424MaxTemp, ac.getTemp());
}
TEST(TestIRHitachiAc424Class, SetAndGetMode) {
IRHitachiAc424 ac(0);
ac.setMode(kHitachiAc424Cool);
ac.setFan(kHitachiAc424FanAuto);
ac.setTemp(25);
EXPECT_EQ(25, ac.getTemp());
EXPECT_EQ(kHitachiAc424Cool, ac.getMode());
EXPECT_EQ(kHitachiAc424FanAuto, ac.getFan());
ac.setMode(kHitachiAc424Fan);
EXPECT_EQ(kHitachiAc424Fan, ac.getMode());
EXPECT_EQ(27, ac.getTemp());
EXPECT_NE(kHitachiAc424FanAuto, ac.getFan());
ac.setMode(kHitachiAc424Heat);
EXPECT_EQ(25, ac.getTemp());
EXPECT_EQ(kHitachiAc424Heat, ac.getMode());
ac.setMode(kHitachiAc424Dry);
EXPECT_EQ(kHitachiAc424Dry, ac.getMode());
EXPECT_NE(kHitachiAc424FanAuto, ac.getFan());
}
TEST(TestIRHitachiAc424Class, SetAndGetFan) {
IRHitachiAc424 ac(0);
ac.setMode(kHitachiAc424Cool); // All fan options are available in this mode.
ac.setFan(kHitachiAc424FanAuto);
EXPECT_EQ(kHitachiAc424FanAuto, ac.getFan());
ac.setFan(kHitachiAc424FanLow);
EXPECT_EQ(kHitachiAc424FanLow, ac.getFan());
EXPECT_EQ(kHitachiAc424ButtonFan, ac.getButton());
ac.setFan(kHitachiAc424FanHigh);
EXPECT_EQ(kHitachiAc424FanHigh, ac.getFan());
ac.setFan(kHitachiAc424FanMax + 1);
EXPECT_EQ(kHitachiAc424FanMax, ac.getFan());
ac.setFan(kHitachiAc424FanMin - 1);
EXPECT_EQ(kHitachiAc424FanMin, ac.getFan());
ac.setFan(kHitachiAc424FanAuto);
ac.setMode(kHitachiAc424Fan); // No auto-fan in Fan mode.
EXPECT_EQ(kHitachiAc424FanMin, ac.getFan());
ac.setFan(kHitachiAc424FanMax);
EXPECT_EQ(kHitachiAc424FanMax, ac.getFan());
// Only min, low and auto fan settings in Dry mode.
ac.setMode(kHitachiAc424Dry);
EXPECT_EQ(kHitachiAc424FanLow, ac.getFan());
ac.setFan(kHitachiAc424FanHigh);
EXPECT_EQ(kHitachiAc424FanLow, ac.getFan());
ac.setFan(kHitachiAc424FanMin);
EXPECT_EQ(kHitachiAc424FanMin, ac.getFan());
ac.setFan(kHitachiAc424FanAuto);
EXPECT_EQ(kHitachiAc424FanAuto, ac.getFan());
// Check additional bytes set by min & max fan
ac.setMode(kHitachiAc424Cool);
ac.setFan(kHitachiAc424FanMax);
EXPECT_EQ(ac.getRaw()[9], 0xA9);
EXPECT_EQ(ac.getRaw()[29], 0x30);
ac.setFan(kHitachiAc424FanMin);
EXPECT_EQ(ac.getRaw()[9], 0x98);
EXPECT_EQ(ac.getRaw()[29], 0x00);
ac.setFan(kHitachiAc424FanLow);
EXPECT_EQ(ac.getRaw()[9], 0x92);
EXPECT_EQ(ac.getRaw()[29], 0x00);
}
TEST(TestIRHitachiAc424Class, SetAndGetButton) {
IRHitachiAc424 ac(0);
ac.on();
EXPECT_EQ(ac.getButton(), kHitachiAc424ButtonPowerMode);
ac.setButton(kHitachiAc424ButtonTempUp);
EXPECT_EQ(ac.getButton(), kHitachiAc424ButtonTempUp);
ac.setButton(kHitachiAc424ButtonSwingV);
EXPECT_EQ(ac.getButton(), kHitachiAc424ButtonSwingV);
}
TEST(TestIRHitachiAc424Class, ToggleSwingVertical) {
IRHitachiAc424 ac(0);
ac.on();
EXPECT_EQ(ac.getButton(), kHitachiAc424ButtonPowerMode);
ac.setSwingVToggle(true);
EXPECT_TRUE(ac.getSwingVToggle());
EXPECT_EQ(ac.getButton(), kHitachiAc424ButtonSwingV);
ac.setSwingVToggle(false);
EXPECT_FALSE(ac.getSwingVToggle());
EXPECT_EQ(ac.getButton(), kHitachiAc424ButtonPowerMode);
}
TEST(TestIRHitachiAc424Class, HumanReadable) {
IRHitachiAc424 ac(0);
ac.setMode(kHitachiAc424Heat);
ac.setTemp(kHitachiAc424MaxTemp);
ac.on();
ac.setFan(kHitachiAc424FanHigh);
EXPECT_EQ(
"Power: On, Mode: 6 (Heat), Temp: 32C, Fan: 4 (High), "
"Swing(V) Toggle: Off, Button: 66 (Fan)",
ac.toString());
ac.setMode(kHitachiAc424Cool);
ac.setFan(kHitachiAc424FanMin);
ac.setTemp(kHitachiAc424MinTemp);
EXPECT_EQ(
"Power: On, Mode: 3 (Cool), Temp: 16C, Fan: 1 (Min), "
"Swing(V) Toggle: Off, Button: 67 (Temp Down)",
ac.toString());
ac.setSwingVToggle(true);
EXPECT_EQ(
"Power: On, Mode: 3 (Cool), Temp: 16C, Fan: 1 (Min), "
"Swing(V) Toggle: On, Button: 129 (Swing(V))",
ac.toString());
ac.setTemp(ac.getTemp() + 1);
EXPECT_EQ(
"Power: On, Mode: 3 (Cool), Temp: 17C, Fan: 1 (Min), "
"Swing(V) Toggle: Off, Button: 68 (Temp Up)",
ac.toString());
ac.setTemp(ac.getTemp() - 1);
EXPECT_EQ(
"Power: On, Mode: 3 (Cool), Temp: 16C, Fan: 1 (Min), "
"Swing(V) Toggle: Off, Button: 67 (Temp Down)",
ac.toString());
}
TEST(TestIRHitachiAc424Class, toCommon) {
IRHitachiAc424 ac(0);
ac.setPower(true);
ac.setMode(kHitachiAc424Cool);
ac.setTemp(20);
ac.setFan(kHitachiAc424FanMax);
// Now test it.
ASSERT_EQ(decode_type_t::HITACHI_AC424, ac.toCommon().protocol);
ASSERT_EQ(-1, ac.toCommon().model);
ASSERT_TRUE(ac.toCommon().power);
ASSERT_TRUE(ac.toCommon().celsius);
ASSERT_EQ(20, ac.toCommon().degrees);
ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
// Unsupported.
ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv);
ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
ASSERT_FALSE(ac.toCommon().turbo);
ASSERT_FALSE(ac.toCommon().clean);
ASSERT_FALSE(ac.toCommon().light);
ASSERT_FALSE(ac.toCommon().quiet);
ASSERT_FALSE(ac.toCommon().econo);
ASSERT_FALSE(ac.toCommon().filter);
ASSERT_FALSE(ac.toCommon().beep);
ASSERT_EQ(-1, ac.toCommon().sleep);
ASSERT_EQ(-1, ac.toCommon().clock);
}
@@ -14,6 +14,7 @@ class RawIRMessage():
# pylint: disable=too-many-instance-attributes
def __init__(self, margin, timings, output=sys.stdout, verbose=True):
self.ldr_mark = None
self.hdr_mark = None
self.hdr_space = None
self.bit_mark = None
@@ -208,14 +209,18 @@ class RawIRMessage():
"%s\n"
"Potential Space Candidates:\n"
"%s\n" % (str(self.marks), str(self.spaces)))
# Largest mark is likely the kHdrMark
self.hdr_mark = self.marks[0]
# The bit mark is likely to be the smallest mark.
self.bit_mark = self.marks[-1]
if len(self.marks) > 2: # Possible leader mark?
self.ldr_mark = self.marks[0]
self.hdr_mark = self.marks[1]
else:
# Largest mark is likely the kHdrMark
self.hdr_mark = self.marks[0]
if self.is_space_encoded() and len(self.spaces) >= 3:
if self.verbose and len(self.marks) > 2:
self.output.write("DANGER: Unexpected and unused mark timings!")
self.output.write("DANGER: Unusual number of mark timings!")
# We should have 3 space candidates at least.
# They should be: zero_space (smallest), one_space, & hdr_space (largest)
spaces = list(self.spaces)
@@ -229,6 +234,12 @@ class RawIRMessage():
"""Make an educated guess if the message is space encoded."""
return len(self.spaces) > len(self.marks)
def is_ldr_mark(self, usec):
"""Is usec the leader mark?"""
if self.ldr_mark is None:
return False
return self._usec_compare(usec, self.ldr_mark)
def is_hdr_mark(self, usec):
"""Is usec the header mark?"""
return self._usec_compare(usec, self.hdr_mark)
@@ -290,6 +301,9 @@ def convert_rawdata(data_str):
def dump_constants(message, defines, name="", output=sys.stdout):
"""Dump the key constants and generate the C++ #defines."""
ldr_mark = None
if message.ldr_mark is not None:
ldr_mark = avg_list(message.mark_buckets[message.ldr_mark])
hdr_mark = avg_list(message.mark_buckets[message.hdr_mark])
bit_mark = avg_list(message.mark_buckets[message.bit_mark])
hdr_space = avg_list(message.space_buckets[message.hdr_space])
@@ -309,6 +323,9 @@ def dump_constants(message, defines, name="", output=sys.stdout):
defines.append("const uint16_t k%sHdrSpace = %d;" % (name, hdr_space))
defines.append("const uint16_t k%sOneSpace = %d;" % (name, one_space))
defines.append("const uint16_t k%sZeroSpace = %d;" % (name, zero_space))
if ldr_mark:
output.write("k%sLdrMark = %d\n" % (name, ldr_mark))
defines.append("const uint16_t k%sLdrMark = %d;" % (name, ldr_mark))
avg_gaps = [avg_list(message.space_buckets[x]) for x in message.gaps]
if len(message.gaps) == 1:
@@ -420,27 +437,40 @@ def decode_data(message, defines, code, name="", output=sys.stdout):
" uint16_t pos = 0;",
" uint16_t used = 0;"])
# states are:
# HM: Header/Leader mark
# HS: Header space
# BM: Bit mark
# BS: Bit space
# GS: Gap space
# UNK: Unknown state.
for usec in message.timings:
# Handle header marks.
if (message.is_hdr_mark(usec) and count % 2 and
not message.is_bit_mark(usec)):
# Handle header/leader marks.
if ((message.is_hdr_mark(usec) or message.is_ldr_mark(usec)) and
count % 2 and not message.is_bit_mark(usec)):
state = "HM"
if message.is_hdr_mark(usec):
mark_type = "H" # Header
else:
mark_type = "L" # Leader
if binary_value:
message.display_binary(binary_value)
code["send"].extend(message.add_data_code(binary_value, name, False))
code["recv"].extend(message.add_data_decode_code(binary_value, name,
False))
message.section_count = message.section_count + 1
code_info["lastmark"] = "k%sHdrMark" % name
code_info["lastmark"] = "k%s%sdrMark" % (name, mark_type)
total_bits = total_bits + binary_value
code_info["firstmark"] = "k%sHdrMark" % name
code_info["firstmark"] = "k%s%sdrMark" % (name, mark_type)
binary_value = add_bit(binary_value, "reset")
output.write("k%sHdrMark+" % name)
code["send"].extend([" // Header", " mark(k%sHdrMark);" % name])
output.write("k%s%sdrMark+" % (name, mark_type))
code["send"].extend([" // %seader" % mark_type,
" mark(k%s%sdrMark);" % (name, mark_type)])
code["recv"].extend([
"",
" // Header",
" if (!matchMark(results->rawbuf[offset++], k%sHdrMark))" % name,
" // %seader" % mark_type,
" if (!matchMark(results->rawbuf[offset++], k%s%sdrMark))" % (
name, mark_type),
" return false;"])
# Handle header spaces.
@@ -473,15 +503,18 @@ def decode_data(message, defines, code, name="", output=sys.stdout):
" if (!matchSpace(results->rawbuf[offset++], k%sHdrSpace))" % name,
" return false;"])
code_info["firstspace"] = "k%sHdrSpace" % name
# Handle bit marks.
elif message.is_bit_mark(usec) and count % 2:
if state not in ("HS", "BS"):
output.write("k%sBitMark(UNEXPECTED)" % name)
state = "BM"
# Handle "zero" spaces
elif message.is_zero_space(usec):
if state != "BM":
output.write("k%sZeroSpace(UNEXPECTED)" % name)
state = "BS"
binary_value = binary64_value = add_bit(binary_value, 0, output)
# Handle "one" spaces
elif message.is_one_space(usec):
if state != "BM":
output.write("k%sOneSpace(UNEXPECTED)" % name)
@@ -490,7 +523,6 @@ def decode_data(message, defines, code, name="", output=sys.stdout):
elif message.is_gap(usec):
if state != "BM":
output.write("UNEXPECTED->")
state = "GS"
output.write("GAP(%d)" % usec)
code_info["lastspace"] = "k%sSpaceGap" % name
if binary64_value:
@@ -506,18 +538,21 @@ def decode_data(message, defines, code, name="", output=sys.stdout):
code["recv"].extend(message.add_data_decode_code(binary_value, name))
message.section_count = message.section_count + 1
else:
code["send"].extend([" // Gap", " mark(k%sBitMark);" % name])
code["recv"].extend([
"",
" // Gap",
" if (!matchMark(results->rawbuf[offset++], k%sBitMark))" % name,
" return false;"])
code["recv"].extend(["",
" // Gap"])
code["send"].extend([" // Gap"])
if state == "BM":
code["send"].extend([" mark(k%sBitMark);" % name])
code["recv"].extend([
" if (!matchMark(results->rawbuf[offset++], k%sBitMark))" % name,
" return false;"])
code["send"].append(" space(k%sSpaceGap);" % name)
code["recv"].extend([
" if (!matchSpace(results->rawbuf[offset++], k%sSpaceGap))" % name,
" return false;"])
total_bits = total_bits + binary_value
binary_value = binary64_value = add_bit(binary_value, "reset")
state = "GS"
else:
output.write("UNKNOWN(%d)" % usec)
state = "UNK"
@@ -4,6 +4,7 @@ from io import StringIO
import unittest
import auto_analyse_raw_data as analyse
# pylint: disable=too-many-lines
class TestRawIRMessage(unittest.TestCase):
"""Unit tests for the RawIRMessage class."""
@@ -19,30 +20,31 @@ class TestRawIRMessage(unittest.TestCase):
message.display_binary("10101010")
message.display_binary("0000000000000000")
message.display_binary("00010010001101000101011001111000")
self.assertEqual(output.getvalue(), '\n'
' Bits: 8\n'
' Hex: 0xAA (MSB first)\n'
' 0x55 (LSB first)\n'
' Dec: 170 (MSB first)\n'
' 85 (LSB first)\n'
' Bin: 0b10101010 (MSB first)\n'
' 0b01010101 (LSB first)\n'
'\n'
' Bits: 16\n'
' Hex: 0x0000 (MSB first)\n'
' 0x0000 (LSB first)\n'
' Dec: 0 (MSB first)\n'
' 0 (LSB first)\n'
' Bin: 0b0000000000000000 (MSB first)\n'
' 0b0000000000000000 (LSB first)\n'
'\n'
' Bits: 32\n'
' Hex: 0x12345678 (MSB first)\n'
' 0x1E6A2C48 (LSB first)\n'
' Dec: 305419896 (MSB first)\n'
' 510274632 (LSB first)\n'
' Bin: 0b00010010001101000101011001111000 (MSB first)\n'
' 0b00011110011010100010110001001000 (LSB first)\n')
self.assertEqual(
output.getvalue(), '\n'
' Bits: 8\n'
' Hex: 0xAA (MSB first)\n'
' 0x55 (LSB first)\n'
' Dec: 170 (MSB first)\n'
' 85 (LSB first)\n'
' Bin: 0b10101010 (MSB first)\n'
' 0b01010101 (LSB first)\n'
'\n'
' Bits: 16\n'
' Hex: 0x0000 (MSB first)\n'
' 0x0000 (LSB first)\n'
' Dec: 0 (MSB first)\n'
' 0 (LSB first)\n'
' Bin: 0b0000000000000000 (MSB first)\n'
' 0b0000000000000000 (LSB first)\n'
'\n'
' Bits: 32\n'
' Hex: 0x12345678 (MSB first)\n'
' 0x1E6A2C48 (LSB first)\n'
' Dec: 305419896 (MSB first)\n'
' 510274632 (LSB first)\n'
' Bin: 0b00010010001101000101011001111000 (MSB first)\n'
' 0b00011110011010100010110001001000 (LSB first)\n')
class TestAutoAnalyseRawData(unittest.TestCase):
@@ -50,6 +52,12 @@ class TestAutoAnalyseRawData(unittest.TestCase):
# pylint: disable=too-many-public-methods
def test_avg_list(self):
"""Tests for the avg_list method."""
self.assertEqual(0, analyse.avg_list([]))
self.assertEqual(23, analyse.avg_list([10, 20, 40]))
def test_dump_constants_simple(self):
"""Simple tests for the dump_constants() function."""
ignore = StringIO()
@@ -70,12 +78,13 @@ class TestAutoAnalyseRawData(unittest.TestCase):
'const uint16_t kBARFreq = 38000; // Hz. (Guessing the most common '
'frequency.)'
])
self.assertEqual(output.getvalue(), 'Guessing key value:\n'
'kBARHdrMark = 7930\n'
'kBARHdrSpace = 3965\n'
'kBARBitMark = 496\n'
'kBAROneSpace = 1485\n'
'kBARZeroSpace = 520\n')
self.assertEqual(
output.getvalue(), 'Guessing key value:\n'
'kBARHdrMark = 7930\n'
'kBARHdrSpace = 3965\n'
'kBARBitMark = 496\n'
'kBAROneSpace = 1485\n'
'kBARZeroSpace = 520\n')
def test_dump_constants_aircon(self):
"""More complex tests for the dump_constants() function."""
@@ -106,13 +115,14 @@ class TestAutoAnalyseRawData(unittest.TestCase):
'const uint16_t kTESTFreq = 38000; // Hz. (Guessing the most common '
'frequency.)'
])
self.assertEqual(output.getvalue(), 'Guessing key value:\n'
'kTESTHdrMark = 9008\n'
'kTESTHdrSpace = 4496\n'
'kTESTBitMark = 650\n'
'kTESTOneSpace = 1657\n'
'kTESTZeroSpace = 554\n'
'kTESTSpaceGap = 19990\n')
self.assertEqual(
output.getvalue(), 'Guessing key value:\n'
'kTESTHdrMark = 9008\n'
'kTESTHdrSpace = 4496\n'
'kTESTBitMark = 650\n'
'kTESTOneSpace = 1657\n'
'kTESTZeroSpace = 554\n'
'kTESTSpaceGap = 19990\n')
def test_convert_rawdata(self):
"""Tests for the convert_rawdata() function."""
@@ -120,8 +130,8 @@ class TestAutoAnalyseRawData(unittest.TestCase):
self.assertEqual(analyse.convert_rawdata("0"), [0])
with self.assertRaises(ValueError) as context:
analyse.convert_rawdata("")
self.assertEqual(str(context.exception),
"Raw Data contains a non-numeric value of ''.")
self.assertEqual(
str(context.exception), "Raw Data contains a non-numeric value of ''.")
# Single parenthesis
self.assertEqual(analyse.convert_rawdata("foo {10"), [10])
@@ -141,14 +151,16 @@ class TestAutoAnalyseRawData(unittest.TestCase):
# Bad parentheses
with self.assertRaises(ValueError) as context:
analyse.convert_rawdata("}10{")
self.assertEqual(str(context.exception),
"Raw Data not parsible due to parentheses placement.")
self.assertEqual(
str(context.exception),
"Raw Data not parsible due to parentheses placement.")
# Non base-10 values
with self.assertRaises(ValueError) as context:
analyse.convert_rawdata("10, 20, foo, bar, 30")
self.assertEqual(str(context.exception),
"Raw Data contains a non-numeric value of 'foo'.")
self.assertEqual(
str(context.exception),
"Raw Data contains a non-numeric value of 'foo'.")
# A messy usual "good" case.
input_str = """uint16_t rawbuf[6] = {
@@ -228,8 +240,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
494, 520, 494, 1482, 494};"""
analyse.parse_and_report(input_str, 200, True, "FOO", output)
self.assertEqual(
output.getvalue(),
'Found 37 timing entries.\n'
output.getvalue(), 'Found 37 timing entries.\n'
'Potential Mark Candidates:\n'
'[7930, 520]\n'
'Potential Space Candidates:\n'
@@ -379,6 +390,350 @@ class TestAutoAnalyseRawData(unittest.TestCase):
'}\n'
'#endif // DECODE_FOO\n')
def test_reduce_list(self):
"""Tests for the reduce_list method."""
ignore = StringIO()
message = analyse.RawIRMessage(200, [
7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494,
520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494,
520, 520, 520, 494, 520, 494, 520, 494, 1482, 494
], ignore)
test_space_data = [4496, 1660, 530, 558, 1636, 1660, 556]
result_list, result_dict = message.reduce_list(test_space_data)
self.assertEqual([4496, 1660, 558], result_list)
self.assertEqual({
558: [558, 556, 530],
1660: [1660, 1660, 1636],
4496: [4496]
}, result_dict)
def test_leader_marks(self):
"""Tests for leader-type marks in parse_and_report() function."""
# Ref Issue #973
output = StringIO()
input_str = """
uint16_t rawData[853] = {
29784, 49290, 3416, 1604, 464, 1210, 468, 372, 460, 374, 462, 374,
466, 368, 464, 372, 462, 374, 464, 374, 464, 368, 464, 370, 464, 370,
466, 370, 464, 1208, 464, 374, 462, 372, 466, 374, 464, 370, 462, 372,
464, 370, 466, 370, 464, 372, 462, 374, 462, 374, 462, 378, 460, 370,
460, 374, 464, 372, 462, 372, 464, 374, 466, 368, 464, 1210, 464, 374,
466, 1202, 464, 1206, 464, 1210, 466, 1206, 468, 1204, 464, 1210, 466,
370, 462, 1214, 460, 1208, 464, 1206, 464, 1208, 466, 1208, 464, 1206,
466, 1208, 464, 1206, 466, 1212, 464, 370, 464, 370, 462, 374, 462,
374, 462, 374, 462, 374, 462, 372, 464, 376, 460, 372, 462, 374, 466,
1204, 464, 1210, 464, 372, 460, 374, 462, 1208, 464, 1212, 464, 1202,
468, 1204, 464, 374, 460, 374, 466, 1208, 462, 1210, 462, 374, 462,
376, 464, 368, 466, 1204, 462, 374, 466, 372, 464, 1206, 462, 376,
460, 376, 464, 1210, 462, 1208, 462, 372, 466, 1206, 464, 1208, 466,
372, 462, 1210, 462, 1210, 466, 374, 468, 1202, 464, 1206, 466, 374,
462, 372, 464, 1208, 464, 374, 464, 372, 464, 376, 462, 370, 466, 368,
464, 1208, 462, 1210, 460, 374, 464, 1208, 466, 1206, 464, 1214, 464,
368, 462, 374, 462, 1212, 460, 1210, 466, 1206, 466, 370, 462, 1210,
464, 416, 424, 1202, 466, 1220, 448, 376, 464, 372, 462, 372, 462,
1212, 462, 374, 460, 1214, 468, 364, 468, 370, 462, 372, 462, 376,
458, 374, 464, 372, 462, 376, 464, 376, 462, 1204, 464, 1210, 462,
1210, 464, 1208, 466, 1208, 464, 1206, 462, 1210, 464, 1212, 464, 368,
462, 372, 464, 372, 464, 372, 464, 372, 466, 370, 466, 370, 464, 376,
464, 1202, 464, 1212, 464, 1204, 464, 1210, 462, 1208, 464, 1212, 462,
1210, 464, 1212, 460, 372, 462, 374, 462, 374, 466, 370, 462, 374, 462,
372, 464, 372, 462, 376, 462, 1206, 464, 1206, 466, 1210, 462, 1208,
464, 1210, 466, 1204, 464, 1210, 462, 1214, 462, 368, 462, 374, 466,
370, 462, 376, 466, 368, 466, 370, 462, 414, 424, 374, 464, 1206, 464,
1206, 464, 1206, 468, 1206, 466, 1206, 466, 1210, 462, 1206, 464, 1214,
468, 364, 466, 372, 466, 370, 462, 372, 462, 374, 464, 372, 462, 374,
460, 376, 466, 1204, 464, 1208, 462, 1210, 464, 1206, 464, 1210, 464,
1208, 464, 1208, 466, 1210, 462, 1206, 466, 1206, 466, 372, 462, 374,
466, 1206, 466, 370, 464, 1206, 466, 376, 464, 368, 462, 372, 466,
1206, 464, 1206, 464, 374, 466, 1204, 464, 374, 466, 1206, 466, 1204,
468, 368, 466, 370, 466, 370, 462, 1212, 462, 1210, 462, 1210, 462,
1214, 464, 368, 464, 1206, 466, 1206, 466, 1206, 464, 374, 464, 370,
466, 370, 462, 378, 466, 366, 464, 372, 466, 368, 466, 370, 464, 370,
462, 372, 462, 374, 464, 374, 464, 1202, 466, 1206, 462, 1208, 466,
1208, 466, 1208, 464, 1210, 462, 1206, 464, 1212, 464, 368, 464, 372,
464, 370, 468, 368, 462, 376, 462, 372, 466, 370, 464, 376, 462, 1206,
464, 1210, 462, 1212, 462, 1208, 464, 1208, 462, 1212, 466, 1246, 424,
1212, 464, 368, 464, 372, 466, 370, 464, 372, 462, 374, 464, 372, 464,
370, 462, 1212, 466, 1206, 462, 1206, 464, 1210, 466, 1206, 462, 1208,
464, 1250, 422, 1208, 468, 372, 464, 1204, 466, 1206, 466, 370, 462,
374, 462, 376, 460, 374, 466, 370, 462, 376, 464, 368, 462, 376, 462,
1210, 462, 1208, 464, 1206, 466, 1206, 464, 1208, 468, 1212, 460, 1206,
464, 372, 464, 372, 466, 370, 462, 374, 466, 370, 466, 370, 466, 374,
464, 368, 462, 1210, 462, 1210, 464, 1210, 462, 1208, 462, 1212, 464,
1206, 466, 1208, 466, 366, 464, 374, 460, 374, 462, 1208, 466, 372,
462, 374, 462, 374, 464, 1212, 468, 1202, 464, 1208, 466, 1204, 464,
376, 460, 1208, 468, 1208, 462, 1208, 464, 378, 460, 372, 460, 372,
462, 376, 464, 372, 462, 374, 460, 374, 464, 370, 462, 378, 464, 1202,
468, 1204, 468, 1204, 466, 1208, 466, 1208, 464, 1210, 460, 1212, 462,
1212, 464, 366, 466, 370, 464, 372, 466, 370, 464, 372, 462, 414, 424,
372, 466, 372, 460, 1206, 466, 1206, 466, 1206, 466, 1208, 466, 1206,
464, 1208, 466, 1208, 462, 1212, 468, 1202, 466, 1204, 470, 1204, 468,
1204, 466, 1206, 466, 1206, 464, 1210, 462, 1212, 468, 366, 464, 372,
462, 374, 460, 374, 460, 374, 466, 410, 424, 372, 460, 378, 466, 1200,
464, 1212, 462, 1210, 464, 1210, 466, 1206, 462, 1208, 464, 1210, 464,
1210, 464, 366, 462, 376, 462, 374, 460, 376, 462, 372, 466, 374, 460,
372, 462, 378, 462, 1202, 468, 1206, 464, 1208, 466, 1208, 462, 1208,
464, 1208, 468, 1204, 464, 1212, 466, 368, 462, 374, 466, 372, 464,
370, 462, 374, 464, 370, 462, 376, 464, 374, 462, 1206, 464, 1208, 462,
1210, 466, 1208, 460, 1210, 468, 1206, 462, 1210, 464, 1212, 466, 366,
464, 374, 462, 372, 466, 370, 462, 374, 464, 372, 464, 370, 464, 374,
462};"""
analyse.parse_and_report(input_str, 200, True, "Hitachi", output)
self.assertEqual(
output.getvalue(), 'Found 853 timing entries.\n'
'Potential Mark Candidates:\n'
'[29784, 3416, 470]\n'
'Potential Space Candidates:\n'
'[49290, 1604, 1250, 416]\n'
'DANGER: Unusual number of mark timings!\n'
'Guessing encoding type:\n'
'Looks like it uses space encoding. Yay!\n'
'\n'
'Guessing key value:\n'
'kHitachiHdrMark = 3416\n'
'kHitachiHdrSpace = 1604\n'
'kHitachiBitMark = 463\n'
'kHitachiOneSpace = 1208\n'
'kHitachiZeroSpace = 372\n'
'kHitachiLdrMark = 29784\n'
'kHitachiSpaceGap = 49290\n'
'\n'
'Decoding protocol based on analysis so far:\n'
'\n'
'kHitachiLdrMark+UNEXPECTED->GAP(49290)kHitachiHdrMark+'
'kHitachiHdrSpace+100000000000100000000000000000101111110111111111'
'0000000000110011110011000100100110110110110010000011011100111010110001'
'010000000011111111000000001111111100000000111111110000000011111111'
'0000000011111111110010100011010110001111011100000000000011111111'
'0000000011111111000000011111111011000000001111111000000001111111'
'0001000111101110000000001111111100000000111111111111111100000000'
'111111110000000011111111000000001111111100000000\n'
' Bits: 424\n'
' Hex: 0x80080002FDFF0033CC49B6C8373AC500FF00FF00FF00FF00FFCA358F7000'
'FF00FF01FEC03F807F11EE00FF00FFFF00FF00FF00FF00 (MSB first)\n'
' 0x00FF00FF00FF00FFFF00FF007788FE01FC037F80FF00FF000EF1AC53FF00'
'FF00FF00FF00FF00A35CEC136D9233CC00FFBF40001001 (LSB first)\n'
' Dec: 21666770463250971033249250747302630158357464218891161163035832'
'525825434564377831675503794869126268735511944198247894513495375616'
' (MSB first)\n'
' 16857184424372658669179408622645041920057617761062334415219526'
'0950249734545225589859643087812860908833344117446370839379316737'
' (LSB first)\n'
' Bin: 0b100000000000100000000000000000101111110111111111000000000011'
'00111100110001001001101101101100100000110111001110101100010100000000'
'1111111100000000111111110000000011111111000000001111111100000000'
'1111111111001010001101011000111101110000000000001111111100000000'
'1111111100000001111111101100000000111111100000000111111100010001'
'1110111000000000111111110000000011111111111111110000000011111111'
'0000000011111111000000001111111100000000 (MSB first)\n'
' 0b000000001111111100000000111111110000000011111111000000001111'
'11111111111100000000111111110000000001110111100010001111111000000001'
'1111110000000011011111111000000011111111000000001111111100000000'
'0000111011110001101011000101001111111111000000001111111100000000'
'1111111100000000111111110000000011111111000000001010001101011100'
'1110110000010011011011011001001000110011110011000000000011111111'
'1011111101000000000000000001000000000001 (LSB first)\n'
'\n'
'Total Nr. of suspected bits: 424\n'
'\n'
'Generating a VERY rough code outline:\n'
'\n'
'// Copyright 2019 David Conran (crankyoldgit)\n'
'// Support for Hitachi protocol\n'
'\n'
'#include "IRrecv.h"\n'
'#include "IRsend.h"\n'
'#include "IRutils.h"\n'
'\n'
"// WARNING: This probably isn't directly usable. It's a guide only.\n"
'\n'
'// See https://github.com/crankyoldgit/IRremoteESP8266/wiki/'
'Adding-support-for-a-new-IR-protocol\n'
'// for details of how to include this in the library.\n'
'const uint16_t kHitachiHdrMark = 3416;\n'
'const uint16_t kHitachiBitMark = 463;\n'
'const uint16_t kHitachiHdrSpace = 1604;\n'
'const uint16_t kHitachiOneSpace = 1208;\n'
'const uint16_t kHitachiZeroSpace = 372;\n'
'const uint16_t kHitachiLdrMark = 29784;\n'
'const uint16_t kHitachiSpaceGap = 49290;\n'
'const uint16_t kHitachiFreq = 38000; // Hz. (Guessing the most'
' common frequency.)\n'
'const uint16_t kHitachiBits = 424; // Move to IRremoteESP8266.h\n'
'const uint16_t kHitachiStateLength = 53; // Move to IRremoteESP8266.h'
'\n'
'const uint16_t kHitachiOverhead = 5;\n'
"// DANGER: More than 64 bits detected. A uint64_t for 'data' won't"
' work!\n'
'#if SEND_HITACHI\n'
'// Function should be safe up to 64 bits.\n'
'void IRsend::sendHitachi(const uint64_t data, const uint16_t nbits,'
' const uint16_t repeat) {\n'
' enableIROut(kHitachiFreq);\n'
' for (uint16_t r = 0; r <= repeat; r++) {\n'
' uint64_t send_data = data;\n'
' // Leader\n'
' mark(kHitachiLdrMark);\n'
' // Gap\n'
' space(kHitachiSpaceGap);\n'
' // Header\n'
' mark(kHitachiHdrMark);\n'
' space(kHitachiHdrSpace);\n'
' // Data Section #1\n'
' // e.g. data = 0x80080002FDFF0033CC49B6C8373AC500FF00FF00FF00FF00'
'FFCA358F7000FF00FF01FEC03F807F11EE00FF00FFFF00FF00FF00FF00,'
' nbits = 424\n'
' sendData(kHitachiBitMark, kHitachiOneSpace, kHitachiBitMark,'
' kHitachiZeroSpace, send_data, 424, true);\n'
' send_data >>= 424;\n'
' // Footer\n'
' mark(kHitachiBitMark);\n'
' space(kDefaultMessageGap); // A 100% made up guess of the gap'
' between messages.\n'
' }\n'
'}\n'
'#endif // SEND_HITACHI\n'
'\n'
'#if SEND_HITACHI\n'
'// Alternative >64bit function to send HITACHI messages\n'
'// Where data is:\n'
'// uint8_t data[kHitachiStateLength] = {0x80, 0x08, 0x00, 0x02,'
' 0xFD, 0xFF, 0x00, 0x33, 0xCC, 0x49, 0xB6, 0xC8, 0x37, 0x3A, 0xC5,'
' 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xCA,'
' 0x35, 0x8F, 0x70, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0xFE, 0xC0, 0x3F,'
' 0x80, 0x7F, 0x11, 0xEE, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF,'
' 0x00, 0xFF, 0x00, 0xFF, 0x00};\n'
'//\n'
'// Args:\n'
'// data: An array of bytes containing the IR command.\n'
'// It is assumed to be in MSB order for this code.\n'
'// nbytes: Nr. of bytes of data in the array.'
' (>=kHitachiStateLength)\n'
'// repeat: Nr. of times the message is to be repeated.\n'
'//\n'
'// Status: ALPHA / Untested.\n'
'void IRsend::sendHitachi(const uint8_t data[], const uint16_t nbytes,'
' const uint16_t repeat) {\n'
' for (uint16_t r = 0; r <= repeat; r++) {\n'
' uint16_t pos = 0;\n'
' // Data Section #1\n'
' // e.g.\n'
' // bits = 424; bytes = 53;\n'
' // *(data + pos) = {0x80, 0x08, 0x00, 0x02, 0xFD, 0xFF, 0x00,'
' 0x33, 0xCC, 0x49, 0xB6, 0xC8, 0x37, 0x3A, 0xC5, 0x00, 0xFF, 0x00,'
' 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xCA, 0x35, 0x8F, 0x70,'
' 0x00, 0xFF, 0x00, 0xFF, 0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F, 0x11,'
' 0xEE, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,'
' 0xFF, 0x00};\n'
' sendGeneric(kHitachiHdrMark, kHitachiHdrSpace,\n'
' kHitachiBitMark, kHitachiOneSpace,\n'
' kHitachiBitMark, kHitachiZeroSpace,\n'
' kHitachiBitMark, kHitachiSpaceGap,\n'
' data + pos, 53, // Bytes\n'
' kHitachiFreq, true, kNoRepeat, kDutyDefault);\n'
' pos += 53; // Adjust by how many bytes of data we sent\n'
' }\n'
'}\n'
'#endif // SEND_HITACHI\n'
'\n'
"// DANGER: More than 64 bits detected. A uint64_t for 'data' won't"
' work!\n'
'#if DECODE_HITACHI\n'
'// Function should be safe up to 64 bits.\n'
'bool IRrecv::decodeHitachi(decode_results *results,'
' const uint16_t nbits, const bool strict) {\n'
' if (results->rawlen < 2 * nbits + kHitachiOverhead)\n'
' return false; // Too short a message to match.\n'
' if (strict && nbits != kHitachiBits)\n'
' return false;\n'
'\n'
' uint16_t offset = kStartOffset;\n'
' uint64_t data = 0;\n'
' match_result_t data_result;\n'
'\n'
' // Leader\n'
' if (!matchMark(results->rawbuf[offset++], kHitachiLdrMark))\n'
' return false;\n'
'\n'
' // Gap\n'
' if (!matchSpace(results->rawbuf[offset++], kHitachiSpaceGap))\n'
' return false;\n'
'\n'
' // Header\n'
' if (!matchMark(results->rawbuf[offset++], kHitachiHdrMark))\n'
' return false;\n'
' if (!matchSpace(results->rawbuf[offset++], kHitachiHdrSpace))\n'
' return false;\n'
'\n'
' // Data Section #1\n'
' // e.g. data_result.data = 0x80080002FDFF0033CC49B6C8373AC500FF00FF'
'00FF00FF00FFCA358F7000FF00FF01FEC03F807F11EE00FF00FFFF00FF00FF00FF00,'
' nbits = 424\n'
' data_result = matchData(&(results->rawbuf[offset]), 424,\n'
' kHitachiBitMark, kHitachiOneSpace,\n'
' kHitachiBitMark, kHitachiZeroSpace);\n'
' offset += data_result.used;\n'
' if (data_result.success == false) return false; // Fail\n'
' data <<= 424; // Make room for the new bits of data.\n'
' data |= data_result.data;\n'
'\n'
' // Footer\n'
' if (!matchMark(results->rawbuf[offset++], kHitachiBitMark))\n'
' return false;\n'
'\n'
' // Success\n'
' results->decode_type = decode_type_t::HITACHI;\n'
' results->bits = nbits;\n'
' results->value = data;\n'
' results->command = 0;\n'
' results->address = 0;\n'
' return true;\n'
'}\n'
'#endif // DECODE_HITACHI\n'
'\n'
'// Note: This should be 64+ bit safe.\n'
'#if DECODE_HITACHI\n'
'// Function should be safe over 64 bits.\n'
'bool IRrecv::decodeHitachi(decode_results *results,'
' const uint16_t nbits, const bool strict) {\n'
' if (results->rawlen < 2 * nbits + kHitachiOverhead)\n'
' return false; // Too short a message to match.\n'
' if (strict && nbits != kHitachiBits)\n'
' return false;\n'
'\n'
' uint16_t offset = kStartOffset;\n'
' uint16_t pos = 0;\n'
' uint16_t used = 0;\n'
'\n'
' // Data Section #1\n'
' // e.g.\n'
' // bits = 424; bytes = 53;\n'
' // *(results->state + pos) = {0x80, 0x08, 0x00, 0x02, 0xFD, 0xFF,'
' 0x00, 0x33, 0xCC, 0x49, 0xB6, 0xC8, 0x37, 0x3A, 0xC5, 0x00, 0xFF,'
' 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xCA, 0x35, 0x8F,'
' 0x70, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F,'
' 0x11, 0xEE, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF,'
' 0x00, 0xFF, 0x00};\n'
' used = matchGeneric(results->rawbuf + offset,'
' results->state + pos,\n'
' results->rawlen - offset, 424,\n'
' kHitachiHdrMark, kHitachiHdrSpace,\n'
' kHitachiBitMark, kHitachiOneSpace,\n'
' kHitachiBitMark, kHitachiZeroSpace,\n'
' kHitachiBitMark, kHitachiSpaceGap, true);\n'
' if (used == 0) return false; // We failed to find any data.\n'
' offset += used; // Adjust for how much of the message we read.\n'
' pos += 53; // Adjust by how many bytes of data we read\n'
'\n'
' // Success\n'
' results->decode_type = decode_type_t::HITACHI;\n'
' results->bits = nbits;\n'
' return true;\n'
'}\n'
'#endif // DECODE_HITACHI\n')
def test_unusual_gaps(self):
"""Tests for unusual Space Gaps in parse_and_report() function."""
@@ -412,8 +767,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
864, 2620, 864, 864, 864, 864, 3485, 3512, 864, 13996};"""
analyse.parse_and_report(input_str, 200, True, "FOO", output)
self.assertEqual(
output.getvalue(),
'Found 272 timing entries.\n'
output.getvalue(), 'Found 272 timing entries.\n'
'Potential Mark Candidates:\n'
'[3485, 864]\n'
'Potential Space Candidates:\n'
@@ -811,30 +1165,6 @@ class TestAutoAnalyseRawData(unittest.TestCase):
'}\n'
'#endif // DECODE_FOO\n')
def test_reduce_list(self):
"""Tests for the reduce_list method."""
ignore = StringIO()
message = analyse.RawIRMessage(200, [
7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494,
520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494,
520, 520, 520, 494, 520, 494, 520, 494, 1482, 494
], ignore)
test_space_data = [4496, 1660, 530, 558, 1636, 1660, 556]
result_list, result_dict = message.reduce_list(test_space_data)
self.assertEqual([4496, 1660, 558], result_list)
self.assertEqual({
558: [558, 556, 530],
1660: [1660, 1660, 1636],
4496: [4496]
}, result_dict)
def test_avg_list(self):
"""Tests for the avg_list method."""
self.assertEqual(0, analyse.avg_list([]))
self.assertEqual(23, analyse.avg_list([10, 20, 40]))
if __name__ == '__main__':
unittest.main(verbosity=2)
@@ -26,8 +26,8 @@ cat >${OUTPUT} << EOF
EOF
# Parse and output contents of INPUT file.
egrep "^(String|char) " ${INPUT} | cut -f1 -d= |
sed 's/ PROGMEM//;s/ $/;/;s/^/extern const /' | sort -u >> ${OUTPUT}
sed 's/ PROGMEM//' ${INPUT} | egrep "^(const )?char" | cut -f1 -d= |
sed 's/ $/;/;s/^/extern /' | sort -u >> ${OUTPUT}
# Footer
cat >> ${OUTPUT} << EOF