mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 16:37:52 +01:00
Daikin climate receiver support (#1001)
* climate.daikin: implement remote receive * climate.daikin: fix temperature value in special modes * climate.daikin: tweak timing to fit better to ir-remote signal
This commit is contained in:
parent
c1dfed5c08
commit
65f4d30fd0
@ -8,7 +8,7 @@ AUTO_LOAD = ['climate_ir']
|
||||
daikin_ns = cg.esphome_ns.namespace('daikin')
|
||||
DaikinClimate = daikin_ns.class_('DaikinClimate', climate_ir.ClimateIR)
|
||||
|
||||
CONFIG_SCHEMA = climate_ir.CLIMATE_IR_SCHEMA.extend({
|
||||
CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(DaikinClimate),
|
||||
})
|
||||
|
||||
|
@ -115,7 +115,8 @@ uint8_t DaikinClimate::temperature_() {
|
||||
// Force special temperatures depending on the mode
|
||||
switch (this->mode) {
|
||||
case climate::CLIMATE_MODE_FAN_ONLY:
|
||||
return 25;
|
||||
return 0x32;
|
||||
case climate::CLIMATE_MODE_AUTO:
|
||||
case climate::CLIMATE_MODE_DRY:
|
||||
return 0xc0;
|
||||
default:
|
||||
@ -124,5 +125,103 @@ uint8_t DaikinClimate::temperature_() {
|
||||
}
|
||||
}
|
||||
|
||||
bool DaikinClimate::parse_state_frame_(const uint8_t frame[]) {
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < (DAIKIN_STATE_FRAME_SIZE - 1); i++) {
|
||||
checksum += frame[i];
|
||||
}
|
||||
if (frame[DAIKIN_STATE_FRAME_SIZE - 1] != checksum)
|
||||
return false;
|
||||
uint8_t mode = frame[5];
|
||||
if (mode & DAIKIN_MODE_ON) {
|
||||
switch (mode & 0xF0) {
|
||||
case DAIKIN_MODE_COOL:
|
||||
this->mode = climate::CLIMATE_MODE_COOL;
|
||||
break;
|
||||
case DAIKIN_MODE_DRY:
|
||||
this->mode = climate::CLIMATE_MODE_DRY;
|
||||
break;
|
||||
case DAIKIN_MODE_HEAT:
|
||||
this->mode = climate::CLIMATE_MODE_HEAT;
|
||||
break;
|
||||
case DAIKIN_MODE_AUTO:
|
||||
this->mode = climate::CLIMATE_MODE_AUTO;
|
||||
break;
|
||||
case DAIKIN_MODE_FAN:
|
||||
this->mode = climate::CLIMATE_MODE_FAN_ONLY;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
this->mode = climate::CLIMATE_MODE_OFF;
|
||||
}
|
||||
uint8_t temperature = frame[6];
|
||||
if (!(temperature & 0xC0)) {
|
||||
this->target_temperature = temperature >> 1;
|
||||
}
|
||||
uint8_t fan_mode = frame[8];
|
||||
if (fan_mode & 0xF)
|
||||
this->swing_mode = climate::CLIMATE_SWING_VERTICAL;
|
||||
else
|
||||
this->swing_mode = climate::CLIMATE_SWING_OFF;
|
||||
switch (fan_mode & 0xF0) {
|
||||
case DAIKIN_FAN_1:
|
||||
case DAIKIN_FAN_2:
|
||||
this->fan_mode = climate::CLIMATE_FAN_LOW;
|
||||
break;
|
||||
case DAIKIN_FAN_3:
|
||||
this->fan_mode = climate::CLIMATE_FAN_MEDIUM;
|
||||
break;
|
||||
case DAIKIN_FAN_4:
|
||||
case DAIKIN_FAN_5:
|
||||
this->fan_mode = climate::CLIMATE_FAN_HIGH;
|
||||
break;
|
||||
case DAIKIN_FAN_AUTO:
|
||||
this->fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||
break;
|
||||
}
|
||||
this->publish_state();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DaikinClimate::on_receive(remote_base::RemoteReceiveData data) {
|
||||
uint8_t state_frame[DAIKIN_STATE_FRAME_SIZE] = {};
|
||||
if (!data.expect_item(DAIKIN_HEADER_MARK, DAIKIN_HEADER_SPACE)) {
|
||||
return false;
|
||||
}
|
||||
for (uint8_t pos = 0; pos < DAIKIN_STATE_FRAME_SIZE; pos++) {
|
||||
uint8_t byte = 0;
|
||||
for (int8_t bit = 0; bit < 8; bit++) {
|
||||
if (data.expect_item(DAIKIN_BIT_MARK, DAIKIN_ONE_SPACE))
|
||||
byte |= 1 << bit;
|
||||
else if (!data.expect_item(DAIKIN_BIT_MARK, DAIKIN_ZERO_SPACE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state_frame[pos] = byte;
|
||||
if (pos == 0) {
|
||||
// frame header
|
||||
if (byte != 0x11)
|
||||
return false;
|
||||
} else if (pos == 1) {
|
||||
// frame header
|
||||
if (byte != 0xDA)
|
||||
return false;
|
||||
} else if (pos == 2) {
|
||||
// frame header
|
||||
if (byte != 0x27)
|
||||
return false;
|
||||
} else if (pos == 3) {
|
||||
// frame header
|
||||
if (byte != 0x00)
|
||||
return false;
|
||||
} else if (pos == 4) {
|
||||
// frame type
|
||||
if (byte != 0x00)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return this->parse_state_frame_(state_frame);
|
||||
}
|
||||
|
||||
} // namespace daikin
|
||||
} // namespace esphome
|
||||
|
@ -31,11 +31,14 @@ const uint8_t DAIKIN_FAN_5 = 0x70;
|
||||
const uint32_t DAIKIN_IR_FREQUENCY = 38000;
|
||||
const uint32_t DAIKIN_HEADER_MARK = 3360;
|
||||
const uint32_t DAIKIN_HEADER_SPACE = 1760;
|
||||
const uint32_t DAIKIN_BIT_MARK = 360;
|
||||
const uint32_t DAIKIN_BIT_MARK = 520;
|
||||
const uint32_t DAIKIN_ONE_SPACE = 1370;
|
||||
const uint32_t DAIKIN_ZERO_SPACE = 520;
|
||||
const uint32_t DAIKIN_ZERO_SPACE = 360;
|
||||
const uint32_t DAIKIN_MESSAGE_SPACE = 32300;
|
||||
|
||||
// State Frame size
|
||||
const uint8_t DAIKIN_STATE_FRAME_SIZE = 19;
|
||||
|
||||
class DaikinClimate : public climate_ir::ClimateIR {
|
||||
public:
|
||||
DaikinClimate()
|
||||
@ -51,6 +54,9 @@ class DaikinClimate : public climate_ir::ClimateIR {
|
||||
uint8_t operation_mode_();
|
||||
uint8_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 daikin
|
||||
|
Loading…
Reference in New Issue
Block a user