From 482142094c8195e7460ae877dde26356e2c098ca Mon Sep 17 00:00:00 2001 From: sqozz Date: Mon, 16 Sep 2024 22:38:48 +0200 Subject: [PATCH] Add source select --- select/__init__.py | 31 +++++++++++++++++++++++++++++++ select/tw7100_select.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ select/tw7100_select.h | 32 ++++++++++++++++++++++++++++++++ tw7100.cpp | 8 +++++++- tw7100.h | 4 ++++ 5 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 select/__init__.py create mode 100644 select/tw7100_select.cpp create mode 100644 select/tw7100_select.h diff --git a/select/__init__.py b/select/__init__.py new file mode 100644 index 0000000..497e8f0 --- /dev/null +++ b/select/__init__.py @@ -0,0 +1,31 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import select +from esphome.const import CONF_POWER, ENTITY_CATEGORY_CONFIG, CONF_ID + +from .. import tw7100, tw7100_ns, CONF_TW7100_ID + +DEPENDENCIES = ["tw7100"] +CODEOWNERS = ["@sqozz"] + +tw7100Select = tw7100_ns.class_("tw7100Select", select.Select, cg.Component) + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(tw7100), + cv.Optional("SOURCE"): select.select_schema( + tw7100Select + ), + } +) + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_ID]) + + if "SOURCE" in config: + select_ = await select.new_select(config["SOURCE"], options=[]) + cg.add(select_.set_disabled_by_default(True)) + cg.add(select_.set_cmd("SOURCE")) + cg.add(select_.set_tw7100_parent(parent)) + cg.add(parent.set_set_source(select_)) diff --git a/select/tw7100_select.cpp b/select/tw7100_select.cpp new file mode 100644 index 0000000..500b6df --- /dev/null +++ b/select/tw7100_select.cpp @@ -0,0 +1,40 @@ +#include "tw7100_select.h" +#include "esphome/core/log.h" +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" + +namespace esphome { +namespace tw7100 { + +std::vector get_map_keys(std::map map_) { + std::vector map_keys; + for (auto element : map_) { map_keys.push_back(element.first); } + return map_keys; +}; + +void tw7100Select::setup() { + static const char *const TAG = "tw7100Select::setup()"; + if (cmd_ == "SOURCE") { + traits.set_options(get_map_keys(sources)); + } + ESP_LOGV(TAG, "control done"); +} + +void tw7100Select::dump_config() { + static const char *const TAG = "dump_config()"; + ESP_LOGCONFIG(TAG, "TW7100:"); + LOG_SELECT(TAG, "tw7100Select", this); +} + +void tw7100Select::control(const std::string &value) { + static const char *const TAG = "tw7100Select::control()"; + + if (cmd_ == "SOURCE") { + uint8_t source_number = sources[value]; + ESP_LOGV("", "Source selection: %s, sending code %02x", value.c_str(), source_number); + } + ESP_LOGV(TAG, "control done"); +}; + +} // namespace tw7100 +} // namespace esphome diff --git a/select/tw7100_select.h b/select/tw7100_select.h new file mode 100644 index 0000000..fcb4843 --- /dev/null +++ b/select/tw7100_select.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include "esphome/core/component.h" +#include "esphome/components/select/select.h" + +namespace esphome { +namespace tw7100 { + +class tw7100Component; + +class tw7100Select : public select::Select, public Component { + public: + void setup() override; + void dump_config() override; + void set_options(std::vector options) { this->traits.set_options(options); } + void set_tw7100_parent(tw7100Component *parent) { this->parent_ = parent; } + void set_cmd(std::string cmd) { this->cmd_ = cmd; } + + protected: + std::map sources = { + {"HDMI1", 0x30}, + {"LAN", 0x53}, + {"HDMI2", 0xA0} + }; + void control(const std::string &value) override; + std::string cmd_; + tw7100Component *parent_; +}; + +} // namespace tw7100 +} // namespace esphome diff --git a/tw7100.cpp b/tw7100.cpp index 27c1219..e5e74cf 100644 --- a/tw7100.cpp +++ b/tw7100.cpp @@ -26,7 +26,7 @@ std::vector pwr_on_query_cmds{ */ // // Source/Input/Resolution settings -// "SOURCE?", // TODO: implement parser + "SOURCE?", // Image settings /* "BRIGHT?", @@ -94,6 +94,7 @@ std::vector pwr_on_query_cmds{ void tw7100Component::setup() { static const char *const TAG = "setup()"; ESP_LOGV(TAG, "SETUP"); + source_select_->setup(); }; void tw7100Component::update() { @@ -227,6 +228,11 @@ void tw7100Component::update_sensor(std::pair data) { ESP_LOGV(TAG, "updating btaudio switch"); int value = std::stoi(value_string); btaudio_switch_->publish_state(value > 0); + } else if (cmd == "SOURCE") { + ESP_LOGV(TAG, "updating source select"); + auto call = source_select_->make_call(); + call.set_option(value_string); + call.perform(); } else { ESP_LOGW(TAG, "Command %s unknown, skipping updating sensor with value", cmd.c_str()); } diff --git a/tw7100.h b/tw7100.h index fa62f6d..63eb619 100644 --- a/tw7100.h +++ b/tw7100.h @@ -6,7 +6,9 @@ #include "esphome/components/binary_sensor/binary_sensor.h" #include "esphome/components/text_sensor/text_sensor.h" #include "esphome/components/switch/switch.h" +#include "esphome/components/select/select.h" #include "esphome/components/uart/uart.h" +#include "select/tw7100_select.h" namespace esphome { namespace tw7100 { @@ -39,6 +41,7 @@ class tw7100Component : public PollingComponent, public uart::UARTDevice { void set_serial(text_sensor::TextSensor *serial) { this->serial_ = serial; } void set_set_power(switch_::Switch *switch_) { this->power_switch_ = switch_; } void set_set_btaudio(switch_::Switch *switch_) { this->btaudio_switch_ = switch_; } + void set_set_source(tw7100::tw7100Select *source_) { this->source_select_ = source_; } protected: binary_sensor::BinarySensor *powered_{nullptr}; @@ -50,6 +53,7 @@ class tw7100Component : public PollingComponent, public uart::UARTDevice { text_sensor::TextSensor *serial_{nullptr}; switch_::Switch *power_switch_{nullptr}; switch_::Switch *btaudio_switch_{nullptr}; + tw7100::tw7100Select *source_select_{nullptr}; }; } // namespace tw7100