mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-27 19:57:38 +00:00
IR Update library and usage instructions
This commit is contained in:
@@ -56,6 +56,7 @@ jobs:
|
||||
- arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino 2> /dev/null
|
||||
- arduino --verify --board $BD $PWD/examples/DumbIRRepeater/DumbIRRepeater.ino 2> /dev/null
|
||||
- arduino --verify --board $BD $PWD/examples/SmartIRRepeater/SmartIRRepeater.ino 2> /dev/null
|
||||
- arduino --verify --board $BD $PWD/examples/CommonAcControl/CommonAcControl.ino 2> /dev/null
|
||||
- script:
|
||||
# Check the version numbers match.
|
||||
- LIB_VERSION=$(egrep "^#define\s+_IRREMOTEESP8266_VERSION_\s+" src/IRremoteESP8266.h | cut -d\" -f2)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/* Copyright 2019 David Conran
|
||||
*
|
||||
* This example code demonstrates how to use the "Common" IRac class to control
|
||||
* various air conditions. The IRac class does not support all the features
|
||||
* for every protocol. Some have more detailed support that what the "Common"
|
||||
* interface offers, and some only have a limited subset of the "Common" options.
|
||||
*
|
||||
* This example code will:
|
||||
* o Try to turn on, then off every fully supported A/C protocol we know of.
|
||||
* o It will try to put the A/C unit into Cooling mode at 25C, with a medium
|
||||
* fan speed, and no fan swinging.
|
||||
* Note: Some protocols support multiple models, only the first model is tried.
|
||||
*
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRac.h>
|
||||
#include <IRutils.h>
|
||||
|
||||
const uint16_t kIrLed = 4; // The ESP GPIO pin to use that controls the IR LED.
|
||||
IRac ac(kIrLed); // Create a A/C object using GPIO to sending messages with.
|
||||
stdAc::state_t state; // Where we will store the desired state of the A/C.
|
||||
stdAc::state_t prev; // Where we will store the previous state of the A/C.
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(200);
|
||||
|
||||
// Set up what we want to send.
|
||||
// See state_t, opmode_t, fanspeed_t, swingv_t, & swingh_t in IRsend.h for
|
||||
// all the various options.
|
||||
state.protocol = decode_type_t::DAIKIN; // Set a protocol to use.
|
||||
state.model = 1; // Some A/C's have different models. Let's try using just 1.
|
||||
state.mode = stdAc::opmode_t::kCool; // Run in cool mode initially.
|
||||
state.celsius = true; // Use Celsius for units of temp. False = Fahrenheit
|
||||
state.degrees = 25; // 25 degrees.
|
||||
state.fanspeed = stdAc::fanspeed_t::kMedium; // Start with the fan at medium.
|
||||
state.swingv = stdAc::swingv_t::kOff; // Don't swing the fan up or down.
|
||||
state.swingh = stdAc::swingh_t::kOff; // Don't swing the fan left or right.
|
||||
state.light = false; // Turn off any LED/Lights/Display that we can.
|
||||
state.beep = false; // Turn off any beep from the A/C if we can.
|
||||
state.econo = false; // Turn off any economy modes if we can.
|
||||
state.filter = false; // Turn off any Ion/Mold/Health filters if we can.
|
||||
state.turbo = false; // Don't use any turbo/powerful/etc modes.
|
||||
state.quiet = false; // Don't use any quiet/silent/etc modes.
|
||||
state.sleep = -1; // Don't set any sleep time or modes.
|
||||
state.clean = false; // Turn off any Cleaning options if we can.
|
||||
state.clock = -1; // Don't set any current time if we can avoid it.
|
||||
state.power = false; // Initially start with the unit off.
|
||||
|
||||
prev = state; // Make sure we have a valid previous state.
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// For every protocol the library has ...
|
||||
for (int i = 1; i < kLastDecodeType; i++) {
|
||||
decode_type_t protocol = (decode_type_t)i;
|
||||
// If the protocol is supported by the IRac class ...
|
||||
if (ac.isProtocolSupported(protocol)) {
|
||||
state.protocol = protocol; // Change the protocol used.
|
||||
|
||||
Serial.println("Protocol " + String(protocol) + " / " +
|
||||
typeToString(protocol));
|
||||
state.power = true; // We want to turn on the A/C unit.
|
||||
// Have the IRac class create and send a message.
|
||||
// We need a `prev` state as some A/Cs use toggle messages.
|
||||
// e.g. On & Off are the same message. When given the previous state,
|
||||
// it will try to do the correct thing for you.
|
||||
ac.sendAc(state, &prev); // Construct and send the message.
|
||||
Serial.println("Sent a message to turn ON the A/C unit.");
|
||||
prev = state; // Copy new state over the previous one.
|
||||
delay(5000); // Wait 5 seconds.
|
||||
state.power = false; // Now we want to turn the A/C off.
|
||||
ac.sendAc(state, &prev); // Construct and send the message.
|
||||
Serial.println("Sent a message to turn OFF the A/C unit.");
|
||||
prev = state; // Copy new state over the previous one.
|
||||
delay(1000); // Wait 1 second.
|
||||
}
|
||||
}
|
||||
Serial.println("Starting from the begining again ...");
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
[platformio]
|
||||
src_dir = .
|
||||
|
||||
[env]
|
||||
lib_extra_dirs = ../../
|
||||
lib_ldf_mode = deep+
|
||||
lib_ignore = examples
|
||||
build_flags =
|
||||
|
||||
[env:nodemcuv2]
|
||||
platform = espressif8266
|
||||
framework = arduino
|
||||
board = nodemcuv2
|
||||
|
||||
[env:esp32dev]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
@@ -5,6 +5,9 @@
|
||||
#ifndef EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_
|
||||
#define EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif // ESP8266
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRrecv.h>
|
||||
#include <IRsend.h>
|
||||
@@ -156,6 +159,16 @@ const uint16_t kMinUnknownSize = 2 * 10;
|
||||
|
||||
// ------------------------ Advanced Usage Only --------------------------------
|
||||
|
||||
// Reports the input voltage to the ESP chip. **NOT** the input voltage
|
||||
// to the development board (e.g. NodeMCU, D1 Mini etc) which are typically
|
||||
// powered by USB (5V) which is then lowered to 3V via a Low Drop Out (LDO)
|
||||
// Voltage regulator. Hence, this feature is turned off by default as it
|
||||
// make little sense for most users as it really isn't the actual input voltage.
|
||||
// E.g. For purposes of monitoring a battery etc.
|
||||
// Note: Turning on the feature costs ~250 bytes of prog space.
|
||||
#define REPORT_VCC false // Do we report Vcc via html info page & MQTT?
|
||||
|
||||
// Keywords for MQTT topics, html arguments, or config file.
|
||||
#define KEY_PROTOCOL "protocol"
|
||||
#define KEY_MODEL "model"
|
||||
#define KEY_POWER "power"
|
||||
@@ -175,6 +188,7 @@ const uint16_t kMinUnknownSize = 2 * 10;
|
||||
#define KEY_CELSIUS "use_celsius"
|
||||
#define KEY_JSON "json"
|
||||
#define KEY_RESEND "resend"
|
||||
#define KEY_VCC "vcc"
|
||||
|
||||
// HTML arguments we will parse for IR code information.
|
||||
#define KEY_TYPE "type" // KEY_PROTOCOL is also checked too.
|
||||
@@ -297,6 +311,9 @@ void sendJsonState(const stdAc::state_t state, const String topic,
|
||||
const bool retain = false, const bool ha_mode = true);
|
||||
#endif // MQTT_CLIMATE_JSON
|
||||
#endif // MQTT_ENABLE
|
||||
#if REPORT_VCC
|
||||
String vccToString(void);
|
||||
#endif // REPORT_VCC
|
||||
bool isSerialGpioUsedByIr(void);
|
||||
void debug(const char *str);
|
||||
void saveWifiConfigCallback(void);
|
||||
|
||||
@@ -347,6 +347,10 @@
|
||||
|
||||
using irutils::msToString;
|
||||
|
||||
#if REPORT_VCC
|
||||
ADC_MODE(ADC_VCC);
|
||||
#endif // REPORT_VCC
|
||||
|
||||
// Globals
|
||||
#if defined(ESP8266)
|
||||
ESP8266WebServer server(kHttpPort);
|
||||
@@ -913,7 +917,7 @@ String htmlSelectGpio(const String name, const int16_t def,
|
||||
|
||||
String htmlSelectMode(const String name, const stdAc::opmode_t def) {
|
||||
String html = "<select name='" + name + "'>";
|
||||
for (int8_t i = -1; i <= 4; i++) {
|
||||
for (int8_t i = -1; i <= (int8_t)stdAc::opmode_t::kLastOpmodeEnum; i++) {
|
||||
String mode = IRac::opmodeToString((stdAc::opmode_t)i);
|
||||
html += htmlOptionItem(mode, mode, (stdAc::opmode_t)i == def);
|
||||
}
|
||||
@@ -923,7 +927,7 @@ String htmlSelectMode(const String name, const stdAc::opmode_t def) {
|
||||
|
||||
String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def) {
|
||||
String html = "<select name='" + name + "'>";
|
||||
for (int8_t i = 0; i <= 5; i++) {
|
||||
for (int8_t i = 0; i <= (int8_t)stdAc::fanspeed_t::kLastFanspeedEnum; i++) {
|
||||
String speed = IRac::fanspeedToString((stdAc::fanspeed_t)i);
|
||||
html += htmlOptionItem(speed, speed, (stdAc::fanspeed_t)i == def);
|
||||
}
|
||||
@@ -933,7 +937,7 @@ String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def) {
|
||||
|
||||
String htmlSelectSwingv(const String name, const stdAc::swingv_t def) {
|
||||
String html = "<select name='" + name + "'>";
|
||||
for (int8_t i = -1; i <= 5; i++) {
|
||||
for (int8_t i = -1; i <= (int8_t)stdAc::swingv_t::kLastSwingvEnum; i++) {
|
||||
String swing = IRac::swingvToString((stdAc::swingv_t)i);
|
||||
html += htmlOptionItem(swing, swing, (stdAc::swingv_t)i == def);
|
||||
}
|
||||
@@ -943,7 +947,7 @@ String htmlSelectSwingv(const String name, const stdAc::swingv_t def) {
|
||||
|
||||
String htmlSelectSwingh(const String name, const stdAc::swingh_t def) {
|
||||
String html = "<select name='" + name + "'>";
|
||||
for (int8_t i = -1; i <= 5; i++) {
|
||||
for (int8_t i = -1; i <= (int8_t)stdAc::swingh_t::kLastSwinghEnum; i++) {
|
||||
String swing = IRac::swinghToString((stdAc::swingh_t)i);
|
||||
html += htmlOptionItem(swing, swing, (stdAc::swingh_t)i == def);
|
||||
}
|
||||
@@ -1121,6 +1125,10 @@ uint32_t maxSketchSpace(void) {
|
||||
#endif // defined(ESP8266)
|
||||
}
|
||||
|
||||
#if REPORT_VCC
|
||||
String vccToString(void) { return String(ESP.getVcc() / 1000.0); }
|
||||
#endif // REPORT_VCC
|
||||
|
||||
// Info web page
|
||||
void handleInfo(void) {
|
||||
String html = htmlHeader(F("IR MQTT server info"));
|
||||
@@ -1175,6 +1183,11 @@ void handleInfo(void) {
|
||||
"Off"
|
||||
#endif // DEBUG
|
||||
"<br>"
|
||||
#if REPORT_VCC
|
||||
"Vcc: ";
|
||||
html += vccToString();
|
||||
html += "V<br>"
|
||||
#endif // REPORT_VCC
|
||||
"</p>"
|
||||
#if MQTT_ENABLE
|
||||
"<h4>MQTT Information</h4>"
|
||||
@@ -1252,7 +1265,8 @@ void doRestart(const char* str, const bool serial_only) {
|
||||
void handleReset(void) {
|
||||
#if HTML_PASSWORD_ENABLE
|
||||
if (!server.authenticate(HttpUsername, HttpPassword)) {
|
||||
debug("Basic HTTP authentication failure for " + kUrlWipe);
|
||||
debug(("Basic HTTP authentication failure for " +
|
||||
String(kUrlWipe)).c_str());
|
||||
return server.requestAuthentication();
|
||||
}
|
||||
#endif
|
||||
@@ -1281,7 +1295,8 @@ void handleReset(void) {
|
||||
void handleReboot() {
|
||||
#if HTML_PASSWORD_ENABLE
|
||||
if (!server.authenticate(HttpUsername, HttpPassword)) {
|
||||
debug("Basic HTTP authentication failure for " + kUrlReboot);
|
||||
debug(("Basic HTTP authentication failure for " +
|
||||
String(kUrlReboot)).c_str());
|
||||
return server.requestAuthentication();
|
||||
}
|
||||
#endif
|
||||
@@ -2167,6 +2182,9 @@ void doBroadcast(TimerMs *timer, const uint32_t interval,
|
||||
debug("Sending MQTT stat update broadcast.");
|
||||
sendClimate(state, state, MqttClimateStat,
|
||||
retain, true, false);
|
||||
#if REPORT_VCC
|
||||
sendString(MqttClimateStat + KEY_VCC, vccToString(), false);
|
||||
#endif // REPORT_VCC
|
||||
#if MQTT_CLIMATE_JSON
|
||||
sendJsonState(state, MqttClimateStat + KEY_JSON);
|
||||
#endif // MQTT_CLIMATE_JSON
|
||||
@@ -2322,29 +2340,22 @@ void sendMQTTDiscovery(const char *topic) {
|
||||
"{"
|
||||
"\"~\":\"" + MqttClimate + "\","
|
||||
"\"name\":\"" + MqttHAName + "\","
|
||||
"\"pow_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" KEY_POWER "\","
|
||||
"\"mode_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" KEY_MODE "\","
|
||||
"\"mode_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/" KEY_MODE
|
||||
"\","
|
||||
"\"pow_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_POWER "\","
|
||||
"\"mode_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_MODE "\","
|
||||
"\"mode_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_MODE "\","
|
||||
"\"modes\":[\"off\",\"auto\",\"cool\",\"heat\",\"dry\",\"fan_only\"],"
|
||||
"\"temp_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" KEY_TEMP "\","
|
||||
"\"temp_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/" KEY_TEMP
|
||||
"\","
|
||||
"\"temp_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_TEMP "\","
|
||||
"\"temp_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_TEMP "\","
|
||||
"\"min_temp\":\"16\","
|
||||
"\"max_temp\":\"30\","
|
||||
"\"temp_step\":\"1\","
|
||||
"\"fan_mode_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/"
|
||||
KEY_FANSPEED "\","
|
||||
"\"fan_mode_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/"
|
||||
KEY_FANSPEED "\","
|
||||
"\"fan_mode_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_FANSPEED "\","
|
||||
"\"fan_mode_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_FANSPEED "\","
|
||||
"\"fan_modes\":[\"auto\",\"min\",\"low\",\"medium\",\"high\",\"max\"],"
|
||||
"\"swing_mode_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/"
|
||||
KEY_SWINGV "\","
|
||||
"\"swing_mode_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/"
|
||||
KEY_SWINGV "\","
|
||||
"\"swing_mode_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_SWINGV "\","
|
||||
"\"swing_mode_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_SWINGV "\","
|
||||
"\"swing_modes\":["
|
||||
"\"off\",\"auto\",\"highest\",\"high\",\"middle\",\"low\",\"lowest\""
|
||||
"]"
|
||||
"\"off\",\"auto\",\"highest\",\"high\",\"middle\",\"low\",\"lowest\"]"
|
||||
"}").c_str())) {
|
||||
mqttLog("MQTT climate discovery successful sent.");
|
||||
hasDiscoveryBeenSent = true;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "IRsend.h"
|
||||
#include "IRremoteESP8266.h"
|
||||
#include "IRutils.h"
|
||||
#include "ir_Amcor.h"
|
||||
#include "ir_Argo.h"
|
||||
#include "ir_Coolix.h"
|
||||
#include "ir_Daikin.h"
|
||||
@@ -46,7 +47,10 @@ IRac::IRac(const uint16_t pin, const bool inverted, const bool use_modulation) {
|
||||
// Is the given protocol supported by the IRac class?
|
||||
bool IRac::isProtocolSupported(const decode_type_t protocol) {
|
||||
switch (protocol) {
|
||||
#if SEND_ARGO
|
||||
#if SEND_AMCOR
|
||||
case decode_type_t::AMCOR:
|
||||
#endif
|
||||
#if SEND_AMCOR
|
||||
case decode_type_t::ARGO:
|
||||
#endif
|
||||
#if SEND_COOLIX
|
||||
@@ -140,6 +144,27 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
|
||||
}
|
||||
}
|
||||
|
||||
#if SEND_AMCOR
|
||||
void IRac::amcor(IRAmcorAc *ac,
|
||||
const bool on, const stdAc::opmode_t mode, const float degrees,
|
||||
const stdAc::fanspeed_t fan) {
|
||||
ac->setPower(on);
|
||||
ac->setMode(ac->convertMode(mode));
|
||||
ac->setTemp(degrees);
|
||||
ac->setFan(ac->convertFan(fan));
|
||||
// No Swing setting available.
|
||||
// No Quiet setting available.
|
||||
// No Light setting available.
|
||||
// No Filter setting available.
|
||||
// No Turbo setting available.
|
||||
// No Economy setting available.
|
||||
// No Clean setting available.
|
||||
// No Beep setting available.
|
||||
// No Sleep setting available.
|
||||
ac->send();
|
||||
}
|
||||
#endif // SEND_AMCOR
|
||||
|
||||
#if SEND_ARGO
|
||||
void IRac::argo(IRArgoAC *ac,
|
||||
const bool on, const stdAc::opmode_t mode, const float degrees,
|
||||
@@ -400,6 +425,7 @@ void IRac::fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model,
|
||||
// No Beep setting available.
|
||||
// No Sleep setting available.
|
||||
// No Clock setting available.
|
||||
ac->on(); // Ref: Issue #860
|
||||
} else {
|
||||
// Off is special case/message. We don't need to send other messages.
|
||||
ac->off();
|
||||
@@ -801,7 +827,7 @@ void IRac::tcl112(IRTcl112Ac *ac,
|
||||
void IRac::teco(IRTecoAc *ac,
|
||||
const bool on, const stdAc::opmode_t mode, const float degrees,
|
||||
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
|
||||
const int16_t sleep) {
|
||||
const bool light, const int16_t sleep) {
|
||||
ac->setPower(on);
|
||||
ac->setMode(ac->convertMode(mode));
|
||||
ac->setTemp(degrees);
|
||||
@@ -810,7 +836,7 @@ void IRac::teco(IRTecoAc *ac,
|
||||
// No Horizontal swing setting available.
|
||||
// No Quiet setting available.
|
||||
// No Turbo setting available.
|
||||
// No Light setting available.
|
||||
ac->setLight(light);
|
||||
// No Filter setting available.
|
||||
// No Clean setting available.
|
||||
// No Beep setting available.
|
||||
@@ -1014,6 +1040,14 @@ bool IRac::sendAc(const decode_type_t vendor, const int16_t model,
|
||||
if (mode == stdAc::opmode_t::kOff) on = false;
|
||||
// Per vendor settings & setup.
|
||||
switch (vendor) {
|
||||
#if SEND_AMCOR
|
||||
case AMCOR:
|
||||
{
|
||||
IRAmcorAc ac(_pin, _inverted, _modulation);
|
||||
amcor(&ac, on, mode, degC, fan);
|
||||
break;
|
||||
}
|
||||
#endif // SEND_AMCOR
|
||||
#if SEND_ARGO
|
||||
case ARGO:
|
||||
{
|
||||
@@ -1247,7 +1281,7 @@ bool IRac::sendAc(const decode_type_t vendor, const int16_t model,
|
||||
{
|
||||
IRTecoAc ac(_pin, _inverted, _modulation);
|
||||
ac.begin();
|
||||
teco(&ac, on, mode, degC, fan, swingv, sleep);
|
||||
teco(&ac, on, mode, degC, fan, swingv, light, sleep);
|
||||
break;
|
||||
}
|
||||
#endif // SEND_TECO
|
||||
@@ -1421,11 +1455,20 @@ stdAc::swingh_t IRac::strToSwingH(const char *str,
|
||||
|
||||
// Assumes str is the model or an integer >= 1.
|
||||
int16_t IRac::strToModel(const char *str, const int16_t def) {
|
||||
// Gree
|
||||
if (!strcasecmp(str, "YAW1F")) {
|
||||
return gree_ac_remote_model_t::YAW1F;
|
||||
} else if (!strcasecmp(str, "YBOFB")) {
|
||||
return gree_ac_remote_model_t::YBOFB;
|
||||
// Fujitsu A/C models
|
||||
if (!strcasecmp(str, "ARRAH2E")) {
|
||||
} else if (!strcasecmp(str, "ARRAH2E")) {
|
||||
return fujitsu_ac_remote_model_t::ARRAH2E;
|
||||
} else if (!strcasecmp(str, "ARDB1")) {
|
||||
return fujitsu_ac_remote_model_t::ARDB1;
|
||||
} else if (!strcasecmp(str, "ARREB1E")) {
|
||||
return fujitsu_ac_remote_model_t::ARREB1E;
|
||||
} else if (!strcasecmp(str, "ARJW2")) {
|
||||
return fujitsu_ac_remote_model_t::ARJW2;
|
||||
// Panasonic A/C families
|
||||
} else if (!strcasecmp(str, "LKE") || !strcasecmp(str, "PANASONICLKE")) {
|
||||
return panasonic_ac_remote_model_t::kPanasonicLke;
|
||||
@@ -1545,7 +1588,7 @@ String IRac::swinghToString(const stdAc::swingh_t swingh) {
|
||||
case stdAc::swingh_t::kRightMax:
|
||||
return F("rightmax");
|
||||
case stdAc::swingh_t::kWide:
|
||||
return F("leftright");
|
||||
return F("wide");
|
||||
default:
|
||||
return F("unknown");
|
||||
}
|
||||
@@ -1559,6 +1602,13 @@ namespace IRAcUtils {
|
||||
// A string with the human description of the A/C message. "" if we can't.
|
||||
String resultAcToString(const decode_results * const result) {
|
||||
switch (result->decode_type) {
|
||||
#if DECODE_AMCOR
|
||||
case decode_type_t::AMCOR: {
|
||||
IRAmcorAc ac(0);
|
||||
ac.setRaw(result->state);
|
||||
return ac.toString();
|
||||
}
|
||||
#endif // DECODE_AMCOR
|
||||
#if DECODE_ARGO
|
||||
case decode_type_t::ARGO: {
|
||||
IRArgoAC ac(0);
|
||||
@@ -1788,6 +1838,14 @@ namespace IRAcUtils {
|
||||
const stdAc::state_t *prev) {
|
||||
if (decode == NULL || result == NULL) return false; // Safety check.
|
||||
switch (decode->decode_type) {
|
||||
#if DECODE_AMCOR
|
||||
case decode_type_t::AMCOR: {
|
||||
IRAmcorAc ac(kGpioUnused);
|
||||
ac.setRaw(decode->state);
|
||||
*result = ac.toCommon();
|
||||
break;
|
||||
}
|
||||
#endif // DECODE_AMCOR
|
||||
#if DECODE_ARGO
|
||||
case decode_type_t::ARGO: {
|
||||
IRArgoAC ac(kGpioUnused);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
#include "IRremoteESP8266.h"
|
||||
#include "ir_Amcor.h"
|
||||
#include "ir_Argo.h"
|
||||
#include "ir_Coolix.h"
|
||||
#include "ir_Daikin.h"
|
||||
@@ -73,6 +74,11 @@ class IRac {
|
||||
uint16_t _pin;
|
||||
bool _inverted;
|
||||
bool _modulation;
|
||||
#if SEND_AMCOR
|
||||
void amcor(IRAmcorAc *ac,
|
||||
const bool on, const stdAc::opmode_t mode, const float degrees,
|
||||
const stdAc::fanspeed_t fan);
|
||||
#endif // SEND_AMCOR
|
||||
#if SEND_ARGO
|
||||
void argo(IRArgoAC *ac,
|
||||
const bool on, const stdAc::opmode_t mode, const float degrees,
|
||||
@@ -260,7 +266,7 @@ void electra(IRElectraAc *ac,
|
||||
void teco(IRTecoAc *ac,
|
||||
const bool on, const stdAc::opmode_t mode, const float degrees,
|
||||
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
|
||||
const int16_t sleep = -1);
|
||||
const bool light, const int16_t sleep = -1);
|
||||
#endif // SEND_TECO
|
||||
#if SEND_TOSHIBA_AC
|
||||
void toshiba(IRToshibaAC *ac,
|
||||
|
||||
@@ -49,6 +49,8 @@ namespace stdAc {
|
||||
kHeat = 2,
|
||||
kDry = 3,
|
||||
kFan = 4,
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastOpmodeEnum = kFan,
|
||||
};
|
||||
|
||||
enum class fanspeed_t {
|
||||
@@ -58,6 +60,8 @@ namespace stdAc {
|
||||
kMedium = 3,
|
||||
kHigh = 4,
|
||||
kMax = 5,
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastFanspeedEnum = kMax,
|
||||
};
|
||||
|
||||
enum class swingv_t {
|
||||
@@ -68,6 +72,8 @@ namespace stdAc {
|
||||
kMiddle = 3,
|
||||
kLow = 4,
|
||||
kLowest = 5,
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastSwingvEnum = kLowest,
|
||||
};
|
||||
|
||||
enum class swingh_t {
|
||||
@@ -78,7 +84,9 @@ namespace stdAc {
|
||||
kMiddle = 3,
|
||||
kRight = 4,
|
||||
kRightMax = 5,
|
||||
kWide = 6,
|
||||
kWide = 6, // a.k.a. left & right at the same time.
|
||||
// Add new entries before this one, and update it to point to the last entry
|
||||
kLastSwinghEnum = kWide,
|
||||
};
|
||||
|
||||
// Structure to hold a common A/C state.
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// Brand: Amcor, Model: TAC-495 remote
|
||||
// Brand: Amcor, Model: TAC-444 remote
|
||||
|
||||
#include "ir_Amcor.h"
|
||||
#include <algorithm>
|
||||
#include "IRrecv.h"
|
||||
#include "IRsend.h"
|
||||
#include "IRutils.h"
|
||||
@@ -22,6 +24,11 @@ const uint16_t kAmcorFooterMark = 1900;
|
||||
const uint16_t kAmcorGap = 34300;
|
||||
const uint8_t kAmcorTolerance = 40;
|
||||
|
||||
using irutils::addBoolToString;
|
||||
using irutils::addModeToString;
|
||||
using irutils::addFanToString;
|
||||
using irutils::addTempToString;
|
||||
|
||||
#if SEND_AMCOR
|
||||
// Send a Amcor HVAC formatted message.
|
||||
//
|
||||
@@ -30,7 +37,7 @@ const uint8_t kAmcorTolerance = 40;
|
||||
// nbytes: The byte size of the array being sent. typically kAmcorStateLength.
|
||||
// repeat: The number of times the message is to be repeated.
|
||||
//
|
||||
// Status: Alpha / Needs testing.
|
||||
// Status: STABLE / Reported as working.
|
||||
//
|
||||
void IRsend::sendAmcor(const unsigned char data[], const uint16_t nbytes,
|
||||
const uint16_t repeat) {
|
||||
@@ -52,7 +59,7 @@ void IRsend::sendAmcor(const unsigned char data[], const uint16_t nbytes,
|
||||
// Returns:
|
||||
// boolean: True if it can decode it, false if it can't.
|
||||
//
|
||||
// Status: BETA / Seems to be working.
|
||||
// Status: STABLE / Reported as working.
|
||||
//
|
||||
bool IRrecv::decodeAmcor(decode_results *results, uint16_t nbits,
|
||||
bool strict) {
|
||||
@@ -75,6 +82,10 @@ bool IRrecv::decodeAmcor(decode_results *results, uint16_t nbits,
|
||||
if (!used) return false;
|
||||
offset += used;
|
||||
|
||||
if (strict) {
|
||||
if (!IRAmcorAc::validChecksum(results->state)) return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
results->bits = nbits;
|
||||
results->decode_type = AMCOR;
|
||||
@@ -84,3 +95,232 @@ bool IRrecv::decodeAmcor(decode_results *results, uint16_t nbits,
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
IRAmcorAc::IRAmcorAc(const uint16_t pin, const bool inverted,
|
||||
const bool use_modulation)
|
||||
: _irsend(pin, inverted, use_modulation) { this->stateReset(); }
|
||||
|
||||
void IRAmcorAc::begin(void) { _irsend.begin(); }
|
||||
|
||||
#if SEND_AMCOR
|
||||
void IRAmcorAc::send(const uint16_t repeat) {
|
||||
this->checksum(); // Create valid checksum before sending
|
||||
_irsend.sendAmcor(remote_state, kAmcorStateLength, repeat);
|
||||
}
|
||||
#endif // SEND_AMCOR
|
||||
|
||||
uint8_t IRAmcorAc::calcChecksum(const uint8_t state[], const uint16_t length) {
|
||||
return irutils::sumNibbles(state, length - 1);
|
||||
}
|
||||
|
||||
bool IRAmcorAc::validChecksum(const uint8_t state[], const uint16_t length) {
|
||||
return (state[length - 1] == IRAmcorAc::calcChecksum(state, length));
|
||||
}
|
||||
|
||||
void IRAmcorAc::checksum(void) {
|
||||
remote_state[kAmcorChecksumByte] = IRAmcorAc::calcChecksum(remote_state,
|
||||
kAmcorStateLength);
|
||||
}
|
||||
|
||||
void IRAmcorAc::stateReset(void) {
|
||||
for (uint8_t i = 1; i < kAmcorStateLength; i++) remote_state[i] = 0x0;
|
||||
remote_state[0] = 0x01;
|
||||
setFan(kAmcorFanAuto);
|
||||
setMode(kAmcorAuto);
|
||||
setTemp(25); // 25C
|
||||
}
|
||||
|
||||
uint8_t* IRAmcorAc::getRaw(void) {
|
||||
this->checksum(); // Ensure correct bit array before returning
|
||||
return remote_state;
|
||||
}
|
||||
|
||||
void IRAmcorAc::setRaw(const uint8_t state[]) {
|
||||
for (uint8_t i = 0; i < kAmcorStateLength; i++) remote_state[i] = state[i];
|
||||
}
|
||||
|
||||
void IRAmcorAc::on(void) { setPower(true); }
|
||||
|
||||
void IRAmcorAc::off(void) { setPower(false); }
|
||||
|
||||
void IRAmcorAc::setPower(const bool on) {
|
||||
remote_state[kAmcorPowerByte] &= ~kAmcorPowerMask;
|
||||
remote_state[kAmcorPowerByte] |= (on ? kAmcorPowerOn : kAmcorPowerOff);
|
||||
}
|
||||
|
||||
bool IRAmcorAc::getPower(void) {
|
||||
return ((remote_state[kAmcorPowerByte] & kAmcorPowerMask) == kAmcorPowerOn);
|
||||
}
|
||||
|
||||
// Set the temp in deg C
|
||||
void IRAmcorAc::setTemp(const uint8_t degrees) {
|
||||
uint8_t temp = std::max(kAmcorMinTemp, degrees);
|
||||
temp = std::min(kAmcorMaxTemp, temp);
|
||||
|
||||
temp <<= 1;
|
||||
remote_state[kAmcorTempByte] &= ~kAmcorTempMask;
|
||||
remote_state[kAmcorTempByte] |= temp;
|
||||
}
|
||||
|
||||
uint8_t IRAmcorAc::getTemp(void) {
|
||||
return (remote_state[kAmcorTempByte] & kAmcorTempMask) >> 1;
|
||||
}
|
||||
|
||||
// Maximum Cooling or Hearing
|
||||
void IRAmcorAc::setMax(const bool on) {
|
||||
if (on) {
|
||||
switch (getMode()) {
|
||||
case kAmcorCool:
|
||||
setTemp(kAmcorMinTemp);
|
||||
break;
|
||||
case kAmcorHeat:
|
||||
setTemp(kAmcorMaxTemp);
|
||||
break;
|
||||
default: // Not allowed in all other operating modes.
|
||||
return;
|
||||
}
|
||||
remote_state[kAmcorSpecialByte] |= kAmcorMaxMask;
|
||||
} else {
|
||||
remote_state[kAmcorSpecialByte] &= ~kAmcorMaxMask;
|
||||
}
|
||||
}
|
||||
|
||||
bool IRAmcorAc::getMax(void) {
|
||||
return ((remote_state[kAmcorSpecialByte] & kAmcorMaxMask) == kAmcorMaxMask);
|
||||
}
|
||||
|
||||
// Set the speed of the fan
|
||||
void IRAmcorAc::setFan(const uint8_t speed) {
|
||||
switch (speed) {
|
||||
case kAmcorFanAuto:
|
||||
case kAmcorFanMin:
|
||||
case kAmcorFanMed:
|
||||
case kAmcorFanMax:
|
||||
remote_state[kAmcorModeFanByte] &= ~kAmcorFanMask;
|
||||
remote_state[kAmcorModeFanByte] |= speed << 4;
|
||||
break;
|
||||
default:
|
||||
setFan(kAmcorFanAuto);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t IRAmcorAc::getFan(void) {
|
||||
return (remote_state[kAmcorModeFanByte] & kAmcorFanMask) >> 4;
|
||||
}
|
||||
|
||||
uint8_t IRAmcorAc::getMode(void) {
|
||||
return remote_state[kAmcorModeFanByte] & kAmcorModeMask;
|
||||
}
|
||||
|
||||
void IRAmcorAc::setMode(const uint8_t mode) {
|
||||
remote_state[kAmcorSpecialByte] &= ~kAmcorVentMask; // Clear the vent setting
|
||||
switch (mode) {
|
||||
case kAmcorFan:
|
||||
remote_state[kAmcorSpecialByte] |= kAmcorVentMask; // Set the vent option
|
||||
// FALL-THRU
|
||||
case kAmcorCool:
|
||||
case kAmcorHeat:
|
||||
case kAmcorDry:
|
||||
case kAmcorAuto:
|
||||
// Mask out bits
|
||||
remote_state[kAmcorModeFanByte] &= ~kAmcorModeMask;
|
||||
// Set the mode at bit positions
|
||||
remote_state[kAmcorModeFanByte] |= mode;
|
||||
return;
|
||||
default:
|
||||
this->setMode(kAmcorAuto);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a standard A/C mode into its native mode.
|
||||
uint8_t IRAmcorAc::convertMode(const stdAc::opmode_t mode) {
|
||||
switch (mode) {
|
||||
case stdAc::opmode_t::kCool:
|
||||
return kAmcorCool;
|
||||
case stdAc::opmode_t::kHeat:
|
||||
return kAmcorHeat;
|
||||
case stdAc::opmode_t::kDry:
|
||||
return kAmcorDry;
|
||||
case stdAc::opmode_t::kFan:
|
||||
return kAmcorFan;
|
||||
default:
|
||||
return kAmcorAuto;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a standard A/C Fan speed into its native fan speed.
|
||||
uint8_t IRAmcorAc::convertFan(const stdAc::fanspeed_t speed) {
|
||||
switch (speed) {
|
||||
case stdAc::fanspeed_t::kMin:
|
||||
case stdAc::fanspeed_t::kLow:
|
||||
return kAmcorFanMin;
|
||||
case stdAc::fanspeed_t::kMedium:
|
||||
return kAmcorFanMed;
|
||||
case stdAc::fanspeed_t::kHigh:
|
||||
case stdAc::fanspeed_t::kMax:
|
||||
return kAmcorFanMax;
|
||||
default:
|
||||
return kAmcorFanAuto;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a native mode to it's common equivalent.
|
||||
stdAc::opmode_t IRAmcorAc::toCommonMode(const uint8_t mode) {
|
||||
switch (mode) {
|
||||
case kAmcorCool: return stdAc::opmode_t::kCool;
|
||||
case kAmcorHeat: return stdAc::opmode_t::kHeat;
|
||||
case kAmcorDry: return stdAc::opmode_t::kDry;
|
||||
case kAmcorFan: return stdAc::opmode_t::kFan;
|
||||
default: return stdAc::opmode_t::kAuto;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a native fan speed to it's common equivalent.
|
||||
stdAc::fanspeed_t IRAmcorAc::toCommonFanSpeed(const uint8_t speed) {
|
||||
switch (speed) {
|
||||
case kAmcorFanMax: return stdAc::fanspeed_t::kMax;
|
||||
case kAmcorFanMed: return stdAc::fanspeed_t::kMedium;
|
||||
case kAmcorFanMin: return stdAc::fanspeed_t::kMin;
|
||||
default: return stdAc::fanspeed_t::kAuto;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the A/C state to it's common equivalent.
|
||||
stdAc::state_t IRAmcorAc::toCommon(void) {
|
||||
stdAc::state_t result;
|
||||
result.protocol = decode_type_t::AMCOR;
|
||||
result.power = this->getPower();
|
||||
result.mode = this->toCommonMode(this->getMode());
|
||||
result.celsius = true;
|
||||
result.degrees = this->getTemp();
|
||||
result.fanspeed = this->toCommonFanSpeed(this->getFan());
|
||||
// Not supported.
|
||||
result.model = -1;
|
||||
result.turbo = false;
|
||||
result.swingv = stdAc::swingv_t::kOff;
|
||||
result.swingh = stdAc::swingh_t::kOff;
|
||||
result.light = false;
|
||||
result.filter = false;
|
||||
result.econo = false;
|
||||
result.quiet = false;
|
||||
result.clean = false;
|
||||
result.beep = false;
|
||||
result.sleep = -1;
|
||||
result.clock = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert the internal state into a human readable string.
|
||||
String IRAmcorAc::toString() {
|
||||
String result = "";
|
||||
result.reserve(70); // Reserve some heap for the string to reduce fragging.
|
||||
result += addBoolToString(getPower(), F("Power"), false);
|
||||
result += addModeToString(getMode(), kAmcorAuto, kAmcorCool,
|
||||
kAmcorHeat, kAmcorDry, kAmcorFan);
|
||||
result += addFanToString(getFan(), kAmcorFanMax, kAmcorFanMin,
|
||||
kAmcorFanAuto, kAmcorFanAuto,
|
||||
kAmcorFanMed);
|
||||
result += addTempToString(getTemp());
|
||||
result += addBoolToString(getMax(), F("Max"));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
// Amcor A/C
|
||||
//
|
||||
// Copyright 2019 David Conran
|
||||
|
||||
#ifndef IR_AMCOR_H_
|
||||
#define IR_AMCOR_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
|
||||
|
||||
// Supports:
|
||||
// Brand: Amcor, Model: ADR-853H A/C
|
||||
// Brand: Amcor, Model: TAC-495 remote
|
||||
// Brand: Amcor, Model: TAC-444 remote
|
||||
// Ref:
|
||||
// https://github.com/crankyoldgit/IRremoteESP8266/issues/834
|
||||
// Kudos:
|
||||
// ldellus: For the breakdown and mapping of the bit values.
|
||||
|
||||
// Constants
|
||||
|
||||
|
||||
// state[1]
|
||||
const uint8_t kAmcorModeFanByte = 1;
|
||||
// Fan Control
|
||||
const uint8_t kAmcorFanMin = 0b001;
|
||||
const uint8_t kAmcorFanMed = 0b010;
|
||||
const uint8_t kAmcorFanMax = 0b011;
|
||||
const uint8_t kAmcorFanAuto = 0b100;
|
||||
const uint8_t kAmcorFanMask = 0b01110000;
|
||||
// Modes
|
||||
const uint8_t kAmcorCool = 0b001;
|
||||
const uint8_t kAmcorHeat = 0b010;
|
||||
const uint8_t kAmcorFan = 0b011; // Aka "Vent"
|
||||
const uint8_t kAmcorDry = 0b100;
|
||||
const uint8_t kAmcorAuto = 0b101;
|
||||
const uint8_t kAmcorModeMask = 0b00000111;
|
||||
|
||||
// state[2]
|
||||
const uint8_t kAmcorTempByte = 2;
|
||||
// Temperature
|
||||
const uint8_t kAmcorMinTemp = 12; // Celsius
|
||||
const uint8_t kAmcorMaxTemp = 32; // Celsius
|
||||
const uint8_t kAmcorTempMask = 0b01111110;
|
||||
|
||||
// state[5]
|
||||
// Power
|
||||
const uint8_t kAmcorPowerByte = 5;
|
||||
const uint8_t kAmcorPowerMask = 0b11110000;
|
||||
const uint8_t kAmcorPowerOn = 0b00110000; // 0x30
|
||||
const uint8_t kAmcorPowerOff = 0b11000000; // 0xC0
|
||||
|
||||
// state[6]
|
||||
const uint8_t kAmcorSpecialByte = 6;
|
||||
// Max Mode (aka "Lo" in Cool and "Hi" in Heat)
|
||||
const uint8_t kAmcorMaxMask = 0b00000011; // 0x03
|
||||
// "Vent" Mode
|
||||
const uint8_t kAmcorVentMask = 0b11000000; // 0xC0
|
||||
|
||||
// state[7]
|
||||
// Checksum byte.
|
||||
const uint8_t kAmcorChecksumByte = kAmcorStateLength - 1;
|
||||
|
||||
// Classes
|
||||
class IRAmcorAc {
|
||||
public:
|
||||
explicit IRAmcorAc(const uint16_t pin, const bool inverted = false,
|
||||
const bool use_modulation = true);
|
||||
|
||||
void stateReset();
|
||||
#if SEND_AMCOR
|
||||
void send(const uint16_t repeat = kAmcorDefaultRepeat);
|
||||
uint8_t calibrate(void) { return _irsend.calibrate(); }
|
||||
#endif // SEND_AMCOR
|
||||
void begin();
|
||||
static uint8_t calcChecksum(const uint8_t state[],
|
||||
const uint16_t length = kAmcorStateLength);
|
||||
static bool validChecksum(const uint8_t state[],
|
||||
const uint16_t length = kAmcorStateLength);
|
||||
void setPower(const bool state);
|
||||
bool getPower();
|
||||
void on();
|
||||
void off();
|
||||
void setTemp(const uint8_t temp);
|
||||
uint8_t getTemp();
|
||||
void setMax(const bool on);
|
||||
bool getMax(void);
|
||||
void setFan(const uint8_t speed);
|
||||
uint8_t getFan();
|
||||
void setMode(const uint8_t mode);
|
||||
uint8_t getMode();
|
||||
uint8_t* getRaw();
|
||||
void setRaw(const uint8_t state[]);
|
||||
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();
|
||||
#ifndef UNIT_TEST
|
||||
|
||||
private:
|
||||
IRsend _irsend;
|
||||
#else
|
||||
IRsendTest _irsend;
|
||||
#endif
|
||||
uint8_t remote_state[kAmcorStateLength]; // The state of the IR remote.
|
||||
void checksum(void);
|
||||
};
|
||||
#endif // IR_AMCOR_H_
|
||||
@@ -267,9 +267,6 @@ bool IRFujitsuAC::setRaw(const uint8_t newState[], const uint16_t length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set the requested power state of the A/C to off.
|
||||
void IRFujitsuAC::off(void) { this->setCmd(kFujitsuAcCmdTurnOff); }
|
||||
|
||||
void IRFujitsuAC::stepHoriz(void) { this->setCmd(kFujitsuAcCmdStepHoriz); }
|
||||
|
||||
void IRFujitsuAC::toggleSwingHoriz(const bool update) {
|
||||
@@ -336,6 +333,17 @@ uint8_t IRFujitsuAC::getCmd(const bool raw) {
|
||||
return _cmd;
|
||||
}
|
||||
|
||||
// Set the requested power state of the A/C.
|
||||
void IRFujitsuAC::setPower(const bool on) {
|
||||
this->setCmd(on ? kFujitsuAcCmdTurnOn : kFujitsuAcCmdTurnOff);
|
||||
}
|
||||
|
||||
// Set the requested power state of the A/C to off.
|
||||
void IRFujitsuAC::off(void) { this->setPower(false); }
|
||||
|
||||
// Set the requested power state of the A/C to on.
|
||||
void IRFujitsuAC::on(void) { this->setPower(true); }
|
||||
|
||||
bool IRFujitsuAC::getPower(void) { return _cmd != kFujitsuAcCmdTurnOff; }
|
||||
|
||||
void IRFujitsuAC::setOutsideQuiet(const bool on) {
|
||||
|
||||
@@ -104,7 +104,6 @@ class IRFujitsuAC {
|
||||
uint8_t calibrate(void) { return _irsend.calibrate(); }
|
||||
#endif // SEND_FUJITSU_AC
|
||||
void begin(void);
|
||||
void off(void);
|
||||
void stepHoriz(void);
|
||||
void toggleSwingHoriz(const bool update = true);
|
||||
void stepVert(void);
|
||||
@@ -123,6 +122,9 @@ class IRFujitsuAC {
|
||||
bool setRaw(const uint8_t newState[], const uint16_t length);
|
||||
uint8_t getStateLength(void);
|
||||
static bool validChecksum(uint8_t* state, const uint16_t length);
|
||||
void setPower(const bool on);
|
||||
void off(void);
|
||||
void on(void);
|
||||
bool getPower(void);
|
||||
void setOutsideQuiet(const bool on);
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ using irutils::addLabeledString;
|
||||
using irutils::addModeToString;
|
||||
using irutils::addFanToString;
|
||||
using irutils::addTempToString;
|
||||
using irutils::minsToString;
|
||||
|
||||
#if SEND_GREE
|
||||
// Send a Gree Heat Pump message.
|
||||
@@ -222,12 +223,13 @@ void IRGreeAC::setTemp(const uint8_t temp) {
|
||||
uint8_t new_temp = std::max((uint8_t)kGreeMinTemp, temp);
|
||||
new_temp = std::min((uint8_t)kGreeMaxTemp, new_temp);
|
||||
if (getMode() == kGreeAuto) new_temp = 25;
|
||||
remote_state[1] = (remote_state[1] & 0xF0U) | (new_temp - kGreeMinTemp);
|
||||
remote_state[1] = (remote_state[1] & ~kGreeTempMask) |
|
||||
(new_temp - kGreeMinTemp);
|
||||
}
|
||||
|
||||
// Return the set temp. in deg C
|
||||
uint8_t IRGreeAC::getTemp(void) {
|
||||
return ((remote_state[1] & 0xFU) + kGreeMinTemp);
|
||||
return ((remote_state[1] & kGreeTempMask) + kGreeMinTemp);
|
||||
}
|
||||
|
||||
// Set the speed of the fan, 0-3, 0 is auto, 1-3 is the speed
|
||||
@@ -359,6 +361,44 @@ uint8_t IRGreeAC::getSwingVerticalPosition(void) {
|
||||
return remote_state[4] & kGreeSwingPosMask;
|
||||
}
|
||||
|
||||
void IRGreeAC::setTimerEnabled(const bool on) {
|
||||
if (on)
|
||||
remote_state[1] |= kGreeTimerEnabledBit;
|
||||
else
|
||||
remote_state[1] &= ~kGreeTimerEnabledBit;
|
||||
}
|
||||
|
||||
bool IRGreeAC::getTimerEnabled(void) {
|
||||
return remote_state[1] & kGreeTimerEnabledBit;
|
||||
}
|
||||
|
||||
// Returns the number of minutes the timer is set for.
|
||||
uint16_t IRGreeAC::getTimer(void) {
|
||||
uint16_t hrs = irutils::bcdToUint8(
|
||||
(remote_state[2] & kGreeTimerHoursMask) |
|
||||
((remote_state[1] & kGreeTimerTensHrMask) >> 1));
|
||||
return hrs * 60 + ((remote_state[1] & kGreeTimerHalfHrBit) ? 30 : 0);
|
||||
}
|
||||
|
||||
// Set the A/C's timer to turn off in X many minutes.
|
||||
// Stores time internally in 30 min units.
|
||||
// e.g. 5 mins means 0 (& Off), 95 mins is 90 mins (& On). Max is 24 hours.
|
||||
//
|
||||
// Args:
|
||||
// minutes: The number of minutes the timer should be set for.
|
||||
void IRGreeAC::setTimer(const uint16_t minutes) {
|
||||
// Clear the previous settings.
|
||||
remote_state[1] &= ~kGreeTimer1Mask;
|
||||
remote_state[2] &= ~kGreeTimerHoursMask;
|
||||
uint16_t mins = std::min(kGreeTimerMax, minutes); // Bounds check.
|
||||
setTimerEnabled(mins >= 30); // Timer is enabled when >= 30 mins.
|
||||
uint8_t hours = mins / 60;
|
||||
uint8_t halfhour = (mins % 60) < 30 ? 0 : 1;
|
||||
// Set the "tens" digit of hours & the half hour.
|
||||
remote_state[1] |= (((hours / 10) << 1) | halfhour) << 4;
|
||||
// Set the "units" digit of hours.
|
||||
remote_state[2] |= (hours % 10);
|
||||
}
|
||||
|
||||
// Convert a standard A/C mode into its native mode.
|
||||
uint8_t IRGreeAC::convertMode(const stdAc::opmode_t mode) {
|
||||
@@ -504,6 +544,11 @@ String IRGreeAC::toString(void) {
|
||||
result += F(" (Auto)");
|
||||
break;
|
||||
}
|
||||
result += F(", Timer: ");
|
||||
if (getTimerEnabled())
|
||||
result += minsToString(getTimer());
|
||||
else
|
||||
result += F("Off");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,40 +36,48 @@ const uint8_t kGreeFan = 3;
|
||||
const uint8_t kGreeHeat = 4;
|
||||
|
||||
// Byte 0
|
||||
const uint8_t kGreeModeMask = 0b00000111;
|
||||
const uint8_t kGreePower1Mask = 0b00001000;
|
||||
const uint8_t kGreeFanMask = 0b00110000;
|
||||
const uint8_t kGreeSwingAutoMask = 0b01000000;
|
||||
const uint8_t kGreeSleepMask = 0b10000000;
|
||||
// Byte 2
|
||||
const uint8_t kGreeTurboMask = 0b00010000;
|
||||
const uint8_t kGreeLightMask = 0b00100000;
|
||||
const uint8_t kGreePower2Mask = 0b01000000; // This might not be used. See #814
|
||||
const uint8_t kGreeXfanMask = 0b10000000;
|
||||
// Byte 4
|
||||
const uint8_t kGreeSwingPosMask = 0b00001111;
|
||||
// byte 5
|
||||
const uint8_t kGreeIFeelMask = 0b00000100;
|
||||
const uint8_t kGreeWiFiMask = 0b01000000;
|
||||
|
||||
|
||||
const uint8_t kGreeMinTemp = 16; // Celsius
|
||||
const uint8_t kGreeMaxTemp = 30; // Celsius
|
||||
const uint8_t kGreeModeMask = 0b00000111;
|
||||
const uint8_t kGreePower1Mask = 0b00001000;
|
||||
const uint8_t kGreeFanMask = 0b00110000;
|
||||
const uint8_t kGreeFanAuto = 0;
|
||||
const uint8_t kGreeFanMin = 1;
|
||||
const uint8_t kGreeFanMed = 2;
|
||||
const uint8_t kGreeFanMax = 3;
|
||||
const uint8_t kGreeSwingAutoMask = 0b01000000;
|
||||
const uint8_t kGreeSleepMask = 0b10000000;
|
||||
// Byte 1
|
||||
const uint8_t kGreeTempMask = 0b00001111;
|
||||
const uint8_t kGreeMinTemp = 16; // Celsius
|
||||
const uint8_t kGreeMaxTemp = 30; // Celsius
|
||||
const uint8_t kGreeTimerEnabledBit = 0b10000000;
|
||||
const uint8_t kGreeTimerHalfHrBit = 0b00010000;
|
||||
const uint8_t kGreeTimerTensHrMask = 0b01100000;
|
||||
const uint8_t kGreeTimer1Mask = kGreeTimerTensHrMask | kGreeTimerHalfHrBit;
|
||||
const uint16_t kGreeTimerMax = 24 * 60;
|
||||
|
||||
const uint8_t kGreeSwingLastPos = 0b00000000;
|
||||
const uint8_t kGreeSwingAuto = 0b00000001;
|
||||
const uint8_t kGreeSwingUp = 0b00000010;
|
||||
const uint8_t kGreeSwingMiddleUp = 0b00000011;
|
||||
const uint8_t kGreeSwingMiddle = 0b00000100;
|
||||
// Byte 2
|
||||
const uint8_t kGreeTimerHoursMask = 0b00001111;
|
||||
const uint8_t kGreeTurboMask = 0b00010000;
|
||||
const uint8_t kGreeLightMask = 0b00100000;
|
||||
// This might not be used. See #814
|
||||
const uint8_t kGreePower2Mask = 0b01000000;
|
||||
const uint8_t kGreeXfanMask = 0b10000000;
|
||||
// Byte 4
|
||||
const uint8_t kGreeSwingPosMask = 0b00001111;
|
||||
// byte 5
|
||||
const uint8_t kGreeIFeelMask = 0b00000100;
|
||||
const uint8_t kGreeWiFiMask = 0b01000000;
|
||||
|
||||
const uint8_t kGreeSwingLastPos = 0b00000000;
|
||||
const uint8_t kGreeSwingAuto = 0b00000001;
|
||||
const uint8_t kGreeSwingUp = 0b00000010;
|
||||
const uint8_t kGreeSwingMiddleUp = 0b00000011;
|
||||
const uint8_t kGreeSwingMiddle = 0b00000100;
|
||||
const uint8_t kGreeSwingMiddleDown = 0b00000101;
|
||||
const uint8_t kGreeSwingDown = 0b00000110;
|
||||
const uint8_t kGreeSwingDownAuto = 0b00000111;
|
||||
const uint8_t kGreeSwingDown = 0b00000110;
|
||||
const uint8_t kGreeSwingDownAuto = 0b00000111;
|
||||
const uint8_t kGreeSwingMiddleAuto = 0b00001001;
|
||||
const uint8_t kGreeSwingUpAuto = 0b00001011;
|
||||
const uint8_t kGreeSwingUpAuto = 0b00001011;
|
||||
|
||||
// Legacy defines.
|
||||
#define GREE_AUTO kGreeAuto
|
||||
@@ -132,6 +140,8 @@ class IRGreeAC {
|
||||
void setSwingVertical(const bool automatic, const uint8_t position);
|
||||
bool getSwingVerticalAuto(void);
|
||||
uint8_t getSwingVerticalPosition(void);
|
||||
uint16_t getTimer(void);
|
||||
void setTimer(const uint16_t minutes);
|
||||
uint8_t convertMode(const stdAc::opmode_t mode);
|
||||
uint8_t convertFan(const stdAc::fanspeed_t speed);
|
||||
uint8_t convertSwingV(const stdAc::swingv_t swingv);
|
||||
@@ -156,6 +166,8 @@ class IRGreeAC {
|
||||
gree_ac_remote_model_t _model;
|
||||
void checksum(const uint16_t length = kGreeStateLength);
|
||||
void fixup(void);
|
||||
void setTimerEnabled(const bool on);
|
||||
bool getTimerEnabled(void);
|
||||
};
|
||||
|
||||
#endif // IR_GREE_H_
|
||||
|
||||
@@ -490,16 +490,10 @@ bool IRrecv::decodeKelvinator(decode_results *results, uint16_t nbits,
|
||||
if (data_result.data != kKelvinatorCmdFooter) return false;
|
||||
offset += data_result.used;
|
||||
|
||||
// Interdata gap.
|
||||
if (!matchMark(results->rawbuf[offset++], kKelvinatorBitMark))
|
||||
return false;
|
||||
if (!matchSpace(results->rawbuf[offset++], kKelvinatorGapSpace))
|
||||
return false;
|
||||
|
||||
// Data (Options) (32 bits)
|
||||
// Gap + Data (Options) (32 bits)
|
||||
used = matchGeneric(results->rawbuf + offset, results->state + pos,
|
||||
results->rawlen - offset, 32,
|
||||
0, 0,
|
||||
kKelvinatorBitMark, kKelvinatorGapSpace,
|
||||
kKelvinatorBitMark, kKelvinatorOneSpace,
|
||||
kKelvinatorBitMark, kKelvinatorZeroSpace,
|
||||
kKelvinatorBitMark, kKelvinatorGapSpace * 2,
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
#include <stdint.h>
|
||||
#include "IRremoteESP8266.h"
|
||||
|
||||
// Supports:
|
||||
// Brand: Yamaha, Model: RAV561 remote
|
||||
// Brand: Yamaha, Model: RXV585B A/V Receiver
|
||||
|
||||
// Constants
|
||||
// Ref:
|
||||
// http://www.sbprojects.com/knowledge/ir/nec.php
|
||||
|
||||
@@ -64,19 +64,18 @@ uint64_t IRTecoAc::getRaw(void) { return remote_state; }
|
||||
|
||||
void IRTecoAc::setRaw(const uint64_t new_code) { remote_state = new_code; }
|
||||
|
||||
void IRTecoAc::on(void) { remote_state |= kTecoPower; }
|
||||
void IRTecoAc::on(void) { setPower(true); }
|
||||
|
||||
void IRTecoAc::off(void) { remote_state &= ~kTecoPower; }
|
||||
void IRTecoAc::off(void) { setPower(false); }
|
||||
|
||||
void IRTecoAc::setPower(const bool on) {
|
||||
if (on)
|
||||
this->on();
|
||||
remote_state |= kTecoPower;
|
||||
else
|
||||
this->off();
|
||||
remote_state &= ~kTecoPower;
|
||||
}
|
||||
|
||||
bool IRTecoAc::getPower(void) {
|
||||
return (remote_state & kTecoPower) == kTecoPower; }
|
||||
bool IRTecoAc::getPower(void) { return remote_state & kTecoPower; }
|
||||
|
||||
void IRTecoAc::setTemp(const uint8_t temp) {
|
||||
uint8_t newtemp = temp;
|
||||
@@ -146,6 +145,33 @@ void IRTecoAc::setSleep(const bool on) {
|
||||
|
||||
bool IRTecoAc::getSleep(void) { return remote_state & kTecoSleep; }
|
||||
|
||||
bool IRTecoAc::getLight(void) { return remote_state & kTecoLight; }
|
||||
|
||||
void IRTecoAc::setLight(const bool on) {
|
||||
if (on)
|
||||
remote_state |= kTecoLight;
|
||||
else
|
||||
remote_state &= ~kTecoLight;
|
||||
}
|
||||
|
||||
bool IRTecoAc::getHumid(void) { return remote_state & kTecoHumid; }
|
||||
|
||||
void IRTecoAc::setHumid(const bool on) {
|
||||
if (on)
|
||||
remote_state |= kTecoHumid;
|
||||
else
|
||||
remote_state &= ~kTecoHumid;
|
||||
}
|
||||
|
||||
bool IRTecoAc::getSave(void) { return remote_state & kTecoSave; }
|
||||
|
||||
void IRTecoAc::setSave(const bool on) {
|
||||
if (on)
|
||||
remote_state |= kTecoSave;
|
||||
else
|
||||
remote_state &= ~kTecoSave;
|
||||
}
|
||||
|
||||
// Convert a standard A/C mode into its native mode.
|
||||
uint8_t IRTecoAc::convertMode(const stdAc::opmode_t mode) {
|
||||
switch (mode) {
|
||||
@@ -212,10 +238,10 @@ stdAc::state_t IRTecoAc::toCommon(void) {
|
||||
result.swingv = this->getSwing() ? stdAc::swingv_t::kAuto :
|
||||
stdAc::swingv_t::kOff;
|
||||
result.sleep = this->getSleep() ? 0 : -1;
|
||||
result.light = this->getLight();
|
||||
// Not supported.
|
||||
result.swingh = stdAc::swingh_t::kOff;
|
||||
result.turbo = false;
|
||||
result.light = false;
|
||||
result.filter = false;
|
||||
result.econo = false;
|
||||
result.quiet = false;
|
||||
@@ -228,7 +254,7 @@ stdAc::state_t IRTecoAc::toCommon(void) {
|
||||
// Convert the internal state into a human readable string.
|
||||
String IRTecoAc::toString(void) {
|
||||
String result = "";
|
||||
result.reserve(80); // Reserve some heap for the string to reduce fragging.
|
||||
result.reserve(100); // Reserve some heap for the string to reduce fragging.
|
||||
result += addBoolToString(getPower(), F("Power"), false);
|
||||
result += addModeToString(getMode(), kTecoAuto, kTecoCool, kTecoHeat,
|
||||
kTecoDry, kTecoFan);
|
||||
@@ -237,6 +263,10 @@ String IRTecoAc::toString(void) {
|
||||
kTecoFanAuto, kTecoFanAuto, kTecoFanMed);
|
||||
result += addBoolToString(getSleep(), F("Sleep"));
|
||||
result += addBoolToString(getSwing(), F("Swing"));
|
||||
result += addBoolToString(getLight(), F("Light"));
|
||||
result += addBoolToString(getHumid(), F("Humid"));
|
||||
result += addBoolToString(getSave(), F("Save"));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
#include "IRsend_test.h"
|
||||
#endif
|
||||
|
||||
// Supports:
|
||||
// Brand: Alaska, Model: SAC9010QC A/C
|
||||
// Brand: Alaska, Model: SAC9010QC remote
|
||||
|
||||
// Constants. Using LSB to be able to send only 35bits.
|
||||
const uint8_t kTecoAuto = 0; // 0b000
|
||||
const uint8_t kTecoCool = 1; // 0b001
|
||||
@@ -35,6 +39,9 @@ const uint64_t kTecoTimerHalfH = 0b00000000000000000000001000000000000;
|
||||
const uint64_t kTecoTimerTenHr = 0b00000000000000000000110000000000000;
|
||||
const uint64_t kTecoTimerOn = 0b00000000000000000001000000000000000;
|
||||
const uint64_t kTecoTimerUniHr = 0b00000000000000011110000000000000000;
|
||||
const uint64_t kTecoHumid = 0b00000000000000100000000000000000000;
|
||||
const uint64_t kTecoLight = 0b00000000000001000000000000000000000;
|
||||
const uint64_t kTecoSave = 0b00000000000100000000000000000000000;
|
||||
const uint64_t kTecoReset = 0b01001010000000000000010000000000000;
|
||||
/*
|
||||
(header mark and space)
|
||||
@@ -42,8 +49,12 @@ const uint64_t kTecoReset = 0b01001010000000000000010000000000000;
|
||||
|
||||
byte 0 = Cst 0x02
|
||||
byte 1 = Cst 0x50
|
||||
b6-7 = "AIR" 0, 1, 2 (Not Implemented)
|
||||
byte 2:
|
||||
b0-3 = 0b0000
|
||||
b0 = Save
|
||||
b1 = "Tree with bubbles" / Filter?? (Not Implemented)
|
||||
b2 = Light/LED.
|
||||
b3 = Humid
|
||||
b4-7 = Timer hours (unit, not thenth)
|
||||
hours:
|
||||
0000 (0) = +0 hour
|
||||
@@ -110,12 +121,21 @@ class IRTecoAc {
|
||||
void setMode(const uint8_t mode);
|
||||
uint8_t getMode(void);
|
||||
|
||||
void setSwing(const bool state);
|
||||
void setSwing(const bool on);
|
||||
bool getSwing(void);
|
||||
|
||||
void setSleep(const bool state);
|
||||
void setSleep(const bool on);
|
||||
bool getSleep(void);
|
||||
|
||||
void setLight(const bool on);
|
||||
bool getLight(void);
|
||||
|
||||
void setHumid(const bool on);
|
||||
bool getHumid(void);
|
||||
|
||||
void setSave(const bool on);
|
||||
bool getSave(void);
|
||||
|
||||
// void setTimer(uint8_t time); // To check unit
|
||||
// uint8_t getTimer(uint8_t);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2019 David Conran
|
||||
|
||||
#include <string>
|
||||
#include "ir_Amcor.h"
|
||||
#include "ir_Argo.h"
|
||||
#include "ir_Daikin.h"
|
||||
#include "ir_Electra.h"
|
||||
@@ -33,6 +34,27 @@
|
||||
|
||||
// Tests for IRac class.
|
||||
|
||||
TEST(TestIRac, Amcor) {
|
||||
IRAmcorAc ac(0);
|
||||
IRac irac(0);
|
||||
IRrecv capture(0);
|
||||
char expected[] =
|
||||
"Power: On, Mode: 5 (AUTO), Fan: 3 (High), Temp: 19C, Max: Off";
|
||||
|
||||
ac.begin();
|
||||
irac.amcor(&ac,
|
||||
true, // Power
|
||||
stdAc::opmode_t::kAuto, // Mode
|
||||
19, // Celsius
|
||||
stdAc::fanspeed_t::kHigh); // Fan speed
|
||||
ASSERT_EQ(expected, ac.toString());
|
||||
ac._irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
|
||||
ASSERT_EQ(AMCOR, ac._irsend.capture.decode_type);
|
||||
ASSERT_EQ(kAmcorBits, ac._irsend.capture.bits);
|
||||
ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
|
||||
}
|
||||
|
||||
TEST(TestIRac, Argo) {
|
||||
IRArgoAC ac(0);
|
||||
IRac irac(0);
|
||||
@@ -390,7 +412,7 @@ TEST(TestIRac, Gree) {
|
||||
"Model: 1 (YAW1F), Power: On, Mode: 1 (COOL), Temp: 22C, "
|
||||
"Fan: 2 (Medium), Turbo: Off, IFeel: Off, WiFi: Off, XFan: On, "
|
||||
"Light: On, Sleep: On, Swing Vertical Mode: Manual, "
|
||||
"Swing Vertical Pos: 3";
|
||||
"Swing Vertical Pos: 3, Timer: Off";
|
||||
|
||||
ac.begin();
|
||||
irac.gree(&ac,
|
||||
@@ -822,7 +844,7 @@ TEST(TestIRac, Teco) {
|
||||
IRrecv capture(0);
|
||||
char expected[] =
|
||||
"Power: On, Mode: 0 (AUTO), Temp: 21C, Fan: 2 (Medium), Sleep: On, "
|
||||
"Swing: On";
|
||||
"Swing: On, Light: On, Humid: Off, Save: Off";
|
||||
|
||||
ac.begin();
|
||||
irac.teco(&ac,
|
||||
@@ -831,6 +853,7 @@ TEST(TestIRac, Teco) {
|
||||
21, // Celsius
|
||||
stdAc::fanspeed_t::kMedium, // Fan speed
|
||||
stdAc::swingv_t::kAuto, // Veritcal swing
|
||||
true, // Light
|
||||
8 * 60 + 30); // Sleep
|
||||
ASSERT_EQ(expected, ac.toString());
|
||||
ac._irsend.makeDecodeResult();
|
||||
@@ -1220,6 +1243,7 @@ TEST(TestIRac, swinghToString) {
|
||||
EXPECT_EQ("off", IRac::swinghToString(stdAc::swingh_t::kOff));
|
||||
EXPECT_EQ("left", IRac::swinghToString(stdAc::swingh_t::kLeft));
|
||||
EXPECT_EQ("auto", IRac::swinghToString(stdAc::swingh_t::kAuto));
|
||||
EXPECT_EQ("wide", IRac::swinghToString(stdAc::swingh_t::kWide));
|
||||
EXPECT_EQ("unknown", IRac::swinghToString((stdAc::swingh_t)500));
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,8 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \
|
||||
ir_Amcor.o
|
||||
|
||||
# All the IR Protocol header files.
|
||||
PROTOCOLS_H = $(USER_DIR)/ir_Argo.h \
|
||||
PROTOCOLS_H = $(USER_DIR)/ir_Amcor.h \
|
||||
$(USER_DIR)/ir_Argo.h \
|
||||
$(USER_DIR)/ir_Gree.h \
|
||||
$(USER_DIR)/ir_Magiquest.h \
|
||||
$(USER_DIR)/ir_Coolix.h \
|
||||
@@ -609,7 +610,7 @@ ir_Neoclima_test.o : ir_Neoclima_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
|
||||
ir_Neoclima_test : $(COMMON_OBJ) ir_Neoclima_test.o
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
|
||||
|
||||
ir_Amcor.o : $(USER_DIR)/ir_Amcor.cpp $(COMMON_DEPS)
|
||||
ir_Amcor.o : $(USER_DIR)/ir_Amcor.h $(USER_DIR)/ir_Amcor.cpp $(COMMON_DEPS)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Amcor.cpp
|
||||
|
||||
ir_Amcor_test.o : ir_Amcor_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2018 David Conran
|
||||
// Copyright 2019 David Conran
|
||||
|
||||
#include "IRac.h"
|
||||
#include "ir_Amcor.h"
|
||||
#include "IRrecv.h"
|
||||
#include "IRrecv_test.h"
|
||||
#include "IRsend.h"
|
||||
@@ -12,10 +13,9 @@ TEST(TestUtils, Housekeeping) {
|
||||
ASSERT_EQ("AMCOR", typeToString(decode_type_t::AMCOR));
|
||||
ASSERT_EQ(decode_type_t::AMCOR, strToDecodeType("AMCOR"));
|
||||
ASSERT_TRUE(hasACState(decode_type_t::AMCOR));
|
||||
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::AMCOR));
|
||||
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::AMCOR));
|
||||
}
|
||||
|
||||
|
||||
// Test sending typical data only.
|
||||
TEST(TestSendAmcor, SendDataOnly) {
|
||||
IRsendTest irsend(0);
|
||||
@@ -54,6 +54,7 @@ TEST(TestSendAmcor, SendDataOnly) {
|
||||
TEST(TestDecodeAmcor, SyntheticSelfDecode) {
|
||||
IRsendTest irsend(0);
|
||||
IRrecv irrecv(0);
|
||||
IRAmcorAc ac(0);
|
||||
|
||||
uint8_t expectedState[kAmcorStateLength] = {
|
||||
0x01, 0x41, 0x30, 0x00, 0x00, 0x30, 0x00, 0x0C};
|
||||
@@ -65,8 +66,11 @@ TEST(TestDecodeAmcor, SyntheticSelfDecode) {
|
||||
ASSERT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(AMCOR, irsend.capture.decode_type);
|
||||
EXPECT_EQ(kAmcorBits, irsend.capture.bits);
|
||||
|
||||
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
|
||||
ac.setRaw(irsend.capture.state);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 1 (COOL), Fan: 4 (Auto), Temp: 24C, Max: Off",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
TEST(TestDecodeAmcor, RealExample) {
|
||||
@@ -152,3 +156,196 @@ TEST(TestDecodeAmcor, RealExample) {
|
||||
EXPECT_EQ(kAmcorBits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expectedState2, irsend.capture.state, irsend.capture.bits);
|
||||
}
|
||||
|
||||
// Tests for IRAmcorAc class.
|
||||
|
||||
TEST(TestAmcorAcClass, Power) {
|
||||
IRAmcorAc ac(0);
|
||||
ac.begin();
|
||||
|
||||
ac.on();
|
||||
EXPECT_TRUE(ac.getPower());
|
||||
|
||||
ac.off();
|
||||
EXPECT_FALSE(ac.getPower());
|
||||
|
||||
ac.setPower(true);
|
||||
EXPECT_TRUE(ac.getPower());
|
||||
|
||||
ac.setPower(false);
|
||||
EXPECT_FALSE(ac.getPower());
|
||||
}
|
||||
|
||||
TEST(TestAmcorAcClass, Temperature) {
|
||||
IRAmcorAc ac(0);
|
||||
ac.begin();
|
||||
|
||||
ac.setTemp(0);
|
||||
EXPECT_EQ(kAmcorMinTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(255);
|
||||
EXPECT_EQ(kAmcorMaxTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(kAmcorMinTemp);
|
||||
EXPECT_EQ(kAmcorMinTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(kAmcorMaxTemp);
|
||||
EXPECT_EQ(kAmcorMaxTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(kAmcorMinTemp - 1);
|
||||
EXPECT_EQ(kAmcorMinTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(kAmcorMaxTemp + 1);
|
||||
EXPECT_EQ(kAmcorMaxTemp, ac.getTemp());
|
||||
|
||||
ac.setTemp(17);
|
||||
EXPECT_EQ(17, ac.getTemp());
|
||||
|
||||
ac.setTemp(21);
|
||||
EXPECT_EQ(21, ac.getTemp());
|
||||
|
||||
ac.setTemp(25);
|
||||
EXPECT_EQ(25, ac.getTemp());
|
||||
|
||||
ac.setTemp(29);
|
||||
EXPECT_EQ(29, ac.getTemp());
|
||||
}
|
||||
|
||||
TEST(TestAmcorAcClass, OperatingMode) {
|
||||
IRAmcorAc ac(0);
|
||||
ac.begin();
|
||||
|
||||
ac.setMode(kAmcorAuto);
|
||||
EXPECT_EQ(kAmcorAuto, ac.getMode());
|
||||
|
||||
ac.setMode(kAmcorCool);
|
||||
EXPECT_EQ(kAmcorCool, ac.getMode());
|
||||
|
||||
ac.setMode(kAmcorHeat);
|
||||
EXPECT_EQ(kAmcorHeat, ac.getMode());
|
||||
|
||||
ac.setMode(kAmcorDry);
|
||||
EXPECT_EQ(kAmcorDry, ac.getMode());
|
||||
|
||||
ac.setMode(kAmcorFan);
|
||||
EXPECT_EQ(kAmcorFan, ac.getMode());
|
||||
|
||||
ac.setMode(kAmcorAuto + 1);
|
||||
EXPECT_EQ(kAmcorAuto, ac.getMode());
|
||||
|
||||
ac.setMode(255);
|
||||
EXPECT_EQ(kAmcorAuto, ac.getMode());
|
||||
}
|
||||
|
||||
TEST(TestAmcorAcClass, FanSpeed) {
|
||||
IRAmcorAc ac(0);
|
||||
ac.begin();
|
||||
|
||||
ac.setFan(0);
|
||||
EXPECT_EQ(kAmcorFanAuto, ac.getFan());
|
||||
|
||||
ac.setFan(255);
|
||||
EXPECT_EQ(kAmcorFanAuto, ac.getFan());
|
||||
|
||||
ac.setFan(kAmcorFanMax);
|
||||
EXPECT_EQ(kAmcorFanMax, ac.getFan());
|
||||
|
||||
ac.setFan(kAmcorFanMax + 1);
|
||||
EXPECT_EQ(kAmcorFanAuto, ac.getFan());
|
||||
|
||||
ac.setFan(kAmcorFanMax - 1);
|
||||
EXPECT_EQ(kAmcorFanMax - 1, ac.getFan());
|
||||
|
||||
ac.setFan(1);
|
||||
EXPECT_EQ(1, ac.getFan());
|
||||
|
||||
ac.setFan(1);
|
||||
EXPECT_EQ(1, ac.getFan());
|
||||
|
||||
ac.setFan(3);
|
||||
EXPECT_EQ(3, ac.getFan());
|
||||
}
|
||||
|
||||
TEST(TestAmcorAcClass, Checksums) {
|
||||
uint8_t state[kAmcorStateLength] = {
|
||||
0x01, 0x41, 0x30, 0x00, 0x00, 0x30, 0x00, 0x0C};
|
||||
|
||||
ASSERT_EQ(0x0C, IRAmcorAc::calcChecksum(state));
|
||||
EXPECT_TRUE(IRAmcorAc::validChecksum(state));
|
||||
// Change the array so the checksum is invalid.
|
||||
state[0] ^= 0xFF;
|
||||
EXPECT_FALSE(IRAmcorAc::validChecksum(state));
|
||||
// Restore the previous change, and change another byte.
|
||||
state[0] ^= 0xFF;
|
||||
state[4] ^= 0xFF;
|
||||
EXPECT_FALSE(IRAmcorAc::validChecksum(state));
|
||||
state[4] ^= 0xFF;
|
||||
EXPECT_TRUE(IRAmcorAc::validChecksum(state));
|
||||
|
||||
// Additional known good states.
|
||||
uint8_t knownGood1[kAmcorStateLength] = {
|
||||
0x01, 0x11, 0x3E, 0x00, 0x00, 0x30, 0x00, 0x17};
|
||||
EXPECT_TRUE(IRAmcorAc::validChecksum(knownGood1));
|
||||
ASSERT_EQ(0x17, IRAmcorAc::calcChecksum(knownGood1));
|
||||
uint8_t knownGood2[kAmcorStateLength] = {
|
||||
0x01, 0x22, 0x26, 0x00, 0x00, 0x30, 0x00, 0x10};
|
||||
EXPECT_TRUE(IRAmcorAc::validChecksum(knownGood2));
|
||||
ASSERT_EQ(0x10, IRAmcorAc::calcChecksum(knownGood2));
|
||||
uint8_t knownGood3[kAmcorStateLength] = {
|
||||
0x01, 0x41, 0x24, 0x00, 0x00, 0xC0, 0x00, 0x18};
|
||||
EXPECT_TRUE(IRAmcorAc::validChecksum(knownGood3));
|
||||
ASSERT_EQ(0x18, IRAmcorAc::calcChecksum(knownGood3));
|
||||
|
||||
// For a recalculation.
|
||||
uint8_t knownBad[kAmcorStateLength] = {
|
||||
// Same as knownGood3 except for the checksum.
|
||||
0x01, 0x41, 0x24, 0x00, 0x00, 0xC0, 0x00, 0x00};
|
||||
EXPECT_FALSE(IRAmcorAc::validChecksum(knownBad));
|
||||
IRAmcorAc ac(0);
|
||||
ac.setRaw(knownBad);
|
||||
EXPECT_STATE_EQ(knownGood3, ac.getRaw(), kAmcorBits);
|
||||
}
|
||||
|
||||
TEST(TestAmcorAcClass, Max) {
|
||||
IRAmcorAc ac(0);
|
||||
ac.begin();
|
||||
|
||||
ac.setMode(kAmcorCool);
|
||||
ac.setMax(true);
|
||||
EXPECT_EQ(kAmcorCool, ac.getMode());
|
||||
EXPECT_EQ(kAmcorMinTemp, ac.getTemp());
|
||||
EXPECT_TRUE(ac.getMax());
|
||||
ac.setMax(false);
|
||||
EXPECT_EQ(kAmcorCool, ac.getMode());
|
||||
EXPECT_EQ(kAmcorMinTemp, ac.getTemp());
|
||||
EXPECT_FALSE(ac.getMax());
|
||||
|
||||
ac.setMode(kAmcorHeat);
|
||||
ac.setMax(true);
|
||||
EXPECT_EQ(kAmcorHeat, ac.getMode());
|
||||
EXPECT_EQ(kAmcorMaxTemp, ac.getTemp());
|
||||
EXPECT_TRUE(ac.getMax());
|
||||
ac.setMax(false);
|
||||
EXPECT_EQ(kAmcorHeat, ac.getMode());
|
||||
EXPECT_EQ(kAmcorMaxTemp, ac.getTemp());
|
||||
EXPECT_FALSE(ac.getMax());
|
||||
|
||||
ac.setMode(kAmcorAuto);
|
||||
ac.setTemp(25);
|
||||
ac.setMax(true);
|
||||
EXPECT_EQ(kAmcorAuto, ac.getMode());
|
||||
EXPECT_EQ(25, ac.getTemp());
|
||||
EXPECT_FALSE(ac.getMax());
|
||||
|
||||
// Test known real data.
|
||||
uint8_t lo[kAmcorStateLength] = {
|
||||
0x01, 0x41, 0x18, 0x00, 0x00, 0x30, 0x03, 0x15};
|
||||
uint8_t hi[kAmcorStateLength] = {
|
||||
0x01, 0x12, 0x40, 0x00, 0x00, 0x30, 0x03, 0x0E};
|
||||
ac.setRaw(lo);
|
||||
EXPECT_EQ("Power: On, Mode: 1 (COOL), Fan: 4 (Auto), Temp: 12C, Max: On",
|
||||
ac.toString());
|
||||
ac.setRaw(hi);
|
||||
EXPECT_EQ("Power: On, Mode: 2 (HEAT), Fan: 1 (Low), Temp: 32C, Max: On",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
@@ -497,7 +497,8 @@ TEST(TestGreeClass, HumanReadable) {
|
||||
EXPECT_EQ(
|
||||
"Model: 1 (YAW1F), Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 0 (Auto), "
|
||||
"Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, "
|
||||
"Swing Vertical Mode: Manual, Swing Vertical Pos: 0 (Last Pos)",
|
||||
"Swing Vertical Mode: Manual, Swing Vertical Pos: 0 (Last Pos), "
|
||||
"Timer: Off",
|
||||
irgree.toString());
|
||||
irgree.on();
|
||||
irgree.setMode(kGreeCool);
|
||||
@@ -510,10 +511,11 @@ TEST(TestGreeClass, HumanReadable) {
|
||||
irgree.setIFeel(true);
|
||||
irgree.setWiFi(true);
|
||||
irgree.setSwingVertical(true, kGreeSwingAuto);
|
||||
irgree.setTimer(12 * 60 + 30);
|
||||
EXPECT_EQ(
|
||||
"Model: 1 (YAW1F), Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 3 (High), "
|
||||
"Turbo: On, IFeel: On, WiFi: On, XFan: On, Light: Off, Sleep: On, "
|
||||
"Swing Vertical Mode: Auto, Swing Vertical Pos: 1 (Auto)",
|
||||
"Swing Vertical Mode: Auto, Swing Vertical Pos: 1 (Auto), Timer: 12:30",
|
||||
irgree.toString());
|
||||
}
|
||||
|
||||
@@ -573,7 +575,7 @@ TEST(TestDecodeGree, NormalRealExample) {
|
||||
EXPECT_EQ(
|
||||
"Model: 1 (YAW1F), Power: On, Mode: 1 (COOL), Temp: 26C, Fan: 1 (Low), "
|
||||
"Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, "
|
||||
"Swing Vertical Mode: Manual, Swing Vertical Pos: 2",
|
||||
"Swing Vertical Mode: Manual, Swing Vertical Pos: 2, Timer: Off",
|
||||
irgree.toString());
|
||||
}
|
||||
|
||||
@@ -628,7 +630,7 @@ TEST(TestGreeClass, Issue814Power) {
|
||||
EXPECT_EQ(
|
||||
"Model: 2 (YBOFB), Power: On, Mode: 1 (COOL), Temp: 23C, Fan: 1 (Low), "
|
||||
"Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, "
|
||||
"Swing Vertical Mode: Auto, Swing Vertical Pos: 1 (Auto)",
|
||||
"Swing Vertical Mode: Auto, Swing Vertical Pos: 1 (Auto), Timer: Off",
|
||||
ac.toString());
|
||||
ac.off();
|
||||
EXPECT_STATE_EQ(off, ac.getRaw(), kGreeBits);
|
||||
@@ -643,3 +645,44 @@ TEST(TestGreeClass, Issue814Power) {
|
||||
ac.on();
|
||||
EXPECT_STATE_EQ(YBOFB_on, ac.getRaw(), kGreeBits);
|
||||
}
|
||||
|
||||
TEST(TestGreeClass, Timer) {
|
||||
IRGreeAC ac(0);
|
||||
ac.begin();
|
||||
|
||||
ac.setTimer(0);
|
||||
EXPECT_FALSE(ac.getTimerEnabled());
|
||||
EXPECT_EQ(0, ac.getTimer());
|
||||
|
||||
ac.setTimer(29);
|
||||
EXPECT_FALSE(ac.getTimerEnabled());
|
||||
EXPECT_EQ(0, ac.getTimer());
|
||||
|
||||
ac.setTimer(30);
|
||||
EXPECT_TRUE(ac.getTimerEnabled());
|
||||
EXPECT_EQ(30, ac.getTimer());
|
||||
|
||||
ac.setTimer(60);
|
||||
EXPECT_TRUE(ac.getTimerEnabled());
|
||||
EXPECT_EQ(60, ac.getTimer());
|
||||
|
||||
ac.setTimer(90);
|
||||
EXPECT_TRUE(ac.getTimerEnabled());
|
||||
EXPECT_EQ(90, ac.getTimer());
|
||||
|
||||
ac.setTimer(10 * 60);
|
||||
EXPECT_TRUE(ac.getTimerEnabled());
|
||||
EXPECT_EQ(10 * 60, ac.getTimer());
|
||||
|
||||
ac.setTimer(23 * 60 + 59);
|
||||
EXPECT_TRUE(ac.getTimerEnabled());
|
||||
EXPECT_EQ(23 * 60 + 30, ac.getTimer());
|
||||
|
||||
ac.setTimer(24 * 60 + 1);
|
||||
EXPECT_TRUE(ac.getTimerEnabled());
|
||||
EXPECT_EQ(24 * 60, ac.getTimer());
|
||||
|
||||
ac.setTimer(24 * 60 + 30);
|
||||
EXPECT_TRUE(ac.getTimerEnabled());
|
||||
EXPECT_EQ(24 * 60, ac.getTimer());
|
||||
}
|
||||
|
||||
@@ -198,26 +198,72 @@ TEST(TestTecoACClass, Sleep) {
|
||||
EXPECT_TRUE(ac.getSleep());
|
||||
}
|
||||
|
||||
TEST(TestTecoACClass, Light) {
|
||||
IRTecoAc ac(0);
|
||||
ac.begin();
|
||||
|
||||
ac.setLight(true);
|
||||
EXPECT_TRUE(ac.getLight());
|
||||
ac.setLight(false);
|
||||
EXPECT_EQ(false, ac.getLight());
|
||||
ac.setLight(true);
|
||||
EXPECT_TRUE(ac.getLight());
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/870#issue-484797174
|
||||
ac.setRaw(0x250200A09);
|
||||
EXPECT_TRUE(ac.getLight());
|
||||
}
|
||||
|
||||
TEST(TestTecoACClass, Humid) {
|
||||
IRTecoAc ac(0);
|
||||
ac.begin();
|
||||
|
||||
ac.setHumid(true);
|
||||
EXPECT_TRUE(ac.getHumid());
|
||||
ac.setHumid(false);
|
||||
EXPECT_EQ(false, ac.getHumid());
|
||||
ac.setHumid(true);
|
||||
EXPECT_TRUE(ac.getHumid());
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/870#issuecomment-524536810
|
||||
ac.setRaw(0x250100A09);
|
||||
EXPECT_TRUE(ac.getHumid());
|
||||
}
|
||||
|
||||
TEST(TestTecoACClass, Save) {
|
||||
IRTecoAc ac(0);
|
||||
ac.begin();
|
||||
|
||||
ac.setSave(true);
|
||||
EXPECT_TRUE(ac.getSave());
|
||||
ac.setSave(false);
|
||||
EXPECT_EQ(false, ac.getSave());
|
||||
ac.setSave(true);
|
||||
EXPECT_TRUE(ac.getSave());
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/870#issuecomment-524536810
|
||||
ac.setRaw(0x250800A09);
|
||||
EXPECT_TRUE(ac.getSave());
|
||||
}
|
||||
|
||||
TEST(TestTecoACClass, MessageConstuction) {
|
||||
IRTecoAc ac(0);
|
||||
|
||||
EXPECT_EQ(
|
||||
"Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Sleep: Off, "
|
||||
"Swing: Off",
|
||||
"Swing: Off, Light: Off, Humid: Off, Save: Off",
|
||||
ac.toString());
|
||||
ac.setPower(true);
|
||||
ac.setMode(kTecoCool);
|
||||
ac.setTemp(21);
|
||||
ac.setFan(kTecoFanHigh);
|
||||
ac.setSwing(false);
|
||||
ac.setLight(false);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), Sleep: Off, "
|
||||
"Swing: Off",
|
||||
"Swing: Off, Light: Off, Humid: Off, Save: Off",
|
||||
ac.toString());
|
||||
ac.setSwing(true);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), Sleep: Off, "
|
||||
"Swing: On",
|
||||
"Swing: On, Light: Off, Humid: Off, Save: Off",
|
||||
ac.toString());
|
||||
ac.setSwing(false);
|
||||
ac.setFan(kTecoFanLow);
|
||||
@@ -225,17 +271,20 @@ TEST(TestTecoACClass, MessageConstuction) {
|
||||
ac.setMode(kTecoHeat);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 1 (Low), Sleep: On, "
|
||||
"Swing: Off",
|
||||
"Swing: Off, Light: Off, Humid: Off, Save: Off",
|
||||
ac.toString());
|
||||
ac.setSleep(false);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 1 (Low), Sleep: Off, "
|
||||
"Swing: Off",
|
||||
"Swing: Off, Light: Off, Humid: Off, Save: Off",
|
||||
ac.toString());
|
||||
ac.setTemp(25);
|
||||
ac.setLight(true);
|
||||
ac.setSave(true);
|
||||
ac.setHumid(true);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 4 (HEAT), Temp: 25C, Fan: 1 (Low), Sleep: Off, "
|
||||
"Swing: Off",
|
||||
"Swing: Off, Light: On, Humid: On, Save: On",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
@@ -253,7 +302,7 @@ TEST(TestTecoACClass, ReconstructKnownMessage) {
|
||||
EXPECT_EQ(expected, ac.getRaw());
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 1 (COOL), Temp: 27C, Fan: 0 (Auto), Sleep: On, "
|
||||
"Swing: On",
|
||||
"Swing: On, Light: Off, Humid: Off, Save: Off",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
@@ -295,7 +344,7 @@ TEST(TestDecodeTeco, NormalDecodeWithStrict) {
|
||||
ac.setRaw(irsend.capture.value);
|
||||
EXPECT_EQ(
|
||||
"Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Sleep: Off, "
|
||||
"Swing: Off",
|
||||
"Swing: Off, Light: Off, Humid: Off, Save: Off",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
@@ -328,7 +377,7 @@ TEST(TestDecodeTeco, RealNormalExample) {
|
||||
ac.setRaw(irsend.capture.value);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 1 (COOL), Temp: 27C, Fan: 0 (Auto), Sleep: On, "
|
||||
"Swing: On",
|
||||
"Swing: On, Light: Off, Humid: Off, Save: Off",
|
||||
ac.toString());
|
||||
|
||||
uint16_t rawData2[73] = {
|
||||
@@ -353,7 +402,7 @@ TEST(TestDecodeTeco, RealNormalExample) {
|
||||
ac.setRaw(irsend.capture.value);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 2 (DRY), Temp: 21C, Fan: 2 (Medium), Sleep: Off, "
|
||||
"Swing: On",
|
||||
"Swing: On, Light: Off, Humid: Off, Save: Off",
|
||||
ac.toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -228,5 +228,5 @@ ir_Goodweather.o : $(USER_DIR)/ir_Goodweather.cpp $(USER_DIR)/ir_Goodweather.h $
|
||||
ir_Neoclima.o : $(USER_DIR)/ir_Neoclima.cpp $(USER_DIR)/ir_Neoclima.h $(COMMON_DEPS) $(GTEST_HEADERS)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Neoclima.cpp
|
||||
|
||||
ir_Amcor.o : $(USER_DIR)/ir_Amcor.cpp $(GTEST_HEADERS)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Amcor.cpp
|
||||
ir_Amcor.o : $(USER_DIR)/ir_Amcor.cpp $(USER_DIR)/ir_Amcor.h $(GTEST_HEADERS)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Amcor.cpp
|
||||
|
||||
+9
-5
@@ -12,10 +12,11 @@
|
||||
//---IRSEND: That commands format is: IRSEND,<protocol>,<data>,<bits>,<repeat>
|
||||
// bits and repeat default to 0 if not used and they are optional
|
||||
// For protocols RAW and RAW2 there is no bits and repeat part, they are supposed to be replayed as they are calculated by a Google docs sheet or by plugin P016
|
||||
//---IRSENDAC: That commands format is: IRSENDAC,{"Protocol":"COOLIX","Power":"on","Opmode":"dry","Fanspeed":"auto","Degrees":22,"Swingv":"max","Swingh":"off"}
|
||||
//---IRSENDAC: That commands format is: IRSENDAC,{"protocol":"COOLIX","power":"on","opmode":"dry","fanspeed":"auto","degrees":22,"swingv":"max","swingh":"off"}
|
||||
//--- The JSON keys are case sensitive and allways small case. The JSON data are case insensitive
|
||||
// The possible values
|
||||
// Protocols: Argo Coolix Daikin Fujitsu Haier Hitachi Kelvinator Midea Mitsubishi MitsubishiHeavy Panasonic Samsung Sharp Tcl Teco Toshiba Trotec Vestel Whirlpool
|
||||
//---Opmodes: ---Fanspeed: --Swingv: --Swingh:
|
||||
//---opmodes: ---fanspeed: --swingv: --swingh:
|
||||
// - "off" - "auto" - "off" - "off"
|
||||
// - "auto" - "min" - "auto" - "auto"
|
||||
// - "cool" - "low" - "highest" - "leftmax"
|
||||
@@ -23,11 +24,14 @@
|
||||
// - "dry" - "high" - "middle" - "middle"
|
||||
// - "fan_only" - "max" - "low" - "right"
|
||||
// - "lowest" - "rightmax"
|
||||
// - "wide"
|
||||
// "on" - "off" parameters are:
|
||||
// - "Power" - "Celsius" - "Quiet" - "Turbo" - "Econo" - "Light" - "Filter" - "Clean" - "Light" - "Beep"
|
||||
// - "power" - "celsius" - "quiet" - "turbo" - "econo" - "light" - "filter" - "clean" - "light" - "beep"
|
||||
// If celcius is set to "off" then farenheit will be used
|
||||
// - "Sleep" Nr. of mins of sleep mode, or use sleep mode. (<= 0 means off.)
|
||||
// - "Clock" Nr. of mins past midnight to set the clock to. (< 0 means off.)
|
||||
// - "sleep" Nr. of mins of sleep mode, or use sleep mode. (<= 0 means off.)
|
||||
// - "clock" Nr. of mins past midnight to set the clock to. (< 0 means off.)
|
||||
// - "model" . Nr or string representation of the model. Better to find it throught P016 - IR RX (0 means default.)
|
||||
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRac.h>
|
||||
#include <IRutils.h>
|
||||
|
||||
Reference in New Issue
Block a user