mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 22:48:10 +01:00
Add Tuya select (#3469)
This commit is contained in:
parent
0665acd190
commit
f62d5d3b9d
6 changed files with 140 additions and 0 deletions
|
@ -222,6 +222,7 @@ esphome/components/tsl2591/* @wjcarpenter
|
||||||
esphome/components/tuya/binary_sensor/* @jesserockz
|
esphome/components/tuya/binary_sensor/* @jesserockz
|
||||||
esphome/components/tuya/climate/* @jesserockz
|
esphome/components/tuya/climate/* @jesserockz
|
||||||
esphome/components/tuya/number/* @frankiboy1
|
esphome/components/tuya/number/* @frankiboy1
|
||||||
|
esphome/components/tuya/select/* @bearpawmaxim
|
||||||
esphome/components/tuya/sensor/* @jesserockz
|
esphome/components/tuya/sensor/* @jesserockz
|
||||||
esphome/components/tuya/switch/* @jesserockz
|
esphome/components/tuya/switch/* @jesserockz
|
||||||
esphome/components/tuya/text_sensor/* @dentra
|
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_ENERGY = "energy"
|
||||||
CONF_ENTITY_CATEGORY = "entity_category"
|
CONF_ENTITY_CATEGORY = "entity_category"
|
||||||
CONF_ENTITY_ID = "entity_id"
|
CONF_ENTITY_ID = "entity_id"
|
||||||
|
CONF_ENUM_DATAPOINT = "enum_datapoint"
|
||||||
CONF_ESP8266_DISABLE_SSL_SUPPORT = "esp8266_disable_ssl_support"
|
CONF_ESP8266_DISABLE_SSL_SUPPORT = "esp8266_disable_ssl_support"
|
||||||
CONF_ESPHOME = "esphome"
|
CONF_ESPHOME = "esphome"
|
||||||
CONF_ETHERNET = "ethernet"
|
CONF_ETHERNET = "ethernet"
|
||||||
|
|
|
@ -61,6 +61,15 @@ tuya:
|
||||||
number: 14
|
number: 14
|
||||||
inverted: true
|
inverted: true
|
||||||
|
|
||||||
|
select:
|
||||||
|
- platform: tuya
|
||||||
|
id: tuya_select
|
||||||
|
enum_datapoint: 42
|
||||||
|
options:
|
||||||
|
0: Internal
|
||||||
|
1: Floor
|
||||||
|
2: Both
|
||||||
|
|
||||||
pipsolar:
|
pipsolar:
|
||||||
id: inverter0
|
id: inverter0
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue