mirror of https://github.com/arendst/Tasmota.git
parent
b0cf8e1437
commit
c702cb17e0
|
@ -9,6 +9,11 @@
|
|||
.gcc-flags.json
|
||||
sonoff/user_config_override.h
|
||||
build
|
||||
firmware.map
|
||||
|
||||
## Visual Studio Code specific ######
|
||||
.vscode
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
*.bak
|
||||
|
|
5
API.md
5
API.md
|
@ -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.
|
||||
|
||||
Callback availability can be checked by searching for either XdrvCall, XsnsCall, XdspCall and XnrgCall.
|
||||
|
|
|
@ -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!**
|
||||
|
||||
|
@ -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.
|
||||
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.
|
||||
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 isn’t 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.
|
||||
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.
|
||||
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.
|
||||
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_ you’re 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>
|
||||
<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.>
|
||||
|
|
70
README.md
70
README.md
|
@ -1,6 +1,6 @@
|
|||
## 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 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.
|
||||
|
||||
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:
|
||||
|
||||
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.
|
||||
|
||||
### 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
|
||||
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
|
||||
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.
|
||||
- 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).
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
### Version Information
|
||||
- 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.
|
||||
|
||||
### Migration Information
|
||||
|
@ -53,51 +53,11 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade
|
|||
### Support Information
|
||||
<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 />
|
||||
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.<br />
|
||||
See [Chat](https://discord.gg/Ks2Kzd4) for more user experience.
|
||||
For a database of supported devices see [Tasmota Device Templates Repository](https://blakadder.github.io/templates)
|
||||
|
||||
The following devices are supported:
|
||||
- [iTead Sonoff Basic (R2)](https://www.itead.cc/smart-home/sonoff-wifi-wireless-switch-1.html)
|
||||
- [iTead Sonoff RF](https://www.itead.cc/smart-home/sonoff-rf.html)
|
||||
- [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/)
|
||||
See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for use instructions and how-to's.<br />
|
||||
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.<br />
|
||||
Visit [Discord Chat](https://discord.gg/Ks2Kzd4) for discussions and troubleshooting.
|
||||
|
||||
### Contribute
|
||||
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
|
||||
- Aidan Mountford for his HSB support
|
||||
- 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
|
||||
- Adrian Scillato for his (security)fixes and implementing and maintaining KNX
|
||||
- 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
|
||||
- Frogmore42 and Jason2866 for providing many issue answers
|
||||
- Blakadder for editing the wiki and providing template management
|
||||
- Stephan Hadinger for refactoring light driver and enhancing HueEmulation
|
||||
- tmo for designing the official logo
|
||||
- Many more providing Tips, Wips, Pocs or PRs
|
||||
|
||||
### License
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
## Tasmota Reference
|
||||
<img src="/tools/logo/TASMOTA_FullLogo_Vector.svg" alt="Logo" align="right" height="76"/>
|
||||
|
||||
# Reference
|
||||
|
||||
Tasmota backgound information.
|
||||
|
||||
## Supported Smart Switch with Energy Monitoring GPIO usage
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
<img src="/tools/logo/TASMOTA_FullLogo_Vector.svg" alt="Logo" align="right" height="76"/>
|
||||
|
||||
# RELEASE NOTES
|
||||
|
||||
## Migration Information
|
||||
See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates:
|
||||
|
||||
|
@ -6,11 +10,10 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade
|
|||
3. Migrate to **Sonoff-Tasmota 5.14**
|
||||
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/
|
||||
|
||||
### 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**.
|
||||
|
||||
To save memory space all other binaries support **WifiManager only**.
|
||||
|
@ -71,14 +74,14 @@ Module | Description
|
|||
49 Neo Coolcam | Neo Coolcam Wifi Smart Socket
|
||||
50 ESP Switch | ESP Switch 4-gang Wifi Switch with Leds
|
||||
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
|
||||
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
|
||||
56 ARMTR Dimmer | ARMtronix Wifi dimmer for Incandescent Lights and Led
|
||||
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
|
||||
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
|
||||
61 OBI Socket 2 | OBI 2 Wifi Smart Socket
|
||||
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/
|
||||
|
||||
### Available Features and Sensors
|
||||
## Available Features and Sensors
|
||||
|
||||
| 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_RF_SENSOR | - | - | - | - | - | x | - | AlectoV2 only
|
||||
| USE_SM16716 | - | x | x | x | x | x | x |
|
||||
| USE_HRE | - | - | - | - | - | x | - |
|
||||
| USE_DISPLAY | - | - | - | - | - | - | x |
|
||||
| USE_DISPLAY_LCD | - | - | - | - | - | - | x |
|
||||
| USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x |
|
||||
|
|
13
SUPPORT.md
13
SUPPORT.md
|
@ -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:
|
||||
|
||||
### Documentation:
|
||||
## Documentation:
|
||||
|
||||
* [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.
|
||||
|
||||
### Support's Community:
|
||||
## Support's Community:
|
||||
|
||||
* [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions.
|
||||
* [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community.
|
||||
* [Search in Issues](https://github.com/arendst/Sonoff-Tasmota/issues): You might find an answer to your question by searching current or closed issues.
|
||||
|
||||
### Developers' Community:
|
||||
## Developers' Community:
|
||||
|
||||
* [Bug Report](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software.
|
||||
* [Feature Request](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software.
|
||||
|
|
|
@ -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.
|
||||
|
||||
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}``
|
||||
|
||||
The following command will update the base of a stored template to Generic
|
||||
``Template {"BASE":0}``
|
||||
``Template {"BASE":0}``
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,14 +3,20 @@
|
|||
# ------------------------------
|
||||
|
||||
# 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.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.none=-w
|
||||
|
@ -24,31 +30,35 @@ build.lwip_flags=-DLWIP_OPEN_SRC
|
|||
|
||||
build.vtable_flags=-DVTABLES_IN_FLASH
|
||||
|
||||
build.sslflags=
|
||||
|
||||
build.exception_flags=-fno-exceptions
|
||||
build.stdcpp_lib=-lstdc++
|
||||
|
||||
#build.float=-u _printf_float -u _scanf_float
|
||||
build.float=
|
||||
build.led=
|
||||
build.sdk=NONOSDK221
|
||||
|
||||
compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
|
||||
compiler.sdk.path={runtime.platform.path}/tools/sdk
|
||||
|
||||
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.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.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.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.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
|
||||
|
||||
|
@ -60,9 +70,6 @@ compiler.elf2hex.flags=
|
|||
|
||||
compiler.size.cmd=xtensa-lx106-elf-size
|
||||
|
||||
compiler.esptool.cmd=esptool
|
||||
compiler.esptool.cmd.windows=esptool.exe
|
||||
|
||||
# This can be overriden in boards.txt
|
||||
build.extra_flags=-DESP8266
|
||||
|
||||
|
@ -77,26 +84,20 @@ compiler.elf2hex.extra_flags=
|
|||
|
||||
## generate file with git version number
|
||||
## 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.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"
|
||||
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"
|
||||
|
||||
## 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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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=
|
||||
|
||||
## 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.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=
|
||||
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"
|
||||
|
||||
## Save hex
|
||||
recipe.output.tmp_file={build.project_name}.bin
|
||||
|
@ -123,22 +118,30 @@ recipe.output.save_file={build.project_name}.{build.variant}.bin
|
|||
|
||||
## Compute size
|
||||
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.eeprom=^(?:\.eeprom)\s+([0-9]+).*
|
||||
|
||||
# ------------------------------
|
||||
|
||||
tools.esptool.cmd=esptool
|
||||
tools.esptool.cmd.windows=esptool.exe
|
||||
tools.esptool.path={runtime.tools.esptool.path}
|
||||
tools.esptool.network_cmd=python
|
||||
tools.esptool.network_cmd.windows=python.exe
|
||||
tools.esptool.path=
|
||||
# Because the variable expansion doesn't allow one tool to find another, the following lines
|
||||
# will point to "{runtime.platform.path}/tools/python/python" in GIT and
|
||||
# "{runtime.tools.python.path}/python" for JSON board manager releases.
|
||||
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.params.verbose=-vv
|
||||
tools.esptool.upload.params.verbose=--trace
|
||||
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.mkspiffs.cmd=mkspiffs
|
||||
|
@ -152,4 +155,3 @@ tools.espupload.upload.protocol=espupload
|
|||
tools.espupload.upload.params.verbose=
|
||||
tools.espupload.upload.params.quiet=
|
||||
tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin"
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
//#define I2C_DEBUG
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
/*!
|
||||
@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
|
||||
then reads the serialnumber and checks that we are talking to an SGP30
|
||||
@param theWire Optional pointer to I2C interface, otherwise use Wire
|
||||
|
@ -60,31 +60,32 @@ boolean Adafruit_SGP30::begin(TwoWire *theWire) {
|
|||
_i2c = theWire;
|
||||
}
|
||||
|
||||
_i2c->begin();
|
||||
// assume i2c initialized already to avoid resetting clock stretching
|
||||
// _i2c->begin();
|
||||
|
||||
|
||||
|
||||
uint8_t command[2];
|
||||
command[0] = 0x36;
|
||||
command[1] = 0x82;
|
||||
if (! readWordFromCommand(command, 2, 10, serialnumber, 3))
|
||||
if (! readWordFromCommand(command, 2, 10, serialnumber, 3))
|
||||
return false;
|
||||
|
||||
uint16_t featureset;
|
||||
command[0] = 0x20;
|
||||
command[1] = 0x2F;
|
||||
if (! readWordFromCommand(command, 2, 10, &featureset, 1))
|
||||
if (! readWordFromCommand(command, 2, 10, &featureset, 1))
|
||||
return false;
|
||||
//Serial.print("Featureset 0x"); Serial.println(featureset, HEX);
|
||||
if (featureset != SGP30_FEATURESET)
|
||||
if (featureset != SGP30_FEATURESET)
|
||||
return false;
|
||||
if (! IAQinit())
|
||||
if (! IAQinit())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
/*!
|
||||
@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!
|
||||
*/
|
||||
|
@ -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}
|
||||
@returns True if command completed successfully, false if something went wrong!
|
||||
*/
|
||||
|
@ -113,9 +114,9 @@ boolean Adafruit_SGP30::IAQmeasure(void) {
|
|||
eCO2 = reply[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
/*!
|
||||
@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 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.
|
||||
@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
|
||||
|
@ -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
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
@ -186,16 +210,16 @@ boolean Adafruit_SGP30::readWordFromCommand(uint8_t command[], uint8_t commandLe
|
|||
|
||||
delay(delayms);
|
||||
|
||||
if (readlen == 0)
|
||||
if (readlen == 0)
|
||||
return true;
|
||||
|
||||
uint8_t replylen = readlen * (SGP30_WORD_LEN +1);
|
||||
if (_i2c->requestFrom(_i2caddr, replylen) != replylen)
|
||||
if (_i2c->requestFrom(_i2caddr, replylen) != replylen)
|
||||
return false;
|
||||
uint8_t replybuffer[replylen];
|
||||
#ifdef I2C_DEBUG
|
||||
Serial.print("\t\t<- ");
|
||||
#endif
|
||||
#endif
|
||||
for (uint8_t i=0; i<replylen; i++) {
|
||||
replybuffer[i] = _i2c->read();
|
||||
#ifdef I2C_DEBUG
|
|
@ -42,6 +42,7 @@ class Adafruit_SGP30 {
|
|||
|
||||
boolean getIAQBaseline(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()}
|
|
@ -3,6 +3,17 @@
|
|||
|
||||
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() {
|
||||
Serial.begin(9600);
|
||||
Serial.println("SGP30 test");
|
||||
|
@ -22,6 +33,11 @@ void setup() {
|
|||
|
||||
int counter = 0;
|
||||
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()) {
|
||||
Serial.println("Measurement failed");
|
||||
return;
|
|
@ -1,5 +1,5 @@
|
|||
name=Adafruit SGP30 Sensor
|
||||
version=1.0.2
|
||||
version=1.0.3
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=This is an Arduino library for the Adafruit SGP30 Gas / Air Quality Sensor
|
File diff suppressed because it is too large
Load Diff
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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));
|
||||
}
|
|
@ -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
|
|
@ -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_
|
|
@ -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]; }
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -12,7 +12,9 @@
|
|||
- [Jorge Cisneros](https://github.com/jorgecis/)
|
||||
- [Denes Varga](https://github.com/denxhun/)
|
||||
- [Brett T. Warden](https://github.com/bwarden/)
|
||||
- [Fabien Valthier](https://github.com/hcoohb)
|
||||
- [Ajay Pala](https://github.com/ajaypala/)
|
||||
|
||||
All contributors can be found on the [contributors site](https://github.com/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)
|
|
@ -1,20 +1,21 @@
|
|||
language: c
|
||||
env:
|
||||
- BD=esp8266:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M
|
||||
- BD=esp8266:esp8266:d1_mini:CpuFrequency=80,FlashSize=4M3M
|
||||
- BD=esp8266:esp8266:nodemcuv2:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled
|
||||
- BD=esp8266:esp8266:d1_mini:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled
|
||||
before_install:
|
||||
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
|
||||
- sleep 3
|
||||
- export DISPLAY=:1.0
|
||||
- wget http://downloads.arduino.cc/arduino-1.8.2-linux64.tar.xz
|
||||
- tar xf arduino-1.8.2-linux64.tar.xz
|
||||
- sudo mv arduino-1.8.2 /usr/local/share/arduino
|
||||
- wget http://downloads.arduino.cc/arduino-1.8.8-linux64.tar.xz
|
||||
- tar xf arduino-1.8.8-linux64.tar.xz
|
||||
- sudo mv arduino-1.8.8 /usr/local/share/arduino
|
||||
- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
|
||||
- wget https://raw.githubusercontent.com/google/styleguide/gh-pages/cpplint/cpplint.py
|
||||
install:
|
||||
- ln -s $PWD /usr/local/share/arduino/libraries/
|
||||
- git clone https://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WiFiManager
|
||||
- git clone https://github.com/knolleary/pubsubclient.git /usr/local/share/arduino/libraries/PubSubClient
|
||||
- git clone https://github.com/bblanchon/ArduinoJson.git --branch 5.x /usr/local/share/arduino/libraries/ArduinoJson
|
||||
- arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs
|
||||
- arduino --install-boards esp8266:esp8266
|
||||
- arduino --board $BD --save-prefs
|
||||
|
@ -40,6 +41,10 @@ script:
|
|||
- arduino --verify --board $BD $PWD/examples/TurnOnArgoAC/TurnOnArgoAC.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/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.
|
||||
- (cd tools; make all)
|
||||
# Check for lint issues.
|
|
@ -1,14 +1,15 @@
|
|||
# IRremote ESP8266 Library
|
||||
|
||||
[![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")
|
||||
[![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)
|
||||
|
||||
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
|
||||
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.
|
||||
## v2.6.0 Now Available
|
||||
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
|
||||
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.
|
|
@ -1,5 +1,107 @@
|
|||
# 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)_
|
||||
|
||||
**[Bug Fixes]**
|
|
@ -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
|
||||
}
|
|
@ -6,11 +6,13 @@ src_dir=.
|
|||
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}
|
|
@ -6,11 +6,13 @@ src_dir=.
|
|||
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}
|
|
@ -6,11 +6,13 @@ src_dir=.
|
|||
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}
|
|
@ -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
|
@ -3,16 +3,19 @@ lib_extra_dirs = ../../
|
|||
src_dir=.
|
||||
|
||||
[common]
|
||||
build_flags = -DMQTT_MAX_PACKET_SIZE=512
|
||||
build_flags = -DMQTT_MAX_PACKET_SIZE=768
|
||||
lib_ldf_mode = chain+
|
||||
lib_deps_builtin =
|
||||
lib_deps_external =
|
||||
PubSubClient
|
||||
WifiManager@0.14
|
||||
ArduinoJson
|
||||
|
||||
[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}
|
||||
|
@ -22,7 +25,18 @@ lib_deps =
|
|||
platform=espressif8266
|
||||
framework=arduino
|
||||
board=d1_mini
|
||||
lib_ldf_mode = ${common.lib_ldf_mode}
|
||||
build_flags = ${common.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_builtin}
|
||||
${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}
|
|
@ -6,11 +6,13 @@ src_dir=.
|
|||
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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -35,9 +35,15 @@
|
|||
#include <ir_Kelvinator.h>
|
||||
#include <ir_Midea.h>
|
||||
#include <ir_Mitsubishi.h>
|
||||
#include <ir_MitsubishiHeavy.h>
|
||||
#include <ir_Panasonic.h>
|
||||
#include <ir_Samsung.h>
|
||||
#include <ir_Tcl.h>
|
||||
#include <ir_Teco.h>
|
||||
#include <ir_Toshiba.h>
|
||||
#include <ir_Vestel.h>
|
||||
#include <ir_Whirlpool.h>
|
||||
|
||||
|
||||
// ==================== start of TUNEABLE PARAMETERS ====================
|
||||
// An IR detector/demodulator is connected to GPIO pin 14
|
||||
|
@ -121,6 +127,20 @@ void dumpACInfo(decode_results *results) {
|
|||
description = ac.toString();
|
||||
}
|
||||
#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 (results->decode_type == FUJITSU_AC) {
|
||||
IRFujitsuAC ac(0);
|
||||
|
@ -142,6 +162,18 @@ void dumpACInfo(decode_results *results) {
|
|||
description = ac.toString();
|
||||
}
|
||||
#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 (results->decode_type == TOSHIBA_AC) {
|
||||
IRToshibaAC ac(0);
|
||||
|
@ -180,7 +212,7 @@ void dumpACInfo(decode_results *results) {
|
|||
#if DECODE_SAMSUNG_AC
|
||||
if (results->decode_type == SAMSUNG_AC) {
|
||||
IRSamsungAc ac(0);
|
||||
ac.setRaw(results->state);
|
||||
ac.setRaw(results->state, results->bits / 8);
|
||||
description = ac.toString();
|
||||
}
|
||||
#endif // DECODE_SAMSUNG_AC
|
||||
|
@ -206,6 +238,34 @@ void dumpACInfo(decode_results *results) {
|
|||
description = ac.toString();
|
||||
}
|
||||
#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 (description != "") Serial.println("Mesg Desc.: " + description);
|
||||
}
|
|
@ -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}
|
|
@ -1,6 +1,6 @@
|
|||
/* 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,
|
||||
* 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, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650,
|
||||
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() {
|
||||
irsend.begin();
|
||||
|
@ -53,19 +57,16 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
#if SEND_NEC
|
||||
Serial.println("NEC");
|
||||
irsend.sendNEC(0x00FFE01FUL, 32);
|
||||
#endif // SEND_NEC
|
||||
irsend.sendNEC(0x00FFE01FUL);
|
||||
delay(2000);
|
||||
#if SEND_SONY
|
||||
Serial.println("Sony");
|
||||
irsend.sendSony(0xa90, 12, 2);
|
||||
#endif // SEND_SONY
|
||||
irsend.sendSony(0xa90, 12, 2); // 12 bits & 2 repeats
|
||||
delay(2000);
|
||||
#if SEND_RAW
|
||||
Serial.println("a rawData capture from IRrecvDumpV2");
|
||||
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);
|
||||
}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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);
|
||||
}
|
|
@ -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}
|
|
@ -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);
|
||||
}
|
|
@ -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}
|
|
@ -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}
|
|
@ -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}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "IRremoteESP8266",
|
||||
"version": "2.5.2",
|
||||
"version": "2.6.0",
|
||||
"keywords": "infrared, ir, remote, esp8266",
|
||||
"description": "Send and receive infrared signals with multiple protocols (ESP8266)",
|
||||
"repository":
|
|
@ -1,5 +1,5 @@
|
|||
name=IRremoteESP8266
|
||||
version=2.5.2
|
||||
version=2.6.0
|
||||
author=Sebastien Warin, Mark Szabo, Ken Shirriff, David Conran
|
||||
maintainer=Mark Szabo, David Conran, Sebastien Warin, Roi Dayan, Massimiliano Pinto
|
||||
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
Loading…
Reference in New Issue