Skip to content

Instantly share code, notes, and snippets.

@Fusseldieb
Last active February 4, 2021 03:08
Show Gist options
  • Select an option

  • Save Fusseldieb/a141581eaccff2b1ff9917c43e750f6a to your computer and use it in GitHub Desktop.

Select an option

Save Fusseldieb/a141581eaccff2b1ff9917c43e750f6a to your computer and use it in GitHub Desktop.

Revisions

  1. Fusseldieb revised this gist Feb 4, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion irsamsung.h
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    // 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.
    // 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"
  2. Fusseldieb created this gist Feb 4, 2021.
    194 changes: 194 additions & 0 deletions irsamsung.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,194 @@
    // 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.

    #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());
    }
    };