mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Add sensor force_update option (#783)
* Add sensor force_update option * Add test
This commit is contained in:
		| @@ -406,6 +406,7 @@ message ListEntitiesSensorResponse { | |||||||
|   string icon = 5; |   string icon = 5; | ||||||
|   string unit_of_measurement = 6; |   string unit_of_measurement = 6; | ||||||
|   int32 accuracy_decimals = 7; |   int32 accuracy_decimals = 7; | ||||||
|  |   bool force_update = 8; | ||||||
| } | } | ||||||
| message SensorStateResponse { | message SensorStateResponse { | ||||||
|   option (id) = 25; |   option (id) = 25; | ||||||
|   | |||||||
| @@ -1359,6 +1359,10 @@ bool ListEntitiesSensorResponse::decode_varint(uint32_t field_id, ProtoVarInt va | |||||||
|       this->accuracy_decimals = value.as_int32(); |       this->accuracy_decimals = value.as_int32(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 8: { | ||||||
|  |       this->force_update = value.as_bool(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -1407,6 +1411,7 @@ void ListEntitiesSensorResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_string(5, this->icon); |   buffer.encode_string(5, this->icon); | ||||||
|   buffer.encode_string(6, this->unit_of_measurement); |   buffer.encode_string(6, this->unit_of_measurement); | ||||||
|   buffer.encode_int32(7, this->accuracy_decimals); |   buffer.encode_int32(7, this->accuracy_decimals); | ||||||
|  |   buffer.encode_bool(8, this->force_update); | ||||||
| } | } | ||||||
| void ListEntitiesSensorResponse::dump_to(std::string &out) const { | void ListEntitiesSensorResponse::dump_to(std::string &out) const { | ||||||
|   char buffer[64]; |   char buffer[64]; | ||||||
| @@ -1440,6 +1445,10 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const { | |||||||
|   sprintf(buffer, "%d", this->accuracy_decimals); |   sprintf(buffer, "%d", this->accuracy_decimals); | ||||||
|   out.append(buffer); |   out.append(buffer); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  force_update: "); | ||||||
|  |   out.append(YESNO(this->force_update)); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| bool SensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { | bool SensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { | ||||||
|   | |||||||
| @@ -364,6 +364,7 @@ class ListEntitiesSensorResponse : public ProtoMessage { | |||||||
|   std::string icon{};                 // NOLINT |   std::string icon{};                 // NOLINT | ||||||
|   std::string unit_of_measurement{};  // NOLINT |   std::string unit_of_measurement{};  // NOLINT | ||||||
|   int32_t accuracy_decimals{0};       // NOLINT |   int32_t accuracy_decimals{0};       // NOLINT | ||||||
|  |   bool force_update{false};           // NOLINT | ||||||
|   void encode(ProtoWriteBuffer buffer) const override; |   void encode(ProtoWriteBuffer buffer) const override; | ||||||
|   void dump_to(std::string &out) const override; |   void dump_to(std::string &out) const override; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -55,6 +55,9 @@ void MQTTSensorComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryCo | |||||||
|   if (!this->sensor_->get_icon().empty()) |   if (!this->sensor_->get_icon().empty()) | ||||||
|     root["icon"] = this->sensor_->get_icon(); |     root["icon"] = this->sensor_->get_icon(); | ||||||
|  |  | ||||||
|  |   if (this->sensor_->get_force_update()) | ||||||
|  |     root["force_update"] = true; | ||||||
|  |  | ||||||
|   config.command_topic = false; |   config.command_topic = false; | ||||||
| } | } | ||||||
| bool MQTTSensorComponent::send_initial_state() { | bool MQTTSensorComponent::send_initial_state() { | ||||||
|   | |||||||
| @@ -6,10 +6,9 @@ from esphome import automation | |||||||
| from esphome.components import mqtt | from esphome.components import mqtt | ||||||
| from esphome.const import CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, CONF_BELOW, \ | from esphome.const import CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, CONF_BELOW, \ | ||||||
|     CONF_EXPIRE_AFTER, CONF_FILTERS, CONF_FROM, CONF_ICON, CONF_ID, CONF_INTERNAL, \ |     CONF_EXPIRE_AFTER, CONF_FILTERS, CONF_FROM, CONF_ICON, CONF_ID, CONF_INTERNAL, \ | ||||||
|     CONF_ON_RAW_VALUE, CONF_ON_VALUE, CONF_ON_VALUE_RANGE, \ |     CONF_ON_RAW_VALUE, CONF_ON_VALUE, CONF_ON_VALUE_RANGE, CONF_SEND_EVERY, CONF_SEND_FIRST_AT, \ | ||||||
|     CONF_SEND_EVERY, CONF_SEND_FIRST_AT, CONF_TO, CONF_TRIGGER_ID, \ |     CONF_TO, CONF_TRIGGER_ID, CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE, CONF_NAME, CONF_MQTT_ID, \ | ||||||
|     CONF_UNIT_OF_MEASUREMENT, \ |     CONF_FORCE_UPDATE | ||||||
|     CONF_WINDOW_SIZE, CONF_NAME, CONF_MQTT_ID |  | ||||||
| from esphome.core import CORE, coroutine, coroutine_with_priority | from esphome.core import CORE, coroutine, coroutine_with_priority | ||||||
| from esphome.util import Registry | from esphome.util import Registry | ||||||
|  |  | ||||||
| @@ -87,6 +86,7 @@ SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ | |||||||
|     cv.Optional(CONF_UNIT_OF_MEASUREMENT): unit_of_measurement, |     cv.Optional(CONF_UNIT_OF_MEASUREMENT): unit_of_measurement, | ||||||
|     cv.Optional(CONF_ICON): icon, |     cv.Optional(CONF_ICON): icon, | ||||||
|     cv.Optional(CONF_ACCURACY_DECIMALS): accuracy_decimals, |     cv.Optional(CONF_ACCURACY_DECIMALS): accuracy_decimals, | ||||||
|  |     cv.Optional(CONF_FORCE_UPDATE, default=False): cv.boolean, | ||||||
|     cv.Optional(CONF_EXPIRE_AFTER): cv.All(cv.requires_component('mqtt'), |     cv.Optional(CONF_EXPIRE_AFTER): cv.All(cv.requires_component('mqtt'), | ||||||
|                                            cv.Any(None, cv.positive_time_period_milliseconds)), |                                            cv.Any(None, cv.positive_time_period_milliseconds)), | ||||||
|     cv.Optional(CONF_FILTERS): validate_filters, |     cv.Optional(CONF_FILTERS): validate_filters, | ||||||
| @@ -258,6 +258,7 @@ def setup_sensor_core_(var, config): | |||||||
|         cg.add(var.set_icon(config[CONF_ICON])) |         cg.add(var.set_icon(config[CONF_ICON])) | ||||||
|     if CONF_ACCURACY_DECIMALS in config: |     if CONF_ACCURACY_DECIMALS in config: | ||||||
|         cg.add(var.set_accuracy_decimals(config[CONF_ACCURACY_DECIMALS])) |         cg.add(var.set_accuracy_decimals(config[CONF_ACCURACY_DECIMALS])) | ||||||
|  |     cg.add(var.set_force_update(config[CONF_FORCE_UPDATE])) | ||||||
|     if CONF_FILTERS in config: |     if CONF_FILTERS in config: | ||||||
|         filters = yield build_filters(config[CONF_FILTERS]) |         filters = yield build_filters(config[CONF_FILTERS]) | ||||||
|         cg.add(var.set_filters(filters)) |         cg.add(var.set_filters(filters)) | ||||||
|   | |||||||
| @@ -18,6 +18,9 @@ namespace sensor { | |||||||
|     if (!obj->unique_id().empty()) { \ |     if (!obj->unique_id().empty()) { \ | ||||||
|       ESP_LOGV(TAG, prefix "  Unique ID: '%s'", obj->unique_id().c_str()); \ |       ESP_LOGV(TAG, prefix "  Unique ID: '%s'", obj->unique_id().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|  |     if (obj->get_force_update()) { \ | ||||||
|  |       ESP_LOGV(TAG, prefix "  Force Update: YES"); \ | ||||||
|  |     } \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
| /** Base-class for all sensors. | /** Base-class for all sensors. | ||||||
| @@ -142,6 +145,15 @@ class Sensor : public Nameable { | |||||||
|  |  | ||||||
|   void internal_send_state_to_frontend(float state); |   void internal_send_state_to_frontend(float state); | ||||||
|  |  | ||||||
|  |   bool get_force_update() const { return force_update_; } | ||||||
|  |   /** Set this sensor's force_update mode. | ||||||
|  |    * | ||||||
|  |    * If the sensor is in force_update mode, the frontend is required to save all | ||||||
|  |    * state changes to the database when they are published, even if the state is the | ||||||
|  |    * same as before. | ||||||
|  |    */ | ||||||
|  |   void set_force_update(bool force_update) { force_update_ = force_update; } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   /** Override this to set the Home Assistant unit of measurement for this sensor. |   /** Override this to set the Home Assistant unit of measurement for this sensor. | ||||||
|    * |    * | ||||||
| @@ -174,6 +186,7 @@ class Sensor : public Nameable { | |||||||
|   optional<int8_t> accuracy_decimals_; |   optional<int8_t> accuracy_decimals_; | ||||||
|   Filter *filter_list_{nullptr};  ///< Store all active filters. |   Filter *filter_list_{nullptr};  ///< Store all active filters. | ||||||
|   bool has_state_{false}; |   bool has_state_{false}; | ||||||
|  |   bool force_update_{false}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class PollingSensorComponent : public PollingComponent, public Sensor { | class PollingSensorComponent : public PollingComponent, public Sensor { | ||||||
|   | |||||||
| @@ -156,6 +156,7 @@ CONF_FILTERS = 'filters' | |||||||
| CONF_FILTER_OUT = 'filter_out' | CONF_FILTER_OUT = 'filter_out' | ||||||
| CONF_FLASH_LENGTH = 'flash_length' | CONF_FLASH_LENGTH = 'flash_length' | ||||||
| CONF_FOR = 'for' | CONF_FOR = 'for' | ||||||
|  | CONF_FORCE_UPDATE = 'force_update' | ||||||
| CONF_FORMALDEHYDE = 'formaldehyde' | CONF_FORMALDEHYDE = 'formaldehyde' | ||||||
| CONF_FORMAT = 'format' | CONF_FORMAT = 'format' | ||||||
| CONF_FREQUENCY = 'frequency' | CONF_FREQUENCY = 'frequency' | ||||||
|   | |||||||
| @@ -185,6 +185,7 @@ sensor: | |||||||
|     accuracy_decimals: 5 |     accuracy_decimals: 5 | ||||||
|     expire_after: 120s |     expire_after: 120s | ||||||
|     setup_priority: -100 |     setup_priority: -100 | ||||||
|  |     force_update: true | ||||||
|     filters: |     filters: | ||||||
|       - offset: 2.0 |       - offset: 2.0 | ||||||
|       - multiply: 1.2 |       - multiply: 1.2 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user