mirror of https://github.com/arendst/Tasmota.git
Merge pull request #14406 from s-hadinger/ir_281
IRremoteESP8266 library from v2.8.0 to v2.8.1
This commit is contained in:
commit
955d807cec
|
@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Tasmota favicon to webbrowser tab (#14322)
|
||||
|
||||
### Changed
|
||||
- IRremoteESP8266 library from v2.8.0 to v2.8.1
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
This library enables you to **send _and_ receive** infra-red signals on an [ESP8266](https://github.com/esp8266/Arduino) or an
|
||||
[ESP32](https://github.com/espressif/arduino-esp32) using the [Arduino framework](https://www.arduino.cc/) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* demodulators etc.
|
||||
|
||||
## v2.8.0 Now Available
|
||||
Version 2.8.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.
|
||||
## v2.8.1 Now Available
|
||||
Version 2.8.1 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.
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
Diese Programmbibliothek ermöglicht das **Senden _und_ Empfangen** von Infrarotsignalen mit [ESP8266](https://github.com/esp8266/Arduino)- und
|
||||
[ESP32](https://github.com/espressif/arduino-esp32)-Mikrocontrollern mithilfe des [Arduino-Frameworks](https://www.arduino.cc/) und handelsüblichen 940nm Infrarot-LEDs undIR-Empfängermodulen, wie zum Beispiel TSOP{17,22,24,36,38,44,48}*-Demodulatoren.
|
||||
|
||||
## v2.8.0 jetzt verfügbar
|
||||
Version 2.8.0 der Bibliothek ist nun [verfügbar](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Die [Versionshinweise](ReleaseNotes.md) enthalten alle wichtigen Neuerungen.
|
||||
## v2.8.1 jetzt verfügbar
|
||||
Version 2.8.1 der Bibliothek ist nun [verfügbar](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Die [Versionshinweise](ReleaseNotes.md) enthalten alle wichtigen Neuerungen.
|
||||
|
||||
#### Hinweis für Nutzer von Versionen vor v2.0
|
||||
Die Benutzung der Bibliothek hat sich mit Version 2.0 leicht geändert. Einige Anpassungen im aufrufenden Code werden nötig sein, um mit Version ab 2.0 korrekt zu funktionieren. Mehr zu den Anpassungen finden sich auf unserer [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0)-Seite.
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
Cette librairie vous permetra de **recevoir et d'envoyer des signaux** infrarouge sur le protocole [ESP8266](https://github.com/esp8266/Arduino) ou sur le protocole
|
||||
[ESP32](https://github.com/espressif/arduino-esp32) en utilisant le [Arduino framework](https://www.arduino.cc/) qui utilise la norme 940nm IR LEDs et le module basique de reception d'onde IR. Exemple : TSOP{17,22,24,36,38,44,48}* modules etc.
|
||||
|
||||
## v2.8.0 disponible
|
||||
Version 2.8.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.
|
||||
## v2.8.1 disponible
|
||||
Version 2.8.1 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.
|
||||
|
|
|
@ -1,5 +1,29 @@
|
|||
# Release Notes
|
||||
|
||||
## _v2.8.1 (20220101)_
|
||||
|
||||
**[Bug Fixes]**
|
||||
- Arduino ESP32 Core v2.0.2+ crashes due to our timer hack. (#1715 #1713)
|
||||
- SONY: Fix old Sony CD-Player Remote (12 Bit) (#1714)
|
||||
|
||||
**[Features]**
|
||||
- Add tool to convert protocol & code to raw timing info. (#1708 #1707 #1703)
|
||||
- Add basic support for COOLIX48 protocol. (#1697 #1694)
|
||||
- MITSUBISHI_AC: Added support for i-SAVE mode. (#1666)
|
||||
- TOSHIBA_AC: Add Filter setting support. aka. Pure. (#1693 #1692)
|
||||
- Airton: Add detailed A/C support. (#1688 #1670)
|
||||
|
||||
**[Misc]**
|
||||
- Add a structured library version number. (#1717)
|
||||
- Workflows Split UnitTests (#1712)
|
||||
- Reduce time for workflow/Build (#1709)
|
||||
- Fix some compiler & linter warnings (#1699 #1700)
|
||||
- Fujitsu: Update supported A/C models (#1690 #1689 #1702 #1701)
|
||||
- Remove extra `const` qualifier for char pointer (#1704)
|
||||
- TCL: Update supported devices. (#1698)
|
||||
- ESP32-C3: Work around for some C3 specific compiler issues. (#1696 #1695)
|
||||
|
||||
|
||||
## _v2.8.0 (20211119)_
|
||||
|
||||
**[Bug Fixes]**
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<!--- WARNING: Do NOT edit this file directly.
|
||||
It is generated by './tools/scrape_supported_devices.py'.
|
||||
Last generated: Fri 19 Nov 2021 00:35:37 +0000 --->
|
||||
Last generated: Fri 31 Dec 2021 21:49:00 +0000 --->
|
||||
# IR Protocols supported by this library
|
||||
|
||||
| Protocol | Brand | Model | A/C Model | Detailed A/C Support |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| [Airton](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airton.cpp) | **Airton** | RD1A1 remote<BR>SMVH09B-2A2A3NH ref. 409730 A/C | | - |
|
||||
| [Airton](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airton.cpp) | **[Airton](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airton.h)** | RD1A1 remote<BR>SMVH09B-2A2A3NH ref. 409730 A/C | | Yes |
|
||||
| [Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airwell.cpp) | **[Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airwell.h)** | DLS 21 DCI R410 AW A/C<BR>RC04 remote<BR>RC08W remote | | Yes |
|
||||
| [Aiwa](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Aiwa.cpp) | **Aiwa** | RC-T501 RCU | | - |
|
||||
| [Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.cpp) | **[Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.h)** | ADR-853H A/C<BR>TAC-444 remote<BR>TAC-495 remote | | Yes |
|
||||
|
@ -15,6 +15,7 @@
|
|||
| [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **[Carrier/Surrey](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.h)** | 42QG5A55970 remote<BR>53NGK009/012 Inverter<BR>619EGX0090E0 A/C<BR>619EGX0120E0 A/C<BR>619EGX0180E0 A/C<BR>619EGX0220E0 A/C | | Yes |
|
||||
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | RC08B remote | | Yes |
|
||||
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Beko](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | BINR 070/071 split-type A/C<BR>RG57K7(B)/BGEF Remote | | Yes |
|
||||
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Bosch](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | B1ZAI2441W/B1ZAO2441W A/C<BR>RG36B4/BGE remote | | Yes |
|
||||
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Kastron](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | RG57A7/BGEF Inverter remote | | Yes |
|
||||
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Kaysun](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | Casual CF A/C | | 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>MSABAU-07HRFN1-QRD0GW A/C (circa 2016)<BR>RG52D/BGE Remote | | Yes |
|
||||
|
@ -35,7 +36,7 @@
|
|||
| [EliteScreens](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_EliteScreens.cpp) | **Elite Screens** | CineTension2 / CineTension3 series<BR>Home2 / Home3 series<BR>Spectrum series<BR>VMAX Plus4 series<BR>VMAX2 / VMAX2 Plus series<BR>ZSP-IR-B / ZSP-IR-W remote | | - |
|
||||
| [EliteScreens](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_EliteScreens.cpp) | **Lumene Screens** | Embassy | | - |
|
||||
| [Epson](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Epson.cpp) | **Epson** | EN-TW9100W Projector<BR>EX3220 Projector<BR>EX5220 Projector<BR>EX5230 Projector<BR>EX6220 Projector<BR>EX7220 Projector<BR>VS230 Projector<BR>VS330 Projector | | - |
|
||||
| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AGTV14LAC A/C (ARRAH2E)<BR>AR-DB1 remote (ARDB1)<BR>AR-DL10 remote (ARDB1)<BR>AR-RAC1E remote (ARRAH2E)<BR>AR-RAE1E remote (ARRAH2E)<BR>AR-RAH1U remote (ARREB1E)<BR>AR-RAH2E remote (ARRAH2E)<BR>AR-REB1E remote (ARREB1E)<BR>AR-REW4E remote (ARREW4E)<BR>AR-RY4 remote (ARRY4)<BR>AST9RSGCW A/C (ARDB1)<BR>ASTB09LBC A/C (ARRY4)<BR>ASU12RLF A/C (ARREB1E)<BR>ASU30C1 A/C (ARDB1)<BR>ASYG09KETA-B A/C (ARREW4E)<BR>ASYG30LFCA A/C (ARRAH2E)<BR>ASYG7LMCA A/C (ARREB1E) | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E<BR>ARREW4E<BR>ARRY4 | Yes |
|
||||
| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AGTV14LAC A/C (ARRAH2E)<BR>AR-DB1 remote (ARDB1)<BR>AR-DL10 remote (ARDB1)<BR>AR-RAC1E remote (ARRAH2E)<BR>AR-RAE1E remote (ARRAH2E)<BR>AR-RAH1U remote (ARREB1E)<BR>AR-RAH2E remote (ARRAH2E)<BR>AR-REB1E remote (ARREB1E)<BR>AR-REB4E remote (ARREB1E)<BR>AR-REW1E remote (ARREW4E)<BR>AR-REW4E remote (ARREW4E)<BR>AR-RY4 remote (ARRY4)<BR>AST9RSGCW A/C (ARDB1)<BR>ASTB09LBC A/C (ARRY4)<BR>ASTG09K A/C (ARREW4E)<BR>ASTG18K A/C (ARREW4E)<BR>ASU12RLF A/C (ARREB1E)<BR>ASU30C1 A/C (ARDB1)<BR>ASYG09KETA-B A/C (ARREW4E)<BR>ASYG30LFCA A/C (ARRAH2E)<BR>ASYG7LMCA A/C (ARREB1E) | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E<BR>ARREW4E<BR>ARRY4 | Yes |
|
||||
| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AOHG09LLC A/C (ARRAH2E)<BR>AR-JW2 remote (ARJW2)<BR>AR-RCE1E remote (ARRAH2E)<BR>ASHG09LLCA A/C (ARRAH2E) | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E<BR>ARREW4E<BR>ARRY4 | Yes |
|
||||
| [GICable](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GICable.cpp) | **G.I. Cable** | XRC-200 remote | | - |
|
||||
| [GlobalCache](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GlobalCache.cpp) | **Global Cache** | Control Tower IR DB | | - |
|
||||
|
@ -79,7 +80,7 @@
|
|||
| [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | VLU series A/C | KKG29AC1<BR>KKG9AC1 | Yes |
|
||||
| [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Tronitechnik](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | KKG29A-C1 remote<BR>Reykir 9000 A/C | KKG29AC1<BR>KKG9AC1 | 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 (MITSUBISHI2)<BR>KM14A 0179213 remote<BR>MS-GK24VA A/C<BR>TV (MITSUBISHI) | | 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 (MITSUBISHI136)<BR>KPOA remote (MITSUBISHI112)<BR>MLZ-RX5017AS A/C (MITSUBISHI_AC)<BR>MSH-A24WV A/C (MITSUBISHI112)<BR>MSZ-GV2519 A/C (MITSUBISHI_AC)<BR>MSZ-SF25VE3 A/C (MITSUBISHI_AC)<BR>MSZ-ZW4017S A/C (MITSUBISHI_AC)<BR>MUH-A24WV A/C (MITSUBISHI112)<BR>PEAD-RP71JAA Ducted A/C (MITSUBISHI136)<BR>RH151/M21ED6426 remote (MITSUBISHI_AC)<BR>SG153/M21EDF426 remote (MITSUBISHI_AC)<BR>SG15D remote (MITSUBISHI_AC) | | 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 (MITSUBISHI136)<BR>KPOA remote (MITSUBISHI112)<BR>MLZ-RX5017AS A/C (MITSUBISHI_AC)<BR>MSH-A24WV A/C (MITSUBISHI112)<BR>MSZ-FHnnVE A/C (MITSUBISHI_AC)<BR>MSZ-GV2519 A/C (MITSUBISHI_AC)<BR>MSZ-SF25VE3 A/C (MITSUBISHI_AC)<BR>MSZ-ZW4017S A/C (MITSUBISHI_AC)<BR>MUH-A24WV A/C (MITSUBISHI112)<BR>PEAD-RP71JAA Ducted A/C (MITSUBISHI136)<BR>RH151/M21ED6426 remote (MITSUBISHI_AC)<BR>SG153/M21EDF426 remote (MITSUBISHI_AC)<BR>SG15D remote (MITSUBISHI_AC) | | 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 (88 bit)<BR>RLA502A700B remote (152 bit)<BR>SRKxxZJ-S A/C (88 bit)<BR>SRKxxZM-S A/C (152 bit)<BR>SRKxxZMXA-S A/C (152 bit) | | Yes |
|
||||
| [Multibrackets](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Multibrackets.cpp) | **Multibrackets** | Motorized Swing mount large - 4500 | | - |
|
||||
| [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Aloka](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | SleepyLights LED Lamp | | - |
|
||||
|
@ -107,6 +108,7 @@
|
|||
| [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **SilverCrest** | SSVS 85 A1 Fan | | - |
|
||||
| [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Symphony** | Air Cooler 3Di | | - |
|
||||
| [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Westinghouse** | 78095 Remote<BR>Ceiling fan | | - |
|
||||
| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Daewoo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | DSB-F0934ELH-V A/C<BR>GYKQ-52E remote | GZ055BE1<BR>TAC09CHSD | Yes |
|
||||
| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Leberg](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | LBS-TOR07 A/C (TAC09CHSD) | GZ055BE1<BR>TAC09CHSD | Yes |
|
||||
| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[TCL](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | TAC-09CHSD/XA31I A/C (TAC09CHSD) | GZ055BE1<BR>TAC09CHSD | Yes |
|
||||
| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Teknopoint](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | Allegro SSA-09H A/C (GZ055BE1)<BR>GZ-055B-E1 remote (GZ055BE1) | GZ055BE1<BR>TAC09CHSD | Yes |
|
||||
|
@ -114,7 +116,7 @@
|
|||
| [Teco](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.cpp) | **[Alaska](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.h)** | SAC9010QC A/C<BR>SAC9010QC remote | | Yes |
|
||||
| [Teknopoint](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teknopoint.cpp) | **Teknopoint** | Allegro SSA-09H A/C<BR>GZ-055B-E1 remote | | - |
|
||||
| [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | 42NQV025M2 / 38NYV025M2 A/C<BR>42NQV035M2 / 38NYV035M2 A/C<BR>42NQV050M2 / 38NYV050M2 A/C<BR>42NQV060M2 / 38NYV060M2 A/C | | Yes |
|
||||
| [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | Akita EVO II<BR>RAS 18SKP-ES<BR>RAS-2558V A/C<BR>RAS-B13N3KV2<BR>RAS-B13N3KVP-E<BR>WC-L03SE<BR>WH-TA04NE<BR>WH-UB03NJ remote | | Yes |
|
||||
| [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | Akita EVO II<BR>RAS 18SKP-ES<BR>RAS-2558V A/C<BR>RAS-25SKVP2-ND A/C<BR>RAS-B13N3KV2<BR>RAS-B13N3KVP-E<BR>WC-L03SE<BR>WH-TA01JE remote<BR>WH-TA04NE<BR>WH-UB03NJ remote | | Yes |
|
||||
| [Transcold](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Transcold.cpp) | **[Transcold](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Transcold.h)** | M1-F-NO-6 A/C | | Yes |
|
||||
| [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Duux](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | Blizzard Smart 10K / DXMA04 A/C (TROTEC) | | Yes |
|
||||
| [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | PAC 3200 A/C (TROTEC)<BR>PAC 3550 Pro A/C (TROTEC_3550) | | Yes |
|
||||
|
@ -149,6 +151,7 @@
|
|||
- CARRIER_AC40
|
||||
- CARRIER_AC64
|
||||
- COOLIX
|
||||
- COOLIX48
|
||||
- CORONA_AC
|
||||
- DAIKIN
|
||||
- DAIKIN128
|
||||
|
|
|
@ -1249,7 +1249,7 @@ void handleInfo(void) {
|
|||
"Built: " __DATE__
|
||||
" " __TIME__ "<br>"
|
||||
"Period Offset: ") + String(offset) + F("us<br>"
|
||||
"IR Lib Version: " _IRREMOTEESP8266_VERSION_ "<br>"
|
||||
"IR Lib Version: " _IRREMOTEESP8266_VERSION_STR "<br>"
|
||||
#if defined(ESP8266)
|
||||
"ESP8266 Core Version: ") + ESP.getCoreVersion() + F("<br>"
|
||||
"Free Sketch Space: ") + String(maxSketchSpace() >> 10) + F("k<br>"
|
||||
|
|
|
@ -154,7 +154,7 @@ void loop() {
|
|||
if (results.overflow)
|
||||
Serial.printf(D_WARN_BUFFERFULL "\n", kCaptureBufferSize);
|
||||
// Display the library version the message was captured with.
|
||||
Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_ "\n");
|
||||
Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_STR "\n");
|
||||
// Display the tolerance percentage if it has been change from the default.
|
||||
if (kTolerancePercentage != kTolerance)
|
||||
Serial.printf(D_STR_TOLERANCE " : %d%%\n", kTolerancePercentage);
|
||||
|
|
|
@ -163,7 +163,7 @@ void loop() {
|
|||
if (results.overflow)
|
||||
Serial.printf(D_WARN_BUFFERFULL "\n", kCaptureBufferSize);
|
||||
// Display the library version the message was captured with.
|
||||
Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_ "\n");
|
||||
Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_STR "\n");
|
||||
// Display the tolerance percentage if it has been change from the default.
|
||||
if (kTolerancePercentage != kTolerance)
|
||||
Serial.printf(D_STR_TOLERANCE " : %d%%\n", kTolerancePercentage);
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
# Datatypes & Classes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
CoronaSection KEYWORD1
|
||||
IRAirtonAc KEYWORD1
|
||||
IRAirwellAc KEYWORD1
|
||||
IRAmcorAc KEYWORD1
|
||||
IRArgoAC KEYWORD1
|
||||
|
@ -147,6 +149,7 @@ addTempFloatToString KEYWORD2
|
|||
addTempToString KEYWORD2
|
||||
addToggleToString KEYWORD2
|
||||
adjustRepeat KEYWORD2
|
||||
airton KEYWORD2
|
||||
airwell KEYWORD2
|
||||
amcor KEYWORD2
|
||||
argo KEYWORD2
|
||||
|
@ -174,6 +177,7 @@ checkSum KEYWORD2
|
|||
checkZjsSig KEYWORD2
|
||||
checkZmsSig KEYWORD2
|
||||
checksum KEYWORD2
|
||||
cleanState KEYWORD2
|
||||
clearOnTimerFlag KEYWORD2
|
||||
clearPowerSpecial KEYWORD2
|
||||
clearSensorTemp KEYWORD2
|
||||
|
@ -211,6 +215,7 @@ decodeCOOLIX KEYWORD2
|
|||
decodeCarrierAC KEYWORD2
|
||||
decodeCarrierAC40 KEYWORD2
|
||||
decodeCarrierAC64 KEYWORD2
|
||||
decodeCoolix48 KEYWORD2
|
||||
decodeCoronaAc KEYWORD2
|
||||
decodeDISH KEYWORD2
|
||||
decodeDaikin KEYWORD2
|
||||
|
@ -339,6 +344,7 @@ fujitsu KEYWORD2
|
|||
get10CHeat KEYWORD2
|
||||
get3D KEYWORD2
|
||||
get8CHeat KEYWORD2
|
||||
getAbsenseDetect KEYWORD2
|
||||
getBeep KEYWORD2
|
||||
getBit KEYWORD2
|
||||
getBoost KEYWORD2
|
||||
|
@ -356,9 +362,11 @@ getCorrectedRawLength KEYWORD2
|
|||
getCurrTime KEYWORD2
|
||||
getCurrentDay KEYWORD2
|
||||
getCurrentTime KEYWORD2
|
||||
getDirectIndirect KEYWORD2
|
||||
getDisplay KEYWORD2
|
||||
getDisplayTempSource KEYWORD2
|
||||
getDryGrade KEYWORD2
|
||||
getEcocool KEYWORD2
|
||||
getEcono KEYWORD2
|
||||
getEconoToggle KEYWORD2
|
||||
getEnableSensorTemp KEYWORD2
|
||||
|
@ -377,6 +385,8 @@ getHold KEYWORD2
|
|||
getHumid KEYWORD2
|
||||
getHumidity KEYWORD2
|
||||
getIFeel KEYWORD2
|
||||
getISave10C KEYWORD2
|
||||
getISee KEYWORD2
|
||||
getId KEYWORD2
|
||||
getInternalStateLength KEYWORD2
|
||||
getIon KEYWORD2
|
||||
|
@ -388,6 +398,7 @@ getLock KEYWORD2
|
|||
getMax KEYWORD2
|
||||
getMode KEYWORD2
|
||||
getMold KEYWORD2
|
||||
getNaturalFlow KEYWORD2
|
||||
getNight KEYWORD2
|
||||
getOffSleepTimer KEYWORD2
|
||||
getOffTime KEYWORD2
|
||||
|
@ -423,7 +434,9 @@ getSleepTimerEnabled KEYWORD2
|
|||
getSpecial KEYWORD2
|
||||
getSpeed KEYWORD2
|
||||
getStartClock KEYWORD2
|
||||
getState KEYWORD2
|
||||
getStateLength KEYWORD2
|
||||
getStatePrev KEYWORD2
|
||||
getStopClock KEYWORD2
|
||||
getSupercool KEYWORD2
|
||||
getSwing KEYWORD2
|
||||
|
@ -474,6 +487,7 @@ haier KEYWORD2
|
|||
haier176 KEYWORD2
|
||||
haierYrwo2 KEYWORD2
|
||||
handleSpecialState KEYWORD2
|
||||
handleToggles KEYWORD2
|
||||
hasACState KEYWORD2
|
||||
hasInvertedStates KEYWORD2
|
||||
hasStateChanged KEYWORD2
|
||||
|
@ -571,6 +585,7 @@ sendCOOLIX KEYWORD2
|
|||
sendCarrierAC KEYWORD2
|
||||
sendCarrierAC40 KEYWORD2
|
||||
sendCarrierAC64 KEYWORD2
|
||||
sendCoolix48 KEYWORD2
|
||||
sendCoronaAc KEYWORD2
|
||||
sendDISH KEYWORD2
|
||||
sendDaikin KEYWORD2
|
||||
|
@ -679,6 +694,7 @@ serialPrintUint64 KEYWORD2
|
|||
set10CHeat KEYWORD2
|
||||
set3D KEYWORD2
|
||||
set8CHeat KEYWORD2
|
||||
setAbsenseDetect KEYWORD2
|
||||
setAuto KEYWORD2
|
||||
setBeep KEYWORD2
|
||||
setBit KEYWORD2
|
||||
|
@ -696,9 +712,11 @@ setCommand KEYWORD2
|
|||
setCurrTime KEYWORD2
|
||||
setCurrentDay KEYWORD2
|
||||
setCurrentTime KEYWORD2
|
||||
setDirectIndirect KEYWORD2
|
||||
setDisplay KEYWORD2
|
||||
setDisplayTempSource KEYWORD2
|
||||
setDryGrade KEYWORD2
|
||||
setEcocool KEYWORD2
|
||||
setEcono KEYWORD2
|
||||
setEconoToggle KEYWORD2
|
||||
setEnableSensorTemp KEYWORD2
|
||||
|
@ -717,6 +735,8 @@ setHold KEYWORD2
|
|||
setHumid KEYWORD2
|
||||
setHumidity KEYWORD2
|
||||
setIFeel KEYWORD2
|
||||
setISave10C KEYWORD2
|
||||
setISee KEYWORD2
|
||||
setId KEYWORD2
|
||||
setInvertedStates KEYWORD2
|
||||
setIon KEYWORD2
|
||||
|
@ -729,6 +749,7 @@ setMax KEYWORD2
|
|||
setMode KEYWORD2
|
||||
setModel KEYWORD2
|
||||
setMold KEYWORD2
|
||||
setNaturalFlow KEYWORD2
|
||||
setNight KEYWORD2
|
||||
setOffTime KEYWORD2
|
||||
setOffTimeEnabled KEYWORD2
|
||||
|
@ -819,6 +840,7 @@ technibel KEYWORD2
|
|||
teco KEYWORD2
|
||||
ticksHigh KEYWORD2
|
||||
ticksLow KEYWORD2
|
||||
toCommon KEYWORD2
|
||||
toString KEYWORD2
|
||||
toggleArrisRelease KEYWORD2
|
||||
toggleRC5 KEYWORD2
|
||||
|
@ -896,6 +918,7 @@ CARRIER_AC40 LITERAL1
|
|||
CARRIER_AC64 LITERAL1
|
||||
CARRIER_AC_BITS LITERAL1
|
||||
COOLIX LITERAL1
|
||||
COOLIX48 LITERAL1
|
||||
COOLIX_BITS LITERAL1
|
||||
CORONA_AC LITERAL1
|
||||
DAIKIN LITERAL1
|
||||
|
@ -930,6 +953,7 @@ DECODE_CARRIER_AC LITERAL1
|
|||
DECODE_CARRIER_AC40 LITERAL1
|
||||
DECODE_CARRIER_AC64 LITERAL1
|
||||
DECODE_COOLIX LITERAL1
|
||||
DECODE_COOLIX48 LITERAL1
|
||||
DECODE_CORONA_AC LITERAL1
|
||||
DECODE_DAIKIN LITERAL1
|
||||
DECODE_DAIKIN128 LITERAL1
|
||||
|
@ -1284,6 +1308,7 @@ SEND_CARRIER_AC LITERAL1
|
|||
SEND_CARRIER_AC40 LITERAL1
|
||||
SEND_CARRIER_AC64 LITERAL1
|
||||
SEND_COOLIX LITERAL1
|
||||
SEND_COOLIX48 LITERAL1
|
||||
SEND_CORONA_AC LITERAL1
|
||||
SEND_DAIKIN LITERAL1
|
||||
SEND_DAIKIN128 LITERAL1
|
||||
|
@ -1443,13 +1468,27 @@ k8CHeatStr LITERAL1
|
|||
kA705Str LITERAL1
|
||||
kA903Str LITERAL1
|
||||
kA907Str LITERAL1
|
||||
kAbsenseDetectStr LITERAL1
|
||||
kAirFlowStr LITERAL1
|
||||
kAirtonAuto LITERAL1
|
||||
kAirtonBitMark LITERAL1
|
||||
kAirtonBits LITERAL1
|
||||
kAirtonCool LITERAL1
|
||||
kAirtonDefaultRepeat LITERAL1
|
||||
kAirtonDry LITERAL1
|
||||
kAirtonFan LITERAL1
|
||||
kAirtonFanAuto LITERAL1
|
||||
kAirtonFanHigh LITERAL1
|
||||
kAirtonFanLow LITERAL1
|
||||
kAirtonFanMax LITERAL1
|
||||
kAirtonFanMed LITERAL1
|
||||
kAirtonFanMin LITERAL1
|
||||
kAirtonFreq LITERAL1
|
||||
kAirtonHdrMark LITERAL1
|
||||
kAirtonHdrSpace LITERAL1
|
||||
kAirtonHeat LITERAL1
|
||||
kAirtonMaxTemp LITERAL1
|
||||
kAirtonMinTemp LITERAL1
|
||||
kAirtonOneSpace LITERAL1
|
||||
kAirtonZeroSpace LITERAL1
|
||||
kAirwellAuto LITERAL1
|
||||
|
@ -1645,6 +1684,8 @@ kCommandStr LITERAL1
|
|||
kCool LITERAL1
|
||||
kCoolStr LITERAL1
|
||||
kCoolingStr LITERAL1
|
||||
kCoolix48Bits LITERAL1
|
||||
kCoolix48ExtraTolerance LITERAL1
|
||||
kCoolixAuto LITERAL1
|
||||
kCoolixBitMark LITERAL1
|
||||
kCoolixBitMarkTicks LITERAL1
|
||||
|
@ -1997,6 +2038,8 @@ kDenonZeroSpaceTicks LITERAL1
|
|||
kDg11j104Str LITERAL1
|
||||
kDg11j13aStr LITERAL1
|
||||
kDg11j191Str LITERAL1
|
||||
kDirectIndirectModeStr LITERAL1
|
||||
kDirectStr LITERAL1
|
||||
kDishBitMark LITERAL1
|
||||
kDishBitMarkTicks LITERAL1
|
||||
kDishBits LITERAL1
|
||||
|
@ -2478,6 +2521,7 @@ kHourStr LITERAL1
|
|||
kHoursStr LITERAL1
|
||||
kHumidStr LITERAL1
|
||||
kIFeelStr LITERAL1
|
||||
kISeeStr LITERAL1
|
||||
kIdStr LITERAL1
|
||||
kIdleState LITERAL1
|
||||
kInaxBitMark LITERAL1
|
||||
|
@ -2489,6 +2533,7 @@ kInaxMinRepeat LITERAL1
|
|||
kInaxOneSpace LITERAL1
|
||||
kInaxTick LITERAL1
|
||||
kInaxZeroSpace LITERAL1
|
||||
kIndirectStr LITERAL1
|
||||
kInsideStr LITERAL1
|
||||
kIonStr LITERAL1
|
||||
kJkeStr LITERAL1
|
||||
|
@ -2894,6 +2939,8 @@ kMitsubishiACStateLength LITERAL1
|
|||
kMitsubishiAcAuto LITERAL1
|
||||
kMitsubishiAcBitMark LITERAL1
|
||||
kMitsubishiAcCool LITERAL1
|
||||
kMitsubishiAcDirect LITERAL1
|
||||
kMitsubishiAcDirectOff LITERAL1
|
||||
kMitsubishiAcDry LITERAL1
|
||||
kMitsubishiAcExtraTolerance LITERAL1
|
||||
kMitsubishiAcFan LITERAL1
|
||||
|
@ -2905,6 +2952,7 @@ kMitsubishiAcFanSilent LITERAL1
|
|||
kMitsubishiAcHdrMark LITERAL1
|
||||
kMitsubishiAcHdrSpace LITERAL1
|
||||
kMitsubishiAcHeat LITERAL1
|
||||
kMitsubishiAcIndirect LITERAL1
|
||||
kMitsubishiAcMaxTemp LITERAL1
|
||||
kMitsubishiAcMinTemp LITERAL1
|
||||
kMitsubishiAcNoTimer LITERAL1
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "IRremoteESP8266",
|
||||
"version": "2.8.0",
|
||||
"version": "2.8.1",
|
||||
"keywords": "infrared, ir, remote, esp8266, esp32",
|
||||
"description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)",
|
||||
"repository":
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name=IRremoteESP8266
|
||||
version=2.8.0
|
||||
version=2.8.1
|
||||
author=David Conran, Sebastien Warin, Mark Szabo, Ken Shirriff
|
||||
maintainer=David Conran, Mark Szabo, Sebastien Warin, Roi Dayan, Massimiliano Pinto, Christian Nilsson
|
||||
sentence=Send and receive infrared signals with multiple protocols (ESP8266/ESP32)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "IRremoteESP8266.h"
|
||||
#include "IRtext.h"
|
||||
#include "IRutils.h"
|
||||
#include "ir_Airton.h"
|
||||
#include "ir_Airwell.h"
|
||||
#include "ir_Amcor.h"
|
||||
#include "ir_Argo.h"
|
||||
|
@ -56,7 +57,7 @@
|
|||
#ifndef STRCASECMP
|
||||
#if defined(ESP8266)
|
||||
#define STRCASECMP(LHS, RHS) \
|
||||
strcasecmp_P(LHS, reinterpret_cast<const char* const>(RHS))
|
||||
strcasecmp_P(LHS, reinterpret_cast<const char*>(RHS))
|
||||
#else // ESP8266
|
||||
#define STRCASECMP(LHS, RHS) strcasecmp(LHS, RHS)
|
||||
#endif // ESP8266
|
||||
|
@ -152,9 +153,12 @@ stdAc::state_t IRac::getStatePrev(void) { return _prev; }
|
|||
/// @return true if the protocol is supported by this class, otherwise false.
|
||||
bool IRac::isProtocolSupported(const decode_type_t protocol) {
|
||||
switch (protocol) {
|
||||
#if SEND_AIRTON
|
||||
case decode_type_t::AIRTON:
|
||||
#endif // SEND_AIRTON
|
||||
#if SEND_AIRWELL
|
||||
case decode_type_t::AIRWELL:
|
||||
#endif
|
||||
#endif // SEND_AIRWELL
|
||||
#if SEND_AMCOR
|
||||
case decode_type_t::AMCOR:
|
||||
#endif
|
||||
|
@ -326,6 +330,44 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
|
|||
}
|
||||
}
|
||||
|
||||
#if SEND_AIRTON
|
||||
/// Send an Airton 56-bit A/C message with the supplied settings.
|
||||
/// @param[in, out] ac A Ptr to an IRAirtonAc object to use.
|
||||
/// @param[in] on The power setting.
|
||||
/// @param[in] mode The operation mode setting.
|
||||
/// @param[in] degrees The temperature setting in degrees.
|
||||
/// @param[in] fan The speed setting for the fan.
|
||||
/// @param[in] swingv The vertical swing setting.
|
||||
/// @param[in] turbo Run the device in turbo/powerful mode.
|
||||
/// @param[in] light Turn on the LED/Display mode.
|
||||
/// @param[in] econo Run the device in economical mode.
|
||||
/// @param[in] filter Turn on the (ion/pollen/health/etc) filter mode.
|
||||
/// @param[in] sleep Nr. of minutes for sleep mode.
|
||||
/// @note -1 is Off, >= 0 is on.
|
||||
void IRac::airton(IRAirtonAc *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
const float degrees, const stdAc::fanspeed_t fan,
|
||||
const stdAc::swingv_t swingv, const bool turbo,
|
||||
const bool light, const bool econo, const bool filter,
|
||||
const int16_t sleep) {
|
||||
ac->begin();
|
||||
ac->setPower(on);
|
||||
ac->setMode(ac->convertMode(mode));
|
||||
ac->setTemp(degrees);
|
||||
ac->setFan(ac->convertFan(fan));
|
||||
ac->setSwingV(swingv != stdAc::swingv_t::kOff);
|
||||
// No Quiet setting available.
|
||||
ac->setLight(light);
|
||||
ac->setHealth(filter);
|
||||
ac->setTurbo(turbo);
|
||||
ac->setEcono(econo);
|
||||
// No Clean setting available.
|
||||
// No Beep setting available.
|
||||
ac->setSleep(sleep >= 0); // Convert to a boolean.
|
||||
ac->send();
|
||||
}
|
||||
#endif // SEND_AIRTON
|
||||
|
||||
#if SEND_AIRWELL
|
||||
/// Send an Airwell A/C message with the supplied settings.
|
||||
/// @param[in, out] ac A Ptr to an IRAirwellAc object to use.
|
||||
|
@ -1530,6 +1572,7 @@ void IRac::mitsubishi(IRMitsubishiAC *ac,
|
|||
ac->setVane(ac->convertSwingV(swingv));
|
||||
ac->setWideVane(ac->convertSwingH(swingh));
|
||||
if (quiet) ac->setFan(kMitsubishiAcFanSilent);
|
||||
ac->setISave10C(false);
|
||||
// No Turbo setting available.
|
||||
// No Light setting available.
|
||||
// No Filter setting available.
|
||||
|
@ -2116,11 +2159,12 @@ void IRac::teco(IRTecoAc *ac,
|
|||
/// @param[in] swingv The vertical swing setting.
|
||||
/// @param[in] turbo Run the device in turbo/powerful mode.
|
||||
/// @param[in] econo Run the device in economical mode.
|
||||
/// @param[in] filter Turn on the (Pure/ion/pollen/etc) filter mode.
|
||||
void IRac::toshiba(IRToshibaAC *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
const float degrees, const stdAc::fanspeed_t fan,
|
||||
const stdAc::swingv_t swingv,
|
||||
const bool turbo, const bool econo) {
|
||||
const bool turbo, const bool econo, const bool filter) {
|
||||
ac->begin();
|
||||
ac->setMode(ac->convertMode(mode));
|
||||
ac->setTemp(degrees);
|
||||
|
@ -2133,7 +2177,7 @@ void IRac::toshiba(IRToshibaAC *ac,
|
|||
ac->setTurbo(turbo);
|
||||
ac->setEcono(econo);
|
||||
// No Light setting available.
|
||||
// No Filter setting available.
|
||||
ac->setFilter(filter);
|
||||
// No Clean setting available.
|
||||
// No Beep setting available.
|
||||
// No Sleep setting available.
|
||||
|
@ -2603,6 +2647,16 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
|
|||
#endif // (SEND_LG || SEND_SHARP_AC)
|
||||
// Per vendor settings & setup.
|
||||
switch (send.protocol) {
|
||||
#if SEND_AIRTON
|
||||
case AIRTON:
|
||||
{
|
||||
IRAirtonAc ac(_pin, _inverted, _modulation);
|
||||
airton(&ac, send.power, send.mode, degC, send.fanspeed,
|
||||
send.swingv, send.turbo, send.light, send.econo, send.filter,
|
||||
send.sleep);
|
||||
break;
|
||||
}
|
||||
#endif // SEND_AIRTON
|
||||
#if SEND_AIRWELL
|
||||
case AIRWELL:
|
||||
{
|
||||
|
@ -3062,7 +3116,7 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
|
|||
{
|
||||
IRToshibaAC ac(_pin, _inverted, _modulation);
|
||||
toshiba(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
|
||||
send.turbo, send.econo);
|
||||
send.turbo, send.econo, send.filter);
|
||||
break;
|
||||
}
|
||||
#endif // SEND_TOSHIBA_AC
|
||||
|
@ -3507,6 +3561,13 @@ namespace IRAcUtils {
|
|||
/// An empty string if we can't.
|
||||
String resultAcToString(const decode_results * const result) {
|
||||
switch (result->decode_type) {
|
||||
#if DECODE_AIRTON
|
||||
case decode_type_t::AIRTON: {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.setRaw(result->value); // AIRTON uses value instead of state.
|
||||
return ac.toString();
|
||||
}
|
||||
#endif // DECODE_AIRTON
|
||||
#if DECODE_AIRWELL
|
||||
case decode_type_t::AIRWELL: {
|
||||
IRAirwellAc ac(kGpioUnused);
|
||||
|
@ -3931,6 +3992,14 @@ namespace IRAcUtils {
|
|||
) {
|
||||
if (decode == NULL || result == NULL) return false; // Safety check.
|
||||
switch (decode->decode_type) {
|
||||
#if DECODE_AIRTON
|
||||
case decode_type_t::AIRTON: {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.setRaw(decode->value); // Uses value instead of state.
|
||||
*result = ac.toCommon();
|
||||
break;
|
||||
}
|
||||
#endif // DECODE_AIRTON
|
||||
#if DECODE_AIRWELL
|
||||
case decode_type_t::AIRWELL: {
|
||||
IRAirwellAc ac(kGpioUnused);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <Arduino.h>
|
||||
#endif
|
||||
#include "IRremoteESP8266.h"
|
||||
#include "ir_Airton.h"
|
||||
#include "ir_Airwell.h"
|
||||
#include "ir_Amcor.h"
|
||||
#include "ir_Argo.h"
|
||||
|
@ -109,6 +110,14 @@ class IRac {
|
|||
bool _inverted; ///< IR LED is lit when GPIO is LOW (true) or HIGH (false)?
|
||||
bool _modulation; ///< Is frequency modulation to be used?
|
||||
stdAc::state_t _prev; ///< The state we expect the device to currently be in.
|
||||
#if SEND_AIRTON
|
||||
void airton(IRAirtonAc *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
const float degrees, const stdAc::fanspeed_t fan,
|
||||
const stdAc::swingv_t swingv, const bool turbo,
|
||||
const bool light, const bool econo, const bool filter,
|
||||
const int16_t sleep = -1);
|
||||
#endif // SEND_AIRTON
|
||||
#if SEND_AIRWELL
|
||||
void airwell(IRAirwellAc *ac,
|
||||
const bool on, const stdAc::opmode_t mode, const float degrees,
|
||||
|
@ -457,7 +466,7 @@ void electra(IRElectraAc *ac,
|
|||
void toshiba(IRToshibaAC *ac,
|
||||
const bool on, const stdAc::opmode_t mode, const float degrees,
|
||||
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
|
||||
const bool turbo, const bool econo);
|
||||
const bool turbo, const bool econo, const bool filter);
|
||||
#endif // SEND_TOSHIBA_AC
|
||||
#if SEND_TROTEC
|
||||
void trotec(IRTrotecESP *ac,
|
||||
|
|
|
@ -13,7 +13,7 @@ extern "C" {
|
|||
}
|
||||
#endif // ESP8266
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
#endif // UNIT_TEST
|
||||
#include <algorithm>
|
||||
#ifdef UNIT_TEST
|
||||
#include <cassert>
|
||||
|
@ -56,6 +56,20 @@ static ETSTimer timer;
|
|||
} // namespace _IRrecv
|
||||
#endif // ESP8266
|
||||
#if defined(ESP32)
|
||||
// We need a horrible timer hack for ESP32 Arduino framework < v2.0.0
|
||||
#if !defined(_ESP32_IRRECV_TIMER_HACK)
|
||||
// Version check
|
||||
#if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
|
||||
// No need for the hack if we are running version >= 2.0.0
|
||||
#define _ESP32_IRRECV_TIMER_HACK false
|
||||
#else // Version check
|
||||
// If no ESP_ARDUINO_VERSION_MAJOR is defined, or less than 2, then we are
|
||||
// using an old ESP32 core, so we need the hack.
|
||||
#define _ESP32_IRRECV_TIMER_HACK true
|
||||
#endif // Version check
|
||||
#endif // !defined(_ESP32_IRRECV_TIMER_HACK)
|
||||
|
||||
#if _ESP32_IRRECV_TIMER_HACK
|
||||
// Required structs/types from:
|
||||
// https://github.com/espressif/arduino-esp32/blob/6b0114366baf986c155e8173ab7c22bc0c5fcedc/cores/esp32/esp32-hal-timer.c#L28-L58
|
||||
// These are needed to be able to directly manipulate the timer registers from
|
||||
|
@ -117,7 +131,7 @@ typedef struct hw_timer_s {
|
|||
uint8_t timer;
|
||||
portMUX_TYPE lock;
|
||||
} hw_timer_t;
|
||||
// End of Horrible Hack.
|
||||
#endif // _ESP32_IRRECV_TIMER_HACK / End of Horrible Hack.
|
||||
|
||||
namespace _IRrecv {
|
||||
static hw_timer_t * timer = NULL;
|
||||
|
@ -211,6 +225,7 @@ static void USE_IRAM_ATTR gpio_intr() {
|
|||
#if defined(ESP32)
|
||||
// Reset the timeout.
|
||||
//
|
||||
#if _ESP32_IRRECV_TIMER_HACK
|
||||
// The following three lines of code are the equiv of:
|
||||
// `timerWrite(timer, 0);`
|
||||
// We can't call that routine safely from inside an ISR as that procedure
|
||||
|
@ -226,6 +241,10 @@ static void USE_IRAM_ATTR gpio_intr() {
|
|||
// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1350
|
||||
// @see https://github.com/espressif/arduino-esp32/blob/6b0114366baf986c155e8173ab7c22bc0c5fcedc/cores/esp32/esp32-hal-timer.c#L176-L178
|
||||
timer->dev->config.alarm_en = 1;
|
||||
#else // _ESP32_IRRECV_TIMER_HACK
|
||||
timerWrite(timer, 0);
|
||||
timerAlarmEnable(timer);
|
||||
#endif // _ESP32_IRRECV_TIMER_HACK
|
||||
#endif // ESP32
|
||||
}
|
||||
#endif // UNIT_TEST
|
||||
|
@ -337,7 +356,9 @@ void IRrecv::enableIRIn(const bool pullup) {
|
|||
// Set the timer so it only fires once, and set it's trigger in uSeconds.
|
||||
timerAlarmWrite(timer, MS_TO_USEC(params.timeout), ONCE);
|
||||
// Note: Interrupt needs to be attached before it can be enabled or disabled.
|
||||
timerAttachInterrupt(timer, &read_timeout, true);
|
||||
// Note: EDGE (true) is not supported, use LEVEL (false). Ref: #1713
|
||||
// See: https://github.com/espressif/arduino-esp32/blob/caef4006af491130136b219c1205bdcf8f08bf2b/cores/esp32/esp32-hal-timer.c#L224-L227
|
||||
timerAttachInterrupt(timer, &read_timeout, false);
|
||||
#endif // ESP32
|
||||
|
||||
// Initialise state machine variables
|
||||
|
@ -695,9 +716,9 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
|
|||
if (decodeSharp(results, offset)) return true;
|
||||
#endif
|
||||
#if DECODE_COOLIX
|
||||
DPRINTLN("Attempting Coolix decode");
|
||||
DPRINTLN("Attempting Coolix 24-bit decode");
|
||||
if (decodeCOOLIX(results, offset)) return true;
|
||||
#endif
|
||||
#endif // DECODE_COOLIX
|
||||
#if DECODE_NIKAI
|
||||
DPRINTLN("Attempting Nikai decode");
|
||||
if (decodeNikai(results, offset)) return true;
|
||||
|
@ -1047,6 +1068,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
|
|||
DPRINTLN("Attempting Airton decode");
|
||||
if (decodeAirton(results, offset)) return true;
|
||||
#endif // DECODE_AIRTON
|
||||
#if DECODE_COOLIX48
|
||||
DPRINTLN("Attempting Coolix 48-bit decode");
|
||||
if (decodeCoolix48(results, offset)) return true;
|
||||
#endif // DECODE_COOLIX48
|
||||
// Typically new protocols are added above this line.
|
||||
}
|
||||
#if DECODE_HASH
|
||||
|
@ -1079,7 +1104,7 @@ uint32_t IRrecv::ticksLow(const uint32_t usecs, const uint8_t tolerance,
|
|||
// max() used to ensure the result can't drop below 0 before the cast.
|
||||
return ((uint32_t)std::max(
|
||||
(int32_t)(usecs * (1.0 - _validTolerance(tolerance) / 100.0) - delta),
|
||||
0));
|
||||
(int32_t)0));
|
||||
}
|
||||
|
||||
/// Calculate the upper bound of the nr. of ticks.
|
||||
|
@ -1162,7 +1187,8 @@ bool IRrecv::matchAtLeast(uint32_t measured, uint32_t desired,
|
|||
// We really should never get a value of 0, except as the last value
|
||||
// in the buffer. If that is the case, then assume infinity and return true.
|
||||
if (measured == 0) return true;
|
||||
return measured >= ticksLow(std::min(desired, MS_TO_USEC(params.timeout)),
|
||||
return measured >= ticksLow(std::min(desired,
|
||||
(uint32_t)MS_TO_USEC(params.timeout)),
|
||||
tolerance, delta);
|
||||
}
|
||||
|
||||
|
|
|
@ -419,7 +419,12 @@ class IRrecv {
|
|||
bool decodeCOOLIX(decode_results *results, uint16_t offset = kStartOffset,
|
||||
const uint16_t nbits = kCoolixBits,
|
||||
const bool strict = true);
|
||||
#endif
|
||||
#endif // DECODE_COOLIX
|
||||
#if DECODE_COOLIX48
|
||||
bool decodeCoolix48(decode_results *results, uint16_t offset = kStartOffset,
|
||||
const uint16_t nbits = kCoolix48Bits,
|
||||
const bool strict = true);
|
||||
#endif // DECODE_COOLIX48
|
||||
#if DECODE_DENON
|
||||
bool decodeDenon(decode_results *results, uint16_t offset = kStartOffset,
|
||||
const uint16_t nbits = kDenonBits,
|
||||
|
|
|
@ -52,8 +52,29 @@
|
|||
#include <string>
|
||||
#endif // UNIT_TEST
|
||||
|
||||
// Library Version
|
||||
#define _IRREMOTEESP8266_VERSION_ "2.8.0"
|
||||
// Library Version Information
|
||||
// Major version number (X.x.x)
|
||||
#define _IRREMOTEESP8266_VERSION_MAJOR 2
|
||||
// Minor version number (x.X.x)
|
||||
#define _IRREMOTEESP8266_VERSION_MINOR 8
|
||||
// Patch version number (x.x.X)
|
||||
#define _IRREMOTEESP8266_VERSION_PATCH 1
|
||||
// Macro to convert version info into an integer
|
||||
#define _IRREMOTEESP8266_VERSION_VAL(major, minor, patch) \
|
||||
((major << 16) | (minor << 8) | (patch))
|
||||
// Macro to convert literal into a string
|
||||
#define MKSTR(x) #x
|
||||
// Integer version
|
||||
#define _IRREMOTEESP8266_VERSION _IRREMOTEESP8266_VERSION_VAL(\
|
||||
_IRREMOTEESP8266_VERSION_MAJOR, \
|
||||
_IRREMOTEESP8266_VERSION_MINOR, \
|
||||
_IRREMOTEESP8266_VERSION_PATCH)
|
||||
// String version
|
||||
#define _IRREMOTEESP8266_VERSION_STR MKSTR(_IRREMOTEESP8266_VERSION_MAJOR) "." \
|
||||
MKSTR(_IRREMOTEESP8266_VERSION_MINOR) "." \
|
||||
MKSTR(_IRREMOTEESP8266_VERSION_PATCH)
|
||||
// String version (DEPRECATED)
|
||||
#define _IRREMOTEESP8266_VERSION_ _IRREMOTEESP8266_VERSION_STR
|
||||
|
||||
// Set the language & locale for the library. See the `locale` dir for options.
|
||||
#ifndef _IR_LOCALE_
|
||||
|
@ -314,6 +335,13 @@
|
|||
#define SEND_COOLIX _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_COOLIX
|
||||
|
||||
#ifndef DECODE_COOLIX48
|
||||
#define DECODE_COOLIX48 _IR_ENABLE_DEFAULT_
|
||||
#endif // DECODE_COOLIX48
|
||||
#ifndef SEND_COOLIX48
|
||||
#define SEND_COOLIX48 _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_COOLIX48
|
||||
|
||||
#ifndef DECODE_GLOBALCACHE
|
||||
#define DECODE_GLOBALCACHE false // Not applicable.
|
||||
#endif // DECODE_GLOBALCACHE
|
||||
|
@ -975,8 +1003,9 @@ enum decode_type_t {
|
|||
ARRIS,
|
||||
RHOSS,
|
||||
AIRTON,
|
||||
COOLIX48, // 110
|
||||
// Add new entries before this one, and update it to point to the last entry.
|
||||
kLastDecodeType = AIRTON,
|
||||
kLastDecodeType = COOLIX48,
|
||||
};
|
||||
|
||||
// Message lengths & required repeat values
|
||||
|
@ -998,6 +1027,7 @@ const uint16_t kArgoBits = kArgoStateLength * 8;
|
|||
const uint16_t kArgoDefaultRepeat = kNoRepeat;
|
||||
const uint16_t kArrisBits = 32;
|
||||
const uint16_t kCoolixBits = 24;
|
||||
const uint16_t kCoolix48Bits = kCoolixBits * 2;
|
||||
const uint16_t kCoolixDefaultRepeat = kSingleRepeat;
|
||||
const uint16_t kCarrierAcBits = 32;
|
||||
const uint16_t kCarrierAcMinRepeat = kNoRepeat;
|
||||
|
|
|
@ -560,6 +560,7 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) {
|
|||
case AIWA_RC_T501:
|
||||
case AMCOR:
|
||||
case COOLIX:
|
||||
case COOLIX48:
|
||||
case ELITESCREENS:
|
||||
case GICABLE:
|
||||
case INAX:
|
||||
|
@ -661,6 +662,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
|
|||
return kDoshishaBits; // 40
|
||||
case SANYO_LC7461:
|
||||
return kSanyoLC7461Bits; // 42
|
||||
case COOLIX48:
|
||||
case GOODWEATHER:
|
||||
case KELON:
|
||||
case MIDEA:
|
||||
|
@ -829,7 +831,12 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
|
|||
case COOLIX:
|
||||
sendCOOLIX(data, nbits, min_repeat);
|
||||
break;
|
||||
#endif
|
||||
#endif // SEND_COOLIX
|
||||
#if SEND_COOLIX48
|
||||
case COOLIX48:
|
||||
sendCoolix48(data, nbits, min_repeat);
|
||||
break;
|
||||
#endif // SEND_COOLIX48
|
||||
#if SEND_DAIKIN64
|
||||
case DAIKIN64:
|
||||
sendDaikin64(data, nbits, min_repeat);
|
||||
|
|
|
@ -42,78 +42,78 @@ const uint32_t kDefaultMessageGap = 100000;
|
|||
|
||||
/// Enumerators and Structures for the Common A/C API.
|
||||
namespace stdAc {
|
||||
/// Common A/C settings for A/C operating modes.
|
||||
enum class opmode_t {
|
||||
kOff = -1,
|
||||
kAuto = 0,
|
||||
kCool = 1,
|
||||
kHeat = 2,
|
||||
kDry = 3,
|
||||
kFan = 4,
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastOpmodeEnum = kFan,
|
||||
};
|
||||
/// Common A/C settings for A/C operating modes.
|
||||
enum class opmode_t {
|
||||
kOff = -1,
|
||||
kAuto = 0,
|
||||
kCool = 1,
|
||||
kHeat = 2,
|
||||
kDry = 3,
|
||||
kFan = 4,
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastOpmodeEnum = kFan,
|
||||
};
|
||||
|
||||
/// Common A/C settings for Fan Speeds.
|
||||
enum class fanspeed_t {
|
||||
kAuto = 0,
|
||||
kMin = 1,
|
||||
kLow = 2,
|
||||
kMedium = 3,
|
||||
kHigh = 4,
|
||||
kMax = 5,
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastFanspeedEnum = kMax,
|
||||
};
|
||||
/// Common A/C settings for Fan Speeds.
|
||||
enum class fanspeed_t {
|
||||
kAuto = 0,
|
||||
kMin = 1,
|
||||
kLow = 2,
|
||||
kMedium = 3,
|
||||
kHigh = 4,
|
||||
kMax = 5,
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastFanspeedEnum = kMax,
|
||||
};
|
||||
|
||||
/// Common A/C settings for Vertical Swing.
|
||||
enum class swingv_t {
|
||||
kOff = -1,
|
||||
kAuto = 0,
|
||||
kHighest = 1,
|
||||
kHigh = 2,
|
||||
kMiddle = 3,
|
||||
kLow = 4,
|
||||
kLowest = 5,
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastSwingvEnum = kLowest,
|
||||
};
|
||||
/// Common A/C settings for Vertical Swing.
|
||||
enum class swingv_t {
|
||||
kOff = -1,
|
||||
kAuto = 0,
|
||||
kHighest = 1,
|
||||
kHigh = 2,
|
||||
kMiddle = 3,
|
||||
kLow = 4,
|
||||
kLowest = 5,
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastSwingvEnum = kLowest,
|
||||
};
|
||||
|
||||
/// Common A/C settings for Horizontal Swing.
|
||||
enum class swingh_t {
|
||||
kOff = -1,
|
||||
kAuto = 0, // a.k.a. On.
|
||||
kLeftMax = 1,
|
||||
kLeft = 2,
|
||||
kMiddle = 3,
|
||||
kRight = 4,
|
||||
kRightMax = 5,
|
||||
kWide = 6, // a.k.a. left & right at the same time.
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastSwinghEnum = kWide,
|
||||
};
|
||||
/// Common A/C settings for Horizontal Swing.
|
||||
enum class swingh_t {
|
||||
kOff = -1,
|
||||
kAuto = 0, // a.k.a. On.
|
||||
kLeftMax = 1,
|
||||
kLeft = 2,
|
||||
kMiddle = 3,
|
||||
kRight = 4,
|
||||
kRightMax = 5,
|
||||
kWide = 6, // a.k.a. left & right at the same time.
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastSwinghEnum = kWide,
|
||||
};
|
||||
|
||||
/// Structure to hold a common A/C state.
|
||||
typedef struct {
|
||||
decode_type_t protocol;
|
||||
int16_t model;
|
||||
bool power;
|
||||
stdAc::opmode_t mode;
|
||||
float degrees;
|
||||
bool celsius;
|
||||
stdAc::fanspeed_t fanspeed;
|
||||
stdAc::swingv_t swingv;
|
||||
stdAc::swingh_t swingh;
|
||||
bool quiet;
|
||||
bool turbo;
|
||||
bool econo;
|
||||
bool light;
|
||||
bool filter;
|
||||
bool clean;
|
||||
bool beep;
|
||||
int16_t sleep;
|
||||
int16_t clock;
|
||||
} state_t;
|
||||
/// Structure to hold a common A/C state.
|
||||
struct state_t {
|
||||
decode_type_t protocol;
|
||||
int16_t model;
|
||||
bool power;
|
||||
stdAc::opmode_t mode;
|
||||
float degrees;
|
||||
bool celsius;
|
||||
stdAc::fanspeed_t fanspeed;
|
||||
stdAc::swingv_t swingv;
|
||||
stdAc::swingh_t swingh;
|
||||
bool quiet;
|
||||
bool turbo;
|
||||
bool econo;
|
||||
bool light;
|
||||
bool filter;
|
||||
bool clean;
|
||||
bool beep;
|
||||
int16_t sleep;
|
||||
int16_t clock;
|
||||
};
|
||||
}; // namespace stdAc
|
||||
|
||||
/// Fujitsu A/C model numbers
|
||||
|
@ -381,9 +381,13 @@ class IRsend {
|
|||
uint16_t repeat = kNoRepeat);
|
||||
#endif
|
||||
#if SEND_COOLIX
|
||||
void sendCOOLIX(uint64_t data, uint16_t nbits = kCoolixBits,
|
||||
uint16_t repeat = kCoolixDefaultRepeat);
|
||||
#endif
|
||||
void sendCOOLIX(const uint64_t data, const uint16_t nbits = kCoolixBits,
|
||||
const uint16_t repeat = kCoolixDefaultRepeat);
|
||||
#endif // SEND_COOLIX
|
||||
#if SEND_COOLIX48
|
||||
void sendCoolix48(const uint64_t data, const uint16_t nbits = kCoolix48Bits,
|
||||
const uint16_t repeat = kCoolixDefaultRepeat);
|
||||
#endif // SEND_COOLIX48
|
||||
#if SEND_WHYNTER
|
||||
void sendWhynter(const uint64_t data, const uint16_t nbits = kWhynterBits,
|
||||
const uint16_t repeat = kNoRepeat);
|
||||
|
|
|
@ -81,6 +81,14 @@ IRTEXT_CONST_STRING(kHoldStr, D_STR_HOLD); ///< "Hold"
|
|||
IRTEXT_CONST_STRING(kButtonStr, D_STR_BUTTON); ///< "Button"
|
||||
IRTEXT_CONST_STRING(k8CHeatStr, D_STR_8C_HEAT); ///< "8C Heat"
|
||||
IRTEXT_CONST_STRING(k10CHeatStr, D_STR_10C_HEAT); ///< "10C Heat"
|
||||
IRTEXT_CONST_STRING(kISeeStr, D_STR_ISEE); ///< "ISee"
|
||||
IRTEXT_CONST_STRING(kAbsenseDetectStr, D_STR_ABSENSEDETECT);
|
||||
///< "AbsenseDetect"
|
||||
IRTEXT_CONST_STRING(kDirectIndirectModeStr, D_STR_DIRECTINDIRECTMODE);
|
||||
///< "Direct/Indirect mode"
|
||||
IRTEXT_CONST_STRING(kDirectStr, D_STR_DIRECT); ///< "Direct"
|
||||
IRTEXT_CONST_STRING(kIndirectStr, D_STR_INDIRECT); ///< "Indirect"
|
||||
|
||||
IRTEXT_CONST_STRING(kNightStr, D_STR_NIGHT); ///< "Night"
|
||||
IRTEXT_CONST_STRING(kSilentStr, D_STR_SILENT); ///< "Silent"
|
||||
IRTEXT_CONST_STRING(kFilterStr, D_STR_FILTER); ///< "Filter"
|
||||
|
@ -382,6 +390,7 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
|
|||
D_STR_ARRIS "\x0"
|
||||
D_STR_RHOSS "\x0"
|
||||
D_STR_AIRTON "\x0"
|
||||
D_STR_COOLIX48 "\x0"
|
||||
///< New protocol strings should be added just above this line.
|
||||
"\x0" ///< This string requires double null termination.
|
||||
};
|
||||
|
|
|
@ -231,5 +231,11 @@ extern IRTEXT_CONST_PTR(kYbofbStr);
|
|||
extern IRTEXT_CONST_PTR(kYesStr);
|
||||
extern IRTEXT_CONST_PTR(kZoneFollowStr);
|
||||
extern IRTEXT_CONST_PTR(kAllProtocolNamesStr);
|
||||
extern IRTEXT_CONST_PTR(kISeeStr);
|
||||
extern IRTEXT_CONST_PTR(kEcocoolStr);
|
||||
extern IRTEXT_CONST_PTR(kAbsenseDetectStr);
|
||||
extern IRTEXT_CONST_PTR(kDirectIndirectModeStr);
|
||||
extern IRTEXT_CONST_PTR(kDirectStr);
|
||||
extern IRTEXT_CONST_PTR(kIndirectStr);
|
||||
|
||||
#endif // IRTEXT_H_
|
||||
|
|
|
@ -1049,6 +1049,21 @@ namespace irutils {
|
|||
return nibbleonly ? sum & 0xF : sum;
|
||||
}
|
||||
|
||||
/// Sum all the bytes together in an integer.
|
||||
/// @param[in] data The integer to be summed.
|
||||
/// @param[in] count The number of bytes to sum. Starts from LSB. Max of 8.
|
||||
/// @param[in] init Starting value of the calculation to use. (Default is 0)
|
||||
/// @param[in] byteonly true, the result is 8 bits. false, it's 16 bits.
|
||||
/// @return The 8/16-bit calculated result of all the bytes and init value.
|
||||
uint16_t sumBytes(const uint64_t data, const uint8_t count,
|
||||
const uint8_t init, const bool byteonly) {
|
||||
uint16_t sum = init;
|
||||
uint64_t copy = data;
|
||||
const uint8_t nrofbytes = (count < 8) ? count : (64 / 8);
|
||||
for (uint8_t i = 0; i < nrofbytes; i++, copy >>= 8) sum += (copy & 0xFF);
|
||||
return byteonly ? sum & 0xFF : sum;
|
||||
}
|
||||
|
||||
/// Convert a byte of Binary Coded Decimal(BCD) into an Integer.
|
||||
/// @param[in] bcd The BCD value.
|
||||
/// @return A normal Integer value.
|
||||
|
|
|
@ -94,6 +94,8 @@ namespace irutils {
|
|||
const uint8_t init = 0);
|
||||
uint8_t sumNibbles(const uint64_t data, const uint8_t count = 16,
|
||||
const uint8_t init = 0, const bool nibbleonly = true);
|
||||
uint16_t sumBytes(const uint64_t data, const uint8_t count = 8,
|
||||
const uint8_t init = 0, const bool byteonly = true);
|
||||
uint8_t bcdToUint8(const uint8_t bcd);
|
||||
uint8_t uint8ToBcd(const uint8_t integer);
|
||||
bool getBit(const uint64_t data, const uint8_t position,
|
||||
|
|
|
@ -3,12 +3,11 @@
|
|||
/// @brief Support for Airton protocol
|
||||
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1670
|
||||
|
||||
// Supports:
|
||||
// Brand: Airton, Model: SMVH09B-2A2A3NH ref. 409730 A/C
|
||||
// Brand: Airton, Model: RD1A1 remote
|
||||
|
||||
#include "ir_Airton.h"
|
||||
#include <algorithm>
|
||||
#include "IRrecv.h"
|
||||
#include "IRsend.h"
|
||||
#include "IRtext.h"
|
||||
#include "IRutils.h"
|
||||
|
||||
const uint16_t kAirtonHdrMark = 6630;
|
||||
|
@ -18,6 +17,12 @@ const uint16_t kAirtonOneSpace = 1260;
|
|||
const uint16_t kAirtonZeroSpace = 430;
|
||||
const uint16_t kAirtonFreq = 38000; // Hz. (Just a guess)
|
||||
|
||||
using irutils::addBoolToString;
|
||||
using irutils::addModeToString;
|
||||
using irutils::addFanToString;
|
||||
using irutils::addTempToString;
|
||||
using irutils::sumBytes;
|
||||
|
||||
#if SEND_AIRTON
|
||||
// Function should be safe up to 64 bits.
|
||||
/// Send a Airton formatted message.
|
||||
|
@ -59,7 +64,8 @@ bool IRrecv::decodeAirton(decode_results *results, uint16_t offset,
|
|||
kAirtonBitMark, kAirtonZeroSpace,
|
||||
kAirtonBitMark, kDefaultMessageGap,
|
||||
true, kUseDefTol, kMarkExcess, false)) return false;
|
||||
|
||||
// Compliance
|
||||
if (strict && !IRAirtonAc::validChecksum(results->value)) return false;
|
||||
// Success
|
||||
results->decode_type = decode_type_t::AIRTON;
|
||||
results->bits = nbits;
|
||||
|
@ -68,3 +74,289 @@ bool IRrecv::decodeAirton(decode_results *results, uint16_t offset,
|
|||
return true;
|
||||
}
|
||||
#endif // DECODE_AIRTON
|
||||
|
||||
/// Class constructor
|
||||
/// @param[in] pin GPIO to be used when sending.
|
||||
/// @param[in] inverted Is the output signal to be inverted?
|
||||
/// @param[in] use_modulation Is frequency modulation to be used?
|
||||
IRAirtonAc::IRAirtonAc(const uint16_t pin, const bool inverted,
|
||||
const bool use_modulation)
|
||||
: _irsend(pin, inverted, use_modulation) { stateReset(); }
|
||||
|
||||
/// Set up hardware to be able to send a message.
|
||||
void IRAirtonAc::begin(void) { _irsend.begin(); }
|
||||
|
||||
#if SEND_AIRTON
|
||||
/// Send the current internal state as an IR message.
|
||||
/// @param[in] repeat Nr. of times the message will be repeated.
|
||||
void IRAirtonAc::send(const uint16_t repeat) {
|
||||
_irsend.sendAirton(getRaw(), kAirtonBits, repeat);
|
||||
}
|
||||
#endif // SEND_AIRTON
|
||||
|
||||
/// Calculate the checksum for the supplied state.
|
||||
/// @param[in] state The source state to generate the checksum from.
|
||||
/// @return The checksum value.
|
||||
uint8_t IRAirtonAc::calcChecksum(const uint64_t state) {
|
||||
return (uint8_t)(0x7F - sumBytes(state, 6)) ^ 0x2C;
|
||||
}
|
||||
|
||||
/// Verify the checksum is valid for a given state.
|
||||
/// @param[in] state The value to verify the checksum of.
|
||||
/// @return A boolean indicating if it's checksum is valid.
|
||||
bool IRAirtonAc::validChecksum(const uint64_t state) {
|
||||
AirtonProtocol p;
|
||||
p.raw = state;
|
||||
return p.Sum == IRAirtonAc::calcChecksum(state);
|
||||
}
|
||||
|
||||
/// Update the checksum value for the internal state.
|
||||
void IRAirtonAc::checksum(void) { _.Sum = IRAirtonAc::calcChecksum(_.raw); }
|
||||
|
||||
/// Reset the internals of the object to a known good state.
|
||||
void IRAirtonAc::stateReset(void) { setRaw(0x11D3); }
|
||||
|
||||
/// Get the raw state of the object, suitable to be sent with the appropriate
|
||||
/// IRsend object method.
|
||||
/// @return A copy to the internal state.
|
||||
uint64_t IRAirtonAc::getRaw(void) {
|
||||
checksum(); // Ensure correct bit array before returning
|
||||
return _.raw;
|
||||
}
|
||||
|
||||
/// Set the raw state of the object.
|
||||
/// @param[in] state The raw state from the native IR message.
|
||||
void IRAirtonAc::setRaw(const uint64_t state) { _.raw = state; }
|
||||
|
||||
|
||||
/// Set the internal state to have the power on.
|
||||
void IRAirtonAc::on(void) { setPower(true); }
|
||||
|
||||
/// Set the internal state to have the power off.
|
||||
void IRAirtonAc::off(void) { setPower(false); }
|
||||
|
||||
/// Set the internal state to have the desired power.
|
||||
/// @param[in] on The desired power state.
|
||||
void IRAirtonAc::setPower(const bool on) {
|
||||
_.Power = on;
|
||||
setMode(getMode()); // Re-do the mode incase we need to do something special.
|
||||
}
|
||||
|
||||
/// Get the power setting from the internal state.
|
||||
/// @return A boolean indicating the power setting.
|
||||
bool IRAirtonAc::getPower(void) const { return _.Power; }
|
||||
|
||||
/// Get the current operation mode setting.
|
||||
/// @return The current operation mode.
|
||||
uint8_t IRAirtonAc::getMode(void) const { return _.Mode; }
|
||||
|
||||
/// Set the desired operation mode.
|
||||
/// @param[in] mode The desired operation mode.
|
||||
void IRAirtonAc::setMode(const uint8_t mode) {
|
||||
// Changing the mode always removes the sleep setting.
|
||||
if (mode != _.Mode) setSleep(false);
|
||||
// Set the actual mode.
|
||||
_.Mode = (mode > kAirtonHeat) ? kAirtonAuto : mode;
|
||||
// Handle special settings for each mode.
|
||||
switch (_.Mode) {
|
||||
case kAirtonAuto:
|
||||
setTemp(25); // Auto has a fixed temp.
|
||||
_.NotAutoOn = !getPower();
|
||||
break;
|
||||
case kAirtonHeat:
|
||||
// When powered on and in Heat mode, set a special bit.
|
||||
_.HeatOn = getPower();
|
||||
// FALL-THRU
|
||||
default:
|
||||
_.NotAutoOn = true;
|
||||
}
|
||||
// Reset the economy setting if we need to.
|
||||
setEcono(getEcono());
|
||||
}
|
||||
|
||||
/// Convert a stdAc::opmode_t enum into its native mode.
|
||||
/// @param[in] mode The enum to be converted.
|
||||
/// @return The native equivalent of the enum.
|
||||
uint8_t IRAirtonAc::convertMode(const stdAc::opmode_t mode) {
|
||||
switch (mode) {
|
||||
case stdAc::opmode_t::kCool: return kAirtonCool;
|
||||
case stdAc::opmode_t::kHeat: return kAirtonHeat;
|
||||
case stdAc::opmode_t::kDry: return kAirtonDry;
|
||||
case stdAc::opmode_t::kFan: return kAirtonFan;
|
||||
default: return kAirtonAuto;
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a native mode into its stdAc equivalent.
|
||||
/// @param[in] mode The native setting to be converted.
|
||||
/// @return The stdAc equivalent of the native setting.
|
||||
stdAc::opmode_t IRAirtonAc::toCommonMode(const uint8_t mode) {
|
||||
switch (mode) {
|
||||
case kAirtonCool: return stdAc::opmode_t::kCool;
|
||||
case kAirtonHeat: return stdAc::opmode_t::kHeat;
|
||||
case kAirtonDry: return stdAc::opmode_t::kDry;
|
||||
case kAirtonFan: return stdAc::opmode_t::kFan;
|
||||
default: return stdAc::opmode_t::kAuto;
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the temperature.
|
||||
/// @param[in] degrees The temperature in degrees celsius.
|
||||
void IRAirtonAc::setTemp(const uint8_t degrees) {
|
||||
uint8_t temp = std::max(kAirtonMinTemp, degrees);
|
||||
temp = std::min(kAirtonMaxTemp, temp);
|
||||
if (_.Mode == kAirtonAuto) temp = kAirtonMaxTemp; // Auto has a fixed temp.
|
||||
_.Temp = temp - kAirtonMinTemp;
|
||||
}
|
||||
|
||||
/// Get the current temperature setting.
|
||||
/// @return Get current setting for temp. in degrees celsius.
|
||||
uint8_t IRAirtonAc::getTemp(void) const { return _.Temp + kAirtonMinTemp; }
|
||||
|
||||
|
||||
/// Set the speed of the fan.
|
||||
/// @param[in] speed The desired setting.
|
||||
void IRAirtonAc::setFan(const uint8_t speed) {
|
||||
_.Fan = (speed > kAirtonFanMax) ? kAirtonFanAuto : speed;
|
||||
}
|
||||
|
||||
/// Get the current fan speed setting.
|
||||
/// @return The current fan speed.
|
||||
uint8_t IRAirtonAc::getFan(void) const { return _.Fan; }
|
||||
|
||||
/// Convert a stdAc::fanspeed_t enum into it's native speed.
|
||||
/// @param[in] speed The enum to be converted.
|
||||
/// @return The native equivalent of the enum.
|
||||
uint8_t IRAirtonAc::convertFan(const stdAc::fanspeed_t speed) {
|
||||
switch (speed) {
|
||||
case stdAc::fanspeed_t::kMin: return kAirtonFanMin;
|
||||
case stdAc::fanspeed_t::kLow: return kAirtonFanLow;
|
||||
case stdAc::fanspeed_t::kMedium: return kAirtonFanMed;
|
||||
case stdAc::fanspeed_t::kHigh: return kAirtonFanHigh;
|
||||
case stdAc::fanspeed_t::kMax: return kAirtonFanMax;
|
||||
default: return kAirtonFanAuto;
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a native fan speed into its stdAc equivalent.
|
||||
/// @param[in] speed The native setting to be converted.
|
||||
/// @return The stdAc equivalent of the native setting.
|
||||
stdAc::fanspeed_t IRAirtonAc::toCommonFanSpeed(const uint8_t speed) {
|
||||
switch (speed) {
|
||||
case kAirtonFanMax: return stdAc::fanspeed_t::kMax;
|
||||
case kAirtonFanHigh: return stdAc::fanspeed_t::kHigh;
|
||||
case kAirtonFanMed: return stdAc::fanspeed_t::kMedium;
|
||||
case kAirtonFanLow: return stdAc::fanspeed_t::kLow;
|
||||
case kAirtonFanMin: return stdAc::fanspeed_t::kMin;
|
||||
default: return stdAc::fanspeed_t::kAuto;
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the Vertical Swing setting of the A/C.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
void IRAirtonAc::setSwingV(const bool on) { _.SwingV = on; }
|
||||
|
||||
/// Get the Vertical Swing setting of the A/C.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRAirtonAc::getSwingV(void) const { return _.SwingV; }
|
||||
|
||||
/// Set the Light/LED/Display setting of the A/C.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
void IRAirtonAc::setLight(const bool on) { _.Light = on; }
|
||||
|
||||
/// Get the Light/LED/Display setting of the A/C.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRAirtonAc::getLight(void) const { return _.Light; }
|
||||
|
||||
/// Set the Economy setting of the A/C.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
/// @note Only available in Cool mode.
|
||||
void IRAirtonAc::setEcono(const bool on) {
|
||||
_.Econo = on && (getMode() == kAirtonCool);
|
||||
}
|
||||
|
||||
/// Get the Economy setting of the A/C.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRAirtonAc::getEcono(void) const { return _.Econo; }
|
||||
|
||||
/// Set the Turbo setting of the A/C.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
void IRAirtonAc::setTurbo(const bool on) {
|
||||
_.Turbo = on;
|
||||
// Pressing the turbo button sets the fan to max as well.
|
||||
if (on) setFan(kAirtonFanMax);
|
||||
}
|
||||
|
||||
/// Get the Turbo setting of the A/C.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRAirtonAc::getTurbo(void) const { return _.Turbo; }
|
||||
|
||||
/// Set the Sleep setting of the A/C.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
/// @note Sleep not available in fan or auto mode.
|
||||
void IRAirtonAc::setSleep(const bool on) {
|
||||
switch (getMode()) {
|
||||
case kAirtonAuto:
|
||||
case kAirtonFan: _.Sleep = false; break;
|
||||
default: _.Sleep = on;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the Sleep setting of the A/C.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRAirtonAc::getSleep(void) const { return _.Sleep; }
|
||||
|
||||
/// Set the Health/Filter setting of the A/C.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
void IRAirtonAc::setHealth(const bool on) { _.Health = on; }
|
||||
|
||||
/// Get the Health/Filter setting of the A/C.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRAirtonAc::getHealth(void) const { return _.Health; }
|
||||
|
||||
/// Convert the current internal state into its stdAc::state_t equivalent.
|
||||
/// @return The stdAc equivalent of the native settings.
|
||||
stdAc::state_t IRAirtonAc::toCommon(void) const {
|
||||
stdAc::state_t result;
|
||||
result.protocol = decode_type_t::AIRTON;
|
||||
result.power = getPower();
|
||||
result.mode = toCommonMode(getMode());
|
||||
result.celsius = true;
|
||||
result.degrees = getTemp();
|
||||
result.fanspeed = toCommonFanSpeed(getFan());
|
||||
result.swingv = getSwingV() ? stdAc::swingv_t::kAuto : stdAc::swingv_t::kOff;
|
||||
result.econo = getEcono();
|
||||
result.turbo = getTurbo();
|
||||
result.filter = getHealth();
|
||||
result.light = getLight();
|
||||
result.sleep = getSleep() ? 0 : -1;
|
||||
// Not supported.
|
||||
result.model = -1;
|
||||
result.swingh = stdAc::swingh_t::kOff;
|
||||
result.quiet = false;
|
||||
result.clean = false;
|
||||
result.beep = false;
|
||||
result.clock = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Convert the current internal state into a human readable string.
|
||||
/// @return A human readable string.
|
||||
String IRAirtonAc::toString(void) const {
|
||||
String result = "";
|
||||
result.reserve(135); // Reserve some heap for the string to reduce fragging.
|
||||
result += addBoolToString(getPower(), kPowerStr, false);
|
||||
result += addModeToString(_.Mode, kAirtonAuto, kAirtonCool,
|
||||
kAirtonHeat, kAirtonDry, kAirtonFan);
|
||||
result += addFanToString(_.Fan, kAirtonFanHigh, kAirtonFanLow,
|
||||
kAirtonFanAuto, kAirtonFanMin, kAirtonFanMed,
|
||||
kAirtonFanMax);
|
||||
result += addTempToString(getTemp());
|
||||
result += addBoolToString(getSwingV(), kSwingVStr);
|
||||
result += addBoolToString(getEcono(), kEconoStr);
|
||||
result += addBoolToString(getTurbo(), kTurboStr);
|
||||
result += addBoolToString(getLight(), kLightStr);
|
||||
result += addBoolToString(getHealth(), kHealthStr);
|
||||
result += addBoolToString(getSleep(), kSleepStr);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
// Copyright 2021 David Conran (crankyoldgit)
|
||||
/// @file
|
||||
/// @brief Support for Airton protocol
|
||||
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1670
|
||||
|
||||
// Supports:
|
||||
// Brand: Airton, Model: SMVH09B-2A2A3NH ref. 409730 A/C
|
||||
// Brand: Airton, Model: RD1A1 remote
|
||||
|
||||
#ifndef IR_AIRTON_H_
|
||||
#define IR_AIRTON_H_
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#include <stdint.h>
|
||||
#ifndef UNIT_TEST
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
#include "IRremoteESP8266.h"
|
||||
#include "IRsend.h"
|
||||
#ifdef UNIT_TEST
|
||||
#include "IRsend_test.h"
|
||||
#endif
|
||||
|
||||
/// Native representation of a Airton 56 A/C message.
|
||||
/// @see https://docs.google.com/spreadsheets/d/1Kpq7WCkh85heLnTQGlwUfCR6eeu_vfBHvhii8wtP4LU/edit?usp=sharing
|
||||
union AirtonProtocol{
|
||||
uint64_t raw; ///< The state in code form.
|
||||
struct { // Common
|
||||
// Byte 1 & 0 (LSB)
|
||||
uint16_t Header :16; // Header. (0x11D3)
|
||||
// Byte 2
|
||||
uint8_t Mode :3; // Operating Mode
|
||||
uint8_t Power :1; // Power Control
|
||||
uint8_t Fan :3;
|
||||
uint8_t Turbo :1;
|
||||
// Byte 3
|
||||
uint8_t Temp :4; // Degrees Celsius (+16 offset)
|
||||
uint8_t :4; // Unknown / Unused.
|
||||
// Byte 4
|
||||
uint8_t SwingV :1;
|
||||
uint8_t :7; // Unknown / Unused.
|
||||
// Byte 5
|
||||
uint8_t Econo :1;
|
||||
uint8_t Sleep :1;
|
||||
uint8_t NotAutoOn :1;
|
||||
uint8_t :1; // Unknown / Unused.
|
||||
uint8_t HeatOn :1;
|
||||
uint8_t :1; // Unknown / Unused.
|
||||
uint8_t Health :1;
|
||||
uint8_t Light :1;
|
||||
// Byte 6
|
||||
uint8_t Sum :8; // Sepecial checksum value
|
||||
};
|
||||
};
|
||||
|
||||
// Constants
|
||||
const uint8_t kAirtonAuto = 0b000; // 0
|
||||
const uint8_t kAirtonCool = 0b001; // 1
|
||||
const uint8_t kAirtonDry = 0b010; // 2
|
||||
const uint8_t kAirtonFan = 0b011; // 3
|
||||
const uint8_t kAirtonHeat = 0b100; // 4
|
||||
|
||||
const uint8_t kAirtonFanAuto = 0b000; // 0
|
||||
const uint8_t kAirtonFanMin = 0b001; // 1
|
||||
const uint8_t kAirtonFanLow = 0b010; // 2
|
||||
const uint8_t kAirtonFanMed = 0b011; // 3
|
||||
const uint8_t kAirtonFanHigh = 0b100; // 4
|
||||
const uint8_t kAirtonFanMax = 0b101; // 5
|
||||
|
||||
const uint8_t kAirtonMinTemp = 16; // 16C
|
||||
const uint8_t kAirtonMaxTemp = 25; // 25C
|
||||
|
||||
|
||||
/// Class for handling detailed Airton 56-bit A/C messages.
|
||||
class IRAirtonAc {
|
||||
public:
|
||||
explicit IRAirtonAc(const uint16_t pin, const bool inverted = false,
|
||||
const bool use_modulation = true);
|
||||
void stateReset(void);
|
||||
#if SEND_AIRTON
|
||||
void send(const uint16_t repeat = kAirtonDefaultRepeat);
|
||||
/// Run the calibration to calculate uSec timing offsets for this platform.
|
||||
/// @return The uSec timing offset needed per modulation of the IR Led.
|
||||
/// @note This will produce a 65ms IR signal pulse at 38kHz.
|
||||
/// Only ever needs to be run once per object instantiation, if at all.
|
||||
int8_t calibrate(void) { return _irsend.calibrate(); }
|
||||
#endif // SEND_AIRTON
|
||||
void begin(void);
|
||||
void on(void);
|
||||
void off(void);
|
||||
void setPower(const bool on);
|
||||
bool getPower(void) const;
|
||||
void setTemp(const uint8_t degrees);
|
||||
uint8_t getTemp(void) const;
|
||||
void setFan(const uint8_t speed);
|
||||
uint8_t getFan(void) const;
|
||||
void setMode(const uint8_t mode);
|
||||
uint8_t getMode(void) const;
|
||||
uint64_t getRaw(void);
|
||||
void setRaw(const uint64_t data);
|
||||
void setLight(const bool on);
|
||||
bool getLight(void) const;
|
||||
void setEcono(const bool on);
|
||||
bool getEcono(void) const;
|
||||
void setTurbo(const bool on);
|
||||
bool getTurbo(void) const;
|
||||
void setHealth(const bool on);
|
||||
bool getHealth(void) const;
|
||||
void setSleep(const bool on);
|
||||
bool getSleep(void) const;
|
||||
void setSwingV(const bool on);
|
||||
bool getSwingV(void) const;
|
||||
static bool validChecksum(const uint64_t data);
|
||||
static uint8_t calcChecksum(const uint64_t data);
|
||||
static uint8_t convertMode(const stdAc::opmode_t mode);
|
||||
static uint8_t convertFan(const stdAc::fanspeed_t speed);
|
||||
static uint8_t convertSwingV(const stdAc::swingv_t position);
|
||||
static stdAc::opmode_t toCommonMode(const uint8_t mode);
|
||||
static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
|
||||
stdAc::state_t toCommon(void) const;
|
||||
String toString(void) const;
|
||||
#ifndef UNIT_TEST
|
||||
|
||||
private:
|
||||
IRsend _irsend; ///< Instance of the IR send class
|
||||
#else // UNIT_TEST
|
||||
/// @cond IGNORE
|
||||
IRsendTest _irsend; ///< Instance of the testing IR send class
|
||||
/// @endcond
|
||||
#endif // UNIT_TEST
|
||||
AirtonProtocol _;
|
||||
void checksum(void);
|
||||
};
|
||||
#endif // IR_AIRTON_H_
|
|
@ -21,17 +21,18 @@
|
|||
// pulse parameters in usec
|
||||
const uint16_t kCoolixTick = 276; // Approximately 10.5 cycles at 38kHz
|
||||
const uint16_t kCoolixBitMarkTicks = 2;
|
||||
const uint16_t kCoolixBitMark = kCoolixBitMarkTicks * kCoolixTick;
|
||||
const uint16_t kCoolixBitMark = kCoolixBitMarkTicks * kCoolixTick; // 552us
|
||||
const uint16_t kCoolixOneSpaceTicks = 6;
|
||||
const uint16_t kCoolixOneSpace = kCoolixOneSpaceTicks * kCoolixTick;
|
||||
const uint16_t kCoolixOneSpace = kCoolixOneSpaceTicks * kCoolixTick; // 1656us
|
||||
const uint16_t kCoolixZeroSpaceTicks = 2;
|
||||
const uint16_t kCoolixZeroSpace = kCoolixZeroSpaceTicks * kCoolixTick;
|
||||
const uint16_t kCoolixZeroSpace = kCoolixZeroSpaceTicks * kCoolixTick; // 552us
|
||||
const uint16_t kCoolixHdrMarkTicks = 17;
|
||||
const uint16_t kCoolixHdrMark = kCoolixHdrMarkTicks * kCoolixTick;
|
||||
const uint16_t kCoolixHdrMark = kCoolixHdrMarkTicks * kCoolixTick; // 4692us
|
||||
const uint16_t kCoolixHdrSpaceTicks = 16;
|
||||
const uint16_t kCoolixHdrSpace = kCoolixHdrSpaceTicks * kCoolixTick;
|
||||
const uint16_t kCoolixHdrSpace = kCoolixHdrSpaceTicks * kCoolixTick; // 4416us
|
||||
const uint16_t kCoolixMinGapTicks = kCoolixHdrMarkTicks + kCoolixZeroSpaceTicks;
|
||||
const uint16_t kCoolixMinGap = kCoolixMinGapTicks * kCoolixTick;
|
||||
const uint16_t kCoolixMinGap = kCoolixMinGapTicks * kCoolixTick; // 5244us
|
||||
const uint8_t kCoolix48ExtraTolerance = 5; // Percent
|
||||
|
||||
using irutils::addBoolToString;
|
||||
using irutils::addIntToString;
|
||||
|
@ -40,7 +41,7 @@ using irutils::addModeToString;
|
|||
using irutils::addTempToString;
|
||||
|
||||
#if SEND_COOLIX
|
||||
/// Send a Coolix message
|
||||
/// Send a Coolix 24-bit message
|
||||
/// Status: STABLE / Confirmed Working.
|
||||
/// @param[in] data The message to be sent.
|
||||
/// @param[in] nbits The number of bits of message to be sent.
|
||||
|
@ -620,7 +621,7 @@ String IRCoolixAC::toString(void) const {
|
|||
}
|
||||
|
||||
#if DECODE_COOLIX
|
||||
/// Decode the supplied Coolix A/C message.
|
||||
/// Decode the supplied Coolix 24-bit A/C message.
|
||||
/// Status: STABLE / Known Working.
|
||||
/// @param[in,out] results Ptr to the data to decode & where to store the decode
|
||||
/// result.
|
||||
|
@ -699,3 +700,58 @@ bool IRrecv::decodeCOOLIX(decode_results *results, uint16_t offset,
|
|||
return true;
|
||||
}
|
||||
#endif // DECODE_COOLIX
|
||||
|
||||
#if SEND_COOLIX48
|
||||
/// Send a Coolix 48-bit message.
|
||||
/// Status: ALPHA / Untested.
|
||||
/// @param[in] data The message to be sent.
|
||||
/// @param[in] nbits The number of bits of message to be sent.
|
||||
/// @param[in] repeat The number of times the command is to be repeated.
|
||||
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1694
|
||||
/// @note This is effectively the same as `sendCOOLIX()` except requiring the
|
||||
/// bit flipping be done prior to the call.
|
||||
void IRsend::sendCoolix48(const uint64_t data, const uint16_t nbits,
|
||||
const uint16_t repeat) {
|
||||
// Header + Data + Footer
|
||||
sendGeneric(kCoolixHdrMark, kCoolixHdrSpace,
|
||||
kCoolixBitMark, kCoolixOneSpace,
|
||||
kCoolixBitMark, kCoolixZeroSpace,
|
||||
kCoolixBitMark, kCoolixMinGap,
|
||||
data, nbits, 38000, true, repeat, 33);
|
||||
}
|
||||
#endif // SEND_COOLIX48
|
||||
|
||||
#if DECODE_COOLIX
|
||||
/// Decode the supplied Coolix 48-bit A/C message.
|
||||
/// Status: BETA / Probably Working.
|
||||
/// @param[in,out] results Ptr to the data to decode & where to store the decode
|
||||
/// result.
|
||||
/// @param[in] offset The starting index to use when attempting to decode the
|
||||
/// raw data. Typically/Defaults to kStartOffset.
|
||||
/// @param[in] nbits The number of data bits to expect.
|
||||
/// @param[in] strict Flag indicating if we should perform strict matching.
|
||||
/// @return A boolean. True if it can decode it, false if it can't.
|
||||
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1694
|
||||
bool IRrecv::decodeCoolix48(decode_results *results, uint16_t offset,
|
||||
const uint16_t nbits, const bool strict) {
|
||||
if (strict && nbits != kCoolix48Bits)
|
||||
return false; // Not strictly a COOLIX48 message.
|
||||
|
||||
// Header + Data + Footer
|
||||
if (!matchGeneric(results->rawbuf + offset, &(results->value),
|
||||
results->rawlen - offset, nbits,
|
||||
kCoolixHdrMark, kCoolixHdrSpace,
|
||||
kCoolixBitMark, kCoolixOneSpace,
|
||||
kCoolixBitMark, kCoolixZeroSpace,
|
||||
kCoolixBitMark, kCoolixMinGap,
|
||||
true, _tolerance + kCoolix48ExtraTolerance, 0, true))
|
||||
return false;
|
||||
|
||||
// Success
|
||||
results->decode_type = COOLIX48;
|
||||
results->bits = nbits;
|
||||
results->address = 0;
|
||||
results->command = 0;
|
||||
return true;
|
||||
}
|
||||
#endif // DECODE_COOLIX48
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
/// @note Kudos:
|
||||
/// Hamper: For the breakdown and mapping of the bit values.
|
||||
/// fraschizzato: For additional ZoneFollow & SwingVStep analysis.
|
||||
/// @note Timers seem to use the `COOLIX48` protocol.
|
||||
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1694
|
||||
|
||||
// Supports:
|
||||
// Brand: Beko, Model: RG57K7(B)/BGEF Remote
|
||||
|
@ -21,6 +23,8 @@
|
|||
// Brand: Toshiba, Model: RAS-M13YKV-E A/C
|
||||
// Brand: Toshiba, Model: RAS-4M27YAV-E A/C
|
||||
// Brand: Toshiba, Model: WH-E1YE remote
|
||||
// Brand: Bosch, Model: RG36B4/BGE remote
|
||||
// Brand: Bosch, Model: B1ZAI2441W/B1ZAO2441W A/C
|
||||
|
||||
#ifndef IR_COOLIX_H_
|
||||
#define IR_COOLIX_H_
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
// Brand: Fujitsu, Model: ASU12RLF A/C (ARREB1E)
|
||||
// Brand: Fujitsu, Model: AR-REW4E remote (ARREW4E)
|
||||
// Brand: Fujitsu, Model: ASYG09KETA-B A/C (ARREW4E)
|
||||
// Brand: Fujitsu, Model: AR-REB4E remote (ARREB1E)
|
||||
// Brand: Fujitsu, Model: ASTG09K A/C (ARREW4E)
|
||||
// Brand: Fujitsu, Model: ASTG18K A/C (ARREW4E)
|
||||
// Brand: Fujitsu, Model: AR-REW1E remote (ARREW4E)
|
||||
|
||||
#ifndef IR_FUJITSU_H_
|
||||
#define IR_FUJITSU_H_
|
||||
|
|
|
@ -399,6 +399,8 @@ void IRMitsubishiAC::setTemp(const float degrees) {
|
|||
// Do we have a half degree celsius?
|
||||
_.HalfDegree = nrHalfDegrees & 1;
|
||||
_.Temp = static_cast<uint8_t>(nrHalfDegrees / 2 - kMitsubishiAcMinTemp);
|
||||
// If temp is modified, iSave10C cannot be ON (because temp is then > 10C)
|
||||
setISave10C(false);
|
||||
}
|
||||
|
||||
/// Get the current temperature setting.
|
||||
|
@ -452,8 +454,104 @@ void IRMitsubishiAC::setMode(const uint8_t mode) {
|
|||
return;
|
||||
}
|
||||
_.Mode = mode;
|
||||
// iSave10C can only be on in Heat mode.
|
||||
if (mode != kMitsubishiAcHeat) {
|
||||
setISave10C(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the iSave10C (i-SAVE) mode of the A/C.
|
||||
/// @param[in] state true, the setting is on. false, the setting is off.
|
||||
/// @note Normal minimum temp is 16C; i-SAVE mode works as gate to enable AC
|
||||
/// to use 10C as setting. However, when Remote control shows 10C, it still
|
||||
/// emits 16C on the "Temp" bits, and instead it uses other bits to indicate
|
||||
/// a target temp of 10C.
|
||||
/// Slightly strange, but I guess it's to keep compatibility to systems
|
||||
/// without i-SAVE.
|
||||
/// i-SAVE only has this 10C functionality when the AC is already in Heat mode.
|
||||
/// In all other modes, minimum temp is 16C.
|
||||
/// I have found no other difference between normal Heat mode and i-SAVE
|
||||
/// other than the ability to go to 10C.
|
||||
/// In this implementation, i-SAVE mode is ONLY used to enable the AC
|
||||
/// temperature setting to 10C. Therefore "Temp" is set to 16 disregarding
|
||||
/// what the remote shows, and mode is set to Heat.
|
||||
void IRMitsubishiAC::setISave10C(const bool state) {
|
||||
if (state) setMode(kMitsubishiAcHeat);
|
||||
if (state) setTemp(kMitsubishiAcMinTemp);
|
||||
_.iSave10C = state;
|
||||
}
|
||||
|
||||
/// Get the iSave10C (i-SAVE) mode of the A/C.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRMitsubishiAC::getISave10C(void) const {
|
||||
return _.iSave10C;
|
||||
}
|
||||
|
||||
/// Set the requested iSee mode.
|
||||
/// @param[in] state requested iSee mode.
|
||||
void IRMitsubishiAC::setISee(const bool state) {
|
||||
_.ISee = state;
|
||||
}
|
||||
|
||||
/// Get the iSee mode of the A/C.
|
||||
/// @return The iSee mode setting.
|
||||
bool IRMitsubishiAC::getISee(void) const {
|
||||
return _.ISee;
|
||||
}
|
||||
|
||||
/// Set the requested Ecocool mode.
|
||||
/// @param[in] state requested Ecocool mode.
|
||||
void IRMitsubishiAC::setEcocool(const bool state) {
|
||||
_.Ecocool = state;
|
||||
}
|
||||
|
||||
/// Get the Ecocool mode of the A/C.
|
||||
/// @return The Ecocool mode setting.
|
||||
bool IRMitsubishiAC::getEcocool(void) const {
|
||||
return _.Ecocool;
|
||||
}
|
||||
|
||||
/// Set the requested Absense Detect mode.
|
||||
/// @param[in] state requested Absense Detect mode.
|
||||
void IRMitsubishiAC::setAbsenseDetect(const bool state) {
|
||||
_.AbsenseDetect = state;
|
||||
}
|
||||
|
||||
/// Get the Absense Detect mode of the A/C.
|
||||
/// @return The Absense Detect mode setting.
|
||||
bool IRMitsubishiAC::getAbsenseDetect(void) const {
|
||||
return _.AbsenseDetect;
|
||||
}
|
||||
|
||||
/// Set the requested Direct/Indirect mode. Only works if I-See mode is ON.
|
||||
/// @param[in] mode requested Direct/Indirect mode.
|
||||
void IRMitsubishiAC::setDirectIndirect(const uint8_t mode) {
|
||||
if (_.ISee) {
|
||||
_.DirectIndirect = std::min(mode, kMitsubishiAcDirect); // bounds check
|
||||
} else {
|
||||
_.DirectIndirect = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the Direct/Indirect mode of the A/C.
|
||||
/// @return The native mode setting.
|
||||
uint8_t IRMitsubishiAC::getDirectIndirect(void) const {
|
||||
return _.DirectIndirect;
|
||||
}
|
||||
|
||||
/// Set the requested Natural Flow mode.
|
||||
/// @param[in] state requested Natural Flow mode.
|
||||
void IRMitsubishiAC::setNaturalFlow(const bool state) {
|
||||
_.NaturalFlow = state;
|
||||
}
|
||||
|
||||
/// Get the Natural Flow mode of the A/C.
|
||||
/// @return The Natural Flow mode setting.
|
||||
bool IRMitsubishiAC::getNaturalFlow(void) const {
|
||||
return _.NaturalFlow;
|
||||
}
|
||||
|
||||
|
||||
/// Set the requested vane (Vertical Swing) operation mode of the a/c unit.
|
||||
/// @note On some models, this represents the Right vertical vane.
|
||||
/// @param[in] position The position/mode to set the vane to.
|
||||
|
@ -463,12 +561,6 @@ void IRMitsubishiAC::setVane(const uint8_t position) {
|
|||
_.Vane = pos;
|
||||
}
|
||||
|
||||
/// Set the requested wide-vane (Horizontal Swing) operation mode of the a/c.
|
||||
/// @param[in] position The position/mode to set the wide vane to.
|
||||
void IRMitsubishiAC::setWideVane(const uint8_t position) {
|
||||
_.WideVane = std::min(position, kMitsubishiAcWideVaneAuto);
|
||||
}
|
||||
|
||||
/// Get the Vane (Vertical Swing) mode of the A/C.
|
||||
/// @note On some models, this represents the Right vertical vane.
|
||||
/// @return The native position/mode setting.
|
||||
|
@ -476,12 +568,6 @@ uint8_t IRMitsubishiAC::getVane(void) const {
|
|||
return _.Vane;
|
||||
}
|
||||
|
||||
/// Get the Wide Vane (Horizontal Swing) mode of the A/C.
|
||||
/// @return The native position/mode setting.
|
||||
uint8_t IRMitsubishiAC::getWideVane(void) const {
|
||||
return _.WideVane;
|
||||
}
|
||||
|
||||
/// Set the requested Left Vane (Vertical Swing) operation mode of the a/c unit.
|
||||
/// @param[in] position The position/mode to set the vane to.
|
||||
void IRMitsubishiAC::setVaneLeft(const uint8_t position) {
|
||||
|
@ -492,6 +578,18 @@ void IRMitsubishiAC::setVaneLeft(const uint8_t position) {
|
|||
/// @return The native position/mode setting.
|
||||
uint8_t IRMitsubishiAC::getVaneLeft(void) const { return _.VaneLeft; }
|
||||
|
||||
/// Set the requested wide-vane (Horizontal Swing) operation mode of the a/c.
|
||||
/// @param[in] position The position/mode to set the wide vane to.
|
||||
void IRMitsubishiAC::setWideVane(const uint8_t position) {
|
||||
_.WideVane = std::min(position, kMitsubishiAcWideVaneAuto);
|
||||
}
|
||||
|
||||
/// Get the Wide Vane (Horizontal Swing) mode of the A/C.
|
||||
/// @return The native position/mode setting.
|
||||
uint8_t IRMitsubishiAC::getWideVane(void) const {
|
||||
return _.WideVane;
|
||||
}
|
||||
|
||||
/// Get the clock time of the A/C unit.
|
||||
/// @return Nr. of 10 minute increments past midnight.
|
||||
/// @note 1 = 1/6 hour (10 minutes). e.g. 4pm = 48.
|
||||
|
@ -777,6 +875,12 @@ String IRMitsubishiAC::toString(void) const {
|
|||
result += ')';
|
||||
}
|
||||
result += addBoolToString(_.WeeklyTimer, kWeeklyTimerStr);
|
||||
result += addBoolToString(_.iSave10C, k10CHeatStr);
|
||||
result += addBoolToString(_.ISee, kISeeStr);
|
||||
result += addBoolToString(_.Ecocool, kEconoStr);
|
||||
result += addBoolToString(_.AbsenseDetect, kAbsenseDetectStr);
|
||||
result += addIntToString(_.DirectIndirect, kDirectIndirectModeStr);
|
||||
result += addBoolToString(_.NaturalFlow, kFreshStr);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
// Brand: Mitsubishi Electric, Model: MSZ-SF25VE3 A/C (MITSUBISHI_AC)
|
||||
// Brand: Mitsubishi Electric, Model: SG15D remote (MITSUBISHI_AC)
|
||||
// Brand: Mitsubishi Electric, Model: MSZ-ZW4017S A/C (MITSUBISHI_AC)
|
||||
// Brand: Mitsubishi Electric, Model: MSZ-FHnnVE A/C (MITSUBISHI_AC)
|
||||
|
||||
#ifndef IR_MITSUBISHI_H_
|
||||
#define IR_MITSUBISHI_H_
|
||||
|
@ -62,7 +63,8 @@ union Mitsubishi144Protocol{
|
|||
// Byte 6
|
||||
uint8_t :3;
|
||||
uint8_t Mode :3;
|
||||
uint8_t :2;
|
||||
uint8_t ISee : 1;
|
||||
uint8_t :1;
|
||||
// Byte 7
|
||||
uint8_t Temp :4;
|
||||
uint8_t HalfDegree :1;
|
||||
|
@ -72,7 +74,7 @@ union Mitsubishi144Protocol{
|
|||
uint8_t WideVane:4; // SwingH
|
||||
// Byte 9
|
||||
uint8_t Fan :3;
|
||||
uint8_t Vane :3; // SwingV
|
||||
uint8_t Vane :3; // SwingV or VaneRight
|
||||
uint8_t VaneBit :1;
|
||||
uint8_t FanAuto :1;
|
||||
// Byte 10
|
||||
|
@ -86,13 +88,21 @@ union Mitsubishi144Protocol{
|
|||
uint8_t WeeklyTimer :1;
|
||||
uint8_t :4;
|
||||
// Byte 14
|
||||
uint8_t :8;
|
||||
uint8_t :5;
|
||||
uint8_t Ecocool :1;
|
||||
uint8_t :2;
|
||||
// Byte 15
|
||||
uint8_t :8;
|
||||
uint8_t DirectIndirect:2;
|
||||
uint8_t AbsenseDetect :1;
|
||||
uint8_t :2;
|
||||
uint8_t iSave10C :1; // i-SAVE:mode=Heat & iSave=on AND 10C on remote
|
||||
uint8_t :2;
|
||||
// Byte 16
|
||||
uint8_t :3;
|
||||
uint8_t VaneLeft :3; // SwingV(Left)
|
||||
uint8_t :2;
|
||||
uint8_t :1;
|
||||
uint8_t NaturalFlow :1;
|
||||
uint8_t :1;
|
||||
uint8_t VaneLeft :3; // SwingV(Left)
|
||||
uint8_t :2;
|
||||
// Byte 17
|
||||
uint8_t Sum :8;
|
||||
};
|
||||
|
@ -126,6 +136,9 @@ const uint8_t kMitsubishiAcWideVaneRight = 0b0100; // 4
|
|||
const uint8_t kMitsubishiAcWideVaneRightMax = 0b0101; // 5
|
||||
const uint8_t kMitsubishiAcWideVaneWide = 0b0110; // 6
|
||||
const uint8_t kMitsubishiAcWideVaneAuto = 0b1000; // 8
|
||||
const uint8_t kMitsubishiAcDirectOff = 0b00; // Vanes move when AC wants to.
|
||||
const uint8_t kMitsubishiAcIndirect = 0b01;
|
||||
const uint8_t kMitsubishiAcDirect = 0b11;
|
||||
const uint8_t kMitsubishiAcNoTimer = 0;
|
||||
const uint8_t kMitsubishiAcStartTimer = 5;
|
||||
const uint8_t kMitsubishiAcStopTimer = 3;
|
||||
|
@ -274,12 +287,24 @@ class IRMitsubishiAC {
|
|||
uint8_t getFan(void) const;
|
||||
void setMode(const uint8_t mode);
|
||||
uint8_t getMode(void) const;
|
||||
void setVane(const uint8_t position);
|
||||
void setWideVane(const uint8_t position);
|
||||
void setISave10C(const bool state);
|
||||
bool getISave10C(void) const;
|
||||
void setISee(const bool state);
|
||||
bool getISee(void) const;
|
||||
void setDirectIndirect(const uint8_t position);
|
||||
uint8_t getDirectIndirect(void) const;
|
||||
void setEcocool(const bool state);
|
||||
bool getEcocool(void) const;
|
||||
void setAbsenseDetect(const bool state);
|
||||
bool getAbsenseDetect(void) const;
|
||||
void setNaturalFlow(const bool state);
|
||||
bool getNaturalFlow(void) const;
|
||||
void setVane(const uint8_t position); // controls RIGHT vane on some models
|
||||
uint8_t getVane(void) const;
|
||||
uint8_t getWideVane(void) const;
|
||||
void setVaneLeft(const uint8_t position);
|
||||
uint8_t getVaneLeft(void) const;
|
||||
void setWideVane(const uint8_t position);
|
||||
uint8_t getWideVane(void) const;
|
||||
uint8_t* getRaw(void);
|
||||
void setRaw(const uint8_t* data);
|
||||
uint8_t getClock(void) const;
|
||||
|
|
|
@ -120,7 +120,7 @@ uint32_t IRsend::encodeSony(const uint16_t nbits, const uint16_t command,
|
|||
/// bits long.
|
||||
bool IRrecv::decodeSony(decode_results *results, uint16_t offset,
|
||||
const uint16_t nbits, const bool strict) {
|
||||
if (results->rawlen <= 2 * nbits + kHeader - 1 + offset)
|
||||
if (results->rawlen < 2 * nbits + kHeader - 1 + offset)
|
||||
return false; // Message is smaller than we expected.
|
||||
|
||||
// Compliance
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
// Brand: TCL, Model: TAC-09CHSD/XA31I A/C (TAC09CHSD)
|
||||
// Brand: Teknopoint, Model: Allegro SSA-09H A/C (GZ055BE1)
|
||||
// Brand: Teknopoint, Model: GZ-055B-E1 remote (GZ055BE1)
|
||||
// Brand: Daewoo, Model: DSB-F0934ELH-V A/C
|
||||
// Brand: Daewoo, Model: GYKQ-52E remote
|
||||
|
||||
#ifndef IR_TCL_H_
|
||||
#define IR_TCL_H_
|
||||
|
|
|
@ -216,9 +216,7 @@ void IRToshibaAC::setTemp(const uint8_t degrees) {
|
|||
|
||||
/// Get the current temperature setting.
|
||||
/// @return The current setting for temp. in degrees celsius.
|
||||
uint8_t IRToshibaAC::getTemp(void) const {
|
||||
return _.Temp + kToshibaAcMinTemp;
|
||||
}
|
||||
uint8_t IRToshibaAC::getTemp(void) const { return _.Temp + kToshibaAcMinTemp; }
|
||||
|
||||
/// Set the speed of the fan.
|
||||
/// @param[in] speed The desired setting (0 is Auto, 1-5 is the speed, 5 is Max)
|
||||
|
@ -339,6 +337,19 @@ void IRToshibaAC::setEcono(const bool on) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the filter (Pure/Ion Filter) setting of the A/C.
|
||||
/// @return true, if the current setting is on. Otherwise, false.
|
||||
bool IRToshibaAC::getFilter(void) const {
|
||||
return (getStateLength() >= kToshibaACStateLength) ? _.Filter : false;
|
||||
}
|
||||
|
||||
/// Set the filter (Pure/Ion Filter) setting of the A/C.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
void IRToshibaAC::setFilter(const bool on) {
|
||||
_.Filter = on;
|
||||
if (on) setStateLength(std::min(kToshibaACStateLength, getStateLength()));
|
||||
}
|
||||
|
||||
/// Convert a stdAc::opmode_t enum into its native mode.
|
||||
/// @param[in] mode The enum to be converted.
|
||||
/// @return The native equivalent of the enum.
|
||||
|
@ -421,6 +432,7 @@ stdAc::state_t IRToshibaAC::toCommon(const stdAc::state_t *prev) const {
|
|||
result.fanspeed = toCommonFanSpeed(getFan());
|
||||
result.turbo = getTurbo();
|
||||
result.econo = getEcono();
|
||||
result.filter = getFilter();
|
||||
}
|
||||
switch (getSwing()) {
|
||||
case kToshibaAcSwingOn:
|
||||
|
@ -436,7 +448,6 @@ stdAc::state_t IRToshibaAC::toCommon(const stdAc::state_t *prev) const {
|
|||
}
|
||||
// Not supported.
|
||||
result.light = false;
|
||||
result.filter = false;
|
||||
result.swingh = stdAc::swingh_t::kOff;
|
||||
result.quiet = false;
|
||||
result.clean = false;
|
||||
|
@ -450,7 +461,7 @@ stdAc::state_t IRToshibaAC::toCommon(const stdAc::state_t *prev) const {
|
|||
/// @return A human readable string.
|
||||
String IRToshibaAC::toString(void) const {
|
||||
String result = "";
|
||||
result.reserve(80);
|
||||
result.reserve(95);
|
||||
result += addTempToString(getTemp(), true, false);
|
||||
switch (getStateLength()) {
|
||||
case kToshibaACStateLengthShort:
|
||||
|
@ -477,6 +488,7 @@ String IRToshibaAC::toString(void) const {
|
|||
kToshibaAcFanMed);
|
||||
result += addBoolToString(getTurbo(), kTurboStr);
|
||||
result += addBoolToString(getEcono(), kEconoStr);
|
||||
result += addBoolToString(getFilter(), kFilterStr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
/// @see https://docs.google.com/spreadsheets/d/1yidE2fvaO9kpCHfKafIdH31q4uaskYR1OwwrkyOxbp0/edit?usp=drivesdk
|
||||
/// @see https://www.toshiba-carrier.co.jp/global/about/index.htm
|
||||
/// @see http://www.toshiba-carrier.co.th/AboutUs/Pages/CompanyProfile.aspx
|
||||
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1692
|
||||
|
||||
// Supports:
|
||||
// Brand: Toshiba, Model: RAS-B13N3KV2
|
||||
|
@ -18,6 +19,8 @@
|
|||
// Brand: Toshiba, Model: WC-L03SE
|
||||
// Brand: Toshiba, Model: WH-UB03NJ remote
|
||||
// Brand: Toshiba, Model: RAS-2558V A/C
|
||||
// Brand: Toshiba, Model: WH-TA01JE remote
|
||||
// Brand: Toshiba, Model: RAS-25SKVP2-ND A/C
|
||||
// Brand: Carrier, Model: 42NQV060M2 / 38NYV060M2 A/C
|
||||
// Brand: Carrier, Model: 42NQV050M2 / 38NYV050M2 A/C
|
||||
// Brand: Carrier, Model: 42NQV035M2 / 38NYV035M2 A/C
|
||||
|
@ -50,28 +53,31 @@ union ToshibaProtocol{
|
|||
///< 1 (56 bit message)
|
||||
///< 3 (72 bit message)
|
||||
///< 4 (80 bit message)
|
||||
uint8_t Length :8;
|
||||
uint8_t Length :8;
|
||||
// Byte[3] - The bit-inverted value of the "length" byte.
|
||||
uint8_t :8;
|
||||
uint8_t :8;
|
||||
// Byte[4]
|
||||
uint8_t :3;
|
||||
uint8_t LongMsg :1;
|
||||
uint8_t :1;
|
||||
uint8_t ShortMsg:1;
|
||||
uint8_t :2;
|
||||
uint8_t :3;
|
||||
uint8_t LongMsg :1;
|
||||
uint8_t :1;
|
||||
uint8_t ShortMsg :1;
|
||||
uint8_t :2;
|
||||
// Byte[5]
|
||||
uint8_t Swing :3;
|
||||
uint8_t :1;
|
||||
uint8_t Temp :4;
|
||||
uint8_t Swing :3;
|
||||
uint8_t :1;
|
||||
uint8_t Temp :4;
|
||||
// Byte[6]
|
||||
uint8_t Mode :3;
|
||||
uint8_t :2;
|
||||
uint8_t Fan :3;
|
||||
uint8_t Mode :3;
|
||||
uint8_t :2;
|
||||
uint8_t Fan :3;
|
||||
// Byte[7]
|
||||
uint8_t :8;
|
||||
uint8_t :4;
|
||||
uint8_t Filter :1;
|
||||
uint8_t :3;
|
||||
|
||||
// Byte[8]
|
||||
// (Checksum for 72 bit messages, Eco/Turbo for long 80 bit messages)
|
||||
uint8_t EcoTurbo :8;
|
||||
uint8_t EcoTurbo :8;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -144,6 +150,8 @@ class IRToshibaAC {
|
|||
bool getTurbo(void) const;
|
||||
void setEcono(const bool on);
|
||||
bool getEcono(void) const;
|
||||
void setFilter(const bool on);
|
||||
bool getFilter(void) const;
|
||||
void setMode(const uint8_t mode);
|
||||
uint8_t getMode(const bool raw = false) const;
|
||||
void setRaw(const uint8_t newState[],
|
||||
|
|
|
@ -120,6 +120,9 @@
|
|||
#ifndef D_STR_IFEEL
|
||||
#define D_STR_IFEEL "IFeel"
|
||||
#endif // D_STR_IFEEL
|
||||
#ifndef D_STR_ISEE
|
||||
#define D_STR_ISEE "ISee"
|
||||
#endif // D_STR_ISEE
|
||||
#ifndef D_STR_HUMID
|
||||
#define D_STR_HUMID "Humid"
|
||||
#endif // D_STR_HUMID
|
||||
|
@ -207,6 +210,19 @@
|
|||
#ifndef D_STR_SENSOR
|
||||
#define D_STR_SENSOR "Sensor"
|
||||
#endif // D_STR_SENSOR
|
||||
#ifndef D_STR_ABSENSEDETECT
|
||||
#define D_STR_ABSENSEDETECT "Absense detect"
|
||||
#endif // D_STR_ABSENSEDETECT
|
||||
#ifndef D_STR_DIRECT
|
||||
#define D_STR_DIRECT "Direct"
|
||||
#endif // D_STR_DIRECT
|
||||
#ifndef D_STR_INDIRECT
|
||||
#define D_STR_INDIRECT "Indirect"
|
||||
#endif // D_STR_INDIRECT
|
||||
#ifndef D_STR_DIRECTINDIRECTMODE
|
||||
#define D_STR_DIRECTINDIRECTMODE D_STR_DIRECT " / " \
|
||||
D_STR_INDIRECT " " D_STR_MODE
|
||||
#endif // D_STR_DIRECTINDIRECTMODE
|
||||
#ifndef D_STR_DISPLAY
|
||||
#define D_STR_DISPLAY "Display"
|
||||
#endif // D_STR_DISPLAY
|
||||
|
@ -702,6 +718,9 @@
|
|||
#ifndef D_STR_COOLIX
|
||||
#define D_STR_COOLIX "COOLIX"
|
||||
#endif // D_STR_COOLIX
|
||||
#ifndef D_STR_COOLIX48
|
||||
#define D_STR_COOLIX48 D_STR_COOLIX "48"
|
||||
#endif // D_STR_COOLIX48
|
||||
#ifndef D_STR_CORONA_AC
|
||||
#define D_STR_CORONA_AC "CORONA_AC"
|
||||
#endif // D_STR_CORONA_AC
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright 2019-2021 David Conran
|
||||
|
||||
#include <string>
|
||||
#include "ir_Airton.h"
|
||||
#include "ir_Airwell.h"
|
||||
#include "ir_Amcor.h"
|
||||
#include "ir_Argo.h"
|
||||
|
@ -44,6 +45,36 @@
|
|||
|
||||
// Tests for IRac class.
|
||||
|
||||
TEST(TestIRac, Airton) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
IRac irac(kGpioUnused);
|
||||
IRrecv capture(kGpioUnused);
|
||||
const char expected[] =
|
||||
"Power: On, Mode: 1 (Cool), Fan: 5 (Maximum), Temp: 18C, "
|
||||
"Swing(V): On, Econo: On, Turbo: On, Light: On, Health: On, Sleep: On";
|
||||
|
||||
ac.begin();
|
||||
irac.airton(&ac,
|
||||
true, // Power
|
||||
stdAc::opmode_t::kCool, // Mode
|
||||
18, // Celsius
|
||||
stdAc::fanspeed_t::kMax, // Fan speed
|
||||
stdAc::swingv_t::kAuto, // Vertical Swing
|
||||
true, // Turbo
|
||||
true, // Light/Display/LED
|
||||
true, // Econo (Eco)
|
||||
true, // Filter (Health)
|
||||
9 * 60 + 12); // Sleep (09:12)
|
||||
ASSERT_EQ(expected, ac.toString());
|
||||
ac._irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
|
||||
ASSERT_EQ(AIRTON, ac._irsend.capture.decode_type);
|
||||
ASSERT_EQ(kAirtonBits, ac._irsend.capture.bits);
|
||||
ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
|
||||
stdAc::state_t r, p;
|
||||
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p));
|
||||
}
|
||||
|
||||
TEST(TestIRac, Airwell) {
|
||||
IRAirwellAc ac(kGpioUnused);
|
||||
IRac irac(kGpioUnused);
|
||||
|
@ -1418,7 +1449,9 @@ TEST(TestIRac, Mitsubishi) {
|
|||
"Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 2 (Medium), "
|
||||
"Swing(V): 0 (Auto), Swing(H): 3 (Middle), "
|
||||
"Clock: 14:30, On Timer: 00:00, Off Timer: 00:00, Timer: -, "
|
||||
"Weekly Timer: Off";
|
||||
"Weekly Timer: Off"
|
||||
", 10C Heat: Off, ISee: Off, Econo: Off, Absense detect: Off, "
|
||||
"Direct / Indirect Mode: 0, Fresh: Off";
|
||||
|
||||
ac.begin();
|
||||
irac.mitsubishi(&ac,
|
||||
|
@ -1958,7 +1991,7 @@ TEST(TestIRac, Toshiba) {
|
|||
IRrecv capture(kGpioUnused);
|
||||
char expected[] =
|
||||
"Temp: 29C, Power: On, Mode: 2 (Dry), Fan: 2 (UNKNOWN), "
|
||||
"Turbo: Off, Econo: On";
|
||||
"Turbo: Off, Econo: On, Filter: Off";
|
||||
|
||||
ac.begin();
|
||||
irac.toshiba(&ac,
|
||||
|
@ -1968,7 +2001,8 @@ TEST(TestIRac, Toshiba) {
|
|||
stdAc::fanspeed_t::kLow, // Fan speed
|
||||
stdAc::swingv_t::kOff, // Vertical Swing
|
||||
false, // Turbo
|
||||
true); // Econo
|
||||
true, // Econo
|
||||
false); // Filter
|
||||
ASSERT_EQ(expected, ac.toString());
|
||||
ASSERT_EQ(kToshibaACStateLengthLong, ac.getStateLength());
|
||||
ac._irsend.makeDecodeResult();
|
||||
|
@ -2873,7 +2907,7 @@ TEST(TestIRac, Issue1250) {
|
|||
// Now send the state so we can actually decode/capture what we sent.
|
||||
char expected_on[] =
|
||||
"Temp: 19C, Power: On, Mode: 4 (Fan), Fan: 0 (Auto), "
|
||||
"Turbo: Off, Econo: Off";
|
||||
"Turbo: Off, Econo: Off, Filter: Off";
|
||||
ac._irsend.reset();
|
||||
irac.toshiba(&ac,
|
||||
irac.next.power, // Power
|
||||
|
@ -2882,7 +2916,8 @@ TEST(TestIRac, Issue1250) {
|
|||
irac.next.fanspeed, // Fan speed
|
||||
irac.next.swingv, // Vertical Swing
|
||||
irac.next.turbo, // Turbo
|
||||
irac.next.econo); // Econo
|
||||
irac.next.econo, // Econo
|
||||
irac.next.filter); // Filter
|
||||
ASSERT_EQ(expected_on, ac.toString());
|
||||
ASSERT_EQ(kToshibaACStateLength, ac.getStateLength());
|
||||
ac._irsend.makeDecodeResult();
|
||||
|
@ -2898,7 +2933,8 @@ TEST(TestIRac, Issue1250) {
|
|||
irac.sendAc();
|
||||
// Now send the state so we can actually decode/capture what we sent.
|
||||
char expected_off[] =
|
||||
"Temp: 19C, Power: Off, Fan: 0 (Auto), Turbo: Off, Econo: Off";
|
||||
"Temp: 19C, Power: Off, Fan: 0 (Auto), Turbo: Off, Econo: Off, "
|
||||
"Filter: Off";
|
||||
ac._irsend.reset();
|
||||
irac.toshiba(&ac,
|
||||
irac.next.power, // Power
|
||||
|
@ -2907,7 +2943,8 @@ TEST(TestIRac, Issue1250) {
|
|||
irac.next.fanspeed, // Fan speed
|
||||
irac.next.swingv, // Vertical Swing
|
||||
irac.next.turbo, // Turbo
|
||||
irac.next.econo); // Econo
|
||||
irac.next.econo, // Econo
|
||||
irac.next.filter); // Filter
|
||||
ASSERT_EQ(expected_off, ac.toString());
|
||||
ASSERT_EQ(kToshibaACStateLength, ac.getStateLength());
|
||||
ac._irsend.makeDecodeResult();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2021 crankyoldgit
|
||||
|
||||
#include "ir_Airton.h"
|
||||
#include "IRac.h"
|
||||
#include "IRrecv.h"
|
||||
#include "IRrecv_test.h"
|
||||
|
@ -34,6 +35,13 @@ TEST(TestDecodeAirton, RealExample) {
|
|||
EXPECT_EQ(0x5E1400090C11D3, irsend.capture.value);
|
||||
EXPECT_EQ(0x0, irsend.capture.address);
|
||||
EXPECT_EQ(0x0, irsend.capture.command);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 4 (Heat), Fan: 0 (Auto), Temp: 25C, "
|
||||
"Swing(V): Off, Econo: Off, Turbo: Off, Light: Off, "
|
||||
"Health: Off, Sleep: Off",
|
||||
IRAcUtils::resultAcToString(&irsend.capture));
|
||||
stdAc::state_t r, p;
|
||||
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
|
||||
}
|
||||
|
||||
TEST(TestDecodeAirton, SyntheticExample) {
|
||||
|
@ -56,7 +64,265 @@ TEST(TestUtils, Housekeeping) {
|
|||
ASSERT_EQ("AIRTON", typeToString(decode_type_t::AIRTON));
|
||||
ASSERT_EQ(decode_type_t::AIRTON, strToDecodeType("AIRTON"));
|
||||
ASSERT_FALSE(hasACState(decode_type_t::AIRTON));
|
||||
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::AIRTON));
|
||||
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::AIRTON));
|
||||
ASSERT_EQ(kAirtonBits, IRsend::defaultBits(decode_type_t::AIRTON));
|
||||
ASSERT_EQ(kAirtonDefaultRepeat, IRsend::minRepeats(decode_type_t::AIRTON));
|
||||
}
|
||||
|
||||
// Tests for IRAirtonAc class.
|
||||
|
||||
TEST(TestIRAirtonAcClass, Power) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
|
||||
ac.on();
|
||||
EXPECT_TRUE(ac.getPower());
|
||||
|
||||
ac.off();
|
||||
EXPECT_FALSE(ac.getPower());
|
||||
|
||||
ac.setPower(true);
|
||||
EXPECT_TRUE(ac.getPower());
|
||||
|
||||
ac.setPower(false);
|
||||
EXPECT_FALSE(ac.getPower());
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, Checksums) {
|
||||
ASSERT_TRUE(IRAirtonAc::validChecksum(0x5E1400090C11D3));
|
||||
ASSERT_EQ(0x5E, IRAirtonAc::calcChecksum(0x5E1400090C11D3));
|
||||
ASSERT_FALSE(IRAirtonAc::validChecksum(0x551400090C11D3));
|
||||
ASSERT_TRUE(IRAirtonAc::validChecksum(0x2F8801060911D3));
|
||||
ASSERT_TRUE(IRAirtonAc::validChecksum(0xDB8800021A11D3));
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, Temperature) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
ac.setMode(kAirtonCool); // Cool mode allows the entire temp range.
|
||||
ac.setTemp(0);
|
||||
EXPECT_EQ(kAirtonMinTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(255);
|
||||
EXPECT_EQ(kAirtonMaxTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(kAirtonMinTemp);
|
||||
EXPECT_EQ(kAirtonMinTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(kAirtonMaxTemp);
|
||||
EXPECT_EQ(kAirtonMaxTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(kAirtonMinTemp - 1);
|
||||
EXPECT_EQ(kAirtonMinTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(kAirtonMaxTemp + 1);
|
||||
EXPECT_EQ(kAirtonMaxTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(17);
|
||||
EXPECT_EQ(17, ac.getTemp());
|
||||
|
||||
ac.setTemp(21);
|
||||
EXPECT_EQ(21, ac.getTemp());
|
||||
|
||||
ac.setTemp(20);
|
||||
EXPECT_EQ(20, ac.getTemp());
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, OperatingMode) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
|
||||
ac.setMode(kAirtonCool);
|
||||
EXPECT_EQ(kAirtonCool, ac.getMode());
|
||||
ac.setMode(kAirtonDry);
|
||||
EXPECT_EQ(kAirtonDry, ac.getMode());
|
||||
ac.setMode(kAirtonFan);
|
||||
EXPECT_EQ(kAirtonFan, ac.getMode());
|
||||
EXPECT_NE(kAirtonMaxTemp, ac.getTemp());
|
||||
ac.setMode(kAirtonAuto);
|
||||
EXPECT_EQ(kAirtonAuto, ac.getMode());
|
||||
EXPECT_EQ(kAirtonMaxTemp, ac.getTemp());
|
||||
ac.setMode(kAirtonHeat);
|
||||
EXPECT_EQ(kAirtonHeat, ac.getMode());
|
||||
|
||||
ac.setMode(kAirtonHeat + 1);
|
||||
EXPECT_EQ(kAirtonAuto, ac.getMode());
|
||||
ac.setMode(255);
|
||||
EXPECT_EQ(kAirtonAuto, ac.getMode());
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, FanSpeed) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
ac.setMode(kAirtonCool); // All fan speeds available in this mode.
|
||||
|
||||
ac.setFan(0);
|
||||
EXPECT_EQ(kAirtonFanAuto, ac.getFan());
|
||||
|
||||
ac.setFan(255);
|
||||
EXPECT_EQ(kAirtonFanAuto, ac.getFan());
|
||||
|
||||
ac.setFan(kAirtonFanHigh);
|
||||
EXPECT_EQ(kAirtonFanHigh, ac.getFan());
|
||||
|
||||
ac.setFan(kAirtonFanLow);
|
||||
EXPECT_EQ(kAirtonFanLow, ac.getFan());
|
||||
|
||||
ac.setFan(kAirtonFanMax);
|
||||
EXPECT_EQ(kAirtonFanMax, ac.getFan());
|
||||
|
||||
ac.setFan(kAirtonFanMin);
|
||||
EXPECT_EQ(kAirtonFanMin, ac.getFan());
|
||||
|
||||
ac.setFan(kAirtonFanMed);
|
||||
EXPECT_EQ(kAirtonFanMed, ac.getFan());
|
||||
|
||||
ac.setFan(kAirtonFanMax + 1);
|
||||
EXPECT_EQ(kAirtonFanAuto, ac.getFan());
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, SwingV) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
|
||||
ac.setSwingV(false);
|
||||
EXPECT_FALSE(ac.getSwingV());
|
||||
ac.setSwingV(true);
|
||||
EXPECT_TRUE(ac.getSwingV());
|
||||
ac.setSwingV(false);
|
||||
EXPECT_FALSE(ac.getSwingV());
|
||||
|
||||
// Known swingv on state
|
||||
ac.setRaw(0xBC0401050111D3);
|
||||
EXPECT_TRUE(ac.getSwingV());
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, Light) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
|
||||
ac.setLight(false);
|
||||
EXPECT_FALSE(ac.getLight());
|
||||
ac.setLight(true);
|
||||
EXPECT_TRUE(ac.getLight());
|
||||
ac.setLight(false);
|
||||
EXPECT_FALSE(ac.getLight());
|
||||
|
||||
// Known light on state
|
||||
ac.setRaw(0x298801040911D3);
|
||||
EXPECT_TRUE(ac.getLight());
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, ConstructKnownExamples) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
ac.stateReset();
|
||||
ac.on();
|
||||
ac.setMode(kAirtonHeat);
|
||||
ac.setFan(kAirtonFanAuto);
|
||||
ac.setTemp(25);
|
||||
ac.setSwingV(false);
|
||||
ac.setLight(false);
|
||||
ac.setTurbo(false);
|
||||
ac.setSleep(false);
|
||||
ac.setEcono(false);
|
||||
ac.setHealth(false);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 4 (Heat), Fan: 0 (Auto), Temp: 25C, "
|
||||
"Swing(V): Off, Econo: Off, Turbo: Off, Light: Off, "
|
||||
"Health: Off, Sleep: Off",
|
||||
ac.toString());
|
||||
EXPECT_EQ(0x5E1400090C11D3, ac.getRaw());
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, Turbo) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
|
||||
ac.setTurbo(false);
|
||||
EXPECT_FALSE(ac.getTurbo());
|
||||
EXPECT_NE(kAirtonFanMax, ac.getFan());
|
||||
ac.setTurbo(true);
|
||||
EXPECT_TRUE(ac.getTurbo());
|
||||
EXPECT_EQ(kAirtonFanMax, ac.getFan());
|
||||
ac.setTurbo(false);
|
||||
EXPECT_FALSE(ac.getTurbo());
|
||||
|
||||
// Known Turbo on state
|
||||
ac.setRaw(0x92040000D911D3);
|
||||
EXPECT_TRUE(ac.getTurbo());
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, Sleep) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
|
||||
ac.setMode(kAirtonCool); // Sleep is available in Cool mode.
|
||||
ac.setSleep(false);
|
||||
EXPECT_FALSE(ac.getSleep());
|
||||
ac.setSleep(true);
|
||||
EXPECT_TRUE(ac.getSleep());
|
||||
ac.setSleep(false);
|
||||
EXPECT_FALSE(ac.getSleep());
|
||||
|
||||
ac.setSleep(true);
|
||||
// Sleep is available in Heat mode, but changing modes resets it.
|
||||
ac.setMode(kAirtonHeat);
|
||||
EXPECT_FALSE(ac.getSleep());
|
||||
ac.setSleep(true);
|
||||
EXPECT_TRUE(ac.getSleep());
|
||||
|
||||
ac.setMode(kAirtonAuto); // Sleep is NOT available in Auto mode.
|
||||
EXPECT_FALSE(ac.getSleep());
|
||||
ac.setSleep(true);
|
||||
EXPECT_FALSE(ac.getSleep());
|
||||
|
||||
ac.setMode(kAirtonFan); // Sleep is NOT available in Fan mode.
|
||||
EXPECT_FALSE(ac.getSleep());
|
||||
ac.setSleep(true);
|
||||
EXPECT_FALSE(ac.getSleep());
|
||||
|
||||
// Known Sleep on state
|
||||
ac.setRaw(0xA00600000911D3);
|
||||
EXPECT_TRUE(ac.getSleep());
|
||||
EXPECT_NE(kAirtonAuto, ac.getMode());
|
||||
EXPECT_NE(kAirtonFan, ac.getMode());
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, Health) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
|
||||
ac.setHealth(false);
|
||||
EXPECT_FALSE(ac.getHealth());
|
||||
ac.setHealth(true);
|
||||
EXPECT_TRUE(ac.getHealth());
|
||||
ac.setHealth(false);
|
||||
EXPECT_FALSE(ac.getHealth());
|
||||
|
||||
// Known Health on state
|
||||
ac.setRaw(0xE5C900000911D3);
|
||||
EXPECT_TRUE(ac.getHealth());
|
||||
}
|
||||
|
||||
TEST(TestIRAirtonAcClass, Econo) {
|
||||
IRAirtonAc ac(kGpioUnused);
|
||||
ac.begin();
|
||||
ac.setMode(kAirtonCool); // Econo is only available in Cool.
|
||||
ac.setEcono(false);
|
||||
EXPECT_FALSE(ac.getEcono());
|
||||
ac.setEcono(true);
|
||||
EXPECT_TRUE(ac.getEcono());
|
||||
ac.setEcono(false);
|
||||
EXPECT_FALSE(ac.getEcono());
|
||||
|
||||
ac.setEcono(true);
|
||||
ac.setMode(kAirtonHeat); // Econo is only available in Cool, not Heat!
|
||||
EXPECT_FALSE(ac.getEcono());
|
||||
ac.setEcono(true);
|
||||
EXPECT_FALSE(ac.getEcono());
|
||||
|
||||
// Known Econo on state
|
||||
ac.setRaw(0xE5C900000911D3);
|
||||
EXPECT_TRUE(ac.getEcono());
|
||||
}
|
||||
|
|
|
@ -6,6 +6,25 @@
|
|||
#include "IRsend_test.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
||||
TEST(TestUtils, Housekeeping) {
|
||||
// COOLIX
|
||||
ASSERT_EQ("COOLIX", typeToString(decode_type_t::COOLIX));
|
||||
ASSERT_EQ(decode_type_t::COOLIX, strToDecodeType("COOLIX"));
|
||||
ASSERT_FALSE(hasACState(decode_type_t::COOLIX));
|
||||
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::COOLIX));
|
||||
ASSERT_EQ(kCoolixBits, IRsend::defaultBits(decode_type_t::COOLIX));
|
||||
ASSERT_EQ(kSingleRepeat, IRsend::minRepeats(decode_type_t::COOLIX));
|
||||
|
||||
// COOLIX48
|
||||
ASSERT_EQ("COOLIX48", typeToString(decode_type_t::COOLIX48));
|
||||
ASSERT_EQ(decode_type_t::COOLIX48, strToDecodeType("COOLIX48"));
|
||||
ASSERT_FALSE(hasACState(decode_type_t::COOLIX48));
|
||||
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::COOLIX48));
|
||||
ASSERT_EQ(kCoolix48Bits, IRsend::defaultBits(decode_type_t::COOLIX48));
|
||||
ASSERT_EQ(kSingleRepeat, IRsend::minRepeats(decode_type_t::COOLIX48));
|
||||
}
|
||||
|
||||
// Tests for sendCOOLIX().
|
||||
|
||||
// Test sending typical data only.
|
||||
|
@ -941,3 +960,76 @@ TEST(TestCoolixACClass, VerifyZoneFollowFan) {
|
|||
"Zone Follow: On, Sensor Temp: 19C",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
TEST(TestDecodeCoolix48, RealExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1694#issue-1068786691
|
||||
// Off Timer: 1 hour
|
||||
const uint16_t rawData[199] = {
|
||||
4342, 4454, 486, 1724, 436, 658, 438, 1748, 464, 1718, 462, 634, 440, 656,
|
||||
462, 1696, 488, 634, 462, 634, 436, 1722, 516, 608, 462, 660, 436, 1694,
|
||||
488, 1720, 440, 630, 488, 1700, 488, 1704, 458, 660, 462, 1698, 490, 632,
|
||||
462, 634, 436, 684, 436, 1700, 464, 1748, 462, 634, 462, 1720, 436, 658,
|
||||
462, 1700, 488, 1692, 512, 1696, 438, 684, 410, 686, 434, 688, 408, 1696,
|
||||
488, 1694, 464, 682, 414, 1748, 436, 1722, 488, 632, 438, 686, 408, 662,
|
||||
462, 1696, 488, 1722, 462, 1696, 462, 1746, 436, 1798, 386, 1694, 490,
|
||||
1720, 516, 5234, 4370, 4446, 490, 1690, 492, 658, 434, 1726, 436, 1746,
|
||||
464, 604, 488, 658, 412, 1718, 490, 636, 460, 660, 438, 1698, 460, 662,
|
||||
458, 632, 436, 1718, 490, 1720, 488, 608, 436, 1754, 462, 1726, 438, 682,
|
||||
414, 1748, 464, 632, 460, 660, 410, 658, 438, 1748, 464, 1694, 464, 660,
|
||||
436, 1720, 488, 634, 460, 1726, 462, 1724, 462, 1692, 490, 606, 462, 714,
|
||||
384, 660, 460, 1722, 460, 1722, 490, 606, 464, 1718, 490, 1670, 486, 634,
|
||||
462, 662, 410, 660, 460, 1722, 464, 1718, 460, 1696, 464, 1720, 462, 1720,
|
||||
462, 1722, 486, 1700, 462}; // UNKNOWN 1F691B97
|
||||
|
||||
irsend.begin();
|
||||
irsend.reset();
|
||||
|
||||
irsend.sendRaw(rawData, 199, 38000);
|
||||
irsend.makeDecodeResult();
|
||||
ASSERT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(COOLIX48, irsend.capture.decode_type);
|
||||
EXPECT_EQ(kCoolix48Bits, irsend.capture.bits);
|
||||
EXPECT_EQ(0xB24DA35C6C7F, irsend.capture.value);
|
||||
EXPECT_EQ(0x0, irsend.capture.address);
|
||||
EXPECT_EQ(0x0, irsend.capture.command);
|
||||
}
|
||||
|
||||
TEST(TestDecodeCoolix48, SyntheticSelfDecode) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendCoolix48(0xB24DA35C6C7F);
|
||||
irsend.makeDecodeResult();
|
||||
|
||||
ASSERT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(COOLIX48, irsend.capture.decode_type);
|
||||
EXPECT_EQ(kCoolix48Bits, irsend.capture.bits);
|
||||
EXPECT_EQ(0xB24DA35C6C7F, irsend.capture.value);
|
||||
EXPECT_EQ(0x0, irsend.capture.address);
|
||||
EXPECT_EQ(0x0, irsend.capture.command);
|
||||
|
||||
EXPECT_EQ(
|
||||
"f38000d33"
|
||||
"m4692s4416" // Message.
|
||||
"m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552"
|
||||
"m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656"
|
||||
"m552s1656m552s552m552s1656m552s552m552s552m552s552m552s1656m552s1656"
|
||||
"m552s552m552s1656m552s552m552s1656m552s1656m552s1656m552s552m552s552"
|
||||
"m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s552m552s552"
|
||||
"m552s552m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656"
|
||||
"m552s5244"
|
||||
"m4692s4416" // Repeat
|
||||
"m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552"
|
||||
"m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656"
|
||||
"m552s1656m552s552m552s1656m552s552m552s552m552s552m552s1656m552s1656"
|
||||
"m552s552m552s1656m552s552m552s1656m552s1656m552s1656m552s552m552s552"
|
||||
"m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s552m552s552"
|
||||
"m552s552m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656"
|
||||
"m552s5244",
|
||||
irsend.outputStr());
|
||||
}
|
||||
|
|
|
@ -913,7 +913,9 @@ TEST(TestMitsubishiACClass, HumanReadable) {
|
|||
"Power: On, Mode: 1 (Heat), Temp: 22C, Fan: 6 (Quiet), "
|
||||
"Swing(V): 0 (Auto), Swing(H): 3 (Middle), "
|
||||
"Clock: 17:10, On Timer: 00:00, Off Timer: 00:00, Timer: -, "
|
||||
"Weekly Timer: Off",
|
||||
"Weekly Timer: Off"
|
||||
", 10C Heat: Off, ISee: Off, Econo: Off, Absense detect: Off, "
|
||||
"Direct / Indirect Mode: 0, Fresh: Off",
|
||||
ac.toString());
|
||||
ac.setTemp(21.5);
|
||||
ac.setWeeklyTimerEnabled(true);
|
||||
|
@ -921,7 +923,9 @@ TEST(TestMitsubishiACClass, HumanReadable) {
|
|||
"Power: On, Mode: 1 (Heat), Temp: 21.5C, Fan: 6 (Quiet), "
|
||||
"Swing(V): 0 (Auto), Swing(H): 3 (Middle), "
|
||||
"Clock: 17:10, On Timer: 00:00, Off Timer: 00:00, Timer: -, "
|
||||
"Weekly Timer: On",
|
||||
"Weekly Timer: On"
|
||||
", 10C Heat: Off, ISee: Off, Econo: Off, Absense detect: Off, "
|
||||
"Direct / Indirect Mode: 0, Fresh: Off",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
|
@ -1434,7 +1438,9 @@ TEST(TestDecodeMitsubishiAC, Issue891) {
|
|||
"Power: Off, Mode: 3 (Cool), Temp: 24C, Fan: 0 (Auto), "
|
||||
"Swing(V): 0 (Auto), Swing(H): 3 (Middle), "
|
||||
"Clock: 00:00, On Timer: 00:00, Off Timer: 00:00, Timer: -, "
|
||||
"Weekly Timer: Off",
|
||||
"Weekly Timer: Off"
|
||||
", 10C Heat: Off, ISee: Off, Econo: Off, Absense detect: Off, "
|
||||
"Direct / Indirect Mode: 0, Fresh: Off",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
|
|
|
@ -312,20 +312,21 @@ TEST(TestToshibaACClass, HumanReadableOutput) {
|
|||
|
||||
ac.setRaw(initial_state);
|
||||
EXPECT_EQ("Temp: 17C, Power: On, Mode: 0 (Auto), Fan: 0 (Auto), "
|
||||
"Turbo: Off, Econo: Off",
|
||||
"Turbo: Off, Econo: Off, Filter: Off",
|
||||
ac.toString());
|
||||
ac.setRaw(modified_state);
|
||||
EXPECT_EQ("Temp: 17C, Power: On, Mode: 1 (Cool), Fan: 5 (High), "
|
||||
"Turbo: Off, Econo: Off",
|
||||
"Turbo: Off, Econo: Off, Filter: Off",
|
||||
ac.toString());
|
||||
ac.setTemp(25);
|
||||
ac.setFan(3);
|
||||
ac.setMode(kToshibaAcDry);
|
||||
EXPECT_EQ("Temp: 25C, Power: On, Mode: 2 (Dry), Fan: 3 (Medium), "
|
||||
"Turbo: Off, Econo: Off",
|
||||
"Turbo: Off, Econo: Off, Filter: Off",
|
||||
ac.toString());
|
||||
ac.off();
|
||||
EXPECT_EQ("Temp: 25C, Power: Off, Fan: 3 (Medium), Turbo: Off, Econo: Off",
|
||||
EXPECT_EQ("Temp: 25C, Power: Off, Fan: 3 (Medium), Turbo: Off, Econo: Off, "
|
||||
"Filter: Off",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
|
@ -379,7 +380,7 @@ TEST(TestDecodeToshibaAC, SyntheticExample) {
|
|||
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
|
||||
EXPECT_EQ(
|
||||
"Temp: 17C, Power: On, Mode: 0 (Auto), Fan: 0 (Auto), Turbo: Off, "
|
||||
"Econo: Off",
|
||||
"Econo: Off, Filter: Off",
|
||||
IRAcUtils::resultAcToString(&irsend.capture));
|
||||
stdAc::state_t r, p;
|
||||
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
|
||||
|
@ -555,6 +556,7 @@ TEST(TestToshibaACClass, toCommon) {
|
|||
ac.setMode(kToshibaAcCool);
|
||||
ac.setTemp(20);
|
||||
ac.setFan(kToshibaAcFanMax);
|
||||
ac.setFilter(true);
|
||||
// Now test it.
|
||||
ASSERT_EQ(decode_type_t::TOSHIBA_AC, ac.toCommon().protocol);
|
||||
ASSERT_EQ(-1, ac.toCommon().model);
|
||||
|
@ -563,13 +565,13 @@ TEST(TestToshibaACClass, toCommon) {
|
|||
ASSERT_EQ(20, ac.toCommon().degrees);
|
||||
ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
|
||||
ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
|
||||
ASSERT_TRUE(ac.toCommon().filter);
|
||||
// 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().econo);
|
||||
ASSERT_FALSE(ac.toCommon().light);
|
||||
ASSERT_FALSE(ac.toCommon().filter);
|
||||
ASSERT_FALSE(ac.toCommon().clean);
|
||||
ASSERT_FALSE(ac.toCommon().beep);
|
||||
ASSERT_FALSE(ac.toCommon().quiet);
|
||||
|
@ -626,7 +628,7 @@ TEST(TestDecodeToshibaAC, RealLongExample) {
|
|||
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
|
||||
EXPECT_EQ(
|
||||
"Temp: 22C, Power: On, Mode: 0 (Auto), Fan: 0 (Auto), Turbo: On, "
|
||||
"Econo: Off",
|
||||
"Econo: Off, Filter: Off",
|
||||
IRAcUtils::resultAcToString(&irsend.capture));
|
||||
}
|
||||
|
||||
|
@ -731,7 +733,7 @@ TEST(TestToshibaACClass, ConstructLongState) {
|
|||
ac.setEcono(true);
|
||||
EXPECT_EQ(
|
||||
"Temp: 29C, Power: On, Mode: 2 (Dry), Fan: 2 (UNKNOWN), "
|
||||
"Turbo: Off, Econo: On",
|
||||
"Turbo: Off, Econo: On, Filter: Off",
|
||||
ac.toString());
|
||||
EXPECT_EQ(kToshibaACStateLengthLong, ac.getStateLength());
|
||||
const uint8_t expectedState[kToshibaACStateLengthLong] = {
|
||||
|
@ -781,7 +783,8 @@ TEST(TestDecodeToshibaAC, RealExample_WHUB03NJ) {
|
|||
EXPECT_EQ(kToshibaACBits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
|
||||
EXPECT_EQ(
|
||||
"Temp: 20C, Power: Off, Fan: 0 (Auto), Turbo: Off, Econo: Off",
|
||||
"Temp: 20C, Power: Off, Fan: 0 (Auto), Turbo: Off, Econo: Off, "
|
||||
"Filter: Off",
|
||||
IRAcUtils::resultAcToString(&irsend.capture));
|
||||
}
|
||||
|
||||
|
@ -828,3 +831,34 @@ TEST(TestToshibaACClass, SwingCodes) {
|
|||
"Temp: 17C, Swing(V): 4 (Toggle)",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
// For https://github.com/crankyoldgit/IRremoteESP8266/issues/1692
|
||||
TEST(TestToshibaACClass, Filter) {
|
||||
IRToshibaAC ac(kGpioUnused);
|
||||
ac.begin();
|
||||
EXPECT_FALSE(ac.getFilter());
|
||||
|
||||
ac.setFilter(true);
|
||||
EXPECT_TRUE(ac.getFilter());
|
||||
|
||||
|
||||
ac.setFilter(false);
|
||||
EXPECT_FALSE(ac.getFilter());
|
||||
|
||||
ac.setFilter(true);
|
||||
EXPECT_TRUE(ac.getFilter());
|
||||
|
||||
const uint8_t pure_off[kToshibaACStateLength] = {
|
||||
0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x40, 0x03, 0x00, 0x42};
|
||||
ac.setRaw(pure_off);
|
||||
EXPECT_FALSE(ac.getFilter());
|
||||
|
||||
const uint8_t pure_on[kToshibaACStateLength] = {
|
||||
0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x40, 0x03, 0x10, 0x52};
|
||||
ac.setRaw(pure_on);
|
||||
EXPECT_TRUE(ac.getFilter());
|
||||
|
||||
// Convert a known filter/pure on state to a known off filter/pure state.
|
||||
ac.setFilter(false);
|
||||
EXPECT_STATE_EQ(pure_off, ac.getRaw(), ac.getStateLength() * 8);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,9 @@ CPPFLAGS += -DUNIT_TEST -D_IR_LOCALE_=en-AU
|
|||
# Flags passed to the C++ compiler.
|
||||
CXXFLAGS += -g -Wall -Wextra -pthread -std=gnu++11
|
||||
|
||||
all : gc_decode mode2_decode
|
||||
objects = $(patsubst %.cpp,%,$(wildcard *.cpp))
|
||||
|
||||
all : $(objects)
|
||||
|
||||
run_tests : all
|
||||
failed=""; \
|
||||
|
@ -35,6 +37,10 @@ run_tests : all
|
|||
echo "RUNNING: $${py_unittest}"; \
|
||||
python3 ./$${py_unittest} || failed="$${failed} $${py_unittest}"; \
|
||||
done; \
|
||||
for shell_unittest in *_test.sh; do \
|
||||
echo "RUNNING: $${shell_unittest}"; \
|
||||
bash ./$${shell_unittest} || failed="$${failed} $${shell_unittest}"; \
|
||||
done; \
|
||||
if [ -n "$${failed}" ]; then \
|
||||
echo "FAIL: :-( :-( Unit test(s)$${failed} failed! :-( :-("; exit 1; \
|
||||
else \
|
||||
|
@ -46,7 +52,7 @@ run-% : all
|
|||
python3 ./$*.py;
|
||||
|
||||
clean :
|
||||
rm -f *.o *.pyc gc_decode mode2_decode
|
||||
rm -f *.o *.pyc $(objects)
|
||||
|
||||
|
||||
# Keep all intermediate files.
|
||||
|
@ -80,7 +86,7 @@ IRrecv.o : $(USER_DIR)/IRrecv.cpp $(USER_DIR)/IRrecv.h $(USER_DIR)/IRremoteESP82
|
|||
|
||||
# new specific targets goes above this line
|
||||
|
||||
%_decode : $(COMMON_OBJ) %_decode.o
|
||||
$(objects) : %: $(COMMON_OBJ) %.o
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
|
||||
|
||||
ir_%.o : $(USER_DIR)/ir_%.h $(USER_DIR)/ir_%.cpp $(COMMON_DEPS) $(GTEST_HEADERS)
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
// Quick and dirty tool to convert a protocol's (hex) codes to raw timings.
|
||||
// Copyright 2021 David Conran
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include "IRac.h"
|
||||
#include "IRsend.h"
|
||||
#include "IRsend_test.h"
|
||||
#include "IRutils.h"
|
||||
|
||||
|
||||
void usage_error(char *name) {
|
||||
std::cerr << "Usage: " << name
|
||||
<< " --protocol PROTOCOL_NAME"
|
||||
<< " --code <hexidecimal>"
|
||||
<< " [--bits 1-" << kStateSizeMax * 8 << "]"
|
||||
<< " [--timinginfo]"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int argv_offset = 1;
|
||||
int repeats = 0;
|
||||
uint64_t code = 0;
|
||||
uint8_t state[kStateSizeMax] = {0}; // All array elements are set to 0.
|
||||
decode_type_t input_type = decode_type_t::UNKNOWN;
|
||||
bool timinginfo = false;
|
||||
|
||||
// Check the invocation/calling usage.
|
||||
if (argc < 5 || argc > 8) {
|
||||
usage_error(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strncmp("--protocol", argv[argv_offset], 11) == 0) {
|
||||
argv_offset++;
|
||||
input_type = strToDecodeType(argv[argv_offset]);
|
||||
switch (input_type) {
|
||||
// Unsupported types
|
||||
case decode_type_t::UNUSED:
|
||||
case decode_type_t::UNKNOWN:
|
||||
case decode_type_t::GLOBALCACHE:
|
||||
case decode_type_t::PRONTO:
|
||||
case decode_type_t::RAW:
|
||||
std::cerr << "The protocol specified is not supported by this program."
|
||||
<< std::endl;
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
argv_offset++;
|
||||
}
|
||||
|
||||
uint16_t nbits = IRsend::defaultBits(input_type);
|
||||
uint16_t stateSize = nbits / 8;
|
||||
if (strncmp("--code", argv[argv_offset], 7) == 0) {
|
||||
argv_offset++;
|
||||
String hexstr = String(argv[argv_offset]);
|
||||
uint64_t strOffset = 0;
|
||||
if (hexstr.rfind("0x", 0) || hexstr.rfind("0X", 0)) strOffset = 2;
|
||||
|
||||
// Calculate how many hexadecimal characters there are.
|
||||
uint64_t hexstrlength = hexstr.length() - strOffset;
|
||||
|
||||
// Ptr to the least significant byte of the resulting state for this
|
||||
// protocol.
|
||||
uint8_t *statePtr = &state[stateSize - 1];
|
||||
|
||||
// Convert the string into a state array of the correct length.
|
||||
for (uint16_t i = 0; i < hexstrlength; i++) {
|
||||
// Grab the next least sigificant hexadecimal digit from the string.
|
||||
uint8_t c = tolower(hexstr[hexstrlength + strOffset - i - 1]);
|
||||
if (isxdigit(c)) {
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else
|
||||
c = c - 'a' + 10;
|
||||
} else {
|
||||
std::cerr << "Code " << argv[argv_offset]
|
||||
<< " contains non-hexidecimal characters." << std::endl;
|
||||
return 3;
|
||||
}
|
||||
if (i % 2 == 1) { // Odd: Upper half of the byte.
|
||||
*statePtr += (c << 4);
|
||||
statePtr--; // Advance up to the next least significant byte of state.
|
||||
} else { // Even: Lower half of the byte.
|
||||
*statePtr = c;
|
||||
}
|
||||
}
|
||||
if (!hasACState(input_type))
|
||||
code = std::stoull(argv[argv_offset], nullptr, 16);
|
||||
argv_offset++;
|
||||
}
|
||||
|
||||
if (argc - argv_offset > 0 && strncmp("--bits", argv[argv_offset], 7) == 0) {
|
||||
argv_offset++;
|
||||
nbits = std::stoul(argv[argv_offset], nullptr, 10);
|
||||
if (nbits == 0 && (nbits <= kStateSizeMax * 8)) {
|
||||
std::cerr << "Nr. of bits " << argv[argv_offset]
|
||||
<< " is invalid." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
stateSize = nbits / 8;
|
||||
argv_offset++;
|
||||
}
|
||||
|
||||
if (argc - argv_offset > 0 &&
|
||||
strncmp("--timinginfo", argv[argv_offset], 13) == 0) {
|
||||
argv_offset++;
|
||||
timinginfo = true;
|
||||
}
|
||||
|
||||
if (argc - argv_offset != 0) {
|
||||
usage_error(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
irsend.reset();
|
||||
|
||||
if (hasACState(input_type)) // Is it larger than 64 bits?
|
||||
irsend.send(input_type, state, stateSize);
|
||||
else
|
||||
irsend.send(input_type, code, nbits, repeats);
|
||||
|
||||
irsend.makeDecodeResult();
|
||||
irrecv.decode(&irsend.capture);
|
||||
|
||||
std::cout << "Code type: " << irsend.capture.decode_type << " ("
|
||||
<< typeToString(irsend.capture.decode_type) << ")" << std::endl
|
||||
<< "Code bits: " << irsend.capture.bits << std::endl;
|
||||
if (hasACState(irsend.capture.decode_type)) {
|
||||
String description = IRAcUtils::resultAcToString(&irsend.capture);
|
||||
if (description.length()) {
|
||||
std::cout << "Description: " << description.c_str() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl << resultToSourceCode(&irsend.capture) << std::endl;
|
||||
if (timinginfo) std::cout << resultToTimingInfo(&irsend.capture);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
#! /bin/bash
|
||||
CODE_TO_RAW=./code_to_raw
|
||||
if [[ ! -x ${CODE_TO_RAW} ]]; then
|
||||
echo "'raw_to_code' failed to compile and produce an executable."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function unittest_success()
|
||||
{
|
||||
COMMAND=$1
|
||||
EXPECTED="$2"
|
||||
echo -n "Testing: \"${COMMAND}\" ..."
|
||||
OUTPUT="$(${COMMAND})"
|
||||
STATUS=$?
|
||||
FAILURE=""
|
||||
if [[ ${STATUS} -ne 0 ]]; then
|
||||
FAILURE="Non-Zero Exit status: ${STATUS}. "
|
||||
fi
|
||||
if [[ "${OUTPUT}" != "${EXPECTED}" ]]; then
|
||||
FAILURE="${FAILURE} Unexpected Output: \"${OUTPUT}\" != \"${EXPECTED}\""
|
||||
fi
|
||||
if [[ -z ${FAILURE} ]]; then
|
||||
echo " ok!"
|
||||
return 0
|
||||
else
|
||||
echo
|
||||
echo "FAILED: ${FAILURE}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
read -r -d '' OUT << EOM
|
||||
Code type: 4 (SONY)
|
||||
Code bits: 12
|
||||
|
||||
uint16_t rawData[78] = {2400, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 600, 600, 600, 600, 600, 24600, 2400, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 600, 600, 600, 600, 600, 24600, 2400, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 600, 600, 600, 600, 600, 24600 }; // SONY F50
|
||||
uint32_t address = 0x1;
|
||||
uint32_t command = 0x2F;
|
||||
uint64_t data = 0xF50;
|
||||
EOM
|
||||
|
||||
unittest_success "${CODE_TO_RAW} --protocol Sony --code 0xf50 --bits 12" "${OUT}"
|
||||
|
||||
read -r -d '' OUT << EOM
|
||||
Code type: 7 (SAMSUNG)
|
||||
Code bits: 32
|
||||
|
||||
uint16_t rawData[68] = {4480, 4480, 560, 1680, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1680, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 1680, 560, 560, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 560, 560, 47040 }; // SAMSUNG E0E09966
|
||||
uint32_t address = 0x7;
|
||||
uint32_t command = 0x99;
|
||||
uint64_t data = 0xE0E09966;
|
||||
EOM
|
||||
|
||||
unittest_success "${CODE_TO_RAW} --protocol SAMSUNG --code 0xE0E09966" "${OUT}"
|
||||
|
||||
read -r -d '' OUT << xEOMx
|
||||
Code type: 18 (KELVINATOR)
|
||||
Code bits: 128
|
||||
Description: Power: On, Mode: 1 (Cool), Temp: 27C, Fan: 1 (Low), Turbo: Off, Quiet: Off, XFan: On, Ion: Off, Light: Off, Swing(H): Off, Swing(V): Off
|
||||
|
||||
uint16_t rawData[280] = {9010, 4504, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 19974, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 1530, 680, 39950, 9010, 4504, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 19974, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 1530, 680, 1530, 680, 39950 }; // KELVINATOR
|
||||
uint8_t state[16] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xF0};
|
||||
xEOMx
|
||||
|
||||
unittest_success "${CODE_TO_RAW} --protocol KELVINATOR --code 0x190B8050000000E0190B8070000010F0" "${OUT}"
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash -e
|
||||
# Copyright 2021 crankyoldgit
|
||||
# Extract and constuct the string version of the IRremoteESP8266 Library Version
|
||||
function getVerNum()
|
||||
{
|
||||
echo $(egrep "^#define\s+_IRREMOTEESP8266_VERSION_$1\s+" \
|
||||
src/IRremoteESP8266.h | awk '{print $3;}')
|
||||
}
|
||||
|
||||
MAJOR=$(getVerNum "MAJOR")
|
||||
MINOR=$(getVerNum "MINOR")
|
||||
PATCH=$(getVerNum "PATCH")
|
||||
LIB_VERSION="${MAJOR}.${MINOR}.${PATCH}"
|
||||
echo $LIB_VERSION
|
|
@ -30,7 +30,8 @@ cat << EndOfTextEndOfTextEndOfText
|
|||
|
||||
EndOfTextEndOfTextEndOfText
|
||||
|
||||
CLASSES=$(egrep -h "^ *((enum|class) |} [a-zA-Z0-9_]+_t;$)" src/*.h |
|
||||
CLASSES=$(egrep -h \
|
||||
"^ *((enum|class|struct) [a-zA-Z0-9_]+|} [a-zA-Z0-9_]+_t;$)" src/*.h |
|
||||
sed 's/^ *//;s/enum class//;s/\;$//' | cut -d' ' -f2 | sort -u |
|
||||
grep -v "^__")
|
||||
for i in ${CLASSES}; do
|
||||
|
@ -45,7 +46,7 @@ cat << EndOfTextEndOfTextEndOfText
|
|||
|
||||
EndOfTextEndOfTextEndOfText
|
||||
CTYPES="u?int(8|16|32|64)?(_t)?|void|bool|char|float|long|double|String|static"
|
||||
OURTYPES="match_result_t|state_t|decode_type_t"
|
||||
OURTYPES="match_result_t|stdAc::state_t|decode_type_t"
|
||||
METHODS=$(egrep -h "^[ ]{0,2}(${CTYPES}|${OURTYPES})\*? [^ ]*\(" src/*.cpp |
|
||||
sed 's/^ //' | cut -d' ' -f2 | sed 's/^\([^:]*::\| *\* *\)//' |
|
||||
cut -d'(' -f1 | sort -u | grep -v RAM_ATTR)
|
||||
|
|
|
@ -0,0 +1,426 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Generate SupportedProtocols.md by scraping source code files"""
|
||||
import pathlib
|
||||
import argparse
|
||||
import subprocess
|
||||
from io import StringIO
|
||||
import sys
|
||||
import re
|
||||
import time
|
||||
|
||||
CODE_URL = "https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_"
|
||||
|
||||
BRAND_MODEL = re.compile(r"""
|
||||
Brand:\s{1,20} # "Brand:" label followd by between 1 and 20 whitespace chars.
|
||||
\b(?P<brand>.{1,40})\b # The actual brand of the device, max 40 chars.
|
||||
\s{0,10}, # Followed by at most 10 whitespace chars, then a comma.
|
||||
\s{1,20} # The between 1 and 20 whitespace chars.
|
||||
Model:\s{1,20} # "Model:" label followd by between 1 and 20 whitespace chars.
|
||||
\b(?P<model>.{1,80}) # The model info of the device, max 80 chars.
|
||||
\s{0,5}$ # Followed by at most 5 whitespaces before the end of line.
|
||||
""", re.VERBOSE)
|
||||
ENUMS = re.compile(r"enum (\w{1,60}) {(.{1,5000}?)};", re.DOTALL)
|
||||
ENUM_ENTRY = re.compile(r"^\s{1,80}(\w{1,80})", re.MULTILINE)
|
||||
DECODED_PROTOCOLS = re.compile(r"""
|
||||
.{0,80} # Ignore upto an 80 char line of whitespace/code etc.
|
||||
# Now look for code that looks like we are assigning the Protocol type.
|
||||
# There are two typical styles used:
|
||||
(?:results->decode_type # The first style.
|
||||
| # Or
|
||||
typeguess) # The second style
|
||||
\s{0,5}=\s{0,5} # The assignment operator and potential whitespace
|
||||
(?:decode_type_t::)? # The protocol could have an optional type prefix.
|
||||
(\w{1,40}); # Finally, the last word of code should be the Protocol.
|
||||
""", re.VERBOSE)
|
||||
AC_FN = re.compile(r"ir_(.{1,80})\.h")
|
||||
AC_MODEL_ENUM_RE = re.compile(r"(.{1,40})_ac_remote_model_t")
|
||||
IRSEND_FN_RE = re.compile(r"IRsend\.h")
|
||||
ALL_FN = re.compile(r"ir_(.{1,80})\.(h|cpp)")
|
||||
|
||||
EXCLUDED_PROTOCOLS = ["UNKNOWN", "UNUSED", "kLastDecodeType", "typeguess"]
|
||||
EXCLUDED_ACS = ["Magiquest", "NEC"]
|
||||
|
||||
def getgitcommittime():
|
||||
"""Call git to get time of last commit
|
||||
"""
|
||||
try:
|
||||
label = subprocess.check_output(\
|
||||
["git", "show", "-s", "--format=%ct", "HEAD"]).strip()
|
||||
return int(label)
|
||||
except FileNotFoundError as err:
|
||||
print("Git failed, which is ok, no git binary found?:", err)
|
||||
return None
|
||||
except subprocess.SubprocessError as err:
|
||||
print("Git failed, which is ok, see output, maybe no git checkout?:", err)
|
||||
return None
|
||||
|
||||
def getmarkdownheader():
|
||||
"""Get the generated header
|
||||
"""
|
||||
srctime = getgitcommittime()
|
||||
# pylint: disable=C0209
|
||||
return """<!--- WARNING: Do NOT edit this file directly.
|
||||
It is generated by './tools/scrape_supported_devices.py'.
|
||||
Last generated: {} --->""".format(
|
||||
time.strftime("%a %d %b %Y %H:%M:%S +0000", time.gmtime(srctime)))
|
||||
# pylint: enable=C0209
|
||||
|
||||
|
||||
|
||||
def getallprotocols():
|
||||
"""Return all protocls configured in IRremoteESP8266.h
|
||||
"""
|
||||
irremote = ARGS.directory / "IRremoteESP8266.h"
|
||||
enums = getenums(irremote)["decode_type_t"]
|
||||
if not enums:
|
||||
errorexit("Error getting ENUMS from IRremoteESP8266.h")
|
||||
return enums
|
||||
|
||||
|
||||
def getdecodedprotocols():
|
||||
"""All protocols that include decoding support"""
|
||||
ret = set()
|
||||
for path in ARGS.directory.iterdir():
|
||||
if path.suffix != ".cpp":
|
||||
continue
|
||||
matches = DECODED_PROTOCOLS.finditer(path.open(encoding="utf-8").read())
|
||||
for match in matches:
|
||||
protocol = match.group(1)
|
||||
if protocol not in EXCLUDED_PROTOCOLS:
|
||||
ret.add(protocol)
|
||||
return ret
|
||||
|
||||
|
||||
def getallacs():
|
||||
"""All supported A/C codes"""
|
||||
ret = {}
|
||||
for path in ARGS.directory.iterdir():
|
||||
match = AC_FN.match(path.name)
|
||||
if match:
|
||||
acprotocol = match.group(1)
|
||||
rawmodels = getenums(path)
|
||||
models = set()
|
||||
for model in rawmodels:
|
||||
model = model.upper()
|
||||
model = model.replace(f"K{acprotocol.upper()}", "")
|
||||
if model and model not in EXCLUDED_PROTOCOLS:
|
||||
models.add(model)
|
||||
if acprotocol in ret:
|
||||
ret[acprotocol].update(models)
|
||||
else:
|
||||
ret[acprotocol] = models
|
||||
# Parse IRsend.h's enums
|
||||
match = IRSEND_FN_RE.match(path.name)
|
||||
if match:
|
||||
rawmodels = getenums(path)
|
||||
for acprotocol, acmodels in rawmodels.items():
|
||||
models = set()
|
||||
for model in acmodels:
|
||||
model = model.upper()
|
||||
model = model.replace(f"K{acprotocol.upper()}", "")
|
||||
if model and model not in EXCLUDED_PROTOCOLS:
|
||||
models.add(model)
|
||||
if acprotocol in ret:
|
||||
ret[acprotocol].update(models)
|
||||
else:
|
||||
ret[acprotocol] = models
|
||||
return ret
|
||||
|
||||
class FnSets():
|
||||
"""Container for getalldevices"""
|
||||
def __init__(self):
|
||||
self.allcodes = {}
|
||||
self.fnnomatch = set()
|
||||
self.allhfileprotos = set()
|
||||
self.fnhmatch = set()
|
||||
self.fncppmatch = set()
|
||||
|
||||
def add(self, supports, path):
|
||||
"""add the path to correct set based on supports"""
|
||||
if path.suffix == ".h":
|
||||
self.allhfileprotos.add(path.stem)
|
||||
if supports:
|
||||
if path.suffix == ".h":
|
||||
self.fnhmatch.add(path.stem)
|
||||
elif path.suffix == ".cpp":
|
||||
self.fncppmatch.add(path.stem)
|
||||
else:
|
||||
self.fnnomatch.add(path.stem)
|
||||
|
||||
def printwarnings(self):
|
||||
"""print warnings"""
|
||||
# all protos with support in .cpp file, when there is a .h file
|
||||
# meaning that the documentation should probably be moved to .h
|
||||
# in the future, with doxygen, that might change
|
||||
protosincppwithh = list(self.fncppmatch & self.allhfileprotos)
|
||||
if protosincppwithh:
|
||||
protosincppwithh.sort()
|
||||
print("The following files has supports section in .cpp, expected in .h")
|
||||
for path in protosincppwithh:
|
||||
print(f"\t{path}")
|
||||
|
||||
protosincppandh = list(self.fncppmatch & self.fnhmatch)
|
||||
if protosincppandh:
|
||||
protosincppandh.sort()
|
||||
print("The following files has supports section in both .h and .cpp")
|
||||
for path in protosincppandh:
|
||||
print(f"\t{path}")
|
||||
|
||||
nosupports = self.getnosupports()
|
||||
if nosupports:
|
||||
nosupports.sort()
|
||||
print("The following files had no supports section:")
|
||||
for path in nosupports:
|
||||
print(f"\t{path}")
|
||||
|
||||
return protosincppwithh or protosincppandh or nosupports
|
||||
|
||||
def getnosupports(self):
|
||||
"""get protos without supports sections"""
|
||||
return list(self.fnnomatch - self.fnhmatch - self.fncppmatch)
|
||||
|
||||
|
||||
def getalldevices():
|
||||
"""All devices and associated branding and model information (if available)
|
||||
"""
|
||||
sets = FnSets()
|
||||
for path in ARGS.directory.iterdir():
|
||||
match = ALL_FN.match(path.name)
|
||||
if not match:
|
||||
continue
|
||||
supports = extractsupports(path)
|
||||
sets.add(supports, path)
|
||||
protocol = match.group(1)
|
||||
for brand, model in supports:
|
||||
protocolbrand = (protocol, brand)
|
||||
pbset = sets.allcodes.get(protocolbrand, [])
|
||||
if model in pbset:
|
||||
print(f"Model {model} is duplicated for {protocol}, {brand}")
|
||||
sets.allcodes[protocolbrand] = pbset + [model]
|
||||
|
||||
for fnprotocol in sets.getnosupports():
|
||||
sets.allcodes[(fnprotocol[3:], "Unknown")] = []
|
||||
return sets
|
||||
|
||||
|
||||
def getenums(path):
|
||||
"""Returns the keys for the first enum type in path
|
||||
"""
|
||||
ret = {}
|
||||
for enums in ENUMS.finditer(path.open(encoding="utf-8").read()):
|
||||
if enums:
|
||||
enum_name = AC_MODEL_ENUM_RE.search(enums.group(1))
|
||||
if enum_name:
|
||||
enum_name = enum_name.group(1).capitalize()
|
||||
else:
|
||||
enum_name = enums.group(1)
|
||||
ret[enum_name] = set()
|
||||
for enum in ENUM_ENTRY.finditer(enums.group(2)):
|
||||
enum = enum.group(1)
|
||||
if enum in EXCLUDED_PROTOCOLS:
|
||||
continue
|
||||
ret[enum_name].add(enum)
|
||||
return ret
|
||||
|
||||
|
||||
ARGS = None
|
||||
|
||||
|
||||
def initargs():
|
||||
"""Init the command line arguments"""
|
||||
global ARGS # pylint: disable=global-statement
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--noout",
|
||||
help="generate no output data, combine with --alert to only check",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--stdout",
|
||||
help="output to stdout rather than SupportedProtocols.md",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument("-v",
|
||||
"--verbose",
|
||||
help="increase output verbosity",
|
||||
action="store_true")
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--alert",
|
||||
help="alert if a file does not have a supports section, "
|
||||
"non zero exit code if issues where found",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument(
|
||||
"directory",
|
||||
nargs="?",
|
||||
help="directory of the source git checkout",
|
||||
default=None,
|
||||
)
|
||||
ARGS = parser.parse_args()
|
||||
if ARGS.directory is None:
|
||||
src = pathlib.Path("../src")
|
||||
if not src.is_dir():
|
||||
src = pathlib.Path("./src")
|
||||
else:
|
||||
src = pathlib.Path(ARGS.directory) / "src"
|
||||
if not src.is_dir():
|
||||
errorexit(f"Directory not valid: {src!s}")
|
||||
ARGS.directory = src
|
||||
return ARGS
|
||||
|
||||
def getmdfile():
|
||||
"""Resolves SupportedProtocols.md path"""
|
||||
foutpath = ARGS.directory / "../SupportedProtocols.md"
|
||||
return foutpath.resolve()
|
||||
|
||||
def errorexit(msg):
|
||||
"""Print an error and exit on critical error"""
|
||||
sys.stderr.write(f"{msg}\n")
|
||||
sys.exit(1)
|
||||
|
||||
def extractsupports(path):
|
||||
"""Extract all of the Supports: sections and associated brands and models
|
||||
"""
|
||||
supports = []
|
||||
insupports = False
|
||||
for line in path.open(encoding="utf-8"):
|
||||
if not line.startswith("//"):
|
||||
continue
|
||||
line = line[2:].strip()
|
||||
if line == "Supports:":
|
||||
insupports = True
|
||||
continue
|
||||
if insupports:
|
||||
match = BRAND_MODEL.match(line)
|
||||
if match:
|
||||
supports.append((match.group("brand"), match.group("model")))
|
||||
else:
|
||||
insupports = False
|
||||
continue
|
||||
# search and inform about any legacy formated supports data
|
||||
elif any(x in line for x in [ \
|
||||
"seems compatible with",
|
||||
"be compatible with",
|
||||
"it working with here"]):
|
||||
print(f"\t{path.name} Legacy supports format found\n\t\t{line}")
|
||||
return supports
|
||||
|
||||
|
||||
def makeurl(txt, path):
|
||||
"""Make a Markup URL from given filename"""
|
||||
return f"[{txt}]({CODE_URL + path})"
|
||||
|
||||
|
||||
def outputprotocols(fout, protocols):
|
||||
"""For a given protocol set, sort and output the markdown"""
|
||||
protocols = list(protocols)
|
||||
protocols.sort()
|
||||
for protocol in protocols:
|
||||
fout.write(f"- {protocol}\n")
|
||||
|
||||
|
||||
def generate(fout):
|
||||
"""Generate data to fout
|
||||
return True on any issues (when alert is active)"""
|
||||
decodedprotocols = getdecodedprotocols()
|
||||
sendonly = getallprotocols() - decodedprotocols
|
||||
allacs = getallacs()
|
||||
|
||||
sets = getalldevices()
|
||||
allcodes = sets.allcodes
|
||||
allbrands = list(allcodes.keys())
|
||||
allbrands.sort()
|
||||
|
||||
fout.write("\n# IR Protocols supported by this library\n\n")
|
||||
fout.write(
|
||||
"| Protocol | Brand | Model | A/C Model | Detailed A/C Support |\n")
|
||||
fout.write("| --- | --- | --- | --- | --- |\n")
|
||||
|
||||
for protocolbrand in allbrands:
|
||||
protocol, brand = protocolbrand
|
||||
codes = allcodes[protocolbrand]
|
||||
codes.sort()
|
||||
acmodels = []
|
||||
acsupport = "-"
|
||||
if protocol in allacs:
|
||||
acmodels = list(allacs[protocol])
|
||||
acmodels.sort()
|
||||
brand = makeurl(brand, protocol + ".h")
|
||||
if protocol not in EXCLUDED_ACS:
|
||||
acsupport = "Yes"
|
||||
# pylint: disable=C0209
|
||||
fout.write("| {} | **{}** | {} | {} | {} |\n".format(
|
||||
makeurl(protocol, protocol + ".cpp"),
|
||||
brand,
|
||||
"<BR>".join(codes).replace("|", "\\|"),
|
||||
"<BR>".join(acmodels),
|
||||
acsupport,
|
||||
))
|
||||
# pylint: enable=C0209
|
||||
|
||||
fout.write("\n\n## Send only protocols:\n\n")
|
||||
outputprotocols(fout, sendonly)
|
||||
|
||||
fout.write("\n\n## Send & decodable protocols:\n\n")
|
||||
outputprotocols(fout, decodedprotocols)
|
||||
|
||||
return ARGS.alert and sets.printwarnings()
|
||||
|
||||
def generatenone():
|
||||
"""No out write
|
||||
return True on any issues"""
|
||||
return generate(StringIO())
|
||||
|
||||
def generatestdout():
|
||||
"""Standard out write
|
||||
return True on any issues"""
|
||||
fout = sys.stdout
|
||||
fout.write(getmarkdownheader())
|
||||
return generate(fout)
|
||||
|
||||
def generatefile():
|
||||
"""File write, extra detection of changes in existing file
|
||||
return True on any issues, but only if there is changes"""
|
||||
# get file path
|
||||
foutpath = getmdfile()
|
||||
if ARGS.verbose:
|
||||
print(f"Output path: {foutpath!s}")
|
||||
# write data to temp memorystream
|
||||
ftemp = StringIO()
|
||||
ret = generate(ftemp)
|
||||
# get old filedata, skipping header
|
||||
with getmdfile().open("r", encoding="utf-8") as forg:
|
||||
olddata = forg.readlines()[3:]
|
||||
# get new data, skip first empty line
|
||||
ftemp.seek(0)
|
||||
newdata = ftemp.readlines()[1:]
|
||||
# if new data is same as old we don't need to write anything
|
||||
if newdata == olddata:
|
||||
print("No changes, exit without write")
|
||||
return False
|
||||
# write output
|
||||
with foutpath.open("w", encoding="utf-8") as fout:
|
||||
fout.write(getmarkdownheader())
|
||||
fout.write(ftemp.getvalue())
|
||||
|
||||
return ret
|
||||
|
||||
def main():
|
||||
"""Default main function
|
||||
return True on any issues"""
|
||||
initargs()
|
||||
if ARGS.verbose:
|
||||
print(f"Looking for files in: {ARGS.directory.resolve()!s}")
|
||||
if ARGS.noout:
|
||||
return generatenone()
|
||||
if ARGS.stdout:
|
||||
return generatestdout()
|
||||
# default file
|
||||
return generatefile()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(1 if main() else 0)
|
Loading…
Reference in New Issue