Last active
February 4, 2021 03:08
-
-
Save Fusseldieb/a141581eaccff2b1ff9917c43e750f6a to your computer and use it in GitHub Desktop.
IRremoteESP8266 for ESPHome with LED "sync" pin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This version of the code allows you to use an INPUT pin to sync the state of your HVAC with ESPHome | |
// This is particularly useful if you have integrated an ESP8266 inside your HVAC and hooked up the ON-LED from it to the ESP8266 | |
// That way even if someone turns the HVAC on with the remote control, Home Assistant should show the ACTUAL state of it (ON/OFF). | |
#include "esphome.h" | |
#include "IRremoteESP8266.h" | |
#include "IRsend.h" | |
#include "ir_Samsung.h" | |
const uint16_t kIrLed = D8; // IR LED (OUTPUT) PIN | |
IRSamsungAc ac(kIrLed); | |
const uint16_t kOnLed = D7; // "ON" LED (INPUT) PIN | |
class SamsungAC : public Component, public Climate { | |
public: | |
sensor::Sensor *sensor_{nullptr}; | |
void set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; } | |
void setup() override | |
{ | |
pinMode(kOnLed, INPUT); | |
if (this->sensor_) { | |
this->sensor_->add_on_state_callback([this](float state) { | |
this->current_temperature = state; | |
this->publish_state(); | |
}); | |
this->current_temperature = this->sensor_->state; | |
} else { | |
this->current_temperature = NAN; | |
} | |
auto restore = this->restore_state_(); | |
if (restore.has_value()) { | |
restore->apply(this); | |
} else { | |
this->mode = climate::CLIMATE_MODE_OFF; | |
this->target_temperature = roundf(clamp(this->current_temperature, 16, 30)); | |
this->fan_mode = climate::CLIMATE_FAN_AUTO; | |
this->swing_mode = climate::CLIMATE_SWING_OFF; | |
} | |
if (isnan(this->target_temperature)) { | |
this->target_temperature = 22; | |
} | |
ac.begin(); | |
ac.on(); | |
if (this->mode == CLIMATE_MODE_OFF) { | |
ac.off(); | |
} else if (this->mode == CLIMATE_MODE_COOL) { | |
ac.setMode(kSamsungAcCool); | |
} else if (this->mode == CLIMATE_MODE_DRY) { | |
ac.setMode(kSamsungAcDry); | |
} else if (this->mode == CLIMATE_MODE_FAN_ONLY) { | |
ac.setMode(kSamsungAcFan); | |
} else if (this->mode == CLIMATE_MODE_HEAT) { | |
ac.setMode(kSamsungAcFan); | |
} else if (this->mode == CLIMATE_MODE_AUTO) { | |
ac.setMode(kSamsungAcFan); | |
} | |
ac.setTemp(this->target_temperature); | |
if (this->fan_mode == CLIMATE_FAN_AUTO) { | |
ac.setFan(kSamsungAcFanAuto); | |
} else if (this->fan_mode == CLIMATE_FAN_LOW) { | |
ac.setFan(kSamsungAcFanLow); | |
} else if (this->fan_mode == CLIMATE_FAN_MEDIUM) { | |
ac.setFan(kSamsungAcFanMed); | |
} else if (this->fan_mode == CLIMATE_FAN_HIGH) { | |
ac.setFan(kSamsungAcFanHigh); | |
} | |
if (this->swing_mode == CLIMATE_SWING_OFF) { | |
ac.setSwing(false); | |
} else if (this->swing_mode == CLIMATE_SWING_VERTICAL) { | |
ac.setSwing(true); | |
} | |
if (this->mode == CLIMATE_MODE_OFF) { | |
ac.sendOff(); | |
} else { | |
ac.send(); | |
} | |
ESP_LOGD("DEBUG", "Samsung A/C remote is in the following state:"); | |
ESP_LOGD("DEBUG", " %s\n", ac.toString().c_str()); | |
} | |
void loop() override | |
{ | |
if (this->mode == CLIMATE_MODE_OFF && digitalRead(kOnLed) == 1) { | |
this->mode = climate::CLIMATE_MODE_AUTO; | |
ESP_LOGD("DEBUG", "Sync'd HA with LED"); | |
ESP_LOGD("DEBUG", "LED was turned on by itself. Assuming AUTO mode (Actual state unknown). This is not an error."); | |
this->publish_state(); | |
} else if (this->mode != CLIMATE_MODE_OFF && digitalRead(kOnLed) == 0) { | |
this->mode = climate::CLIMATE_MODE_OFF; | |
ESP_LOGD("DEBUG", "Sync'd HA with LED."); | |
this->publish_state(); | |
} | |
} | |
climate::ClimateTraits traits() { | |
auto traits = climate::ClimateTraits(); | |
traits.set_supports_cool_mode(true); | |
traits.set_supports_current_temperature(this->sensor_ != nullptr); | |
traits.set_supports_dry_mode(true); | |
traits.set_supports_auto_mode(true); | |
traits.set_supports_heat_mode(true); | |
traits.set_supports_fan_mode_auto(true); | |
traits.set_supports_fan_mode_high(true); | |
traits.set_supports_fan_mode_low(true); | |
traits.set_supports_fan_mode_medium(true); | |
traits.set_supports_fan_only_mode(true); | |
traits.set_supports_swing_mode_off(true); | |
traits.set_supports_swing_mode_vertical(true); | |
traits.set_supports_two_point_target_temperature(false); | |
traits.set_visual_max_temperature(30); | |
traits.set_visual_min_temperature(16); | |
traits.set_visual_temperature_step(1); | |
return traits; | |
} | |
void control(const ClimateCall &call) override { | |
if (call.get_mode().has_value()) { | |
ClimateMode mode = *call.get_mode(); | |
if (mode == CLIMATE_MODE_OFF) { | |
ac.off(); | |
} else if (mode == CLIMATE_MODE_COOL) { | |
ac.on(); | |
ac.setMode(kSamsungAcCool); | |
} else if (mode == CLIMATE_MODE_DRY) { | |
ac.on(); | |
ac.setMode(kSamsungAcDry); | |
} else if (mode == CLIMATE_MODE_FAN_ONLY) { | |
ac.on(); | |
ac.setMode(kSamsungAcFan); | |
} else if (mode == CLIMATE_MODE_HEAT) { | |
ac.on(); | |
ac.setMode(kSamsungAcFan); | |
} else if (mode == CLIMATE_MODE_AUTO) { | |
ac.on(); | |
ac.setMode(kSamsungAcFan); | |
} | |
this->mode = mode; | |
} | |
if (call.get_target_temperature().has_value()) { | |
float temp = *call.get_target_temperature(); | |
ac.setTemp(temp); | |
this->target_temperature = temp; | |
} | |
if (call.get_fan_mode().has_value()) { | |
ClimateFanMode fan_mode = *call.get_fan_mode(); | |
if (fan_mode == CLIMATE_FAN_AUTO) { | |
ac.setFan(kSamsungAcFanAuto); | |
} else if (fan_mode == CLIMATE_FAN_LOW) { | |
ac.setFan(kSamsungAcFanLow); | |
} else if (fan_mode == CLIMATE_FAN_MEDIUM) { | |
ac.setFan(kSamsungAcFanMed); | |
} else if (fan_mode == CLIMATE_FAN_HIGH) { | |
ac.setFan(kSamsungAcFanHigh); | |
} | |
this->fan_mode = fan_mode; | |
} | |
if (call.get_swing_mode().has_value()) { | |
ClimateSwingMode swing_mode = *call.get_swing_mode(); | |
if (swing_mode == CLIMATE_SWING_OFF) { | |
ac.setSwing(false); | |
} else if (swing_mode == CLIMATE_SWING_VERTICAL) { | |
ac.setSwing(true); | |
} | |
this->swing_mode = swing_mode; | |
} | |
if (this->mode == CLIMATE_MODE_OFF) { | |
ac.sendOff(); | |
} else { | |
ac.send(); | |
} | |
this->publish_state(); | |
ESP_LOGD("DEBUG", "Samsung A/C remote is in the following state:"); | |
ESP_LOGD("DEBUG", " %s\n", ac.toString().c_str()); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment