This commit is contained in:
Roy Goldshtein 2024-05-02 15:46:55 +12:00 committed by GitHub
commit e7df005524
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 313 additions and 0 deletions

View File

@ -107,6 +107,7 @@ esphome/components/dsmr/* @glmnet @zuidwijk
esphome/components/duty_time/* @dudanov
esphome/components/ee895/* @Stock-M
esphome/components/ektf2232/touchscreen/* @jesserockz
esphome/components/electra_rc3_ir/* @roygolds
esphome/components/emc2101/* @ellull
esphome/components/emmeti/* @E440QF
esphome/components/ens160/* @vincentscode

View File

@ -0,0 +1 @@
CODEOWNERS = ["@roygolds"]

View File

@ -0,0 +1,21 @@
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"]
CODEOWNERS = ["@roygolds"]
electra_rc3_ir_ns = cg.esphome_ns.namespace("electra_rc3_ir")
ElectraRC3IR = electra_rc3_ir_ns.class_("ElectraRC3IR", climate_ir.ClimateIR)
CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(ElectraRC3IR),
}
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await climate_ir.register_climate_ir(var, config)

View File

@ -0,0 +1,111 @@
#include "electra_rc3_ir.h"
#include "esphome/components/remote_base/electra_rc3_protocol.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace electra_rc3_ir {
// using climate::ClimateMode;
// using climate::ClimateFanMode;
using remote_base::ElectraRC3Data;
static const char *const TAG = "electra_rc3_ir.climate";
using ElectraRC3Mode = enum ElectraRC3Mode {
ELECTRA_RC3_MODE_COOL = 0b001,
ELECTRA_RC3_MODE_HEAT = 0b010,
ELECTRA_RC3_MODE_AUTO = 0b011,
ELECTRA_RC3_MODE_DRY = 0b100,
ELECTRA_RC3_MODE_FAN = 0b101,
ELECTRA_RC3_MODE_OFF = 0b111
};
using ElectraRC3Fan = enum ElectraRC3Fan {
ELECTRA_RC3_FAN_LOW = 0b00,
ELECTRA_RC3_FAN_MEDIUM = 0b01,
ELECTRA_RC3_FAN_HIGH = 0b10,
ELECTRA_RC3_FAN_AUTO = 0b11
};
// void ElectraRC3IR::control(const climate::ClimateCall &call) {
// // swing and preset resets after unit powered off
// if (call.get_mode().has_value() && (climate::CLIMATE_MODE_OFF == call.get_mode())) {
// this->current_mode = call.get_mode();
// }
// climate_ir::ClimateIR::control(call);
// }
void ElectraRC3IR::transmit_state() {
ElectraRC3Data data;
switch (this->fan_mode.value()) {
case climate::CLIMATE_FAN_LOW:
data.fan = ElectraRC3Fan::ELECTRA_RC3_FAN_LOW;
break;
case climate::CLIMATE_FAN_MEDIUM:
data.fan = ElectraRC3Fan::ELECTRA_RC3_FAN_MEDIUM;
break;
case climate::CLIMATE_FAN_HIGH:
data.fan = ElectraRC3Fan::ELECTRA_RC3_FAN_HIGH;
break;
default:
data.fan = ElectraRC3Fan::ELECTRA_RC3_FAN_AUTO;
break;
}
switch (this->mode) {
case climate::CLIMATE_MODE_COOL:
data.mode = ElectraRC3Mode::ELECTRA_RC3_MODE_COOL;
break;
case climate::CLIMATE_MODE_HEAT:
data.mode = ElectraRC3Mode::ELECTRA_RC3_MODE_HEAT;
break;
case climate::CLIMATE_MODE_AUTO:
data.mode = ElectraRC3Mode::ELECTRA_RC3_MODE_AUTO;
break;
case climate::CLIMATE_MODE_DRY:
data.mode = ElectraRC3Mode::ELECTRA_RC3_MODE_DRY;
break;
case climate::CLIMATE_MODE_FAN_ONLY:
data.mode = ElectraRC3Mode::ELECTRA_RC3_MODE_FAN;
break;
case climate::CLIMATE_MODE_OFF:
default:
data.mode = ElectraRC3Mode::ELECTRA_RC3_MODE_OFF;
break;
}
if (climate::CLIMATE_MODE_OFF != this->mode) {
data.power = (climate::CLIMATE_MODE_OFF == this->current_mode_) ? 1 : 0;
}
this->current_mode_ = this->mode;
auto temp = (uint8_t) roundf(this->target_temperature);
if (temp < ELECTRA_RC3_TEMP_MIN) {
temp = ELECTRA_RC3_TEMP_MIN;
} else if (temp > ELECTRA_RC3_TEMP_MAX) {
temp = ELECTRA_RC3_TEMP_MAX;
}
data.temperature = temp - 15;
data.sleep = (this->preset == climate::CLIMATE_PRESET_SLEEP) ? 1 : 0;
;
data.swing = (this->swing_mode == climate::CLIMATE_SWING_VERTICAL) ? 1 : 0;
ESP_LOGD(TAG,
"Electra RC3: power = 0x%llX, mode = 0x%llX, fan = 0x%llX, swing = 0x%llX, "
"ifeel = 0x%llX, temperature = 0x%llX, sleep = 0x%llX",
data.power, data.mode, data.fan, data.swing, data.ifeel, data.temperature, data.sleep);
auto transmit = this->transmitter_->transmit();
remote_base::ElectraRC3Protocol().encode(transmit.get_data(), data);
transmit.perform();
}
bool ElectraRC3IR::on_receive(remote_base::RemoteReceiveData data) { return false; }
} // namespace electra_rc3_ir
} // namespace esphome

View File

@ -0,0 +1,34 @@
#pragma once
#include "esphome/components/climate_ir/climate_ir.h"
namespace esphome {
namespace electra_rc3_ir {
// Temperature
const uint8_t ELECTRA_RC3_TEMP_MIN = 16;
const uint8_t ELECTRA_RC3_TEMP_MAX = 30;
class ElectraRC3IR : public climate_ir::ClimateIR {
public:
ElectraRC3IR()
: climate_ir::ClimateIR(ELECTRA_RC3_TEMP_MIN, ELECTRA_RC3_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_PRESET_NONE, climate::CLIMATE_PRESET_SLEEP}) {}
// void control(const climate::ClimateCall &call) override;
protected:
/// Transmit via IR the state of this climate controller.
void transmit_state() override;
/// Handle received IR Buffer
bool on_receive(remote_base::RemoteReceiveData data) override;
private:
climate::ClimateMode current_mode_{climate::ClimateMode::CLIMATE_MODE_OFF};
};
} // namespace electra_rc3_ir
} // namespace esphome

View File

@ -0,0 +1,79 @@
#include "electra_rc3_protocol.h"
#include "esphome/core/log.h"
namespace esphome {
namespace remote_base {
static const char *const ELECTRA_RC3_TAG = "remote.electra_rc3";
static const uint16_t ELECTRA_RC3_FREQ = 38000;
static const uint16_t ELECTRA_RC3_UNIT = 1000;
static const uint16_t ELECTRA_RC3_HEADER_MARK = (3 * ELECTRA_RC3_UNIT);
static const uint16_t ELECTRA_RC3_HEADER_SPACE = (3 * ELECTRA_RC3_UNIT);
static const uint16_t ELECTRA_RC3_FOOTER_MARK = (4 * ELECTRA_RC3_UNIT);
static const uint16_t ELECTRA_RC3_NUM_BITS = 34;
static const uint16_t ELECTRA_RC3_RETEATS = 3;
void ElectraRC3Protocol::encode(RemoteTransmitData *dst, const ElectraRC3Data &data) {
dst->reserve(44);
dst->set_carrier_frequency(ELECTRA_RC3_FREQ);
for (uint8_t i = 0; i < ELECTRA_RC3_RETEATS; ++i) {
// Encode header
dst->mark(ELECTRA_RC3_HEADER_MARK);
uint16_t next_value = ELECTRA_RC3_HEADER_SPACE;
bool is_next_space = true;
// Encode Data
for (int bit_index = ELECTRA_RC3_NUM_BITS - 1; bit_index >= 0; --bit_index) {
uint8_t bit = (data.q_word >> bit_index) & 1;
if (is_next_space) {
if (bit == 1) {
dst->space(next_value + ELECTRA_RC3_UNIT);
next_value = ELECTRA_RC3_UNIT;
is_next_space = false;
} else {
dst->space(next_value);
dst->mark(ELECTRA_RC3_UNIT);
next_value = ELECTRA_RC3_UNIT;
is_next_space = true;
}
} else {
if (bit == 1) {
dst->mark(next_value);
dst->space(ELECTRA_RC3_UNIT);
next_value = ELECTRA_RC3_UNIT;
is_next_space = false;
} else {
dst->mark(next_value + ELECTRA_RC3_UNIT);
next_value = ELECTRA_RC3_UNIT;
is_next_space = true;
}
}
}
dst->space(next_value);
}
// Encode footer
dst->mark(ELECTRA_RC3_FOOTER_MARK);
}
optional<ElectraRC3Data> ElectraRC3Protocol::decode(RemoteReceiveData src) {
ElectraRC3Data data;
return data;
}
void ElectraRC3Protocol::dump(const ElectraRC3Data &data) {
ESP_LOGD(ELECTRA_RC3_TAG,
"Received Electra RC3: power = 0x%llX, mode = 0x%llX, fan = 0x%llX, swing = 0x%llX, "
"ifeel = 0x%llX, temperature = 0x%llX, sleep = 0x%llX",
data.power, data.mode, data.fan, data.swing, data.ifeel, data.temperature, data.sleep);
}
} // namespace remote_base
} // namespace esphome

View File

@ -0,0 +1,66 @@
#pragma once
#include "remote_base.h"
namespace esphome {
namespace remote_base {
struct ElectraRC3Data {
union {
uint64_t q_word;
struct {
uint64_t zeros1 : 1;
uint64_t ones1 : 1;
uint64_t zeros2 : 16;
uint64_t sleep : 1;
uint64_t temperature : 4;
uint64_t zeros3 : 1;
uint64_t ifeel : 1;
uint64_t swing : 1;
uint64_t zeros4 : 2;
uint64_t fan : 2;
uint64_t mode : 3;
uint64_t power : 1;
};
};
ElectraRC3Data() : q_word(0) { ones1 = 1; }
bool operator==(const ElectraRC3Data &rhs) const { return (q_word == rhs.q_word); }
};
class ElectraRC3Protocol : public RemoteProtocol<ElectraRC3Data> {
public:
void encode(RemoteTransmitData *dst, const ElectraRC3Data &data) override;
optional<ElectraRC3Data> decode(RemoteReceiveData src) override;
void dump(const ElectraRC3Data &data) override;
};
DECLARE_REMOTE_PROTOCOL(ElectraRC3)
template<typename... Ts> class ElectraRC3Action : public RemoteTransmitterActionBase<Ts...> {
public:
TEMPLATABLE_VALUE(uint64_t, power)
TEMPLATABLE_VALUE(uint64_t, mode)
TEMPLATABLE_VALUE(uint64_t, fan)
TEMPLATABLE_VALUE(uint64_t, swing)
TEMPLATABLE_VALUE(uint64_t, ifeel)
TEMPLATABLE_VALUE(uint64_t, temperature)
TEMPLATABLE_VALUE(uint64_t, sleep)
void encode(RemoteTransmitData *dst, Ts... x) {
ElectraRC3Data data{};
data.mode = 0;
data.power = this->power_.value(x...);
data.mode = this->mode_.value(x...);
data.fan = this->fan_.value(x...);
data.swing = this->swing_.value(x...);
data.ifeel = this->ifeel_.value(x...);
data.temperature = this->temperature_.value(x...);
data.sleep = this->sleep_.value(x...);
ElectraRC3Protocol().encode(dst, data);
}
};
} // namespace remote_base
} // namespace esphome