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 unit_of_measurement = 6; | ||||
|   int32 accuracy_decimals = 7; | ||||
|   bool force_update = 8; | ||||
| } | ||||
| message SensorStateResponse { | ||||
|   option (id) = 25; | ||||
|   | ||||
| @@ -1359,6 +1359,10 @@ bool ListEntitiesSensorResponse::decode_varint(uint32_t field_id, ProtoVarInt va | ||||
|       this->accuracy_decimals = value.as_int32(); | ||||
|       return true; | ||||
|     } | ||||
|     case 8: { | ||||
|       this->force_update = value.as_bool(); | ||||
|       return true; | ||||
|     } | ||||
|     default: | ||||
|       return false; | ||||
|   } | ||||
| @@ -1407,6 +1411,7 @@ void ListEntitiesSensorResponse::encode(ProtoWriteBuffer buffer) const { | ||||
|   buffer.encode_string(5, this->icon); | ||||
|   buffer.encode_string(6, this->unit_of_measurement); | ||||
|   buffer.encode_int32(7, this->accuracy_decimals); | ||||
|   buffer.encode_bool(8, this->force_update); | ||||
| } | ||||
| void ListEntitiesSensorResponse::dump_to(std::string &out) const { | ||||
|   char buffer[64]; | ||||
| @@ -1440,6 +1445,10 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const { | ||||
|   sprintf(buffer, "%d", this->accuracy_decimals); | ||||
|   out.append(buffer); | ||||
|   out.append("\n"); | ||||
|  | ||||
|   out.append("  force_update: "); | ||||
|   out.append(YESNO(this->force_update)); | ||||
|   out.append("\n"); | ||||
|   out.append("}"); | ||||
| } | ||||
| bool SensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { | ||||
|   | ||||
| @@ -364,6 +364,7 @@ class ListEntitiesSensorResponse : public ProtoMessage { | ||||
|   std::string icon{};                 // NOLINT | ||||
|   std::string unit_of_measurement{};  // NOLINT | ||||
|   int32_t accuracy_decimals{0};       // NOLINT | ||||
|   bool force_update{false};           // NOLINT | ||||
|   void encode(ProtoWriteBuffer buffer) 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()) | ||||
|     root["icon"] = this->sensor_->get_icon(); | ||||
|  | ||||
|   if (this->sensor_->get_force_update()) | ||||
|     root["force_update"] = true; | ||||
|  | ||||
|   config.command_topic = false; | ||||
| } | ||||
| bool MQTTSensorComponent::send_initial_state() { | ||||
|   | ||||
| @@ -6,10 +6,9 @@ from esphome import automation | ||||
| from esphome.components import mqtt | ||||
| 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_ON_RAW_VALUE, CONF_ON_VALUE, CONF_ON_VALUE_RANGE, \ | ||||
|     CONF_SEND_EVERY, CONF_SEND_FIRST_AT, CONF_TO, CONF_TRIGGER_ID, \ | ||||
|     CONF_UNIT_OF_MEASUREMENT, \ | ||||
|     CONF_WINDOW_SIZE, CONF_NAME, CONF_MQTT_ID | ||||
|     CONF_ON_RAW_VALUE, CONF_ON_VALUE, CONF_ON_VALUE_RANGE, CONF_SEND_EVERY, CONF_SEND_FIRST_AT, \ | ||||
|     CONF_TO, CONF_TRIGGER_ID, CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE, CONF_NAME, CONF_MQTT_ID, \ | ||||
|     CONF_FORCE_UPDATE | ||||
| from esphome.core import CORE, coroutine, coroutine_with_priority | ||||
| 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_ICON): icon, | ||||
|     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.Any(None, cv.positive_time_period_milliseconds)), | ||||
|     cv.Optional(CONF_FILTERS): validate_filters, | ||||
| @@ -258,6 +258,7 @@ def setup_sensor_core_(var, config): | ||||
|         cg.add(var.set_icon(config[CONF_ICON])) | ||||
|     if CONF_ACCURACY_DECIMALS in config: | ||||
|         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: | ||||
|         filters = yield build_filters(config[CONF_FILTERS]) | ||||
|         cg.add(var.set_filters(filters)) | ||||
|   | ||||
| @@ -18,6 +18,9 @@ namespace sensor { | ||||
|     if (!obj->unique_id().empty()) { \ | ||||
|       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. | ||||
| @@ -142,6 +145,15 @@ class Sensor : public Nameable { | ||||
|  | ||||
|   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: | ||||
|   /** 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_; | ||||
|   Filter *filter_list_{nullptr};  ///< Store all active filters. | ||||
|   bool has_state_{false}; | ||||
|   bool force_update_{false}; | ||||
| }; | ||||
|  | ||||
| class PollingSensorComponent : public PollingComponent, public Sensor { | ||||
|   | ||||
| @@ -156,6 +156,7 @@ CONF_FILTERS = 'filters' | ||||
| CONF_FILTER_OUT = 'filter_out' | ||||
| CONF_FLASH_LENGTH = 'flash_length' | ||||
| CONF_FOR = 'for' | ||||
| CONF_FORCE_UPDATE = 'force_update' | ||||
| CONF_FORMALDEHYDE = 'formaldehyde' | ||||
| CONF_FORMAT = 'format' | ||||
| CONF_FREQUENCY = 'frequency' | ||||
|   | ||||
| @@ -185,6 +185,7 @@ sensor: | ||||
|     accuracy_decimals: 5 | ||||
|     expire_after: 120s | ||||
|     setup_priority: -100 | ||||
|     force_update: true | ||||
|     filters: | ||||
|       - offset: 2.0 | ||||
|       - multiply: 1.2 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user