Initial commit - hard fork
Това подаване се съдържа в:
подаване
16984710d2
7 променени файла с 297 добавяния и 0 изтривания
22
LICENSE
Обикновен файл
22
LICENSE
Обикновен файл
|
@ -0,0 +1,22 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 Roman Klassen
|
||||
Copyright (c) 2024 Sagi Dayan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
43
README.md
Обикновен файл
43
README.md
Обикновен файл
|
@ -0,0 +1,43 @@
|
|||
# ESPHome Electra AC IR remote control component
|
||||
|
||||
This implementation of the ESPHome component to control HVAC with IR channel.
|
||||
|
||||
Base implementation of the protocol can be found here: [https://github.com/crankyoldgit/IRremoteESP8266](https://github.com/crankyoldgit/IRremoteESP8266)
|
||||
|
||||
This repo was originally forked from [https://github.com/rozh1/esphome-haier-ac-ir](https://github.com/rozh1/esphome-haier-ac-ir)
|
||||
|
||||
## Supported AC
|
||||
- Brand: AUX, Model: KFR-35GW/BpNFW=3 A/C
|
||||
- Brand: AUX, Model: YKR-T/011 remote
|
||||
- Brand: Electra, Model: Classic INV 17 / AXW12DCS A/C
|
||||
- Brand: Electra, Model: YKR-M/003E remote
|
||||
- Brand: Frigidaire, Model: FGPC102AB1 A/C
|
||||
- Brand: Subtropic, Model: SUB-07HN1_18Y A/C
|
||||
- Brand: Subtropic, Model: YKR-H/102E remote
|
||||
- Brand: Centek, Model: SCT-65Q09 A/C
|
||||
- Brand: Centek, Model: YKR-P/002E remote
|
||||
- Brand: AEG, Model: Chillflex Pro AXP26U338CW A/C
|
||||
- Brand: Electrolux, Model: YKR-H/531E A/C
|
||||
- Brand: Delonghi, Modell: PAC EM90
|
||||
|
||||
## How to use
|
||||
|
||||
1. Add sensor configuration. It can be a connected temperature sensor or home assistant provided sensor. For example:
|
||||
|
||||
```
|
||||
sensor:
|
||||
# External temperature sensor from Home Assistant
|
||||
- platform: homeassistant
|
||||
id: current_temperature
|
||||
entity_id: ${temperature_sensor}
|
||||
```
|
||||
|
||||
2. Add climate component, set platform as `electra_ac`, set `sensor_id` and `pin` number for IR LED.
|
||||
|
||||
```
|
||||
climate:
|
||||
- platform: electra_ac
|
||||
sensor_id: current_temperature # Sensor ID with the current temperature
|
||||
pin: 3 # Pin with IR led
|
||||
name: "Electra A/C"
|
||||
```
|
0
components/electra_ac/__init__.py
Обикновен файл
0
components/electra_ac/__init__.py
Обикновен файл
29
components/electra_ac/climate.py
Обикновен файл
29
components/electra_ac/climate.py
Обикновен файл
|
@ -0,0 +1,29 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import climate, sensor
|
||||
from esphome.const import CONF_ID, CONF_PIN, CONF_SENSOR_ID
|
||||
from esphome.core import CORE
|
||||
|
||||
AUTO_LOAD = ["climate"]
|
||||
|
||||
electra_ac_ns = cg.esphome_ns.namespace("electra_ac")
|
||||
ElectraClimate = electra_ac_ns.class_("ElectraClimate", climate.Climate)
|
||||
|
||||
CONFIG_SCHEMA = climate.CLIMATE_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(ElectraClimate),
|
||||
cv.Required(CONF_SENSOR_ID): cv.use_id(sensor.Sensor),
|
||||
cv.Required(CONF_PIN): cv.int_,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
if CORE.is_esp8266 or CORE.is_esp32:
|
||||
cg.add_library("crankyoldgit/IRremoteESP8266", "2.8.4")
|
||||
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await climate.register_climate(var, config)
|
||||
|
||||
sens = await cg.get_variable(config[CONF_SENSOR_ID])
|
||||
cg.add(var.init(sens, config[CONF_PIN]))
|
129
components/electra_ac/electra_ac.cpp
Обикновен файл
129
components/electra_ac/electra_ac.cpp
Обикновен файл
|
@ -0,0 +1,129 @@
|
|||
#include "electra_ac.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace electra_ac {
|
||||
|
||||
static const char *const TAG = "climate.electra_ac";
|
||||
|
||||
void ElectraClimate::init(sensor::Sensor *sensor, uint16_t pin) {
|
||||
this->set_sensor(sensor);
|
||||
ac_ = new IRElectraAc(pin);
|
||||
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 = 24;
|
||||
this->fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||
this->swing_mode = climate::CLIMATE_SWING_OFF;
|
||||
this->preset = climate::CLIMATE_PRESET_NONE;
|
||||
}
|
||||
|
||||
if (isnan(this->target_temperature)) {
|
||||
this->target_temperature = 25;
|
||||
}
|
||||
|
||||
ac_->begin();
|
||||
this->setup_ir_cmd();
|
||||
|
||||
ESP_LOGD("DEBUG", "Electra A/C remote is in the following state:");
|
||||
ESP_LOGD("DEBUG", " %s\n", ac_->toString().c_str());
|
||||
}
|
||||
|
||||
void ElectraClimate::set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
|
||||
|
||||
void ElectraClimate::setup_ir_cmd() {
|
||||
if (this->mode == climate::CLIMATE_MODE_OFF) {
|
||||
ac_->off();
|
||||
} else {
|
||||
ac_->on();
|
||||
if (this->mode == climate::CLIMATE_MODE_AUTO) {
|
||||
ac_->setMode(kElectraAcAuto);
|
||||
} else if (this->mode == climate::CLIMATE_MODE_COOL) {
|
||||
ac_->setMode(kElectraAcCool);
|
||||
} else if (this->mode == climate::CLIMATE_MODE_HEAT) {
|
||||
ac_->setMode(kElectraAcHeat);
|
||||
} else if (this->mode == climate::CLIMATE_MODE_DRY) {
|
||||
ac_->setMode(kElectraAcDry);
|
||||
} else if (this->mode == climate::CLIMATE_MODE_FAN_ONLY) {
|
||||
ac_->setMode(kElectraAcFan);
|
||||
}
|
||||
|
||||
ac_->setTemp((uint8_t)this->target_temperature);
|
||||
|
||||
if (this->fan_mode == climate::CLIMATE_FAN_AUTO) {
|
||||
ac_->setFan(kElectraAcFanAuto);
|
||||
} else if (this->fan_mode == climate::CLIMATE_FAN_LOW) {
|
||||
ac_->setFan(kElectraAcFanLow);
|
||||
} else if (this->fan_mode == climate::CLIMATE_FAN_MEDIUM) {
|
||||
ac_->setFan(kElectraAcFanMed);
|
||||
} else if (this->fan_mode == climate::CLIMATE_FAN_HIGH) {
|
||||
ac_->setFan(kElectraAcFanHigh);
|
||||
}
|
||||
|
||||
if (this->swing_mode == climate::CLIMATE_SWING_OFF) {
|
||||
ac_->setSwingV(kElectraAcSwingOff);
|
||||
} else if (this->swing_mode == climate::CLIMATE_SWING_VERTICAL) {
|
||||
ac_->setSwingV(kElectraAcSwingOn);
|
||||
}
|
||||
|
||||
//ac_->setSleep(this->preset == climate::CLIMATE_PRESET_SLEEP);
|
||||
//ac_->setHealth(this->preset == climate::CLIMATE_PRESET_COMFORT);
|
||||
ac_->setTurbo(this->preset == climate::CLIMATE_PRESET_BOOST);
|
||||
}
|
||||
}
|
||||
|
||||
climate::ClimateTraits ElectraClimate::traits() {
|
||||
auto traits = climate::ClimateTraits();
|
||||
traits.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_COOL, climate::CLIMATE_MODE_HEAT,
|
||||
climate::CLIMATE_MODE_FAN_ONLY, climate::CLIMATE_MODE_DRY, climate::CLIMATE_MODE_AUTO});
|
||||
traits.set_supported_fan_modes(
|
||||
{climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH, climate::CLIMATE_FAN_AUTO});
|
||||
traits.set_supported_swing_modes({climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL});
|
||||
traits.set_supported_presets({climate::CLIMATE_PRESET_NONE, climate::CLIMATE_PRESET_BOOST});
|
||||
|
||||
traits.set_visual_max_temperature(ELECTRA_AC_TEMP_MAX);
|
||||
traits.set_visual_min_temperature(ELECTRA_AC_TEMP_MIN);
|
||||
traits.set_visual_temperature_step(1);
|
||||
traits.set_supports_current_temperature(true);
|
||||
|
||||
return traits;
|
||||
}
|
||||
|
||||
void ElectraClimate::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();
|
||||
|
||||
if (call.get_fan_mode().has_value())
|
||||
this->fan_mode = *call.get_fan_mode();
|
||||
|
||||
if (call.get_swing_mode().has_value())
|
||||
this->swing_mode = *call.get_swing_mode();
|
||||
|
||||
if (call.get_preset().has_value())
|
||||
this->preset = *call.get_preset();
|
||||
|
||||
this->setup_ir_cmd();
|
||||
ac_->send();
|
||||
|
||||
this->publish_state();
|
||||
|
||||
ESP_LOGD("DEBUG", "Electra A/C remote is in the following state:");
|
||||
ESP_LOGD("DEBUG", " %s\n", ac_->toString().c_str());
|
||||
}
|
||||
|
||||
} // namespace electra_ac
|
||||
} // namespace esphome
|
37
components/electra_ac/electra_ac.h
Обикновен файл
37
components/electra_ac/electra_ac.h
Обикновен файл
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/climate/climate.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
|
||||
#include "IRremoteESP8266.h"
|
||||
#include "IRsend.h"
|
||||
#include "ir_Electra.h"
|
||||
|
||||
|
||||
namespace esphome {
|
||||
namespace electra_ac {
|
||||
|
||||
const uint8_t ELECTRA_AC_TEMP_MIN = 16; // 16C
|
||||
const uint8_t ELECTRA_AC_TEMP_MAX = 30; // 32C
|
||||
|
||||
class ElectraClimate : public climate::Climate {
|
||||
public:
|
||||
ElectraClimate() : climate::Climate() {}
|
||||
public:
|
||||
void set_sensor(sensor::Sensor *sensor);
|
||||
void init(sensor::Sensor *sensor, uint16_t pin);
|
||||
|
||||
protected:
|
||||
IRElectraAc *ac_{nullptr};
|
||||
sensor::Sensor *sensor_{nullptr};
|
||||
|
||||
void setup_ir_cmd();
|
||||
|
||||
climate::ClimateTraits traits() override;
|
||||
void control(const climate::ClimateCall &call) override;
|
||||
|
||||
};
|
||||
|
||||
} // namespace haier_acyrw02
|
||||
} // namespace esphome
|
37
example.yaml
Обикновен файл
37
example.yaml
Обикновен файл
|
@ -0,0 +1,37 @@
|
|||
esphome:
|
||||
name: electra-ac-ir-remote
|
||||
|
||||
esp8266:
|
||||
board: esp01_1m
|
||||
|
||||
logger:
|
||||
baud_rate: 0
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
|
||||
# Enable fallback hotspot (captive portal) in case wifi connection fails
|
||||
ap:
|
||||
ssid: "electra-ac-ir-remote Fallback Hotspot"
|
||||
password: "0000"
|
||||
|
||||
web_server:
|
||||
port: 80
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: git
|
||||
url: https://git.dayanhub.com/sagi/esphome-electra-ac-ir
|
||||
|
||||
sensor:
|
||||
# External temperature sensor from Home Assistant
|
||||
- platform: homeassistant
|
||||
id: current_temperature
|
||||
entity_id: ${temperature_sensor}
|
||||
|
||||
climate:
|
||||
- platform: electra_ac
|
||||
sensor_id: current_temperature
|
||||
pin: 3 # Pin with IR led
|
||||
name: "Electra A/C"
|
Зареждане…
Препратка в нова задача