Base climate ir (#726)

* add ClimateIR

* update climate ir

* update class comment

* lint

* moved to climate_ir

* fix include path

* use climateir

* updates

* update include path

* lint

* fixed variable assigned to itself
This commit is contained in:
Guillermo Ruffino 2019-10-17 16:01:02 -03:00 committed by Otto Winter
parent 1242f43769
commit 578e5a0d7a
6 changed files with 121 additions and 82 deletions

View File

@ -0,0 +1,57 @@
#include "climate_ir.h"
namespace esphome {
namespace climate {
climate::ClimateTraits ClimateIR::traits() {
auto traits = climate::ClimateTraits();
traits.set_supports_current_temperature(this->sensor_ != nullptr);
traits.set_supports_auto_mode(true);
traits.set_supports_cool_mode(this->supports_cool_);
traits.set_supports_heat_mode(this->supports_heat_);
traits.set_supports_two_point_target_temperature(false);
traits.set_supports_away(false);
traits.set_visual_min_temperature(this->minimum_temperature_);
traits.set_visual_max_temperature(this->maximum_temperature_);
traits.set_visual_temperature_step(this->temperature_step_);
return traits;
}
void ClimateIR::setup() {
if (this->sensor_) {
this->sensor_->add_on_state_callback([this](float state) {
this->current_temperature = state;
// current temperature changed, publish state
this->publish_state();
});
this->current_temperature = this->sensor_->state;
} else
this->current_temperature = NAN;
// restore set points
auto restore = this->restore_state_();
if (restore.has_value()) {
restore->apply(this);
} else {
// restore from defaults
this->mode = climate::CLIMATE_MODE_OFF;
// initialize target temperature to some value so that it's not NAN
this->target_temperature =
roundf(clamp(this->current_temperature, this->minimum_temperature_, this->maximum_temperature_));
}
// Never send nan to HA
if (isnan(this->target_temperature))
this->target_temperature = 24;
}
void ClimateIR::control(const climate::ClimateCall &call) {
if (call.get_mode().has_value())
this->mode = *call.get_mode();
if (call.get_target_temperature().has_value())
this->target_temperature = *call.get_target_temperature();
this->transmit_state();
this->publish_state();
}
} // namespace climate
} // namespace esphome

View File

@ -0,0 +1,53 @@
#pragma once
#include "esphome/components/climate/climate.h"
#include "esphome/components/remote_base/remote_base.h"
#include "esphome/components/remote_transmitter/remote_transmitter.h"
#include "esphome/components/sensor/sensor.h"
namespace esphome {
namespace climate {
/* A base for climate which works by sending (and receiving) IR codes
To send IR codes implement
void ClimateIR::transmit_state_()
Likewise to decode a IR into the AC state, implement
bool RemoteReceiverListener::on_receive(remote_base::RemoteReceiveData data) and return true
*/
class ClimateIR : public climate::Climate, public Component, public remote_base::RemoteReceiverListener {
public:
ClimateIR(float minimum_temperature, float maximum_temperature, float temperature_step = 1.0f) {
this->minimum_temperature_ = minimum_temperature;
this->maximum_temperature_ = maximum_temperature;
this->temperature_step_ = temperature_step;
}
void setup() override;
void set_transmitter(remote_transmitter::RemoteTransmitterComponent *transmitter) {
this->transmitter_ = transmitter;
}
void set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
void set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
void set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
protected:
float minimum_temperature_, maximum_temperature_, temperature_step_;
/// Override control to change settings of the climate device.
void control(const climate::ClimateCall &call) override;
/// Return the traits of this controller.
climate::ClimateTraits traits() override;
/// Transmit via IR the state of this climate controller.
virtual void transmit_state() {}
bool supports_cool_{true};
bool supports_heat_{true};
remote_transmitter::RemoteTransmitterComponent *transmitter_;
sensor::Sensor *sensor_{nullptr};
};
} // namespace climate
} // namespace esphome

View File

@ -3,7 +3,7 @@ import esphome.config_validation as cv
from esphome.components import climate, remote_transmitter, remote_receiver, sensor from esphome.components import climate, remote_transmitter, remote_receiver, sensor
from esphome.const import CONF_ID, CONF_SENSOR from esphome.const import CONF_ID, CONF_SENSOR
AUTO_LOAD = ['sensor'] AUTO_LOAD = ['sensor', 'climate_ir']
coolix_ns = cg.esphome_ns.namespace('coolix') coolix_ns = cg.esphome_ns.namespace('coolix')
CoolixClimate = coolix_ns.class_('CoolixClimate', climate.Climate, cg.Component) CoolixClimate = coolix_ns.class_('CoolixClimate', climate.Climate, cg.Component)

View File

@ -27,8 +27,6 @@ const uint32_t COOLIX_FAN_MED = 0x5000;
const uint32_t COOLIX_FAN_MAX = 0x3000; const uint32_t COOLIX_FAN_MAX = 0x3000;
// Temperature // Temperature
const uint8_t COOLIX_TEMP_MIN = 17; // Celsius
const uint8_t COOLIX_TEMP_MAX = 30; // Celsius
const uint8_t COOLIX_TEMP_RANGE = COOLIX_TEMP_MAX - COOLIX_TEMP_MIN + 1; const uint8_t COOLIX_TEMP_RANGE = COOLIX_TEMP_MAX - COOLIX_TEMP_MIN + 1;
const uint8_t COOLIX_FAN_TEMP_CODE = 0b1110; // Part of Fan Mode. const uint8_t COOLIX_FAN_TEMP_CODE = 0b1110; // Part of Fan Mode.
const uint32_t COOLIX_TEMP_MASK = 0b11110000; const uint32_t COOLIX_TEMP_MASK = 0b11110000;
@ -60,56 +58,7 @@ static const uint32_t FOOTER_SPACE_US = HEADER_SPACE_US;
const uint16_t COOLIX_BITS = 24; const uint16_t COOLIX_BITS = 24;
climate::ClimateTraits CoolixClimate::traits() { void CoolixClimate::transmit_state() {
auto traits = climate::ClimateTraits();
traits.set_supports_current_temperature(this->sensor_ != nullptr);
traits.set_supports_auto_mode(true);
traits.set_supports_cool_mode(this->supports_cool_);
traits.set_supports_heat_mode(this->supports_heat_);
traits.set_supports_two_point_target_temperature(false);
traits.set_supports_away(false);
traits.set_visual_min_temperature(17);
traits.set_visual_max_temperature(30);
traits.set_visual_temperature_step(1);
return traits;
}
void CoolixClimate::setup() {
if (this->sensor_) {
this->sensor_->add_on_state_callback([this](float state) {
this->current_temperature = state;
// current temperature changed, publish state
this->publish_state();
});
this->current_temperature = this->sensor_->state;
} else
this->current_temperature = NAN;
// restore set points
auto restore = this->restore_state_();
if (restore.has_value()) {
restore->apply(this);
} else {
// restore from defaults
this->mode = climate::CLIMATE_MODE_OFF;
// initialize target temperature to some value so that it's not NAN
this->target_temperature = (uint8_t) roundf(clamp(this->current_temperature, COOLIX_TEMP_MIN, COOLIX_TEMP_MAX));
}
// never send nan as temperature. HA will disable the user to change the temperature.
if (isnan(this->target_temperature))
this->target_temperature = 24;
}
void CoolixClimate::control(const climate::ClimateCall &call) {
if (call.get_mode().has_value())
this->mode = *call.get_mode();
if (call.get_target_temperature().has_value())
this->target_temperature = *call.get_target_temperature();
this->transmit_state_();
this->publish_state();
}
void CoolixClimate::transmit_state_() {
uint32_t remote_state; uint32_t remote_state;
switch (this->mode) { switch (this->mode) {

View File

@ -1,43 +1,23 @@
#pragma once #pragma once
#include "esphome/core/component.h" #include "esphome/components/climate_ir/climate_ir.h"
#include "esphome/core/automation.h"
#include "esphome/components/climate/climate.h"
#include "esphome/components/remote_base/remote_base.h"
#include "esphome/components/remote_transmitter/remote_transmitter.h"
#include "esphome/components/sensor/sensor.h"
namespace esphome { namespace esphome {
namespace coolix { namespace coolix {
using namespace remote_base; // Temperature
const uint8_t COOLIX_TEMP_MIN = 17; // Celsius
const uint8_t COOLIX_TEMP_MAX = 30; // Celsius
class CoolixClimate : public climate::Climate, public Component, public RemoteReceiverListener { class CoolixClimate : public climate::ClimateIR {
public: public:
void setup() override; CoolixClimate() : climate::ClimateIR(COOLIX_TEMP_MIN, COOLIX_TEMP_MAX) {}
void set_transmitter(remote_transmitter::RemoteTransmitterComponent *transmitter) {
this->transmitter_ = transmitter;
}
void set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
void set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
void set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
protected: protected:
/// Override control to change settings of the climate device.
void control(const climate::ClimateCall &call) override;
/// Return the traits of this controller.
climate::ClimateTraits traits() override;
/// Transmit via IR the state of this climate controller. /// Transmit via IR the state of this climate controller.
void transmit_state_(); void transmit_state() override;
/// Handle received IR Buffer
bool on_receive(RemoteReceiveData data) override; bool on_receive(remote_base::RemoteReceiveData data) override;
bool supports_cool_;
bool supports_heat_;
remote_transmitter::RemoteTransmitterComponent *transmitter_;
sensor::Sensor *sensor_{nullptr};
}; };
} // namespace coolix } // namespace coolix