mirror of
https://github.com/esphome/esphome.git
synced 2024-12-21 16:27:44 +01:00
Add Tuya select (#3469)
This commit is contained in:
parent
0665acd190
commit
f62d5d3b9d
@ -222,6 +222,7 @@ esphome/components/tsl2591/* @wjcarpenter
|
||||
esphome/components/tuya/binary_sensor/* @jesserockz
|
||||
esphome/components/tuya/climate/* @jesserockz
|
||||
esphome/components/tuya/number/* @frankiboy1
|
||||
esphome/components/tuya/select/* @bearpawmaxim
|
||||
esphome/components/tuya/sensor/* @jesserockz
|
||||
esphome/components/tuya/switch/* @jesserockz
|
||||
esphome/components/tuya/text_sensor/* @dentra
|
||||
|
47
esphome/components/tuya/select/__init__.py
Normal file
47
esphome/components/tuya/select/__init__.py
Normal file
@ -0,0 +1,47 @@
|
||||
from esphome.components import select
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
from esphome.const import CONF_OPTIONS, CONF_OPTIMISTIC, CONF_ENUM_DATAPOINT
|
||||
from .. import tuya_ns, CONF_TUYA_ID, Tuya
|
||||
|
||||
DEPENDENCIES = ["tuya"]
|
||||
CODEOWNERS = ["@bearpawmaxim"]
|
||||
|
||||
TuyaSelect = tuya_ns.class_("TuyaSelect", select.Select, cg.Component)
|
||||
|
||||
|
||||
def ensure_option_map(value):
|
||||
cv.check_not_templatable(value)
|
||||
option = cv.All(cv.int_range(0, 2**8 - 1))
|
||||
mapping = cv.All(cv.string_strict)
|
||||
options_map_schema = cv.Schema({option: mapping})
|
||||
value = options_map_schema(value)
|
||||
|
||||
all_values = list(value.keys())
|
||||
unique_values = set(value.keys())
|
||||
if len(all_values) != len(unique_values):
|
||||
raise cv.Invalid("Mapping values must be unique.")
|
||||
|
||||
return value
|
||||
|
||||
|
||||
CONFIG_SCHEMA = select.SELECT_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(TuyaSelect),
|
||||
cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya),
|
||||
cv.Required(CONF_ENUM_DATAPOINT): cv.uint8_t,
|
||||
cv.Required(CONF_OPTIONS): ensure_option_map,
|
||||
cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
options_map = config[CONF_OPTIONS]
|
||||
var = await select.new_select(config, options=list(options_map.values()))
|
||||
await cg.register_component(var, config)
|
||||
cg.add(var.set_select_mappings(list(options_map.keys())))
|
||||
parent = await cg.get_variable(config[CONF_TUYA_ID])
|
||||
cg.add(var.set_tuya_parent(parent))
|
||||
cg.add(var.set_select_id(config[CONF_ENUM_DATAPOINT]))
|
||||
cg.add(var.set_optimistic(config[CONF_OPTIMISTIC]))
|
52
esphome/components/tuya/select/tuya_select.cpp
Normal file
52
esphome/components/tuya/select/tuya_select.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "esphome/core/log.h"
|
||||
#include "tuya_select.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace tuya {
|
||||
|
||||
static const char *const TAG = "tuya.select";
|
||||
|
||||
void TuyaSelect::setup() {
|
||||
this->parent_->register_listener(this->select_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
uint8_t enum_value = datapoint.value_enum;
|
||||
ESP_LOGV(TAG, "MCU reported select %u value %u", this->select_id_, enum_value);
|
||||
auto options = this->traits.get_options();
|
||||
auto mappings = this->mappings_;
|
||||
auto it = std::find(mappings.cbegin(), mappings.cend(), enum_value);
|
||||
if (it == mappings.end()) {
|
||||
ESP_LOGW(TAG, "Invalid value %u", enum_value);
|
||||
return;
|
||||
}
|
||||
size_t mapping_idx = std::distance(mappings.cbegin(), it);
|
||||
auto value = this->at(mapping_idx);
|
||||
this->publish_state(value.value());
|
||||
});
|
||||
}
|
||||
|
||||
void TuyaSelect::control(const std::string &value) {
|
||||
if (this->optimistic_)
|
||||
this->publish_state(value);
|
||||
|
||||
auto idx = this->index_of(value);
|
||||
if (idx.has_value()) {
|
||||
uint8_t mapping = this->mappings_.at(idx.value());
|
||||
ESP_LOGV(TAG, "Setting %u datapoint value to %u:%s", this->select_id_, mapping, value.c_str());
|
||||
this->parent_->set_enum_datapoint_value(this->select_id_, mapping);
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "Invalid value %s", value.c_str());
|
||||
}
|
||||
|
||||
void TuyaSelect::dump_config() {
|
||||
LOG_SELECT("", "Tuya Select", this);
|
||||
ESP_LOGCONFIG(TAG, " Select has datapoint ID %u", this->select_id_);
|
||||
ESP_LOGCONFIG(TAG, " Options are:");
|
||||
auto options = this->traits.get_options();
|
||||
for (auto i = 0; i < this->mappings_.size(); i++) {
|
||||
ESP_LOGCONFIG(TAG, " %i: %s", this->mappings_.at(i), options.at(i).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tuya
|
||||
} // namespace esphome
|
30
esphome/components/tuya/select/tuya_select.h
Normal file
30
esphome/components/tuya/select/tuya_select.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/tuya/tuya.h"
|
||||
#include "esphome/components/select/select.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace tuya {
|
||||
|
||||
class TuyaSelect : public select::Select, public Component {
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
|
||||
void set_tuya_parent(Tuya *parent) { this->parent_ = parent; }
|
||||
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||
void set_select_id(uint8_t select_id) { this->select_id_ = select_id; }
|
||||
void set_select_mappings(std::vector<uint8_t> mappings) { this->mappings_ = std::move(mappings); }
|
||||
|
||||
protected:
|
||||
void control(const std::string &value) override;
|
||||
|
||||
Tuya *parent_;
|
||||
bool optimistic_ = false;
|
||||
uint8_t select_id_;
|
||||
std::vector<uint8_t> mappings_;
|
||||
};
|
||||
|
||||
} // namespace tuya
|
||||
} // namespace esphome
|
@ -198,6 +198,7 @@ CONF_ENABLE_TIME = "enable_time"
|
||||
CONF_ENERGY = "energy"
|
||||
CONF_ENTITY_CATEGORY = "entity_category"
|
||||
CONF_ENTITY_ID = "entity_id"
|
||||
CONF_ENUM_DATAPOINT = "enum_datapoint"
|
||||
CONF_ESP8266_DISABLE_SSL_SUPPORT = "esp8266_disable_ssl_support"
|
||||
CONF_ESPHOME = "esphome"
|
||||
CONF_ETHERNET = "ethernet"
|
||||
|
@ -61,6 +61,15 @@ tuya:
|
||||
number: 14
|
||||
inverted: true
|
||||
|
||||
select:
|
||||
- platform: tuya
|
||||
id: tuya_select
|
||||
enum_datapoint: 42
|
||||
options:
|
||||
0: Internal
|
||||
1: Floor
|
||||
2: Both
|
||||
|
||||
pipsolar:
|
||||
id: inverter0
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user