copy from Kannix2005
This commit is contained in:
@@ -85,6 +85,7 @@ VERTICAL_SWING_DIRECTION_OPTIONS = {
|
|||||||
"UP_DOWN": VerticalSwingDirection.UPDOWN,
|
"UP_DOWN": VerticalSwingDirection.UPDOWN,
|
||||||
"UPSIDE": VerticalSwingDirection.UPSIDE,
|
"UPSIDE": VerticalSwingDirection.UPSIDE,
|
||||||
"DOWNSIDE": VerticalSwingDirection.DOWNSIDE,
|
"DOWNSIDE": VerticalSwingDirection.DOWNSIDE,
|
||||||
|
"OFF": VerticalSwingDirection.OFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
HorizontalSwingDirection = tclac_ns.enum("HorizontalSwingDirection", True)
|
HorizontalSwingDirection = tclac_ns.enum("HorizontalSwingDirection", True)
|
||||||
@@ -93,6 +94,7 @@ HORIZONTAL_SWING_DIRECTION_OPTIONS = {
|
|||||||
"LEFTSIDE": HorizontalSwingDirection.LEFTSIDE,
|
"LEFTSIDE": HorizontalSwingDirection.LEFTSIDE,
|
||||||
"CENTER": HorizontalSwingDirection.CENTER,
|
"CENTER": HorizontalSwingDirection.CENTER,
|
||||||
"RIGHTSIDE": HorizontalSwingDirection.RIGHTSIDE,
|
"RIGHTSIDE": HorizontalSwingDirection.RIGHTSIDE,
|
||||||
|
"OFF": HorizontalSwingDirection.OFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
AirflowVerticalDirection = tclac_ns.enum("AirflowVerticalDirection", True)
|
AirflowVerticalDirection = tclac_ns.enum("AirflowVerticalDirection", True)
|
||||||
@@ -143,8 +145,7 @@ def validate_visual(config):
|
|||||||
|
|
||||||
# Проверка конфигурации компонента и принятие значений по умолчанию
|
# Проверка конфигурации компонента и принятие значений по умолчанию
|
||||||
CONFIG_SCHEMA = cv.All(
|
CONFIG_SCHEMA = cv.All(
|
||||||
climate.climate_schema(tclacClimate)
|
climate.CLIMATE_SCHEMA.extend(
|
||||||
.extend(
|
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(tclacClimate),
|
cv.GenerateID(): cv.declare_id(tclacClimate),
|
||||||
cv.Optional(CONF_BEEPER, default=True): cv.boolean,
|
cv.Optional(CONF_BEEPER, default=True): cv.boolean,
|
||||||
@@ -153,10 +154,10 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
cv.Optional(CONF_TX_LED): pins.gpio_output_pin_schema,
|
cv.Optional(CONF_TX_LED): pins.gpio_output_pin_schema,
|
||||||
cv.Optional(CONF_FORCE_MODE, default=True): cv.boolean,
|
cv.Optional(CONF_FORCE_MODE, default=True): cv.boolean,
|
||||||
cv.Optional(CONF_MODULE_DISPLAY, default=True): cv.boolean,
|
cv.Optional(CONF_MODULE_DISPLAY, default=True): cv.boolean,
|
||||||
cv.Optional(CONF_VERTICAL_AIRFLOW, default="CENTER"): cv.ensure_list(cv.enum(AIRFLOW_VERTICAL_DIRECTION_OPTIONS, upper=True)),
|
cv.Optional(CONF_VERTICAL_AIRFLOW, default="LAST"): cv.ensure_list(cv.enum(AIRFLOW_VERTICAL_DIRECTION_OPTIONS, upper=True)),
|
||||||
cv.Optional(CONF_VERTICAL_SWING_MODE, default="UP_DOWN"): cv.ensure_list(cv.enum(VERTICAL_SWING_DIRECTION_OPTIONS, upper=True)),
|
cv.Optional(CONF_VERTICAL_SWING_MODE, default="OFF"): cv.ensure_list(cv.enum(VERTICAL_SWING_DIRECTION_OPTIONS, upper=True)),
|
||||||
cv.Optional(CONF_HORIZONTAL_AIRFLOW, default="CENTER"): cv.ensure_list(cv.enum(AIRFLOW_HORIZONTAL_DIRECTION_OPTIONS, upper=True)),
|
cv.Optional(CONF_HORIZONTAL_AIRFLOW, default="LAST"): cv.ensure_list(cv.enum(AIRFLOW_HORIZONTAL_DIRECTION_OPTIONS, upper=True)),
|
||||||
cv.Optional(CONF_HORIZONTAL_SWING_MODE, default="LEFT_RIGHT"): cv.ensure_list(cv.enum(HORIZONTAL_SWING_DIRECTION_OPTIONS, upper=True)),
|
cv.Optional(CONF_HORIZONTAL_SWING_MODE, default="OFF"): cv.ensure_list(cv.enum(HORIZONTAL_SWING_DIRECTION_OPTIONS, upper=True)),
|
||||||
cv.Optional(CONF_SUPPORTED_PRESETS,default=["NONE","ECO","SLEEP","COMFORT",],): cv.ensure_list(cv.enum(SUPPORTED_CLIMATE_PRESETS_OPTIONS, upper=True)),
|
cv.Optional(CONF_SUPPORTED_PRESETS,default=["NONE","ECO","SLEEP","COMFORT",],): cv.ensure_list(cv.enum(SUPPORTED_CLIMATE_PRESETS_OPTIONS, upper=True)),
|
||||||
cv.Optional(CONF_SUPPORTED_SWING_MODES,default=["OFF","VERTICAL","HORIZONTAL","BOTH",],): cv.ensure_list(cv.enum(SUPPORTED_SWING_MODES_OPTIONS, upper=True)),
|
cv.Optional(CONF_SUPPORTED_SWING_MODES,default=["OFF","VERTICAL","HORIZONTAL","BOTH",],): cv.ensure_list(cv.enum(SUPPORTED_SWING_MODES_OPTIONS, upper=True)),
|
||||||
cv.Optional(CONF_SUPPORTED_MODES,default=["OFF","AUTO","COOL","HEAT","DRY","FAN_ONLY",],): cv.ensure_list(cv.enum(SUPPORTED_CLIMATE_MODES_OPTIONS, upper=True)),
|
cv.Optional(CONF_SUPPORTED_MODES,default=["OFF","AUTO","COOL","HEAT","DRY","FAN_ONLY",],): cv.ensure_list(cv.enum(SUPPORTED_CLIMATE_MODES_OPTIONS, upper=True)),
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* Create by Miguel Ángel López on 20/07/19
|
* Create by Miguel Ángel López on 20/07/19
|
||||||
* and modify by xaxexa
|
* and modify by xaxexa, edit for newer models by Kannix2005
|
||||||
* Refactoring & component making:
|
* Refactoring & component making:
|
||||||
* Соловей с паяльником 15.03.2024
|
* Соловей с паяльником 15.03.2024
|
||||||
**/
|
**/
|
||||||
#include "esphome.h"
|
#include "esphome.h"
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "tclac.h"
|
#include "tclac.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
namespace esphome{
|
namespace esphome{
|
||||||
namespace tclac{
|
namespace tclac{
|
||||||
@@ -24,11 +26,15 @@ ClimateTraits tclacClimate::traits() {
|
|||||||
traits.set_supported_fan_modes(this->supported_fan_modes_);
|
traits.set_supported_fan_modes(this->supported_fan_modes_);
|
||||||
traits.set_supported_swing_modes(this->supported_swing_modes_);
|
traits.set_supported_swing_modes(this->supported_swing_modes_);
|
||||||
|
|
||||||
traits.add_supported_mode(climate::CLIMATE_MODE_OFF); // Выключенный режим кондиционера доступен всегда
|
traits.add_supported_mode(climate::CLIMATE_MODE_OFF); // Off mode is always available
|
||||||
traits.add_supported_mode(climate::CLIMATE_MODE_AUTO); // Автоматический режим кондиционера тоже
|
traits.add_supported_mode(climate::CLIMATE_MODE_AUTO); // Auto mode is always available
|
||||||
traits.add_supported_fan_mode(climate::CLIMATE_FAN_AUTO); // Автоматический режим вентилятора доступен всегда
|
traits.add_supported_mode(climate::CLIMATE_MODE_COOL); // Cool mode is always available
|
||||||
traits.add_supported_swing_mode(climate::CLIMATE_SWING_OFF); // Выключенный режим качания заслонок доступен всегда
|
traits.add_supported_mode(climate::CLIMATE_MODE_HEAT); // Heat mode is always available
|
||||||
traits.add_supported_preset(ClimatePreset::CLIMATE_PRESET_NONE);// На всякий случай без предустановок
|
traits.add_supported_mode(climate::CLIMATE_MODE_DRY); // Dry mode is always available
|
||||||
|
traits.add_supported_mode(climate::CLIMATE_MODE_FAN_ONLY); // Fan only mode is also available
|
||||||
|
traits.add_supported_fan_mode(climate::CLIMATE_FAN_AUTO); // Auto fan mode is always available
|
||||||
|
traits.add_supported_swing_mode(climate::CLIMATE_SWING_OFF); // Swing off mode is always available
|
||||||
|
traits.add_supported_preset(ClimatePreset::CLIMATE_PRESET_NONE);// No preset just in case
|
||||||
|
|
||||||
return traits;
|
return traits;
|
||||||
}
|
}
|
||||||
@@ -36,6 +42,16 @@ ClimateTraits tclacClimate::traits() {
|
|||||||
|
|
||||||
void tclacClimate::setup() {
|
void tclacClimate::setup() {
|
||||||
|
|
||||||
|
//this->esphome::uart::UARTDevice::write_array(setup1, sizeof(setup1));
|
||||||
|
//this->esphome::uart::UARTDevice::flush();
|
||||||
|
//this->esphome::uart::UARTDevice::write_array(setup2, sizeof(setup2));
|
||||||
|
//this->esphome::uart::UARTDevice::flush();
|
||||||
|
//this->esphome::uart::UARTDevice::write_array(setup3, sizeof(setup3));
|
||||||
|
//this->esphome::uart::UARTDevice::flush();
|
||||||
|
|
||||||
|
target_temperature_set = 20;
|
||||||
|
target_temperature = 20;
|
||||||
|
restore_state_();
|
||||||
#ifdef CONF_RX_LED
|
#ifdef CONF_RX_LED
|
||||||
this->rx_led_pin_->setup();
|
this->rx_led_pin_->setup();
|
||||||
this->rx_led_pin_->digital_write(false);
|
this->rx_led_pin_->digital_write(false);
|
||||||
@@ -47,17 +63,17 @@ void tclacClimate::setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void tclacClimate::loop() {
|
void tclacClimate::loop() {
|
||||||
// Если в буфере UART что-то есть, то читаем это что-то
|
|
||||||
if (esphome::uart::UARTDevice::available() > 0) {
|
if (esphome::uart::UARTDevice::available() > 0) {
|
||||||
dataShow(0, true);
|
dataShow(0, true);
|
||||||
|
memset(dataRX, 0, sizeof(dataRX));
|
||||||
dataRX[0] = esphome::uart::UARTDevice::read();
|
dataRX[0] = esphome::uart::UARTDevice::read();
|
||||||
// Если принятый байт- не заголовок (0xBB), то просто покидаем цикл
|
// If the received byte is not the header (0xBB), just exit the loop
|
||||||
if (dataRX[0] != 0xBB) {
|
if (dataRX[0] != 0xBB) {
|
||||||
ESP_LOGD("TCL", "Wrong byte");
|
ESP_LOGD("TCL", "Wrong byte");
|
||||||
dataShow(0,0);
|
dataShow(0,0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// А вот если совпал заголовок (0xBB), то начинаем чтение по цепочке еще 4 байт
|
// If the header (0xBB) matches, start reading 4 more bytes in sequence
|
||||||
delay(5);
|
delay(5);
|
||||||
dataRX[1] = esphome::uart::UARTDevice::read();
|
dataRX[1] = esphome::uart::UARTDevice::read();
|
||||||
delay(5);
|
delay(5);
|
||||||
@@ -67,20 +83,25 @@ void tclacClimate::loop() {
|
|||||||
delay(5);
|
delay(5);
|
||||||
dataRX[4] = esphome::uart::UARTDevice::read();
|
dataRX[4] = esphome::uart::UARTDevice::read();
|
||||||
|
|
||||||
auto raw = getHex(dataRX, 5);
|
//auto raw = getHex(dataRX, 5);
|
||||||
|
|
||||||
ESP_LOGD("TCL", "first 5 byte : %s ", raw.c_str());
|
//ESP_LOGD("TCL", "first 5 byte : %s ", raw.c_str());
|
||||||
|
|
||||||
// Из первых 5 байт нам нужен пятый- он содержит длину сообщения
|
// From the first 5 bytes we need the fifth - it contains the message length
|
||||||
esphome::uart::UARTDevice::read_array(dataRX+5, dataRX[4]+1);
|
esphome::uart::UARTDevice::read_array(dataRX+5, dataRX[4]+1);
|
||||||
|
//int c = 0;
|
||||||
|
//while(esphome::uart::UARTDevice::available() != 0){
|
||||||
|
// esphome::uart::UARTDevice::read_byte(&dataRX[5+c]);
|
||||||
|
// c++;
|
||||||
|
//}
|
||||||
|
|
||||||
byte check = getChecksum(dataRX, sizeof(dataRX));
|
uint8_t check = getChecksum(dataRX, sizeof(dataRX));
|
||||||
|
|
||||||
raw = getHex(dataRX, sizeof(dataRX));
|
auto raw = getHex(dataRX, sizeof(dataRX));
|
||||||
|
|
||||||
ESP_LOGD("TCL", "RX full : %s ", raw.c_str());
|
//ESP_LOGD("TCL", "RX full : %s ", raw.c_str());
|
||||||
|
|
||||||
// Проверяем контрольную сумму
|
// Check the checksum
|
||||||
if (check != dataRX[60]) {
|
if (check != dataRX[60]) {
|
||||||
ESP_LOGD("TCL", "Invalid checksum %x", check);
|
ESP_LOGD("TCL", "Invalid checksum %x", check);
|
||||||
tclacClimate::dataShow(0,0);
|
tclacClimate::dataShow(0,0);
|
||||||
@@ -89,7 +110,7 @@ void tclacClimate::loop() {
|
|||||||
ESP_LOGD("TCL", "checksum OK %x", check);
|
ESP_LOGD("TCL", "checksum OK %x", check);
|
||||||
}
|
}
|
||||||
tclacClimate::dataShow(0,0);
|
tclacClimate::dataShow(0,0);
|
||||||
// Прочитав все из буфера приступаем к разбору данных
|
// After reading everything from the buffer, we proceed to parse the data
|
||||||
tclacClimate::readData();
|
tclacClimate::readData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,153 +118,273 @@ void tclacClimate::loop() {
|
|||||||
void tclacClimate::update() {
|
void tclacClimate::update() {
|
||||||
tclacClimate::dataShow(1,1);
|
tclacClimate::dataShow(1,1);
|
||||||
this->esphome::uart::UARTDevice::write_array(poll, sizeof(poll));
|
this->esphome::uart::UARTDevice::write_array(poll, sizeof(poll));
|
||||||
auto raw = tclacClimate::getHex(poll, sizeof(poll));
|
//const char* raw = tclacClimate::getHex(poll, sizeof(poll)).c_str();
|
||||||
ESP_LOGD("TCL", "chek status sended");
|
this->esphome::uart::UARTDevice::flush();
|
||||||
|
//delay(100);
|
||||||
|
//this->esphome::uart::UARTDevice::write_array(poll2, sizeof(poll2));
|
||||||
|
//this->esphome::uart::UARTDevice::flush();
|
||||||
|
//this->esphome::uart::UARTDevice::write_array(poll3, sizeof(poll3));
|
||||||
|
//this->esphome::uart::UARTDevice::flush();
|
||||||
|
|
||||||
tclacClimate::dataShow(1,0);
|
tclacClimate::dataShow(1,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tclacClimate::readData() {
|
void tclacClimate::readData() {
|
||||||
|
// BBx01x00x03x37x04x00x00x00x00x00x00x00x00x00x80x36x00x23x08x00x00x00x00x00x00x00x00x00x20x66xFFx42x00x50x21x21x21x00x00x80x00x00x00x00xE9x00x00x00x54x40x03x23x00x00x7Ax00x00x00x00xBA
|
||||||
current_temperature = float((( (dataRX[17] << 8) | dataRX[18] ) / 374 - 32)/1.8);
|
//current_temperature = float((( (dataRX[17] << 8) | dataRX[18] ) / 374 - 32)/1.8);
|
||||||
target_temperature = (dataRX[FAN_SPEED_POS] & SET_TEMP_MASK) + 16;
|
//target_temperature = (dataRX[FAN_SPEED_POS] & SET_TEMP_MASK) + 16;
|
||||||
|
//current_temperature = float((dataRX[29] | (dataRX[30] << 8))*0.001);
|
||||||
|
//auto current_temperature2 = float((( (dataRX[45] << 8) | dataRX[46] ) / 374 - 32)/1.8);
|
||||||
|
current_temperature = 256 - dataRX[45]; // 256-233 = 23°C (plausible!)
|
||||||
|
//this->current_temperature = current_temperature;
|
||||||
|
//target_temperature = 20;
|
||||||
|
|
||||||
|
//this->target_temperature = target_temperature_set;
|
||||||
|
|
||||||
|
//current_temperature = float((( (dataRX[17] << 8) | dataRX[18] ) / 374 - 32)/1.8);
|
||||||
|
//target_temperature = (dataRX[FAN_SPEED_POS] & SET_TEMP_MASK) + 16;
|
||||||
|
|
||||||
ESP_LOGD("TCL", "TEMP: %f ", current_temperature);
|
ESP_LOGD("TCL", "TEMP: %f ", current_temperature);
|
||||||
|
//ESP_LOGD("TCL", "TEMP: %f ", current_temperature2);
|
||||||
|
|
||||||
|
|
||||||
if (dataRX[MODE_POS] & ( 1 << 4)) {
|
if (dataRX[MODE_POS] & ( 1 << 4)) {
|
||||||
// Если кондиционер включен, то разбираем данные для отображения
|
// If the air conditioner is on, parse the data for display
|
||||||
// ESP_LOGD("TCL", "AC is on");
|
// ESP_LOGD("TCL", "AC is on");
|
||||||
uint8_t modeswitch = MODE_MASK & dataRX[MODE_POS];
|
uint8_t modeswitch = MODE_MASK & dataRX[MODE_POS];
|
||||||
uint8_t fanspeedswitch = FAN_SPEED_MASK & dataRX[FAN_SPEED_POS];
|
uint8_t fanspeedswitch = FAN_SPEED_MASK & dataRX[FAN_SPEED_POS];
|
||||||
uint8_t swingmodeswitch = SWING_MODE_MASK & dataRX[SWING_POS];
|
uint8_t swingmodeswitch = SWING_MODE_MASK & dataRX[SWING_POS];
|
||||||
|
|
||||||
switch (modeswitch) {
|
// switch (modeswitch) {
|
||||||
case MODE_AUTO:
|
// case MODE_AUTO:
|
||||||
mode = climate::CLIMATE_MODE_AUTO;
|
// mode = climate::CLIMATE_MODE_AUTO;
|
||||||
break;
|
// break;
|
||||||
case MODE_COOL:
|
// case MODE_COOL:
|
||||||
mode = climate::CLIMATE_MODE_COOL;
|
// mode = climate::CLIMATE_MODE_COOL;
|
||||||
break;
|
// break;
|
||||||
case MODE_DRY:
|
// case MODE_DRY:
|
||||||
mode = climate::CLIMATE_MODE_DRY;
|
// mode = climate::CLIMATE_MODE_DRY;
|
||||||
break;
|
// break;
|
||||||
case MODE_FAN_ONLY:
|
// case MODE_FAN_ONLY:
|
||||||
mode = climate::CLIMATE_MODE_FAN_ONLY;
|
// mode = climate::CLIMATE_MODE_FAN_ONLY;
|
||||||
break;
|
// break;
|
||||||
case MODE_HEAT:
|
// case MODE_HEAT:
|
||||||
mode = climate::CLIMATE_MODE_HEAT;
|
// mode = climate::CLIMATE_MODE_HEAT;
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
mode = climate::CLIMATE_MODE_AUTO;
|
// mode = climate::CLIMATE_MODE_OFF;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if ( dataRX[FAN_QUIET_POS] & FAN_QUIET) {
|
|
||||||
fan_mode = climate::CLIMATE_FAN_QUIET;
|
|
||||||
} else if (dataRX[MODE_POS] & FAN_DIFFUSE){
|
|
||||||
fan_mode = climate::CLIMATE_FAN_DIFFUSE;
|
|
||||||
} else {
|
|
||||||
switch (fanspeedswitch) {
|
|
||||||
case FAN_AUTO:
|
|
||||||
fan_mode = climate::CLIMATE_FAN_AUTO;
|
|
||||||
break;
|
|
||||||
case FAN_LOW:
|
|
||||||
fan_mode = climate::CLIMATE_FAN_LOW;
|
|
||||||
break;
|
|
||||||
case FAN_MIDDLE:
|
|
||||||
fan_mode = climate::CLIMATE_FAN_MIDDLE;
|
|
||||||
break;
|
|
||||||
case FAN_MEDIUM:
|
|
||||||
fan_mode = climate::CLIMATE_FAN_MEDIUM;
|
|
||||||
break;
|
|
||||||
case FAN_HIGH:
|
|
||||||
fan_mode = climate::CLIMATE_FAN_HIGH;
|
|
||||||
break;
|
|
||||||
case FAN_FOCUS:
|
|
||||||
fan_mode = climate::CLIMATE_FAN_FOCUS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fan_mode = climate::CLIMATE_FAN_AUTO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (swingmodeswitch) {
|
// //OVERRIDE
|
||||||
case SWING_OFF:
|
|
||||||
swing_mode = climate::CLIMATE_SWING_OFF;
|
// switch (dataRX[MODE_POS])
|
||||||
break;
|
// {
|
||||||
case SWING_HORIZONTAL:
|
// case 0x08:
|
||||||
swing_mode = climate::CLIMATE_SWING_HORIZONTAL;
|
// //auto
|
||||||
break;
|
// mode = climate::CLIMATE_MODE_AUTO;
|
||||||
case SWING_VERTICAL:
|
// break;
|
||||||
swing_mode = climate::CLIMATE_SWING_VERTICAL;
|
|
||||||
break;
|
|
||||||
case SWING_BOTH:
|
|
||||||
swing_mode = climate::CLIMATE_SWING_BOTH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обработка данных о пресете
|
// case 0x07:
|
||||||
preset = ClimatePreset::CLIMATE_PRESET_NONE;
|
// //Lüfter
|
||||||
if (dataRX[7] & (1 << 6)){
|
// mode = climate::CLIMATE_MODE_FAN_ONLY;
|
||||||
preset = ClimatePreset::CLIMATE_PRESET_ECO;
|
// break;
|
||||||
} else if (dataRX[9] & (1 << 2)){
|
|
||||||
preset = ClimatePreset::CLIMATE_PRESET_COMFORT;
|
|
||||||
} else if (dataRX[19] & (1 << 0)){
|
|
||||||
preset = ClimatePreset::CLIMATE_PRESET_SLEEP;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
// case 0x02:
|
||||||
// Если кондиционер выключен, то все режимы показываются, как выключенные
|
// //Trocknen
|
||||||
mode = climate::CLIMATE_MODE_OFF;
|
// mode = climate::CLIMATE_MODE_DRY;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case 0x01:
|
||||||
|
// //Heizen
|
||||||
|
// mode = climate::CLIMATE_MODE_HEAT;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case 0x03:
|
||||||
|
// //Kühlen
|
||||||
|
// mode = climate::CLIMATE_MODE_COOL;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if ( dataRX[FAN_QUIET_POS] & FAN_QUIET) {
|
||||||
|
// fan_mode = climate::CLIMATE_FAN_QUIET;
|
||||||
|
// } else if (dataRX[MODE_POS] & FAN_DIFFUSE){
|
||||||
|
// fan_mode = climate::CLIMATE_FAN_DIFFUSE;
|
||||||
|
// } else {
|
||||||
|
// switch (fanspeedswitch) {
|
||||||
|
// case FAN_AUTO:
|
||||||
|
// fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||||
|
// break;
|
||||||
|
// case FAN_LOW:
|
||||||
|
// fan_mode = climate::CLIMATE_FAN_LOW;
|
||||||
|
// break;
|
||||||
|
// case FAN_MIDDLE:
|
||||||
|
// fan_mode = climate::CLIMATE_FAN_MIDDLE;
|
||||||
|
// break;
|
||||||
|
// case FAN_MEDIUM:
|
||||||
|
// fan_mode = climate::CLIMATE_FAN_MEDIUM;
|
||||||
|
// break;
|
||||||
|
// case FAN_HIGH:
|
||||||
|
// fan_mode = climate::CLIMATE_FAN_HIGH;
|
||||||
|
// break;
|
||||||
|
// case FAN_FOCUS:
|
||||||
|
// fan_mode = climate::CLIMATE_FAN_FOCUS;
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// switch (swingmodeswitch) {
|
||||||
|
// case SWING_OFF:
|
||||||
|
// swing_mode = climate::CLIMATE_SWING_OFF;
|
||||||
|
// break;
|
||||||
|
// case SWING_HORIZONTAL:
|
||||||
|
// swing_mode = climate::CLIMATE_SWING_HORIZONTAL;
|
||||||
|
// break;
|
||||||
|
// case SWING_VERTICAL:
|
||||||
|
// swing_mode = climate::CLIMATE_SWING_VERTICAL;
|
||||||
|
// break;
|
||||||
|
// case SWING_BOTH:
|
||||||
|
// swing_mode = climate::CLIMATE_SWING_BOTH;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Обработка данных о пресете
|
||||||
|
// preset = ClimatePreset::CLIMATE_PRESET_NONE;
|
||||||
|
// if (dataRX[7] & (1 << 6)){
|
||||||
|
// preset = ClimatePreset::CLIMATE_PRESET_ECO;
|
||||||
|
// } else if (dataRX[9] & (1 << 2)){
|
||||||
|
// preset = ClimatePreset::CLIMATE_PRESET_COMFORT;
|
||||||
|
// } else if (dataRX[19] & (1 << 0)){
|
||||||
|
// preset = ClimatePreset::CLIMATE_PRESET_SLEEP;
|
||||||
|
// }
|
||||||
|
|
||||||
|
} //else {
|
||||||
|
// If the air conditioner is off, all modes are shown as off
|
||||||
|
//mode = climate::CLIMATE_MODE_OFF;
|
||||||
//fan_mode = climate::CLIMATE_FAN_OFF;
|
//fan_mode = climate::CLIMATE_FAN_OFF;
|
||||||
swing_mode = climate::CLIMATE_SWING_OFF;
|
//swing_mode = climate::CLIMATE_SWING_OFF;
|
||||||
preset = ClimatePreset::CLIMATE_PRESET_NONE;
|
//preset = ClimatePreset::CLIMATE_PRESET_NONE;
|
||||||
}
|
//}
|
||||||
// Публикуем данные
|
// Publish the data
|
||||||
this->publish_state();
|
this->publish_state();
|
||||||
allow_take_control = true;
|
allow_take_control = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Climate control
|
// Climate control
|
||||||
void tclacClimate::control(const ClimateCall &call) {
|
void tclacClimate::control(const ClimateCall &call) {
|
||||||
// Запрашиваем данные из переключателя режимов работы кондиционера
|
// Request data from the AC mode switch
|
||||||
if (call.get_mode().has_value()){
|
if (call.get_mode().has_value()){
|
||||||
switch_climate_mode = call.get_mode().value();
|
switch_climate_mode = call.get_mode().value();
|
||||||
ESP_LOGD("TCL", "Get MODE from call");
|
|
||||||
} else {
|
switch (switch_climate_mode) {
|
||||||
switch_climate_mode = mode;
|
case 6:
|
||||||
ESP_LOGD("TCL", "Get MODE from AC");
|
mode = climate::CLIMATE_MODE_AUTO;
|
||||||
}
|
break;
|
||||||
|
case 2:
|
||||||
// Запрашиваем данные из переключателя предустановок кондиционера
|
mode = climate::CLIMATE_MODE_COOL;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
mode = climate::CLIMATE_MODE_DRY;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
mode = climate::CLIMATE_MODE_FAN_ONLY;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
mode = climate::CLIMATE_MODE_HEAT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mode = climate::CLIMATE_MODE_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD("TCL", "Get MODE %i from call", (int) mode);
|
||||||
|
} //else {
|
||||||
|
//switch_climate_mode = mode;
|
||||||
|
//ESP_LOGD("TCL", "Get MODE from AC");
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Request data from the AC preset switch
|
||||||
if (call.get_preset().has_value()){
|
if (call.get_preset().has_value()){
|
||||||
switch_preset = call.get_preset().value();
|
switch_preset = call.get_preset().value();
|
||||||
} else {
|
|
||||||
switch_preset = preset.value();
|
switch (switch_preset){
|
||||||
}
|
case 0:
|
||||||
|
preset = climate::CLIMATE_PRESET_NONE;
|
||||||
|
case 5:
|
||||||
|
preset = climate::CLIMATE_PRESET_ECO;
|
||||||
|
case 6:
|
||||||
|
preset = climate::CLIMATE_PRESET_SLEEP;
|
||||||
|
case 4:
|
||||||
|
preset = climate::CLIMATE_PRESET_COMFORT;
|
||||||
|
}
|
||||||
|
} //else {
|
||||||
|
//switch_preset = preset.value();
|
||||||
|
//}
|
||||||
|
|
||||||
// Запрашиваем данные из переключателя режимов вентилятора
|
// Request data from the fan mode switch
|
||||||
if (call.get_fan_mode().has_value()){
|
if (call.get_fan_mode().has_value()){
|
||||||
switch_fan_mode = call.get_fan_mode().value();
|
switch_fan_mode = call.get_fan_mode().value();
|
||||||
} else {
|
|
||||||
switch_fan_mode = fan_mode.value();
|
if (mode != climate::CLIMATE_MODE_OFF){
|
||||||
}
|
switch (switch_fan_mode) {
|
||||||
|
case 2:
|
||||||
|
fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||||
|
case 3:
|
||||||
|
fan_mode = climate::CLIMATE_FAN_LOW;
|
||||||
|
case 6:
|
||||||
|
fan_mode = climate::CLIMATE_FAN_MIDDLE;
|
||||||
|
case 4:
|
||||||
|
fan_mode = climate::CLIMATE_FAN_MEDIUM;
|
||||||
|
case 5:
|
||||||
|
fan_mode = climate::CLIMATE_FAN_HIGH;
|
||||||
|
case 7:
|
||||||
|
fan_mode = climate::CLIMATE_FAN_FOCUS;
|
||||||
|
default:
|
||||||
|
fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fan_mode = climate::CLIMATE_FAN_OFF;
|
||||||
|
}
|
||||||
|
} //else {
|
||||||
|
// switch_fan_mode = fan_mode.value();
|
||||||
|
//}
|
||||||
|
|
||||||
// Запрашиваем данные из переключателя режимов качания заслонок
|
// Request data from the swing mode switch
|
||||||
if (call.get_swing_mode().has_value()){
|
if (call.get_swing_mode().has_value()){
|
||||||
switch_swing_mode = call.get_swing_mode().value();
|
switch_swing_mode = call.get_swing_mode().value();
|
||||||
} else {
|
|
||||||
// А если в переключателе пусто- заполняем значением из последнего опроса состояния. Типа, ничего не поменялось.
|
switch (switch_swing_mode) {
|
||||||
switch_swing_mode = swing_mode;
|
case 0:
|
||||||
}
|
swing_mode = climate::CLIMATE_SWING_OFF;
|
||||||
|
case 3:
|
||||||
|
swing_mode = climate::CLIMATE_SWING_HORIZONTAL;
|
||||||
|
case 2:
|
||||||
|
swing_mode = climate::CLIMATE_SWING_VERTICAL;
|
||||||
|
case 1:
|
||||||
|
swing_mode = climate::CLIMATE_SWING_BOTH;
|
||||||
|
default:
|
||||||
|
swing_mode = climate::CLIMATE_SWING_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //else {
|
||||||
|
// If the switch is empty, fill with the value from the last state poll. Like, nothing changed.
|
||||||
|
//switch_swing_mode = swing_mode;
|
||||||
|
//}
|
||||||
|
|
||||||
// Расчет температуры
|
// Calculate temperature
|
||||||
if (call.get_target_temperature().has_value()) {
|
if (call.get_target_temperature().has_value()) {
|
||||||
target_temperature_set = 31-(int)call.get_target_temperature().value();
|
target_temperature_set = (int)call.get_target_temperature().value();
|
||||||
} else {
|
target_temperature = target_temperature_set;
|
||||||
target_temperature_set = 31-(int)target_temperature;
|
} //else {
|
||||||
}
|
//target_temperature_set = 111 - (int)target_temperature;
|
||||||
|
//}
|
||||||
|
|
||||||
is_call_control = true;
|
is_call_control = true;
|
||||||
takeControl();
|
takeControl();
|
||||||
|
this->publish_state();
|
||||||
allow_take_control = true;
|
allow_take_control = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,10 +406,10 @@ void tclacClimate::takeControl() {
|
|||||||
switch_preset = preset.value();
|
switch_preset = preset.value();
|
||||||
switch_fan_mode = fan_mode.value();
|
switch_fan_mode = fan_mode.value();
|
||||||
switch_swing_mode = swing_mode;
|
switch_swing_mode = swing_mode;
|
||||||
target_temperature_set = 31-(int)target_temperature;
|
target_temperature_set = (int)target_temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Включаем или отключаем пищалку в зависимости от переключателя в настройках
|
// Enable or disable the beeper depending on the setting switch
|
||||||
if (beeper_status_){
|
if (beeper_status_){
|
||||||
ESP_LOGD("TCL", "Beep mode ON");
|
ESP_LOGD("TCL", "Beep mode ON");
|
||||||
dataTX[7] += 0b00100000;
|
dataTX[7] += 0b00100000;
|
||||||
@@ -277,20 +418,20 @@ void tclacClimate::takeControl() {
|
|||||||
dataTX[7] += 0b00000000;
|
dataTX[7] += 0b00000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Включаем или отключаем дисплей на кондиционере в зависимости от переключателя в настройках
|
// Enable or disable the AC display depending on the setting switch
|
||||||
// Включаем дисплей только если кондиционер в одном из рабочих режимов
|
// Only enable the display if the AC is in one of the operating modes
|
||||||
|
|
||||||
// ВНИМАНИЕ! При выключении дисплея кондиционер сам принудительно переходит в автоматический режим!
|
// WARNING! When the display is turned off, the AC automatically switches to automatic mode!
|
||||||
|
|
||||||
if ((display_status_) && (switch_climate_mode != climate::CLIMATE_MODE_OFF)){
|
if ((display_status_) && (switch_climate_mode != climate::CLIMATE_MODE_OFF)){
|
||||||
ESP_LOGD("TCL", "Dispaly turn ON");
|
ESP_LOGD("TCL", "Display turn ON");
|
||||||
dataTX[7] += 0b01000000;
|
dataTX[7] += 0b01000000;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGD("TCL", "Dispaly turn OFF");
|
ESP_LOGD("TCL", "Display turn OFF");
|
||||||
dataTX[7] += 0b00000000;
|
dataTX[7] += 0b00000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Настраиваем режим работы кондиционера
|
// Configure the AC operating mode
|
||||||
switch (switch_climate_mode) {
|
switch (switch_climate_mode) {
|
||||||
case climate::CLIMATE_MODE_OFF:
|
case climate::CLIMATE_MODE_OFF:
|
||||||
dataTX[7] += 0b00000000;
|
dataTX[7] += 0b00000000;
|
||||||
@@ -318,7 +459,8 @@ void tclacClimate::takeControl() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Настраиваем режим вентилятора
|
|
||||||
|
// Configure the fan mode
|
||||||
switch(switch_fan_mode) {
|
switch(switch_fan_mode) {
|
||||||
case climate::CLIMATE_FAN_AUTO:
|
case climate::CLIMATE_FAN_AUTO:
|
||||||
dataTX[8] += 0b00000000;
|
dataTX[8] += 0b00000000;
|
||||||
@@ -354,7 +496,7 @@ void tclacClimate::takeControl() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Устанавливаем режим качания заслонок
|
// Set the damper swing mode
|
||||||
switch(switch_swing_mode) {
|
switch(switch_swing_mode) {
|
||||||
case climate::CLIMATE_SWING_OFF:
|
case climate::CLIMATE_SWING_OFF:
|
||||||
dataTX[10] += 0b00000000;
|
dataTX[10] += 0b00000000;
|
||||||
@@ -374,7 +516,7 @@ void tclacClimate::takeControl() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Устанавливаем предустановки кондиционера
|
// Set the AC presets
|
||||||
switch(switch_preset) {
|
switch(switch_preset) {
|
||||||
case ClimatePreset::CLIMATE_PRESET_NONE:
|
case ClimatePreset::CLIMATE_PRESET_NONE:
|
||||||
break;
|
break;
|
||||||
@@ -389,42 +531,46 @@ void tclacClimate::takeControl() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Режим заслонок
|
//Damper mode
|
||||||
// Вертикальная заслонка
|
// Vertical damper
|
||||||
// Качание вертикальной заслонки [10 байт, маска 00111000]:
|
// Vertical damper swing [byte 10, mask 00111000]:
|
||||||
// 000 - Качание отключено, заслонка в последней позиции или в фиксации
|
// 000 - Swing off, damper in last position or fixed
|
||||||
// 111 - Качание включено в выбранном режиме
|
// 111 - Swing on in selected mode
|
||||||
// Режим качания вертикальной заслонки (режим фиксации заслонки роли не играет, если качание включено) [32 байт, маска 00011000]:
|
// Vertical damper swing mode (fixed mode doesn't matter if swing is on) [byte 32, mask 00011000]:
|
||||||
// 01 - качание сверху вниз, ПО УМОЛЧАНИЮ
|
// 01 - swing up-down, DEFAULT
|
||||||
// 10 - качание в верхней половине
|
// 10 - swing in upper half
|
||||||
// 11 - качание в нижней половине
|
// 11 - swing in lower half
|
||||||
// Режим фиксации заслонки (режим качания заслонки роли не играет, если качание выключено) [32 байт, маска 00000111]:
|
// Damper fixed mode (swing mode doesn't matter if swing is off) [byte 32, mask 00000111]:
|
||||||
// 000 - нет фиксации, ПО УМОЛЧАНИЮ
|
// 000 - no fixation, DEFAULT
|
||||||
// 001 - фиксация вверху
|
// 001 - fixed at top
|
||||||
// 010 - фиксация между верхом и серединой
|
// 010 - fixed between top and center
|
||||||
// 011 - фиксация в середине
|
// 011 - fixed in center
|
||||||
// 100 - фиксация между серединой и низом
|
// 100 - fixed between center and bottom
|
||||||
// 101 - фиксация внизу
|
// 101 - fixed at bottom
|
||||||
// Горизонтальные заслонки
|
// Horizontal dampers
|
||||||
// Качание горизонтальных заслонок [11 байт, маска 00001000]:
|
// Horizontal damper swing [byte 11, mask 00001000]:
|
||||||
// 0 - Качание отключено, заслонки в последней позиции или в фиксации
|
// 0 - Swing off, dampers in last position or fixed
|
||||||
// 1 - Качание включено в выбранном режиме
|
// 1 - Swing on in selected mode
|
||||||
// Режим качания горизонтальных заслонок (режим фиксации заслонок роли не играет, если качание включено) [33 байт, маска 00111000]:
|
// Horizontal damper swing mode (fixed mode doesn't matter if swing is on) [byte 33, mask 00111000]:
|
||||||
// 001 - качание слева направо, ПО УМОЛЧАНИЮ
|
// 001 - swing left-right, DEFAULT
|
||||||
// 010 - качание слева
|
// 010 - swing left
|
||||||
// 011 - качание по середине
|
// 011 - swing center
|
||||||
// 100 - качание справа
|
// 100 - swing right
|
||||||
// Режим фиксации горизонтальных заслонок (режим качания заслонок роли не играет, если качание выключено) [33 байт, маска 00000111]:
|
// Horizontal damper fixed mode (swing mode doesn't matter if swing is off) [byte 33, mask 00000111]:
|
||||||
// 000 - нет фиксации, ПО УМОЛЧАНИЮ
|
// 000 - no fixation, DEFAULT
|
||||||
// 001 - фиксация слева
|
// 001 - fixed left
|
||||||
// 010 - фиксация между левой стороной и серединой
|
// 010 - fixed between left and center
|
||||||
// 011 - фиксация в середине
|
// 011 - fixed in center
|
||||||
// 100 - фиксация между серединой и правой стороной
|
// 100 - fixed between center and right
|
||||||
// 101 - фиксация справа
|
// 101 - fixed right
|
||||||
|
|
||||||
|
|
||||||
// Устанавливаем режим для качания вертикальной заслонки
|
// Set the vertical damper swing mode
|
||||||
switch(vertical_swing_direction_) {
|
switch(vertical_swing_direction_) {
|
||||||
|
case VerticalSwingDirection::OFF:
|
||||||
|
dataTX[32] += 0b00000000;
|
||||||
|
ESP_LOGD("TCL", "Vertical swing: off");
|
||||||
|
break;
|
||||||
case VerticalSwingDirection::UP_DOWN:
|
case VerticalSwingDirection::UP_DOWN:
|
||||||
dataTX[32] += 0b00001000;
|
dataTX[32] += 0b00001000;
|
||||||
ESP_LOGD("TCL", "Vertical swing: up-down");
|
ESP_LOGD("TCL", "Vertical swing: up-down");
|
||||||
@@ -438,8 +584,12 @@ void tclacClimate::takeControl() {
|
|||||||
ESP_LOGD("TCL", "Vertical swing: downer");
|
ESP_LOGD("TCL", "Vertical swing: downer");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Устанавливаем режим для качания горизонтальных заслонок
|
// Set the horizontal damper swing mode
|
||||||
switch(horizontal_swing_direction_) {
|
switch(horizontal_swing_direction_) {
|
||||||
|
case HorizontalSwingDirection::OFF:
|
||||||
|
dataTX[33] += 0b00000000;
|
||||||
|
ESP_LOGD("TCL", "Horizontal swing: left-right");
|
||||||
|
break;
|
||||||
case HorizontalSwingDirection::LEFT_RIGHT:
|
case HorizontalSwingDirection::LEFT_RIGHT:
|
||||||
dataTX[33] += 0b00001000;
|
dataTX[33] += 0b00001000;
|
||||||
ESP_LOGD("TCL", "Horizontal swing: left-right");
|
ESP_LOGD("TCL", "Horizontal swing: left-right");
|
||||||
@@ -457,7 +607,7 @@ void tclacClimate::takeControl() {
|
|||||||
ESP_LOGD("TCL", "Horizontal swing: righter");
|
ESP_LOGD("TCL", "Horizontal swing: righter");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Устанавливаем положение фиксации вертикальной заслонки
|
// Set the vertical damper fixed position
|
||||||
switch(vertical_direction_) {
|
switch(vertical_direction_) {
|
||||||
case AirflowVerticalDirection::LAST:
|
case AirflowVerticalDirection::LAST:
|
||||||
dataTX[32] += 0b00000000;
|
dataTX[32] += 0b00000000;
|
||||||
@@ -484,7 +634,7 @@ void tclacClimate::takeControl() {
|
|||||||
ESP_LOGD("TCL", "Vertical fix: down");
|
ESP_LOGD("TCL", "Vertical fix: down");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Устанавливаем положение фиксации горизонтальных заслонок
|
// Set the horizontal damper fixed position
|
||||||
switch(horizontal_direction_) {
|
switch(horizontal_direction_) {
|
||||||
case AirflowHorizontalDirection::LAST:
|
case AirflowHorizontalDirection::LAST:
|
||||||
dataTX[33] += 0b00000000;
|
dataTX[33] += 0b00000000;
|
||||||
@@ -512,15 +662,15 @@ void tclacClimate::takeControl() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Установка температуры
|
// Set temperature
|
||||||
dataTX[9] = target_temperature_set;
|
dataTX[9] = 111 - target_temperature_set;
|
||||||
|
|
||||||
// Собираем массив байт для отправки в кондиционер
|
// Assemble the byte array to send to the AC
|
||||||
dataTX[0] = 0xBB; //стартовый байт заголовка
|
dataTX[0] = 0xBB; // Header start byte
|
||||||
dataTX[1] = 0x00; //стартовый байт заголовка
|
dataTX[1] = 0x00; // Header start byte
|
||||||
dataTX[2] = 0x01; //стартовый байт заголовка
|
dataTX[2] = 0x01; // Header start byte
|
||||||
dataTX[3] = 0x03; //0x03 - управление, 0x04 - опрос
|
dataTX[3] = 0x03; // 0x03 - control, 0x04 - poll
|
||||||
dataTX[4] = 0x20; //0x20 - управление, 0x19 - опрос
|
dataTX[4] = 0x20; // 0x20 - control, 0x19 - poll
|
||||||
dataTX[5] = 0x03; //??
|
dataTX[5] = 0x03; //??
|
||||||
dataTX[6] = 0x01; //??
|
dataTX[6] = 0x01; //??
|
||||||
//dataTX[7] = 0x64; //eco,display,beep,ontimerenable, offtimerenable,power,0,0
|
//dataTX[7] = 0x64; //eco,display,beep,ontimerenable, offtimerenable,power,0,0
|
||||||
@@ -535,7 +685,7 @@ void tclacClimate::takeControl() {
|
|||||||
dataTX[16] = 0x00; //??
|
dataTX[16] = 0x00; //??
|
||||||
dataTX[17] = 0x00; //??
|
dataTX[17] = 0x00; //??
|
||||||
dataTX[18] = 0x00; //??
|
dataTX[18] = 0x00; //??
|
||||||
//dataTX[19] = 0x00; //sleep on = 1 off=0
|
//dataTX[19] = 0x00; //sleep on = 1 off=0 --- 0,0,0,0,0,0,0,1 = sleep on; 0,0,0,1,0,0,0,0 = self clean on
|
||||||
dataTX[20] = 0x00; //??
|
dataTX[20] = 0x00; //??
|
||||||
dataTX[21] = 0x00; //??
|
dataTX[21] = 0x00; //??
|
||||||
dataTX[22] = 0x00; //??
|
dataTX[22] = 0x00; //??
|
||||||
@@ -545,14 +695,15 @@ void tclacClimate::takeControl() {
|
|||||||
dataTX[26] = 0x00; //??
|
dataTX[26] = 0x00; //??
|
||||||
dataTX[27] = 0x00; //??
|
dataTX[27] = 0x00; //??
|
||||||
dataTX[28] = 0x00; //??
|
dataTX[28] = 0x00; //??
|
||||||
|
dataTX[29] = 0x20; //??
|
||||||
dataTX[30] = 0x00; //??
|
dataTX[30] = 0x00; //??
|
||||||
dataTX[31] = 0x00; //??
|
dataTX[31] = 0x00; //??
|
||||||
//dataTX[32] = 0x00; //0,0,0,режим вертикального качания(2),режим вертикальной фиксации(3)
|
//dataTX[32] = 0x00; //0,0,0,vertical swing mode(2), vertical fixed position(3)
|
||||||
//dataTX[33] = 0x00; //0,0,режим горизонтального качания(3),режим горизонтальной фиксации(3)
|
//dataTX[33] = 0x00; //0,0,vertical swing mode(2), vertical fixed position(3)
|
||||||
dataTX[34] = 0x00; //??
|
dataTX[34] = 0x00; //??
|
||||||
dataTX[35] = 0x00; //??
|
dataTX[35] = 0x00; //??
|
||||||
dataTX[36] = 0x00; //??
|
dataTX[36] = 0x00; //??
|
||||||
dataTX[37] = 0xFF; //Контрольная сумма
|
dataTX[37] = 0xFF; //Checksum
|
||||||
dataTX[37] = tclacClimate::getChecksum(dataTX, sizeof(dataTX));
|
dataTX[37] = tclacClimate::getChecksum(dataTX, sizeof(dataTX));
|
||||||
|
|
||||||
tclacClimate::sendData(dataTX, sizeof(dataTX));
|
tclacClimate::sendData(dataTX, sizeof(dataTX));
|
||||||
@@ -560,38 +711,48 @@ void tclacClimate::takeControl() {
|
|||||||
is_call_control = false;
|
is_call_control = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Отправка данных в кондиционер
|
// Send data to the AC
|
||||||
void tclacClimate::sendData(byte * message, byte size) {
|
void tclacClimate::sendData(uint8_t * message, uint8_t size) {
|
||||||
tclacClimate::dataShow(1,1);
|
tclacClimate::dataShow(1,1);
|
||||||
//Serial.write(message, size);
|
//Serial.write(message, size);
|
||||||
this->esphome::uart::UARTDevice::write_array(message, size);
|
this->esphome::uart::UARTDevice::write_array(message, size);
|
||||||
auto raw = getHex(message, size);
|
//auto raw = getHex(message, size);
|
||||||
|
ESP_LOGD("TCL", "Message sent to TCL...");
|
||||||
ESP_LOGD("TCL", "TX full : %s ", raw.c_str());
|
|
||||||
ESP_LOGD("TCL", "Message to TCL sended...");
|
|
||||||
tclacClimate::dataShow(1,0);
|
tclacClimate::dataShow(1,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Преобразование байта в читабельный формат
|
// Convert byte to readable format
|
||||||
String tclacClimate::getHex(byte *message, byte size) {
|
String tclacClimate::getHex(uint8_t *message, uint8_t size) {
|
||||||
String raw;
|
std::ostringstream oss;
|
||||||
for (int i = 0; i < size; i++) {
|
// print each byte as two uppercase hex digits
|
||||||
raw += "\n" + String(message[i]);
|
for (uint8_t i = 0; i < size; ++i) {
|
||||||
|
oss << std::hex
|
||||||
|
<< std::uppercase
|
||||||
|
<< std::setw(2)
|
||||||
|
<< std::setfill('0')
|
||||||
|
<< static_cast<int>(message[i]);
|
||||||
|
if (i + 1 < size)
|
||||||
|
oss << ' '; // optional separator
|
||||||
}
|
}
|
||||||
raw.toUpperCase();
|
// grab the std::string, ensure uppercase
|
||||||
return raw;
|
std::string s = oss.str();
|
||||||
|
// (oss.str() is already uppercase thanks to std::uppercase, so
|
||||||
|
// this transform is optional)
|
||||||
|
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
|
||||||
|
// convert to esphome::String and return
|
||||||
|
return String(s.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Вычисление контрольной суммы
|
// Calculate checksum
|
||||||
byte tclacClimate::getChecksum(const byte * message, size_t size) {
|
uint8_t tclacClimate::getChecksum(const uint8_t * message, size_t size) {
|
||||||
byte position = size - 1;
|
uint8_t position = size - 1;
|
||||||
byte crc = 0;
|
uint8_t crc = 0;
|
||||||
for (int i = 0; i < position; i++)
|
for (int i = 0; i < position; i++)
|
||||||
crc ^= message[i];
|
crc ^= message[i];
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Мигаем светодиодами
|
// Blink LEDs
|
||||||
void tclacClimate::dataShow(bool flow, bool shine) {
|
void tclacClimate::dataShow(bool flow, bool shine) {
|
||||||
if (module_display_status_){
|
if (module_display_status_){
|
||||||
if (flow == 0){
|
if (flow == 0){
|
||||||
@@ -619,9 +780,9 @@ void tclacClimate::dataShow(bool flow, bool shine) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Действия с данными из конфига
|
// Actions with data from config
|
||||||
|
|
||||||
// Получение состояния пищалки
|
// Get beeper state
|
||||||
void tclacClimate::set_beeper_state(bool state) {
|
void tclacClimate::set_beeper_state(bool state) {
|
||||||
this->beeper_status_ = state;
|
this->beeper_status_ = state;
|
||||||
if (force_mode_status_){
|
if (force_mode_status_){
|
||||||
@@ -630,7 +791,7 @@ void tclacClimate::set_beeper_state(bool state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Получение состояния дисплея кондиционера
|
// Get AC display state
|
||||||
void tclacClimate::set_display_state(bool state) {
|
void tclacClimate::set_display_state(bool state) {
|
||||||
this->display_status_ = state;
|
this->display_status_ = state;
|
||||||
if (force_mode_status_){
|
if (force_mode_status_){
|
||||||
@@ -639,27 +800,27 @@ void tclacClimate::set_display_state(bool state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Получение состояния режима принудительного применения настроек
|
// Get forced settings application mode state
|
||||||
void tclacClimate::set_force_mode_state(bool state) {
|
void tclacClimate::set_force_mode_state(bool state) {
|
||||||
this->force_mode_status_ = state;
|
this->force_mode_status_ = state;
|
||||||
}
|
}
|
||||||
// Получение пина светодиода приема данных
|
// Get receive data LED pin
|
||||||
#ifdef CONF_RX_LED
|
#ifdef CONF_RX_LED
|
||||||
void tclacClimate::set_rx_led_pin(GPIOPin *rx_led_pin) {
|
void tclacClimate::set_rx_led_pin(GPIOPin *rx_led_pin) {
|
||||||
this->rx_led_pin_ = rx_led_pin;
|
this->rx_led_pin_ = rx_led_pin;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Получение пина светодиода передачи данных
|
// Get transmit data LED pin
|
||||||
#ifdef CONF_TX_LED
|
#ifdef CONF_TX_LED
|
||||||
void tclacClimate::set_tx_led_pin(GPIOPin *tx_led_pin) {
|
void tclacClimate::set_tx_led_pin(GPIOPin *tx_led_pin) {
|
||||||
this->tx_led_pin_ = tx_led_pin;
|
this->tx_led_pin_ = tx_led_pin;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Получение состояния светодиодов связи модуля
|
// Get module communication LED state
|
||||||
void tclacClimate::set_module_display_state(bool state) {
|
void tclacClimate::set_module_display_state(bool state) {
|
||||||
this->module_display_status_ = state;
|
this->module_display_status_ = state;
|
||||||
}
|
}
|
||||||
// Получение режима фиксации вертикальной заслонки
|
// Get vertical damper fixed mode
|
||||||
void tclacClimate::set_vertical_airflow(AirflowVerticalDirection direction) {
|
void tclacClimate::set_vertical_airflow(AirflowVerticalDirection direction) {
|
||||||
this->vertical_direction_ = direction;
|
this->vertical_direction_ = direction;
|
||||||
if (force_mode_status_){
|
if (force_mode_status_){
|
||||||
@@ -668,7 +829,7 @@ void tclacClimate::set_vertical_airflow(AirflowVerticalDirection direction) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Получение режима фиксации горизонтальных заслонок
|
// Get horizontal damper fixed mode
|
||||||
void tclacClimate::set_horizontal_airflow(AirflowHorizontalDirection direction) {
|
void tclacClimate::set_horizontal_airflow(AirflowHorizontalDirection direction) {
|
||||||
this->horizontal_direction_ = direction;
|
this->horizontal_direction_ = direction;
|
||||||
if (force_mode_status_){
|
if (force_mode_status_){
|
||||||
@@ -677,7 +838,7 @@ void tclacClimate::set_horizontal_airflow(AirflowHorizontalDirection direction)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Получение режима качания вертикальной заслонки
|
// Get vertical damper swing mode
|
||||||
void tclacClimate::set_vertical_swing_direction(VerticalSwingDirection direction) {
|
void tclacClimate::set_vertical_swing_direction(VerticalSwingDirection direction) {
|
||||||
this->vertical_swing_direction_ = direction;
|
this->vertical_swing_direction_ = direction;
|
||||||
if (force_mode_status_){
|
if (force_mode_status_){
|
||||||
@@ -686,11 +847,11 @@ void tclacClimate::set_vertical_swing_direction(VerticalSwingDirection direction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Получение доступных режимов работы кондиционера
|
// Get supported AC operating modes
|
||||||
void tclacClimate::set_supported_modes(const std::set<climate::ClimateMode> &modes) {
|
void tclacClimate::set_supported_modes(const std::set<climate::ClimateMode> &modes) {
|
||||||
this->supported_modes_ = modes;
|
this->supported_modes_ = modes;
|
||||||
}
|
}
|
||||||
// Получение режима качания горизонтальных заслонок
|
// Get horizontal damper swing mode
|
||||||
void tclacClimate::set_horizontal_swing_direction(HorizontalSwingDirection direction) {
|
void tclacClimate::set_horizontal_swing_direction(HorizontalSwingDirection direction) {
|
||||||
horizontal_swing_direction_ = direction;
|
horizontal_swing_direction_ = direction;
|
||||||
if (force_mode_status_){
|
if (force_mode_status_){
|
||||||
@@ -699,18 +860,18 @@ void tclacClimate::set_horizontal_swing_direction(HorizontalSwingDirection direc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Получение доступных скоростей вентилятора
|
// Get supported fan speeds
|
||||||
void tclacClimate::set_supported_fan_modes(const std::set<climate::ClimateFanMode> &modes){
|
void tclacClimate::set_supported_fan_modes(const std::set<climate::ClimateFanMode> &modes){
|
||||||
this->supported_fan_modes_ = modes;
|
this->supported_fan_modes_ = modes;
|
||||||
}
|
}
|
||||||
// Получение доступных режимов качания заслонок
|
// Get supported swing modes
|
||||||
void tclacClimate::set_supported_swing_modes(const std::set<climate::ClimateSwingMode> &modes) {
|
void tclacClimate::set_supported_swing_modes(const std::set<climate::ClimateSwingMode> &modes) {
|
||||||
this->supported_swing_modes_ = modes;
|
this->supported_swing_modes_ = modes;
|
||||||
}
|
}
|
||||||
// Получение доступных предустановок
|
// Get supported presets
|
||||||
void tclacClimate::set_supported_presets(const std::set<climate::ClimatePreset> &presets) {
|
void tclacClimate::set_supported_presets(const std::set<climate::ClimatePreset> &presets) {
|
||||||
this->supported_presets_ = presets;
|
this->supported_presets_ = presets;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace tclac {
|
|||||||
|
|
||||||
#define SET_TEMP_MASK 0b00001111
|
#define SET_TEMP_MASK 0b00001111
|
||||||
|
|
||||||
#define MODE_POS 7
|
#define MODE_POS 34
|
||||||
#define MODE_MASK 0b00111111
|
#define MODE_MASK 0b00111111
|
||||||
|
|
||||||
#define MODE_AUTO 0b00110101
|
#define MODE_AUTO 0b00110101
|
||||||
@@ -26,9 +26,10 @@ namespace tclac {
|
|||||||
#define MODE_DRY 0b00110011
|
#define MODE_DRY 0b00110011
|
||||||
#define MODE_FAN_ONLY 0b00110010
|
#define MODE_FAN_ONLY 0b00110010
|
||||||
#define MODE_HEAT 0b00110100
|
#define MODE_HEAT 0b00110100
|
||||||
|
#define MODE_OFF 0b00000000
|
||||||
|
|
||||||
#define FAN_SPEED_POS 8
|
#define FAN_SPEED_POS 35
|
||||||
#define FAN_QUIET_POS 33
|
#define FAN_QUIET_POS 36
|
||||||
|
|
||||||
#define FAN_AUTO 0b10000000 //auto
|
#define FAN_AUTO 0b10000000 //auto
|
||||||
#define FAN_QUIET 0x80 //silent
|
#define FAN_QUIET 0x80 //silent
|
||||||
@@ -58,12 +59,14 @@ enum class VerticalSwingDirection : uint8_t {
|
|||||||
UP_DOWN = 0,
|
UP_DOWN = 0,
|
||||||
UPSIDE = 1,
|
UPSIDE = 1,
|
||||||
DOWNSIDE = 2,
|
DOWNSIDE = 2,
|
||||||
|
OFF = 3
|
||||||
};
|
};
|
||||||
enum class HorizontalSwingDirection : uint8_t {
|
enum class HorizontalSwingDirection : uint8_t {
|
||||||
LEFT_RIGHT = 0,
|
LEFT_RIGHT = 0,
|
||||||
LEFTSIDE = 1,
|
LEFTSIDE = 1,
|
||||||
CENTER = 2,
|
CENTER = 2,
|
||||||
RIGHTSIDE = 3,
|
RIGHTSIDE = 3,
|
||||||
|
OFF = 4
|
||||||
};
|
};
|
||||||
enum class AirflowVerticalDirection : uint8_t {
|
enum class AirflowVerticalDirection : uint8_t {
|
||||||
LAST = 0,
|
LAST = 0,
|
||||||
@@ -85,13 +88,33 @@ enum class AirflowHorizontalDirection : uint8_t {
|
|||||||
class tclacClimate : public climate::Climate, public esphome::uart::UARTDevice, public PollingComponent {
|
class tclacClimate : public climate::Climate, public esphome::uart::UARTDevice, public PollingComponent {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
byte checksum;
|
uint8_t checksum;
|
||||||
// dataTX с управлением состоит из 38 байт
|
// dataTX с управлением состоит из 38 байт
|
||||||
byte dataTX[38];
|
uint8_t dataTX[38];
|
||||||
// А dataRX по прежнему из 61 байта
|
// А dataRX по прежнему из 61 байта
|
||||||
byte dataRX[61];
|
uint8_t dataRX[61];
|
||||||
// Команда запроса состояния
|
// Команда запроса состояния dataTX[0] = 0xBB;
|
||||||
byte poll[8] = {0xBB,0x00,0x01,0x04,0x02,0x01,0x00,0xBD};
|
|
||||||
|
//uint8_t poll[8] = {0xBB,0x00,0x01,0x04,0x02,0x00,0x01,0xBD};
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// NEUE von Serial Monitor
|
||||||
|
uint8_t poll[31] = {0xBB, 0x00, 0x01, 0x04, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x08, 0x0F, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F,
|
||||||
|
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0xA6};
|
||||||
|
//uint8_t poll[9] = {0xBB,0x00,0x01,0x0A,0x03,0x02,0x00,0x05,0xB4};
|
||||||
|
//uint8_t poll[8] = {0xBB,0x00,0x01,0x09,0x02,0x04,0x00,0xB5};
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
|
||||||
|
//uint8_t poll[8] = {0xBB,0x00,0x01,0x09,0x02,0x04,0x00,0xB5};
|
||||||
|
//byte poll3[8] = {0xBB,0x00,0x01,0x09,0x02,0x04,0x00,0xB5};
|
||||||
|
//byte poll2[9] = {0xBB,0x00,0x01,0x0A,0x03,0x02,0x00,0x05,0xB4};
|
||||||
|
//byte setup3[7] = {0xBB,0x00,0x01,0x02,0x04,0x00,0xB5};
|
||||||
|
//byte poll[6] = {0xBB,0x01,0x01,0x04,0x00,0xBF};
|
||||||
|
//byte poll[9] = {0xBB,0x00,0x01,0x04,0x03,0x02,0x00,0x05,0xB4};
|
||||||
|
int i = 0;
|
||||||
// Инициализация и начальное наполнение переменных состоянй переключателей
|
// Инициализация и начальное наполнение переменных состоянй переключателей
|
||||||
bool beeper_status_;
|
bool beeper_status_;
|
||||||
bool display_status_;
|
bool display_status_;
|
||||||
@@ -124,11 +147,11 @@ class tclacClimate : public climate::Climate, public esphome::uart::UARTDevice,
|
|||||||
void set_force_mode_state(bool state);
|
void set_force_mode_state(bool state);
|
||||||
void set_rx_led_pin(GPIOPin *rx_led_pin);
|
void set_rx_led_pin(GPIOPin *rx_led_pin);
|
||||||
void set_tx_led_pin(GPIOPin *tx_led_pin);
|
void set_tx_led_pin(GPIOPin *tx_led_pin);
|
||||||
void sendData(byte * message, byte size);
|
void sendData(uint8_t * message, uint8_t size);
|
||||||
void set_module_display_state(bool state);
|
void set_module_display_state(bool state);
|
||||||
static String getHex(byte *message, byte size);
|
static String getHex(uint8_t *message, uint8_t size);
|
||||||
void control(const ClimateCall &call) override;
|
void control(const ClimateCall &call) override;
|
||||||
static byte getChecksum(const byte * message, size_t size);
|
static uint8_t getChecksum(const uint8_t * message, size_t size);
|
||||||
void set_vertical_airflow(AirflowVerticalDirection direction);
|
void set_vertical_airflow(AirflowVerticalDirection direction);
|
||||||
void set_horizontal_airflow(AirflowHorizontalDirection direction);
|
void set_horizontal_airflow(AirflowHorizontalDirection direction);
|
||||||
void set_vertical_swing_direction(VerticalSwingDirection direction);
|
void set_vertical_swing_direction(VerticalSwingDirection direction);
|
||||||
@@ -154,4 +177,4 @@ class tclacClimate : public climate::Climate, public esphome::uart::UARTDevice,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //TCL_ESP_TCL_H
|
#endif //TCL_ESP_TCL_H
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# Компонент климата
|
# Компонент климата
|
||||||
external_components:
|
external_components:
|
||||||
- source:
|
- source:
|
||||||
url: https://github.com/I-am-nightingale/tclac.git
|
url: https://github.com/Kannix2005/tclac.git
|
||||||
type: git
|
type: git
|
||||||
ref: master
|
ref: master
|
||||||
components: [ tclac ]
|
components: [ tclac ]
|
||||||
@@ -40,6 +40,8 @@ esphome:
|
|||||||
id(${device_name}climate).set_vertical_swing_direction(esphome::tclac::VerticalSwingDirection::UPSIDE);
|
id(${device_name}climate).set_vertical_swing_direction(esphome::tclac::VerticalSwingDirection::UPSIDE);
|
||||||
} else if (id(vswing).active_index() == 2){
|
} else if (id(vswing).active_index() == 2){
|
||||||
id(${device_name}climate).set_vertical_swing_direction(esphome::tclac::VerticalSwingDirection::DOWNSIDE);
|
id(${device_name}climate).set_vertical_swing_direction(esphome::tclac::VerticalSwingDirection::DOWNSIDE);
|
||||||
|
} else if (id(vswing).active_index() == 3){
|
||||||
|
id(${device_name}climate).set_vertical_swing_direction(esphome::tclac::VerticalSwingDirection::OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id(hswing).active_index() == 0){
|
if (id(hswing).active_index() == 0){
|
||||||
@@ -50,6 +52,8 @@ esphome:
|
|||||||
id(${device_name}climate).set_horizontal_swing_direction(esphome::tclac::HorizontalSwingDirection::CENTER);
|
id(${device_name}climate).set_horizontal_swing_direction(esphome::tclac::HorizontalSwingDirection::CENTER);
|
||||||
} else if (id(hswing).active_index() == 3){
|
} else if (id(hswing).active_index() == 3){
|
||||||
id(${device_name}climate).set_horizontal_swing_direction(esphome::tclac::HorizontalSwingDirection::RIGHTSIDE);
|
id(${device_name}climate).set_horizontal_swing_direction(esphome::tclac::HorizontalSwingDirection::RIGHTSIDE);
|
||||||
|
} else if (id(hswing).active_index() == 4){
|
||||||
|
id(${device_name}climate).set_horizontal_swing_direction(esphome::tclac::HorizontalSwingDirection::OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id(vfixing).active_index() == 0){
|
if (id(vfixing).active_index() == 0){
|
||||||
@@ -206,6 +210,7 @@ select:
|
|||||||
- "Von oben nach unten"
|
- "Von oben nach unten"
|
||||||
- "In der oberen Hälfte"
|
- "In der oberen Hälfte"
|
||||||
- "In der unteren Hälfte"
|
- "In der unteren Hälfte"
|
||||||
|
- "Aus"
|
||||||
optimistic: true
|
optimistic: true
|
||||||
restore_value: true
|
restore_value: true
|
||||||
on_value:
|
on_value:
|
||||||
@@ -217,6 +222,8 @@ select:
|
|||||||
id(${device_name}climate).set_vertical_swing_direction(esphome::tclac::VerticalSwingDirection::UPSIDE);
|
id(${device_name}climate).set_vertical_swing_direction(esphome::tclac::VerticalSwingDirection::UPSIDE);
|
||||||
} else if (id(vswing).active_index() == 2){
|
} else if (id(vswing).active_index() == 2){
|
||||||
id(${device_name}climate).set_vertical_swing_direction(esphome::tclac::VerticalSwingDirection::DOWNSIDE);
|
id(${device_name}climate).set_vertical_swing_direction(esphome::tclac::VerticalSwingDirection::DOWNSIDE);
|
||||||
|
} else if (id(vswing).active_index() == 3){
|
||||||
|
id(${device_name}climate).set_vertical_swing_direction(esphome::tclac::VerticalSwingDirection::OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Настройка горизонтального качания
|
# Настройка горизонтального качания
|
||||||
@@ -229,6 +236,7 @@ select:
|
|||||||
- "Im linken Bereich"
|
- "Im linken Bereich"
|
||||||
- "Im Zentrum"
|
- "Im Zentrum"
|
||||||
- "Im rechten Bereich"
|
- "Im rechten Bereich"
|
||||||
|
- "Aus"
|
||||||
optimistic: true
|
optimistic: true
|
||||||
restore_value: true
|
restore_value: true
|
||||||
on_value:
|
on_value:
|
||||||
@@ -242,6 +250,8 @@ select:
|
|||||||
id(${device_name}climate).set_horizontal_swing_direction(esphome::tclac::HorizontalSwingDirection::CENTER);
|
id(${device_name}climate).set_horizontal_swing_direction(esphome::tclac::HorizontalSwingDirection::CENTER);
|
||||||
} else if (id(hswing).active_index() == 3){
|
} else if (id(hswing).active_index() == 3){
|
||||||
id(${device_name}climate).set_horizontal_swing_direction(esphome::tclac::HorizontalSwingDirection::RIGHTSIDE);
|
id(${device_name}climate).set_horizontal_swing_direction(esphome::tclac::HorizontalSwingDirection::RIGHTSIDE);
|
||||||
|
} else if (id(hswing).active_index() == 4){
|
||||||
|
id(${device_name}climate).set_horizontal_swing_direction(esphome::tclac::HorizontalSwingDirection::OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Настройка фиксации вертикальной заслонки
|
# Настройка фиксации вертикальной заслонки
|
||||||
|
|||||||
Reference in New Issue
Block a user