mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Modbus Controller added some features (#5318)
This commit is contained in:
		| @@ -8,6 +8,7 @@ from .const import ( | ||||
|     CONF_BITMASK, | ||||
|     CONF_BYTE_OFFSET, | ||||
|     CONF_COMMAND_THROTTLE, | ||||
|     CONF_OFFLINE_SKIP_UPDATES, | ||||
|     CONF_CUSTOM_COMMAND, | ||||
|     CONF_FORCE_NEW_RANGE, | ||||
|     CONF_MODBUS_CONTROLLER_ID, | ||||
| @@ -104,6 +105,7 @@ CONFIG_SCHEMA = cv.All( | ||||
|             cv.Optional( | ||||
|                 CONF_COMMAND_THROTTLE, default="0ms" | ||||
|             ): cv.positive_time_period_milliseconds, | ||||
|             cv.Optional(CONF_OFFLINE_SKIP_UPDATES, default=0): cv.positive_int, | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
| @@ -206,8 +208,9 @@ async def add_modbus_base_properties( | ||||
|  | ||||
|  | ||||
| async def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_COMMAND_THROTTLE]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     cg.add(var.set_command_throttle(config[CONF_COMMAND_THROTTLE])) | ||||
|     cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES])) | ||||
|     await register_modbus_device(var, config) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| CONF_BITMASK = "bitmask" | ||||
| CONF_BYTE_OFFSET = "byte_offset" | ||||
| CONF_COMMAND_THROTTLE = "command_throttle" | ||||
| CONF_OFFLINE_SKIP_UPDATES = "offline_skip_updates" | ||||
| CONF_CUSTOM_COMMAND = "custom_command" | ||||
| CONF_FORCE_NEW_RANGE = "force_new_range" | ||||
| CONF_MODBUS_CONTROLLER_ID = "modbus_controller_id" | ||||
|   | ||||
| @@ -26,6 +26,17 @@ bool ModbusController::send_next_command_() { | ||||
|  | ||||
|     // remove from queue if command was sent too often | ||||
|     if (command->send_countdown < 1) { | ||||
|       if (!this->module_offline_) { | ||||
|         ESP_LOGW(TAG, "Modbus device=%d set offline", this->address_); | ||||
|  | ||||
|         if (this->offline_skip_updates_ > 0) { | ||||
|           // Update skip_updates_counter to stop flooding channel with timeouts | ||||
|           for (auto &r : this->register_ranges_) { | ||||
|             r.skip_updates_counter = this->offline_skip_updates_; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       this->module_offline_ = true; | ||||
|       ESP_LOGD( | ||||
|           TAG, | ||||
|           "Modbus command to device=%d register=0x%02X countdown=%d no response received - removed from send queue", | ||||
| @@ -49,6 +60,18 @@ bool ModbusController::send_next_command_() { | ||||
| void ModbusController::on_modbus_data(const std::vector<uint8_t> &data) { | ||||
|   auto ¤t_command = this->command_queue_.front(); | ||||
|   if (current_command != nullptr) { | ||||
|     if (this->module_offline_) { | ||||
|       ESP_LOGW(TAG, "Modbus device=%d back online", this->address_); | ||||
|  | ||||
|       if (this->offline_skip_updates_ > 0) { | ||||
|         // Restore skip_updates_counter to restore commands updates | ||||
|         for (auto &r : this->register_ranges_) { | ||||
|           r.skip_updates_counter = 0; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     this->module_offline_ = false; | ||||
|  | ||||
|     // Move the commandItem to the response queue | ||||
|     current_command->payload = data; | ||||
|     this->incoming_queue_.push(std::move(current_command)); | ||||
|   | ||||
| @@ -409,7 +409,6 @@ class ModbusCommandItem { | ||||
|  | ||||
| class ModbusController : public PollingComponent, public modbus::ModbusDevice { | ||||
|  public: | ||||
|   ModbusController(uint16_t throttle = 0) : command_throttle_(throttle){}; | ||||
|   void dump_config() override; | ||||
|   void loop() override; | ||||
|   void setup() override; | ||||
| @@ -431,6 +430,12 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { | ||||
|                                   const std::vector<uint8_t> &data); | ||||
|   /// called by esphome generated code to set the command_throttle period | ||||
|   void set_command_throttle(uint16_t command_throttle) { this->command_throttle_ = command_throttle; } | ||||
|   /// called by esphome generated code to set the offline_skip_updates | ||||
|   void set_offline_skip_updates(uint16_t offline_skip_updates) { this->offline_skip_updates_ = offline_skip_updates; } | ||||
|   /// get the number of queued modbus commands (should be mostly empty) | ||||
|   size_t get_command_queue_length() { return command_queue_.size(); } | ||||
|   /// get if the module is offline, didn't respond the last command | ||||
|   bool get_module_offline() { return module_offline_; } | ||||
|  | ||||
|  protected: | ||||
|   /// parse sensormap_ and create range of sequential addresses | ||||
| @@ -443,8 +448,6 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { | ||||
|   void process_modbus_data_(const ModbusCommandItem *response); | ||||
|   /// send the next modbus command from the send queue | ||||
|   bool send_next_command_(); | ||||
|   /// get the number of queued modbus commands (should be mostly empty) | ||||
|   size_t get_command_queue_length_() { return command_queue_.size(); } | ||||
|   /// dump the parsed sensormap for diagnostics | ||||
|   void dump_sensors_(); | ||||
|   /// Collection of all sensors for this component | ||||
| @@ -459,6 +462,10 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { | ||||
|   uint32_t last_command_timestamp_; | ||||
|   /// min time in ms between sending modbus commands | ||||
|   uint16_t command_throttle_; | ||||
|   /// if module didn't respond the last command | ||||
|   bool module_offline_; | ||||
|   /// how many updates to skip if module is offline | ||||
|   uint16_t offline_skip_updates_; | ||||
| }; | ||||
|  | ||||
| /** Convert vector<uint8_t> response payload to float. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user