Release 6.6

Release 6.6
This commit is contained in:
Theo Arends 2019-07-05 13:44:24 +02:00
parent b0cf8e1437
commit c702cb17e0
677 changed files with 95371 additions and 10573 deletions

5
.gitignore vendored
View File

@ -9,6 +9,11 @@
.gcc-flags.json .gcc-flags.json
sonoff/user_config_override.h sonoff/user_config_override.h
build build
firmware.map
## Visual Studio Code specific ###### ## Visual Studio Code specific ######
.vscode .vscode
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
*.bak

5
API.md
View File

@ -1,4 +1,7 @@
## Sonoff-Tasmota basic API information <img src="/tools/logo/TASMOTA_FullLogo_Vector.svg" alt="Logo" align="right" height="76"/>
# Basic API information
Sonoff-Tasmota can easily be extended by developers using provided function pointers as callback Ids. This document lists the available callback function Ids. See the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Sensor-API) for more information. Sonoff-Tasmota can easily be extended by developers using provided function pointers as callback Ids. This document lists the available callback function Ids. See the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Sensor-API) for more information.
Callback availability can be checked by searching for either XdrvCall, XsnsCall, XdspCall and XnrgCall. Callback availability can be checked by searching for either XdrvCall, XsnsCall, XdspCall and XnrgCall.

View File

@ -1,4 +1,6 @@
# Contributing to Sonoff-Tasmota <img src="/tools/logo/TASMOTA_FullLogo_Vector.svg" alt="Logo" align="right" height="76"/>
# Contributing
**Any contribution helps our team and makes Tasmota better for the entire community!** **Any contribution helps our team and makes Tasmota better for the entire community!**
@ -26,7 +28,7 @@ This document describes rules that are in effect for this repository, meant for
1. Any contributor to the project can participate in the triaging process, if he/she chooses to do so. 1. Any contributor to the project can participate in the triaging process, if he/she chooses to do so.
2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor. 2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor.
3. Issues that are accepted should be marked with appropriate labels. 3. Issues that are accepted should be marked with appropriate labels.
4. Issues that could impact functionality for many users should be considered severe. 4. Issues that could impact functionality for many users should be considered severe.
5. Issues caused by the SDK or chip should not be marked severe, as there usually isnt much to be done. Common sense should be applied when deciding. Such issues should be documented in the Wiki, for reference by users. 5. Issues caused by the SDK or chip should not be marked severe, as there usually isnt much to be done. Common sense should be applied when deciding. Such issues should be documented in the Wiki, for reference by users.
6. Issues with feature requests should be discussed for viability/desirability. 6. Issues with feature requests should be discussed for viability/desirability.
7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified. 7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified.
@ -56,7 +58,57 @@ The process is straight-forward.
7. All pull requests should consider updates to the documentation. 7. All pull requests should consider updates to the documentation.
8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. 8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority.
9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. 9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged.
10. Pull requests that don't meet the above will be denied and closed. 10. By submitting a PR, it is needed to use the provided PR template and check all boxes, performing the required tasks and accepting the CLA.
11. Pull requests that don't meet the above will be denied and closed.
--------------------------------------
## Contributor License Agreement (CLA)
```
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the GPL-3.0 license; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the GPL-3.0 license; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it) is maintained indefinitely
and may be redistributed consistent with this project or the open
source license(s) involved.
```
This Contributor License Agreement (CLA) was adopted on April 1st, 2019.
The text of this license is available under the [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). It is based on the Linux [Developer Certificate Of Origin](http://elinux.org/Developer_Certificate_Of_Origin), but is modified to explicitly use the GPL-3.0 license and not mention sign-off (due to GitHub.com keeps an historial, with your user name, of PRs' commits and all editions on PR's comments).
To accept the CLA it is required to put a x between [ ] on `[ ] I accept the CLA` in the PR template when submitting it. The [ ] is an opt-in box, so you have to manually accept it.
**Why a CLA ?**
_"A Contributor Licence Agreement (CLA) is strongly recommended when accepting third party contributions to an open development project, such as an open source software project. In order to redistribute contributions, it is necessary to ensure that the project has the necessary rights to do so. A Contributor Licence Agreement is a lightweight agreement, signed by the copyright holder, that grants the necessary rights for the contribution to be redistributed as part of the project."_ [OSS Watch](http://oss-watch.ac.uk/resources/cla)
A CLA is a legal document in which you state _you are entitled to contribute the code/documentation/translation to the project_ youre contributing to and that _you are willing to have it used in distributions and derivative works_. This means that should there be any kind of legal issue in the future as to the origins and ownership of any particular piece of code, then that project has the necessary forms on file from the contributor(s) saying they were permitted to make this contribution.
CLA is a safety because it also ensures that once you have provided a contribution, you cannot try to withdraw permission for its use at a later date. People can therefore use that software, confident that they will not be asked to stop using pieces of the code at a later date.
A __license__ grants "outbound" rights to the user of project.
A __CLA__ enables a contributor to grant "inbound" rights to a project.
<Other> <Other>
<A table should be maintained for relating maintainers and components. When triaging, this is essential to figure out if someone in particular should be consulted about specific changes.> <A table should be maintained for relating maintainers and components. When triaging, this is essential to figure out if someone in particular should be consulted about specific changes.>

View File

@ -1,6 +1,6 @@
## Sonoff-Tasmota ## Sonoff-Tasmota
Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custome device templates and sensors support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. <img src="/tools/logo/TASMOTA_FullLogo_Vector.svg" alt="Logo" align="right" height="90"/>Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO.
[![GitHub version](https://img.shields.io/github/release/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) [![GitHub version](https://img.shields.io/github/release/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest)
[![GitHub download](https://img.shields.io/github/downloads/arendst/Sonoff-Tasmota/total.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) [![GitHub download](https://img.shields.io/github/downloads/arendst/Sonoff-Tasmota/total.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest)
@ -15,31 +15,31 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute!
See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/master/RELEASENOTES.md) for release information. See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/master/RELEASENOTES.md) for release information.
In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest) the binaries can also be OTA downloaded from http://thehackbox.org/tasmota/release/ In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest) the binaries can also be downloaded from http://thehackbox.org/tasmota/release/
### Disclaimer #### Disclaimer
:warning: **DANGER OF ELECTROCUTION** :warning: :warning: **DANGER OF ELECTROCUTION** :warning:
A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician. Remember: _**SAFETY FIRST**_. It is not worth to risk yourself, your family and your home if you don't know exactly what you are doing. Never try to flash a Sonoff device while it is connected to MAINS AC. A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician. Remember: _**SAFETY FIRST**_. It is not worth risk to yourself, your family, and your home if you don't know exactly what you are doing. Never try to flash a Sonoff device while it is connected to MAINS AC.
We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site.
### Note ### Note
Please do not ask to add devices where you can't provide a basic working configuration (other than sonoff). Since there are thousands of them.. Please do not ask to add new devices unless it requires additional code for new features. If the device is not listed as a module, try using [Templates](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates) first. If it is not listed in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) create your own [Template](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates#creating-your-template-).
### Quick Install ### Quick Install
Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as [documented in the wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Flashing).
### Important User Compilation Information ### Important User Compilation Information
If you want to compile Sonoff-Tasmota yourself keep in mind the following: If you want to compile Sonoff-Tasmota yourself keep in mind the following:
- Only Flash Mode **DOUT** is supported. Do not use Flash Mode DIO / QIO / QOUT as it might seem to brick your device. See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Theo's-Tasmota-Tips) for background information. - Only Flash Mode **DOUT** is supported. Do not use Flash Mode DIO / QIO / QOUT as it might seem to brick your device. See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Theo's-Tasmota-Tips) for background information.
- Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. If you compile using ESP/Arduino library 2.3.0 then download the provided new linker script to your Arduino IDE or Platformio base folder. Later version of ESP/Arduino library already contain the correct linker script. See [Wiki > Prerequisite](https://github.com/arendst/Sonoff-Tasmota/wiki/Prerequisite). - Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. If you compile using ESP/Arduino library 2.3.0 then download the provided new linker script to your Arduino IDE or Platformio base folder. Later version of ESP/Arduino library already contain the correct linker script. See [Wiki > Prerequisites](https://github.com/arendst/Sonoff-Tasmota/wiki/Prerequisites).
- To make compile time changes to Sonoff-Tasmota it can use the ``user_config_override.h`` file. It assures keeping your settings when you download and compile a new version. To use ``user_config.override.h`` you will have to make a copy of the provided ``user_config.override_sample.h`` file and add your setting overrides. To enable the override file you will need to use a compile define as documented in the ``user_config_override_sample.h`` file. - To make compile time changes to Sonoff-Tasmota it can use the ``user_config_override.h`` file. It assures keeping your settings when you download and compile a new version. To use ``user_config.override.h`` you will have to make a copy of the provided ``user_config_override_sample.h`` file and add your setting overrides. To enable the override file you will need to use a compile define as documented in the ``user_config_override_sample.h`` file.
### Version Information ### Version Information
- Sonoff-Tasmota provides all (Sonoff) modules in one file and starts with module Sonoff Basic. - Sonoff-Tasmota provides all (Sonoff) modules in one file and starts with module Sonoff Basic.
- Once uploaded select module using the configuration webpage or the commands ```Modules``` and ```Module```. - Once uploaded, select [Module](https://github.com/arendst/Sonoff-Tasmota/wiki/Modules) using the configuration webpage, the commands ```Modules``` and ```Module``` or configure the [Template](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates) for your device
- After reboot select config menu again or use commands ```GPIOs``` and ```GPIO``` to change GPIO with desired sensor. - After reboot select config menu again or use commands ```GPIOs``` and ```GPIO``` to change GPIO with desired sensor.
### Migration Information ### Migration Information
@ -53,51 +53,11 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade
### Support Information ### Support Information
<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoffbasic.jpg" width="250" align="right" /> <img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoffbasic.jpg" width="250" align="right" />
See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for more information.<br /> For a database of supported devices see [Tasmota Device Templates Repository](https://blakadder.github.io/templates)
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.<br />
See [Chat](https://discord.gg/Ks2Kzd4) for more user experience.
The following devices are supported: See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for use instructions and how-to's.<br />
- [iTead Sonoff Basic (R2)](https://www.itead.cc/smart-home/sonoff-wifi-wireless-switch-1.html) See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.<br />
- [iTead Sonoff RF](https://www.itead.cc/smart-home/sonoff-rf.html) Visit [Discord Chat](https://discord.gg/Ks2Kzd4) for discussions and troubleshooting.
- [iTead Sonoff SV](https://www.itead.cc/smart-home/sonoff-sv.html)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoff_th.jpg" width="250" align="right" />
- [iTead Sonoff TH10/TH16 with temperature sensor](https://www.itead.cc/smart-home/sonoff-th.html)
- [iTead Sonoff Dual (R2)](https://www.itead.cc/smart-home/sonoff-dual.html)
- [iTead Sonoff Pow with Energy Monitoring](https://www.itead.cc/smart-home/sonoff-pow.html)
- [iTead Sonoff Pow R2 with Energy Monitoring](https://www.itead.cc/sonoff-pow-r2.html)
- [iTead Sonoff 4CH (R2)](https://www.itead.cc/smart-home/sonoff-4ch.html)
- [iTead Sonoff 4CH Pro (R2)](https://www.itead.cc/smart-home/sonoff-4ch-pro.html)
- [iTead Sonoff S20 Smart Socket](https://www.itead.cc/smart-socket.html)
- [Sonoff S22 Smart Socket](https://github.com/arendst/Sonoff-Tasmota/issues/627)
- [iTead Sonoff S26 Smart Socket](https://www.itead.cc/sonoff-s26-wifi-smart-plug.html)
- [iTead Sonoff S31 Smart Socket with Energy Monitoring](https://www.itead.cc/sonoff-s31.html)
- [iTead Slampher](https://www.itead.cc/slampher.html)
- [iTead Sonoff Touch](https://www.itead.cc/sonoff-touch.html)
- [iTead Sonoff T1](https://www.itead.cc/sonoff-t1.html)
- [iTead Sonoff SC](https://www.itead.cc/sonoff-sc.html)
- [iTead Sonoff Led](https://www.itead.cc/sonoff-led.html)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoff4chpror2.jpg" height="250" align="right" />
- [iTead Sonoff BN-SZ01 Ceiling Led](https://www.itead.cc/bn-sz01.html)
- [iTead Sonoff B1](https://www.itead.cc/sonoff-b1.html)
- [iTead Sonoff iFan02](https://www.itead.cc/sonoff-ifan02-wifi-smart-ceiling-fan-with-light.html)
- [iTead Sonoff RF Bridge 433](https://www.itead.cc/sonoff-rf-bridge-433.html)
- [iTead Sonoff Dev](https://www.itead.cc/sonoff-dev.html)
- [iTead 1 Channel Switch 5V / 12V](https://www.itead.cc/smart-home/inching-self-locking-wifi-wireless-switch.html)
- [iTead Motor Clockwise/Anticlockwise](https://www.itead.cc/smart-home/motor-reversing-wifi-wireless-switch.html)
- [Electrodragon IoT Relay Board](http://www.electrodragon.com/product/wifi-iot-relay-board-based-esp8266/)
- AI Light or any my9291 compatible RGBW LED bulb
- H801 PWM LED controller
- [MagicHome PWM LED controller](https://github.com/arendst/Sonoff-Tasmota/wiki/MagicHome-LED-strip-controller)
- AriLux AL-LC01, AL-LC06 and AL-LC11 PWM LED controller
- [Supla device - Espablo-inCan mod. for electrical Installation box](https://forum.supla.org/viewtopic.php?f=33&t=2188)
- [BlitzWolf BW-SHP2 Smart Socket with Energy Monitoring](https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/shelly2_small_250a.png" width="250" align="right" />
- [Luani HVIO board](https://luani.de/projekte/esp8266-hvio/)
- [Wemos D1 mini](https://wiki.wemos.cc/products:d1:d1_mini)
- [HuaFan Smart Socket](https://github.com/arendst/Sonoff-Tasmota/wiki/HuaFan-Smart-Socket)
- [Hyleton-313 Smart Plug](https://github.com/arendst/Sonoff-Tasmota/wiki/Hyleton-313-Smart-Plug)
- [Allterco Shelly 1](https://shelly.cloud/shelly1-open-source/)
- [Allterco Shelly 2 with Energy Monitoring](https://shelly.cloud/shelly2/)
- NodeMcu and Ledunia
- [KS-602 based switches like GresaTek, Jesiya, NewRice, Lyasi etc](https://ucexperiment.wordpress.com/2017/11/14/reprogramming-a-lyasi-wifi-wall-switch-with-esp8285/)
### Contribute ### Contribute
You can contribute to Sonoff-Tasmota by You can contribute to Sonoff-Tasmota by
@ -153,7 +113,7 @@ People helping to keep the show on the road:
- Emontnemery for his HomeAssistant Discovery concept and many code tuning tips - Emontnemery for his HomeAssistant Discovery concept and many code tuning tips
- Aidan Mountford for his HSB support - Aidan Mountford for his HSB support
- Daniel Ztolnai for his Serial Bridge implementation - Daniel Ztolnai for his Serial Bridge implementation
- Gerhard Mutz for his SGP30, Sunrise/Sunset and display support drivers - Gerhard Mutz for multiple sensor & display drivers, Sunrise/Sunset, and scripting
- Nuno Ferreira for his HC-SR04 driver - Nuno Ferreira for his HC-SR04 driver
- Adrian Scillato for his (security)fixes and implementing and maintaining KNX - Adrian Scillato for his (security)fixes and implementing and maintaining KNX
- Gennaro Tortone for implementing and maintaining Eastron drivers - Gennaro Tortone for implementing and maintaining Eastron drivers
@ -163,6 +123,8 @@ People helping to keep the show on the road:
- Joel Stein and digiblur for their Tuya research and driver - Joel Stein and digiblur for their Tuya research and driver
- Frogmore42 and Jason2866 for providing many issue answers - Frogmore42 and Jason2866 for providing many issue answers
- Blakadder for editing the wiki and providing template management - Blakadder for editing the wiki and providing template management
- Stephan Hadinger for refactoring light driver and enhancing HueEmulation
- tmo for designing the official logo
- Many more providing Tips, Wips, Pocs or PRs - Many more providing Tips, Wips, Pocs or PRs
### License ### License

View File

@ -1,4 +1,7 @@
## Tasmota Reference <img src="/tools/logo/TASMOTA_FullLogo_Vector.svg" alt="Logo" align="right" height="76"/>
# Reference
Tasmota backgound information. Tasmota backgound information.
## Supported Smart Switch with Energy Monitoring GPIO usage ## Supported Smart Switch with Energy Monitoring GPIO usage

View File

@ -1,3 +1,7 @@
<img src="/tools/logo/TASMOTA_FullLogo_Vector.svg" alt="Logo" align="right" height="76"/>
# RELEASE NOTES
## Migration Information ## Migration Information
See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates:
@ -6,11 +10,10 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade
3. Migrate to **Sonoff-Tasmota 5.14** 3. Migrate to **Sonoff-Tasmota 5.14**
4. Migrate to **Sonoff-Tasmota 6.x** 4. Migrate to **Sonoff-Tasmota 6.x**
## Release notes ## Core version 2.3.0 vs 2.4.2
### Core version 2.3.0 vs 2.4.2
This release is based on ESP8266/Arduino library core 2.3.0 (again) as some people encountered wifi related issues on core 2.4.2. For others core 2.4.2 is working just fine. Both version are available from http://thehackbox.org/tasmota/release/ This release is based on ESP8266/Arduino library core 2.3.0 (again) as some people encountered wifi related issues on core 2.4.2. For others core 2.4.2 is working just fine. Both version are available from http://thehackbox.org/tasmota/release/
### Change in default initial configuration tool ## Change in default initial configuration tool
Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**. Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**.
To save memory space all other binaries support **WifiManager only**. To save memory space all other binaries support **WifiManager only**.
@ -71,14 +74,14 @@ Module | Description
49 Neo Coolcam | Neo Coolcam Wifi Smart Socket 49 Neo Coolcam | Neo Coolcam Wifi Smart Socket
50 ESP Switch | ESP Switch 4-gang Wifi Switch with Leds 50 ESP Switch | ESP Switch 4-gang Wifi Switch with Leds
51 OBI Socket | OBI Wifi Smart Socket 51 OBI Socket | OBI Wifi Smart Socket
52 Teckin | Teckin SP20 Wifi Smart Switch with Energy Monitoring 52 Teckin | Teckin SP22 Wifi Smart Switch with Energy Monitoring
53 AplicWDP303075 | Aplic WDP 303075 CSL Wifi Smart Switch with Energy Monitoring 53 AplicWDP303075 | Aplic WDP 303075 CSL Wifi Smart Switch with Energy Monitoring
54 Tuya Dimmer | MIUO (and other Tuya based) Wifi Dimmer for Incandescent Lights and Led 54 Tuya Dimmer | MIUO (and other Tuya based) Wifi Dimmer for Incandescent Lights and Led
55 Gosund SP1 v23 | Gosund SP1 v2.3 Wifi Smart Switch with Energy Monitoring 55 Gosund SP1 v23 | Gosund SP1 v2.3 Wifi Smart Switch with Energy Monitoring
56 ARMTR Dimmer | ARMtronix Wifi dimmer for Incandescent Lights and Led 56 ARMTR Dimmer | ARMtronix Wifi dimmer for Incandescent Lights and Led
57 SK03 Outdoor | SK03 Outdoor Wifi Smart Switch with Energy Monitoring 57 SK03 Outdoor | SK03 Outdoor Wifi Smart Switch with Energy Monitoring
58 PS-16-DZ | PS-16-DZ Wifi dimmer for Incandescent Lights and Led 58 PS-16-DZ | PS-16-DZ Wifi dimmer for Incandescent Lights and Led
59 Teckin US | Teckin US and ZooZee SA102 Wifi Smart Switch with Energy Monitoring 59 Teckin US | Teckin SP20 and ZooZee SA102 Wifi Smart Switch with Energy Monitoring
60 Manzoku strip | Manzoku Wifi Smart Power Strip with four Relays 60 Manzoku strip | Manzoku Wifi Smart Power Strip with four Relays
61 OBI Socket 2 | OBI 2 Wifi Smart Socket 61 OBI Socket 2 | OBI 2 Wifi Smart Socket
62 YTF IR Bridge | YTF Infra Red Wifi Bridge 62 YTF IR Bridge | YTF Infra Red Wifi Bridge
@ -104,7 +107,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/release/020402/ Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/release/020402/
### Available Features and Sensors ## Available Features and Sensors
| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks
|-----------------------|---------|-------|---------|--------|------|---------|---------|-------- |-----------------------|---------|-------|---------|--------|------|---------|---------|--------
@ -194,6 +197,7 @@ Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/re
| USE_RC_SWITCH | - | - | - | x | x | x | x | | USE_RC_SWITCH | - | - | - | x | x | x | x |
| USE_RF_SENSOR | - | - | - | - | - | x | - | AlectoV2 only | USE_RF_SENSOR | - | - | - | - | - | x | - | AlectoV2 only
| USE_SM16716 | - | x | x | x | x | x | x | | USE_SM16716 | - | x | x | x | x | x | x |
| USE_HRE | - | - | - | - | - | x | - |
| USE_DISPLAY | - | - | - | - | - | - | x | | USE_DISPLAY | - | - | - | - | - | - | x |
| USE_DISPLAY_LCD | - | - | - | - | - | - | x | | USE_DISPLAY_LCD | - | - | - | - | - | - | x |
| USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x | | USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x |

View File

@ -1,20 +1,23 @@
# Sonoff-Tasmota Support <img src="/tools/logo/TASMOTA_FullLogo_Vector.svg" alt="Logo" align="right" height="76"/>
# Support
If you're looking for support on **Sonoff-Tasmota** there are some options available: If you're looking for support on **Sonoff-Tasmota** there are some options available:
### Documentation: ## Documentation:
* [Wiki Pages](https://github.com/arendst/Sonoff-Tasmota/wiki): For information on how to Flash Tasmota, configure and use it. * [Wiki Pages](https://github.com/arendst/Sonoff-Tasmota/wiki): For information on how to Flash Tasmota, configure and use it.
* [Troubleshooting Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting): For information on common problems and solutions. * [FAQ](https://github.com/arendst/Sonoff-Tasmota/wiki/FAQ): For information on common problems and solutions.
* [Troubleshooting Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting): For ways to debug and troubleshoot.
* [Commands Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands): For information on all the commands supported by Tasmota. * [Commands Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands): For information on all the commands supported by Tasmota.
### Support's Community: ## Support's Community:
* [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions. * [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions.
* [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community. * [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community.
* [Search in Issues](https://github.com/arendst/Sonoff-Tasmota/issues): You might find an answer to your question by searching current or closed issues. * [Search in Issues](https://github.com/arendst/Sonoff-Tasmota/issues): You might find an answer to your question by searching current or closed issues.
### Developers' Community: ## Developers' Community:
* [Bug Report](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software. * [Bug Report](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software.
* [Feature Request](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software. * [Feature Request](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software.

View File

@ -1,4 +1,7 @@
## Sonoff-Tasmota template information <img src="/tools/logo/TASMOTA_FullLogo_Vector.svg" alt="Logo" align="right" height="76"/>
# Template information
Sonoff-Tasmota uses Device or Module information to control peripherals connected to GPIOs. This information is stored in the ``sonoff_template.h`` file as a device specific template. The template contains information about what GPIO should be connected to what peripheral and what GPIO may be configured online using the ``GPIO`` command or GUI Configure Module menu. In addition a device may need specific coding to process the data from these peripherals. The module number as provided by the ``Modules`` command is used to select this coding. Sonoff-Tasmota uses Device or Module information to control peripherals connected to GPIOs. This information is stored in the ``sonoff_template.h`` file as a device specific template. The template contains information about what GPIO should be connected to what peripheral and what GPIO may be configured online using the ``GPIO`` command or GUI Configure Module menu. In addition a device may need specific coding to process the data from these peripherals. The module number as provided by the ``Modules`` command is used to select this coding.
Starting with version 6.4.1.16 Sonoff-Tasmota Modules can be extended by users online using a template. To provide easy processing by Sonoff-Tasmota a user template is written as JSON text and could look like this: Starting with version 6.4.1.16 Sonoff-Tasmota Modules can be extended by users online using a template. To provide easy processing by Sonoff-Tasmota a user template is written as JSON text and could look like this:
@ -83,4 +86,4 @@ The following command will update the flag of a stored template
``Template {"FLAG":1}`` ``Template {"FLAG":1}``
The following command will update the base of a stored template to Generic The following command will update the base of a stored template to Generic
``Template {"BASE":0}`` ``Template {"BASE":0}``

View File

@ -3,14 +3,20 @@
# ------------------------------ # ------------------------------
# For more info: # For more info:
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification
name=ESP8266 Boards (2.5.2)
version=2.5.2
# These will be removed by the packager script when doing a JSON release
name=ESP8266 Boards (2.5.0)
version=2.5.0
runtime.tools.xtensa-lx106-elf-gcc.path={runtime.platform.path}/tools/xtensa-lx106-elf
runtime.tools.esptool.path={runtime.platform.path}/tools/esptool
runtime.tools.signing={runtime.platform.path}/tools/signing.py runtime.tools.signing={runtime.platform.path}/tools/signing.py
runtime.tools.elf2bin={runtime.platform.path}/tools/elf2bin.py
runtime.tools.makecorever={runtime.platform.path}/tools/makecorever.py
runtime.tools.eboot={runtime.platform.path}/bootloaders/eboot/eboot.elf
compiler.warning_flags=-w compiler.warning_flags=-w
compiler.warning_flags.none=-w compiler.warning_flags.none=-w
@ -24,31 +30,35 @@ build.lwip_flags=-DLWIP_OPEN_SRC
build.vtable_flags=-DVTABLES_IN_FLASH build.vtable_flags=-DVTABLES_IN_FLASH
build.sslflags=
build.exception_flags=-fno-exceptions build.exception_flags=-fno-exceptions
build.stdcpp_lib=-lstdc++ build.stdcpp_lib=-lstdc++
#build.float=-u _printf_float -u _scanf_float #build.float=-u _printf_float -u _scanf_float
build.float= build.float=
build.led= build.led=
build.sdk=NONOSDK221
compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
compiler.sdk.path={runtime.platform.path}/tools/sdk compiler.sdk.path={runtime.platform.path}/tools/sdk
compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core"
compiler.c.cmd=xtensa-lx106-elf-gcc compiler.c.cmd=xtensa-lx106-elf-gcc
compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags}
compiler.S.cmd=xtensa-lx106-elf-gcc compiler.S.cmd=xtensa-lx106-elf-gcc
compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls
compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/lib/{build.sdk}" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
compiler.c.elf.cmd=xtensa-lx106-elf-gcc compiler.c.elf.cmd=xtensa-lx106-elf-gcc
compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc
compiler.cpp.cmd=xtensa-lx106-elf-g++ compiler.cpp.cmd=xtensa-lx106-elf-g++
compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags} compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags}
compiler.as.cmd=xtensa-lx106-elf-as compiler.as.cmd=xtensa-lx106-elf-as
@ -60,9 +70,6 @@ compiler.elf2hex.flags=
compiler.size.cmd=xtensa-lx106-elf-size compiler.size.cmd=xtensa-lx106-elf-size
compiler.esptool.cmd=esptool
compiler.esptool.cmd.windows=esptool.exe
# This can be overriden in boards.txt # This can be overriden in boards.txt
build.extra_flags=-DESP8266 build.extra_flags=-DESP8266
@ -77,26 +84,20 @@ compiler.elf2hex.extra_flags=
## generate file with git version number ## generate file with git version number
## needs bash, git, and echo ## needs bash, git, and echo
recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h" recipe.hooks.core.prebuild.1.pattern="{runtime.tools.python.path}/python" "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h"
recipe.hooks.core.prebuild.2.pattern=bash -c "mkdir -p {build.path}/core && echo \#define ARDUINO_ESP8266_GIT_VER 0x`git --git-dir {runtime.platform.path}/.git rev-parse --short=8 HEAD 2>/dev/null || echo ffffffff` >{build.path}/core/core_version.h"
recipe.hooks.core.prebuild.3.pattern=bash -c "mkdir -p {build.path}/core && echo \#define ARDUINO_ESP8266_GIT_DESC `cd "{runtime.platform.path}"; git describe --tags 2>/dev/null || echo unix-{version}` >>{build.path}/core/core_version.h"
## windows-compatible version without git
recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows
recipe.hooks.core.prebuild.2.pattern.windows=cmd.exe /c mkdir {build.path}\core & (echo #define ARDUINO_ESP8266_GIT_VER 0x00000000 & echo #define ARDUINO_ESP8266_GIT_DESC win-{version} ) > {build.path}\core\core_version.h
recipe.hooks.core.prebuild.3.pattern.windows=cmd.exe /c if exist {build.source.path}\public.key echo #error Cannot automatically build signed binaries on Windows > {build.path}\core\Updater_Signing.h
## Build the app.ld linker file ## Build the app.ld linker file
recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld" recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld"
## Compile c files ## Compile c files
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile c++ files ## Compile c++ files
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile S files ## Compile S files
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Create archives ## Create archives
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
@ -108,14 +109,8 @@ recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_
recipe.objcopy.eep.pattern= recipe.objcopy.eep.pattern=
## Create hex ## Create hex
#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" recipe.objcopy.hex.1.pattern="{runtime.tools.python.path}/python" "{runtime.tools.elf2bin}" --eboot "{runtime.tools.eboot}" --app "{build.path}/{build.project_name}.elf" --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size {build.flash_size} --path "{runtime.tools.xtensa-lx106-elf-gcc.path}/bin" --out "{build.path}/{build.project_name}.bin"
recipe.objcopy.hex.2.pattern="{runtime.tools.python.path}/python" "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed"
recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed"
# No signing on Windows
recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
recipe.objcopy.hex.2.pattern.windows=
## Save hex ## Save hex
recipe.output.tmp_file={build.project_name}.bin recipe.output.tmp_file={build.project_name}.bin
@ -123,22 +118,30 @@ recipe.output.save_file={build.project_name}.{build.variant}.bin
## Compute size ## Compute size
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).* recipe.size.regex=^(?:\.irom0\.text|\.text|\.text1|\.data|\.rodata|)\s+([0-9]+).*
recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).*
#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* #recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
# ------------------------------ # ------------------------------
tools.esptool.cmd=esptool tools.esptool.path=
tools.esptool.cmd.windows=esptool.exe # Because the variable expansion doesn't allow one tool to find another, the following lines
tools.esptool.path={runtime.tools.esptool.path} # will point to "{runtime.platform.path}/tools/python/python" in GIT and
tools.esptool.network_cmd=python # "{runtime.tools.python.path}/python" for JSON board manager releases.
tools.esptool.network_cmd.windows=python.exe tools.esptool.cmd={runtime.tools.python.path}/python
tools.esptool.network_cmd={runtime.tools.python.path}/python
tools.esptool.upload.protocol=esp tools.esptool.upload.protocol=esp
tools.esptool.upload.params.verbose=-vv tools.esptool.upload.params.verbose=--trace
tools.esptool.upload.params.quiet= tools.esptool.upload.params.quiet=
tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin"
# First, potentially perform an erase or nothing
# Next, do the binary upload
# Combined in one rule because Arduino doesn't suport upload.1.pattern/upload.3.pattern
tools.esptool.upload.pattern="{cmd}" "{runtime.platform.path}/tools/upload.py" --chip esp8266 --port "{serial.port}" --baud "{upload.speed}" "{upload.verbose}" {upload.erase_cmd} --end --chip esp8266 --port "{serial.port}" --baud "{upload.speed}" "{upload.verbose}" write_flash 0x0 "{build.path}/{build.project_name}.bin" --end
tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
tools.mkspiffs.cmd=mkspiffs tools.mkspiffs.cmd=mkspiffs
@ -152,4 +155,3 @@ tools.espupload.upload.protocol=espupload
tools.espupload.upload.params.verbose= tools.espupload.upload.params.verbose=
tools.espupload.upload.params.quiet= tools.espupload.upload.params.quiet=
tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin"

1
include/dummy.txt Normal file
View File

@ -0,0 +1 @@

View File

@ -37,7 +37,7 @@
//#define I2C_DEBUG //#define I2C_DEBUG
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Instantiates a new SGP30 class @brief Instantiates a new SGP30 class
*/ */
/**************************************************************************/ /**************************************************************************/
@ -45,7 +45,7 @@ Adafruit_SGP30::Adafruit_SGP30() {
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Setups the hardware and detects a valid SGP30. Initializes I2C @brief Setups the hardware and detects a valid SGP30. Initializes I2C
then reads the serialnumber and checks that we are talking to an SGP30 then reads the serialnumber and checks that we are talking to an SGP30
@param theWire Optional pointer to I2C interface, otherwise use Wire @param theWire Optional pointer to I2C interface, otherwise use Wire
@ -60,31 +60,32 @@ boolean Adafruit_SGP30::begin(TwoWire *theWire) {
_i2c = theWire; _i2c = theWire;
} }
_i2c->begin(); // assume i2c initialized already to avoid resetting clock stretching
// _i2c->begin();
uint8_t command[2]; uint8_t command[2];
command[0] = 0x36; command[0] = 0x36;
command[1] = 0x82; command[1] = 0x82;
if (! readWordFromCommand(command, 2, 10, serialnumber, 3)) if (! readWordFromCommand(command, 2, 10, serialnumber, 3))
return false; return false;
uint16_t featureset; uint16_t featureset;
command[0] = 0x20; command[0] = 0x20;
command[1] = 0x2F; command[1] = 0x2F;
if (! readWordFromCommand(command, 2, 10, &featureset, 1)) if (! readWordFromCommand(command, 2, 10, &featureset, 1))
return false; return false;
//Serial.print("Featureset 0x"); Serial.println(featureset, HEX); //Serial.print("Featureset 0x"); Serial.println(featureset, HEX);
if (featureset != SGP30_FEATURESET) if (featureset != SGP30_FEATURESET)
return false; return false;
if (! IAQinit()) if (! IAQinit())
return false; return false;
return true; return true;
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Commands the sensor to begin the IAQ algorithm. Must be called after startup. @brief Commands the sensor to begin the IAQ algorithm. Must be called after startup.
@returns True if command completed successfully, false if something went wrong! @returns True if command completed successfully, false if something went wrong!
*/ */
@ -97,7 +98,7 @@ boolean Adafruit_SGP30::IAQinit(void) {
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Commands the sensor to take a single eCO2/VOC measurement. Places results in {@link TVOC} and {@link eCO2} @brief Commands the sensor to take a single eCO2/VOC measurement. Places results in {@link TVOC} and {@link eCO2}
@returns True if command completed successfully, false if something went wrong! @returns True if command completed successfully, false if something went wrong!
*/ */
@ -113,9 +114,9 @@ boolean Adafruit_SGP30::IAQmeasure(void) {
eCO2 = reply[0]; eCO2 = reply[0];
return true; return true;
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Request baseline calibration values for both CO2 and TVOC IAQ calculations. Places results in parameter memory locaitons. @brief Request baseline calibration values for both CO2 and TVOC IAQ calculations. Places results in parameter memory locaitons.
@param eco2_base A pointer to a uint16_t which we will save the calibration value to @param eco2_base A pointer to a uint16_t which we will save the calibration value to
@param tvoc_base A pointer to a uint16_t which we will save the calibration value to @param tvoc_base A pointer to a uint16_t which we will save the calibration value to
@ -135,7 +136,7 @@ boolean Adafruit_SGP30::getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base)
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Assign baseline calibration values for both CO2 and TVOC IAQ calculations. @brief Assign baseline calibration values for both CO2 and TVOC IAQ calculations.
@param eco2_base A uint16_t which we will save the calibration value from @param eco2_base A uint16_t which we will save the calibration value from
@param tvoc_base A uint16_t which we will save the calibration value from @param tvoc_base A uint16_t which we will save the calibration value from
@ -157,7 +158,30 @@ boolean Adafruit_SGP30::setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base) {
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Set the absolute humidity value [mg/m^3] for compensation to increase precision of TVOC and eCO2.
@param absolute_humidity A uint32_t [mg/m^3] which we will be used for compensation. If the absolute humidity is set to zero, humidity compensation will be disabled.
@returns True if command completed successfully, false if something went wrong!
*/
/**************************************************************************/
boolean Adafruit_SGP30::setHumidity(uint32_t absolute_humidity) {
if (absolute_humidity > 256000) {
return false;
}
uint16_t ah_scaled = (uint16_t)(((uint64_t)absolute_humidity * 256 * 16777) >> 24);
uint8_t command[5];
command[0] = 0x20;
command[1] = 0x61;
command[2] = ah_scaled >> 8;
command[3] = ah_scaled & 0xFF;
command[4] = generateCRC(command+2, 2);
return readWordFromCommand(command, 5, 10);
}
/**************************************************************************/
/*!
@brief I2C low level interfacing @brief I2C low level interfacing
*/ */
/**************************************************************************/ /**************************************************************************/
@ -186,16 +210,16 @@ boolean Adafruit_SGP30::readWordFromCommand(uint8_t command[], uint8_t commandLe
delay(delayms); delay(delayms);
if (readlen == 0) if (readlen == 0)
return true; return true;
uint8_t replylen = readlen * (SGP30_WORD_LEN +1); uint8_t replylen = readlen * (SGP30_WORD_LEN +1);
if (_i2c->requestFrom(_i2caddr, replylen) != replylen) if (_i2c->requestFrom(_i2caddr, replylen) != replylen)
return false; return false;
uint8_t replybuffer[replylen]; uint8_t replybuffer[replylen];
#ifdef I2C_DEBUG #ifdef I2C_DEBUG
Serial.print("\t\t<- "); Serial.print("\t\t<- ");
#endif #endif
for (uint8_t i=0; i<replylen; i++) { for (uint8_t i=0; i<replylen; i++) {
replybuffer[i] = _i2c->read(); replybuffer[i] = _i2c->read();
#ifdef I2C_DEBUG #ifdef I2C_DEBUG

View File

@ -42,6 +42,7 @@ class Adafruit_SGP30 {
boolean getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base); boolean getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base);
boolean setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base); boolean setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base);
boolean setHumidity(uint32_t absolute_humidity);
/** /**
* The last measurement of the IAQ-calculated Total Volatile Organic Compounds in ppb. This value is set when you call {@link IAQmeasure()} * The last measurement of the IAQ-calculated Total Volatile Organic Compounds in ppb. This value is set when you call {@link IAQmeasure()}

View File

@ -3,6 +3,17 @@
Adafruit_SGP30 sgp; Adafruit_SGP30 sgp;
/* return absolute humidity [mg/m^3] with approximation formula
* @param temperature [°C]
* @param humidity [%RH]
*/
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
// approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
return absoluteHumidityScaled;
}
void setup() { void setup() {
Serial.begin(9600); Serial.begin(9600);
Serial.println("SGP30 test"); Serial.println("SGP30 test");
@ -22,6 +33,11 @@ void setup() {
int counter = 0; int counter = 0;
void loop() { void loop() {
// If you have a temperature / humidity sensor, you can set the absolute humidity to enable the humditiy compensation for the air quality signals
//float temperature = 22.1; // [°C]
//float humidity = 45.2; // [%RH]
//sgp.setHumidity(getAbsoluteHumidity(temperature, humidity));
if (! sgp.IAQmeasure()) { if (! sgp.IAQmeasure()) {
Serial.println("Measurement failed"); Serial.println("Measurement failed");
return; return;

View File

@ -1,5 +1,5 @@
name=Adafruit SGP30 Sensor name=Adafruit SGP30 Sensor
version=1.0.2 version=1.0.3
author=Adafruit author=Adafruit
maintainer=Adafruit <info@adafruit.com> maintainer=Adafruit <info@adafruit.com>
sentence=This is an Arduino library for the Adafruit SGP30 Gas / Air Quality Sensor sentence=This is an Arduino library for the Adafruit SGP30 Gas / Air Quality Sensor

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,17 +0,0 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,470 +0,0 @@
// Copyright 2017 David Conran
#include "IRutils.h"
#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#define __STDC_LIMIT_MACROS
#include <stdint.h>
#include <algorithm>
#ifndef ARDUINO
#include <string>
#endif
#include "IRrecv.h"
#include "IRremoteESP8266.h"
// Reverse the order of the requested least significant nr. of bits.
// Args:
// input: Bit pattern/integer to reverse.
// nbits: Nr. of bits to reverse.
// Returns:
// The reversed bit pattern.
uint64_t reverseBits(uint64_t input, uint16_t nbits) {
if (nbits <= 1) return input; // Reversing <= 1 bits makes no change at all.
// Cap the nr. of bits to rotate to the max nr. of bits in the input.
nbits = std::min(nbits, (uint16_t)(sizeof(input) * 8));
uint64_t output = 0;
for (uint16_t i = 0; i < nbits; i++) {
output <<= 1;
output |= (input & 1);
input >>= 1;
}
// Merge any remaining unreversed bits back to the top of the reversed bits.
return (input << nbits) | output;
}
// Convert a uint64_t (unsigned long long) to a string.
// Arduino String/toInt/Serial.print() can't handle printing 64 bit values.
//
// Args:
// input: The value to print
// base: The output base.
// Returns:
// A string representation of the integer.
// Note: Based on Arduino's Print::printNumber()
#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist.
String uint64ToString(uint64_t input, uint8_t base) {
String result = "";
#else
std::string uint64ToString(uint64_t input, uint8_t base) {
std::string result = "";
#endif
// prevent issues if called with base <= 1
if (base < 2) base = 10;
// Check we have a base that we can actually print.
// i.e. [0-9A-Z] == 36
if (base > 36) base = 10;
do {
char c = input % base;
input /= base;
if (c < 10)
c += '0';
else
c += 'A' - 10;
result = c + result;
} while (input);
return result;
}
#ifdef ARDUINO
// Print a uint64_t/unsigned long long to the Serial port
// Serial.print() can't handle printing long longs. (uint64_t)
//
// Args:
// input: The value to print
// base: The output base.
void serialPrintUint64(uint64_t input, uint8_t base) {
Serial.print(uint64ToString(input, base));
}
#endif
// Convert a protocol type (enum etc) to a human readable string.
// Args:
// protocol: Nr. (enum) of the protocol.
// isRepeat: A flag indicating if it is a repeat message of the protocol.
// Returns:
// A string containing the protocol name.
#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist.
String typeToString(const decode_type_t protocol, const bool isRepeat) {
String result = "";
#else
std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
std::string result = "";
#endif
switch (protocol) {
default:
case UNKNOWN:
result = "UNKNOWN";
break;
case UNUSED:
result = "UNUSED";
break;
case AIWA_RC_T501:
result = "AIWA_RC_T501";
break;
case ARGO:
result = "ARGO";
break;
case CARRIER_AC:
result = "CARRIER_AC";
break;
case COOLIX:
result = "COOLIX";
break;
case DAIKIN:
result = "DAIKIN";
break;
case DENON:
result = "DENON";
break;
case DISH:
result = "DISH";
break;
case ELECTRA_AC:
result = "ELECTRA_AC";
break;
case FUJITSU_AC:
result = "FUJITSU_AC";
break;
case GICABLE:
result = "GICABLE";
break;
case GLOBALCACHE:
result = "GLOBALCACHE";
break;
case GREE:
result = "GREE";
break;
case HAIER_AC:
result = "HAIER_AC";
break;
case HAIER_AC_YRW02:
result = "HAIER_AC_YRW02";
break;
case HITACHI_AC:
result = "HITACHI_AC";
break;
case HITACHI_AC1:
result = "HITACHI_AC1";
break;
case HITACHI_AC2:
result = "HITACHI_AC2";
break;
case JVC:
result = "JVC";
break;
case KELVINATOR:
result = "KELVINATOR";
break;
case LG:
result = "LG";
break;
case LG2:
result = "LG2";
break;
case LASERTAG:
result = "LASERTAG";
break;
case LUTRON:
result = "LUTRON";
break;
case MAGIQUEST:
result = "MAGIQUEST";
break;
case MIDEA:
result = "MIDEA";
break;
case MITSUBISHI:
result = "MITSUBISHI";
break;
case MITSUBISHI2:
result = "MITSUBISHI2";
break;
case MITSUBISHI_AC:
result = "MITSUBISHI_AC";
break;
case MWM:
result = "MWM";
break;
case NEC:
result = "NEC";
break;
case NEC_LIKE:
result = "NEC (non-strict)";
break;
case NIKAI:
result = "NIKAI";
break;
case PANASONIC:
result = "PANASONIC";
break;
case PANASONIC_AC:
result = "PANASONIC_AC";
break;
case PIONEER:
result = "PIONEER";
break;
case PRONTO:
result = "PRONTO";
break;
case RAW:
result = "RAW";
break;
case RC5:
result = "RC5";
break;
case RC5X:
result = "RC5X";
break;
case RC6:
result = "RC6";
break;
case RCMM:
result = "RCMM";
break;
case SAMSUNG:
result = "SAMSUNG";
break;
case SAMSUNG_AC:
result = "SAMSUNG_AC";
break;
case SANYO:
result = "SANYO";
break;
case SANYO_LC7461:
result = "SANYO_LC7461";
break;
case SHARP:
result = "SHARP";
break;
case SHERWOOD:
result = "SHERWOOD";
break;
case SONY:
result = "SONY";
break;
case TOSHIBA_AC:
result = "TOSHIBA_AC";
break;
case TROTEC:
result = "TROTEC";
break;
case WHIRLPOOL_AC:
result = "WHIRLPOOL_AC";
break;
case WHYNTER:
result = "WHYNTER";
break;
}
if (isRepeat) result += " (Repeat)";
return result;
}
// Does the given protocol use a complex state as part of the decode?
bool hasACState(const decode_type_t protocol) {
switch (protocol) {
case DAIKIN:
case ELECTRA_AC:
case FUJITSU_AC:
case GREE:
case HAIER_AC:
case HAIER_AC_YRW02:
case HITACHI_AC:
case HITACHI_AC1:
case HITACHI_AC2:
case KELVINATOR:
case MITSUBISHI_AC:
case MWM:
case PANASONIC_AC:
case SAMSUNG_AC:
case TOSHIBA_AC:
case WHIRLPOOL_AC:
return true;
default:
return false;
}
}
// Return the corrected length of a 'raw' format array structure
// after over-large values are converted into multiple entries.
// Args:
// results: A ptr to a decode result.
// Returns:
// A uint16_t containing the length.
uint16_t getCorrectedRawLength(const decode_results *results) {
uint16_t extended_length = results->rawlen - 1;
for (uint16_t i = 0; i < results->rawlen - 1; i++) {
uint32_t usecs = results->rawbuf[i] * kRawTick;
// Add two extra entries for multiple larger than UINT16_MAX it is.
extended_length += (usecs / (UINT16_MAX + 1)) * 2;
}
return extended_length;
}
// Return a string containing the key values of a decode_results structure
// in a C/C++ code style format.
#ifdef ARDUINO
String resultToSourceCode(const decode_results *results) {
String output = "";
#else
std::string resultToSourceCode(const decode_results *results) {
std::string output = "";
#endif
// Start declaration
output += "uint16_t "; // variable type
output += "rawData["; // array name
output += uint64ToString(getCorrectedRawLength(results), 10);
// array size
output += "] = {"; // Start declaration
// Dump data
for (uint16_t i = 1; i < results->rawlen; i++) {
uint32_t usecs;
for (usecs = results->rawbuf[i] * kRawTick; usecs > UINT16_MAX;
usecs -= UINT16_MAX) {
output += uint64ToString(UINT16_MAX);
if (i % 2)
output += ", 0, ";
else
output += ", 0, ";
}
output += uint64ToString(usecs, 10);
if (i < results->rawlen - 1)
output += ", "; // ',' not needed on the last one
if (i % 2 == 0) output += " "; // Extra if it was even.
}
// End declaration
output += "};";
// Comment
output += " // " + typeToString(results->decode_type, results->repeat);
// Only display the value if the decode type doesn't have an A/C state.
if (!hasACState(results->decode_type))
output += " " + uint64ToString(results->value, 16);
output += "\n";
// Now dump "known" codes
if (results->decode_type != UNKNOWN) {
if (hasACState(results->decode_type)) {
#if DECODE_AC
uint16_t nbytes = results->bits / 8;
output += "uint8_t state[" + uint64ToString(nbytes) + "] = {";
for (uint16_t i = 0; i < nbytes; i++) {
output += "0x";
if (results->state[i] < 0x10) output += "0";
output += uint64ToString(results->state[i], 16);
if (i < nbytes - 1) output += ", ";
}
output += "};\n";
#endif // DECODE_AC
} else {
// Simple protocols
// Some protocols have an address &/or command.
// NOTE: It will ignore the atypical case when a message has been
// decoded but the address & the command are both 0.
if (results->address > 0 || results->command > 0) {
output += "uint32_t address = 0x" +
uint64ToString(results->address, 16) + ";\n";
output += "uint32_t command = 0x" +
uint64ToString(results->command, 16) + ";\n";
}
// Most protocols have data
output +=
"uint64_t data = 0x" + uint64ToString(results->value, 16) + ";\n";
}
}
return output;
}
// Dump out the decode_results structure.
//
#ifdef ARDUINO
String resultToTimingInfo(const decode_results *results) {
String output = "";
String value = "";
#else
std::string resultToTimingInfo(const decode_results *results) {
std::string output = "";
std::string value = "";
#endif
output += "Raw Timing[" + uint64ToString(results->rawlen - 1, 10) + "]:\n";
for (uint16_t i = 1; i < results->rawlen; i++) {
if (i % 2 == 0)
output += "-"; // even
else
output += " +"; // odd
value = uint64ToString(results->rawbuf[i] * kRawTick);
// Space pad the value till it is at least 6 chars long.
while (value.length() < 6) value = " " + value;
output += value;
if (i < results->rawlen - 1) output += ", "; // ',' not needed for last one
if (!(i % 8)) output += "\n"; // Newline every 8 entries.
}
output += "\n";
return output;
}
// Convert the decode_results structure's value/state to simple hexadecimal.
//
#ifdef ARDUINO
String resultToHexidecimal(const decode_results *result) {
String output = "";
#else
std::string resultToHexidecimal(const decode_results *result) {
std::string output = "";
#endif
if (hasACState(result->decode_type)) {
#if DECODE_AC
for (uint16_t i = 0; result->bits > i * 8; i++) {
if (result->state[i] < 0x10) output += "0"; // Zero pad
output += uint64ToString(result->state[i], 16);
}
#endif // DECODE_AC
} else {
output += uint64ToString(result->value, 16);
}
return output;
}
// Dump out the decode_results structure.
//
#ifdef ARDUINO
String resultToHumanReadableBasic(const decode_results *results) {
String output = "";
#else
std::string resultToHumanReadableBasic(const decode_results *results) {
std::string output = "";
#endif
// Show Encoding standard
output +=
"Encoding : " + typeToString(results->decode_type, results->repeat) +
"\n";
// Show Code & length
output += "Code : ";
output += resultToHexidecimal(results);
output += " (" + uint64ToString(results->bits) + " bits)\n";
return output;
}
uint8_t sumBytes(uint8_t *start, const uint16_t length, const uint8_t init) {
uint8_t checksum = init;
uint8_t *ptr;
for (ptr = start; ptr - start < length; ptr++) checksum += *ptr;
return checksum;
}
uint64_t invertBits(const uint64_t data, const uint16_t nbits) {
// No change if we are asked to invert no bits.
if (nbits == 0) return data;
uint64_t result = ~data;
// If we are asked to invert all the bits or more than we have, it's simple.
if (nbits >= sizeof(data) * 8) return result;
// Mask off any unwanted bits and return the result.
return (result & ((1ULL << nbits) - 1));
}

View File

@ -1,750 +0,0 @@
/*
An Arduino sketch to emulate IR Daikin ARC433** remote control unit
Read more at:
http://harizanov.com/2012/02/control-daikin-air-conditioner-over-the-internet/
Copyright 2016 sillyfrog
Copyright 2017 sillyfrog, crankyoldgit
*/
#include "ir_Daikin.h"
#include <algorithm>
#ifndef ARDUINO
#include <string>
#endif
#include "IRrecv.h"
#include "IRremoteESP8266.h"
#include "IRsend.h"
#include "IRutils.h"
// DDDDD AAA IIIII KK KK IIIII NN NN
// DD DD AAAAA III KK KK III NNN NN
// DD DD AA AA III KKKK III NN N NN
// DD DD AAAAAAA III KK KK III NN NNN
// DDDDDD AA AA IIIII KK KK IIIII NN NN
// Constants
// Ref:
// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
// http://rdlab.cdmt.vn/project-2013/daikin-ir-protocol
#if SEND_DAIKIN
// Original header
// static uint8_t header1[DAIKIN_HEADER1_LENGTH];
// header1[0] = 0b00010001;
// header1[1] = 0b11011010;
// header1[2] = 0b00100111;
// header1[3] = 0b00000000;
// header1[4] = 0b11000101;
// header1[5] = 0b00000000;
// header1[6] = 0b00000000;
// header1[7] = 0b11010111;
// Send a Daikin A/C message.
//
// Args:
// data: An array of kDaikinStateLength bytes containing the IR command.
//
// Status: STABLE
//
// Ref:
// IRDaikinESP.cpp
// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
void IRsend::sendDaikin(unsigned char data[], uint16_t nbytes,
uint16_t repeat) {
if (nbytes < kDaikinStateLength)
return; // Not enough bytes to send a proper message.
for (uint16_t r = 0; r <= repeat; r++) {
// Send the header, 0b00000
sendGeneric(0, 0, // No header for the header
kDaikinBitMark, kDaikinOneSpace, kDaikinBitMark,
kDaikinZeroSpace, kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
(uint64_t)0b00000, 5, 38, false, 0, 50);
// Leading header
// Do this as a constant to save RAM and keep in flash memory
sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
kDaikinBitMark, kDaikinZeroSpace + kDaikinGap,
kDaikinFirstHeader64, 64, 38, false, 0, 50);
// Data #1
sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, data, 8, 38,
false, 0, 50);
// Data #2
sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark,
kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace,
kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, data + 8,
nbytes - 8, 38, false, 0, 50);
}
}
#endif // SEND_DAIKIN
IRDaikinESP::IRDaikinESP(uint16_t pin) : _irsend(pin) { stateReset(); }
void IRDaikinESP::begin() { _irsend.begin(); }
#if SEND_DAIKIN
void IRDaikinESP::send() {
checksum();
_irsend.sendDaikin(daikin);
}
#endif // SEND_DAIKIN
// Calculate the checksum for a given data block.
// Args:
// block: Ptr to the start of the data block.
// length: Nr. of bytes to checksum.
// Returns:
// A byte containing the calculated checksum.
uint8_t IRDaikinESP::calcBlockChecksum(const uint8_t *block,
const uint16_t length) {
uint8_t sum = 0;
// Daikin checksum is just the addition of all the data bytes
// in the block but capped to 8 bits.
for (uint16_t i = 0; i < length; i++, block++) sum += *block;
return sum & 0xFFU;
}
// Verify the checksum is valid for a given state.
// Args:
// state: The array to verify the checksum of.
// length: The size of the state.
// Returns:
// A boolean.
bool IRDaikinESP::validChecksum(const uint8_t state[], const uint16_t length) {
if (length < 8 || state[7] != calcBlockChecksum(state, 7)) return false;
if (length < 10 ||
state[length - 1] != calcBlockChecksum(state + 8, length - 9))
return false;
return true;
}
// Calculate and set the checksum values for the internal state.
void IRDaikinESP::checksum() {
daikin[7] = calcBlockChecksum(daikin, 7);
daikin[26] = calcBlockChecksum(daikin + 8, 17);
}
void IRDaikinESP::stateReset() {
for (uint8_t i = 0; i < kDaikinStateLength; i++) daikin[i] = 0x0;
daikin[0] = 0x11;
daikin[1] = 0xDA;
daikin[2] = 0x27;
daikin[4] = 0x42;
// daikin[7] is a checksum byte, it will be set by checksum().
daikin[8] = 0x11;
daikin[9] = 0xDA;
daikin[10] = 0x27;
daikin[13] = 0x49;
daikin[14] = 0x1E;
daikin[16] = 0xB0;
daikin[19] = 0x06;
daikin[20] = 0x60;
daikin[23] = 0xC0;
// daikin[26] is a checksum byte, it will be set by checksum().
checksum();
}
uint8_t *IRDaikinESP::getRaw() {
checksum(); // Ensure correct settings before sending.
return daikin;
}
void IRDaikinESP::setRaw(uint8_t new_code[]) {
for (uint8_t i = 0; i < kDaikinStateLength; i++) daikin[i] = new_code[i];
}
void IRDaikinESP::on() {
// state = ON;
setBit(kDaikinBytePower, kDaikinBitPower);
}
void IRDaikinESP::off() {
// state = OFF;
clearBit(kDaikinBytePower, kDaikinBitPower);
}
void IRDaikinESP::setPower(bool state) {
if (state)
on();
else
off();
}
bool IRDaikinESP::getPower() {
return (getBit(kDaikinBytePower, kDaikinBitPower) > 0);
}
// Set the temp in deg C
void IRDaikinESP::setTemp(uint8_t temp) {
if (temp < kDaikinMinTemp)
temp = kDaikinMinTemp;
else if (temp > kDaikinMaxTemp)
temp = kDaikinMaxTemp;
daikin[14] = temp * 2;
}
uint8_t IRDaikinESP::getTemp() { return daikin[14] / 2; }
// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet
void IRDaikinESP::setFan(uint8_t fan) {
// Set the fan speed bits, leave low 4 bits alone
uint8_t fanset;
if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto)
fanset = fan;
else if (fan < kDaikinFanMin || fan > kDaikinFanMax)
fanset = kDaikinFanAuto;
else
fanset = 2 + fan;
daikin[16] &= 0x0F;
daikin[16] |= (fanset << 4);
}
uint8_t IRDaikinESP::getFan() {
uint8_t fan = daikin[16] >> 4;
if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2;
return fan;
}
uint8_t IRDaikinESP::getMode() {
/*
kDaikinCool
kDaikinHeat
kDaikinFan
kDaikinAuto
kDaikinDry
*/
return daikin[13] >> 4;
}
void IRDaikinESP::setMode(uint8_t mode) {
switch (mode) {
case kDaikinCool:
case kDaikinHeat:
case kDaikinFan:
case kDaikinDry:
break;
default:
mode = kDaikinAuto;
}
mode <<= 4;
daikin[13] &= 0b10001111;
daikin[13] |= mode;
}
void IRDaikinESP::setSwingVertical(bool state) {
if (state)
daikin[16] |= 0x0F;
else
daikin[16] &= 0xF0;
}
bool IRDaikinESP::getSwingVertical() { return daikin[16] & 0x01; }
void IRDaikinESP::setSwingHorizontal(bool state) {
if (state)
daikin[17] |= 0x0F;
else
daikin[17] &= 0xF0;
}
bool IRDaikinESP::getSwingHorizontal() { return daikin[17] & 0x01; }
void IRDaikinESP::setQuiet(bool state) {
if (state) {
setBit(kDaikinByteSilent, kDaikinBitSilent);
// Powerful & Quiet mode being on are mutually exclusive.
setPowerful(false);
} else {
clearBit(kDaikinByteSilent, kDaikinBitSilent);
}
}
bool IRDaikinESP::getQuiet() {
return (getBit(kDaikinByteSilent, kDaikinBitSilent) > 0);
}
void IRDaikinESP::setPowerful(bool state) {
if (state) {
setBit(kDaikinBytePowerful, kDaikinBitPowerful);
// Powerful, Quiet, & Econo mode being on are mutually exclusive.
setQuiet(false);
setEcono(false);
} else {
clearBit(kDaikinBytePowerful, kDaikinBitPowerful);
}
}
bool IRDaikinESP::getPowerful() {
return (getBit(kDaikinBytePowerful, kDaikinBitPowerful) > 0);
}
void IRDaikinESP::setSensor(bool state) {
if (state)
setBit(kDaikinByteSensor, kDaikinBitSensor);
else
clearBit(kDaikinByteSensor, kDaikinBitSensor);
}
bool IRDaikinESP::getSensor() {
return (getBit(kDaikinByteSensor, kDaikinBitSensor) > 0);
}
void IRDaikinESP::setEcono(bool state) {
if (state) {
setBit(kDaikinByteEcono, kDaikinBitEcono);
// Powerful & Econo mode being on are mutually exclusive.
setPowerful(false);
} else {
clearBit(kDaikinByteEcono, kDaikinBitEcono);
}
}
bool IRDaikinESP::getEcono() {
return (getBit(kDaikinByteEcono, kDaikinBitEcono) > 0);
}
void IRDaikinESP::setEye(bool state) {
if (state)
setBit(kDaikinByteEye, kDaikinBitEye);
else
clearBit(kDaikinByteEye, kDaikinBitEye);
}
bool IRDaikinESP::getEye() {
return (getBit(kDaikinByteEye, kDaikinBitEye) > 0);
}
void IRDaikinESP::setMold(bool state) {
if (state)
setBit(kDaikinByteMold, kDaikinBitMold);
else
clearBit(kDaikinByteMold, kDaikinBitMold);
}
bool IRDaikinESP::getMold() {
return (getBit(kDaikinByteMold, kDaikinBitMold) > 0);
}
void IRDaikinESP::setBit(uint8_t byte, uint8_t bitmask) {
daikin[byte] |= bitmask;
}
void IRDaikinESP::clearBit(uint8_t byte, uint8_t bitmask) {
bitmask = ~bitmask;
daikin[byte] &= bitmask;
}
uint8_t IRDaikinESP::getBit(uint8_t byte, uint8_t bitmask) {
return daikin[byte] & bitmask;
}
// starttime: Number of minutes after midnight, in 10 minutes increments
void IRDaikinESP::enableOnTimer(uint16_t starttime) {
setBit(kDaikinByteOnTimer, kDaikinBitOnTimer);
daikin[18] = (uint8_t)(starttime & 0x00FF);
// only keep 4 bits
daikin[19] &= 0xF0;
daikin[19] |= (uint8_t)((starttime >> 8) & 0x0F);
}
void IRDaikinESP::disableOnTimer() {
enableOnTimer(0x600);
clearBit(kDaikinByteOnTimer, kDaikinBitOnTimer);
}
uint16_t IRDaikinESP::getOnTime() {
uint16_t ret;
ret = daikin[19] & 0x0F;
ret = ret << 8;
ret += daikin[18];
return ret;
}
bool IRDaikinESP::getOnTimerEnabled() {
return getBit(kDaikinByteOnTimer, kDaikinBitOnTimer);
}
// endtime: Number of minutes after midnight, in 10 minutes increments
void IRDaikinESP::enableOffTimer(uint16_t endtime) {
setBit(kDaikinByteOffTimer, kDaikinBitOffTimer);
daikin[20] = (uint8_t)((endtime >> 4) & 0xFF);
daikin[19] &= 0x0F;
daikin[19] |= (uint8_t)((endtime & 0x000F) << 4);
}
void IRDaikinESP::disableOffTimer() {
enableOffTimer(0x600);
clearBit(kDaikinByteOffTimer, kDaikinBitOffTimer);
}
uint16_t IRDaikinESP::getOffTime() {
uint16_t ret, tmp;
ret = daikin[20];
ret <<= 4;
tmp = daikin[19] & 0xF0;
tmp >>= 4;
ret += tmp;
return ret;
}
bool IRDaikinESP::getOffTimerEnabled() {
return getBit(kDaikinByteOffTimer, kDaikinBitOffTimer);
}
void IRDaikinESP::setCurrentTime(uint16_t numMins) {
if (numMins > 24 * 60) numMins = 0; // If > 23:59, set to 00:00
daikin[5] = (uint8_t)(numMins & 0x00FF);
// only keep 4 bits
daikin[6] &= 0xF0;
daikin[6] |= (uint8_t)((numMins >> 8) & 0x0F);
}
uint16_t IRDaikinESP::getCurrentTime() {
uint16_t ret;
ret = daikin[6] & 0x0F;
ret <<= 8;
ret += daikin[5];
return ret;
}
#ifdef ARDUINO
String IRDaikinESP::renderTime(uint16_t timemins) {
String ret;
#else // ARDUINO
std::string IRDaikinESP::renderTime(uint16_t timemins) {
std::string ret;
#endif // ARDUINO
uint16_t hours, mins;
hours = timemins / 60;
ret = uint64ToString(hours) + ":";
mins = timemins - (hours * 60);
if (mins < 10) ret += "0";
ret += uint64ToString(mins);
return ret;
}
// Convert the internal state into a human readable string.
#ifdef ARDUINO
String IRDaikinESP::toString() {
String result = "";
#else // ARDUINO
std::string IRDaikinESP::toString() {
std::string result = "";
#endif // ARDUINO
result += "Power: ";
if (getPower())
result += "On";
else
result += "Off";
result += ", Mode: " + uint64ToString(getMode());
switch (getMode()) {
case kDaikinAuto:
result += " (AUTO)";
break;
case kDaikinCool:
result += " (COOL)";
break;
case kDaikinHeat:
result += " (HEAT)";
break;
case kDaikinDry:
result += " (DRY)";
break;
case kDaikinFan:
result += " (FAN)";
break;
default:
result += " (UNKNOWN)";
}
result += ", Temp: " + uint64ToString(getTemp()) + "C";
result += ", Fan: " + uint64ToString(getFan());
switch (getFan()) {
case kDaikinFanAuto:
result += " (AUTO)";
break;
case kDaikinFanQuiet:
result += " (QUIET)";
break;
case kDaikinFanMin:
result += " (MIN)";
break;
case kDaikinFanMax:
result += " (MAX)";
break;
}
result += ", Powerful: ";
if (getPowerful())
result += "On";
else
result += "Off";
result += ", Quiet: ";
if (getQuiet())
result += "On";
else
result += "Off";
result += ", Sensor: ";
if (getSensor())
result += "On";
else
result += "Off";
result += ", Eye: ";
if (getEye())
result += "On";
else
result += "Off";
result += ", Mold: ";
if (getMold())
result += "On";
else
result += "Off";
result += ", Swing (Horizontal): ";
if (getSwingHorizontal())
result += "On";
else
result += "Off";
result += ", Swing (Vertical): ";
if (getSwingVertical())
result += "On";
else
result += "Off";
result += ", Current Time: " + renderTime(getCurrentTime());
result += ", On Time: ";
if (getOnTimerEnabled())
result += renderTime(getOnTime());
else
result += "Off";
result += ", Off Time: ";
if (getOffTimerEnabled())
result += renderTime(getOffTime());
else
result += "Off";
return result;
}
#if DAIKIN_DEBUG
// Print what we have
void IRDaikinESP::printState() {
#ifdef ARDUINO
String strbits;
#else // ARDUINO
std::string strbits;
#endif // ARDUINO
DPRINTLN("Raw Bits:");
for (uint8_t i = 0; i < kDaikinStateLength; i++) {
strbits = uint64ToString(daikin[i], BIN);
while (strbits.length() < 8) strbits = "0" + strbits;
DPRINT(strbits);
DPRINT(" ");
}
DPRINTLN("");
DPRINTLN(toString());
}
#endif // DAIKIN_DEBUG
/*
* Return most important bits to allow replay
* layout is:
* 0: Power
* 1-3: Mode
* 4-7: Fan speed/mode
* 8-14: Target Temperature
* 15: Econo
* 16: Powerful
* 17: Quiet
* 18: Sensor
* 19: Swing Vertical
* 20-31: Current time (mins since midnight)
* */
uint32_t IRDaikinESP::getCommand() {
uint32_t ret = 0;
uint32_t tmp = 0;
if (getPower()) ret |= 0b00000000000000000000000000000001;
tmp = getMode();
tmp = tmp << 1;
ret |= tmp;
tmp = getFan();
tmp <<= 4;
ret |= tmp;
tmp = getTemp();
tmp <<= 8;
ret |= tmp;
if (getEcono()) ret |= 0b00000000000000001000000000000000;
if (getPowerful()) ret |= 0b00000000000000010000000000000000;
if (getQuiet()) ret |= 0b00000000000000100000000000000000;
if (getSensor()) ret |= 0b00000000000001000000000000000000;
if (getSwingVertical()) ret |= 0b00000000000010000000000000000000;
ret |= (getCurrentTime() << 20);
return ret;
}
void IRDaikinESP::setCommand(uint32_t value) {
uint32_t tmp = 0;
if (value & 0b00000000000000000000000000000001) setPower(true);
tmp = value & 0b00000000000000000000000000001110;
tmp >>= 1;
setMode(tmp);
tmp = value & 0b00000000000000000000000011110000;
tmp >>= 4;
setFan(tmp);
tmp = value & 0b00000000000000000111111100000000;
tmp >>= 8;
setTemp(tmp);
if (value & 0b00000000000000001000000000000000) setEcono(true);
if (value & 0b00000000000000010000000000000000) setPowerful(true);
if (value & 0b00000000000000100000000000000000) setQuiet(true);
if (value & 0b00000000000001000000000000000000) setSensor(true);
if (value & 0b00000000000010000000000000000000) setSwingVertical(true);
value >>= 20;
setCurrentTime(value);
}
#if DECODE_DAIKIN
void addbit(bool val, unsigned char data[]) {
uint8_t curbit = data[kDaikinCurBit];
uint8_t curindex = data[kDaikinCurIndex];
if (val) {
unsigned char bit = 1;
bit = bit << curbit;
data[curindex] |= bit;
}
curbit++;
if (curbit == 8) {
curbit = 0;
curindex++;
}
data[kDaikinCurBit] = curbit;
data[kDaikinCurIndex] = curindex;
}
bool checkheader(decode_results *results, uint16_t *offset) {
if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinBitMark,
kDaikinTolerance, kDaikinMarkExcess))
return false;
if (!IRrecv::matchSpace(results->rawbuf[(*offset)++],
kDaikinZeroSpace + kDaikinGap, kDaikinTolerance,
kDaikinMarkExcess))
return false;
if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinHdrMark,
kDaikinTolerance, kDaikinMarkExcess))
return false;
if (!IRrecv::matchSpace(results->rawbuf[(*offset)++], kDaikinHdrSpace,
kDaikinTolerance, kDaikinMarkExcess))
return false;
return true;
}
bool readbits(decode_results *results, uint16_t *offset,
unsigned char daikin_code[], uint16_t countbits) {
for (uint16_t i = 0; i < countbits && *offset < results->rawlen - 1;
i++, (*offset)++) {
if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinBitMark,
kDaikinTolerance, kDaikinMarkExcess))
return false;
if (IRrecv::matchSpace(results->rawbuf[*offset], kDaikinOneSpace,
kDaikinTolerance, kDaikinMarkExcess))
addbit(1, daikin_code);
else if (IRrecv::matchSpace(results->rawbuf[*offset], kDaikinZeroSpace,
kDaikinTolerance, kDaikinMarkExcess))
addbit(0, daikin_code);
else
return false;
}
return true;
}
// Decode the supplied Daikin A/C message.
// Args:
// results: Ptr to the data to decode and where to store the decode result.
// nbits: Nr. of bits to expect in the data portion. (kDaikinRawBits)
// strict: Flag to indicate if we strictly adhere to the specification.
// Returns:
// boolean: True if it can decode it, false if it can't.
//
// Status: BETA / Should be working.
//
// Notes:
// If DAIKIN_DEBUG enabled, will print all the set options and values.
//
// Ref:
// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote
bool IRrecv::decodeDaikin(decode_results *results, uint16_t nbits,
bool strict) {
if (results->rawlen < kDaikinRawBits) return false;
// Compliance
if (strict && nbits != kDaikinRawBits) return false;
uint16_t offset = kStartOffset;
unsigned char daikin_code[kDaikinStateLength + 2];
for (uint8_t i = 0; i < kDaikinStateLength + 2; i++) daikin_code[i] = 0;
// Header (#1)
for (uint8_t i = 0; i < 10; i++) {
if (!matchMark(results->rawbuf[offset++], kDaikinBitMark)) return false;
}
if (!checkheader(results, &offset)) return false;
// Data (#1)
if (!readbits(results, &offset, daikin_code, 8 * 8)) return false;
// Ignore everything that has just been captured as it is not needed.
// Some remotes may not send this portion, my remote did, but it's not
// required.
for (uint8_t i = 0; i < kDaikinStateLength + 2; i++) daikin_code[i] = 0;
// Header (#2)
if (!checkheader(results, &offset)) return false;
// Data (#2)
if (!readbits(results, &offset, daikin_code, 8 * 8)) return false;
// Header (#3)
if (!checkheader(results, &offset)) return false;
// Data (#3), read up everything else
if (!readbits(results, &offset, daikin_code, kDaikinBits - (8 * 8)))
return false;
// Footer
if (!matchMark(results->rawbuf[offset++], kDaikinBitMark)) return false;
if (offset < results->rawlen &&
!matchAtLeast(results->rawbuf[offset], kDaikinGap))
return false;
// Compliance
if (strict) {
if (!IRDaikinESP::validChecksum(daikin_code)) return false;
}
// Success
#if DAIKIN_DEBUG
IRDaikinESP dako = IRDaikinESP(0);
dako.setRaw(daikin_code);
#ifdef ARDUINO
yield();
#endif // ARDUINO
dako.printState();
#endif // DAIKIN_DEBUG
// Copy across the bits to state
for (uint8_t i = 0; i < kDaikinStateLength; i++)
results->state[i] = daikin_code[i];
results->bits = kDaikinStateLength * 8;
results->decode_type = DAIKIN;
return true;
}
#endif // DECODE_DAIKIN

View File

@ -1,208 +0,0 @@
// Copyright 2016 sillyfrog
// Copyright 2017 sillyfrog, crankyoldgit
#ifndef IR_DAIKIN_H_
#define IR_DAIKIN_H_
#ifndef UNIT_TEST
#include <Arduino.h>
#else
#include <string>
#endif
#include "IRrecv.h"
#include "IRremoteESP8266.h"
#include "IRsend.h"
// Option to disable the additional Daikin debug info to conserve memory
#define DAIKIN_DEBUG false
// DDDDD AAA IIIII KK KK IIIII NN NN
// DD DD AAAAA III KK KK III NNN NN
// DD DD AA AA III KKKK III NN N NN
// DD DD AAAAAAA III KK KK III NN NNN
// DDDDDD AA AA IIIII KK KK IIIII NN NN
/*
Daikin AC map
byte 5=Current time, mins past midnight, low bits
byte 6
b0-b3=Current time, mins past midnight, high bits
byte 7= checksum of the first part (and last byte before a 29ms pause)
byte 13=mode
b7 = 0
b6+b5+b4 = Mode
Modes: b6+b5+b4
011 = Cool
100 = Heat (temp 23)
110 = FAN (temp not shown, but 25)
000 = Fully Automatic (temp 25)
010 = DRY (temp 0xc0 = 96 degrees c)
b3 = 1
b2 = OFF timer set
b1 = ON timer set
b0 = Air Conditioner ON
byte 14=temp*2 (Temp should be between 10 - 32)
byte 16=Fan
FAN control
b7+b6+b5+b4 = Fan speed
Fan: b7+b6+b5+b4
0×3 = 1 bar
0×4 = 2 bar
0×5 = 3 bar
0×6 = 4 bar
0×7 = 5 bar
0xa = Auto
0xb = Quite
b3+b2+b1+b0 = Swing control up/down
Swing control up/down:
0000 = Swing up/down off
1111 = Swing up/down on
byte 17
Swing control left/right:
0000 = Swing left/right off
1111 = Swing left/right on
byte 18=On timer mins past midnight, low bits
byte 19
b0-b3=On timer mins past midnight, high bits
b4-b7=Off timer mins past midnight, low bits
byte 20=Off timer mins past midnight, high bits
byte 21=Aux -> Powerful (bit 1), Silent (bit 5)
byte 24=Aux2
b1: Sensor
b2: Econo mode
b7: Intelligent eye on
byte 25=Aux3
b1: Mold Proof
byte 26= checksum of the second part
*/
// Constants
const uint8_t kDaikinAuto = 0b000;
const uint8_t kDaikinDry = 0b010;
const uint8_t kDaikinCool = 0b011;
const uint8_t kDaikinHeat = 0b100;
const uint8_t kDaikinFan = 0b110;
const uint8_t kDaikinMinTemp = 10; // Celsius
const uint8_t kDaikinMaxTemp = 32; // Celsius
const uint8_t kDaikinFanMin = 1;
const uint8_t kDaikinFanMax = 5;
const uint8_t kDaikinFanAuto = 0b1010;
const uint8_t kDaikinFanQuiet = 0b1011;
const uint8_t kDaikinBytePower = 13;
const uint8_t kDaikinBitPower = 0b00000001;
const uint8_t kDaikinBytePowerful = 21;
const uint8_t kDaikinBitPowerful = 0b00000001;
const uint8_t kDaikinByteSilent = 21;
const uint8_t kDaikinBitSilent = 0b00100000;
const uint8_t kDaikinByteSensor = 24;
const uint8_t kDaikinBitSensor = 0b00000010;
const uint8_t kDaikinByteEcono = 24;
const uint8_t kDaikinBitEcono = 0b00000100;
const uint8_t kDaikinByteEye = 24;
const uint8_t kDaikinBitEye = 0b10000000;
const uint8_t kDaikinByteMold = 25;
const uint8_t kDaikinBitMold = 0b00000010;
const uint8_t kDaikinByteOffTimer = 13;
const uint8_t kDaikinBitOffTimer = 0b00000100;
const uint8_t kDaikinByteOnTimer = 13;
const uint8_t kDaikinBitOnTimer = 0b00000010;
const uint8_t kDaikinCurBit = kDaikinStateLength;
const uint8_t kDaikinCurIndex = kDaikinStateLength + 1;
const uint8_t kDaikinTolerance = 35;
const uint16_t kDaikinMarkExcess = kMarkExcess;
const uint16_t kDaikinHdrMark = 3650; // kDaikinBitMark * 8
const uint16_t kDaikinHdrSpace = 1623; // kDaikinBitMark * 4
const uint16_t kDaikinBitMark = 428;
const uint16_t kDaikinZeroSpace = 428;
const uint16_t kDaikinOneSpace = 1280;
const uint16_t kDaikinGap = 29000;
// Note bits in each octet swapped so can be sent as a single value
const uint64_t kDaikinFirstHeader64 =
0b1101011100000000000000001100010100000000001001111101101000010001;
// Legacy defines.
#define DAIKIN_COOL kDaikinCool
#define DAIKIN_HEAT kDaikinHeat
#define DAIKIN_FAN kDaikinFan
#define DAIKIN_AUTO kDaikinAuto
#define DAIKIN_DRY kDaikinDry
#define DAIKIN_MIN_TEMP kDaikinMinTemp
#define DAIKIN_MAX_TEMP kDaikinMaxTemp
#define DAIKIN_FAN_MIN kDaikinFanMin
#define DAIKIN_FAN_MAX kDaikinFanMax
#define DAIKIN_FAN_AUTO kDaikinFanAuto
#define DAIKIN_FAN_QUIET kDaikinFanQuiet
class IRDaikinESP {
public:
explicit IRDaikinESP(uint16_t pin);
#if SEND_DAIKIN
void send();
#endif
void begin();
void on();
void off();
void setPower(bool state);
bool getPower();
void setTemp(uint8_t temp);
uint8_t getTemp();
void setFan(uint8_t fan);
uint8_t getFan();
uint8_t getMode();
void setMode(uint8_t mode);
void setSwingVertical(bool state);
bool getSwingVertical();
void setSwingHorizontal(bool state);
bool getSwingHorizontal();
bool getQuiet();
void setQuiet(bool state);
bool getPowerful();
void setPowerful(bool state);
void setSensor(bool state);
bool getSensor();
void setEcono(bool state);
bool getEcono();
void setEye(bool state);
bool getEye();
void setMold(bool state);
bool getMold();
void enableOnTimer(uint16_t starttime);
void disableOnTimer();
uint16_t getOnTime();
bool getOnTimerEnabled();
void enableOffTimer(uint16_t endtime);
void disableOffTimer();
uint16_t getOffTime();
bool getOffTimerEnabled();
void setCurrentTime(uint16_t time);
uint16_t getCurrentTime();
uint8_t* getRaw();
void setRaw(uint8_t new_code[]);
#if DAIKIN_DEBUG
void printState();
#endif // DAIKIN_DEBUG
uint32_t getCommand();
void setCommand(uint32_t value);
static bool validChecksum(const uint8_t state[],
const uint16_t length = kDaikinStateLength);
#ifdef ARDUINO
String toString();
static String renderTime(uint16_t timemins);
#else
std::string toString();
static std::string renderTime(uint16_t timemins);
#endif
private:
// # of bytes per command
uint8_t daikin[kDaikinStateLength];
void stateReset();
static uint8_t calcBlockChecksum(const uint8_t* block, const uint16_t length);
void checksum();
void setBit(uint8_t byte, uint8_t bitmask);
void clearBit(uint8_t byte, uint8_t bitmask);
uint8_t getBit(uint8_t byte, uint8_t bitmask);
IRsend _irsend;
};
#endif // IR_DAIKIN_H_

View File

@ -1,127 +0,0 @@
// Copyright 2017 stufisher
#include "ir_Trotec.h"
#include "IRremoteESP8266.h"
#include "IRutils.h"
// Constants
const uint16_t kTrotecHdrMark = 5952;
const uint16_t kTrotecHdrSpace = 7364;
const uint16_t kTrotecOneMark = 592;
const uint16_t kTrotecOneSpace = 1560;
const uint16_t kTrotecZeroMark = 592;
const uint16_t kTrotecZeroSpace = 592;
const uint16_t kTrotecGap = 6184;
const uint16_t kTrotecGapEnd = 1500; // made up value
#if SEND_TROTEC
void IRsend::sendTrotec(unsigned char data[], uint16_t nbytes,
uint16_t repeat) {
if (nbytes < kTrotecStateLength) return;
for (uint16_t r = 0; r <= repeat; r++) {
sendGeneric(kTrotecHdrMark, kTrotecHdrSpace, kTrotecOneMark,
kTrotecOneSpace, kTrotecZeroMark, kTrotecZeroSpace,
kTrotecOneMark, kTrotecGap, data, nbytes, 36, false,
0, // Repeats handled elsewhere
50);
// More footer
enableIROut(36);
mark(kTrotecOneMark);
space(kTrotecGapEnd);
}
}
#endif // SEND_TROTEC
IRTrotecESP::IRTrotecESP(uint16_t pin) : _irsend(pin) { stateReset(); }
void IRTrotecESP::begin() { _irsend.begin(); }
#if SEND_TROTEC
void IRTrotecESP::send() {
checksum();
_irsend.sendTrotec(trotec);
}
#endif // SEND_TROTEC
void IRTrotecESP::checksum() {
uint8_t sum = 0;
uint8_t i;
for (i = 2; i < 8; i++) sum += trotec[i];
trotec[8] = sum & 0xFF;
}
void IRTrotecESP::stateReset() {
for (uint8_t i = 2; i < kTrotecStateLength; i++) trotec[i] = 0x0;
trotec[0] = kTrotecIntro1;
trotec[1] = kTrotecIntro2;
setPower(false);
setTemp(kTrotecDefTemp);
setSpeed(kTrotecFanMed);
setMode(kTrotecAuto);
}
uint8_t* IRTrotecESP::getRaw() {
checksum();
return trotec;
}
void IRTrotecESP::setPower(bool state) {
if (state)
trotec[2] |= (kTrotecOn << 3);
else
trotec[2] &= ~(kTrotecOn << 3);
}
uint8_t IRTrotecESP::getPower() { return trotec[2] & (kTrotecOn << 3); }
void IRTrotecESP::setSpeed(uint8_t speed) {
trotec[2] = (trotec[2] & 0xcf) | (speed << 4);
}
uint8_t IRTrotecESP::getSpeed() { return trotec[2] & 0x30; }
void IRTrotecESP::setMode(uint8_t mode) {
trotec[2] = (trotec[2] & 0xfc) | mode;
}
uint8_t IRTrotecESP::getMode() { return trotec[2] & 0x03; }
void IRTrotecESP::setTemp(uint8_t temp) {
if (temp < kTrotecMinTemp)
temp = kTrotecMinTemp;
else if (temp > kTrotecMaxTemp)
temp = kTrotecMaxTemp;
trotec[3] = (trotec[3] & 0x80) | (temp - kTrotecMinTemp);
}
uint8_t IRTrotecESP::getTemp() { return trotec[3] & 0x7f; }
void IRTrotecESP::setSleep(bool sleep) {
if (sleep)
trotec[3] |= (kTrotecSleepOn << 7);
else
trotec[3] &= ~(kTrotecSleepOn << 7);
}
bool IRTrotecESP::getSleep(void) { return trotec[3] & (kTrotecSleepOn << 7); }
void IRTrotecESP::setTimer(uint8_t timer) {
if (timer > kTrotecMaxTimer) timer = kTrotecMaxTimer;
if (timer) {
trotec[5] |= (kTrotecTimerOn << 6);
trotec[6] = timer;
} else {
trotec[5] &= ~(kTrotecTimerOn << 6);
trotec[6] = 0;
}
}
uint8_t IRTrotecESP::getTimer() { return trotec[6]; }

View File

@ -1,149 +0,0 @@
// Copyright 2018 David Conran
//
// Code to emulate Whirlpool protocol compatible devices.
// Should be compatible with:
// * SPIS409L, SPIS412L, SPIW409L, SPIW412L, SPIW418L
//
#include <algorithm>
#ifndef ARDUINO
#include <string>
#endif
#include "IRrecv.h"
#include "IRremoteESP8266.h"
#include "IRsend.h"
#include "IRutils.h"
// WW WW HH HH IIIII RRRRRR LL PPPPPP OOOOO OOOOO LL
// WW WW HH HH III RR RR LL PP PP OO OO OO OO LL
// WW W WW HHHHHHH III RRRRRR LL PPPPPP OO OO OO OO LL
// WW WWW WW HH HH III RR RR LL PP OO OO OO OO LL
// WW WW HH HH IIIII RR RR LLLLLLL PP OOOO0 OOOO0 LLLLLLL
// Constants
// Ref: https://github.com/markszabo/IRremoteESP8266/issues/509
const uint16_t kWhirlpoolAcHdrMark = 8950;
const uint16_t kWhirlpoolAcHdrSpace = 4484;
const uint16_t kWhirlpoolAcBitMark = 597;
const uint16_t kWhirlpoolAcOneSpace = 1649;
const uint16_t kWhirlpoolAcZeroSpace = 533;
const uint16_t kWhirlpoolAcGap = 7920;
const uint32_t kWhirlpoolAcMinGap = 100000; // Completely made up value.
const uint8_t kWhirlpoolAcSections = 3;
#if SEND_WHIRLPOOL_AC
// Send a Whirlpool A/C message.
//
// Args:
// data: An array of bytes containing the IR command.
// nbytes: Nr. of bytes of data in the array. (>=kWhirlpoolAcStateLength)
// repeat: Nr. of times the message is to be repeated. (Default = 0).
//
// Status: ALPHA / Untested.
//
// Ref:
// https://github.com/markszabo/IRremoteESP8266/issues/509
void IRsend::sendWhirlpoolAC(unsigned char data[], uint16_t nbytes,
uint16_t repeat) {
if (nbytes < kWhirlpoolAcStateLength)
return; // Not enough bytes to send a proper message.
for (uint16_t r = 0; r <= repeat; r++) {
// Section 1
sendGeneric(kWhirlpoolAcHdrMark, kWhirlpoolAcHdrSpace, kWhirlpoolAcBitMark,
kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark,
kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, kWhirlpoolAcGap,
data, 6, // 6 bytes == 48 bits
38000, // Complete guess of the modulation frequency.
false, 0, 50);
// Section 2
sendGeneric(0, 0, kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace,
kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark,
kWhirlpoolAcGap, data + 6, 8, // 8 bytes == 64 bits
38000, // Complete guess of the modulation frequency.
false, 0, 50);
// Section 3
sendGeneric(0, 0, kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace,
kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark,
kWhirlpoolAcMinGap, data + 14, 7, // 7 bytes == 56 bits
38000, // Complete guess of the modulation frequency.
false, 0, 50);
}
}
#endif // SEND_WHIRLPOOL_AC
#if DECODE_WHIRLPOOL_AC
// Decode the supplied Whirlpool A/C message.
//
// Args:
// results: Ptr to the data to decode and where to store the decode result.
// nbits: The number of data bits to expect. Typically kWhirlpoolAcBits
// strict: Flag indicating if we should perform strict matching.
// Returns:
// boolean: True if it can decode it, false if it can't.
//
// Status: ALPHA / Untested.
//
//
// Ref:
// https://github.com/markszabo/IRremoteESP8266/issues/509
bool IRrecv::decodeWhirlpoolAC(decode_results *results, uint16_t nbits,
bool strict) {
if (results->rawlen < 2 * nbits + 4 + kHeader + kFooter - 1)
return false; // Can't possibly be a valid Whirlpool A/C message.
if (strict) {
if (nbits != kWhirlpoolAcBits) return false;
}
uint16_t offset = kStartOffset;
uint16_t dataBitsSoFar = 0;
uint16_t i = 0;
match_result_t data_result;
uint8_t sectionSize[kWhirlpoolAcSections] = {6, 8, 7};
// Header
if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcHdrMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcHdrSpace))
return false;
// Data Section
// Keep reading bytes until we either run out of section or state to fill.
for (uint8_t section = 0, pos = 0; section < kWhirlpoolAcSections;
section++) {
pos += sectionSize[section];
for (; offset <= results->rawlen - 16 && i < pos;
i++, dataBitsSoFar += 8, offset += data_result.used) {
data_result =
matchData(&(results->rawbuf[offset]), 8, kWhirlpoolAcBitMark,
kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark,
kWhirlpoolAcZeroSpace, kTolerance, kMarkExcess, false);
if (data_result.success == false) break; // Fail
// Data is in LSB order. We need to reverse it.
results->state[i] = (uint8_t)data_result.data;
}
// Section Footer
if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcBitMark))
return false;
if (section < kWhirlpoolAcSections - 1) { // Inter-section gaps.
if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcGap)) return false;
} else { // Last section / End of message gap.
if (offset <= results->rawlen &&
!matchAtLeast(results->rawbuf[offset++], kWhirlpoolAcGap))
return false;
}
}
// Compliance
if (strict) {
// Re-check we got the correct size/length due to the way we read the data.
if (dataBitsSoFar != kWhirlpoolAcBits) return false;
}
// Success
results->decode_type = WHIRLPOOL_AC;
results->bits = dataBitsSoFar;
// No need to record the state as we stored it as we decoded it.
// As we use result->state, we don't record value, address, or command as it
// is a union data type.
return true;
}
#endif // WHIRLPOOL_AC

View File

@ -1,290 +0,0 @@
// Copyright 2017 David Conran
#include "IRsend_test.h"
#include "IRsend.h"
#include "gtest/gtest.h"
// Tests sendData().
// Test sending zero bits.
TEST(TestSendData, SendZeroBits) {
IRsendTest irsend(4);
irsend.begin();
irsend.sendData(1, 2, 3, 4, 0b1, 0, true);
EXPECT_EQ("", irsend.outputStr());
}
// Test sending zero and one.
TEST(TestSendData, SendSingleBit) {
IRsendTest irsend(4);
irsend.begin();
irsend.sendData(1, 2, 3, 4, 0b1, 1, true);
EXPECT_EQ("m1s2", irsend.outputStr());
irsend.sendData(1, 2, 3, 4, 0b0, 1, true);
EXPECT_EQ("m3s4", irsend.outputStr());
}
// Test sending bit order.
TEST(TestSendData, TestingBitSendOrder) {
IRsendTest irsend(4);
irsend.begin();
irsend.sendData(1, 2, 3, 4, 0b10, 2, true);
EXPECT_EQ("m1s2m3s4", irsend.outputStr());
irsend.sendData(1, 2, 3, 4, 0b10, 2, false);
EXPECT_EQ("m3s4m1s2", irsend.outputStr());
irsend.sendData(1, 2, 3, 4, 0b0001, 4, false);
EXPECT_EQ("m1s2m3s4m3s4m3s4", irsend.outputStr());
}
// Test sending typical data.
TEST(TestSendData, SendTypicalData) {
IRsendTest irsend(4);
irsend.begin();
irsend.sendData(1, 2, 3, 4, 0b1010110011110000, 16, true);
EXPECT_EQ("m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4m3s4",
irsend.outputStr());
irsend.sendData(1, 2, 3, 4, 0x1234567890ABCDEF, 64, true);
EXPECT_EQ(
"m3s4m3s4m3s4m1s2m3s4m3s4m1s2m3s4m3s4m3s4m1s2m1s2m3s4m1s2m3s4m3s4"
"m3s4m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4"
"m1s2m3s4m3s4m1s2m3s4m3s4m3s4m3s4m1s2m3s4m1s2m3s4m1s2m3s4m1s2m1s2"
"m1s2m1s2m3s4m3s4m1s2m1s2m3s4m1s2m1s2m1s2m1s2m3s4m1s2m1s2m1s2m1s2",
irsend.outputStr());
}
// Test sending more than expected bits.
TEST(TestSendData, SendOverLargeData) {
IRsendTest irsend(4);
irsend.begin();
irsend.sendData(1, 2, 3, 4, 0xFFFFFFFFFFFFFFFF, 70, true);
EXPECT_EQ(
"m3s4m3s4m3s4m3s4m3s4m3s4"
"m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2"
"m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2"
"m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2"
"m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2",
irsend.outputStr());
}
// Test inverting the output.
TEST(TestIRSend, InvertedOutput) {
IRsendTest irsend(4, true);
irsend.begin();
irsend.sendData(1, 2, 3, 4, 0b1, 1, true);
EXPECT_EQ("s1m2", irsend.outputStr());
irsend.sendData(1, 2, 3, 4, 0b0, 1, true);
EXPECT_EQ("s3m4", irsend.outputStr());
}
// Test typical use of sendRaw().
TEST(TestSendRaw, GeneralUse) {
IRsendTest irsend(4);
IRrecv irrecv(0);
irsend.begin();
// NEC C3E0E0E8 as measured in #204
uint16_t rawData[67] = {
8950, 4500, 550, 1650, 600, 1650, 550, 550, 600, 500, 600, 550,
550, 550, 600, 1650, 550, 1650, 600, 1650, 600, 1650, 550, 1700,
550, 550, 600, 550, 550, 550, 600, 500, 600, 550, 550, 1650,
600, 1650, 600, 1650, 550, 550, 600, 500, 600, 500, 600, 550,
550, 550, 600, 1650, 550, 1650, 600, 1650, 600, 500, 650, 1600,
600, 500, 600, 550, 550, 550, 600};
irsend.sendRaw(rawData, 67, 38);
EXPECT_EQ(
"m8950s4500"
"m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650"
"m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550"
"m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550"
"m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550"
"m600",
irsend.outputStr());
irsend.reset();
irsend.sendRaw(rawData, 67, 38);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false));
EXPECT_EQ(NEC, irsend.capture.decode_type);
EXPECT_EQ(32, irsend.capture.bits);
EXPECT_EQ(0xC3E0E0E8, irsend.capture.value);
EXPECT_EQ(
"m8950s4500"
"m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650"
"m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550"
"m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550"
"m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550"
"m600",
irsend.outputStr());
}
// Incorrect handling of decodes from Raw. i.e. There is no gap recorded at
// the end of a command when using the interrupt code. sendRaw() best emulates
// this for unit testing purposes. sendGC() and sendXXX() will add the trailing
// gap. Users won't see this in normal use.
TEST(TestSendRaw, NoTrailingGap) {
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
irsend.reset();
uint16_t rawData[67] = {
9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, 600, 1650,
650, 550, 600, 1650, 650, 1650, 650, 1650, 600, 550, 650, 1650,
650, 1650, 650, 550, 600, 1650, 650, 1650, 650, 550, 650, 550,
650, 1650, 650, 550, 650, 550, 650, 550, 600, 550, 650, 550,
650, 550, 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650,
650, 1650, 650, 1650, 650, 1650, 600};
irsend.sendRaw(rawData, 67, 38);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture));
EXPECT_EQ(NEC, irsend.capture.decode_type);
EXPECT_EQ(kNECBits, irsend.capture.bits);
}
TEST(TestLowLevelSend, MarkFrequencyModulationAt38kHz) {
IRsendLowLevelTest irsend(0);
irsend.begin();
irsend.reset();
irsend.enableIROut(38000, 50);
EXPECT_EQ(5, irsend.mark(100));
EXPECT_EQ(
"[On]10usecs[Off]11usecs[On]10usecs[Off]11usecs[On]10usecs[Off]11usecs"
"[On]10usecs[Off]11usecs[On]10usecs[Off]6usecs",
irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(38000, 33);
EXPECT_EQ(5, irsend.mark(100));
EXPECT_EQ(
"[On]6usecs[Off]15usecs[On]6usecs[Off]15usecs[On]6usecs[Off]15usecs"
"[On]6usecs[Off]15usecs[On]6usecs[Off]10usecs",
irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(38000, 100);
EXPECT_EQ(1, irsend.mark(1000));
EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence);
}
TEST(TestLowLevelSend, MarkFrequencyModulationAt36_7kHz) {
IRsendLowLevelTest irsend(0);
irsend.begin();
irsend.reset();
irsend.enableIROut(36700, 50);
EXPECT_EQ(5, irsend.mark(100));
EXPECT_EQ(
"[On]11usecs[Off]11usecs[On]11usecs[Off]11usecs[On]11usecs[Off]11usecs"
"[On]11usecs[Off]11usecs[On]11usecs[Off]1usecs",
irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(36700, 33);
EXPECT_EQ(5, irsend.mark(100));
EXPECT_EQ(
"[On]7usecs[Off]15usecs[On]7usecs[Off]15usecs[On]7usecs[Off]15usecs"
"[On]7usecs[Off]15usecs[On]7usecs[Off]5usecs",
irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(36700, 100);
EXPECT_EQ(1, irsend.mark(1000));
EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence);
}
TEST(TestLowLevelSend, MarkFrequencyModulationAt40kHz) {
IRsendLowLevelTest irsend(0);
irsend.begin();
irsend.reset();
irsend.enableIROut(40000, 50);
EXPECT_EQ(5, irsend.mark(100));
EXPECT_EQ(
"[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs"
"[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs",
irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(40000, 33);
EXPECT_EQ(5, irsend.mark(100));
EXPECT_EQ(
"[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs"
"[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs",
irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(40000, 100);
EXPECT_EQ(1, irsend.mark(1000));
EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence);
}
TEST(TestLowLevelSend, MarkNoModulation) {
IRsendLowLevelTest irsend(0, false, false);
irsend.begin();
irsend.reset();
irsend.enableIROut(38000, 50);
EXPECT_EQ(1, irsend.mark(1000));
EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(36700, 25);
EXPECT_EQ(1, irsend.mark(1000));
EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(40000, 75);
EXPECT_EQ(1, irsend.mark(1000));
EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence);
}
TEST(TestLowLevelSend, SpaceFrequencyModulation) {
IRsendLowLevelTest irsend(0);
irsend.reset();
irsend.enableIROut(38000);
irsend.space(1000);
EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(40000, 75);
irsend.space(1000);
EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(38000, 100);
irsend.space(1000);
EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(38000, 33);
irsend.space(1000);
EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence);
}
TEST(TestLowLevelSend, SpaceNoModulation) {
IRsendLowLevelTest irsend(0, false, false);
irsend.begin();
irsend.reset();
irsend.enableIROut(38000, 50);
irsend.space(1000);
EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(36700, 25);
irsend.space(1000);
EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence);
irsend.reset();
irsend.enableIROut(40000, 75);
irsend.space(1000);
EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence);
}

View File

@ -1,838 +0,0 @@
// Copyright 2017 David Conran
#include "ir_Daikin.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
// Tests for sendDaikin().
// Test sending typical data only.
TEST(TestSendDaikin, SendDataOnly) {
IRsendTest irsend(4);
irsend.begin();
uint8_t daikin_code[kDaikinStateLength] = {
0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11,
0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3};
irsend.reset();
irsend.sendDaikin(daikin_code);
EXPECT_EQ(
"m428s428m428s428m428s428m428s428m428s428"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428"
"m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280"
"m428s29428",
irsend.outputStr());
}
// Test sending with repeats.
TEST(TestSendDaikin, SendWithRepeats) {
IRsendTest irsend(4);
irsend.begin();
irsend.reset();
uint8_t daikin_code[kDaikinStateLength] = {
0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11,
0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3};
irsend.reset();
irsend.sendDaikin(daikin_code, kDaikinStateLength, 1);
EXPECT_EQ(
"m428s428m428s428m428s428m428s428m428s428"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428"
"m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280"
"m428s29428"
"m428s428m428s428m428s428m428s428m428s428"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428"
"m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280"
"m428s29428",
irsend.outputStr());
}
// Test sending atypical sizes.
TEST(TestSendDaikin, SendUnexpectedSizes) {
IRsendTest irsend(4);
irsend.begin();
uint8_t daikin_short_code[kDaikinStateLength - 1] = {
0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11,
0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00};
irsend.reset();
irsend.sendDaikin(daikin_short_code, kDaikinStateLength - 1);
ASSERT_EQ("", irsend.outputStr());
uint8_t daikin_long_code[kDaikinStateLength + 1] = {
0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, 0xDA,
0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3, 0x11};
irsend.reset();
irsend.sendDaikin(daikin_long_code, kDaikinStateLength + 1);
ASSERT_EQ(
"m428s428m428s428m428s428m428s428m428s428"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428"
"m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s29428",
irsend.outputStr());
}
// Tests for IRDaikinESP class.
TEST(TestDaikinClass, Power) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
irdaikin.on();
EXPECT_TRUE(irdaikin.getPower());
irdaikin.off();
EXPECT_FALSE(irdaikin.getPower());
irdaikin.setPower(true);
EXPECT_TRUE(irdaikin.getPower());
irdaikin.setPower(false);
EXPECT_FALSE(irdaikin.getPower());
}
TEST(TestDaikinClass, Temperature) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
irdaikin.setTemp(0);
EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp());
irdaikin.setTemp(255);
EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp());
irdaikin.setTemp(kDaikinMinTemp);
EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp());
irdaikin.setTemp(kDaikinMaxTemp);
EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp());
irdaikin.setTemp(kDaikinMinTemp - 1);
EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp());
irdaikin.setTemp(kDaikinMaxTemp + 1);
EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp());
irdaikin.setTemp(kDaikinMinTemp + 1);
EXPECT_EQ(kDaikinMinTemp + 1, irdaikin.getTemp());
irdaikin.setTemp(21);
EXPECT_EQ(21, irdaikin.getTemp());
irdaikin.setTemp(25);
EXPECT_EQ(25, irdaikin.getTemp());
irdaikin.setTemp(29);
EXPECT_EQ(29, irdaikin.getTemp());
}
TEST(TestDaikinClass, OperatingMode) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
irdaikin.setMode(kDaikinAuto);
EXPECT_EQ(kDaikinAuto, irdaikin.getMode());
irdaikin.setMode(kDaikinCool);
EXPECT_EQ(kDaikinCool, irdaikin.getMode());
irdaikin.setMode(kDaikinHeat);
EXPECT_EQ(kDaikinHeat, irdaikin.getMode());
irdaikin.setMode(kDaikinDry);
EXPECT_EQ(kDaikinDry, irdaikin.getMode());
irdaikin.setMode(kDaikinFan);
EXPECT_EQ(kDaikinFan, irdaikin.getMode());
irdaikin.setMode(kDaikinFan + 1);
EXPECT_EQ(kDaikinAuto, irdaikin.getMode());
irdaikin.setMode(kDaikinAuto + 1);
EXPECT_EQ(kDaikinAuto, irdaikin.getMode());
irdaikin.setMode(255);
EXPECT_EQ(kDaikinAuto, irdaikin.getMode());
}
TEST(TestDaikinClass, VaneSwing) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
irdaikin.setSwingHorizontal(true);
irdaikin.setSwingVertical(false);
irdaikin.setSwingHorizontal(true);
EXPECT_TRUE(irdaikin.getSwingHorizontal());
EXPECT_FALSE(irdaikin.getSwingVertical());
irdaikin.setSwingVertical(true);
EXPECT_TRUE(irdaikin.getSwingHorizontal());
EXPECT_TRUE(irdaikin.getSwingVertical());
irdaikin.setSwingHorizontal(false);
EXPECT_FALSE(irdaikin.getSwingHorizontal());
EXPECT_TRUE(irdaikin.getSwingVertical());
irdaikin.setSwingVertical(false);
EXPECT_FALSE(irdaikin.getSwingHorizontal());
EXPECT_FALSE(irdaikin.getSwingVertical());
}
TEST(TestDaikinClass, QuietMode) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
irdaikin.setQuiet(true);
EXPECT_TRUE(irdaikin.getQuiet());
irdaikin.setQuiet(false);
EXPECT_FALSE(irdaikin.getQuiet());
irdaikin.setQuiet(true);
EXPECT_TRUE(irdaikin.getQuiet());
// Setting Econo mode should NOT change out of quiet mode.
irdaikin.setEcono(true);
EXPECT_TRUE(irdaikin.getQuiet());
irdaikin.setEcono(false);
EXPECT_TRUE(irdaikin.getQuiet());
// But setting Powerful mode should exit out of quiet mode.
irdaikin.setPowerful(true);
EXPECT_FALSE(irdaikin.getQuiet());
}
TEST(TestDaikinClass, PowerfulMode) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
irdaikin.setPowerful(true);
EXPECT_TRUE(irdaikin.getPowerful());
irdaikin.setPowerful(false);
EXPECT_FALSE(irdaikin.getPowerful());
irdaikin.setPowerful(true);
EXPECT_TRUE(irdaikin.getPowerful());
irdaikin.setQuiet(true);
EXPECT_FALSE(irdaikin.getPowerful());
irdaikin.setPowerful(true);
irdaikin.setEcono(true);
EXPECT_FALSE(irdaikin.getPowerful());
}
TEST(TestDaikinClass, EconoMode) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
irdaikin.setEcono(true);
EXPECT_TRUE(irdaikin.getEcono());
irdaikin.setEcono(false);
EXPECT_FALSE(irdaikin.getEcono());
irdaikin.setEcono(true);
EXPECT_TRUE(irdaikin.getEcono());
// Setting Quiet mode should NOT change out of Econo mode.
irdaikin.setQuiet(true);
EXPECT_TRUE(irdaikin.getEcono());
irdaikin.setQuiet(false);
EXPECT_TRUE(irdaikin.getEcono());
// But setting Powerful mode should exit out of Econo mode.
irdaikin.setPowerful(true);
EXPECT_FALSE(irdaikin.getEcono());
}
TEST(TestDaikinClass, FanSpeed) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
// Unexpected value should default to Auto.
irdaikin.setFan(0);
EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan());
// Unexpected value should default to Auto.
irdaikin.setFan(255);
EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan());
irdaikin.setFan(kDaikinFanMax);
EXPECT_EQ(kDaikinFanMax, irdaikin.getFan());
// Beyond Max should default to Auto.
irdaikin.setFan(kDaikinFanMax + 1);
EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan());
irdaikin.setFan(kDaikinFanMax - 1);
EXPECT_EQ(kDaikinFanMax - 1, irdaikin.getFan());
irdaikin.setFan(kDaikinFanMin);
EXPECT_EQ(kDaikinFanMin, irdaikin.getFan());
irdaikin.setFan(kDaikinFanMin + 1);
EXPECT_EQ(kDaikinFanMin + 1, irdaikin.getFan());
// Beyond Min should default to Auto.
irdaikin.setFan(kDaikinFanMin - 1);
EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan());
irdaikin.setFan(3);
EXPECT_EQ(3, irdaikin.getFan());
irdaikin.setFan(kDaikinFanAuto);
EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan());
irdaikin.setFan(kDaikinFanQuiet);
EXPECT_EQ(kDaikinFanQuiet, irdaikin.getFan());
}
TEST(TestDaikinClass, CurrentTime) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
irdaikin.setCurrentTime(0); // 00:00
EXPECT_EQ(0, irdaikin.getCurrentTime());
irdaikin.setCurrentTime(754); // 12:34
EXPECT_EQ(754, irdaikin.getCurrentTime());
irdaikin.setCurrentTime(1439); // 23:59
EXPECT_EQ(1439, irdaikin.getCurrentTime());
}
TEST(TestDaikinClass, OnOffTimers) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
// Both timers turned off.
irdaikin.disableOnTimer();
irdaikin.disableOffTimer();
EXPECT_FALSE(irdaikin.getOnTimerEnabled());
EXPECT_EQ(0x600, irdaikin.getOnTime());
EXPECT_FALSE(irdaikin.getOffTimerEnabled());
EXPECT_EQ(0x600, irdaikin.getOffTime());
// Turn on just the On Timer.
irdaikin.enableOnTimer(123);
EXPECT_TRUE(irdaikin.getOnTimerEnabled());
EXPECT_EQ(123, irdaikin.getOnTime());
EXPECT_FALSE(irdaikin.getOffTimerEnabled());
EXPECT_EQ(0x600, irdaikin.getOffTime());
// Now turn on the Off Timer.
irdaikin.enableOffTimer(754);
EXPECT_TRUE(irdaikin.getOffTimerEnabled());
EXPECT_EQ(754, irdaikin.getOffTime());
EXPECT_TRUE(irdaikin.getOnTimerEnabled());
EXPECT_EQ(123, irdaikin.getOnTime());
// Turn off the just the On Timer.
irdaikin.disableOnTimer();
EXPECT_FALSE(irdaikin.getOnTimerEnabled());
EXPECT_EQ(0x600, irdaikin.getOnTime());
EXPECT_TRUE(irdaikin.getOffTimerEnabled());
EXPECT_EQ(754, irdaikin.getOffTime());
// Now turn off the Off Timer.
irdaikin.disableOffTimer();
EXPECT_FALSE(irdaikin.getOffTimerEnabled());
EXPECT_EQ(0x600, irdaikin.getOffTime());
EXPECT_FALSE(irdaikin.getOnTimerEnabled());
EXPECT_EQ(0x600, irdaikin.getOnTime());
// Use some canary values around the timers to ensure no accidental
// bit flips happen. i.e. Neighbouring bytes in the state.
// (Found some during testing on systems with different endian-ness)
// Tests here to make sure it never happens again.
irdaikin.setSwingHorizontal(true);
irdaikin.setPowerful(true);
irdaikin.disableOffTimer();
irdaikin.disableOnTimer();
ASSERT_TRUE(irdaikin.getSwingHorizontal());
ASSERT_TRUE(irdaikin.getPowerful());
irdaikin.enableOnTimer(123);
irdaikin.enableOffTimer(456);
ASSERT_TRUE(irdaikin.getSwingHorizontal());
ASSERT_TRUE(irdaikin.getPowerful());
irdaikin.disableOffTimer();
irdaikin.disableOnTimer();
ASSERT_TRUE(irdaikin.getSwingHorizontal());
ASSERT_TRUE(irdaikin.getPowerful());
irdaikin.setSwingHorizontal(false);
irdaikin.setPowerful(false);
irdaikin.disableOffTimer();
irdaikin.disableOnTimer();
ASSERT_FALSE(irdaikin.getSwingHorizontal());
ASSERT_FALSE(irdaikin.getPowerful());
irdaikin.enableOnTimer(123);
irdaikin.enableOffTimer(456);
ASSERT_FALSE(irdaikin.getSwingHorizontal());
ASSERT_FALSE(irdaikin.getPowerful());
irdaikin.disableOffTimer();
irdaikin.disableOnTimer();
ASSERT_FALSE(irdaikin.getSwingHorizontal());
ASSERT_FALSE(irdaikin.getPowerful());
}
// Test Eye mode.
TEST(TestDaikinClass, EyeSetting) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
// The Eye setting is stored in the same byte as Econo mode.
// Econo mode tests are there to make sure it isn't harmed and vice-versa.
irdaikin.setEcono(false);
irdaikin.setEye(false);
ASSERT_FALSE(irdaikin.getEye());
EXPECT_FALSE(irdaikin.getEcono());
irdaikin.setEye(true);
ASSERT_TRUE(irdaikin.getEye());
EXPECT_FALSE(irdaikin.getEcono());
irdaikin.setEcono(false);
ASSERT_TRUE(irdaikin.getEye());
EXPECT_FALSE(irdaikin.getEcono());
irdaikin.setEcono(true);
ASSERT_TRUE(irdaikin.getEye());
EXPECT_TRUE(irdaikin.getEcono());
irdaikin.setEye(false);
ASSERT_FALSE(irdaikin.getEye());
EXPECT_TRUE(irdaikin.getEcono());
}
// Test Mold mode.
TEST(TestDaikinClass, MoldSetting) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
irdaikin.setMold(false);
ASSERT_FALSE(irdaikin.getMold());
irdaikin.setMold(true);
ASSERT_TRUE(irdaikin.getMold());
irdaikin.setMold(false);
ASSERT_FALSE(irdaikin.getMold());
}
// Test Sensor mode.
TEST(TestDaikinClass, SensorSetting) {
IRDaikinESP irdaikin(0);
irdaikin.begin();
irdaikin.setSensor(false);
ASSERT_FALSE(irdaikin.getSensor());
irdaikin.setSensor(true);
ASSERT_TRUE(irdaikin.getSensor());
irdaikin.setSensor(false);
ASSERT_FALSE(irdaikin.getSensor());
}
TEST(TestDaikinClass, RenderTime) {
EXPECT_EQ("0:00", IRDaikinESP::renderTime(0));
EXPECT_EQ("0:10", IRDaikinESP::renderTime(10));
EXPECT_EQ("1:00", IRDaikinESP::renderTime(1 * 60 + 0));
EXPECT_EQ("23:59", IRDaikinESP::renderTime(23 * 60 + 59));
}
TEST(TestDaikinClass, SetAndGetRaw) {
IRDaikinESP irdaikin(0);
uint8_t initialState[kDaikinStateLength] = {
0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11,
0xDA, 0x27, 0x00, 0x00, 0x49, 0x1E, 0x00, 0xB0, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x4F};
uint8_t expectedState[kDaikinStateLength] = {
0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11,
0xDA, 0x27, 0x00, 0x00, 0x48, 0x2A, 0x00, 0xB0, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x02, 0x5A};
EXPECT_STATE_EQ(initialState, irdaikin.getRaw(), kDaikinBits);
// toggle the power state.
irdaikin.setPower(!irdaikin.getPower());
irdaikin.setTemp(21);
irdaikin.setMold(true);
EXPECT_STATE_EQ(expectedState, irdaikin.getRaw(), kDaikinBits);
irdaikin.setRaw(initialState);
EXPECT_STATE_EQ(initialState, irdaikin.getRaw(), kDaikinBits);
}
TEST(TestDaikinClass, ChecksumValidation) {
uint8_t daikin_code[kDaikinStateLength] = {
0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02, 0x11,
0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE1};
EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code));
// Change the array so the checksum is invalid.
daikin_code[0] ^= 0xFF;
EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code));
// Restore the previous change, and change another byte.
daikin_code[0] ^= 0xFF;
daikin_code[4] ^= 0xFF;
EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code));
daikin_code[4] ^= 0xFF;
// Change something in the 2nd block.
daikin_code[10] ^= 0xFF;
EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code));
daikin_code[10] ^= 0xFF;
EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code));
}
// Test human readable output.
TEST(TestDaikinClass, HumanReadable) {
IRDaikinESP irdaikin(0);
EXPECT_EQ(
"Power: On, Mode: 4 (HEAT), Temp: 15C, Fan: 11 (QUIET), "
"Powerful: Off, Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, "
"Swing (Horizontal): Off, Swing (Vertical): Off, "
"Current Time: 0:00, On Time: Off, Off Time: Off",
irdaikin.toString());
irdaikin.setMode(kDaikinAuto);
irdaikin.setTemp(25);
irdaikin.setFan(kDaikinFanAuto);
irdaikin.setQuiet(true);
irdaikin.setSensor(true);
irdaikin.setEye(true);
irdaikin.setMold(true);
irdaikin.setSwingVertical(true);
irdaikin.setSwingHorizontal(true);
irdaikin.setCurrentTime(9 * 60 + 15);
irdaikin.enableOnTimer(8 * 60 + 0);
irdaikin.enableOffTimer(17 * 60 + 30);
irdaikin.off();
EXPECT_EQ(
"Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 10 (AUTO), "
"Powerful: Off, Quiet: On, Sensor: On, Eye: On, Mold: On, "
"Swing (Horizontal): On, Swing (Vertical): On, "
"Current Time: 9:15, On Time: 8:00, Off Time: 17:30",
irdaikin.toString());
}
// Test general message construction after tweaking some settings.
TEST(TestDaikinClass, MessageConstuction) {
IRDaikinESP irdaikin(0);
IRsendTest irsend(4);
irdaikin.begin();
irsend.begin();
irdaikin.setFan(kDaikinFanMin);
irdaikin.setMode(kDaikinCool);
irdaikin.setTemp(27);
irdaikin.setSwingVertical(false);
irdaikin.setSwingHorizontal(true);
irdaikin.setQuiet(false);
irdaikin.setPower(true);
// Check everything for kicks.
EXPECT_EQ(kDaikinFanMin, irdaikin.getFan());
EXPECT_EQ(kDaikinCool, irdaikin.getMode());
EXPECT_EQ(27, irdaikin.getTemp());
EXPECT_FALSE(irdaikin.getSwingVertical());
EXPECT_TRUE(irdaikin.getSwingHorizontal());
EXPECT_FALSE(irdaikin.getQuiet());
EXPECT_TRUE(irdaikin.getPower());
irsend.reset();
irsend.sendDaikin(irdaikin.getRaw());
EXPECT_EQ(
"m428s428m428s428m428s428m428s428m428s428"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s428m428s428m428s428m428s1280m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s1280m428s428m428s1280m428s428m428s1280m428s428"
"m428s29428m3650s1623"
"m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428"
"m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280"
"m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s1280m428s428m428s428m428s1280m428s1280m428s1280m428s428m428s428"
"m428s428m428s1280m428s1280m428s428m428s1280m428s1280m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s428"
"m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s1280m428s1280m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428"
"m428s428m428s1280m428s1280m428s428m428s428m428s1280m428s1280m428s1280"
"m428s29428",
irsend.outputStr());
}
// Tests for decodeDaikin().
// Test decoding a message captured from a real IR remote.
TEST(TestDecodeDaikin, RealExample) {
IRDaikinESP irdaikin(0);
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
uint8_t expectedState[kDaikinStateLength] = {
0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11,
0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00,
0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32};
uint16_t rawData[kDaikinRawBits] = {
416, 446, 416, 446, 416, 446, 418, 446, 416, 446, 416, 25434,
3436, 1768, 390, 1336, 390, 446, 416, 446, 416, 446, 416, 1336,
390, 446, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 448,
416, 1336, 390, 1336, 390, 448, 416, 1336, 390, 1336, 390, 1338,
388, 1338, 390, 1336, 390, 446, 416, 446, 416, 1336, 390, 446,
416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 448,
416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, 416, 1336,
390, 448, 416, 446, 416, 446, 416, 1336, 390, 1336, 390, 446,
416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446,
416, 446, 416, 446, 416, 448, 416, 446, 416, 446, 416, 446,
416, 448, 414, 448, 416, 448, 416, 1336, 390, 1336, 390, 1336,
390, 446, 414, 1336, 390, 448, 414, 1336, 390, 1336, 390, 34878,
3436, 1768, 390, 1336, 390, 446, 416, 448, 416, 446, 416, 1336,
390, 446, 416, 448, 416, 446, 416, 446, 416, 1336, 390, 446,
416, 1336, 390, 1336, 390, 446, 416, 1336, 390, 1336, 390, 1336,
390, 1336, 390, 1336, 392, 446, 414, 448, 416, 1336, 390, 446,
416, 446, 416, 446, 416, 446, 414, 448, 416, 446, 416, 448,
414, 448, 416, 446, 416, 446, 416, 446, 414, 1336, 390, 448,
416, 446, 416, 446, 416, 448, 416, 1336, 390, 446, 416, 446,
416, 1336, 390, 446, 416, 1336, 390, 1336, 390, 1336, 390, 446,
416, 446, 414, 1338, 390, 446, 416, 1336, 390, 446, 416, 446,
416, 446, 416, 446, 416, 446, 416, 1336, 390, 1336, 390, 446,
416, 446, 416, 1336, 390, 446, 416, 446, 416, 1336, 390, 34876,
3436, 1768, 388, 1336, 390, 446, 416, 446, 416, 448, 416, 1336,
390, 446, 416, 446, 416, 446, 416, 448, 416, 1336, 390, 448,
414, 1336, 390, 1336, 390, 446, 416, 1336, 388, 1338, 388, 1336,
390, 1336, 390, 1336, 390, 446, 416, 446, 416, 1336, 390, 446,
420, 442, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446,
416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 448,
416, 446, 416, 448, 416, 446, 416, 448, 416, 446, 416, 1336,
390, 1336, 390, 1336, 388, 1338, 390, 1336, 390, 1336, 392, 446,
416, 446, 416, 448, 416, 1334, 390, 446, 416, 1338, 388, 1336,
390, 1336, 390, 446, 416, 446, 416, 448, 414, 446, 416, 446,
416, 446, 416, 448, 416, 446, 416, 446, 416, 446, 416, 446,
416, 446, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446,
416, 1336, 390, 446, 414, 448, 416, 446, 416, 446, 416, 446,
416, 448, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446,
416, 1336, 390, 446, 416, 446, 416, 446, 416, 448, 416, 1338,
390, 444, 418, 1336, 390, 448, 416, 446, 416, 1336, 390, 446,
416, 446, 416, 1336, 390, 1336, 388, 1336, 390, 446, 416, 1336,
390, 448, 414, 448, 414, 448, 416, 1334, 390, 446, 416, 446,
416, 446, 416, 448, 416, 446, 416, 446, 416, 448, 416, 446,
416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446,
416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446,
416, 448, 416, 1336, 390, 1336, 390, 446, 416, 446, 416, 446,
416, 446, 414, 446, 416, 448, 416, 446, 416, 448, 414, 446,
418, 446, 416, 446, 416, 448, 416, 446, 416, 448, 416, 446,
416, 448, 416, 446, 416, 1336, 390, 446, 416, 446, 416, 1338,
390, 1336, 390, 446, 416, 446, 416}; // Captured by @sillyfrog
irsend.reset();
irsend.sendRaw(rawData, kDaikinRawBits, 38000);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(DAIKIN, irsend.capture.decode_type);
ASSERT_EQ(kDaikinBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
}
// Decoding a message we entirely constructed based solely on a given state.
TEST(TestDecodeDaikin, SyntheticExample) {
IRDaikinESP irdaikin(0);
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
uint8_t expectedState[kDaikinStateLength] = {
0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11,
0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00,
0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32};
irsend.reset();
irsend.sendDaikin(expectedState);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(DAIKIN, irsend.capture.decode_type);
ASSERT_EQ(kDaikinBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
}

View File

@ -1,118 +0,0 @@
// Copyright 2018 David Conran
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
// Tests for sendWhirlpoolAC().
// Test sending typical data only.
TEST(TestSendWhirlpoolAC, SendDataOnly) {
IRsendTest irsend(0);
irsend.begin();
uint8_t data[kWhirlpoolAcStateLength] = {
0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00,
0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02};
irsend.sendWhirlpoolAC(data);
EXPECT_EQ(
"m8950s4484"
"m597s1649m597s1649m597s533m597s533m597s533m597s533m597s533m597s1649"
"m597s533m597s1649m597s1649m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s1649m597s533m597s533m597s533"
"m597s1649m597s533m597s533m597s533m597s1649m597s1649m597s1649m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s7920"
"m597s1649m597s533m597s533m597s533m597s1649m597s533m597s533m597s1649"
"m597s1649m597s1649m597s1649m597s1649m597s1649m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s1649m597s1649m597s1649m597s1649m597s533m597s1649m597s1649m597s1649"
"m597s7920"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s1649m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s533m597s1649m597s533m597s533m597s533m597s533m597s533m597s533"
"m597s100000",
irsend.outputStr());
}
// Tests for decodeWhirlpoolAC().
// Decode normal WhirlpoolAC messages.
TEST(TestDecodeWhirlpoolAC, SyntheticDecode) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
// Synthesised Normal WhirlpoolAC message.
irsend.reset();
uint8_t expectedState[kWhirlpoolAcStateLength] = {
0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00,
0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02};
irsend.sendWhirlpoolAC(expectedState);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type);
EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
}
// Decode a recorded example
TEST(TestDecodeWhirlpoolAC, RealExampleDecode) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
// Real WhirlpoolAC message.
// Ref: https://github.com/markszabo/IRremoteESP8266/issues/509
uint16_t rawData[343] = {
8950, 4484, 598, 1642, 598, 1646, 594, 534, 594, 538, 602, 532,
598, 540, 600, 542, 598, 1650, 600, 522, 598, 1644, 596, 1650,
600, 532, 598, 538, 602, 536, 594, 548, 592, 538, 602, 518,
600, 524, 596, 532, 598, 532, 598, 1654, 596, 544, 596, 544,
596, 536, 594, 1644, 596, 528, 600, 528, 592, 538, 602, 1648,
602, 1654, 596, 1664, 598, 534, 594, 526, 594, 530, 598, 528,
602, 530, 600, 534, 596, 542, 598, 542, 598, 534, 596, 526,
594, 530, 600, 528, 602, 530, 600, 534, 596, 542, 598, 544,
596, 518, 602, 7916, 598, 1642, 598, 528, 600, 528, 602, 530,
600, 1652, 598, 542, 598, 544, 596, 1654, 596, 1644, 596, 1648,
602, 1644, 596, 1654, 596, 1656, 604, 536, 594, 548, 602, 528,
600, 520, 600, 524, 596, 532, 598, 532, 596, 538, 602, 536,
594, 546, 594, 538, 602, 518, 600, 524, 596, 532, 598, 532,
598, 536, 594, 544, 596, 544, 596, 536, 594, 526, 592, 530,
600, 528, 600, 530, 602, 532, 596, 542, 598, 542, 598, 534,
596, 524, 596, 528, 600, 526, 592, 538, 592, 542, 598, 540,
600, 540, 600, 530, 598, 522, 598, 526, 594, 534, 596, 534,
594, 540, 602, 536, 592, 548, 592, 538, 600, 1636, 594, 1648,
602, 1642, 598, 1652, 598, 538, 602, 1680, 570, 1662, 598, 1634,
596, 7924, 600, 520, 598, 526, 592, 534, 596, 534, 596, 540,
600, 536, 604, 538, 602, 530, 600, 520, 598, 1640, 600, 528,
600, 530, 600, 534, 594, 544, 596, 544, 596, 534, 596, 526,
594, 528, 600, 526, 594, 536, 592, 542, 598, 538, 602, 538,
602, 528, 600, 520, 600, 524, 596, 530, 600, 532, 598, 534,
596, 542, 598, 542, 598, 532, 598, 524, 596, 528, 602, 526,
594, 536, 594, 540, 600, 536, 594, 548, 592, 538, 602, 518,
602, 522, 596, 530, 600, 530, 600, 534, 596, 542, 598, 544,
596, 534, 596, 524, 594, 1644, 596, 532, 596, 534, 596, 538,
602, 536, 594, 546, 594, 520, 600};
uint8_t expectedState[kWhirlpoolAcStateLength] = {
0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00,
0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02};
irsend.reset();
irsend.sendRaw(rawData, 343, 38000);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type);
EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
}

View File

@ -12,7 +12,9 @@
- [Jorge Cisneros](https://github.com/jorgecis/) - [Jorge Cisneros](https://github.com/jorgecis/)
- [Denes Varga](https://github.com/denxhun/) - [Denes Varga](https://github.com/denxhun/)
- [Brett T. Warden](https://github.com/bwarden/) - [Brett T. Warden](https://github.com/bwarden/)
- [Fabien Valthier](https://github.com/hcoohb)
- [Ajay Pala](https://github.com/ajaypala/)
All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors). All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors).
### Contributors of the [original project](https://github.com/z3t0/Arduino-IRremote) can be found on the [original project's contributors page](https://github.com/z3t0/Arduino-IRremote/blob/master/Contributors.md) ### Contributors of the [original project](https://github.com/z3t0/Arduino-IRremote) can be found on the [original project's contributors page](https://github.com/z3t0/Arduino-IRremote/blob/master/Contributors.md)

View File

@ -1,20 +1,21 @@
language: c language: c
env: env:
- BD=esp8266:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M - BD=esp8266:esp8266:nodemcuv2:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled
- BD=esp8266:esp8266:d1_mini:CpuFrequency=80,FlashSize=4M3M - BD=esp8266:esp8266:d1_mini:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled
before_install: before_install:
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
- sleep 3 - sleep 3
- export DISPLAY=:1.0 - export DISPLAY=:1.0
- wget http://downloads.arduino.cc/arduino-1.8.2-linux64.tar.xz - wget http://downloads.arduino.cc/arduino-1.8.8-linux64.tar.xz
- tar xf arduino-1.8.2-linux64.tar.xz - tar xf arduino-1.8.8-linux64.tar.xz
- sudo mv arduino-1.8.2 /usr/local/share/arduino - sudo mv arduino-1.8.8 /usr/local/share/arduino
- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
- wget https://raw.githubusercontent.com/google/styleguide/gh-pages/cpplint/cpplint.py - wget https://raw.githubusercontent.com/google/styleguide/gh-pages/cpplint/cpplint.py
install: install:
- ln -s $PWD /usr/local/share/arduino/libraries/ - ln -s $PWD /usr/local/share/arduino/libraries/
- git clone https://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WiFiManager - git clone https://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WiFiManager
- git clone https://github.com/knolleary/pubsubclient.git /usr/local/share/arduino/libraries/PubSubClient - git clone https://github.com/knolleary/pubsubclient.git /usr/local/share/arduino/libraries/PubSubClient
- git clone https://github.com/bblanchon/ArduinoJson.git --branch 5.x /usr/local/share/arduino/libraries/ArduinoJson
- arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs - arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs
- arduino --install-boards esp8266:esp8266 - arduino --install-boards esp8266:esp8266
- arduino --board $BD --save-prefs - arduino --board $BD --save-prefs
@ -40,6 +41,10 @@ script:
- arduino --verify --board $BD $PWD/examples/TurnOnArgoAC/TurnOnArgoAC.ino - arduino --verify --board $BD $PWD/examples/TurnOnArgoAC/TurnOnArgoAC.ino
- arduino --verify --board $BD $PWD/examples/IRMQTTServer/IRMQTTServer.ino - arduino --verify --board $BD $PWD/examples/IRMQTTServer/IRMQTTServer.ino
- arduino --verify --board $BD $PWD/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino - arduino --verify --board $BD $PWD/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino
- arduino --verify --board $BD $PWD/examples/ControlSamsungAC/ControlSamsungAC.ino
- arduino --verify --board $BD $PWD/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino
- arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino
# Also check the tools programs compile. # Also check the tools programs compile.
- (cd tools; make all) - (cd tools; make all)
# Check for lint issues. # Check for lint issues.

View File

@ -1,14 +1,15 @@
# IRremote ESP8266 Library # IRremote ESP8266 Library
[![Build Status](https://travis-ci.org/markszabo/IRremoteESP8266.svg?branch=master)](https://travis-ci.org/markszabo/IRremoteESP8266) [![Build Status](https://travis-ci.org/markszabo/IRremoteESP8266.svg?branch=master)](https://travis-ci.org/markszabo/IRremoteESP8266)
[![arduino-library-badge](https://www.ardu-badge.com/badge/IRremoteESP8266.svg?)](https://www.ardu-badge.com/IRremoteESP8266)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Average time to resolve an issue") [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Percentage of issues still open") [![Percentage of issues still open](http://isitmaintained.com/badge/open/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Percentage of issues still open")
[![GitLicense](https://gitlicense.com/badge/markszabo/IRremoteESP8266)](https://gitlicense.com/license/markszabo/IRremoteESP8266) [![GitLicense](https://gitlicense.com/badge/markszabo/IRremoteESP8266)](https://gitlicense.com/license/markszabo/IRremoteESP8266)
This library enables you to **send _and_ receive** infra-red signals on an [ESP8266 using the Arduino framework](https://github.com/esp8266/Arduino) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* etc. This library enables you to **send _and_ receive** infra-red signals on an [ESP8266 using the Arduino framework](https://github.com/esp8266/Arduino) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* etc.
## v2.5.2 Now Available ## v2.6.0 Now Available
Version 2.5.2 of the library is now [available](https://github.com/markszabo/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. Version 2.6.0 of the library is now [available](https://github.com/markszabo/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
#### Upgrading from pre-v2.0 #### 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/markszabo/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. 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/markszabo/IRremoteESP8266/wiki/Upgrading-to-v2.0) page.

View File

@ -1,5 +1,107 @@
# Release Notes # Release Notes
## _v2.6.0 (20190430)_
**[Bug Fixes]**
- Fixed problem where LG protocol used wrong duty cycle for repeat. (#687)
- Fix checksum calculation for Daikin protocols. (#678)
- Fix the byte array version of sendGree() (#684, #685)
- Fix artificial vs. real state creation on HaierAC. (#668, #671)
- Fix issues caused by having `MQTT_ENABLE` set to false. (#677)
- Fix compile problem when DEBUG is defined. (#673, #674)
- Fix Minor bug with MQTT_ENABLE False condition (#654)
**[Features]**
- Experimental support for DAIKIN216 (ARC433B69) (#690)
- Experimental support for Mitsubishi Heavy Industries A/Cs. (#660, #665, #667)
- Support more features of TCL A/C (#656)
- Add LEGO(TM) Power Functions IR protocol. (#655)
- Add Panasonic AC RKR model & Example (#649)
- DAIKIN/IRDaikinESP overhaul and add Comfort mode support. (#678)
**WARNING**: Previous `sendDaikin()` calls may not work.
Please recapture codes or use `kDaikinStateLengthShort` for
`nbytes` in those calls.
- IRMQTTServer: Move MQTT server and other parameters to WifiManager. (#680)
**WARNING**: Previous users may need to fully wipe/reset the
SPIFFS/WifiManager settings by visiting
`http://<your_esp8266's_ip_address>/reset` prior to or
after update.
- Add Wifi filtering options to IRMQTTServer. (#679)
- Add advanced aircon/climate functionality to IRMQTTServer (#677)
- Initial prototype of a common interface for all A/Cs. (#664)
- Improve MQTT topic usage for feedback messages. (#663)
- Add multiple independent GPIO sending support via MQTT. (#661)
**[Misc]**
- Adjust kGreeHdrSpace to 4500 (#684, #686)
- Add Home Assistant mqtt climate instructions. (#682)
- Implement htmlEscape() to prevent XSS etc. (#681)
- Add F() Macros (#670)
- Update Daikin2's Cool mode min temp to 18C (#658)
- Change per byte bit-order in Electra protocol. (#648)
- Improve Daikin2 power on/off. (#647)
## _v2.5.6 (20190316)_
**[Bug Fixes]**
- Fix Coolix A/C Class to handle special states better. (#633, #624)
**[Features]**
- Fix case style for recent A/C protocols. (#631)
- Update `IRsend::send()` to include all simple protocols. (#629, #628)
- Experimental basic support for 112 bit TCL AC messages (#627, #619)
- Add support for TECO AC (#622)
- Experimental support for Samsung 36 bit protocol (#625, #621)
**[Misc]**
- Set Coolix to default to 1 repeat. (#637, #636, #624, #439)
- Set Daikin2 modulation to 36.7kHz. (#635)
- Refactor IRVestelAC class to use portable code. (#617)
- Adjust Daikin2 timings and tolerance. (#616, #582)
## _v2.5.5 (20190207)_
**[Bug Fixes]**
- Fix decoding of Samsung A/C Extended messages. (#610)
- Fix IRMQTTServer example to work with GPIO0 as IR_RX (#608)
- Fix incorrect #define usage. (#597, #596)
**[Features]**
- Add deep decoding/construction of Daikin2 messages (#600)
- Added Old Vestel A/C support (56 Bits) with full functions. (#607)
**[Misc]**
- Add ControlSamsungAC example code. (#599)
- Add how to send a state/air-con to IRsendDemo.ino (#594)
## _v2.5.4 (20190102)_
**[Features]**
- Experimental basic support for 39 Byte Daikin A/C (#583)
- Handle send() repeats in A/C classes. Improve Coolix support. (#580)
- Add optional RX pin pullup and dump raw messages in IRMQTTServer.ino (#589)
**[Misc]**
- Make auto_analyse_raw_data.py work with Python3 (#581)
- Update CI/travis config due to esp8266 core 2.5.0 changes (#591)
## _v2.5.3 (20181123)_
**[Features]**
- Add deep support for the Hitachi 28-Byte A/C Protocol (#563)
- Deep decoding for Whirlpool A/C (#572)
- Improve security options for IRMQTTServer example. (#575)
- Require a changed firmware password before upload. (#576)
**[Misc]**
- Add missing '}' in output of Auto analyse. (#562)
- Make A/C example code a bit more simple. (#571)
## _v2.5.2 (20181021)_ ## _v2.5.2 (20181021)_
**[Bug Fixes]** **[Bug Fixes]**

View File

@ -0,0 +1,99 @@
/* Copyright 2019 David Conran
*
* An IR LED circuit *MUST* be connected to the ESP8266 on a pin
* as specified by kIrLed below.
*
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
* have enough current to drive the IR LED effectively.
* * Make sure you have the IR LED polarity correct.
* See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity
* * Typical digital camera/phones can be used to see if the IR LED is flashed.
* Replace the IR LED with a normal LED if you don't have a digital camera
* when debugging.
* * Avoid using the following pins unless you really know what you are doing:
* * Pin 0/D3: Can interfere with the boot/program mode & support circuits.
* * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere.
* * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere.
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
* for your first time. e.g. ESP-12 etc.
*/
#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ir_Samsung.h>
const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2).
IRSamsungAc ac(kIrLed); // Set the GPIO used for sending messages.
void printState() {
// Display the settings.
Serial.println("Samsung A/C remote is in the following state:");
Serial.printf(" %s\n", ac.toString().c_str());
}
void setup() {
ac.begin();
Serial.begin(115200);
delay(200);
// Set up what we want to send. See ir_Samsung.cpp for all the options.
Serial.println("Default state of the remote.");
printState();
Serial.println("Setting initial state for A/C.");
ac.off();
ac.setFan(kSamsungAcFanLow);
ac.setMode(kSamsungAcCool);
ac.setTemp(25);
ac.setSwing(false);
printState();
}
void loop() {
// Turn the A/C unit on and set to cooling mode.
// Power changes require we send an extended message.
Serial.println("Sending an extended IR command to A/C ...");
ac.on();
ac.setMode(kSamsungAcCool);
ac.sendExtended();
printState();
delay(15000); // wait 15 seconds
// Increase the fan speed.
Serial.println("Sending a normal IR command to A/C ...");
ac.setFan(kSamsungAcFanHigh);
ac.send();
printState();
delay(15000);
// Change to swing the fan.
Serial.println("Sending a normal IR command to A/C ...");
ac.setSwing(true);
ac.send();
printState();
delay(15000);
// Change to Fan mode, lower the speed, and stop the swing.
Serial.println("Sending a normal IR command to A/C ...");
ac.setSwing(false);
ac.setMode(kSamsungAcFan);
ac.setFan(kSamsungAcFanLow);
ac.send();
printState();
delay(15000);
// Turn the A/C unit off.
// Power changes require we send an extended message.
Serial.println("Sending an extended IR command to A/C ...");
ac.off();
ac.sendExtended();
printState();
delay(15000); // wait 15 seconds
}

View File

@ -6,11 +6,13 @@ src_dir=.
build_flags = build_flags =
lib_deps_builtin = lib_deps_builtin =
lib_deps_external = lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2] [env:nodemcuv2]
platform = espressif8266 platform = espressif8266
framework = arduino framework = arduino
board = nodemcuv2 board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
lib_deps = lib_deps =
${common.lib_deps_builtin} ${common.lib_deps_builtin}

View File

@ -6,11 +6,13 @@ src_dir=.
build_flags = build_flags =
lib_deps_builtin = lib_deps_builtin =
lib_deps_external = lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2] [env:nodemcuv2]
platform = espressif8266 platform = espressif8266
framework = arduino framework = arduino
board = nodemcuv2 board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
lib_deps = lib_deps =
${common.lib_deps_builtin} ${common.lib_deps_builtin}

View File

@ -6,11 +6,13 @@ src_dir=.
build_flags = build_flags =
lib_deps_builtin = lib_deps_builtin =
lib_deps_external = lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2] [env:nodemcuv2]
platform = espressif8266 platform = espressif8266
framework = arduino framework = arduino
board = nodemcuv2 board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
lib_deps = lib_deps =
${common.lib_deps_builtin} ${common.lib_deps_builtin}

View File

@ -0,0 +1,258 @@
/*
* Send & receive arbitrary IR codes via a web server or MQTT.
* Copyright David Conran 2016, 2017, 2018, 2019
*/
#ifndef EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_
#define EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRsend.h>
#include <IRtimer.h>
#include <IRutils.h>
#include <IRac.h>
// ---------------- Start of User Configuration Section ------------------------
#ifndef MQTT_ENABLE
#define MQTT_ENABLE true // Whether or not MQTT is used at all.
#endif // MQTT_ENABLE
// ---------------------- Board Related Settings -------------------------------
// NOTE: Make sure you set your Serial Monitor to the same speed.
#define BAUD_RATE 115200 // Serial port Baud rate.
// GPIO the IR LED is connected to/controlled by. GPIO 4 = D2.
#define IR_LED 4 // <=- CHANGE_ME (optional)
// define IR_LED 3 // For an ESP-01 we suggest you use RX/GPIO3/Pin 7.
// GPIO the IR RX module is connected to/controlled by. e.g. GPIO 14 = D5.
// Comment this out to disable receiving/decoding IR messages entirely.
#define IR_RX 14 // <=- CHANGE_ME (optional)
#define IR_RX_PULLUP false
// --------------------- Network Related Settings ------------------------------
const uint16_t kHttpPort = 80; // The TCP port the HTTP server is listening on.
// Change to 'true'/'false' if you do/don't want these features or functions.
#define USE_STATIC_IP false // Change to 'true' if you don't want to use DHCP.
// We obtain our network config via DHCP by default but allow an easy way to
// use a static IP config.
#if USE_STATIC_IP
const IPAddress kIPAddress = IPAddress(10, 0, 1, 78);
const IPAddress kGateway = IPAddress(10, 0, 1, 1);
const IPAddress kSubnetMask = IPAddress(255, 255, 255, 0);
#endif // USE_STATIC_IP
// See: https://github.com/tzapu/WiFiManager#filter-networks for these settings.
#define HIDE_DUPLIATE_NETWORKS false // Should WifiManager hide duplicate SSIDs
// #define MIN_SIGNAL_STRENGTH 20 // Minimum WiFi signal stength (percentage)
// before we will connect.
// The unset default is 8%.
// (Uncomment to enable)
// ----------------------- HTTP Related Settings -------------------------------
#define FIRMWARE_OTA true // Allow remote update of the firmware via http.
// Less secure if enabled.
// Note: Firmware OTA is also disabled until
// a password is set.
#define HTML_PASSWORD_ENABLE false // Protect access to the HTML interface.
// Note: OTA update is always passworded.
// If you do not set a password, Firmware OTA updates will be blocked.
// ----------------------- MQTT Related Settings -------------------------------
#if MQTT_ENABLE
const uint32_t kMqttReconnectTime = 5000; // Delay(ms) between reconnect tries.
#define MQTT_ACK "sent" // Sub-topic we send back acknowledgements on.
#define MQTT_SEND "send" // Sub-topic we get new commands from.
#define MQTT_RECV "received" // Topic we send received IRs to.
#define MQTT_LOG "log" // Topic we send log messages to.
#define MQTT_LWT "status" // Topic for the Last Will & Testament.
#define MQTT_CLIMATE "ac" // Sub-topic for the climate topics.
#define MQTT_CLIMATE_CMND "cmnd" // Sub-topic for the climate command topics.
#define MQTT_CLIMATE_STAT "stat" // Sub-topic for the climate stat topics.
#define MQTTbroadcastInterval 10 * 60 // Seconds between rebroadcasts
#define QOS 1 // MQTT broker should queue up any unreceived messages for us
// #define QOS 0 // MQTT broker WON'T queue up messages for us. Fire & Forget.
#endif // MQTT_ENABLE
// ------------------------ IR Capture Settings --------------------------------
// Let's use a larger than normal buffer so we can handle AirCon remote codes.
const uint16_t kCaptureBufferSize = 1024;
#if DECODE_AC
// Some A/C units have gaps in their protocols of ~40ms. e.g. Kelvinator
// A value this large may swallow repeats of some protocols
const uint8_t kCaptureTimeout = 50; // Milliseconds
#else // DECODE_AC
// Suits most messages, while not swallowing many repeats.
const uint8_t kCaptureTimeout = 15; // Milliseconds
#endif // DECODE_AC
// Ignore unknown messages with <10 pulses (see also REPORT_UNKNOWNS)
const uint16_t kMinUnknownSize = 2 * 10;
#define REPORT_UNKNOWNS false // Report inbound IR messages that we don't know.
#define REPORT_RAW_UNKNOWNS false // Report the whole buffer, recommended:
// MQTT_MAX_PACKET_SIZE of 1024 or more
// ------------------------ Advanced Usage Only --------------------------------
// Change if you need multiple independent send gpio/topics.
const uint8_t gpioTable[] = {
IR_LED, // Default GPIO. e.g. ir_server/send or ir_server/send_0
// Uncomment the following as needed.
// NOTE: Remember to disable DEBUG if you are using one of the serial pins.
// 5, // GPIO 5 / D1 e.g. ir_server/send_1
// 14, // GPIO 14 / D5 e.g. ir_server/send_2
// 16, // GPIO 16 / D0 e.g. ir_server/send_3
};
#define KEY_PROTOCOL "protocol"
#define KEY_MODEL "model"
#define KEY_POWER "power"
#define KEY_MODE "mode"
#define KEY_TEMP "temp"
#define KEY_FANSPEED "fanspeed"
#define KEY_SWINGV "swingv"
#define KEY_SWINGH "swingh"
#define KEY_QUIET "quiet"
#define KEY_TURBO "turbo"
#define KEY_LIGHT "light"
#define KEY_BEEP "beep"
#define KEY_ECONO "econo"
#define KEY_SLEEP "sleep"
#define KEY_CLOCK "clock"
#define KEY_FILTER "filter"
#define KEY_CLEAN "clean"
#define KEY_CELSIUS "use_celsius"
// HTML arguments we will parse for IR code information.
#define KEY_TYPE "type" // KEY_PROTOCOL is also checked too.
#define KEY_CODE "code"
#define KEY_BITS "bits"
#define KEY_REPEAT "repeats"
// Text for Last Will & Testament status messages.
const char* kLwtOnline = "Online";
const char* kLwtOffline = "Offline";
const uint8_t kHostnameLength = 30;
const uint8_t kPortLength = 5; // Largest value of uint16_t is "65535".
const uint8_t kUsernameLength = 15;
const uint8_t kPasswordLength = 20;
// -------------------------- Debug Settings -----------------------------------
// Disable debug output if any of the IR pins are on the TX (D1) pin.
// Note: This is a crude method to catch the common use cases.
// See `isSerialGpioUsedByIr()` for the better method.
#if (IR_LED != 1 && IR_RX != 1)
#ifndef DEBUG
#define DEBUG true // Change to 'false' to disable all serial output.
#endif // DEBUG
#else // (IR_LED != 1 && IR_RX != 1)
#undef DEBUG
#define DEBUG false
#endif
// ----------------- End of User Configuration Section -------------------------
// Constants
#define _MY_VERSION_ "v1.0.0"
const uint8_t kSendTableSize = sizeof(gpioTable);
// JSON stuff
// Name of the json config file in SPIFFS.
const char* kConfigFile = "/config.json";
const char* kMqttServerKey = "mqtt_server";
const char* kMqttPortKey = "mqtt_port";
const char* kMqttUserKey = "mqtt_user";
const char* kMqttPassKey = "mqtt_pass";
const char* kMqttPrefixKey = "mqtt_prefix";
const char* kHostnameKey = "hostname";
const char* kHttpUserKey = "http_user";
const char* kHttpPassKey = "http_pass";
#if MQTT_ENABLE
const uint32_t kBroadcastPeriodMs = MQTTbroadcastInterval * 1000; // mSeconds.
const uint32_t kStatListenPeriodMs = 5 * 1000; // mSeconds
void mqttCallback(char* topic, byte* payload, unsigned int length);
String listOfCommandTopics(void);
void handleSendMqttDiscovery(void);
void subscribing(const String topic_name);
void unsubscribing(const String topic_name);
void mqttLog(const String mesg);
bool reconnect(void);
void receivingMQTT(String const topic_name, String const callback_str);
void callback(char* topic, byte* payload, unsigned int length);
void sendMQTTDiscovery(const char *topic);
void doBroadcast(TimerMs *timer, const uint32_t interval,
const commonAcState_t state, const bool retain,
const bool force);
#endif // MQTT_ENABLE
bool isSerialGpioUsedByIr(void);
void debug(const char *str);
void saveWifiConfigCallback(void);
void saveWifiConfig(void);
void loadWifiConfigFile(void);
String msToHumanString(uint32_t const msecs);
String timeElapsed(uint32_t const msec);
String timeSince(uint32_t const start);
String listOfSendGpios(void);
bool hasUnsafeHTMLChars(String input);
String htmlMenu(void);
void handleRoot(void);
String addJsReloadUrl(const String url, const uint16_t timeout_s,
const bool notify);
void handleExamples(void);
String boolToString(const bool value);
String opmodeToString(const stdAc::opmode_t mode);
String fanspeedToString(const stdAc::fanspeed_t speed);
String swingvToString(const stdAc::swingv_t swingv);
String swinghToString(const stdAc::swingh_t swingh);
String htmlSelectBool(const String name, const bool def);
String htmlSelectProtocol(const String name, const decode_type_t def);
String htmlSelectModel(const String name, const int16_t def);
String htmlSelectMode(const String name, const stdAc::opmode_t def);
String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def);
String htmlSelectSwingv(const String name, const stdAc::swingv_t def);
String htmlSelectSwingh(const String name, const stdAc::swingh_t def);
void handleAirCon(void);
void handleAirConSet(void);
void handleAdmin(void);
void handleInfo(void);
void handleReset(void);
void handleReboot(void);
bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType,
const String str);
uint16_t countValuesInStr(const String str, char sep);
uint16_t * newCodeArray(const uint16_t size);
#if SEND_GLOBALCACHE
bool parseStringAndSendGC(IRsend *irsend, const String str);
#endif // SEND_GLOBALCACHE
#if SEND_PRONTO
bool parseStringAndSendPronto(IRsend *irsend, const String str,
uint16_t repeats);
#endif // SEND_PRONTO
#if SEND_RAW
bool parseStringAndSendRaw(IRsend *irsend, const String str);
#endif // SEND_RAW
void handleIr(void);
void handleNotFound(void);
void setup_wifi(void);
void init_vars(void);
void setup(void);
void loop(void);
uint64_t getUInt64fromHex(char const *str);
bool sendIRCode(IRsend *irsend, int const ir_type,
uint64_t const code, char const * code_str, uint16_t bits,
uint16_t repeat);
bool sendInt(const String topic, const int32_t num, const bool retain);
bool sendBool(const String topic, const bool on, const bool retain);
bool sendString(const String topic, const String str, const bool retain);
bool sendFloat(const String topic, const float_t temp, const bool retain);
commonAcState_t updateClimate(commonAcState_t current, const String str,
const String prefix, const String payload);
bool cmpClimate(const commonAcState_t a, const commonAcState_t b);
bool sendClimate(const commonAcState_t prev, const commonAcState_t next,
const String topic_prefix, const bool retain,
const bool forceMQTT, const bool forceIR);
#endif // EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_

File diff suppressed because it is too large Load Diff

View File

@ -3,16 +3,19 @@ lib_extra_dirs = ../../
src_dir=. src_dir=.
[common] [common]
build_flags = -DMQTT_MAX_PACKET_SIZE=512 build_flags = -DMQTT_MAX_PACKET_SIZE=768
lib_ldf_mode = chain+
lib_deps_builtin = lib_deps_builtin =
lib_deps_external = lib_deps_external =
PubSubClient PubSubClient
WifiManager@0.14 WifiManager@0.14
ArduinoJson
[env:nodemcuv2] [env:nodemcuv2]
platform = espressif8266 platform = espressif8266
framework = arduino framework = arduino
board = nodemcuv2 board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
lib_deps = lib_deps =
${common.lib_deps_builtin} ${common.lib_deps_builtin}
@ -22,7 +25,18 @@ lib_deps =
platform=espressif8266 platform=espressif8266
framework=arduino framework=arduino
board=d1_mini board=d1_mini
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
lib_deps = lib_deps =
${common.lib_deps_builtin} ${common.lib_deps_builtin}
${common.lib_deps_external} ${common.lib_deps_external}
[env:d1_mini_no_mqtt]
platform=espressif8266
framework=arduino
board=d1_mini
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags} -DMQTT_ENABLE=false
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -6,11 +6,13 @@ src_dir=.
build_flags = build_flags =
lib_deps_builtin = lib_deps_builtin =
lib_deps_external = lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2] [env:nodemcuv2]
platform = espressif8266 platform = espressif8266
framework = arduino framework = arduino
board = nodemcuv2 board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
lib_deps = lib_deps =
${common.lib_deps_builtin} ${common.lib_deps_builtin}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -35,9 +35,15 @@
#include <ir_Kelvinator.h> #include <ir_Kelvinator.h>
#include <ir_Midea.h> #include <ir_Midea.h>
#include <ir_Mitsubishi.h> #include <ir_Mitsubishi.h>
#include <ir_MitsubishiHeavy.h>
#include <ir_Panasonic.h> #include <ir_Panasonic.h>
#include <ir_Samsung.h> #include <ir_Samsung.h>
#include <ir_Tcl.h>
#include <ir_Teco.h>
#include <ir_Toshiba.h> #include <ir_Toshiba.h>
#include <ir_Vestel.h>
#include <ir_Whirlpool.h>
// ==================== start of TUNEABLE PARAMETERS ==================== // ==================== start of TUNEABLE PARAMETERS ====================
// An IR detector/demodulator is connected to GPIO pin 14 // An IR detector/demodulator is connected to GPIO pin 14
@ -121,6 +127,20 @@ void dumpACInfo(decode_results *results) {
description = ac.toString(); description = ac.toString();
} }
#endif // DECODE_DAIKIN #endif // DECODE_DAIKIN
#if DECODE_DAIKIN2
if (results->decode_type == DAIKIN2) {
IRDaikin2 ac(0);
ac.setRaw(results->state);
description = ac.toString();
}
#endif // DECODE_DAIKIN2
#if DECODE_DAIKIN216
if (results->decode_type == DAIKIN216) {
IRDaikin216 ac(0);
ac.setRaw(results->state);
description = ac.toString();
}
#endif // DECODE_DAIKIN216
#if DECODE_FUJITSU_AC #if DECODE_FUJITSU_AC
if (results->decode_type == FUJITSU_AC) { if (results->decode_type == FUJITSU_AC) {
IRFujitsuAC ac(0); IRFujitsuAC ac(0);
@ -142,6 +162,18 @@ void dumpACInfo(decode_results *results) {
description = ac.toString(); description = ac.toString();
} }
#endif // DECODE_MITSUBISHI_AC #endif // DECODE_MITSUBISHI_AC
#if DECODE_MITSUBISHIHEAVY
if (results->decode_type == MITSUBISHI_HEAVY_88) {
IRMitsubishiHeavy88Ac ac(0);
ac.setRaw(results->state);
description = ac.toString();
}
if (results->decode_type == MITSUBISHI_HEAVY_152) {
IRMitsubishiHeavy152Ac ac(0);
ac.setRaw(results->state);
description = ac.toString();
}
#endif // DECODE_MITSUBISHIHEAVY
#if DECODE_TOSHIBA_AC #if DECODE_TOSHIBA_AC
if (results->decode_type == TOSHIBA_AC) { if (results->decode_type == TOSHIBA_AC) {
IRToshibaAC ac(0); IRToshibaAC ac(0);
@ -180,7 +212,7 @@ void dumpACInfo(decode_results *results) {
#if DECODE_SAMSUNG_AC #if DECODE_SAMSUNG_AC
if (results->decode_type == SAMSUNG_AC) { if (results->decode_type == SAMSUNG_AC) {
IRSamsungAc ac(0); IRSamsungAc ac(0);
ac.setRaw(results->state); ac.setRaw(results->state, results->bits / 8);
description = ac.toString(); description = ac.toString();
} }
#endif // DECODE_SAMSUNG_AC #endif // DECODE_SAMSUNG_AC
@ -206,6 +238,34 @@ void dumpACInfo(decode_results *results) {
description = ac.toString(); description = ac.toString();
} }
#endif // DECODE_HITACHI_AC #endif // DECODE_HITACHI_AC
#if DECODE_WHIRLPOOL_AC
if (results->decode_type == WHIRLPOOL_AC) {
IRWhirlpoolAc ac(0);
ac.setRaw(results->state);
description = ac.toString();
}
#endif // DECODE_WHIRLPOOL_AC
#if DECODE_VESTEL_AC
if (results->decode_type == VESTEL_AC) {
IRVestelAc ac(0);
ac.setRaw(results->value); // Like Coolix, use value instead of state.
description = ac.toString();
}
#endif // DECODE_VESTEL_AC
#if DECODE_TECO
if (results->decode_type == TECO) {
IRTecoAc ac(0);
ac.setRaw(results->value); // Like Coolix, use value instead of state.
description = ac.toString();
}
#endif // DECODE_TECO
#if DECODE_TCL112AC
if (results->decode_type == TCL112AC) {
IRTcl112Ac ac(0);
ac.setRaw(results->state);
description = ac.toString();
}
#endif // DECODE_TCL112AC
// If we got a human-readable description of the message, display it. // If we got a human-readable description of the message, display it.
if (description != "") Serial.println("Mesg Desc.: " + description); if (description != "") Serial.println("Mesg Desc.: " + description);
} }

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -1,6 +1,6 @@
/* IRremoteESP8266: IRsendDemo - demonstrates sending IR codes with IRsend. /* IRremoteESP8266: IRsendDemo - demonstrates sending IR codes with IRsend.
* *
* Version 1.0 April, 2017 * Version 1.1 January, 2019
* Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009,
* Copyright 2009 Ken Shirriff, http://arcfn.com * Copyright 2009 Ken Shirriff, http://arcfn.com
* *
@ -46,6 +46,10 @@ uint16_t rawData[67] = {9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550,
650, 550, 650, 550, 600, 550, 650, 550, 650, 550, 650, 550, 650, 550, 600, 550, 650, 550, 650, 550,
650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650,
650, 1650, 650, 1650, 650, 1650, 600}; 650, 1650, 650, 1650, 650, 1650, 600};
// Example Samsung A/C state captured from IRrecvDumpV2.ino
uint8_t samsungState[kSamsungAcStateLength] = {
0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0};
void setup() { void setup() {
irsend.begin(); irsend.begin();
@ -53,19 +57,16 @@ void setup() {
} }
void loop() { void loop() {
#if SEND_NEC
Serial.println("NEC"); Serial.println("NEC");
irsend.sendNEC(0x00FFE01FUL, 32); irsend.sendNEC(0x00FFE01FUL);
#endif // SEND_NEC
delay(2000); delay(2000);
#if SEND_SONY
Serial.println("Sony"); Serial.println("Sony");
irsend.sendSony(0xa90, 12, 2); irsend.sendSony(0xa90, 12, 2); // 12 bits & 2 repeats
#endif // SEND_SONY
delay(2000); delay(2000);
#if SEND_RAW
Serial.println("a rawData capture from IRrecvDumpV2"); Serial.println("a rawData capture from IRrecvDumpV2");
irsend.sendRaw(rawData, 67, 38); // Send a raw data capture at 38kHz. irsend.sendRaw(rawData, 67, 38); // Send a raw data capture at 38kHz.
#endif // SEND_RAW delay(2000);
Serial.println("a Samsung A/C state from IRrecvDumpV2");
irsend.sendSamsungAC(samsungState);
delay(2000); delay(2000);
} }

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,72 @@
/* Copyright 2019 David Conran
*
* An IR LED circuit *MUST* be connected to the ESP8266 on a pin
* as specified by kIrLed below.
*
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
* have enough current to drive the IR LED effectively.
* * Make sure you have the IR LED polarity correct.
* See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity
* * Typical digital camera/phones can be used to see if the IR LED is flashed.
* Replace the IR LED with a normal LED if you don't have a digital camera
* when debugging.
* * Avoid using the following pins unless you really know what you are doing:
* * Pin 0/D3: Can interfere with the boot/program mode & support circuits.
* * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere.
* * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere.
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
* for your first time. e.g. ESP-12 etc.
*/
#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ir_MitsubishiHeavy.h>
const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2).
IRMitsubishiHeavy152Ac ac(kIrLed); // Set the GPIO used for sending messages.
void printState() {
// Display the settings.
Serial.println("Mitsubishi Heavy A/C remote is in the following state:");
Serial.printf(" %s\n", ac.toString().c_str());
// Display the encoded IR sequence.
unsigned char* ir_code = ac.getRaw();
Serial.print("IR Code: 0x");
for (uint8_t i = 0; i < kMitsubishiHeavy152StateLength; i++)
Serial.printf("%02X", ir_code[i]);
Serial.println();
}
void setup() {
ac.begin();
Serial.begin(115200);
delay(200);
// Set up what we want to send. See ir_MitsubishiHeavy.(cpp|h) for all the
// options.
Serial.println("Default state of the remote.");
printState();
Serial.println("Setting desired state for A/C.");
ac.setPower(true); // Turn it on.
ac.setFan(kMitsubishiHeavy152FanMed); // Medium Fan
ac.setMode(kMitsubishiHeavyCool); // Cool mode
ac.setTemp(26); // Celsius
ac.setSwingVertical(kMitsubishiHeavy152SwingVAuto); // Swing vertically
ac.setSwingHorizontal(kMitsubishiHeavy152SwingHMiddle); // Swing Horizontally
}
void loop() {
// Now send the IR signal.
Serial.println("Sending IR command to A/C ...");
ac.send();
printState();
delay(5000);
}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,74 @@
/* Copyright 2017, 2018 David Conran
*
* An IR LED circuit *MUST* be connected to the ESP8266 on a pin
* as specified by kIrLed below.
*
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
*
* Suggested circuit:
* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
*
* Common mistakes & tips:
* * Don't just connect the IR LED directly to the pin, it won't
* have enough current to drive the IR LED effectively.
* * Make sure you have the IR LED polarity correct.
* See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity
* * Typical digital camera/phones can be used to see if the IR LED is flashed.
* Replace the IR LED with a normal LED if you don't have a digital camera
* when debugging.
* * Avoid using the following pins unless you really know what you are doing:
* * Pin 0/D3: Can interfere with the boot/program mode & support circuits.
* * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere.
* * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere.
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
* for your first time. e.g. ESP-12 etc.
*/
#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ir_Panasonic.h>
const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2).
IRPanasonicAc ac(kIrLed); // Set the GPIO used for sending messages.
void printState() {
// Display the settings.
Serial.println("Panasonic A/C remote is in the following state:");
Serial.printf(" %s\n", ac.toString().c_str());
// Display the encoded IR sequence.
unsigned char* ir_code = ac.getRaw();
Serial.print("IR Code: 0x");
for (uint8_t i = 0; i < kPanasonicAcStateLength; i++)
Serial.printf("%02X", ir_code[i]);
Serial.println();
}
void setup() {
ac.begin();
Serial.begin(115200);
delay(200);
// Set up what we want to send. See ir_Panasonic.cpp for all the options.
Serial.println("Default state of the remote.");
printState();
Serial.println("Setting desired state for A/C.");
ac.setModel(kPanasonicRkr);
ac.on();
ac.setFan(kPanasonicAcFanAuto);
ac.setMode(kPanasonicAcCool);
ac.setTemp(26);
ac.setSwingVertical(kPanasonicAcSwingVAuto);
ac.setSwingHorizontal(kPanasonicAcSwingHAuto);
}
void loop() {
// Now send the IR signal.
#if SEND_PANASONIC_AC
Serial.println("Sending IR command to A/C ...");
ac.send();
#endif // SEND_PANASONIC_AC
printState();
delay(5000);
}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

@ -0,0 +1,19 @@
[platformio]
lib_extra_dirs = ../../
src_dir=.
[common]
build_flags =
lib_deps_builtin =
lib_deps_external =
lib_ldf_mode = chain+
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More