mirror of
https://github.com/esphome/esphome.git
synced 2024-11-28 17:54:13 +01:00
Delonghi Penguino PAC W120HP ir support (#3124)
This commit is contained in:
parent
53e0fe8e51
commit
4e1f6518e8
6 changed files with 274 additions and 0 deletions
|
@ -55,6 +55,7 @@ esphome/components/current_based/* @djwmarcx
|
||||||
esphome/components/daly_bms/* @s1lvi0
|
esphome/components/daly_bms/* @s1lvi0
|
||||||
esphome/components/dashboard_import/* @esphome/core
|
esphome/components/dashboard_import/* @esphome/core
|
||||||
esphome/components/debug/* @OttoWinter
|
esphome/components/debug/* @OttoWinter
|
||||||
|
esphome/components/delonghi/* @grob6000
|
||||||
esphome/components/dfplayer/* @glmnet
|
esphome/components/dfplayer/* @glmnet
|
||||||
esphome/components/dht/* @OttoWinter
|
esphome/components/dht/* @OttoWinter
|
||||||
esphome/components/ds1307/* @badbadc0ffee
|
esphome/components/ds1307/* @badbadc0ffee
|
||||||
|
|
1
esphome/components/delonghi/__init__.py
Normal file
1
esphome/components/delonghi/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
CODEOWNERS = ["@grob6000"]
|
20
esphome/components/delonghi/climate.py
Normal file
20
esphome/components/delonghi/climate.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import climate_ir
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
|
AUTO_LOAD = ["climate_ir"]
|
||||||
|
|
||||||
|
delonghi_ns = cg.esphome_ns.namespace("delonghi")
|
||||||
|
DelonghiClimate = delonghi_ns.class_("DelonghiClimate", climate_ir.ClimateIR)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(DelonghiClimate),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await climate_ir.register_climate_ir(var, config)
|
186
esphome/components/delonghi/delonghi.cpp
Normal file
186
esphome/components/delonghi/delonghi.cpp
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
#include "delonghi.h"
|
||||||
|
#include "esphome/components/remote_base/remote_base.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace delonghi {
|
||||||
|
|
||||||
|
static const char *const TAG = "delonghi.climate";
|
||||||
|
|
||||||
|
void DelonghiClimate::transmit_state() {
|
||||||
|
uint8_t remote_state[DELONGHI_STATE_FRAME_SIZE] = {0};
|
||||||
|
remote_state[0] = DELONGHI_ADDRESS;
|
||||||
|
remote_state[1] = this->temperature_();
|
||||||
|
remote_state[1] |= (this->fan_speed_()) << 5;
|
||||||
|
remote_state[2] = this->operation_mode_();
|
||||||
|
// Calculate checksum
|
||||||
|
for (int i = 0; i < DELONGHI_STATE_FRAME_SIZE - 1; i++) {
|
||||||
|
remote_state[DELONGHI_STATE_FRAME_SIZE - 1] += remote_state[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto transmit = this->transmitter_->transmit();
|
||||||
|
auto *data = transmit.get_data();
|
||||||
|
data->set_carrier_frequency(DELONGHI_IR_FREQUENCY);
|
||||||
|
|
||||||
|
data->mark(DELONGHI_HEADER_MARK);
|
||||||
|
data->space(DELONGHI_HEADER_SPACE);
|
||||||
|
for (unsigned char b : remote_state) {
|
||||||
|
for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask
|
||||||
|
data->mark(DELONGHI_BIT_MARK);
|
||||||
|
bool bit = b & mask;
|
||||||
|
data->space(bit ? DELONGHI_ONE_SPACE : DELONGHI_ZERO_SPACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data->mark(DELONGHI_BIT_MARK);
|
||||||
|
data->space(0);
|
||||||
|
|
||||||
|
transmit.perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t DelonghiClimate::operation_mode_() {
|
||||||
|
uint8_t operating_mode = DELONGHI_MODE_ON;
|
||||||
|
switch (this->mode) {
|
||||||
|
case climate::CLIMATE_MODE_COOL:
|
||||||
|
operating_mode |= DELONGHI_MODE_COOL;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_DRY:
|
||||||
|
operating_mode |= DELONGHI_MODE_DRY;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_HEAT:
|
||||||
|
operating_mode |= DELONGHI_MODE_HEAT;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_HEAT_COOL:
|
||||||
|
operating_mode |= DELONGHI_MODE_AUTO;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_FAN_ONLY:
|
||||||
|
operating_mode |= DELONGHI_MODE_FAN;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_OFF:
|
||||||
|
default:
|
||||||
|
operating_mode = DELONGHI_MODE_OFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return operating_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t DelonghiClimate::fan_speed_() {
|
||||||
|
uint16_t fan_speed;
|
||||||
|
switch (this->fan_mode.value()) {
|
||||||
|
case climate::CLIMATE_FAN_LOW:
|
||||||
|
fan_speed = DELONGHI_FAN_LOW;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_FAN_MEDIUM:
|
||||||
|
fan_speed = DELONGHI_FAN_MEDIUM;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_FAN_HIGH:
|
||||||
|
fan_speed = DELONGHI_FAN_HIGH;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_FAN_AUTO:
|
||||||
|
default:
|
||||||
|
fan_speed = DELONGHI_FAN_AUTO;
|
||||||
|
}
|
||||||
|
return fan_speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t DelonghiClimate::temperature_() {
|
||||||
|
// Force special temperatures depending on the mode
|
||||||
|
uint8_t temperature = 0b0001;
|
||||||
|
switch (this->mode) {
|
||||||
|
case climate::CLIMATE_MODE_HEAT:
|
||||||
|
temperature = (uint8_t) roundf(this->target_temperature) - DELONGHI_TEMP_OFFSET_HEAT;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_COOL:
|
||||||
|
case climate::CLIMATE_MODE_DRY:
|
||||||
|
case climate::CLIMATE_MODE_HEAT_COOL:
|
||||||
|
case climate::CLIMATE_MODE_FAN_ONLY:
|
||||||
|
case climate::CLIMATE_MODE_OFF:
|
||||||
|
default:
|
||||||
|
temperature = (uint8_t) roundf(this->target_temperature) - DELONGHI_TEMP_OFFSET_COOL;
|
||||||
|
}
|
||||||
|
if (temperature > 0x0F) {
|
||||||
|
temperature = 0x0F; // clamp maximum
|
||||||
|
}
|
||||||
|
return temperature;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DelonghiClimate::parse_state_frame_(const uint8_t frame[]) {
|
||||||
|
uint8_t checksum = 0;
|
||||||
|
for (int i = 0; i < (DELONGHI_STATE_FRAME_SIZE - 1); i++) {
|
||||||
|
checksum += frame[i];
|
||||||
|
}
|
||||||
|
if (frame[DELONGHI_STATE_FRAME_SIZE - 1] != checksum) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t mode = frame[2] & 0x0F;
|
||||||
|
if (mode & DELONGHI_MODE_ON) {
|
||||||
|
switch (mode & 0x0E) {
|
||||||
|
case DELONGHI_MODE_COOL:
|
||||||
|
this->mode = climate::CLIMATE_MODE_COOL;
|
||||||
|
break;
|
||||||
|
case DELONGHI_MODE_DRY:
|
||||||
|
this->mode = climate::CLIMATE_MODE_DRY;
|
||||||
|
break;
|
||||||
|
case DELONGHI_MODE_HEAT:
|
||||||
|
this->mode = climate::CLIMATE_MODE_HEAT;
|
||||||
|
break;
|
||||||
|
case DELONGHI_MODE_AUTO:
|
||||||
|
this->mode = climate::CLIMATE_MODE_HEAT_COOL;
|
||||||
|
break;
|
||||||
|
case DELONGHI_MODE_FAN:
|
||||||
|
this->mode = climate::CLIMATE_MODE_FAN_ONLY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this->mode = climate::CLIMATE_MODE_OFF;
|
||||||
|
}
|
||||||
|
uint8_t temperature = frame[1] & 0x0F;
|
||||||
|
if (this->mode == climate::CLIMATE_MODE_HEAT) {
|
||||||
|
this->target_temperature = temperature + DELONGHI_TEMP_OFFSET_HEAT;
|
||||||
|
} else {
|
||||||
|
this->target_temperature = temperature + DELONGHI_TEMP_OFFSET_COOL;
|
||||||
|
}
|
||||||
|
uint8_t fan_mode = frame[1] >> 5;
|
||||||
|
switch (fan_mode) {
|
||||||
|
case DELONGHI_FAN_LOW:
|
||||||
|
this->fan_mode = climate::CLIMATE_FAN_LOW;
|
||||||
|
break;
|
||||||
|
case DELONGHI_FAN_MEDIUM:
|
||||||
|
this->fan_mode = climate::CLIMATE_FAN_MEDIUM;
|
||||||
|
break;
|
||||||
|
case DELONGHI_FAN_HIGH:
|
||||||
|
this->fan_mode = climate::CLIMATE_FAN_HIGH;
|
||||||
|
break;
|
||||||
|
case DELONGHI_FAN_AUTO:
|
||||||
|
this->fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this->publish_state();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DelonghiClimate::on_receive(remote_base::RemoteReceiveData data) {
|
||||||
|
uint8_t state_frame[DELONGHI_STATE_FRAME_SIZE] = {};
|
||||||
|
if (!data.expect_item(DELONGHI_HEADER_MARK, DELONGHI_HEADER_SPACE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (uint8_t pos = 0; pos < DELONGHI_STATE_FRAME_SIZE; pos++) {
|
||||||
|
uint8_t byte = 0;
|
||||||
|
for (int8_t bit = 0; bit < 8; bit++) {
|
||||||
|
if (data.expect_item(DELONGHI_BIT_MARK, DELONGHI_ONE_SPACE)) {
|
||||||
|
byte |= 1 << bit;
|
||||||
|
} else if (!data.expect_item(DELONGHI_BIT_MARK, DELONGHI_ZERO_SPACE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state_frame[pos] = byte;
|
||||||
|
if (pos == 0) {
|
||||||
|
// frame header
|
||||||
|
if (byte != DELONGHI_ADDRESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this->parse_state_frame_(state_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace delonghi
|
||||||
|
} // namespace esphome
|
64
esphome/components/delonghi/delonghi.h
Normal file
64
esphome/components/delonghi/delonghi.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/components/climate_ir/climate_ir.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace delonghi {
|
||||||
|
|
||||||
|
// Values for DELONGHI ARC43XXX IR Controllers
|
||||||
|
const uint8_t DELONGHI_ADDRESS = 83;
|
||||||
|
|
||||||
|
// Temperature
|
||||||
|
const uint8_t DELONGHI_TEMP_MIN = 13; // Celsius
|
||||||
|
const uint8_t DELONGHI_TEMP_MAX = 32; // Celsius
|
||||||
|
const uint8_t DELONGHI_TEMP_OFFSET_COOL = 17; // Celsius
|
||||||
|
const uint8_t DELONGHI_TEMP_OFFSET_HEAT = 12; // Celsius
|
||||||
|
|
||||||
|
// Modes
|
||||||
|
const uint8_t DELONGHI_MODE_AUTO = 0b1000;
|
||||||
|
const uint8_t DELONGHI_MODE_COOL = 0b0000;
|
||||||
|
const uint8_t DELONGHI_MODE_HEAT = 0b0110;
|
||||||
|
const uint8_t DELONGHI_MODE_DRY = 0b0010;
|
||||||
|
const uint8_t DELONGHI_MODE_FAN = 0b0100;
|
||||||
|
const uint8_t DELONGHI_MODE_OFF = 0b0000;
|
||||||
|
const uint8_t DELONGHI_MODE_ON = 0b0001;
|
||||||
|
|
||||||
|
// Fan Speed
|
||||||
|
const uint8_t DELONGHI_FAN_AUTO = 0b00;
|
||||||
|
const uint8_t DELONGHI_FAN_HIGH = 0b01;
|
||||||
|
const uint8_t DELONGHI_FAN_MEDIUM = 0b10;
|
||||||
|
const uint8_t DELONGHI_FAN_LOW = 0b11;
|
||||||
|
|
||||||
|
// IR Transmission - similar to NEC1
|
||||||
|
const uint32_t DELONGHI_IR_FREQUENCY = 38000;
|
||||||
|
const uint32_t DELONGHI_HEADER_MARK = 9000;
|
||||||
|
const uint32_t DELONGHI_HEADER_SPACE = 4500;
|
||||||
|
const uint32_t DELONGHI_BIT_MARK = 465;
|
||||||
|
const uint32_t DELONGHI_ONE_SPACE = 1750;
|
||||||
|
const uint32_t DELONGHI_ZERO_SPACE = 670;
|
||||||
|
|
||||||
|
// State Frame size
|
||||||
|
const uint8_t DELONGHI_STATE_FRAME_SIZE = 8;
|
||||||
|
|
||||||
|
class DelonghiClimate : public climate_ir::ClimateIR {
|
||||||
|
public:
|
||||||
|
DelonghiClimate()
|
||||||
|
: climate_ir::ClimateIR(DELONGHI_TEMP_MIN, DELONGHI_TEMP_MAX, 1.0f, true, true,
|
||||||
|
{climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM,
|
||||||
|
climate::CLIMATE_FAN_HIGH},
|
||||||
|
{climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL,
|
||||||
|
climate::CLIMATE_SWING_HORIZONTAL, climate::CLIMATE_SWING_BOTH}) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Transmit via IR the state of this climate controller.
|
||||||
|
void transmit_state() override;
|
||||||
|
uint8_t operation_mode_();
|
||||||
|
uint16_t fan_speed_();
|
||||||
|
uint8_t temperature_();
|
||||||
|
// Handle received IR Buffer
|
||||||
|
bool on_receive(remote_base::RemoteReceiveData data) override;
|
||||||
|
bool parse_state_frame_(const uint8_t frame[]);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace delonghi
|
||||||
|
} // namespace esphome
|
|
@ -1811,6 +1811,8 @@ climate:
|
||||||
name: Fujitsu General Climate
|
name: Fujitsu General Climate
|
||||||
- platform: daikin
|
- platform: daikin
|
||||||
name: Daikin Climate
|
name: Daikin Climate
|
||||||
|
- platform: delonghi
|
||||||
|
name: Delonghi Climate
|
||||||
- platform: yashima
|
- platform: yashima
|
||||||
name: Yashima Climate
|
name: Yashima Climate
|
||||||
- platform: mitsubishi
|
- platform: mitsubishi
|
||||||
|
|
Loading…
Reference in a new issue