Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use IRremoteESP8266 to control AC/Heatpump #1054

Closed
martimarkov opened this issue Dec 25, 2020 · 2 comments
Closed

Use IRremoteESP8266 to control AC/Heatpump #1054

martimarkov opened this issue Dec 25, 2020 · 2 comments

Comments

@martimarkov
Copy link

Describe the problem you have/What new integration you would like

Use IRremoteESP8266 to control AC/Heatpump

Please describe your use case for this integration and alternatives you've tried:

Currently, there is a lack of support for ACs/Heatpumps. For example GREE, Kelvinator, etc. They are all implemented in IRremoteESP8266 and there is no need to recreate all that logic in esphome.

I have a semi-working version with Gree and I'm trying to make it generic now.

So mainly I'm looking for feedback. Is this something ESPHome thinks is good/in the right direction or is there a reason to not include it?

Additional context

@avbor
Copy link

avbor commented Dec 28, 2020

Yea, for me, Daikin platform from IR Remote Climate does not working =(
But, with lib from IRremoteESP8266 my Daikin FTXB partially works.
I found how to do it here - #444 (comment)
But I really want to have native support right out of the box.

@iglu-sebastian
Copy link

Since I also have a Daikin AC i've used the same approach with IRremoteESP8266 as in #444 (comment) - with pretty much all support for my needs.

include/irdaikin.h

#include "esphome.h"
#include "IRremoteESP8266.h"
#include "IRsend.h"
#include "ir_Daikin.h"

const uint16_t kIrLed = 14;
IRDaikinESP ac(kIrLed);

class DaikinAC : public Component, public Climate {
  public:
    sensor::Sensor *sensor_{nullptr};

    void set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }

    void setup() override
    {
      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 = 25;
      }

      ac.begin();
      ac.on();
      if (this->mode == CLIMATE_MODE_OFF) {
        ac.off();
      } else if (this->mode == CLIMATE_MODE_COOL) {
        ac.setMode(kDaikinCool);
      } else if (this->mode == CLIMATE_MODE_DRY) {
        ac.setMode(kDaikinDry);
      } else if (this->mode == CLIMATE_MODE_FAN_ONLY) {
        ac.setMode(kDaikinFan);
      }
      ac.setTemp(this->target_temperature);
      if (this->fan_mode == CLIMATE_FAN_AUTO) {
        ac.setFan(kDaikinFanAuto);
      } else if (this->fan_mode == CLIMATE_FAN_LOW) {
        ac.setFan(kDaikinFanMin);
      } else if (this->fan_mode == CLIMATE_FAN_MEDIUM) {
        ac.setFan(kDaikinFanMed);
      } else if (this->fan_mode == CLIMATE_FAN_HIGH) {
        ac.setFan(kDaikinFanMax);
      }
      if (this->swing_mode == CLIMATE_SWING_OFF) {
        ac.setSwingVertical(false);
      } else if (this->swing_mode == CLIMATE_SWING_VERTICAL) {
        ac.setSwingVertical(true);
      }
      ac.send();

      ESP_LOGD("DEBUG", "Daikin A/C remote is in the following state:");
      ESP_LOGD("DEBUG", "  %s\n", ac.toString().c_str());
    }

    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_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(kDaikinCool);
      } else if (mode == CLIMATE_MODE_DRY) {
        ac.on();
        ac.setMode(kDaikinDry);
      } else if (mode == CLIMATE_MODE_FAN_ONLY) {
        ac.on();
        ac.setMode(kDaikinFan);
      }
      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(kDaikinFanAuto);
      } else if (fan_mode == CLIMATE_FAN_LOW) {
        ac.setFan(kDaikinFanMin);
      } else if (fan_mode == CLIMATE_FAN_MEDIUM) {
        ac.setFan(kDaikinFanMed);
      } else if (fan_mode == CLIMATE_FAN_HIGH) {
        ac.setFan(kDaikinFanMax);
      }
      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.setSwingVertical(false);
      } else if (swing_mode == CLIMATE_SWING_VERTICAL) {
        ac.setSwingVertical(true);
      }
      this->swing_mode = swing_mode;
    }

    ac.send();

    this->publish_state();

    ESP_LOGD("DEBUG", "Daikin A/C remote is in the following state:");
    ESP_LOGD("DEBUG", "  %s\n", ac.toString().c_str());
  }
};

includes:

  includes: 
    - include/irdaikin.h
  libraries:
    - IRremoteESP8266

climate:

- platform: custom
  lambda: |-
    auto daikinac = new DaikinAC();
    daikinac->set_sensor(id(YOUR_SENSOR_HERE));
    App.register_component(daikinac);
    return {daikinac};
  climates:
    - name: "AC"

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants