From 5645be4e0f8ab88026aad03340a846d65602839c Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Mon, 17 May 2021 01:16:22 +0200 Subject: [PATCH] Add attribute support to Home Assistant sensors (#1770) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/api/api.proto | 2 ++ esphome/components/api/api_connection.cpp | 4 +++- esphome/components/api/api_pb2.cpp | 18 +++++++++++++++ esphome/components/api/api_pb2.h | 2 ++ esphome/components/api/api_server.cpp | 4 +++- esphome/components/api/api_server.h | 4 +++- esphome/components/api/custom_api_device.h | 20 ++++++++++------- .../homeassistant/binary_sensor/__init__.py | 5 ++++- .../homeassistant_binary_sensor.cpp | 12 ++++++++-- .../homeassistant_binary_sensor.h | 2 ++ .../homeassistant/sensor/__init__.py | 4 ++++ .../sensor/homeassistant_sensor.cpp | 12 ++++++++-- .../sensor/homeassistant_sensor.h | 2 ++ .../homeassistant/text_sensor/__init__.py | 5 ++++- .../text_sensor/homeassistant_text_sensor.cpp | 22 +++++++++++++------ .../text_sensor/homeassistant_text_sensor.h | 5 ++++- esphome/const.py | 1 + tests/custom.h | 2 ++ tests/test2.yaml | 12 ++++++++++ 19 files changed, 113 insertions(+), 25 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index ede2cc6205..e228fe6874 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -561,6 +561,7 @@ message SubscribeHomeAssistantStateResponse { option (id) = 39; option (source) = SOURCE_SERVER; string entity_id = 1; + string attribute = 2; } message HomeAssistantStateResponse { @@ -570,6 +571,7 @@ message HomeAssistantStateResponse { string entity_id = 1; string state = 2; + string attribute = 3; } // ==================== IMPORT TIME ==================== diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 8098c93781..ac04e1f09f 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -642,8 +642,9 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) { } void APIConnection::on_home_assistant_state_response(const HomeAssistantStateResponse &msg) { for (auto &it : this->parent_->get_state_subs()) - if (it.entity_id == msg.entity_id) + if (it.entity_id == msg.entity_id && it.attribute.value() == msg.attribute) { it.callback(msg.state); + } } void APIConnection::execute_service(const ExecuteServiceRequest &msg) { bool found = false; @@ -660,6 +661,7 @@ void APIConnection::subscribe_home_assistant_states(const SubscribeHomeAssistant for (auto &it : this->parent_->get_state_subs()) { SubscribeHomeAssistantStateResponse resp; resp.entity_id = it.entity_id; + resp.attribute = it.attribute.value(); if (!this->send_subscribe_home_assistant_state_response(resp)) { this->on_fatal_error(); return; diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 23538b77bf..8f8e2abf58 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -2123,12 +2123,17 @@ bool SubscribeHomeAssistantStateResponse::decode_length(uint32_t field_id, Proto this->entity_id = value.as_string(); return true; } + case 2: { + this->attribute = value.as_string(); + return true; + } default: return false; } } void SubscribeHomeAssistantStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->entity_id); + buffer.encode_string(2, this->attribute); } void SubscribeHomeAssistantStateResponse::dump_to(std::string &out) const { char buffer[64]; @@ -2136,6 +2141,10 @@ void SubscribeHomeAssistantStateResponse::dump_to(std::string &out) const { out.append(" entity_id: "); out.append("'").append(this->entity_id).append("'"); out.append("\n"); + + out.append(" attribute: "); + out.append("'").append(this->attribute).append("'"); + out.append("\n"); out.append("}"); } bool HomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { @@ -2148,6 +2157,10 @@ bool HomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDel this->state = value.as_string(); return true; } + case 3: { + this->attribute = value.as_string(); + return true; + } default: return false; } @@ -2155,6 +2168,7 @@ bool HomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDel void HomeAssistantStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->entity_id); buffer.encode_string(2, this->state); + buffer.encode_string(3, this->attribute); } void HomeAssistantStateResponse::dump_to(std::string &out) const { char buffer[64]; @@ -2166,6 +2180,10 @@ void HomeAssistantStateResponse::dump_to(std::string &out) const { out.append(" state: "); out.append("'").append(this->state).append("'"); out.append("\n"); + + out.append(" attribute: "); + out.append("'").append(this->attribute).append("'"); + out.append("\n"); out.append("}"); } void GetTimeRequest::encode(ProtoWriteBuffer buffer) const {} diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 2ef92ce6f5..5715a7f50f 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -557,6 +557,7 @@ class SubscribeHomeAssistantStatesRequest : public ProtoMessage { class SubscribeHomeAssistantStateResponse : public ProtoMessage { public: std::string entity_id{}; + std::string attribute{}; void encode(ProtoWriteBuffer buffer) const override; void dump_to(std::string &out) const override; @@ -567,6 +568,7 @@ class HomeAssistantStateResponse : public ProtoMessage { public: std::string entity_id{}; std::string state{}; + std::string attribute{}; void encode(ProtoWriteBuffer buffer) const override; void dump_to(std::string &out) const override; diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 25ae9a98a3..dd77f2004f 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -208,9 +208,11 @@ void APIServer::send_homeassistant_service_call(const HomeassistantServiceRespon } } APIServer::APIServer() { global_api_server = this; } -void APIServer::subscribe_home_assistant_state(std::string entity_id, std::function f) { +void APIServer::subscribe_home_assistant_state(std::string entity_id, optional attribute, + std::function f) { this->state_subs_.push_back(HomeAssistantStateSubscription{ .entity_id = std::move(entity_id), + .attribute = std::move(attribute), .callback = std::move(f), }); } diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index db826c55c2..538a385efb 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -71,10 +71,12 @@ class APIServer : public Component, public Controller { struct HomeAssistantStateSubscription { std::string entity_id; + optional attribute; std::function callback; }; - void subscribe_home_assistant_state(std::string entity_id, std::function f); + void subscribe_home_assistant_state(std::string entity_id, optional attribute, + std::function f); const std::vector &get_state_subs() const; const std::vector &get_user_services() const { return this->user_services_; } diff --git a/esphome/components/api/custom_api_device.h b/esphome/components/api/custom_api_device.h index aac91244b6..74343904eb 100644 --- a/esphome/components/api/custom_api_device.h +++ b/esphome/components/api/custom_api_device.h @@ -76,13 +76,13 @@ class CustomAPIDevice { global_api_server->register_user_service(service); } - /** Subscribe to the state of an entity from Home Assistant. + /** Subscribe to the state (or attribute state) of an entity from Home Assistant. * * Usage: * * ```cpp * void setup() override { - * subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "sensor.weather_forecast"); + * subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "climate.kitchen", "current_temperature"); * } * * void on_state_changed(std::string state) { @@ -93,17 +93,19 @@ class CustomAPIDevice { * @tparam T The class type creating the service, automatically deduced from the function pointer. * @param callback The member function to call when the entity state changes. * @param entity_id The entity_id to track. + * @param attribute The entity state attribute to track. */ template - void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id) { + void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id, + const std::string &attribute = "") { auto f = std::bind(callback, (T *) this, std::placeholders::_1); - global_api_server->subscribe_home_assistant_state(entity_id, f); + global_api_server->subscribe_home_assistant_state(entity_id, optional(attribute), f); } - /** Subscribe to the state of an entity from Home Assistant. + /** Subscribe to the state (or attribute state) of an entity from Home Assistant. * * Usage: - * + *å * ```cpp * void setup() override { * subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "sensor.weather_forecast"); @@ -117,11 +119,13 @@ class CustomAPIDevice { * @tparam T The class type creating the service, automatically deduced from the function pointer. * @param callback The member function to call when the entity state changes. * @param entity_id The entity_id to track. + * @param attribute The entity state attribute to track. */ template - void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id) { + void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id, + const std::string &attribute = "") { auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1); - global_api_server->subscribe_home_assistant_state(entity_id, f); + global_api_server->subscribe_home_assistant_state(entity_id, optional(attribute), f); } /** Call a Home Assistant service from ESPHome. diff --git a/esphome/components/homeassistant/binary_sensor/__init__.py b/esphome/components/homeassistant/binary_sensor/__init__.py index 850f239d6f..cf2f3092af 100644 --- a/esphome/components/homeassistant/binary_sensor/__init__.py +++ b/esphome/components/homeassistant/binary_sensor/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import binary_sensor -from esphome.const import CONF_ENTITY_ID, CONF_ID +from esphome.const import CONF_ATTRIBUTE, CONF_ENTITY_ID, CONF_ID from .. import homeassistant_ns DEPENDENCIES = ["api"] @@ -13,6 +13,7 @@ CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(HomeassistantBinarySensor), cv.Required(CONF_ENTITY_ID): cv.entity_id, + cv.Optional(CONF_ATTRIBUTE): cv.string, } ).extend(cv.COMPONENT_SCHEMA) @@ -23,3 +24,5 @@ def to_code(config): yield binary_sensor.register_binary_sensor(var, config) cg.add(var.set_entity_id(config[CONF_ENTITY_ID])) + if CONF_ATTRIBUTE in config: + cg.add(var.set_attribute(config[CONF_ATTRIBUTE])) diff --git a/esphome/components/homeassistant/binary_sensor/homeassistant_binary_sensor.cpp b/esphome/components/homeassistant/binary_sensor/homeassistant_binary_sensor.cpp index 203f6d8a24..cf2415d9c0 100644 --- a/esphome/components/homeassistant/binary_sensor/homeassistant_binary_sensor.cpp +++ b/esphome/components/homeassistant/binary_sensor/homeassistant_binary_sensor.cpp @@ -8,7 +8,7 @@ namespace homeassistant { static const char *TAG = "homeassistant.binary_sensor"; void HomeassistantBinarySensor::setup() { - api::global_api_server->subscribe_home_assistant_state(this->entity_id_, [this](std::string state) { + api::global_api_server->subscribe_home_assistant_state(this->entity_id_, this->attribute_, [this](std::string state) { auto val = parse_on_off(state.c_str()); switch (val) { case PARSE_NONE: @@ -18,7 +18,12 @@ void HomeassistantBinarySensor::setup() { case PARSE_ON: case PARSE_OFF: bool new_state = val == PARSE_ON; - ESP_LOGD(TAG, "'%s': Got state %s", this->entity_id_.c_str(), ONOFF(new_state)); + if (this->attribute_.has_value()) { + ESP_LOGD(TAG, "'%s::%s': Got attribute state %s", this->entity_id_.c_str(), this->attribute_.value().c_str(), + ONOFF(new_state)); + } else { + ESP_LOGD(TAG, "'%s': Got state %s", this->entity_id_.c_str(), ONOFF(new_state)); + } if (this->initial_) this->publish_initial_state(new_state); else @@ -31,6 +36,9 @@ void HomeassistantBinarySensor::setup() { void HomeassistantBinarySensor::dump_config() { LOG_BINARY_SENSOR("", "Homeassistant Binary Sensor", this); ESP_LOGCONFIG(TAG, " Entity ID: '%s'", this->entity_id_.c_str()); + if (this->attribute_.has_value()) { + ESP_LOGCONFIG(TAG, " Attribute: '%s'", this->attribute_.value().c_str()); + } } float HomeassistantBinarySensor::get_setup_priority() const { return setup_priority::AFTER_WIFI; } diff --git a/esphome/components/homeassistant/binary_sensor/homeassistant_binary_sensor.h b/esphome/components/homeassistant/binary_sensor/homeassistant_binary_sensor.h index e468fd00eb..7026496295 100644 --- a/esphome/components/homeassistant/binary_sensor/homeassistant_binary_sensor.h +++ b/esphome/components/homeassistant/binary_sensor/homeassistant_binary_sensor.h @@ -9,12 +9,14 @@ namespace homeassistant { class HomeassistantBinarySensor : public binary_sensor::BinarySensor, public Component { public: void set_entity_id(const std::string &entity_id) { entity_id_ = entity_id; } + void set_attribute(const std::string &attribute) { attribute_ = attribute; } void setup() override; void dump_config() override; float get_setup_priority() const override; protected: std::string entity_id_; + optional attribute_; bool initial_{true}; }; diff --git a/esphome/components/homeassistant/sensor/__init__.py b/esphome/components/homeassistant/sensor/__init__.py index 9c19c7867f..c754ae295b 100644 --- a/esphome/components/homeassistant/sensor/__init__.py +++ b/esphome/components/homeassistant/sensor/__init__.py @@ -2,6 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor from esphome.const import ( + CONF_ATTRIBUTE, CONF_ENTITY_ID, CONF_ID, ICON_EMPTY, @@ -22,6 +23,7 @@ CONFIG_SCHEMA = sensor.sensor_schema( { cv.GenerateID(): cv.declare_id(HomeassistantSensor), cv.Required(CONF_ENTITY_ID): cv.entity_id, + cv.Optional(CONF_ATTRIBUTE): cv.string, } ) @@ -32,3 +34,5 @@ def to_code(config): yield sensor.register_sensor(var, config) cg.add(var.set_entity_id(config[CONF_ENTITY_ID])) + if CONF_ATTRIBUTE in config: + cg.add(var.set_attribute(config[CONF_ATTRIBUTE])) diff --git a/esphome/components/homeassistant/sensor/homeassistant_sensor.cpp b/esphome/components/homeassistant/sensor/homeassistant_sensor.cpp index 6b1299f70e..5f7916403e 100644 --- a/esphome/components/homeassistant/sensor/homeassistant_sensor.cpp +++ b/esphome/components/homeassistant/sensor/homeassistant_sensor.cpp @@ -8,7 +8,7 @@ namespace homeassistant { static const char *TAG = "homeassistant.sensor"; void HomeassistantSensor::setup() { - api::global_api_server->subscribe_home_assistant_state(this->entity_id_, [this](std::string state) { + api::global_api_server->subscribe_home_assistant_state(this->entity_id_, this->attribute_, [this](std::string state) { auto val = parse_float(state); if (!val.has_value()) { ESP_LOGW(TAG, "Can't convert '%s' to number!", state.c_str()); @@ -16,13 +16,21 @@ void HomeassistantSensor::setup() { return; } - ESP_LOGD(TAG, "'%s': Got state %.2f", this->entity_id_.c_str(), *val); + if (this->attribute_.has_value()) { + ESP_LOGD(TAG, "'%s::%s': Got attribute state %.2f", this->entity_id_.c_str(), this->attribute_.value().c_str(), + *val); + } else { + ESP_LOGD(TAG, "'%s': Got state %.2f", this->entity_id_.c_str(), *val); + } this->publish_state(*val); }); } void HomeassistantSensor::dump_config() { LOG_SENSOR("", "Homeassistant Sensor", this); ESP_LOGCONFIG(TAG, " Entity ID: '%s'", this->entity_id_.c_str()); + if (this->attribute_.has_value()) { + ESP_LOGCONFIG(TAG, " Attribute: '%s'", this->attribute_.value().c_str()); + } } float HomeassistantSensor::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } diff --git a/esphome/components/homeassistant/sensor/homeassistant_sensor.h b/esphome/components/homeassistant/sensor/homeassistant_sensor.h index baca6594c1..53b288d7d4 100644 --- a/esphome/components/homeassistant/sensor/homeassistant_sensor.h +++ b/esphome/components/homeassistant/sensor/homeassistant_sensor.h @@ -9,12 +9,14 @@ namespace homeassistant { class HomeassistantSensor : public sensor::Sensor, public Component { public: void set_entity_id(const std::string &entity_id) { entity_id_ = entity_id; } + void set_attribute(const std::string &attribute) { attribute_ = attribute; } void setup() override; void dump_config() override; float get_setup_priority() const override; protected: std::string entity_id_; + optional attribute_; }; } // namespace homeassistant diff --git a/esphome/components/homeassistant/text_sensor/__init__.py b/esphome/components/homeassistant/text_sensor/__init__.py index 478bd1c3d2..ed14615b80 100644 --- a/esphome/components/homeassistant/text_sensor/__init__.py +++ b/esphome/components/homeassistant/text_sensor/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import text_sensor -from esphome.const import CONF_ENTITY_ID, CONF_ID +from esphome.const import CONF_ATTRIBUTE, CONF_ENTITY_ID, CONF_ID from .. import homeassistant_ns DEPENDENCIES = ["api"] @@ -14,6 +14,7 @@ CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(HomeassistantTextSensor), cv.Required(CONF_ENTITY_ID): cv.entity_id, + cv.Optional(CONF_ATTRIBUTE): cv.string, } ) @@ -24,3 +25,5 @@ def to_code(config): yield text_sensor.register_text_sensor(var, config) cg.add(var.set_entity_id(config[CONF_ENTITY_ID])) + if CONF_ATTRIBUTE in config: + cg.add(var.set_attribute(config[CONF_ATTRIBUTE])) diff --git a/esphome/components/homeassistant/text_sensor/homeassistant_text_sensor.cpp b/esphome/components/homeassistant/text_sensor/homeassistant_text_sensor.cpp index 67fbf3cd5d..07b06cad3c 100644 --- a/esphome/components/homeassistant/text_sensor/homeassistant_text_sensor.cpp +++ b/esphome/components/homeassistant/text_sensor/homeassistant_text_sensor.cpp @@ -7,16 +7,24 @@ namespace homeassistant { static const char *TAG = "homeassistant.text_sensor"; -void HomeassistantTextSensor::dump_config() { - LOG_TEXT_SENSOR("", "Homeassistant Text Sensor", this); - ESP_LOGCONFIG(TAG, " Entity ID: '%s'", this->entity_id_.c_str()); -} void HomeassistantTextSensor::setup() { - api::global_api_server->subscribe_home_assistant_state(this->entity_id_, [this](std::string state) { - ESP_LOGD(TAG, "'%s': Got state '%s'", this->entity_id_.c_str(), state.c_str()); + api::global_api_server->subscribe_home_assistant_state(this->entity_id_, this->attribute_, [this](std::string state) { + if (this->attribute_.has_value()) { + ESP_LOGD(TAG, "'%s::%s': Got attribute state '%s'", this->entity_id_.c_str(), this->attribute_.value().c_str(), + state.c_str()); + } else { + ESP_LOGD(TAG, "'%s': Got state '%s'", this->entity_id_.c_str(), state.c_str()); + } this->publish_state(state); }); } - +void HomeassistantTextSensor::dump_config() { + LOG_TEXT_SENSOR("", "Homeassistant Text Sensor", this); + ESP_LOGCONFIG(TAG, " Entity ID: '%s'", this->entity_id_.c_str()); + if (this->attribute_.has_value()) { + ESP_LOGCONFIG(TAG, " Attribute: '%s'", this->attribute_.value().c_str()); + } +} +float HomeassistantTextSensor::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } } // namespace homeassistant } // namespace esphome diff --git a/esphome/components/homeassistant/text_sensor/homeassistant_text_sensor.h b/esphome/components/homeassistant/text_sensor/homeassistant_text_sensor.h index 02a74af1db..ce6b2c2c3f 100644 --- a/esphome/components/homeassistant/text_sensor/homeassistant_text_sensor.h +++ b/esphome/components/homeassistant/text_sensor/homeassistant_text_sensor.h @@ -9,11 +9,14 @@ namespace homeassistant { class HomeassistantTextSensor : public text_sensor::TextSensor, public Component { public: void set_entity_id(const std::string &entity_id) { entity_id_ = entity_id; } - void dump_config() override; + void set_attribute(const std::string &attribute) { attribute_ = attribute; } void setup() override; + void dump_config() override; + float get_setup_priority() const override; protected: std::string entity_id_; + optional attribute_; }; } // namespace homeassistant diff --git a/esphome/const.py b/esphome/const.py index e6ce4a6ba2..a83e090285 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -66,6 +66,7 @@ CONF_ARGS = "args" CONF_ASSUMED_STATE = "assumed_state" CONF_AT = "at" CONF_ATTENUATION = "attenuation" +CONF_ATTRIBUTE = "attribute" CONF_AUTH = "auth" CONF_AUTO_MODE = "auto_mode" CONF_AUTOMATION_ID = "automation_id" diff --git a/tests/custom.h b/tests/custom.h index 278e300785..f1a35b9b3c 100644 --- a/tests/custom.h +++ b/tests/custom.h @@ -49,6 +49,7 @@ class CustomNativeAPI : public Component, public CustomAPIDevice { register_service(&CustomNativeAPI::on_start_dryer, "start_dryer", {"value"}); register_service(&CustomNativeAPI::on_many_values, "many_values", {"bool", "int", "float", "str1", "str2"}); subscribe_homeassistant_state(&CustomNativeAPI::on_light_state, "light.my_light"); + subscribe_homeassistant_state(&CustomNativeAPI::on_brightness_state, "light.my_light", "brightness"); } void on_hello_world() { ESP_LOGD("custom_api", "Hello World from native API service!"); } @@ -69,4 +70,5 @@ class CustomNativeAPI : public Component, public CustomAPIDevice { call_homeassistant_service("homeassistant.restart"); } void on_light_state(std::string state) { ESP_LOGD("custom_api", "Got state %s", state.c_str()); } + void on_brightness_state(std::string state) { ESP_LOGD("custom_api", "Got attribute state %s", state.c_str()); } }; diff --git a/tests/test2.yaml b/tests/test2.yaml index 9b4db1477f..faa76300cc 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -63,6 +63,10 @@ sensor: - platform: homeassistant entity_id: sensor.hello_world id: ha_hello_world + - platform: homeassistant + entity_id: climate.living_room + attribute: temperature + id: ha_hello_world_temperature - platform: ble_rssi mac_address: AC:37:43:77:5F:4C name: 'BLE Google Home Mini RSSI value' @@ -246,6 +250,10 @@ binary_sensor: - platform: homeassistant entity_id: binary_sensor.hello_world id: ha_hello_world_binary + - platform: homeassistant + entity_id: binary_sensor.hello + attribute: world + id: ha_hello_world_binary_attribute - platform: ble_presence mac_address: AC:37:43:77:5F:4C name: 'ESP32 BLE Tracker Google Home Mini' @@ -355,6 +363,10 @@ text_sensor: - platform: homeassistant entity_id: sensor.hello_world2 id: ha_hello_world2 + - platform: homeassistant + entity_id: sensor.hello_world3 + id: ha_hello_world3 + attribute: some_attribute - platform: ble_scanner name: Scanner