Add functioning power and btaudio switches

This commit is contained in:
sqozz 2024-09-16 02:25:05 +02:00
parent ce09d85bd3
commit 6bf6ecc114
5 changed files with 55 additions and 15 deletions

View file

@ -36,3 +36,10 @@ text_sensor:
- platform: tw7100 - platform: tw7100
serial: serial:
name: "Serial number" name: "Serial number"
switch:
- platform: tw7100
PWR:
name: "Power"
BTAUDIO:
name: "Bluetooth Audio"

View file

@ -16,6 +16,9 @@ CONFIG_SCHEMA = cv.Schema(
cv.Optional("PWR"): switch.switch_schema( cv.Optional("PWR"): switch.switch_schema(
tw7100Switch tw7100Switch
), ),
cv.Optional("BTAUDIO"): switch.switch_schema(
tw7100Switch
),
} }
) )
@ -27,3 +30,10 @@ async def to_code(config):
switch_ = await switch.new_switch(config["PWR"]) switch_ = await switch.new_switch(config["PWR"])
cg.add(switch_.set_cmd("PWR")) cg.add(switch_.set_cmd("PWR"))
cg.add(switch_.set_tw7100_parent(parent)) cg.add(switch_.set_tw7100_parent(parent))
cg.add(parent.set_set_power(switch_))
if "BTAUDIO" in config:
switch_ = await switch.new_switch(config["BTAUDIO"])
cg.add(switch_.set_cmd("BTAUDIO"))
cg.add(switch_.set_tw7100_parent(parent))
cg.add(parent.set_set_btaudio(switch_))

View file

@ -15,11 +15,17 @@ void tw7100Switch::dump_config() {
void tw7100Switch::write_state(bool state) { void tw7100Switch::write_state(bool state) {
static const char *const TAG = "write_state()"; static const char *const TAG = "write_state()";
ESP_LOGV(TAG, "write switch state for cmd: %s", this->cmd_.c_str()); ESP_LOGV(TAG, "write switch state for cmd: %s, new state: %i", this->cmd_.c_str(), state);
parent_->push_cmd("PWR?"); if (cmd_ == "PWR") {
// TODO: actually send something! std::string param = state ? "ON" : "OFF";
// TODO: check response before publishing state ESP_LOGV(TAG, "pushing back cmd %s with param %s", cmd_.c_str(), param.c_str());
publish_state(state); parent_->push_cmd(cmd_, param);
} else if (cmd_ == "BTAUDIO") {
char param [3];
sprintf(param, "%02d", state);
ESP_LOGV(TAG, "pushing back cmd %s with param %s", cmd_.c_str(), param);
parent_->push_cmd(cmd_, param);
}
} }
} // namespace tw7100 } // namespace tw7100

View file

@ -9,6 +9,7 @@ namespace tw7100 {
bool waiting_for_answer = false; bool waiting_for_answer = false;
std::deque<std::string> cmd_queue; std::deque<std::string> cmd_queue;
unsigned long last_set_cmd_timestamp;
std::map<int, std::string> sourcelist; std::map<int, std::string> sourcelist;
std::vector<std::string> pwr_off_query_cmds{ "PWR?", "LAMP?" }; std::vector<std::string> pwr_off_query_cmds{ "PWR?", "LAMP?" };
@ -73,15 +74,15 @@ std::vector<std::string> pwr_on_query_cmds{
"SPEED?", "SPEED?",
"ILLUM?", "ILLUM?",
"STANDBYCONF?", "STANDBYCONF?",
"PRODUCT?",
*/ */
// "PRODUCT?",
// //
// Home Screen settings // Home Screen settings
// "AUTOHOME?", // TODO: implement parser // "AUTOHOME?", // TODO: implement parser
// Network settings // Network settings
// "WLPWR?", // TODO: implement parser // "WLPWR?", // TODO: implement parser
// Bluetooth // Bluetooth
// "BTAUDIO?", // TODO: implement parser "BTAUDIO?", // TODO: implement parser
// Information // Information
"SIGNAL?", "SIGNAL?",
// "SOURCELIST?" // Pushed on demand if sensor value is empty (e.g. after boot-up) // "SOURCELIST?" // Pushed on demand if sensor value is empty (e.g. after boot-up)
@ -124,13 +125,17 @@ void tw7100Component::loop() {
std::string response = readStringUntil(':'); std::string response = readStringUntil(':');
if (response == "") { // no response on bus, we can use our time to do something else if (response == "") { // no response on bus, we can use our time to do something else
if (!cmd_queue.empty() && !waiting_for_answer) { if (!cmd_queue.empty() && !waiting_for_answer && (millis() - last_set_cmd_timestamp > _timeout_after_cmd)) {
waiting_for_answer = true;
std::string cmd = cmd_queue.front(); std::string cmd = cmd_queue.front();
cmd_queue.pop_front(); cmd_queue.pop_front();
ESP_LOGV(TAG, "sending out command: %s", cmd.c_str()); ESP_LOGV(TAG, "sending out command: %s", cmd.c_str());
write_str((cmd + "\r\n").c_str()); write_str((cmd + "\r\n").c_str());
flush(); flush();
if (cmd.find("?") != std::string::npos) { // only wait for response on CMD? requests
waiting_for_answer = true;
} else {
last_set_cmd_timestamp = millis();
}
} }
} else { // response found, handle eventual errors } else { // response found, handle eventual errors
ESP_LOGV(TAG, "buffer content: %s", response.c_str()); ESP_LOGV(TAG, "buffer content: %s", response.c_str());
@ -159,10 +164,13 @@ void tw7100Component::dump_config() {
this->check_uart_settings(9600); this->check_uart_settings(9600);
}; };
void tw7100Component::push_cmd(std::string cmd) { void tw7100Component::push_cmd(std::string cmd, std::string param) {
static const char *const TAG = "push_cmd()"; static const char *const TAG = "push_cmd()";
cmd_queue.push_front(cmd); if (powered_->state) {
ESP_LOGV(TAG, "pushing priority cmd (%s) from external component", cmd.c_str()); ESP_LOGV(TAG, "pushing priority cmd (%s) from external component", cmd.c_str());
cmd_queue.push_front(cmd + "?");
cmd_queue.push_front(cmd + " " + param);
}
} }
void tw7100Component::update_sensor(std::pair<std::string, std::string> data) { void tw7100Component::update_sensor(std::pair<std::string, std::string> data) {
@ -173,6 +181,7 @@ void tw7100Component::update_sensor(std::pair<std::string, std::string> data) {
ESP_LOGV(TAG, "updating power sensors"); ESP_LOGV(TAG, "updating power sensors");
int value = std::stoi(value_string); int value = std::stoi(value_string);
powered_->publish_state(value > 0); powered_->publish_state(value > 0);
power_switch_->publish_state(value > 0); // ack previous cmd or update switch
power_status_->publish_state(value); power_status_->publish_state(value);
} else if (cmd == "LAMP") { } else if (cmd == "LAMP") {
ESP_LOGV(TAG, "updating lamp sensors"); ESP_LOGV(TAG, "updating lamp sensors");
@ -212,6 +221,10 @@ void tw7100Component::update_sensor(std::pair<std::string, std::string> data) {
// TODO: if we exceed parse_rounds we most likely encountered a critical issue, inform user somehow // TODO: if we exceed parse_rounds we most likely encountered a critical issue, inform user somehow
} else if (cmd == "SNO") { } else if (cmd == "SNO") {
serial_->publish_state(value_string); serial_->publish_state(value_string);
} else if (cmd == "BTAUDIO") {
ESP_LOGV(TAG, "updating btaudio switch");
int value = std::stoi(value_string);
btaudio_switch_->publish_state(value > 0);
} else { } else {
ESP_LOGW(TAG, "Command %s unknown, skipping updating sensor with value", cmd.c_str()); ESP_LOGW(TAG, "Command %s unknown, skipping updating sensor with value", cmd.c_str());
} }

View file

@ -5,6 +5,7 @@
#include "esphome/components/sensor/sensor.h" #include "esphome/components/sensor/sensor.h"
#include "esphome/components/binary_sensor/binary_sensor.h" #include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/text_sensor/text_sensor.h" #include "esphome/components/text_sensor/text_sensor.h"
#include "esphome/components/switch/switch.h"
#include "esphome/components/uart/uart.h" #include "esphome/components/uart/uart.h"
namespace esphome { namespace esphome {
@ -14,12 +15,13 @@ class tw7100Component : public PollingComponent, public uart::UARTDevice {
private: private:
unsigned long _max_loop_time = 30; unsigned long _max_loop_time = 30;
unsigned long _readStringUntil_timeout = _max_loop_time/5; // number of milliseconds to wait for the next char before aborting timed read unsigned long _readStringUntil_timeout = _max_loop_time/5; // number of milliseconds to wait for the next char before aborting timed read
unsigned long _timeout_after_cmd = 1000;
public: public:
tw7100Component() = default; tw7100Component() = default;
std::string readStringUntil(char terminator); std::string readStringUntil(char terminator);
void push_cmd(std::string cmd); void push_cmd(std::string cmd, std::string param);
void update_sensor(std::pair<std::string, std::string> data); void update_sensor(std::pair<std::string, std::string> data);
std::pair<std::string, std::string> parse_response(std::string data); std::pair<std::string, std::string> parse_response(std::string data);
int timedRead(void); int timedRead(void);
@ -35,7 +37,8 @@ class tw7100Component : public PollingComponent, public uart::UARTDevice {
void set_signal_status(sensor::Sensor *signal_status) { this->signal_status_ = signal_status; } void set_signal_status(sensor::Sensor *signal_status) { this->signal_status_ = signal_status; }
void set_luminance_level(sensor::Sensor *luminance_level) { this->luminance_level_ = luminance_level; } void set_luminance_level(sensor::Sensor *luminance_level) { this->luminance_level_ = luminance_level; }
void set_serial(text_sensor::TextSensor *serial) { this->serial_ = serial; } void set_serial(text_sensor::TextSensor *serial) { this->serial_ = serial; }
//void set_set_power(tw7100::tw7100Switch *switch_) { this->power_switch_ = switch_; } void set_set_power(switch_::Switch *switch_) { this->power_switch_ = switch_; }
void set_set_btaudio(switch_::Switch *switch_) { this->btaudio_switch_ = switch_; }
protected: protected:
binary_sensor::BinarySensor *powered_{nullptr}; binary_sensor::BinarySensor *powered_{nullptr};
@ -45,7 +48,8 @@ class tw7100Component : public PollingComponent, public uart::UARTDevice {
sensor::Sensor *signal_status_{nullptr}; sensor::Sensor *signal_status_{nullptr};
sensor::Sensor *luminance_level_{nullptr}; sensor::Sensor *luminance_level_{nullptr};
text_sensor::TextSensor *serial_{nullptr}; text_sensor::TextSensor *serial_{nullptr};
//tw7100::tw7100Switch *power_switch_{nullptr}; switch_::Switch *power_switch_{nullptr};
switch_::Switch *btaudio_switch_{nullptr};
}; };
} // namespace tw7100 } // namespace tw7100