Merge branch 'development' into development

This commit is contained in:
Theo Arends 2020-04-10 15:28:55 +02:00 committed by GitHub
commit 6254c9a35c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
312 changed files with 6728 additions and 2532 deletions

View File

@ -1,43 +0,0 @@
# Device Groups
The device groups module provides a framework to allow multiple devices to be in a group with values such as power, light color/temperature/brightness, PWM values, sensor values, etc. shared with other devices in the group. For example, with multiple light modules in a device group, the light settings can be changed on one module and the settings will automatically be changed on the other light modules. Dimmer switch modules could be in a device group with light modules and the dimmer switch could control the power, brightness and colors of all the lights in the group. Multiple dimmer switches could be in a device group to form a 3-way/4-way dimmer switch.
UDP multicasts, followed by UDP unicasts if necessary, are used to send updates to all devices so updates are fast. There is no need for an MQTT server but all the devices in a group must be on the same IP network.
To include device groups support in the build, define USE_DEVICE_GROUPS in your user_config_override. This adds 3.5K to the code size. All devices in a group must be running firmware with device group support and have device groups enabled.
To enable device groups, execute the command SetOption85 1.
## Device Groups Operation
The device group name is the MQTT group topic set with the GroupTopic command. All devices in the same IP network with the same group topic are in the same group. Some modules may define additional device groups. For example, if Remote Device Mode is enabled, the PWM Dimmer module defines three devices groups.
The items that are sent to the group and the items that are received from the group are selected with the DevGroupShare command. By default all items are sent and received from the group. An example of when the DevGroupShare command would be used is when you have a group of lights that you control with a dimmer switch and home automation software. You want the dimmer switch to be able to control all items. The home automation software controls each light individually. When it controls the whole group, it actually sends command to each light in the group. If you use the home automation software to turn an individual light on or off or change its brightness, color or scheme, you do not want the change to be replicated to the other lights. In this case, you would set the incoming and outgoing item masks to 0xffffffff (all items) on the dimmer switch (DevGroupShare 0xffffffff,0xffffffff) and set the incoming item mask to 0xffffffff and outgoing item mask to 0 on all the lights (DevGroupShare 0xffffffff,0).
### Commands
<table>
<tr>
<td><strong>Command</strong>
</td>
<td><strong>Parameters</strong>
</td>
</tr>
<tr>
<td>DevGroupShare
</td>
<td>&lt;in>,&lt;out> = set incoming and outgoing shared item mask (default = 0xffffffff,0xffffffff)<br>
1 = Power, 2 = Light brightness, 4 = Light fade/speed, 8 = Light scheme, 16 = Light color, 32 = Dimmer settings (presets)
</td>
</tr>
<tr>
<td>GroupTopic&lt;x>
</td>
<td>1 = reset device group &lt;x> MQTT group topic to firmware default (MQTT_GRPTOPIC) and restart<br>
&lt;value> = set device group &lt;x> MQTT group topic (32 chars max) and restart
</td>
</tr>
</table>

View File

@ -67,4 +67,5 @@ Index | Define | Driver | Device | Address(es) | Description
43 | USE_AHT1x | xsns_63 | AHT10/15 | 0x38 | Temperature and humidity sensor
44 | USE_WEMOS_MOTOR_V1 | xdrv_34 | | 0x2D - 0x30 | WEMOS motor shield v1.0.0 (6612FNG)
45 | USE_HDC1080 | xsns_65 | HDC1080 | 0x40 | Temperature and Humidity sensor
46 | USE_DISPLAY_SEVENSEG| xdsp_11 | HT16K33 | 0x70 - 0x77 | Seven segment LED
46 | USE_IAQ | xsns_66 | IAQ | 0x5a | Air quality sensor
47 | USE_DISPLAY_SEVENSEG| xdsp_11 | HT16K33 | 0x70 - 0x77 | Seven segment LED

View File

@ -1,94 +0,0 @@
# PWM Dimmer
The PWM Dimmer module adds support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches. The brightness of the load for these dimmers is controlled by a PWM GPIO pin. They typically have power, up and down buttons, a powered-on LED, five brightness LEDs and another status LED. Examples are:[ https://www.amazon.com/dp/B07FXYSVR1](https://www.amazon.com/dp/B07FXYSVR1),[ https://www.amazon.com/dp/B07V26Q3VD](https://www.amazon.com/dp/B07V26Q3VD),[ https://www.amazon.com/dp/B07K67D43J](https://www.amazon.com/dp/B07K67D43J),[ https://www.amazon.com/dp/B07TTGFWFM](https://www.amazon.com/dp/B07TTGFWFM)
To include PWM dimmer support in the build, define USE_PWM_DIMMER in your user_config_override. This adds 4.5K to the code size. The light module is not required for PWM dimmer operation so you can #undef USE_LIGHT to reduce the firmware bin size.
To enable PWM dimmer operation, select the PWM Dimmer module.
## PWM Dimmer Operation
Pressing and releasing the power button toggles the power on/off. If the toggle turns the power on, the load is returned to the last brightness it was adjusted to. If Fade is enabled, the load is faded on/off at the rate defined by the Speed setting.
When the power is on, holding the down or up button decreases/increases the brightness. The brightness can also be changed using just the power button. When the power is on, holding the power button alternately increases or decreases the brightness. Initially, holding the power button increases the brightness. Releasing and then holding the power button again decreases the brightness.
When the power is off, pressing and releasing the down or up button turns the power on at a temporary brightness of the low/high levels set by the DimmerPreset command. Turning the power on at the low preset can also be accomplished by holding the power button while the power is off. The dimmer presets are intended to enable quickly turning on a light to a dim or bright level without changing the normal desired brightness. Turning the power on to a preset does not change the brightness the load will be set to when the switch is turned on the next time. For example, if the light is on and you adjust the brightness to 80 and then turn the light off, when you turn it back on, the brightness will return to 80. If you turn the power off again and then press the down button, the light will be turned on with a brightness of the low preset. If you then turn the light off and on again, the brightness will return to 80.
When the power is off, holding the down or up button publishes an MQTT EVENT command. The topic follows the format of the Full Topic with a prefix of Event (ex. cmnd/LightSwitch1/EVENT). The MQTT payload is Trigger#, where # is 1 if the down button is held or 2 if the up button is held. These triggers can be used in rules on remote devices (ON Event#Trigger1) or by automation software to trigger automations such as scene changes. For example, the Event topic Trigger1 payload could trigger the automation software to turn on the previous scene in a list and the Trigger2 payload could trigger the automation software to turn on the next scene in a list.
If there are LEDs defined in the template, they are turned on to indicate the current brightness. More LEDs are turned on at higher brightnesses. The LedTimeout command enables/disables an LED timeout. If LED timeout is enabled, the LEDs turn off five seconds after the last change in brightness. Note that the lowest LED and the blue power LED are always on when the power is on. The LED timeout can also be enabled/disabled by holding the power button while tapping (pressing and releasing quickly) the down button.
The LEDLink LED can be used as a nightlight/powered-off indicator. The PoweredOffLed command enables/disables turning the LEDLink LED on when the power is off. The powered-off indicator can also be enabled/disabled by holding the power button and tapping the up button.
Holding the power button, tapping the down button and then tapping or holding the down or up button sends a device group message to set RGB lights in the device group to the previous/next fixed color. The command is sent/value is adjusted once every .5 seconds for as long as the button is held. The color sequence as defined by the Light module is red, green, blue, orange, light green, light blue, amber, cyan, purple, yellow, pink, white using RGB channels, white using CT channels.
Holding the power button, tapping the up button and then tapping or holding the down or up button publishes an MQTT Event command. The command is sent/value is adjusted once every .5 seconds for as long as the button is held. The MQTT topic is as described above. The MQTT payload is Trigger#, where # is 3 if the down button is held or 4 if the up button is held.
Holding the down or up button alone for over 10 seconds executes the WiFiConfig 2 command.
Pressing and releasing any button publishes an MQTT TOGGLE command for the button. Holding a button publishes an MQTT HOLD command followed by an MQTT OFF command when the button is released.
When Device Groups are enabled, the PWM Dimmer brightness presets are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group.
### Commands
<table>
<tr>
<td><strong>Command</strong>
</td>
<td><strong>Parameters</strong>
</td>
</tr>
<tr>
<td>BriPreset
</td>
<td> &lt;low>,&lt;high> = set brightness low and high presets<br>
1..255 = set brightness preset<br>
+ = increase brightness preset<br>
- = decrease brightness preset
</td>
</tr>
<tr>
<td>SetOption86
</td>
<td>Set brightness LED timeout<br>
0 = disable timeout (default)<br>
1 = enable timeout
</td>
</tr>
<tr>
<td>SetOption87
</td>
<td>Set powered-off LED (nightlight)<br>
0 = disable powered-off LED (default)<br>
1 = enable powered-off LED
</td>
</tr>
<tr>
<td>SetOption88
</td>
<td>Set remote device mode<br>
0 = disable remote device mode(default)<br>
1 = enable remote device mode
</td>
</tr>
</table>
### Remote Device Mode
Remote device mode allows PWM Dimmer switches to control remote devices. With remote device mode enabled, each button controls a different device. Note that dimmer switches with toggle-style down/up buttons have limited functionality as remote device mode switches because you can not push the down and up buttons simultaneously.
To include remote device mode support in the build, define USE_PWM_DIMMER_REMOTE in your user_config_override. Remote device mode support requires device group support so USE_DEVICE_GROUPS is automatically defined if USE_PWM_DIMMER_REMOTE is defined. Remote device mode support adds 0.7K to the code size in addition to the code size required for device groups support.
To enable remote device mode, execute the command SetOption88 1 (the device will restart). Each remote device must be running firmware with device group support and have remote device support enabled. The remote devices do not need to be built with PWM dimmer support nor do they need to be switches.
If a remote device is a PWM dimmer, the device acts like a 3-way dimmer switch would and may or may not have a load connected to it. Its also possible to use a PWM dimmer switch without a load to act as a wall switch to control the power, brightness and color of one or more smart lights with Tasmota with device group support loaded on them.
With remote device mode is enabled, button 1 is the power button for the local device while buttons 2 and 3 are the power buttons for remote devices. Group names for buttons 2 and 3 are set by the GroupTopic2 and GroupTopic3 commands respectively. Note that the button numbers are defined by the module template and can be in any physical order on the switch (button 1 can be defined as the top button, the middle button or the bottom button). Button combinations that publish MQTT Event commands use a topic in the format cmnd/%group-topic%/EVENT.
Pressing and releasing a power button toggles the power on all devices in the group assigned to the button. When the power is on, holding the button alternately increases or decreases the brightness. When the power is off, holding the button turns the power on at a temporary brightness of the low level set by the BriPreset command.
While holding a power button, the other two buttons act like the down and up buttons for the remote device. All the functions performed by the down and up buttons in non-remote device mode are available in remote device mode. While holding button 1, button 2 performs the functions of the down button and button 3 performs the functions of the up button. While holding button 2, button 1 performs the functions of the down button and button 3 performs the functions of the up button. While holding button 3, button 1 performs the functions of the down button and button 2 performs the functions of the up button.

View File

@ -58,17 +58,28 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034)
- Change remove floating point libs from IRAM
- Change remove MQTT Info messages on restart for DeepSleep Wake (#8044)
- Change IRremoteESP8266 library updated to v2.7.5
- Fix possible Relay toggle on (OTA) restart
- Fix PWM flickering during wifi connection (#8046)
- Fix Zigbee sending wrong Sat value with Hue emulation
- Fix Zigbee crash with Occupancy sensor (#8089)
- Add Zigbee command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2``
- Add Zigbee command ``ZbUnbind``
- Add Zigbee command ``ZbBindState`` and ``manuf``attribute
- Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021)
- Add commands ``NrfPage``, ``NrfIgnore``, ``NrfScan`` and ``NrfBeacon`` to NRF24 Bluetooth driver (#8075)
- Add command ``SetOption41 <x>`` to force sending gratuitous ARP every <x> seconds
- Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044)
- Add command ``SetOption91 1`` to enable fading at startup / power on
- Add command ``Sensor10 0/1/2`` to control BH1750 resolution - 0 = High (default), 1 = High2, 2 = Low (#8016)
- Add command ``Sensor10 31..254`` to control BH1750 measurement time which defaults to 69 (#8016)
- Add command ``DevGroupName`` to specify up to four Device Group Names (#8087)
- Add command ``DevGroupSend`` to send an update to a Device Group (#8093)
- Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa
- Add support for 64x48 SSD1306 OLED (#6740)
- Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014)
- Add console command history (#7483, #8015)
- Add support for up to four MQTT GroupTopics (#8014)
- Add support for longer template names
- Add support for an iAQ sensor (#8107)
- Add console command history (#7483, #8015)
- Add quick wifi reconnect using saved AP parameters when ``SetOption56 0`` (#3189)
- Add more accuracy to GPS NTP server (#8088)

View File

@ -17,63 +17,81 @@
bool NtpServer::beginListening()
{
if (timeServerPort_.begin(NTP_PORT)){
return true;
}
return false;
if (timeServerPort_.begin(NTP_PORT)){
return true;
}
return false;
}
bool NtpServer::processOneRequest(uint32_t utc, uint32_t millisecs)
{
// We need the time we've received the packet in our response.
uint32_t recvSecs = utc + NTP_TIMESTAMP_DIFF;
double recvFractDouble = (double)millisecs/0.00023283064365386963; // millisec/((10^6)/(2^32))
uint32_t recvFract = (double)recvFractDouble; //TODO: really handle this!!!
bool processed = false;
int packetDataSize = timeServerPort_.parsePacket();
if (packetDataSize && packetDataSize >= NtpPacket::PACKET_SIZE)
{
// Received what is probably an NTP packet. Read it in and verify
// that it's legit.
NtpPacket packet;
timeServerPort_.read((char*)&packet, NtpPacket::PACKET_SIZE);
// TODO: verify packet.
// millisecs is millis() at the time of the last iTOW reception, where iTOW%1000 == 0
uint32_t refMillis = millis()-millisecs;
if (refMillis>999){
utc++;
refMillis = refMillis%1000;
}
// Populate response.
packet.swapEndian();
packet.leapIndicator(0);
packet.versionNumber(4);
packet.mode(4);
packet.stratum = 2; // I guess stratum 1 is too optimistic
packet.poll = 10; // 6-10 per RFC 5905.
packet.precision = -21; // ~0.5 microsecond precision.
packet.rootDelay = 0; //60 * (0xFFFF / 1000); // ~60 milliseconds, TBD
packet.rootDispersion = 0; //10 * (0xFFFF / 1000); // ~10 millisecond dispersion, TBD
packet.referenceId[0] = 'G';
packet.referenceId[1] = 'P';
packet.referenceId[2] = 'S';
packet.referenceId[3] = 0;
packet.referenceTimestampSeconds = utc;
packet.referenceTimestampFraction = recvFract;
packet.originTimestampSeconds = packet.transmitTimestampSeconds;
packet.originTimestampFraction = packet.transmitTimestampFraction;
packet.receiveTimestampSeconds = recvSecs;
packet.receiveTimestampFraction = recvFract;
// ...and the transmit time.
// timeSource_.now(&packet.transmitTimestampSeconds, &packet.transmitTimestampFraction);
// Now transmit the response to the client.
packet.swapEndian();
timeServerPort_.beginPacket(timeServerPort_.remoteIP(), timeServerPort_.remotePort());
for (int count = 0; count < NtpPacket::PACKET_SIZE; count++)
{
timeServerPort_.write(packet.packet()[count]);
}
timeServerPort_.endPacket();
processed = true;
}
return processed;
bool processed = false;
int packetDataSize = timeServerPort_.parsePacket();
if (packetDataSize && packetDataSize >= NtpPacket::PACKET_SIZE)
{
// We need the time we've received the packet in our response.
uint32_t recvSecs = utc + NTP_TIMESTAMP_DIFF;
uint64_t recvFract64 = refMillis;
recvFract64 <<= 32;
recvFract64 /= 1000;
uint32_t recvFract = recvFract64 & 0xffffffff;
// is equal to:
// uint32_t recvFract = (double)(refMillis)/0.00000023283064365386963;
// Received what is probably an NTP packet. Read it in and verify
// that it's legit.
NtpPacket packet;
timeServerPort_.read((char*)&packet, NtpPacket::PACKET_SIZE);
// TODO: verify packet.
// Populate response.
packet.swapEndian();
packet.leapIndicator(0);
packet.versionNumber(4);
packet.mode(4);
packet.stratum = 1; // >1 will lead to misinterpretation of refId
packet.poll = 10; // 6-10 per RFC 5905.
packet.precision = -21; // ~0.5 microsecond precision.
packet.rootDelay = 100 * (0xFFFF / 1000); //~100 milliseconds
packet.rootDispersion = 50 * (0xFFFF / 1000);; //~50 millisecond dispersion
packet.referenceId[0] = 'G';
packet.referenceId[1] = 'P';
packet.referenceId[2] = 'S';
packet.referenceId[3] = 0;
packet.referenceTimestampSeconds = recvSecs;
packet.referenceTimestampFraction = 0; // the "click" of the GPS
packet.originTimestampSeconds = packet.transmitTimestampSeconds;
packet.originTimestampFraction = packet.transmitTimestampFraction;
packet.receiveTimestampSeconds = recvSecs;
packet.receiveTimestampFraction = recvFract;
// ...and the transmit time.
// the latency has been between 135 and 175 microseconds in internal testing, so we harcode 150
uint32_t transFract = recvFract+(150*(10^3)/(2^32)); // microsec/((10^3)/(2^32))
if (recvFract>transFract){
recvSecs++; //overflow
}
packet.transmitTimestampSeconds = recvSecs;
packet.transmitTimestampFraction = transFract;
// Now transmit the response to the client.
packet.swapEndian();
timeServerPort_.beginPacket(timeServerPort_.remoteIP(), timeServerPort_.remotePort());
timeServerPort_.write(packet.packet(), NtpPacket::PACKET_SIZE);
timeServerPort_.endPacket();
processed = true;
}
return processed;
}

View File

@ -1,178 +0,0 @@
// Hitachi A/C
//
// Copyright 2018-2019 David Conran
// Supports:
// Brand: Hitachi, Model: RAS-35THA6 remote
// Brand: Hitachi, Model: LT0541-HTA remote
// Brand: Hitachi, Model: Series VI A/C (Circa 2007)
// Brand: Hitachi, Model: RAR-8P2 remote
// Brand: Hitachi, Model: RAS-AJ25H A/C
#ifndef IR_HITACHI_H_
#define IR_HITACHI_H_
#define __STDC_LIMIT_MACROS
#include <stdint.h>
#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
#ifdef UNIT_TEST
#include "IRsend_test.h"
#endif
// Constants
const uint16_t kHitachiAcFreq = 38000; // Hz.
const uint8_t kHitachiAcAuto = 2;
const uint8_t kHitachiAcHeat = 3;
const uint8_t kHitachiAcCool = 4;
const uint8_t kHitachiAcDry = 5;
const uint8_t kHitachiAcFan = 0xC;
const uint8_t kHitachiAcFanAuto = 1;
const uint8_t kHitachiAcFanLow = 2;
const uint8_t kHitachiAcFanMed = 3;
const uint8_t kHitachiAcFanHigh = 5;
const uint8_t kHitachiAcMinTemp = 16; // 16C
const uint8_t kHitachiAcMaxTemp = 32; // 32C
const uint8_t kHitachiAcAutoTemp = 23; // 23C
const uint8_t kHitachiAcPowerOffset = 0;
const uint8_t kHitachiAcSwingOffset = 7;
// HitachiAc424
// Byte[11]
const uint8_t kHitachiAc424ButtonByte = 11;
const uint8_t kHitachiAc424ButtonPowerMode = 0x13;
const uint8_t kHitachiAc424ButtonFan = 0x42;
const uint8_t kHitachiAc424ButtonTempDown = 0x43;
const uint8_t kHitachiAc424ButtonTempUp = 0x44;
const uint8_t kHitachiAc424ButtonSwingV = 0x81;
// Byte[13]
const uint8_t kHitachiAc424TempByte = 13;
const uint8_t kHitachiAc424TempOffset = 2;
const uint8_t kHitachiAc424TempSize = 6;
const uint8_t kHitachiAc424MinTemp = 16; // 16C
const uint8_t kHitachiAc424MaxTemp = 32; // 32C
const uint8_t kHitachiAc424FanTemp = 27; // 27C
// Byte[25]
const uint8_t kHitachiAc424ModeByte = 25;
const uint8_t kHitachiAc424Fan = 1;
const uint8_t kHitachiAc424Cool = 3;
const uint8_t kHitachiAc424Dry = 5;
const uint8_t kHitachiAc424Heat = 6;
const uint8_t kHitachiAc424FanByte = kHitachiAc424ModeByte;
const uint8_t kHitachiAc424FanMin = 1;
const uint8_t kHitachiAc424FanLow = 2;
const uint8_t kHitachiAc424FanMedium = 3;
const uint8_t kHitachiAc424FanHigh = 4;
const uint8_t kHitachiAc424FanAuto = 5;
const uint8_t kHitachiAc424FanMax = 6;
const uint8_t kHitachiAc424FanMaxDry = 2;
// Byte[27]
const uint8_t kHitachiAc424PowerByte = 27;
const uint8_t kHitachiAc424PowerOn = 0xF1;
const uint8_t kHitachiAc424PowerOff = 0xE1;
// Classes
class IRHitachiAc {
public:
explicit IRHitachiAc(const uint16_t pin, const bool inverted = false,
const bool use_modulation = true);
void stateReset(void);
#if SEND_HITACHI_AC
void send(const uint16_t repeat = kHitachiAcDefaultRepeat);
uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_HITACHI_AC
void begin(void);
void on(void);
void off(void);
void setPower(const bool on);
bool getPower(void);
void setTemp(const uint8_t temp);
uint8_t getTemp(void);
void setFan(const uint8_t speed);
uint8_t getFan(void);
void setMode(const uint8_t mode);
uint8_t getMode(void);
void setSwingVertical(const bool on);
bool getSwingVertical(void);
void setSwingHorizontal(const bool on);
bool getSwingHorizontal(void);
uint8_t* getRaw(void);
void setRaw(const uint8_t new_code[],
const uint16_t length = kHitachiAcStateLength);
static bool validChecksum(const uint8_t state[],
const uint16_t length = kHitachiAcStateLength);
static uint8_t calcChecksum(const uint8_t state[],
const uint16_t length = kHitachiAcStateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
static stdAc::opmode_t toCommonMode(const uint8_t mode);
static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
stdAc::state_t toCommon(void);
String toString(void);
#ifndef UNIT_TEST
private:
IRsend _irsend;
#else
IRsendTest _irsend;
#endif
// The state of the IR remote in IR code form.
uint8_t remote_state[kHitachiAcStateLength];
void checksum(const uint16_t length = kHitachiAcStateLength);
uint8_t _previoustemp;
};
class IRHitachiAc424 {
public:
explicit IRHitachiAc424(const uint16_t pin, const bool inverted = false,
const bool use_modulation = true);
void stateReset(void);
#if SEND_HITACHI_AC424
void send(const uint16_t repeat = kHitachiAcDefaultRepeat);
uint8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_HITACHI_AC424
void begin(void);
void on(void);
void off(void);
void setPower(const bool on);
bool getPower(void);
void setTemp(const uint8_t temp, bool setPrevious = true);
uint8_t getTemp(void);
void setFan(const uint8_t speed);
uint8_t getFan(void);
uint8_t getButton(void);
void setButton(const uint8_t button);
void setSwingVToggle(const bool on);
bool getSwingVToggle(void);
void setMode(const uint8_t mode);
uint8_t getMode(void);
uint8_t* getRaw(void);
void setRaw(const uint8_t new_code[],
const uint16_t length = kHitachiAc424StateLength);
uint8_t convertMode(const stdAc::opmode_t mode);
uint8_t convertFan(const stdAc::fanspeed_t speed);
static stdAc::opmode_t toCommonMode(const uint8_t mode);
static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
stdAc::state_t toCommon(void);
String toString(void);
#ifndef UNIT_TEST
private:
IRsend _irsend;
#else
IRsendTest _irsend;
#endif
// The state of the IR remote in IR code form.
uint8_t remote_state[kHitachiAc424StateLength];
void setInvertedStates(void);
uint8_t _previoustemp;
};
#endif // IR_HITACHI_H_

View File

@ -9,8 +9,8 @@
This library enables you to **send _and_ receive** infra-red signals on an [ESP8266](https://github.com/esp8266/Arduino) or an
[ESP32](https://github.com/espressif/arduino-esp32) using the [Arduino framework](https://www.arduino.cc/) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* demodulators etc.
## v2.7.4 Now Available
Version 2.7.4 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
## v2.7.5 Now Available
Version 2.7.5 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
#### Upgrading from pre-v2.0
Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page.

View File

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

View File

@ -1,5 +1,23 @@
# Release Notes
## _v2.7.5 (20200409)_
**[Features]**
- Detailed support for `HITACHI_AC1` protocol. (#1056, #1061, #1072)
- update sharp to match Sharp AH-A5SAY (#1074)
- Experimental support for AIRWELL protocol. (#1069, #1070)
- SamsungAC: Add Breeze (Aka WindFree) control (#1062, #1071)
- Support for Daikin FFN-C A/C (#1064, #1065)
- Add basic support for HITACHI_AC3 protocol. (#1060, #1063)
- Add support for `SYMPHONY` 11 bit protocol. (#1057, #1058)
- IRMQTTServer: Improve Home-Assistant discovery by sending a 'device' with the discovery packet (#1055)
**[Misc]**
- Clean up support status of various protocols.
- Add `decodeToState()` unit tests to all supported protocols (#1067, #1068)
- Add Gree AC example code. (#1066)
## _v2.7.4 (20200226)_
**[Bug Fixes]**

View File

@ -1,18 +1,20 @@
<!--- WARNING: Do NOT edit this file directly.
It is generated by './tools/scrape_supported_devices.py'.
Last generated: Wed Feb 26 16:31:08 2020 --->
Last generated: Thu Apr 9 15:49:53 2020 --->
# IR Protocols supported by this library
| Protocol | Brand | Model | A/C Model | Detailed A/C Support |
| --- | --- | --- | --- | --- |
| [Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airwell.cpp) | **Airwell** | RC08W remote | | - |
| [Aiwa](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Aiwa.cpp) | **Aiwa** | RC-T501 RCU | | - |
| [Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.cpp) | **[Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.h)** | ADR-853H A/C<BR>ADR-853H A/C<BR>TAC-444 remote<BR>TAC-444 remote<BR>TAC-495 remote<BR>TAC-495 remote | | Yes |
| [Argo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Argo.cpp) | **[Argo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Argo.h)** | Ulisse 13 DCI Mobile Split A/C | | Yes |
| [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **Carrier/Surrey** | 42QG5A55970 remote<BR>53NGK009/012 Inverter<BR>619EGX0090E0 A/C<BR>619EGX0120E0 A/C<BR>619EGX0180E0 A/C<BR>619EGX0220E0 A/C | | - |
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | RC08B remote | | Yes |
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Beko](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | BINR 070/071 split-type A/C<BR>BINR 070/071 split-type A/C<BR>RG57K7(B)/BGEF Remote<BR>RG57K7(B)/BGEF Remote | | Yes |
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | MS12FU-10HRDN1-QRD0GW(B) A/C<BR>MS12FU-10HRDN1-QRD0GW(B) A/C<BR>MSABAU-07HRFN1-QRD0GW A/C (circa 2016)<BR>MSABAU-07HRFN1-QRD0GW A/C (circa 2016)<BR>RG52D/BGE Remote<BR>RG52D/BGE Remote | | Yes |
| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Tokio](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | AATOEMF17-12CHR1SW split-type RG51\|50/BGE Remote<BR>AATOEMF17-12CHR1SW split-type RG51\|50/BGE Remote | | Yes |
| [Daikin](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Daikin.cpp) | **[Daikin](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Daikin.h)** | 17 Series A/C (DAIKIN128)<BR>ARC423A5 remote<BR>ARC433** remote<BR>ARC433B69 remote<BR>ARC477A1 remote<BR>ARC480A5 remote (DAIKIN152)<BR>BRC4C153 remote<BR>BRC52B63 remote (DAIKIN128)<BR>FTE12HV2S A/C<BR>FTXB09AXVJU A/C (DAIKIN128)<BR>FTXB12AXVJU A/C (DAIKIN128)<BR>FTXZ25NV1B A/C<BR>FTXZ35NV1B A/C<BR>FTXZ50NV1B A/C | | Yes |
| [Daikin](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Daikin.cpp) | **[Daikin](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Daikin.h)** | 17 Series A/C (DAIKIN128)<BR>ARC423A5 remote<BR>ARC433** remote<BR>ARC433B69 remote<BR>ARC477A1 remote<BR>ARC480A5 remote (DAIKIN152)<BR>BRC4C153 remote<BR>BRC52B63 remote (DAIKIN128)<BR>DGS01 remote (DAIKIN64)<BR>FFN-C/FCN-F Series A/C (DAIKIN64)<BR>FTE12HV2S A/C<BR>FTXB09AXVJU A/C (DAIKIN128)<BR>FTXB12AXVJU A/C (DAIKIN128)<BR>FTXZ25NV1B A/C<BR>FTXZ35NV1B A/C<BR>FTXZ50NV1B A/C | | Yes |
| [Denon](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Denon.cpp) | **Unknown** | | | - |
| [Dish](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Dish.cpp) | **DISH NETWORK** | echostar 301 | | - |
| [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[AUX](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | KFR-35GW/BpNFW=3 A/C<BR>YKR-T/011 remote | | Yes |
@ -28,7 +30,7 @@
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[RusClimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | EACS/I-09HAR_X/N3 A/C<BR>YAW1F remote | YAW1F<BR>YBOFB | Yes |
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Ultimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | Heat Pump | YAW1F<BR>YBOFB | Yes |
| [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | HSU-09HMC203 A/C<BR>HSU07-HEA03 remote<BR>YR-W02 remote | | Yes |
| [Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.cpp) | **[Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.h)** | LT0541-HTA remote<BR>RAR-8P2 remote<BR>RAS-35THA6 remote<BR>RAS-AJ25H A/C<BR>Series VI A/C (Circa 2007) | | Yes |
| [Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.cpp) | **[Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.h)** | KAZE-312KSDP A/C (HITACHI_AC1)<BR>LT0541-HTA remote<BR>PC-LH3B (HITACHI_AC3)<BR>R-LT0541-HTA/Y.K.1.1-1 V2.3 remote (HITACHI_AC1)<BR>RAR-8P2 remote<BR>RAS-35THA6 remote<BR>RAS-AJ25H A/C<BR>Series VI A/C (Circa 2007) | | Yes |
| [Inax](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Inax.cpp) | **Lixil** | Inax DT-BA283 Toilet | | - |
| [JVC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_JVC.cpp) | **Unknown** | | | - |
| [Kelvinator](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.cpp) | **[Green](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.h)** | YAPOF3 remote | | Yes |
@ -56,11 +58,12 @@
| [Pronto](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Pronto.cpp) | **Unknown** | | | - |
| [RC5_RC6](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp) | **Unknown** | | | - |
| [RCMM](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RCMM.cpp) | **Microsoft** | XBOX 360 | | - |
| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AR09FSSDAWKNFA A/C<BR>AR12HSSDBWKNEU A/C<BR>AR12KSFPEWQNET A/C<BR>DB63-03556X003 remote<BR>IEC-R03 remote<BR>UA55H6300 TV | | Yes |
| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AR09FSSDAWKNFA A/C<BR>AR12HSSDBWKNEU A/C<BR>AR12KSFPEWQNET A/C<BR>AR12NXCXAWKXEU A/C<BR>DB63-03556X003 remote<BR>DB93-16761C remote<BR>IEC-R03 remote<BR>UA55H6300 TV | | Yes |
| [Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.cpp) | **Unknown** | | | - |
| [Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.cpp) | **[Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.h)** | AY-ZP40KR A/C<BR>LC-52D62U TV | | Yes |
| [Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.cpp) | **[Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.h)** | AH-AxSAY A/C<BR>AY-ZP40KR A/C<BR>LC-52D62U TV | | Yes |
| [Sherwood](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sherwood.cpp) | **Sherwood** | RC-138 remote<BR>RD6505(B) Receiver | | - |
| [Sony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sony.cpp) | **Sony** | HT-CT380 Soundbar (Uses 38kHz & 3 repeats) | | - |
| [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Symphony** | Air Cooler 3Di | | - |
| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Leberg](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | LBS-TOR07 A/C | | Yes |
| [Teco](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.cpp) | **[Alaska](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.h)** | SAC9010QC A/C<BR>SAC9010QC remote | | Yes |
| [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | Akita EVO II<BR>RAS 18SKP-ES<BR>RAS-B13N3KV2<BR>RAS-B13N3KVP-E<BR>WC-L03SE<BR>WH-TA04NE | | Yes |
@ -81,6 +84,7 @@
## Send & decodable protocols:
- AIRWELL
- AIWA_RC_T501
- AMCOR
- ARGO
@ -93,6 +97,7 @@
- DAIKIN176
- DAIKIN2
- DAIKIN216
- DAIKIN64
- DENON
- DISH
- ELECTRA_AC
@ -106,6 +111,7 @@
- HITACHI_AC
- HITACHI_AC1
- HITACHI_AC2
- HITACHI_AC3
- HITACHI_AC424
- INAX
- JVC
@ -144,6 +150,7 @@
- SHARP
- SHARP_AC
- SONY
- SYMPHONY
- TCL112AC
- TECO
- TOSHIBA_AC

View File

@ -239,7 +239,7 @@ const uint16_t kJsonAcStateMaxSize = 1024; // Bytes
// ----------------- End of User Configuration Section -------------------------
// Constants
#define _MY_VERSION_ "v1.4.6"
#define _MY_VERSION_ "v1.4.7"
const uint8_t kRebootTime = 15; // Seconds
const uint8_t kQuickDisplayTime = 2; // Seconds

View File

@ -449,6 +449,7 @@ String MqttClimate; // Sub-topic for the climate topics.
String MqttClimateCmnd; // Sub-topic for the climate command topics.
#if MQTT_DISCOVERY_ENABLE
String MqttDiscovery;
String MqttUniqueId;
#endif // MQTT_DISCOVERY_ENABLE
String MqttHAName;
String MqttClientId;
@ -1228,6 +1229,7 @@ void handleInfo(void) {
"<h3>General</h3>"
"<p>Hostname: " + String(Hostname) + "<br>"
"IP address: " + WiFi.localIP().toString() + "<br>"
"MAC address: " + WiFi.macAddress() + "<br>"
"Booted: " + timeSince(1) + "<br>" +
"Version: " _MY_VERSION_ "<br>"
"Built: " __DATE__
@ -1516,6 +1518,23 @@ bool parseStringAndSendAirCon(IRsend *irsend, const decode_type_t irType,
// Lastly, it should never exceed the maximum "normal" size.
stateSize = std::min(stateSize, kFujitsuAcStateLength);
break;
case HITACHI_AC3:
// HitachiAc3 has two distinct & different size states, so make a best
// guess which one we are being presented with based on the number of
// hexadecimal digits provided. i.e. Zero-pad if you need to to get
// the correct length/byte size.
stateSize = inputLength / 2; // Every two hex chars is a byte.
// Use at least the minimum size.
stateSize = std::max(stateSize,
(uint16_t) (kHitachiAc3MinStateLength));
// If we think it isn't a "short" message.
if (stateSize > kHitachiAc3MinStateLength)
// Then it probably the "normal" size.
stateSize = std::max(stateSize,
(uint16_t) (kHitachiAc3StateLength));
// Lastly, it should never exceed the maximum "normal" size.
stateSize = std::min(stateSize, kHitachiAc3StateLength);
break;
case MWM:
// MWM has variable size states, so make a best guess
// which one we are being presented with based on the number of
@ -2033,6 +2052,8 @@ void init_vars(void) {
// Sub-topic for the climate stat topics.
#if MQTT_DISCOVERY_ENABLE
MqttDiscovery = "homeassistant/climate/" + String(Hostname) + "/config";
MqttUniqueId = WiFi.macAddress();
MqttUniqueId.replace(":", "");
#endif // MQTT_DISCOVERY_ENABLE
MqttHAName = String(Hostname) + "_aircon";
// Create a unique MQTT client id.
@ -2531,7 +2552,16 @@ void sendMQTTDiscovery(const char *topic) {
"\"swing_mode_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_SWINGV "\","
"\"swing_modes\":[\"" D_STR_OFF "\",\"" D_STR_AUTO "\",\"" D_STR_HIGHEST
"\",\"" D_STR_HIGH "\",\"" D_STR_MIDDLE "\",\""
D_STR_LOW "\",\"" D_STR_LOWEST "\"]"
D_STR_LOW "\",\"" D_STR_LOWEST "\"],"
"\"uniq_id\":\"" + MqttUniqueId + "\","
"\"device\":{"
"\"identifiers\":[\"" + MqttUniqueId + "\"],"
"\"connections\":[[\"mac\",\"" + WiFi.macAddress() + "\"]],"
"\"manufacturer\":\"IRremoteESP8266\","
"\"model\":\"IRMQTTServer\","
"\"name\":\"" + Hostname + "\","
"\"sw_version\":\"" _MY_VERSION_ "\""
"}"
"}").c_str(), true)) {
mqttLog("MQTT climate discovery successful sent.");
hasDiscoveryBeenSent = true;

View File

@ -0,0 +1,77 @@
/* Copyright 2016, 2018 David Conran
* Copyright 2020 Sadid Rafsun Tulon
*
* 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/crankyoldgit/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.
*/
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ir_Gree.h>
const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2).
IRGreeAC ac(kIrLed); // Set the GPIO to be used for sending messages.
void printState() {
// Display the settings.
Serial.println("GREE 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 < kGreeStateLength; 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_Gree.cpp for all the options.
// Most things default to off.
Serial.println("Default state of the remote.");
printState();
Serial.println("Setting desired state for A/C.");
ac.on();
ac.setFan(1);
// kGreeAuto, kGreeDry, kGreeCool, kGreeFan, kGreeHeat
ac.setMode(kGreeCool);
ac.setTemp(20); // 16-30C
ac.setSwingVertical(true, kGreeSwingAuto);
ac.setXFan(false);
ac.setLight(false);
ac.setSleep(false);
ac.setTurbo(false);
}
void loop() {
// Now send the IR signal.
#if SEND_GREE
Serial.println("Sending IR command to A/C ...");
ac.send();
#endif // SEND_GREE
printState();
delay(5000);
}

View File

@ -0,0 +1,17 @@
[platformio]
src_dir = .
[env]
lib_extra_dirs = ../../
lib_ldf_mode = deep+
lib_ignore = examples
framework = arduino
build_flags = ; -D_IR_LOCALE_=en-AU
[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
[env:esp32dev]
platform = espressif32
board = esp32dev

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -29,6 +29,7 @@ IRDaikin160 KEYWORD1
IRDaikin176 KEYWORD1
IRDaikin2 KEYWORD1
IRDaikin216 KEYWORD1
IRDaikin64 KEYWORD1
IRDaikinESP KEYWORD1
IRElectraAc KEYWORD1
IRFujitsuAC KEYWORD1
@ -37,6 +38,8 @@ IRGreeAC KEYWORD1
IRHaierAC KEYWORD1
IRHaierACYRW02 KEYWORD1
IRHitachiAc KEYWORD1
IRHitachiAc1 KEYWORD1
IRHitachiAc3 KEYWORD1
IRHitachiAc424 KEYWORD1
IRKelvinatorAC KEYWORD1
IRLgAc KEYWORD1
@ -66,6 +69,7 @@ decode_type_t KEYWORD1
fanspeed_t KEYWORD1
fujitsu_ac_remote_model_t KEYWORD1
gree_ac_remote_model_t KEYWORD1
hitachi_ac1_remote_model_t KEYWORD1
irparams_t KEYWORD1
lg_ac_remote_model_t KEYWORD1
match_result_t KEYWORD1
@ -141,7 +145,9 @@ daikin160 KEYWORD2
daikin176 KEYWORD2
daikin2 KEYWORD2
daikin216 KEYWORD2
daikin64 KEYWORD2
decode KEYWORD2
decodeAirwell KEYWORD2
decodeAiwaRCT501 KEYWORD2
decodeAmcor KEYWORD2
decodeArgo KEYWORD2
@ -155,6 +161,7 @@ decodeDaikin160 KEYWORD2
decodeDaikin176 KEYWORD2
decodeDaikin2 KEYWORD2
decodeDaikin216 KEYWORD2
decodeDaikin64 KEYWORD2
decodeDenon KEYWORD2
decodeElectraAC KEYWORD2
decodeEpson KEYWORD2
@ -166,6 +173,7 @@ decodeHaierAC KEYWORD2
decodeHaierACYRW02 KEYWORD2
decodeHash KEYWORD2
decodeHitachiAC KEYWORD2
decodeHitachiAc3 KEYWORD2
decodeHitachiAc424 KEYWORD2
decodeInax KEYWORD2
decodeJVC KEYWORD2
@ -200,6 +208,7 @@ decodeSanyoLC7461 KEYWORD2
decodeSharp KEYWORD2
decodeSharpAc KEYWORD2
decodeSony KEYWORD2
decodeSymphony KEYWORD2
decodeTeco KEYWORD2
decodeToState KEYWORD2
decodeToshibaAC KEYWORD2
@ -243,6 +252,7 @@ get3D KEYWORD2
get8CHeat KEYWORD2
getBeep KEYWORD2
getBit KEYWORD2
getBreeze KEYWORD2
getBufSize KEYWORD2
getButton KEYWORD2
getClean KEYWORD2
@ -280,15 +290,18 @@ getMode KEYWORD2
getMold KEYWORD2
getNight KEYWORD2
getOffTime KEYWORD2
getOffTimeEnabled KEYWORD2
getOffTimer KEYWORD2
getOffTimerEnabled KEYWORD2
getOnTime KEYWORD2
getOnTimeEnabled KEYWORD2
getOnTimer KEYWORD2
getOnTimerEnabled KEYWORD2
getOutsideQuiet KEYWORD2
getPower KEYWORD2
getPowerToggle KEYWORD2
getPowerful KEYWORD2
getPreviousPower KEYWORD2
getPurify KEYWORD2
getQuiet KEYWORD2
getRClevel KEYWORD2
@ -309,6 +322,7 @@ getSuper KEYWORD2
getSwing KEYWORD2
getSwingH KEYWORD2
getSwingHorizontal KEYWORD2
getSwingToggle KEYWORD2
getSwingV KEYWORD2
getSwingVToggle KEYWORD2
getSwingVertical KEYWORD2
@ -336,8 +350,10 @@ haier KEYWORD2
haierYrwo2 KEYWORD2
handleSpecialState KEYWORD2
hasACState KEYWORD2
hasInvertedStates KEYWORD2
hasStateChanged KEYWORD2
hitachi KEYWORD2
hitachi1 KEYWORD2
hitachi424 KEYWORD2
htmlEscape KEYWORD2
initState KEYWORD2
@ -364,6 +380,7 @@ matchAtLeast KEYWORD2
matchBytes KEYWORD2
matchData KEYWORD2
matchGeneric KEYWORD2
matchManchester KEYWORD2
matchMark KEYWORD2
matchSpace KEYWORD2
midea KEYWORD2
@ -394,6 +411,7 @@ reverseBits KEYWORD2
samsung KEYWORD2
send KEYWORD2
sendAc KEYWORD2
sendAirwell KEYWORD2
sendAiwaRCT501 KEYWORD2
sendAmcor KEYWORD2
sendArgo KEYWORD2
@ -407,6 +425,7 @@ sendDaikin160 KEYWORD2
sendDaikin176 KEYWORD2
sendDaikin2 KEYWORD2
sendDaikin216 KEYWORD2
sendDaikin64 KEYWORD2
sendData KEYWORD2
sendDenon KEYWORD2
sendElectraAC KEYWORD2
@ -423,6 +442,7 @@ sendHaierACYRW02 KEYWORD2
sendHitachiAC KEYWORD2
sendHitachiAC1 KEYWORD2
sendHitachiAC2 KEYWORD2
sendHitachiAc3 KEYWORD2
sendHitachiAc424 KEYWORD2
sendInax KEYWORD2
sendJVC KEYWORD2
@ -434,6 +454,8 @@ sendLegoPf KEYWORD2
sendLutron KEYWORD2
sendMWM KEYWORD2
sendMagiQuest KEYWORD2
sendManchester KEYWORD2
sendManchesterData KEYWORD2
sendMidea KEYWORD2
sendMitsubishi KEYWORD2
sendMitsubishi112 KEYWORD2
@ -466,6 +488,7 @@ sendSharpRaw KEYWORD2
sendSherwood KEYWORD2
sendSony KEYWORD2
sendSony38 KEYWORD2
sendSymphony KEYWORD2
sendTcl112Ac KEYWORD2
sendTeco KEYWORD2
sendToshibaAC KEYWORD2
@ -480,6 +503,7 @@ setAuto KEYWORD2
setBeep KEYWORD2
setBit KEYWORD2
setBits KEYWORD2
setBreeze KEYWORD2
setButton KEYWORD2
setClean KEYWORD2
setClock KEYWORD2
@ -516,9 +540,13 @@ setMode KEYWORD2
setModel KEYWORD2
setMold KEYWORD2
setNight KEYWORD2
setOffTime KEYWORD2
setOffTimeEnabled KEYWORD2
setOffTimer KEYWORD2
setOffTimerActive KEYWORD2
setOffTimerEnabled KEYWORD2
setOnTime KEYWORD2
setOnTimeEnabled KEYWORD2
setOnTimer KEYWORD2
setOnTimerActive KEYWORD2
setOnTimerEnabled KEYWORD2
@ -526,6 +554,7 @@ setOutsideQuiet KEYWORD2
setPower KEYWORD2
setPowerToggle KEYWORD2
setPowerful KEYWORD2
setPreviousPower KEYWORD2
setPurify KEYWORD2
setQuiet KEYWORD2
setRaw KEYWORD2
@ -543,6 +572,7 @@ setSuper KEYWORD2
setSwing KEYWORD2
setSwingH KEYWORD2
setSwingHorizontal KEYWORD2
setSwingToggle KEYWORD2
setSwingV KEYWORD2
setSwingVToggle KEYWORD2
setSwingVertical KEYWORD2
@ -600,6 +630,7 @@ xorBytes KEYWORD2
#######################################
// LITERAL1
AIRWELL LITERAL1
AIWA_RC_T501 LITERAL1
AIWA_RC_T501_BITS LITERAL1
AKB75215403 LITERAL1
@ -644,6 +675,7 @@ DAIKIN160 LITERAL1
DAIKIN176 LITERAL1
DAIKIN2 LITERAL1
DAIKIN216 LITERAL1
DAIKIN64 LITERAL1
DAIKIN_AUTO LITERAL1
DAIKIN_COMMAND_LENGTH LITERAL1
DAIKIN_COOL LITERAL1
@ -657,6 +689,7 @@ DAIKIN_HEAT LITERAL1
DAIKIN_MAX_TEMP LITERAL1
DAIKIN_MIN_TEMP LITERAL1
DECODE_AC LITERAL1
DECODE_AIRWELL LITERAL1
DECODE_AIWA_RC_T501 LITERAL1
DECODE_AMCOR LITERAL1
DECODE_ARGO LITERAL1
@ -669,6 +702,7 @@ DECODE_DAIKIN160 LITERAL1
DECODE_DAIKIN176 LITERAL1
DECODE_DAIKIN2 LITERAL1
DECODE_DAIKIN216 LITERAL1
DECODE_DAIKIN64 LITERAL1
DECODE_DENON LITERAL1
DECODE_DISH LITERAL1
DECODE_ELECTRA_AC LITERAL1
@ -684,6 +718,7 @@ DECODE_HASH LITERAL1
DECODE_HITACHI_AC LITERAL1
DECODE_HITACHI_AC1 LITERAL1
DECODE_HITACHI_AC2 LITERAL1
DECODE_HITACHI_AC3 LITERAL1
DECODE_HITACHI_AC424 LITERAL1
DECODE_INAX LITERAL1
DECODE_JVC LITERAL1
@ -719,6 +754,7 @@ DECODE_SHARP LITERAL1
DECODE_SHARP_AC LITERAL1
DECODE_SHERWOOD LITERAL1
DECODE_SONY LITERAL1
DECODE_SYMPHONY LITERAL1
DECODE_TCL112AC LITERAL1
DECODE_TECO LITERAL1
DECODE_TOSHIBA_AC LITERAL1
@ -855,6 +891,7 @@ HITACHI_AC1_STATE_LENGTH LITERAL1
HITACHI_AC2 LITERAL1
HITACHI_AC2_BITS LITERAL1
HITACHI_AC2_STATE_LENGTH LITERAL1
HITACHI_AC3 LITERAL1
HITACHI_AC424 LITERAL1
HITACHI_AC_BITS LITERAL1
HITACHI_AC_STATE_LENGTH LITERAL1
@ -950,6 +987,8 @@ RC6_36_BITS LITERAL1
RC6_MODE0_BITS LITERAL1
RCMM LITERAL1
RCMM_BITS LITERAL1
R_LT0541_HTA_A LITERAL1
R_LT0541_HTA_B LITERAL1
SAMSUNG LITERAL1
SAMSUNG36 LITERAL1
SAMSUNG_AC LITERAL1
@ -958,6 +997,7 @@ SANYO LITERAL1
SANYO_LC7461 LITERAL1
SANYO_LC7461_BITS LITERAL1
SANYO_SA8650B_BITS LITERAL1
SEND_AIRWELL LITERAL1
SEND_AIWA_RC_T501 LITERAL1
SEND_AMCOR LITERAL1
SEND_ARGO LITERAL1
@ -970,6 +1010,7 @@ SEND_DAIKIN160 LITERAL1
SEND_DAIKIN176 LITERAL1
SEND_DAIKIN2 LITERAL1
SEND_DAIKIN216 LITERAL1
SEND_DAIKIN64 LITERAL1
SEND_DENON LITERAL1
SEND_DISH LITERAL1
SEND_ELECTRA_AC LITERAL1
@ -984,6 +1025,7 @@ SEND_HAIER_AC_YRW02 LITERAL1
SEND_HITACHI_AC LITERAL1
SEND_HITACHI_AC1 LITERAL1
SEND_HITACHI_AC2 LITERAL1
SEND_HITACHI_AC3 LITERAL1
SEND_HITACHI_AC424 LITERAL1
SEND_INAX LITERAL1
SEND_JVC LITERAL1
@ -1020,6 +1062,7 @@ SEND_SHARP LITERAL1
SEND_SHARP_AC LITERAL1
SEND_SHERWOOD LITERAL1
SEND_SONY LITERAL1
SEND_SYMPHONY LITERAL1
SEND_TCL112AC LITERAL1
SEND_TECO LITERAL1
SEND_TOSHIBA_AC LITERAL1
@ -1037,6 +1080,7 @@ SONY_12_BITS LITERAL1
SONY_15_BITS LITERAL1
SONY_20_BITS LITERAL1
SONY_38K LITERAL1
SYMPHONY LITERAL1
TCL112AC LITERAL1
TECO LITERAL1
TIMEOUT_MS LITERAL1
@ -1076,6 +1120,13 @@ k3DStr LITERAL1
k6thSenseStr LITERAL1
k8CHeatStr LITERAL1
kAirFlowStr LITERAL1
kAirwellBits LITERAL1
kAirwellFooterMark LITERAL1
kAirwellHalfClockPeriod LITERAL1
kAirwellHdrMark LITERAL1
kAirwellHdrSpace LITERAL1
kAirwellMinRepeats LITERAL1
kAirwellOverhead LITERAL1
kAiwaRcT501Bits LITERAL1
kAiwaRcT501MinRepeats LITERAL1
kAiwaRcT501PostBits LITERAL1
@ -1498,6 +1549,53 @@ kDaikin2SwingVLow LITERAL1
kDaikin2SwingVSwing LITERAL1
kDaikin2Tolerance LITERAL1
kDaikin2ZeroSpace LITERAL1
kDaikin64BitMark LITERAL1
kDaikin64Bits LITERAL1
kDaikin64ChecksumOffset LITERAL1
kDaikin64ChecksumSize LITERAL1
kDaikin64ClockHoursSize LITERAL1
kDaikin64ClockMinsSize LITERAL1
kDaikin64ClockOffset LITERAL1
kDaikin64ClockSize LITERAL1
kDaikin64Cool LITERAL1
kDaikin64DefaultRepeat LITERAL1
kDaikin64Dry LITERAL1
kDaikin64Fan LITERAL1
kDaikin64FanAuto LITERAL1
kDaikin64FanHigh LITERAL1
kDaikin64FanLow LITERAL1
kDaikin64FanMed LITERAL1
kDaikin64FanOffset LITERAL1
kDaikin64FanQuiet LITERAL1
kDaikin64FanSize LITERAL1
kDaikin64FanTurbo LITERAL1
kDaikin64Freq LITERAL1
kDaikin64Gap LITERAL1
kDaikin64HdrMark LITERAL1
kDaikin64HdrSpace LITERAL1
kDaikin64KnownGoodState LITERAL1
kDaikin64LdrMark LITERAL1
kDaikin64LdrSpace LITERAL1
kDaikin64MaxTemp LITERAL1
kDaikin64MinTemp LITERAL1
kDaikin64ModeOffset LITERAL1
kDaikin64ModeSize LITERAL1
kDaikin64OffTimeEnableBit LITERAL1
kDaikin64OffTimeHalfHourBit LITERAL1
kDaikin64OffTimeOffset LITERAL1
kDaikin64OffTimeSize LITERAL1
kDaikin64OnTimeEnableBit LITERAL1
kDaikin64OnTimeHalfHourBit LITERAL1
kDaikin64OnTimeOffset LITERAL1
kDaikin64OnTimeSize LITERAL1
kDaikin64OneSpace LITERAL1
kDaikin64Overhead LITERAL1
kDaikin64PowerToggleBit LITERAL1
kDaikin64SleepBit LITERAL1
kDaikin64SwingVBit LITERAL1
kDaikin64TempOffset LITERAL1
kDaikin64TempSize LITERAL1
kDaikin64ZeroSpace LITERAL1
kDaikinAuto LITERAL1
kDaikinBeepLoud LITERAL1
kDaikinBeepOff LITERAL1
@ -1955,12 +2053,67 @@ kHighNibble LITERAL1
kHighStr LITERAL1
kHighest LITERAL1
kHighestStr LITERAL1
kHitachiAc1Auto LITERAL1
kHitachiAc1Bits LITERAL1
kHitachiAc1ChecksumStartByte LITERAL1
kHitachiAc1Cool LITERAL1
kHitachiAc1Dry LITERAL1
kHitachiAc1Fan LITERAL1
kHitachiAc1FanAuto LITERAL1
kHitachiAc1FanByte LITERAL1
kHitachiAc1FanHigh LITERAL1
kHitachiAc1FanLow LITERAL1
kHitachiAc1FanMed LITERAL1
kHitachiAc1FanOffset LITERAL1
kHitachiAc1FanSize LITERAL1
kHitachiAc1HdrMark LITERAL1
kHitachiAc1HdrSpace LITERAL1
kHitachiAc1Heat LITERAL1
kHitachiAc1ModeByte LITERAL1
kHitachiAc1ModeOffset LITERAL1
kHitachiAc1ModeSize LITERAL1
kHitachiAc1ModelByte LITERAL1
kHitachiAc1ModelOffset LITERAL1
kHitachiAc1ModelSize LITERAL1
kHitachiAc1Model_A LITERAL1
kHitachiAc1Model_B LITERAL1
kHitachiAc1OffTimerHighByte LITERAL1
kHitachiAc1OffTimerLowByte LITERAL1
kHitachiAc1OnTimerHighByte LITERAL1
kHitachiAc1OnTimerLowByte LITERAL1
kHitachiAc1PowerByte LITERAL1
kHitachiAc1PowerOffset LITERAL1
kHitachiAc1PowerToggleOffset LITERAL1
kHitachiAc1Sleep1 LITERAL1
kHitachiAc1Sleep2 LITERAL1
kHitachiAc1Sleep3 LITERAL1
kHitachiAc1Sleep4 LITERAL1
kHitachiAc1SleepByte LITERAL1
kHitachiAc1SleepOff LITERAL1
kHitachiAc1SleepOffset LITERAL1
kHitachiAc1SleepSize LITERAL1
kHitachiAc1StateLength LITERAL1
kHitachiAc1SwingByte LITERAL1
kHitachiAc1SwingHOffset LITERAL1
kHitachiAc1SwingToggleOffset LITERAL1
kHitachiAc1SwingVOffset LITERAL1
kHitachiAc1TempAuto LITERAL1
kHitachiAc1TempByte LITERAL1
kHitachiAc1TempDelta LITERAL1
kHitachiAc1TempOffset LITERAL1
kHitachiAc1TempSize LITERAL1
kHitachiAc1TimerSize LITERAL1
kHitachiAc2Bits LITERAL1
kHitachiAc2StateLength LITERAL1
kHitachiAc3BitMark LITERAL1
kHitachiAc3Bits LITERAL1
kHitachiAc3HdrMark LITERAL1
kHitachiAc3HdrSpace LITERAL1
kHitachiAc3MinBits LITERAL1
kHitachiAc3MinStateLength LITERAL1
kHitachiAc3OneSpace LITERAL1
kHitachiAc3StateLength LITERAL1
kHitachiAc3ZeroSpace LITERAL1
kHitachiAc424BitMark LITERAL1
kHitachiAc424Bits LITERAL1
kHitachiAc424ButtonByte LITERAL1
@ -2709,6 +2862,7 @@ kPioneerZeroSpaceTicks LITERAL1
kPowerStr LITERAL1
kPowerToggleStr LITERAL1
kPowerfulStr LITERAL1
kPreviousPowerStr LITERAL1
kProntoDataOffset LITERAL1
kProntoFreqFactor LITERAL1
kProntoFreqOffset LITERAL1
@ -2770,12 +2924,14 @@ kRightMaxStr LITERAL1
kRightStr LITERAL1
kRoomStr LITERAL1
kSamsung36Bits LITERAL1
kSamsungACSectionLength LITERAL1
kSamsungAcAuto LITERAL1
kSamsungAcAutoTemp LITERAL1
kSamsungAcBeepOffset LITERAL1
kSamsungAcBitMark LITERAL1
kSamsungAcBits LITERAL1
kSamsungAcBreezeOffset LITERAL1
kSamsungAcBreezeOn LITERAL1
kSamsungAcBreezeSize LITERAL1
kSamsungAcClean10Offset LITERAL1
kSamsungAcClean11Offset LITERAL1
kSamsungAcCool LITERAL1
@ -2806,11 +2962,13 @@ kSamsungAcPower6Offset LITERAL1
kSamsungAcPower6Size LITERAL1
kSamsungAcPowerSection LITERAL1
kSamsungAcPowerful10Offset LITERAL1
kSamsungAcPowerful10On LITERAL1
kSamsungAcPowerful10Size LITERAL1
kSamsungAcPowerfulMask8 LITERAL1
kSamsungAcQuiet1Offset LITERAL1
kSamsungAcQuiet5Offset LITERAL1
kSamsungAcSectionGap LITERAL1
kSamsungAcSectionLength LITERAL1
kSamsungAcSectionMark LITERAL1
kSamsungAcSectionSpace LITERAL1
kSamsungAcSections LITERAL1
@ -2864,14 +3022,17 @@ kSensorStr LITERAL1
kSensorTempStr LITERAL1
kSetStr LITERAL1
kSharpAcAuto LITERAL1
kSharpAcBitFanManualOffset LITERAL1
kSharpAcBitMark LITERAL1
kSharpAcBitModeNonAutoOffset LITERAL1
kSharpAcBitPowerOffset LITERAL1
kSharpAcBitTempManualOffset LITERAL1
kSharpAcBitPreviousPowerOffset LITERAL1
kSharpAcBits LITERAL1
kSharpAcButtonFan LITERAL1
kSharpAcButtonOffset LITERAL1
kSharpAcButtonPowerMode LITERAL1
kSharpAcButtonSize LITERAL1
kSharpAcButtonTemp LITERAL1
kSharpAcByteButton LITERAL1
kSharpAcByteFan LITERAL1
kSharpAcByteManual LITERAL1
kSharpAcByteMode LITERAL1
kSharpAcBytePower LITERAL1
kSharpAcByteTemp LITERAL1
@ -2952,6 +3113,14 @@ kSwingStr LITERAL1
kSwingVModeStr LITERAL1
kSwingVStr LITERAL1
kSwingVToggleStr LITERAL1
kSymphonyBits LITERAL1
kSymphonyDefaultRepeat LITERAL1
kSymphonyFooterGap LITERAL1
kSymphonyFooterMark LITERAL1
kSymphonyOneMark LITERAL1
kSymphonyOneSpace LITERAL1
kSymphonyZeroMark LITERAL1
kSymphonyZeroSpace LITERAL1
kTcl112AcAuto LITERAL1
kTcl112AcBitEconoOffset LITERAL1
kTcl112AcBitHealthOffset LITERAL1

View File

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

View File

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

View File

@ -123,6 +123,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
#if SEND_DAIKIN216
case decode_type_t::DAIKIN216:
#endif
#if SEND_DAIKIN64
case decode_type_t::DAIKIN64:
#endif
#if SEND_ELECTRA_AC
case decode_type_t::ELECTRA_AC:
#endif
@ -144,6 +147,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
#if SEND_HITACHI_AC
case decode_type_t::HITACHI_AC:
#endif
#if SEND_HITACHI_AC1
case decode_type_t::HITACHI_AC1:
#endif
#if SEND_HITACHI_AC424
case decode_type_t::HITACHI_AC424:
#endif
@ -461,6 +467,27 @@ void IRac::daikin216(IRDaikin216 *ac,
}
#endif // SEND_DAIKIN216
#if SEND_DAIKIN64
void IRac::daikin64(IRDaikin64 *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv,
const bool quiet, const bool turbo,
const int16_t sleep, const int16_t clock) {
ac->begin();
ac->setPowerToggle(on);
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
ac->setFan(ac->convertFan(fan));
ac->setSwingVertical((int8_t)swingv >= 0);
ac->setTurbo(turbo);
ac->setQuiet(quiet);
ac->setSleep(sleep >= 0);
ac->setClock(clock);
ac->send();
}
#endif // SEND_DAIKIN64
#if SEND_ELECTRA_AC
void IRac::electra(IRElectraAc *ac,
const bool on, const stdAc::opmode_t mode,
@ -674,6 +701,37 @@ void IRac::hitachi(IRHitachiAc *ac,
}
#endif // SEND_HITACHI_AC
#if SEND_HITACHI_AC1
void IRac::hitachi1(IRHitachiAc1 *ac, const hitachi_ac1_remote_model_t model,
const bool on, const bool power_toggle,
const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
const bool swing_toggle, const int16_t sleep) {
ac->begin();
ac->setModel(model);
ac->setPower(on);
ac->setPowerToggle(power_toggle);
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
ac->setFan(ac->convertFan(fan));
ac->setSwingV(swingv != stdAc::swingv_t::kOff);
ac->setSwingH(swingh != stdAc::swingh_t::kOff);
ac->setSwingToggle(swing_toggle);
ac->setSleep((sleep >= 0) ? kHitachiAc1Sleep2 : kHitachiAc1SleepOff);
// No Sleep setting available.
// No Swing(H) setting available.
// No Quiet setting available.
// No Turbo setting available.
// No Light setting available.
// No Filter setting available.
// No Clean setting available.
// No Beep setting available.
// No Clock setting available.
ac->send();
}
#endif // SEND_HITACHI_AC1
#if SEND_HITACHI_AC424
void IRac::hitachi424(IRHitachiAc424 *ac,
const bool on, const stdAc::opmode_t mode,
@ -999,10 +1057,11 @@ void IRac::samsung(IRSamsungAc *ac,
#if SEND_SHARP_AC
void IRac::sharp(IRSharpAc *ac,
const bool on, const stdAc::opmode_t mode,
const bool on, const bool prev_power,
const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan) {
ac->begin();
ac->setPower(on);
ac->setPower(on, prev_power);
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
ac->setFan(ac->convertFan(fan));
@ -1233,6 +1292,7 @@ stdAc::state_t IRac::handleToggles(const stdAc::state_t desired,
else
result.swingv = stdAc::swingv_t::kOff; // No change, so no toggle.
break;
case decode_type_t::DAIKIN64:
case decode_type_t::WHIRLPOOL_AC:
result.power = desired.power ^ prev->power;
break;
@ -1390,6 +1450,15 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
break;
}
#endif // SEND_DAIKIN216
#if SEND_DAIKIN64
case DAIKIN64:
{
IRDaikin64 ac(_pin, _inverted, _modulation);
daikin64(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
send.quiet, send.turbo, send.sleep, send.clock);
break;
}
#endif // SEND_DAIKIN64
#if SEND_ELECTRA_AC
case ELECTRA_AC:
{
@ -1457,6 +1526,23 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
break;
}
#endif // SEND_HITACHI_AC
#if SEND_HITACHI_AC1
case HITACHI_AC1:
{
IRHitachiAc1 ac(_pin, _inverted, _modulation);
bool power_toggle = false;
bool swing_toggle = false;
if (prev != NULL) {
power_toggle = (send.power != prev->power);
swing_toggle = (send.swingv != prev->swingv) ||
(send.swingh != prev->swingh);
}
hitachi1(&ac, (hitachi_ac1_remote_model_t)send.model, send.power,
power_toggle, send.mode, degC, send.fanspeed, send.swingv,
send.swingh, swing_toggle, send.sleep);
break;
}
#endif // SEND_HITACHI_AC1
#if SEND_HITACHI_AC424
case HITACHI_AC424:
{
@ -1572,7 +1658,9 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
case SHARP_AC:
{
IRSharpAc ac(_pin, _inverted, _modulation);
sharp(&ac, send.power, send.mode, degC, send.fanspeed);
bool prev_power = !send.power;
if (prev != NULL) prev_power = prev->power;
sharp(&ac, send.power, prev_power, send.mode, degC, send.fanspeed);
break;
}
#endif // SEND_SHARP_AC
@ -1796,6 +1884,11 @@ int16_t IRac::strToModel(const char *str, const int16_t def) {
return gree_ac_remote_model_t::YAW1F;
} else if (!strcasecmp(str, "YBOFB")) {
return gree_ac_remote_model_t::YBOFB;
// HitachiAc1 models
} else if (!strcasecmp(str, "R-LT0541-HTA-A")) {
return hitachi_ac1_remote_model_t::R_LT0541_HTA_A;
} else if (!strcasecmp(str, "R-LT0541-HTA-B")) {
return hitachi_ac1_remote_model_t::R_LT0541_HTA_B;
// Fujitsu A/C models
} else if (!strcasecmp(str, "ARRAH2E")) {
return fujitsu_ac_remote_model_t::ARRAH2E;
@ -2008,6 +2101,13 @@ namespace IRAcUtils {
return ac.toString();
}
#endif // DECODE_DAIKIN216
#if DECODE_DAIKIN64
case decode_type_t::DAIKIN64: {
IRDaikin64 ac(kGpioUnused);
ac.setRaw(result->value); // Daikin64 uses value instead of state.
return ac.toString();
}
#endif // DECODE_DAIKIN216
#if DECODE_ELECTRA_AC
case decode_type_t::ELECTRA_AC: {
IRElectraAc ac(0);
@ -2157,6 +2257,13 @@ namespace IRAcUtils {
return ac.toString();
}
#endif // DECODE_HITACHI_AC
#if DECODE_HITACHI_AC1
case decode_type_t::HITACHI_AC1: {
IRHitachiAc1 ac(kGpioUnused);
ac.setRaw(result->state);
return ac.toString();
}
#endif // DECODE_HITACHI_AC1
#if DECODE_HITACHI_AC424
case decode_type_t::HITACHI_AC424: {
IRHitachiAc424 ac(0);
@ -2305,6 +2412,14 @@ namespace IRAcUtils {
break;
}
#endif // DECODE_DAIKIN216
#if DECODE_DAIKIN64
case decode_type_t::DAIKIN64: {
IRDaikin64 ac(kGpioUnused);
ac.setRaw(decode->value); // Uses value instead of state.
*result = ac.toCommon(prev);
break;
}
#endif // DECODE_DAIKIN64
#if DECODE_ELECTRA_AC
case decode_type_t::ELECTRA_AC: {
IRElectraAc ac(kGpioUnused);
@ -2361,6 +2476,14 @@ namespace IRAcUtils {
break;
}
#endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC2)
#if DECODE_HITACHI_AC1
case decode_type_t::HITACHI_AC1: {
IRHitachiAc1 ac(kGpioUnused);
ac.setRaw(decode->state);
*result = ac.toCommon();
break;
}
#endif // DECODE_HITACHI_AC1
#if DECODE_HITACHI_AC424
case decode_type_t::HITACHI_AC424: {
IRHitachiAc424 ac(kGpioUnused);

View File

@ -166,6 +166,14 @@ void daikin216(IRDaikin216 *ac,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
const bool quiet, const bool turbo);
#endif // SEND_DAIKIN216
#if SEND_DAIKIN64
void daikin64(IRDaikin64 *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv,
const bool quiet, const bool turbo,
const int16_t sleep = -1, const int16_t clock = -1);
#endif // SEND_DAIKIN64
#if SEND_ELECTRA_AC
void electra(IRElectraAc *ac,
const bool on, const stdAc::opmode_t mode,
@ -219,6 +227,14 @@ void electra(IRElectraAc *ac,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh);
#endif // SEND_HITACHI_AC
#if SEND_HITACHI_AC1
void hitachi1(IRHitachiAc1 *ac, const hitachi_ac1_remote_model_t model,
const bool on, const bool power_toggle,
const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
const bool swing_toggle, const int16_t sleep = -1);
#endif // SEND_HITACHI_AC1
#if SEND_HITACHI_AC424
void hitachi424(IRHitachiAc424 *ac,
const bool on, const stdAc::opmode_t mode,
@ -308,7 +324,7 @@ void electra(IRElectraAc *ac,
#endif // SEND_SAMSUNG_AC
#if SEND_SHARP_AC
void sharp(IRSharpAc *ac,
const bool on, const stdAc::opmode_t mode,
const bool on, const bool prev_power, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan);
#endif // SEND_SHARP_AC
#if SEND_TCL112AC

View File

@ -641,10 +641,28 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
if (decodeHaierACYRW02(results, offset)) return true;
#endif
#if DECODE_HITACHI_AC424
// HitachiAc424 should be checked before HitachiAC & HitachiAC2
// HitachiAc424 should be checked before HitachiAC, HitachiAC2,
// & HitachiAC184
DPRINTLN("Attempting Hitachi AC 424 decode");
if (decodeHitachiAc424(results, offset, kHitachiAc424Bits)) return true;
#endif // DECODE_HITACHI_AC2
#endif // DECODE_HITACHI_AC424
#if DECODE_MITSUBISHI136
// Needs to happen before HitachiAc3 decode.
DPRINTLN("Attempting Mitsubishi136 decode");
if (decodeMitsubishi136(results, offset)) return true;
#endif // DECODE_MITSUBISHI136
#if DECODE_HITACHI_AC3
// HitachiAc3 should be checked before HitachiAC & HitachiAC2
// Attempt normal before the short version.
DPRINTLN("Attempting Hitachi AC3 decode");
// Order these in decreasing bit size, as it is more optimal.
if (decodeHitachiAc3(results, offset, kHitachiAc3Bits) ||
decodeHitachiAc3(results, offset, kHitachiAc3Bits - 4 * 8) ||
decodeHitachiAc3(results, offset, kHitachiAc3Bits - 6 * 8) ||
decodeHitachiAc3(results, offset, kHitachiAc3MinBits + 2 * 8) ||
decodeHitachiAc3(results, offset, kHitachiAc3MinBits))
return true;
#endif // DECODE_HITACHI_AC3
#if DECODE_HITACHI_AC2
// HitachiAC2 should be checked before HitachiAC
DPRINTLN("Attempting Hitachi AC2 decode");
@ -759,12 +777,20 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
DPRINTLN("Attempting Daikin152 decode");
if (decodeDaikin152(results, offset)) return true;
#endif // DECODE_DAIKIN152
#if DECODE_MITSUBISHI136
DPRINTLN("Attempting Mitsubishi136 decode");
if (decodeMitsubishi136(results, offset)) return true;
#endif // DECODE_MITSUBISHI136
}
#if DECODE_SYMPHONY
DPRINTLN("Attempting Symphony decode");
if (decodeSymphony(results, offset)) return true;
#endif // DECODE_SYMPHONY
#if DECODE_DAIKIN64
DPRINTLN("Attempting Daikin64 decode");
if (decodeDaikin64(results, offset)) return true;
#endif // DECODE_DAIKIN64
#if DECODE_AIRWELL
DPRINTLN("Attempting Airwell decode");
if (decodeAirwell(results, offset)) return true;
#endif // DECODE_AIRWELL
// Typically new protocols are added above this line.
}
#if DECODE_HASH
// decodeHash returns a hash on any input.
// Thus, it needs to be last in the list.
@ -1270,4 +1296,166 @@ uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
zeromark, zerospace, footermark, footerspace, atleast,
tolerance, excess, MSBfirst);
}
// Match & decode a Manchester Code <= 64bit IR message.
// The data is stored at result_ptr.
// Values of 0 for hdrmark, hdrspace, footermark, or footerspace mean skip
// that requirement.
//
// Args:
// data_ptr: A pointer to where we are at in the capture buffer.
// NOTE: It is assumed to be pointing to a "Mark", not a "Space".
// result_ptr: A pointer to where to start storing the bits we decoded.
// remaining: The size of the capture buffer are remaining.
// nbits: Nr. of data bits we expect.
// hdrmark: Nr. of uSeconds for the expected header mark signal.
// hdrspace: Nr. of uSeconds for the expected header space signal.
// half_period: Nr. of uSeconds for half the clock's period. (1/2 wavelength)
// footermark: Nr. of uSeconds for the expected footer mark signal.
// footerspace: Nr. of uSeconds for the expected footer space/gap signal.
// atleast: Is the match on the footerspace a matchAtLeast or matchSpace?
// tolerance: Percentage error margin to allow. (Def: kUseDefTol)
// excess: Nr. of useconds. (Def: kMarkExcess)
// MSBfirst: Bit order to save the data in. (Def: true)
// GEThomas: Use G.E. Thomas (true/default) or IEEE 802.3 (false) convention?
// Returns:
// A uint16_t: If successful, how many buffer entries were used. Otherwise 0.
//
// Ref:
// https://en.wikipedia.org/wiki/Manchester_code
// http://ww1.microchip.com/downloads/en/AppNotes/Atmel-9164-Manchester-Coding-Basics_Application-Note.pdf
uint16_t IRrecv::matchManchester(volatile const uint16_t *data_ptr,
uint64_t *result_ptr,
const uint16_t remaining,
const uint16_t nbits,
const uint16_t hdrmark,
const uint32_t hdrspace,
const uint16_t half_period,
const uint16_t footermark,
const uint32_t footerspace,
const bool atleast,
const uint8_t tolerance,
const int16_t excess,
const bool MSBfirst,
const bool GEThomas) {
uint16_t offset = 0;
uint64_t data = 0;
uint16_t nr_of_half_periods = GEThomas;
// 2 per bit, and 4 extra for the timing sync.
uint16_t expected_half_periods = 2 * nbits + 4;
bool currentBit = false;
// Calculate how much remaining buffer is required.
// Shortest case. Longest case is 2 * nbits.
uint16_t min_remaining = nbits + 2;
if (hdrmark) min_remaining++;
if (hdrspace) min_remaining++;
if (footermark) min_remaining++;
// Don't need to extend for footerspace because it could be the end of message
// Check if there is enough capture buffer to possibly have the message.
if (remaining < min_remaining) return 0; // Nope, so abort.
// Header
if (hdrmark && !matchMark(*(data_ptr + offset++), hdrmark, tolerance, excess))
return 0;
// Manchester Code always has a guaranteed 2x half_period (T2) at the start
// of the data section. e.g. a sync header. If it is a GEThomas-style, then
// it is space(T);mark(2xT);space(T), thus we need to check for that space
// plus any requested "header" space.
if ((hdrspace || GEThomas) &&
!matchSpace(*(data_ptr + offset++),
hdrspace + ((GEThomas) ? half_period : 0), tolerance, excess))
return 0;
// Data
// Loop until we find a 'long' pulse. This is the timing sync per protocol.
while ((offset < remaining) && (nr_of_half_periods < expected_half_periods) &&
!match(*(data_ptr + offset), half_period * 2, tolerance, excess)) {
// Was it not a short pulse?
if (!match(*(data_ptr + offset), half_period, tolerance, excess))
return 0;
nr_of_half_periods++;
offset++;
}
// Data (cont.)
// We are now pointing to the first 'long' pulse.
// Loop through the buffer till we run out of buffer, or nr of half periods.
while (offset < remaining && nr_of_half_periods < expected_half_periods) {
// Only if there is enough half_periods left for a long pulse &
// Is it a 'long' pulse?
if (nr_of_half_periods < expected_half_periods - 1 &&
match(*(data_ptr + offset), half_period * 2, tolerance, excess)) {
// Yes, so invert the value we will append.
currentBit = !currentBit;
nr_of_half_periods += 2; // A 'long' pulse is two half periods.
offset++;
// Append the bit value.
data <<= 1;
data |= currentBit;
} else if (match(*(data_ptr + offset), half_period, tolerance, excess)) {
// or is it part of a 'short' pulse pair?
nr_of_half_periods++;
offset++;
// Look for the second half of the 'short' pulse pair.
// Do we have enough buffer or nr of half periods?
if (offset < remaining && nr_of_half_periods < expected_half_periods) {
// We do, so look for it.
if (match(*(data_ptr + offset), half_period, tolerance, excess)) {
// Found it!
nr_of_half_periods++;
// No change of the polarity of the bit we will append.
// Append the bit value.
data <<= 1;
data |= currentBit;
offset++;
} else {
// It's not what we expected.
return 0;
}
}
} else if (nr_of_half_periods == expected_half_periods - 1 &&
matchAtLeast(*(data_ptr + offset), half_period, tolerance,
excess)) {
// Special case when we are at the end of the expected nr of periods.
// i.e. The pulse could be merged with the footer.
nr_of_half_periods++;
break;
} else {
// It's neither, so abort.
return 0;
}
}
// Did we collect the expected amount of data?
if (nr_of_half_periods < expected_half_periods) return 0;
// Footer
if (footermark &&
!(matchMark(*(data_ptr + offset), footermark + half_period,
tolerance, excess) ||
matchMark(*(data_ptr + offset), footermark,
tolerance, excess)))
return 0;
offset++;
// If we have something still to match & haven't reached the end of the buffer
if (footerspace && offset < remaining) {
if (atleast) {
if (!matchAtLeast(*(data_ptr + offset), footerspace, tolerance, excess))
return 0;
} else {
if (!matchSpace(*(data_ptr + offset), footerspace, tolerance, excess))
return 0;
}
offset++;
}
// Clean up and process the data.
if (!MSBfirst) data = reverseBits(data, nbits);
// Trim the data to size to remove timing sync.
*result_ptr = GETBITS64(data, 0, nbits);
return offset;
}
// End of IRrecv class -------------------

View File

@ -221,6 +221,20 @@ class IRrecv {
const uint8_t tolerance = kUseDefTol,
const int16_t excess = kMarkExcess,
const bool MSBfirst = true);
uint16_t matchManchester(volatile const uint16_t *data_ptr,
uint64_t *result_ptr,
const uint16_t remaining,
const uint16_t nbits,
const uint16_t hdrmark,
const uint32_t hdrspace,
const uint16_t clock_period,
const uint16_t footermark,
const uint32_t footerspace,
const bool atleast = false,
const uint8_t tolerance = kUseDefTol,
const int16_t excess = kMarkExcess,
const bool MSBfirst = true,
const bool GEThomas = true);
void crudeNoiseFilter(decode_results *results, const uint16_t floor = 0);
bool decodeHash(decode_results *results);
#if (DECODE_NEC || DECODE_SHERWOOD || DECODE_AIWA_RC_T501 || SEND_SANYO)
@ -393,6 +407,11 @@ class IRrecv {
const uint16_t nbits = kDaikinBits,
const bool strict = true);
#endif
#if DECODE_DAIKIN64
bool decodeDaikin64(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kDaikin64Bits,
const bool strict = true);
#endif // DECODE_DAIKIN64
#if DECODE_DAIKIN128
bool decodeDaikin128(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kDaikin128Bits,
@ -485,6 +504,12 @@ class IRrecv {
const uint16_t nbits = kHitachiAc1Bits,
const bool strict = true);
#endif
#if DECODE_HITACHI_AC3
bool decodeHitachiAc3(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kHitachiAc3Bits,
const bool strict = true);
#endif // DECODE_HITACHI_AC3
#if DECODE_HITACHI_AC424
bool decodeHitachiAc424(decode_results *results,
uint16_t offset = kStartOffset,
@ -558,6 +583,16 @@ class IRrecv {
const uint16_t nbits = kEpsonBits,
const bool strict = true);
#endif // DECODE_EPSON
#if DECODE_SYMPHONY
bool decodeSymphony(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kSymphonyBits,
const bool strict = true);
#endif // DECODE_SYMPHONY
#if DECODE_AIRWELL
bool decodeAirwell(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kAirwellBits,
const bool strict = true);
#endif // DECODE_AIRWELL
};
#endif // IRRECV_H_

View File

@ -52,7 +52,7 @@
#endif // UNIT_TEST
// Library Version
#define _IRREMOTEESP8266_VERSION_ "2.7.4"
#define _IRREMOTEESP8266_VERSION_ "2.7.5"
// Set the language & locale for the library. See the `locale` dir for options.
#ifndef _IR_LOCALE_
@ -411,6 +411,20 @@
#define SEND_HITACHI_AC2 _IR_ENABLE_DEFAULT_
#endif // SEND_HITACHI_AC2
#ifndef DECODE_HITACHI_AC3
#define DECODE_HITACHI_AC3 _IR_ENABLE_DEFAULT_
#endif // DECODE_HITACHI_AC3
#ifndef SEND_HITACHI_AC3
#define SEND_HITACHI_AC3 _IR_ENABLE_DEFAULT_
#endif // SEND_HITACHI_AC3
#ifndef DECODE_HITACHI_AC424
#define DECODE_HITACHI_AC424 _IR_ENABLE_DEFAULT_
#endif // DECODE_HITACHI_AC424
#ifndef SEND_HITACHI_AC424
#define SEND_HITACHI_AC424 _IR_ENABLE_DEFAULT_
#endif // SEND_HITACHI_AC424
#ifndef DECODE_GICABLE
#define DECODE_GICABLE _IR_ENABLE_DEFAULT_
#endif // DECODE_GICABLE
@ -558,13 +572,6 @@
#define SEND_DAIKIN152 _IR_ENABLE_DEFAULT_
#endif // SEND_DAIKIN152
#ifndef DECODE_HITACHI_AC424
#define DECODE_HITACHI_AC424 _IR_ENABLE_DEFAULT_
#endif // DECODE_HITACHI_AC424
#ifndef SEND_HITACHI_AC424
#define SEND_HITACHI_AC424 _IR_ENABLE_DEFAULT_
#endif // SEND_HITACHI_AC424
#ifndef DECODE_EPSON
#define DECODE_EPSON _IR_ENABLE_DEFAULT_
#endif // DECODE_EPSON
@ -572,6 +579,27 @@
#define SEND_EPSON _IR_ENABLE_DEFAULT_
#endif // SEND_EPSON
#ifndef DECODE_SYMPHONY
#define DECODE_SYMPHONY _IR_ENABLE_DEFAULT_
#endif // DECODE_SYMPHONY
#ifndef SEND_SYMPHONY
#define SEND_SYMPHONY _IR_ENABLE_DEFAULT_
#endif // SEND_SYMPHONY
#ifndef DECODE_DAIKIN64
#define DECODE_DAIKIN64 _IR_ENABLE_DEFAULT_
#endif // DECODE_DAIKIN64
#ifndef SEND_DAIKIN64
#define SEND_DAIKIN64 _IR_ENABLE_DEFAULT_
#endif // SEND_DAIKIN64
#ifndef DECODE_AIRWELL
#define DECODE_AIRWELL _IR_ENABLE_DEFAULT_
#endif // DECODE_AIRWELL
#ifndef SEND_AIRWELL
#define SEND_AIRWELL _IR_ENABLE_DEFAULT_
#endif // SEND_AIRWELL
#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \
DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \
DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \
@ -582,7 +610,7 @@
DECODE_DAIKIN216 || DECODE_SHARP_AC || DECODE_DAIKIN160 || \
DECODE_NEOCLIMA || DECODE_DAIKIN176 || DECODE_DAIKIN128 || \
DECODE_AMCOR || DECODE_DAIKIN152 || DECODE_MITSUBISHI136 || \
DECODE_MITSUBISHI112 || DECODE_HITACHI_AC424)
DECODE_MITSUBISHI112 || DECODE_HITACHI_AC424 || DECODE_HITACHI_AC3)
#define DECODE_AC true // We need some common infrastructure for decoding A/Cs.
#else
#define DECODE_AC false // We don't need that infrastructure.
@ -695,14 +723,20 @@ enum decode_type_t {
HITACHI_AC424,
SONY_38K,
EPSON, // 75
SYMPHONY,
HITACHI_AC3,
DAIKIN64,
AIRWELL,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = EPSON,
kLastDecodeType = AIRWELL,
};
// Message lengths & required repeat values
const uint16_t kNoRepeat = 0;
const uint16_t kSingleRepeat = 1;
const uint16_t kAirwellBits = 32;
const uint16_t kAirwellMinRepeats = 2;
const uint16_t kAiwaRcT501Bits = 15;
const uint16_t kAiwaRcT501MinRepeats = kSingleRepeat;
const uint16_t kAlokaBits = 32;
@ -724,6 +758,8 @@ const uint16_t kDaikinDefaultRepeat = kNoRepeat;
const uint16_t kDaikin2StateLength = 39;
const uint16_t kDaikin2Bits = kDaikin2StateLength * 8;
const uint16_t kDaikin2DefaultRepeat = kNoRepeat;
const uint16_t kDaikin64Bits = 64;
const uint16_t kDaikin64DefaultRepeat = kNoRepeat;
const uint16_t kDaikin160StateLength = 20;
const uint16_t kDaikin160Bits = kDaikin160StateLength * 8;
const uint16_t kDaikin160DefaultRepeat = kNoRepeat;
@ -774,6 +810,10 @@ const uint16_t kHitachiAc1StateLength = 13;
const uint16_t kHitachiAc1Bits = kHitachiAc1StateLength * 8;
const uint16_t kHitachiAc2StateLength = 53;
const uint16_t kHitachiAc2Bits = kHitachiAc2StateLength * 8;
const uint16_t kHitachiAc3StateLength = 27;
const uint16_t kHitachiAc3Bits = kHitachiAc3StateLength * 8;
const uint16_t kHitachiAc3MinStateLength = 15;
const uint16_t kHitachiAc3MinBits = kHitachiAc3MinStateLength * 8;
const uint16_t kHitachiAc424StateLength = 53;
const uint16_t kHitachiAc424Bits = kHitachiAc424StateLength * 8;
const uint16_t kInaxBits = 24;
@ -857,6 +897,8 @@ const uint16_t kSony15Bits = 15;
const uint16_t kSony20Bits = 20;
const uint16_t kSonyMinBits = 12;
const uint16_t kSonyMinRepeat = 2;
const uint16_t kSymphonyBits = 11;
const uint16_t kSymphonyDefaultRepeat = kSingleRepeat;
const uint16_t kTcl112AcStateLength = 14;
const uint16_t kTcl112AcBits = kTcl112AcStateLength * 8;
const uint16_t kTcl112AcDefaultRepeat = kNoRepeat;

View File

@ -462,6 +462,105 @@ void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace,
}
}
// Generic method for sending Manchester code data.
// Will send leading or trailing 0's if the nbits is larger than the number
// of bits in data.
//
// Args:
// half_period: Nr. of uSeconds for half the clock's period. (1/2 wavelength)
// data: The data to be transmitted.
// nbits: Nr. of bits of data to be sent.
// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order.
// GEThomas: Use G.E. Thomas (true/default) or IEEE 802.3 (false).
void IRsend::sendManchesterData(const uint16_t half_period,
const uint64_t data,
const uint16_t nbits, const bool MSBfirst,
const bool GEThomas) {
if (nbits == 0) return; // Nothing to send.
uint16_t bits = nbits;
uint64_t copy = (GEThomas) ? data : ~data;
if (MSBfirst) { // Send the MSB first.
// Send 0's until we get down to a bit size we can actually manage.
if (bits > (sizeof(data) * 8)) {
sendManchesterData(half_period, 0ULL, bits - sizeof(data) * 8, MSBfirst,
GEThomas);
bits = sizeof(data) * 8;
}
// Send the supplied data.
for (uint64_t mask = 1ULL << (bits - 1); mask; mask >>= 1)
if (copy & mask) {
mark(half_period);
space(half_period);
} else {
space(half_period);
mark(half_period);
}
} else { // Send the Least Significant Bit (LSB) first / MSB last.
for (bits = 0; bits < nbits; bits++, copy >>= 1)
if (copy & 1) {
mark(half_period);
space(half_period);
} else {
space(half_period);
mark(half_period);
}
}
}
// Generic method for sending Manchester code messages.
// Will send leading or trailing 0's if the nbits is larger than the number
// of bits in data.
//
// Args:
// headermark: Nr. of usecs for the led to be pulsed for the header mark.
// A value of 0 means no header mark.
// headerspace: Nr. of usecs for the led to be off after the header mark.
// A value of 0 means no header space.
// half_period: Nr. of uSeconds for half the clock's period. (1/2 wavelength)
// footermark: Nr. of usecs for the led to be pulsed for the footer mark.
// A value of 0 means no footer mark.
// gap: Min. nr. of usecs for the led to be off after the footer mark.
// This is effectively the absolute minimum gap between messages.
// data: The data to be transmitted.
// nbits: Nr. of bits of data to be sent.
// frequency: The frequency we want to modulate at.
// Assumes < 1000 means kHz otherwise it is in Hz.
// Most common value is 38000 or 38, for 38kHz.
// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order.
// repeat: Nr. of extra times the message will be sent.
// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages
// dutycycle: Percentage duty cycle of the LED.
// e.g. 25 = 25% = 1/4 on, 3/4 off.
// If you are not sure, try 50 percent.
// GEThomas: Use G.E. Thomas (true/default) or IEEE 802.3 (false).
void IRsend::sendManchester(const uint16_t headermark,
const uint32_t headerspace,
const uint16_t half_period,
const uint16_t footermark, const uint32_t gap,
const uint64_t data, const uint16_t nbits,
const uint16_t frequency, const bool MSBfirst,
const uint16_t repeat, const uint8_t dutycycle,
const bool GEThomas) {
// Setup
enableIROut(frequency, dutycycle);
// We always send a message, even for repeat=0, hence '<= repeat'.
for (uint16_t r = 0; r <= repeat; r++) {
// Header
if (headermark) mark(headermark);
if (headerspace) space(headerspace);
// Data Marker/sync
// This guarantees a double width half_period. i.e. a Period or T2.
sendManchesterData(half_period, 0b01, 2, true, GEThomas);
// Data
sendManchesterData(half_period, data, nbits, MSBfirst, GEThomas);
// Footer
if (footermark) mark(footermark);
if (gap) space(gap);
}
}
#if SEND_RAW
// Send a raw IRremote message.
//
@ -509,17 +608,20 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) {
case MITSUBISHI2:
case MITSUBISHI_AC:
case SHERWOOD:
case SYMPHONY:
case TOSHIBA_AC:
return kSingleRepeat;
// Special
case AIRWELL:
return kAirwellMinRepeats;
case DISH:
return kDishMinRepeat;
case EPSON:
return kEpsonMinRepeat;
case SONY:
return kSonyMinRepeat;
case SONY_38K:
return kSonyMinRepeat + 1;
case EPSON:
return kEpsonMinRepeat;
default:
return kNoRepeat;
}
@ -532,6 +634,8 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) {
// int16_t: The number of bits.
uint16_t IRsend::defaultBits(const decode_type_t protocol) {
switch (protocol) {
case SYMPHONY:
return 11;
case RC5:
return 12;
case LASERTAG:
@ -560,6 +664,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
case LG:
case LG2:
return 28;
case AIRWELL:
case CARRIER_AC:
case EPSON:
case NEC:
@ -601,6 +706,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return kDaikin2Bits;
case DAIKIN216:
return kDaikin216Bits;
case DAIKIN64:
return kDaikin64Bits;
case ELECTRA_AC:
return kElectraAcBits;
case GREE:
@ -615,6 +722,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return kHitachiAc1Bits;
case HITACHI_AC2:
return kHitachiAc2Bits;
case HITACHI_AC3:
return kHitachiAc3Bits;
case HITACHI_AC424:
return kHitachiAc424Bits;
case KELVINATOR:
@ -666,6 +775,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
const uint16_t nbits, const uint16_t repeat) {
uint16_t min_repeat = std::max(IRsend::minRepeats(type), repeat);
switch (type) {
#if SEND_AIRWELL
case AIRWELL:
sendAirwell(data, nbits, min_repeat);
break;
#endif
#if SEND_AIWA_RC_T501
case AIWA_RC_T501:
sendAiwaRCT501(data, nbits, min_repeat);
@ -681,6 +795,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
sendCOOLIX(data, nbits, min_repeat);
break;
#endif
#if SEND_DAIKIN64
case DAIKIN64:
sendDaikin64(data, nbits, min_repeat);
break;
#endif
#if SEND_DENON
case DENON:
sendDenon(data, nbits, min_repeat);
@ -834,6 +953,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
sendSony38(data, nbits, min_repeat);
break;
#endif
#if SEND_SYMPHONY
case SYMPHONY:
sendSymphony(data, nbits, min_repeat);
break;
#endif
#if SEND_TECO
case TECO:
sendTeco(data, nbits, min_repeat);
@ -951,6 +1075,11 @@ bool IRsend::send(const decode_type_t type, const unsigned char *state,
sendHitachiAC2(state, nbytes);
break;
#endif // SEND_HITACHI_AC2
#if SEND_HITACHI_AC3
case HITACHI_AC3:
sendHitachiAc3(state, nbytes);
break;
#endif // SEND_HITACHI_AC3
#if SEND_HITACHI_AC424
case HITACHI_AC424:
sendHitachiAc424(state, nbytes);

View File

@ -126,6 +126,11 @@ enum gree_ac_remote_model_t {
YBOFB, // (2) Green, YBOFB2, YAPOF3
};
enum hitachi_ac1_remote_model_t {
R_LT0541_HTA_A = 1, // (1) R-LT0541-HTA Remote in "A" setting. (Default)
R_LT0541_HTA_B, // (2) R-LT0541-HTA Remote in "B" setting.
};
enum panasonic_ac_remote_model_t {
kPanasonicUnknown = 0,
kPanasonicLke = 1,
@ -162,6 +167,17 @@ class IRsend {
void sendData(uint16_t onemark, uint32_t onespace, uint16_t zeromark,
uint32_t zerospace, uint64_t data, uint16_t nbits,
bool MSBfirst = true);
void sendManchesterData(const uint16_t half_period, const uint64_t data,
const uint16_t nbits, const bool MSBfirst = true,
const bool GEThomas = true);
void sendManchester(const uint16_t headermark, const uint32_t headerspace,
const uint16_t half_period, const uint16_t footermark,
const uint32_t gap, const uint64_t data,
const uint16_t nbits, const uint16_t frequency = 38,
const bool MSBfirst = true,
const uint16_t repeat = kNoRepeat,
const uint8_t dutycycle = kDutyDefault,
const bool GEThomas = true);
void sendGeneric(const uint16_t headermark, const uint32_t headerspace,
const uint16_t onemark, const uint32_t onespace,
const uint16_t zeromark, const uint32_t zerospace,
@ -362,6 +378,10 @@ class IRsend {
const uint16_t nbytes = kDaikinStateLength,
const uint16_t repeat = kDaikinDefaultRepeat);
#endif
#if SEND_DAIKIN64
void sendDaikin64(const uint64_t data, const uint16_t nbits = kDaikin64Bits,
const uint16_t repeat = kDaikin64DefaultRepeat);
#endif // SEND_DAIKIN64
#if SEND_DAIKIN128
void sendDaikin128(const unsigned char data[],
const uint16_t nbytes = kDaikin128StateLength,
@ -471,6 +491,12 @@ class IRsend {
const uint16_t nbytes = kHitachiAc2StateLength,
const uint16_t repeat = kHitachiAcDefaultRepeat);
#endif
#if SEND_HITACHI_AC3
void sendHitachiAc3(const unsigned char data[],
const uint16_t nbytes, // No default as there as so many
// different sizes
const uint16_t repeat = kHitachiAcDefaultRepeat);
#endif // SEND_HITACHI_AC3
#if SEND_HITACHI_AC424
void sendHitachiAc424(const unsigned char data[],
const uint16_t nbytes = kHitachiAc424StateLength,
@ -539,6 +565,14 @@ class IRsend {
void sendEpson(uint64_t data, uint16_t nbits = kEpsonBits,
uint16_t repeat = kEpsonMinRepeat);
#endif
#if SEND_SYMPHONY
void sendSymphony(uint64_t data, uint16_t nbits = kSymphonyBits,
uint16_t repeat = kSymphonyDefaultRepeat);
#endif
#if SEND_AIRWELL
void sendAirwell(uint64_t data, uint16_t nbits = kAirwellBits,
uint16_t repeat = kAirwellMinRepeats);
#endif
protected:
#ifdef UNIT_TEST

View File

@ -130,6 +130,7 @@ const PROGMEM char* kEyeAutoStr = D_STR_EYEAUTO;
const PROGMEM char* kLightToggleStr = D_STR_LIGHTTOGGLE;
const PROGMEM char* kOutsideQuietStr = D_STR_OUTSIDEQUIET;
const PROGMEM char* kPowerToggleStr = D_STR_POWERTOGGLE;
const PROGMEM char* kPreviousPowerStr = D_STR_PREVIOUSPOWER;
const PROGMEM char* kSensorTempStr = D_STR_SENSORTEMP;
const PROGMEM char* kSleepTimerStr = D_STR_SLEEP_TIMER;
const PROGMEM char* kSwingVModeStr = D_STR_SWINGVMODE;

View File

@ -104,6 +104,7 @@ extern const char* kOutsideStr;
extern const char* kPowerfulStr;
extern const char* kPowerStr;
extern const char* kPowerToggleStr;
extern const char* kPreviousPowerStr;
extern const char* kProtocolStr;
extern const char* kPurifyStr;
extern const char* kQuietStr;

View File

@ -95,6 +95,8 @@ decode_type_t strToDecodeType(const char * const str) {
return decode_type_t::UNKNOWN;
else if (!strcasecmp(str, "UNUSED"))
return decode_type_t::UNUSED;
else if (!strcasecmp(str, "AIRWELL"))
return decode_type_t::AIRWELL;
else if (!strcasecmp(str, "AIWA_RC_T501"))
return decode_type_t::AIWA_RC_T501;
else if (!strcasecmp(str, "AMCOR"))
@ -119,6 +121,8 @@ decode_type_t strToDecodeType(const char * const str) {
return decode_type_t::DAIKIN2;
else if (!strcasecmp(str, "DAIKIN216"))
return decode_type_t::DAIKIN216;
else if (!strcasecmp(str, "DAIKIN64"))
return decode_type_t::DAIKIN64;
else if (!strcasecmp(str, "DENON"))
return decode_type_t::DENON;
else if (!strcasecmp(str, "DISH"))
@ -147,6 +151,8 @@ decode_type_t strToDecodeType(const char * const str) {
return decode_type_t::HITACHI_AC1;
else if (!strcasecmp(str, "HITACHI_AC2"))
return decode_type_t::HITACHI_AC2;
else if (!strcasecmp(str, "HITACHI_AC3"))
return decode_type_t::HITACHI_AC3;
else if (!strcasecmp(str, "HITACHI_AC424"))
return decode_type_t::HITACHI_AC424;
else if (!strcasecmp(str, "INAX"))
@ -232,6 +238,8 @@ decode_type_t strToDecodeType(const char * const str) {
return decode_type_t::SONY;
else if (!strcasecmp(str, "SONY_38K"))
return decode_type_t::SONY_38K;
else if (!strcasecmp(str, "SYMPHONY"))
return decode_type_t::SYMPHONY;
else if (!strcasecmp(str, "TCL112AC"))
return decode_type_t::TCL112AC;
else if (!strcasecmp(str, "TECO"))
@ -267,6 +275,9 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) {
case UNUSED:
result = F("UNUSED");
break;
case AIRWELL:
result = F("AIRWELL");
break;
case AIWA_RC_T501:
result = F("AIWA_RC_T501");
break;
@ -303,6 +314,9 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) {
case DAIKIN216:
result = F("DAIKIN216");
break;
case DAIKIN64:
result = F("DAIKIN64");
break;
case DENON:
result = F("DENON");
break;
@ -345,6 +359,9 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) {
case HITACHI_AC2:
result = F("HITACHI_AC2");
break;
case HITACHI_AC3:
result = F("HITACHI_AC3");
break;
case HITACHI_AC424:
result = F("HITACHI_AC424");
break;
@ -471,6 +488,9 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) {
case SONY_38K:
result = F("SONY_38K");
break;
case SYMPHONY:
result = F("SYMPHONY");
break;
case TCL112AC:
result = F("TCL112AC");
break;
@ -525,6 +545,7 @@ bool hasACState(const decode_type_t protocol) {
case HITACHI_AC:
case HITACHI_AC1:
case HITACHI_AC2:
case HITACHI_AC3:
case HITACHI_AC424:
case KELVINATOR:
case MITSUBISHI136:
@ -851,6 +872,15 @@ namespace irutils {
default: return kUnknownStr;
}
break;
case decode_type_t::HITACHI_AC1:
switch (model) {
case hitachi_ac1_remote_model_t::R_LT0541_HTA_A:
return F("R-LT0541-HTA-A");
case hitachi_ac1_remote_model_t::R_LT0541_HTA_B:
return F("R-LT0541-HTA-B");
default: return kUnknownStr;
}
break;
case decode_type_t::LG:
case decode_type_t::LG2:
switch (model) {

View File

@ -0,0 +1,83 @@
// Copyright 2020 David Conran
#include "IRrecv.h"
#include "IRsend.h"
// Airwell "Manchester code" based protocol.
// Some other Airwell products use the COOLIX protocol.
//
// Supports:
// Brand: Airwell, Model: RC08W remote
const uint8_t kAirwellOverhead = 4;
const uint16_t kAirwellHalfClockPeriod = 950; // uSeconds
const uint16_t kAirwellHdrMark = 3 * kAirwellHalfClockPeriod; // uSeconds
const uint16_t kAirwellHdrSpace = 4 * kAirwellHalfClockPeriod; // uSeconds
const uint16_t kAirwellFooterMark = 5 * kAirwellHalfClockPeriod; // uSeconds
#if SEND_AIRWELL
// Send an Airwell Manchester Code formatted message.
//
// Args:
// data: The message to be sent.
// nbits: The number of bits of the message to be sent.
// Typically kAirwellBits.
// repeat: The number of times the command is to be repeated.
//
// Status: BETA / Appears to be working.
//
// Ref:
// https://github.com/crankyoldgit/IRremoteESP8266/issues/1069
void IRsend::sendAirwell(uint64_t data, uint16_t nbits, uint16_t repeat) {
// Header + Data
sendManchester(kAirwellHdrMark, kAirwellHdrMark, kAirwellHalfClockPeriod,
0, 0, data, nbits, 38000, true, repeat);
// Footer
mark(kAirwellHdrMark + kAirwellHalfClockPeriod);
space(kDefaultMessageGap); // A guess.
}
#endif
#if DECODE_AIRWELL
// Decode the supplied Airwell "Manchester code" message.
//
// Args:
// results: Ptr to the data to decode and where to store the decode result.
// offset: The starting index to use when attempting to decode the raw data.
// Typically/Defaults to kStartOffset.
// nbits: The number of data bits to expect. Typically kAirwellBits.
// strict: Flag indicating if we should perform strict matching.
// Returns:
// boolean: True if it can decode it, false if it can't.
//
// Status: BETA / Appears to be working.
//
// Ref:
// https://github.com/crankyoldgit/IRremoteESP8266/issues/1069
bool IRrecv::decodeAirwell(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < nbits + kAirwellOverhead - offset)
return false; // Too short a message to match.
// Compliance
if (strict && nbits != kAirwellBits)
return false; // Doesn't match our protocol defn.
// Header #1 + Data #1 + Footer #1 (There are total of 3 sections)
uint16_t used = matchManchester(results->rawbuf + offset, &results->value,
results->rawlen - offset, nbits,
kAirwellHdrMark, kAirwellHdrMark,
kAirwellHalfClockPeriod,
kAirwellHdrMark, kAirwellHdrSpace,
true);
if (used == 0) return false;
offset += used;
// Success
results->decode_type = decode_type_t::AIRWELL;
results->bits = nbits;
results->address = 0;
results->command = 0;
return true;
}
#endif

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