mirror of
https://github.com/esphome/esphome.git
synced 2026-05-24 09:56:46 +08:00
[mitsubishi_cn105] Simplified protocol lookups (#16399)
This commit is contained in:
@@ -30,44 +30,53 @@ static constexpr uint8_t STATUS_MSG_ROOM_TEMP = 0x03;
|
||||
static constexpr uint8_t PACKET_TYPE_WRITE_SETTINGS_REQUEST = 0x41;
|
||||
static constexpr uint8_t PACKET_TYPE_WRITE_SETTINGS_RESPONSE = 0x61;
|
||||
|
||||
static constexpr std::array<std::optional<MitsubishiCN105::Mode>, 9> PROTOCOL_MODE_MAP = {
|
||||
std::nullopt, // 0x00
|
||||
template<auto Unknown, size_t N> struct LookupMap {
|
||||
using value_type = decltype(Unknown);
|
||||
static constexpr auto UNKNOWN_VALUE = Unknown;
|
||||
const std::array<value_type, N> table;
|
||||
|
||||
constexpr value_type lookup(uint8_t raw) const { return (raw < N) ? this->table[raw] : UNKNOWN_VALUE; }
|
||||
|
||||
constexpr bool reverse_lookup(value_type value, uint8_t &out) const {
|
||||
static_assert(N <= std::numeric_limits<uint8_t>::max());
|
||||
if (value == UNKNOWN_VALUE) {
|
||||
return false;
|
||||
}
|
||||
for (uint8_t i = 0; i < static_cast<uint8_t>(N); ++i) {
|
||||
if (this->table[i] == value) {
|
||||
out = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<auto Unknown, class T, std::size_t N> static constexpr auto make_map(const T (&values)[N]) {
|
||||
return LookupMap<Unknown, N>{std::to_array(values)};
|
||||
}
|
||||
|
||||
static constexpr auto PROTOCOL_MODE_MAP = make_map<MitsubishiCN105::Mode::UNKNOWN>({
|
||||
MitsubishiCN105::Mode::UNKNOWN, // 0x00
|
||||
MitsubishiCN105::Mode::HEAT, // 0x01
|
||||
MitsubishiCN105::Mode::DRY, // 0x02
|
||||
MitsubishiCN105::Mode::COOL, // 0x03
|
||||
std::nullopt, // 0x04
|
||||
std::nullopt, // 0x05
|
||||
std::nullopt, // 0x06
|
||||
MitsubishiCN105::Mode::UNKNOWN, // 0x04
|
||||
MitsubishiCN105::Mode::UNKNOWN, // 0x05
|
||||
MitsubishiCN105::Mode::UNKNOWN, // 0x06
|
||||
MitsubishiCN105::Mode::FAN_ONLY, // 0x07
|
||||
MitsubishiCN105::Mode::AUTO // 0x08
|
||||
};
|
||||
});
|
||||
|
||||
static constexpr std::array<std::optional<MitsubishiCN105::FanMode>, 7> PROTOCOL_FAN_MODE_MAP = {
|
||||
static constexpr auto PROTOCOL_FAN_MODE_MAP = make_map<MitsubishiCN105::FanMode::UNKNOWN>({
|
||||
MitsubishiCN105::FanMode::AUTO, // 0x00
|
||||
MitsubishiCN105::FanMode::QUIET, // 0x01
|
||||
MitsubishiCN105::FanMode::SPEED_1, // 0x02
|
||||
MitsubishiCN105::FanMode::SPEED_2, // 0x03
|
||||
std::nullopt, // 0x04
|
||||
MitsubishiCN105::FanMode::UNKNOWN, // 0x04
|
||||
MitsubishiCN105::FanMode::SPEED_3, // 0x05
|
||||
MitsubishiCN105::FanMode::SPEED_4 // 0x06
|
||||
};
|
||||
|
||||
template<typename T, size_t N>
|
||||
static constexpr std::optional<T> lookup(const std::array<std::optional<T>, N> &table, uint8_t value) {
|
||||
return (value < N) ? table[value] : std::nullopt;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
static constexpr bool reverse_lookup(const std::array<std::optional<T>, N> &table, T value, uint8_t &placeholder) {
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
const auto &table_value = table[i];
|
||||
if (table_value.has_value() && table_value == value) {
|
||||
placeholder = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
static constexpr uint8_t checksum(const uint8_t *bytes, size_t length) {
|
||||
return static_cast<uint8_t>(0xFC - std::accumulate(bytes, bytes + length, uint8_t{0}));
|
||||
@@ -323,11 +332,11 @@ bool MitsubishiCN105::parse_status_settings_(const uint8_t *payload, size_t len)
|
||||
|
||||
if (!this->pending_updates_.contains(UpdateFlag::MODE)) {
|
||||
const bool i_see = payload[3] > 0x08;
|
||||
this->status_.mode = lookup(PROTOCOL_MODE_MAP, payload[3] - (i_see ? 0x08 : 0)).value_or(Mode::UNKNOWN);
|
||||
this->status_.mode = PROTOCOL_MODE_MAP.lookup(payload[3] - (i_see ? 0x08 : 0));
|
||||
}
|
||||
|
||||
if (!this->pending_updates_.contains(UpdateFlag::FAN)) {
|
||||
this->status_.fan_mode = lookup(PROTOCOL_FAN_MODE_MAP, payload[5]).value_or(FanMode::UNKNOWN);
|
||||
this->status_.fan_mode = PROTOCOL_FAN_MODE_MAP.lookup(payload[5]);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -382,7 +391,7 @@ void MitsubishiCN105::set_target_temperature(float target_temperature) {
|
||||
|
||||
void MitsubishiCN105::set_mode(Mode mode) {
|
||||
uint8_t placeholder;
|
||||
if (!reverse_lookup(PROTOCOL_MODE_MAP, mode, placeholder)) {
|
||||
if (!PROTOCOL_MODE_MAP.reverse_lookup(mode, placeholder)) {
|
||||
ESP_LOGD(TAG, "Setting invalid mode: %u", static_cast<uint8_t>(mode));
|
||||
return;
|
||||
}
|
||||
@@ -392,7 +401,7 @@ void MitsubishiCN105::set_mode(Mode mode) {
|
||||
|
||||
void MitsubishiCN105::set_fan_mode(FanMode fan_mode) {
|
||||
uint8_t placeholder;
|
||||
if (!reverse_lookup(PROTOCOL_FAN_MODE_MAP, fan_mode, placeholder)) {
|
||||
if (!PROTOCOL_FAN_MODE_MAP.reverse_lookup(fan_mode, placeholder)) {
|
||||
ESP_LOGD(TAG, "Setting invalid fan mode: %u", static_cast<uint8_t>(fan_mode));
|
||||
return;
|
||||
}
|
||||
@@ -432,12 +441,12 @@ void MitsubishiCN105::apply_settings_() {
|
||||
}
|
||||
|
||||
if (this->pending_updates_.contains(UpdateFlag::MODE) &&
|
||||
reverse_lookup(PROTOCOL_MODE_MAP, this->status_.mode, payload[4])) {
|
||||
PROTOCOL_MODE_MAP.reverse_lookup(this->status_.mode, payload[4])) {
|
||||
payload[1] |= 0x02;
|
||||
}
|
||||
|
||||
if (this->pending_updates_.contains(UpdateFlag::FAN) &&
|
||||
reverse_lookup(PROTOCOL_FAN_MODE_MAP, this->status_.fan_mode, payload[6])) {
|
||||
PROTOCOL_FAN_MODE_MAP.reverse_lookup(this->status_.fan_mode, payload[6])) {
|
||||
payload[1] |= 0x08;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user