homelab-codex-ws/hardware/esp/ir-ac-ha-integration/components/gree_ir/gree_ir.h

86 lines
3 KiB
C
Raw Permalink Normal View History

#pragma once
#include "esphome/core/component.h"
#include "esphome/components/climate/climate.h"
#include "esphome/components/remote_transmitter/remote_transmitter.h"
namespace esphome {
namespace gree_ir {
class GreeIR : public climate::Climate, public Component {
public:
void set_transmitter(remote_transmitter::RemoteTransmitterComponent *tx) {
this->transmitter_ = tx;
}
void setup() override {
this->mode = climate::CLIMATE_MODE_OFF;
this->target_temperature = 24;
this->publish_state();
}
climate::ClimateTraits traits() override {
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,
});
traits.set_visual_min_temperature(16);
traits.set_visual_max_temperature(30);
traits.set_visual_temperature_step(1);
return traits;
}
void control(const climate::ClimateCall &call) override {
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();
this->transmit_state_();
this->publish_state();
}
protected:
remote_transmitter::RemoteTransmitterComponent *transmitter_{nullptr};
void transmit_state_() {
uint8_t b[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t mode_byte, b2, b1_0;
switch (this->mode) {
case climate::CLIMATE_MODE_COOL: mode_byte = 0x19; b2 = 0x60; b1_0 = 0x06; break;
case climate::CLIMATE_MODE_HEAT: mode_byte = 0x4C; b2 = 0x40; b1_0 = 0x01; break;
case climate::CLIMATE_MODE_FAN_ONLY: mode_byte = 0x1B; b2 = 0x60; b1_0 = 0x02; break;
default: mode_byte = 0x44; b2 = 0x00; b1_0 = 0x01; break;
}
int temp = (int) this->target_temperature;
if (temp < 16) temp = 16;
if (temp > 30) temp = 30;
uint8_t t = (this->mode == climate::CLIMATE_MODE_OFF) ? 0x0A : (uint8_t)(temp - 16);
b[0] = mode_byte; b[1] = t; b[2] = b2; b[3] = 0x50;
b[4] = b1_0; b[5] = 0x00; b[6] = 0x00;
uint8_t cs = ((b[0] & 0xF) + (b[1] & 0xF) + (b[2] & 0xF) + (b[3] & 0xF) +
((b[4] >> 4) & 0xF) + ((b[5] >> 4) & 0xF) + ((b[6] >> 4) & 0xF) + 0x0A) & 0xF;
b[7] = (cs << 4) & 0xF0;
auto transmit = this->transmitter_->transmit();
auto *data = transmit.get_data();
data->set_carrier_frequency(38000);
const int MK = 677, S0 = 553, S1 = 1630, GAP = 19960;
data->mark(9030); data->space(4460);
for (int by = 0; by < 4; by++)
for (int bit = 0; bit < 8; bit++) { data->mark(MK); data->space(((b[by] >> bit) & 1) ? S1 : S0); }
const int foot[3] = {0, 1, 0};
for (int i = 0; i < 3; i++) { data->mark(MK); data->space(foot[i] ? S1 : S0); }
data->mark(MK); data->space(GAP);
for (int by = 4; by < 8; by++)
for (int bit = 0; bit < 8; bit++) { data->mark(MK); data->space(((b[by] >> bit) & 1) ? S1 : S0); }
data->mark(MK);
transmit.perform();
}
};
} // namespace gree_ir
} // namespace