From fb055750df912a56e406cf151c4513195867f792 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Tue, 12 Nov 2019 18:58:26 +0100 Subject: [PATCH] Add missing state attribute (#851) * Add api missing_state attribute Fixes https://github.com/esphome/issues/issues/828 Adds a new property for missing state, so that HA can now when a sensor does not have a state yet. * Update api.proto --- esphome/components/api/api.proto | 9 +++++ esphome/components/api/api_connection.cpp | 3 ++ esphome/components/api/api_pb2.cpp | 39 ++++++++++++++++++++++ esphome/components/api/api_pb2.h | 17 ++++++---- esphome/components/api/subscribe_state.cpp | 9 ----- 5 files changed, 62 insertions(+), 15 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 175bd3858f..4e55744384 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -216,6 +216,9 @@ message BinarySensorStateResponse { fixed32 key = 1; bool state = 2; + // If the binary sensor does not have a valid state yet. + // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller + bool missing_state = 3; } // ==================== COVER ==================== @@ -416,6 +419,9 @@ message SensorStateResponse { fixed32 key = 1; float state = 2; + // If the sensor does not have a valid state yet. + // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller + bool missing_state = 3; } // ==================== SWITCH ==================== @@ -472,6 +478,9 @@ message TextSensorStateResponse { fixed32 key = 1; string state = 2; + // If the text sensor does not have a valid state yet. + // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller + bool missing_state = 3; } // ==================== SUBSCRIBE LOGS ==================== diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index e786fe61be..d4c4a52054 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -163,6 +163,7 @@ bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary BinarySensorStateResponse resp; resp.key = binary_sensor->get_object_id_hash(); resp.state = state; + resp.missing_state = !binary_sensor->has_state(); return this->send_binary_sensor_state_response(resp); } bool APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor) { @@ -362,6 +363,7 @@ bool APIConnection::send_sensor_state(sensor::Sensor *sensor, float state) { SensorStateResponse resp{}; resp.key = sensor->get_object_id_hash(); resp.state = state; + resp.missing_state = !sensor->has_state(); return this->send_sensor_state_response(resp); } bool APIConnection::send_sensor_info(sensor::Sensor *sensor) { @@ -419,6 +421,7 @@ bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor, TextSensorStateResponse resp{}; resp.key = text_sensor->get_object_id_hash(); resp.state = std::move(state); + resp.missing_state = !text_sensor->has_state(); return this->send_text_sensor_state_response(resp); } bool APIConnection::send_text_sensor_info(text_sensor::TextSensor *text_sensor) { diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 7f45d38f1b..0b6021c224 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -404,6 +404,10 @@ bool BinarySensorStateResponse::decode_varint(uint32_t field_id, ProtoVarInt val this->state = value.as_bool(); return true; } + case 3: { + this->missing_state = value.as_bool(); + return true; + } default: return false; } @@ -421,6 +425,7 @@ bool BinarySensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value void BinarySensorStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bool(2, this->state); + buffer.encode_bool(3, this->missing_state); } void BinarySensorStateResponse::dump_to(std::string &out) const { char buffer[64]; @@ -433,6 +438,10 @@ void BinarySensorStateResponse::dump_to(std::string &out) const { out.append(" state: "); out.append(YESNO(this->state)); out.append("\n"); + + out.append(" missing_state: "); + out.append(YESNO(this->missing_state)); + out.append("\n"); out.append("}"); } bool ListEntitiesCoverResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -1451,6 +1460,16 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append("}"); } +bool SensorStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 3: { + this->missing_state = value.as_bool(); + return true; + } + default: + return false; + } +} bool SensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { switch (field_id) { case 1: { @@ -1468,6 +1487,7 @@ bool SensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { void SensorStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_float(2, this->state); + buffer.encode_bool(3, this->missing_state); } void SensorStateResponse::dump_to(std::string &out) const { char buffer[64]; @@ -1481,6 +1501,10 @@ void SensorStateResponse::dump_to(std::string &out) const { sprintf(buffer, "%g", this->state); out.append(buffer); out.append("\n"); + + out.append(" missing_state: "); + out.append(YESNO(this->missing_state)); + out.append("\n"); out.append("}"); } bool ListEntitiesSwitchResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -1700,6 +1724,16 @@ void ListEntitiesTextSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append("}"); } +bool TextSensorStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 3: { + this->missing_state = value.as_bool(); + return true; + } + default: + return false; + } +} bool TextSensorStateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { switch (field_id) { case 2: { @@ -1723,6 +1757,7 @@ bool TextSensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) void TextSensorStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_string(2, this->state); + buffer.encode_bool(3, this->missing_state); } void TextSensorStateResponse::dump_to(std::string &out) const { char buffer[64]; @@ -1735,6 +1770,10 @@ void TextSensorStateResponse::dump_to(std::string &out) const { out.append(" state: "); out.append("'").append(this->state).append("'"); out.append("\n"); + + out.append(" missing_state: "); + out.append(YESNO(this->missing_state)); + out.append("\n"); out.append("}"); } bool SubscribeLogsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index eb6a15afd4..3fe64fcb61 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -188,8 +188,9 @@ class ListEntitiesBinarySensorResponse : public ProtoMessage { }; class BinarySensorStateResponse : public ProtoMessage { public: - uint32_t key{0}; // NOLINT - bool state{false}; // NOLINT + uint32_t key{0}; // NOLINT + bool state{false}; // NOLINT + bool missing_state{false}; // NOLINT void encode(ProtoWriteBuffer buffer) const override; void dump_to(std::string &out) const override; @@ -380,13 +381,15 @@ class ListEntitiesSensorResponse : public ProtoMessage { }; class SensorStateResponse : public ProtoMessage { public: - uint32_t key{0}; // NOLINT - float state{0.0f}; // NOLINT + uint32_t key{0}; // NOLINT + float state{0.0f}; // NOLINT + bool missing_state{false}; // NOLINT void encode(ProtoWriteBuffer buffer) const override; void dump_to(std::string &out) const override; protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; class ListEntitiesSwitchResponse : public ProtoMessage { public: @@ -442,14 +445,16 @@ class ListEntitiesTextSensorResponse : public ProtoMessage { }; class TextSensorStateResponse : public ProtoMessage { public: - uint32_t key{0}; // NOLINT - std::string state{}; // NOLINT + uint32_t key{0}; // NOLINT + std::string state{}; // NOLINT + bool missing_state{false}; // NOLINT void encode(ProtoWriteBuffer buffer) const override; void dump_to(std::string &out) const override; protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; class SubscribeLogsRequest : public ProtoMessage { public: diff --git a/esphome/components/api/subscribe_state.cpp b/esphome/components/api/subscribe_state.cpp index 50d674bee2..2612a852d3 100644 --- a/esphome/components/api/subscribe_state.cpp +++ b/esphome/components/api/subscribe_state.cpp @@ -7,9 +7,6 @@ namespace api { #ifdef USE_BINARY_SENSOR bool InitialStateIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) { - if (!binary_sensor->has_state()) - return true; - return this->client_->send_binary_sensor_state(binary_sensor, binary_sensor->state); } #endif @@ -24,9 +21,6 @@ bool InitialStateIterator::on_light(light::LightState *light) { return this->cli #endif #ifdef USE_SENSOR bool InitialStateIterator::on_sensor(sensor::Sensor *sensor) { - if (!sensor->has_state()) - return true; - return this->client_->send_sensor_state(sensor, sensor->state); } #endif @@ -37,9 +31,6 @@ bool InitialStateIterator::on_switch(switch_::Switch *a_switch) { #endif #ifdef USE_TEXT_SENSOR bool InitialStateIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) { - if (!text_sensor->has_state()) - return true; - return this->client_->send_text_sensor_state(text_sensor, text_sensor->state); } #endif