Fix status parsing and power flag handling
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
namespace esphome{
|
||||
namespace tclac{
|
||||
|
||||
constexpr uint8_t TCL_FRAME_TYPE_STATUS = 0x04;
|
||||
constexpr size_t TCL_STATUS_FRAME_MIN_SIZE = 40;
|
||||
|
||||
ClimateTraits tclacClimate::traits() {
|
||||
auto traits = climate::ClimateTraits();
|
||||
@@ -51,17 +53,27 @@ void tclacClimate::setup() {
|
||||
}
|
||||
|
||||
void tclacClimate::loop() {
|
||||
// Если в буфере UART что-то есть, то читаем это что-то
|
||||
if (esphome::uart::UARTDevice::available() > 0) {
|
||||
dataShow(0, true);
|
||||
dataRX[0] = esphome::uart::UARTDevice::read();
|
||||
// Если принятый байт- не заголовок (0xBB), то просто покидаем цикл
|
||||
if (dataRX[0] != 0xBB) {
|
||||
ESP_LOGD("TCL", "Wrong byte");
|
||||
size_t skipped = 0;
|
||||
bool header_found = false;
|
||||
while (esphome::uart::UARTDevice::available() > 0) {
|
||||
uint8_t byte = esphome::uart::UARTDevice::read();
|
||||
if (byte == 0xBB) {
|
||||
dataRX[0] = byte;
|
||||
header_found = true;
|
||||
break;
|
||||
}
|
||||
skipped += 1;
|
||||
}
|
||||
if (!header_found) {
|
||||
if (skipped > 0)
|
||||
ESP_LOGV("TCL", "Skipped %u byte(s) waiting for header", (unsigned) skipped);
|
||||
dataShow(0,0);
|
||||
return;
|
||||
}
|
||||
// А вот если совпал заголовок (0xBB), то начинаем чтение по цепочке еще 4 байт
|
||||
if (skipped > 0)
|
||||
ESP_LOGV("TCL", "Resynced after skipping %u byte(s)", (unsigned) skipped);
|
||||
delay(5);
|
||||
dataRX[1] = esphome::uart::UARTDevice::read();
|
||||
delay(5);
|
||||
@@ -70,32 +82,30 @@ void tclacClimate::loop() {
|
||||
dataRX[3] = esphome::uart::UARTDevice::read();
|
||||
delay(5);
|
||||
dataRX[4] = esphome::uart::UARTDevice::read();
|
||||
|
||||
//auto raw = getHex(dataRX, 5);
|
||||
|
||||
//ESP_LOGD("TCL", "first 5 byte : %s ", raw.c_str());
|
||||
|
||||
// Из первы<D0B2>
|
||||
5 байт нам нужен пятый- он содержит длину сообщения
|
||||
esphome::uart::UARTDevice::read_array(dataRX+5, dataRX[4]+1);
|
||||
|
||||
uint8_t check = getChecksum(dataRX, sizeof(dataRX));
|
||||
|
||||
//raw = getHex(dataRX, sizeof(dataRX));
|
||||
|
||||
//ESP_LOGD("TCL", "RX full : %s ", raw.c_str());
|
||||
|
||||
// Проверяем контрольную сумму
|
||||
if (check != dataRX[60]) {
|
||||
size_t payload_with_checksum = static_cast<size_t>(dataRX[4]) + 1;
|
||||
size_t frame_size = payload_with_checksum + 5;
|
||||
if (frame_size > sizeof(dataRX)) {
|
||||
ESP_LOGW("TCL", "Frame size %u exceeds buffer", (unsigned) frame_size);
|
||||
tclacClimate::dataShow(0,0);
|
||||
return;
|
||||
}
|
||||
esphome::uart::UARTDevice::read_array(dataRX + 5, payload_with_checksum);
|
||||
uint8_t check = getChecksum(dataRX, frame_size);
|
||||
if (check != dataRX[frame_size - 1]) {
|
||||
ESP_LOGD("TCL", "Invalid checksum %x", check);
|
||||
tclacClimate::dataShow(0,0);
|
||||
return;
|
||||
} else {
|
||||
//ESP_LOGD("TCL", "checksum OK %x", check);
|
||||
}
|
||||
tclacClimate::dataShow(0,0);
|
||||
// Прочитав все из буфера приступаем к разбору данны<D0BD>
|
||||
|
||||
uint8_t frame_type = dataRX[3];
|
||||
if (frame_type != TCL_FRAME_TYPE_STATUS) {
|
||||
ESP_LOGV("TCL", "Ignoring frame type 0x%02X", frame_type);
|
||||
return;
|
||||
}
|
||||
if (frame_size < TCL_STATUS_FRAME_MIN_SIZE) {
|
||||
ESP_LOGV("TCL", "Ignoring short status frame (%u bytes)", (unsigned) frame_size);
|
||||
return;
|
||||
}
|
||||
tclacClimate::readData();
|
||||
}
|
||||
}
|
||||
@@ -115,7 +125,8 @@ void tclacClimate::readData() {
|
||||
|
||||
//ESP_LOGD("TCL", "TEMP: %f ", current_temperature);
|
||||
|
||||
if (dataRX[MODE_POS] & ( 1 << 4)) {
|
||||
bool device_is_on = (dataRX[MODE_POS] & MODE_STATUS_POWER_FLAG) != 0;
|
||||
if (device_is_on) {
|
||||
// Если кондиционер включен, то разбираем данные для отображения
|
||||
// ESP_LOGD("TCL", "AC is on");
|
||||
uint8_t modeswitch = MODE_MASK & dataRX[MODE_POS];
|
||||
@@ -308,23 +319,23 @@ void tclacClimate::takeControl() {
|
||||
dataTX[8] += 0b00000000;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_AUTO:
|
||||
dataTX[7] += 0b00000100;
|
||||
dataTX[7] += MODE_COMMAND_POWER_FLAG;
|
||||
dataTX[8] += 0b00001000;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_COOL:
|
||||
dataTX[7] += 0b00000100;
|
||||
dataTX[7] += MODE_COMMAND_POWER_FLAG;
|
||||
dataTX[8] += 0b00000011;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_DRY:
|
||||
dataTX[7] += 0b00000100;
|
||||
dataTX[7] += MODE_COMMAND_POWER_FLAG;
|
||||
dataTX[8] += 0b00000010;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_FAN_ONLY:
|
||||
dataTX[7] += 0b00000100;
|
||||
dataTX[7] += MODE_COMMAND_POWER_FLAG;
|
||||
dataTX[8] += 0b00000111;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_HEAT:
|
||||
dataTX[7] += 0b00000100;
|
||||
dataTX[7] += MODE_COMMAND_POWER_FLAG;
|
||||
dataTX[8] += 0b00000001;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ using byte = uint8_t;
|
||||
|
||||
#define MODE_POS 7
|
||||
#define MODE_MASK 0b00111111
|
||||
#define MODE_STATUS_POWER_FLAG 0b00010000
|
||||
#define MODE_COMMAND_POWER_FLAG 0b00000100
|
||||
|
||||
#define MODE_AUTO 0b00110101
|
||||
#define MODE_COOL 0b00110001
|
||||
|
||||
Reference in New Issue
Block a user