From c343d8db4a730472ceac1b8a907fa1cf9e65b3ac Mon Sep 17 00:00:00 2001 From: Oxan van Leeuwen Date: Fri, 3 Feb 2023 00:03:26 +0100 Subject: [PATCH] Add binary sensor to show whether clients are connected Co-authored-by: Joshua Spence --- components/stream_server/__init__.py | 3 +- components/stream_server/binary_sensor.py | 43 ++++++++++++++++++++++ components/stream_server/sensor.py | 41 +++++++++++++++++++++ components/stream_server/stream_server.cpp | 16 +++++++- components/stream_server/stream_server.h | 14 +++++++ 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 components/stream_server/binary_sensor.py create mode 100644 components/stream_server/sensor.py diff --git a/components/stream_server/__init__.py b/components/stream_server/__init__.py index e4a3dac..16df63d 100644 --- a/components/stream_server/__init__.py +++ b/components/stream_server/__init__.py @@ -26,7 +26,8 @@ DEPENDENCIES = ["uart", "network"] MULTI_CONF = True -StreamServerComponent = cg.global_ns.class_("StreamServerComponent", cg.Component) +ns = cg.global_ns +StreamServerComponent = ns.class_("StreamServerComponent", cg.Component) def validate_buffer_size(buffer_size): diff --git a/components/stream_server/binary_sensor.py b/components/stream_server/binary_sensor.py new file mode 100644 index 0000000..eb0f029 --- /dev/null +++ b/components/stream_server/binary_sensor.py @@ -0,0 +1,43 @@ +# Copyright (C) 2023 Oxan van Leeuwen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import binary_sensor +from esphome.const import ( + DEVICE_CLASS_CONNECTIVITY, + ENTITY_CATEGORY_DIAGNOSTIC, +) +from . import ns, StreamServerComponent + +CONF_CONNECTED = "connected" +CONF_STREAM_SERVER = "stream_server" + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_STREAM_SERVER): cv.use_id(StreamServerComponent), + cv.Required(CONF_CONNECTED): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_CONNECTIVITY, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + } +) + + +async def to_code(config): + server = await cg.get_variable(config[CONF_STREAM_SERVER]) + + sens = await binary_sensor.new_binary_sensor(config[CONF_CONNECTED]) + cg.add(server.set_connected_sensor(sens)) diff --git a/components/stream_server/sensor.py b/components/stream_server/sensor.py new file mode 100644 index 0000000..a64af60 --- /dev/null +++ b/components/stream_server/sensor.py @@ -0,0 +1,41 @@ +# Copyright (C) 2023 Oxan van Leeuwen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + ENTITY_CATEGORY_DIAGNOSTIC, +) +from . import ns, StreamServerComponent + +CONF_CONNECTION_COUNT = "connection_count" +CONF_STREAM_SERVER = "stream_server" + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_STREAM_SERVER): cv.use_id(StreamServerComponent), + cv.Required(CONF_CONNECTION_COUNT): sensor.sensor_schema( + accuracy_decimals=0, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ) + } +) + +async def to_code(config): + server = await cg.get_variable(config[CONF_STREAM_SERVER]) + + sens = await sensor.new_sensor(config[CONF_CONNECTION_COUNT]) + cg.add(server.set_connection_count_sensor(sens)) diff --git a/components/stream_server/stream_server.cpp b/components/stream_server/stream_server.cpp index 4d51791..93f4954 100644 --- a/components/stream_server/stream_server.cpp +++ b/components/stream_server/stream_server.cpp @@ -53,6 +53,9 @@ void StreamServerComponent::loop() { void StreamServerComponent::dump_config() { ESP_LOGCONFIG(TAG, "Stream Server:"); ESP_LOGCONFIG(TAG, " Address: %s:%u", esphome::network::get_use_address().c_str(), this->port_); +#ifdef USE_BINARY_SENSOR + LOG_BINARY_SENSOR(" ", "Connected:", this->connected_sensor_); +#endif } void StreamServerComponent::on_shutdown() { @@ -60,6 +63,13 @@ void StreamServerComponent::on_shutdown() { client.socket->shutdown(SHUT_RDWR); } +void StreamServerComponent::publish_sensor() { +#ifdef USE_BINARY_SENSOR + if (this->connected_sensor_) + this->connected_sensor_->publish_state(this->clients_.size() > 0); +#endif +} + void StreamServerComponent::accept() { struct sockaddr_storage client_addr; socklen_t client_addrlen = sizeof(client_addr); @@ -71,12 +81,16 @@ void StreamServerComponent::accept() { std::string identifier = socket->getpeername(); this->clients_.emplace_back(std::move(socket), identifier, this->buf_head_); ESP_LOGD(TAG, "New client connected from %s", identifier.c_str()); + this->publish_sensor(); } void StreamServerComponent::cleanup() { auto discriminator = [](const Client &client) { return !client.disconnected; }; auto last_client = std::partition(this->clients_.begin(), this->clients_.end(), discriminator); - this->clients_.erase(last_client, this->clients_.end()); + if (last_client != this->clients_.end()) { + this->clients_.erase(last_client, this->clients_.end()); + this->publish_sensor(); + } } void StreamServerComponent::read() { diff --git a/components/stream_server/stream_server.h b/components/stream_server/stream_server.h index e188096..3be5fd7 100644 --- a/components/stream_server/stream_server.h +++ b/components/stream_server/stream_server.h @@ -20,6 +20,10 @@ #include "esphome/components/socket/socket.h" #include "esphome/components/uart/uart.h" +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif + #include #include #include @@ -31,6 +35,10 @@ public: void set_uart_parent(esphome::uart::UARTComponent *parent) { this->stream_ = parent; } void set_buffer_size(size_t size) { this->buf_size_ = size; } +#ifdef USE_BINARY_SENSOR + void set_connected_sensor(esphome::binary_sensor::BinarySensor *connected) { this->connected_sensor_ = connected; } +#endif + void setup() override; void loop() override; void dump_config() override; @@ -41,6 +49,8 @@ public: void set_port(uint16_t port) { this->port_ = port; } protected: + void publish_sensor(); + void accept(); void cleanup(); void read(); @@ -64,6 +74,10 @@ protected: uint16_t port_; size_t buf_size_; +#ifdef USE_BINARY_SENSOR + esphome::binary_sensor::BinarySensor *connected_sensor_; +#endif + std::unique_ptr buf_{}; size_t buf_head_{0}; size_t buf_tail_{0};