esphome 2024.11.3__py3-none-any.whl → 2024.12.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. esphome/components/adc/adc_sensor.h +7 -8
  2. esphome/components/adc/adc_sensor_common.cpp +24 -0
  3. esphome/components/adc/{adc_sensor.cpp → adc_sensor_esp32.cpp} +10 -179
  4. esphome/components/adc/adc_sensor_esp8266.cpp +58 -0
  5. esphome/components/adc/adc_sensor_libretiny.cpp +48 -0
  6. esphome/components/adc/adc_sensor_rp2040.cpp +93 -0
  7. esphome/components/alarm_control_panel/alarm_control_panel_call.cpp +3 -4
  8. esphome/components/animation/__init__.py +1 -2
  9. esphome/components/apds9306/apds9306.cpp +2 -1
  10. esphome/components/audio/audio.h +1 -1
  11. esphome/components/bk72xx/__init__.py +1 -1
  12. esphome/components/cse7766/cse7766.cpp +1 -1
  13. esphome/components/deep_sleep/deep_sleep_esp32.cpp +2 -2
  14. esphome/components/dht/dht.cpp +2 -1
  15. esphome/components/display/display.cpp +10 -6
  16. esphome/components/display/display.h +14 -0
  17. esphome/components/display_menu_base/__init__.py +0 -2
  18. esphome/components/display_menu_base/display_menu_base.cpp +1 -1
  19. esphome/components/dsmr/dsmr.cpp +1 -1
  20. esphome/components/esp32/__init__.py +94 -12
  21. esphome/components/esp32/boards.py +222 -14
  22. esphome/components/esp32_ble/__init__.py +22 -2
  23. esphome/components/esp32_ble/ble.cpp +39 -12
  24. esphome/components/esp32_ble/ble.h +2 -0
  25. esphome/components/esp32_ble/ble_advertising.cpp +1 -1
  26. esphome/components/esp32_ble/ble_uuid.cpp +9 -10
  27. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +4 -1
  28. esphome/components/esp32_camera_web_server/camera_web_server.h +1 -1
  29. esphome/components/esp32_rmt_led_strip/light.py +3 -3
  30. esphome/components/esp8266/__init__.py +5 -7
  31. esphome/components/ezo/ezo.cpp +14 -26
  32. esphome/components/font/__init__.py +10 -25
  33. esphome/components/font/font.cpp +5 -3
  34. esphome/components/graphical_display_menu/__init__.py +2 -0
  35. esphome/components/haier/hon_climate.cpp +79 -80
  36. esphome/components/hbridge/switch/__init__.py +44 -0
  37. esphome/components/hbridge/switch/hbridge_switch.cpp +95 -0
  38. esphome/components/hbridge/switch/hbridge_switch.h +50 -0
  39. esphome/components/hitachi_ac344/hitachi_ac344.cpp +4 -2
  40. esphome/components/hitachi_ac424/hitachi_ac424.cpp +4 -2
  41. esphome/components/homeassistant/number/homeassistant_number.cpp +3 -0
  42. esphome/components/hx711/hx711.cpp +1 -1
  43. esphome/components/hx711/hx711.h +1 -1
  44. esphome/components/i2c/i2c_bus_esp_idf.cpp +2 -2
  45. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +61 -59
  46. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -17
  47. esphome/components/ili9xxx/display.py +1 -2
  48. esphome/components/ili9xxx/ili9xxx_display.cpp +3 -2
  49. esphome/components/image/__init__.py +1 -2
  50. esphome/components/logger/logger.cpp +1 -1
  51. esphome/components/ltr501/ltr501.cpp +1 -1
  52. esphome/components/lvgl/defines.py +8 -1
  53. esphome/components/lvgl/lv_validation.py +8 -3
  54. esphome/components/lvgl/lvgl_esphome.cpp +1 -1
  55. esphome/components/lvgl/lvgl_esphome.h +16 -0
  56. esphome/components/lvgl/widgets/animimg.py +12 -17
  57. esphome/components/lvgl/widgets/img.py +1 -3
  58. esphome/components/matrix_keypad/__init__.py +15 -3
  59. esphome/components/matrix_keypad/matrix_keypad.cpp +4 -0
  60. esphome/components/matrix_keypad/matrix_keypad.h +5 -0
  61. esphome/components/max31865/max31865.cpp +4 -2
  62. esphome/components/modbus_controller/modbus_controller.cpp +24 -24
  63. esphome/components/modbus_controller/modbus_controller.h +22 -22
  64. esphome/components/modbus_controller/number/modbus_number.cpp +8 -8
  65. esphome/components/modbus_controller/number/modbus_number.h +4 -4
  66. esphome/components/modbus_controller/output/modbus_output.cpp +7 -6
  67. esphome/components/modbus_controller/output/modbus_output.h +5 -5
  68. esphome/components/modbus_controller/select/modbus_select.cpp +4 -3
  69. esphome/components/modbus_controller/select/modbus_select.h +4 -4
  70. esphome/components/modbus_controller/switch/modbus_switch.cpp +5 -5
  71. esphome/components/modbus_controller/switch/modbus_switch.h +2 -2
  72. esphome/components/mqtt/__init__.py +4 -0
  73. esphome/components/mqtt/mqtt_alarm_control_panel.cpp +2 -5
  74. esphome/components/mqtt/mqtt_backend_esp32.cpp +3 -3
  75. esphome/components/mqtt/mqtt_client.cpp +4 -0
  76. esphome/components/mqtt/mqtt_client.h +6 -0
  77. esphome/components/mqtt/mqtt_climate.cpp +13 -3
  78. esphome/components/mqtt/mqtt_sensor.cpp +2 -0
  79. esphome/components/network/ip_address.h +1 -1
  80. esphome/components/nextion/__init__.py +2 -0
  81. esphome/components/nextion/automation.h +76 -0
  82. esphome/components/nextion/base_component.py +1 -0
  83. esphome/components/nextion/binary_sensor/__init__.py +43 -2
  84. esphome/components/nextion/display.py +15 -0
  85. esphome/components/nextion/nextion.cpp +8 -5
  86. esphome/components/nextion/nextion.h +7 -0
  87. esphome/components/nextion/nextion_upload_idf.cpp +2 -2
  88. esphome/components/nextion/sensor/__init__.py +38 -5
  89. esphome/components/nextion/switch/__init__.py +38 -2
  90. esphome/components/nextion/text_sensor/__init__.py +37 -2
  91. esphome/components/nfc/ndef_record.cpp +3 -3
  92. esphome/components/online_image/__init__.py +1 -0
  93. esphome/components/opentherm/opentherm.cpp +3 -3
  94. esphome/components/opentherm/opentherm.h +1 -1
  95. esphome/components/ota/automation.h +1 -1
  96. esphome/components/output/float_output.cpp +1 -1
  97. esphome/components/pca6416a/pca6416a.cpp +5 -3
  98. esphome/components/pca9554/pca9554.cpp +4 -4
  99. esphome/components/pipsolar/pipsolar.cpp +2 -2
  100. esphome/components/pipsolar/switch/pipsolar_switch.cpp +2 -2
  101. esphome/components/pn532/pn532_mifare_ultralight.cpp +2 -2
  102. esphome/components/pn7150/pn7150_mifare_ultralight.cpp +2 -2
  103. esphome/components/pn7160/pn7160_mifare_ultralight.cpp +2 -2
  104. esphome/components/qmc5883l/qmc5883l.cpp +45 -19
  105. esphome/components/qmc5883l/qmc5883l.h +1 -1
  106. esphome/components/qspi_dbi/qspi_dbi.cpp +2 -1
  107. esphome/components/remote_base/raw_protocol.cpp +1 -1
  108. esphome/components/remote_receiver/__init__.py +5 -6
  109. esphome/components/rotary_encoder/rotary_encoder.cpp +3 -1
  110. esphome/components/rp2040/__init__.py +1 -1
  111. esphome/components/rtl87xx/__init__.py +1 -1
  112. esphome/components/safe_mode/automation.h +1 -1
  113. esphome/components/seeed_mr60bha2/__init__.py +41 -0
  114. esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +173 -0
  115. esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +61 -0
  116. esphome/components/seeed_mr60bha2/sensor.py +57 -0
  117. esphome/components/seeed_mr60fda2/__init__.py +41 -0
  118. esphome/components/seeed_mr60fda2/binary_sensor.py +33 -0
  119. esphome/components/seeed_mr60fda2/button/__init__.py +45 -0
  120. esphome/components/seeed_mr60fda2/button/get_radar_parameters_button.cpp +9 -0
  121. esphome/components/seeed_mr60fda2/button/get_radar_parameters_button.h +18 -0
  122. esphome/components/seeed_mr60fda2/button/reset_radar_button.cpp +9 -0
  123. esphome/components/seeed_mr60fda2/button/reset_radar_button.h +18 -0
  124. esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +368 -0
  125. esphome/components/seeed_mr60fda2/seeed_mr60fda2.h +101 -0
  126. esphome/components/seeed_mr60fda2/select/__init__.py +59 -0
  127. esphome/components/seeed_mr60fda2/select/height_threshold_select.cpp +15 -0
  128. esphome/components/seeed_mr60fda2/select/height_threshold_select.h +18 -0
  129. esphome/components/seeed_mr60fda2/select/install_height_select.cpp +15 -0
  130. esphome/components/seeed_mr60fda2/select/install_height_select.h +18 -0
  131. esphome/components/seeed_mr60fda2/select/sensitivity_select.cpp +15 -0
  132. esphome/components/seeed_mr60fda2/select/sensitivity_select.h +18 -0
  133. esphome/components/sen5x/sensor.py +5 -6
  134. esphome/components/sgp30/sensor.py +8 -9
  135. esphome/components/sgp30/sgp30.cpp +2 -6
  136. esphome/components/shelly_dimmer/shelly_dimmer.cpp +1 -1
  137. esphome/components/sim800l/sim800l.cpp +1 -1
  138. esphome/components/sntp/sntp_component.cpp +14 -20
  139. esphome/components/sntp/sntp_component.h +6 -9
  140. esphome/components/sntp/time.py +4 -7
  141. esphome/components/sprinkler/sprinkler.cpp +2 -2
  142. esphome/components/st7735/st7735.cpp +1 -1
  143. esphome/components/st7789v/st7789v.cpp +1 -1
  144. esphome/components/stepper/stepper.h +0 -1
  145. esphome/components/sun_gtil2/sun_gtil2.cpp +1 -1
  146. esphome/components/switch/binary_sensor/__init__.py +31 -0
  147. esphome/components/switch/binary_sensor/switch_binary_sensor.cpp +17 -0
  148. esphome/components/switch/binary_sensor/switch_binary_sensor.h +22 -0
  149. esphome/components/sx1509/sx1509_gpio_pin.cpp +2 -1
  150. esphome/components/sx1509/sx1509_gpio_pin.h +5 -5
  151. esphome/components/uart/uart.h +1 -1
  152. esphome/components/udp/udp_component.cpp +32 -16
  153. esphome/components/ufire_ec/sensor.py +4 -4
  154. esphome/components/uln2003/uln2003.cpp +4 -1
  155. esphome/components/waveshare_epaper/display.py +8 -0
  156. esphome/components/waveshare_epaper/waveshare_epaper.cpp +191 -0
  157. esphome/components/waveshare_epaper/waveshare_epaper.h +56 -0
  158. esphome/components/wiegand/__init__.py +3 -4
  159. esphome/components/wifi/__init__.py +42 -0
  160. esphome/components/wifi/wifi_component.cpp +2 -2
  161. esphome/components/wifi/wifi_component.h +82 -1
  162. esphome/components/wifi/wifi_component_esp32_arduino.cpp +1 -1
  163. esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
  164. esphome/components/wifi/wifi_component_esp_idf.cpp +1 -1
  165. esphome/components/wifi/wifi_component_libretiny.cpp +1 -1
  166. esphome/components/wifi/wifi_component_pico_w.cpp +1 -1
  167. esphome/components/wireguard/wireguard.cpp +2 -2
  168. esphome/components/xiaomi_ble/xiaomi_ble.cpp +1 -1
  169. esphome/config_validation.py +15 -11
  170. esphome/const.py +11 -1
  171. esphome/core/component.cpp +1 -1
  172. esphome/core/config.py +1 -2
  173. esphome/core/defines.h +3 -1
  174. esphome/core/helpers.cpp +8 -2
  175. esphome/core/helpers.h +2 -1
  176. esphome/core/optional.h +2 -2
  177. esphome/dashboard/web_server.py +6 -0
  178. {esphome-2024.11.3.dist-info → esphome-2024.12.0.dist-info}/METADATA +4 -4
  179. {esphome-2024.11.3.dist-info → esphome-2024.12.0.dist-info}/RECORD +183 -153
  180. {esphome-2024.11.3.dist-info → esphome-2024.12.0.dist-info}/LICENSE +0 -0
  181. {esphome-2024.11.3.dist-info → esphome-2024.12.0.dist-info}/WHEEL +0 -0
  182. {esphome-2024.11.3.dist-info → esphome-2024.12.0.dist-info}/entry_points.txt +0 -0
  183. {esphome-2024.11.3.dist-info → esphome-2024.12.0.dist-info}/top_level.txt +0 -0
@@ -152,11 +152,11 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t
152
152
  }
153
153
 
154
154
  SensorSet ModbusController::find_sensors_(ModbusRegisterType register_type, uint16_t start_address) const {
155
- auto reg_it = find_if(begin(register_ranges_), end(register_ranges_), [=](RegisterRange const &r) {
156
- return (r.start_address == start_address && r.register_type == register_type);
157
- });
155
+ auto reg_it = std::find_if(
156
+ std::begin(this->register_ranges_), std::end(this->register_ranges_),
157
+ [=](RegisterRange const &r) { return (r.start_address == start_address && r.register_type == register_type); });
158
158
 
159
- if (reg_it == register_ranges_.end()) {
159
+ if (reg_it == this->register_ranges_.end()) {
160
160
  ESP_LOGE(TAG, "No matching range for sensor found - start_address : 0x%X", start_address);
161
161
  } else {
162
162
  return reg_it->sensors;
@@ -240,18 +240,18 @@ void ModbusController::update() {
240
240
 
241
241
  // walk through the sensors and determine the register ranges to read
242
242
  size_t ModbusController::create_register_ranges_() {
243
- register_ranges_.clear();
244
- if (this->parent_->role == modbus::ModbusRole::CLIENT && sensorset_.empty()) {
243
+ this->register_ranges_.clear();
244
+ if (this->parent_->role == modbus::ModbusRole::CLIENT && this->sensorset_.empty()) {
245
245
  ESP_LOGW(TAG, "No sensors registered");
246
246
  return 0;
247
247
  }
248
248
 
249
249
  // iterator is sorted see SensorItemsComparator for details
250
- auto ix = sensorset_.begin();
250
+ auto ix = this->sensorset_.begin();
251
251
  RegisterRange r = {};
252
252
  uint8_t buffer_offset = 0;
253
253
  SensorItem *prev = nullptr;
254
- while (ix != sensorset_.end()) {
254
+ while (ix != this->sensorset_.end()) {
255
255
  SensorItem *curr = *ix;
256
256
 
257
257
  ESP_LOGV(TAG, "Register: 0x%X %d %d %d offset=%u skip=%u addr=%p", curr->start_address, curr->register_count,
@@ -278,12 +278,12 @@ size_t ModbusController::create_register_ranges_() {
278
278
  // this register can re-use the data from the previous register
279
279
 
280
280
  // remove this sensore because start_address is changed (sort-order)
281
- ix = sensorset_.erase(ix);
281
+ ix = this->sensorset_.erase(ix);
282
282
 
283
283
  curr->start_address = r.start_address;
284
284
  curr->offset += prev->offset;
285
285
 
286
- sensorset_.insert(curr);
286
+ this->sensorset_.insert(curr);
287
287
  // move iterator backwards because it will be incremented later
288
288
  ix--;
289
289
 
@@ -293,14 +293,14 @@ size_t ModbusController::create_register_ranges_() {
293
293
  // this register can extend the current range
294
294
 
295
295
  // remove this sensore because start_address is changed (sort-order)
296
- ix = sensorset_.erase(ix);
296
+ ix = this->sensorset_.erase(ix);
297
297
 
298
298
  curr->start_address = r.start_address;
299
299
  curr->offset += buffer_offset;
300
300
  buffer_offset += curr->get_register_size();
301
301
  r.register_count += curr->register_count;
302
302
 
303
- sensorset_.insert(curr);
303
+ this->sensorset_.insert(curr);
304
304
  // move iterator backwards because it will be incremented later
305
305
  ix--;
306
306
 
@@ -327,7 +327,7 @@ size_t ModbusController::create_register_ranges_() {
327
327
  ix++;
328
328
  } else {
329
329
  ESP_LOGV(TAG, "Add range 0x%X %d skip:%d", r.start_address, r.register_count, r.skip_updates);
330
- register_ranges_.push_back(r);
330
+ this->register_ranges_.push_back(r);
331
331
  r = {};
332
332
  buffer_offset = 0;
333
333
  // do not increment the iterator here because the current sensor has to be re-evaluated
@@ -339,10 +339,10 @@ size_t ModbusController::create_register_ranges_() {
339
339
  if (r.register_count > 0) {
340
340
  // Add the last range
341
341
  ESP_LOGV(TAG, "Add last range 0x%X %d skip:%d", r.start_address, r.register_count, r.skip_updates);
342
- register_ranges_.push_back(r);
342
+ this->register_ranges_.push_back(r);
343
343
  }
344
344
 
345
- return register_ranges_.size();
345
+ return this->register_ranges_.size();
346
346
  }
347
347
 
348
348
  void ModbusController::dump_config() {
@@ -352,18 +352,18 @@ void ModbusController::dump_config() {
352
352
  ESP_LOGCONFIG(TAG, " Offline Skip Updates: %d", this->offline_skip_updates_);
353
353
  #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
354
354
  ESP_LOGCONFIG(TAG, "sensormap");
355
- for (auto &it : sensorset_) {
355
+ for (auto &it : this->sensorset_) {
356
356
  ESP_LOGCONFIG(TAG, " Sensor type=%zu start=0x%X offset=0x%X count=%d size=%d",
357
357
  static_cast<uint8_t>(it->register_type), it->start_address, it->offset, it->register_count,
358
358
  it->get_register_size());
359
359
  }
360
360
  ESP_LOGCONFIG(TAG, "ranges");
361
- for (auto &it : register_ranges_) {
361
+ for (auto &it : this->register_ranges_) {
362
362
  ESP_LOGCONFIG(TAG, " Range type=%zu start=0x%X count=%d skip_updates=%d", static_cast<uint8_t>(it.register_type),
363
363
  it.start_address, it.register_count, it.skip_updates);
364
364
  }
365
365
  ESP_LOGCONFIG(TAG, "server registers");
366
- for (auto &r : server_registers_) {
366
+ for (auto &r : this->server_registers_) {
367
367
  ESP_LOGCONFIG(TAG, " Address=0x%02X value_type=%zu register_count=%u", r->address,
368
368
  static_cast<uint8_t>(r->value_type), r->register_count);
369
369
  }
@@ -372,15 +372,15 @@ void ModbusController::dump_config() {
372
372
 
373
373
  void ModbusController::loop() {
374
374
  // Incoming data to process?
375
- if (!incoming_queue_.empty()) {
376
- auto &message = incoming_queue_.front();
375
+ if (!this->incoming_queue_.empty()) {
376
+ auto &message = this->incoming_queue_.front();
377
377
  if (message != nullptr)
378
- process_modbus_data_(message.get());
379
- incoming_queue_.pop();
378
+ this->process_modbus_data_(message.get());
379
+ this->incoming_queue_.pop();
380
380
 
381
381
  } else {
382
382
  // all messages processed send pending commands
383
- send_next_command_();
383
+ this->send_next_command_();
384
384
  }
385
385
  }
386
386
 
@@ -391,7 +391,7 @@ void ModbusController::on_write_register_response(ModbusRegisterType register_ty
391
391
 
392
392
  void ModbusController::dump_sensors_() {
393
393
  ESP_LOGV(TAG, "sensors");
394
- for (auto &it : sensorset_) {
394
+ for (auto &it : this->sensorset_) {
395
395
  ESP_LOGV(TAG, " Sensor start=0x%X count=%d size=%d offset=%d", it->start_address, it->register_count,
396
396
  it->get_register_size(), it->offset);
397
397
  }
@@ -240,14 +240,14 @@ class SensorItem {
240
240
  }
241
241
  // Override register size for modbus devices not using 1 register for one dword
242
242
  void set_register_size(uint8_t register_size) { response_bytes = register_size; }
243
- ModbusRegisterType register_type;
244
- SensorValueType sensor_value_type;
245
- uint16_t start_address;
246
- uint32_t bitmask;
247
- uint8_t offset;
248
- uint8_t register_count;
243
+ ModbusRegisterType register_type{ModbusRegisterType::CUSTOM};
244
+ SensorValueType sensor_value_type{SensorValueType::RAW};
245
+ uint16_t start_address{0};
246
+ uint32_t bitmask{0};
247
+ uint8_t offset{0};
248
+ uint8_t register_count{0};
249
249
  uint8_t response_bytes{0};
250
- uint16_t skip_updates;
250
+ uint16_t skip_updates{0};
251
251
  std::vector<uint8_t> custom_data{};
252
252
  bool force_new_range{false};
253
253
  };
@@ -261,9 +261,9 @@ class ServerRegister {
261
261
  this->register_count = register_count;
262
262
  this->read_lambda = std::move(read_lambda);
263
263
  }
264
- uint16_t address;
265
- SensorValueType value_type;
266
- uint8_t register_count;
264
+ uint16_t address{0};
265
+ SensorValueType value_type{SensorValueType::RAW};
266
+ uint8_t register_count{0};
267
267
  std::function<float()> read_lambda;
268
268
  };
269
269
 
@@ -312,11 +312,11 @@ struct RegisterRange {
312
312
  class ModbusCommandItem {
313
313
  public:
314
314
  static const size_t MAX_PAYLOAD_BYTES = 240;
315
- ModbusController *modbusdevice;
316
- uint16_t register_address;
317
- uint16_t register_count;
318
- ModbusFunctionCode function_code;
319
- ModbusRegisterType register_type;
315
+ ModbusController *modbusdevice{nullptr};
316
+ uint16_t register_address{0};
317
+ uint16_t register_count{0};
318
+ ModbusFunctionCode function_code{ModbusFunctionCode::CUSTOM};
319
+ ModbusRegisterType register_type{ModbusRegisterType::CUSTOM};
320
320
  std::function<void(ModbusRegisterType register_type, uint16_t start_address, const std::vector<uint8_t> &data)>
321
321
  on_data_func;
322
322
  std::vector<uint8_t> payload = {};
@@ -493,23 +493,23 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice {
493
493
  /// Collection of all sensors for this component
494
494
  SensorSet sensorset_;
495
495
  /// Collection of all server registers for this component
496
- std::vector<ServerRegister *> server_registers_;
496
+ std::vector<ServerRegister *> server_registers_{};
497
497
  /// Continuous range of modbus registers
498
- std::vector<RegisterRange> register_ranges_;
498
+ std::vector<RegisterRange> register_ranges_{};
499
499
  /// Hold the pending requests to be sent
500
500
  std::list<std::unique_ptr<ModbusCommandItem>> command_queue_;
501
501
  /// modbus response data waiting to get processed
502
502
  std::queue<std::unique_ptr<ModbusCommandItem>> incoming_queue_;
503
503
  /// if duplicate commands can be sent
504
- bool allow_duplicate_commands_;
504
+ bool allow_duplicate_commands_{false};
505
505
  /// when was the last send operation
506
- uint32_t last_command_timestamp_;
506
+ uint32_t last_command_timestamp_{0};
507
507
  /// min time in ms between sending modbus commands
508
- uint16_t command_throttle_;
508
+ uint16_t command_throttle_{0};
509
509
  /// if module didn't respond the last command
510
- bool module_offline_;
510
+ bool module_offline_{false};
511
511
  /// how many updates to skip if module is offline
512
- uint16_t offline_skip_updates_;
512
+ uint16_t offline_skip_updates_{0};
513
513
  /// How many times we will retry a command if we get no response
514
514
  uint8_t max_cmd_retries_{4};
515
515
  /// Command sent callback
@@ -8,7 +8,7 @@ namespace modbus_controller {
8
8
  static const char *const TAG = "modbus.number";
9
9
 
10
10
  void ModbusNumber::parse_and_publish(const std::vector<uint8_t> &data) {
11
- float result = payload_to_float(data, *this) / multiply_by_;
11
+ float result = payload_to_float(data, *this) / this->multiply_by_;
12
12
 
13
13
  // Is there a lambda registered
14
14
  // call it with the pre converted value and the raw data array
@@ -43,7 +43,7 @@ void ModbusNumber::control(float value) {
43
43
  return;
44
44
  }
45
45
  } else {
46
- write_value = multiply_by_ * write_value;
46
+ write_value = this->multiply_by_ * write_value;
47
47
  }
48
48
 
49
49
  if (!data.empty()) {
@@ -63,21 +63,21 @@ void ModbusNumber::control(float value) {
63
63
  // Create and send the write command
64
64
  if (this->register_count == 1 && !this->use_write_multiple_) {
65
65
  // since offset is in bytes and a register is 16 bits we get the start by adding offset/2
66
- write_cmd =
67
- ModbusCommandItem::create_write_single_command(parent_, this->start_address + this->offset / 2, data[0]);
66
+ write_cmd = ModbusCommandItem::create_write_single_command(this->parent_, this->start_address + this->offset / 2,
67
+ data[0]);
68
68
  } else {
69
- write_cmd = ModbusCommandItem::create_write_multiple_command(parent_, this->start_address + this->offset / 2,
70
- this->register_count, data);
69
+ write_cmd = ModbusCommandItem::create_write_multiple_command(
70
+ this->parent_, this->start_address + this->offset / 2, this->register_count, data);
71
71
  }
72
72
  // publish new value
73
73
  write_cmd.on_data_func = [this, write_cmd, value](ModbusRegisterType register_type, uint16_t start_address,
74
74
  const std::vector<uint8_t> &data) {
75
75
  // gets called when the write command is ack'd from the device
76
- parent_->on_write_register_response(write_cmd.register_type, start_address, data);
76
+ this->parent_->on_write_register_response(write_cmd.register_type, start_address, data);
77
77
  this->publish_state(value);
78
78
  };
79
79
  }
80
- parent_->queue_command(write_cmd);
80
+ this->parent_->queue_command(write_cmd);
81
81
  this->publish_state(value);
82
82
  }
83
83
  void ModbusNumber::dump_config() { LOG_NUMBER(TAG, "Modbus Number", this); }
@@ -29,7 +29,7 @@ class ModbusNumber : public number::Number, public Component, public SensorItem
29
29
  void parse_and_publish(const std::vector<uint8_t> &data) override;
30
30
  float get_setup_priority() const override { return setup_priority::HARDWARE; }
31
31
  void set_parent(ModbusController *parent) { this->parent_ = parent; }
32
- void set_write_multiply(float factor) { multiply_by_ = factor; }
32
+ void set_write_multiply(float factor) { this->multiply_by_ = factor; }
33
33
 
34
34
  using transform_func_t = std::function<optional<float>(ModbusNumber *, float, const std::vector<uint8_t> &)>;
35
35
  using write_transform_func_t = std::function<optional<float>(ModbusNumber *, float, std::vector<uint16_t> &)>;
@@ -39,9 +39,9 @@ class ModbusNumber : public number::Number, public Component, public SensorItem
39
39
 
40
40
  protected:
41
41
  void control(float value) override;
42
- optional<transform_func_t> transform_func_;
43
- optional<write_transform_func_t> write_transform_func_;
44
- ModbusController *parent_;
42
+ optional<transform_func_t> transform_func_{nullopt};
43
+ optional<write_transform_func_t> write_transform_func_{nullopt};
44
+ ModbusController *parent_{nullptr};
45
45
  float multiply_by_{1.0};
46
46
  bool use_write_multiple_{false};
47
47
  };
@@ -27,7 +27,7 @@ void ModbusFloatOutput::write_state(float value) {
27
27
  return;
28
28
  }
29
29
  } else {
30
- value = multiply_by_ * value;
30
+ value = this->multiply_by_ * value;
31
31
  }
32
32
  // lambda didn't set payload
33
33
  if (data.empty()) {
@@ -40,12 +40,13 @@ void ModbusFloatOutput::write_state(float value) {
40
40
  // Create and send the write command
41
41
  ModbusCommandItem write_cmd;
42
42
  if (this->register_count == 1 && !this->use_write_multiple_) {
43
- write_cmd = ModbusCommandItem::create_write_single_command(parent_, this->start_address + this->offset, data[0]);
43
+ write_cmd =
44
+ ModbusCommandItem::create_write_single_command(this->parent_, this->start_address + this->offset, data[0]);
44
45
  } else {
45
- write_cmd = ModbusCommandItem::create_write_multiple_command(parent_, this->start_address + this->offset,
46
+ write_cmd = ModbusCommandItem::create_write_multiple_command(this->parent_, this->start_address + this->offset,
46
47
  this->register_count, data);
47
48
  }
48
- parent_->queue_command(write_cmd);
49
+ this->parent_->queue_command(write_cmd);
49
50
  }
50
51
 
51
52
  void ModbusFloatOutput::dump_config() {
@@ -90,9 +91,9 @@ void ModbusBinaryOutput::write_state(bool state) {
90
91
  // offset for coil and discrete inputs is the coil/register number not bytes
91
92
  if (this->use_write_multiple_) {
92
93
  std::vector<bool> states{state};
93
- cmd = ModbusCommandItem::create_write_multiple_coils(parent_, this->start_address + this->offset, states);
94
+ cmd = ModbusCommandItem::create_write_multiple_coils(this->parent_, this->start_address + this->offset, states);
94
95
  } else {
95
- cmd = ModbusCommandItem::create_write_single_coil(parent_, this->start_address + this->offset, state);
96
+ cmd = ModbusCommandItem::create_write_single_coil(this->parent_, this->start_address + this->offset, state);
96
97
  }
97
98
  }
98
99
  this->parent_->queue_command(cmd);
@@ -25,7 +25,7 @@ class ModbusFloatOutput : public output::FloatOutput, public Component, public S
25
25
  void dump_config() override;
26
26
 
27
27
  void set_parent(ModbusController *parent) { this->parent_ = parent; }
28
- void set_write_multiply(float factor) { multiply_by_ = factor; }
28
+ void set_write_multiply(float factor) { this->multiply_by_ = factor; }
29
29
  // Do nothing
30
30
  void parse_and_publish(const std::vector<uint8_t> &data) override{};
31
31
 
@@ -37,9 +37,9 @@ class ModbusFloatOutput : public output::FloatOutput, public Component, public S
37
37
  void write_state(float value) override;
38
38
  optional<write_transform_func_t> write_transform_func_{nullopt};
39
39
 
40
- ModbusController *parent_;
40
+ ModbusController *parent_{nullptr};
41
41
  float multiply_by_{1.0};
42
- bool use_write_multiple_;
42
+ bool use_write_multiple_{false};
43
43
  };
44
44
 
45
45
  class ModbusBinaryOutput : public output::BinaryOutput, public Component, public SensorItem {
@@ -68,8 +68,8 @@ class ModbusBinaryOutput : public output::BinaryOutput, public Component, public
68
68
  void write_state(bool state) override;
69
69
  optional<write_transform_func_t> write_transform_func_{nullopt};
70
70
 
71
- ModbusController *parent_;
72
- bool use_write_multiple_;
71
+ ModbusController *parent_{nullptr};
72
+ bool use_write_multiple_{false};
73
73
  };
74
74
 
75
75
  } // namespace modbus_controller
@@ -74,12 +74,13 @@ void ModbusSelect::control(const std::string &value) {
74
74
  const uint16_t write_address = this->start_address + this->offset / 2;
75
75
  ModbusCommandItem write_cmd;
76
76
  if ((this->register_count == 1) && (!this->use_write_multiple_)) {
77
- write_cmd = ModbusCommandItem::create_write_single_command(parent_, write_address, data[0]);
77
+ write_cmd = ModbusCommandItem::create_write_single_command(this->parent_, write_address, data[0]);
78
78
  } else {
79
- write_cmd = ModbusCommandItem::create_write_multiple_command(parent_, write_address, this->register_count, data);
79
+ write_cmd =
80
+ ModbusCommandItem::create_write_multiple_command(this->parent_, write_address, this->register_count, data);
80
81
  }
81
82
 
82
- parent_->queue_command(write_cmd);
83
+ this->parent_->queue_command(write_cmd);
83
84
 
84
85
  if (this->optimistic_)
85
86
  this->publish_state(value);
@@ -42,12 +42,12 @@ class ModbusSelect : public Component, public select::Select, public SensorItem
42
42
  void control(const std::string &value) override;
43
43
 
44
44
  protected:
45
- std::vector<int64_t> mapping_;
46
- ModbusController *parent_;
45
+ std::vector<int64_t> mapping_{};
46
+ ModbusController *parent_{nullptr};
47
47
  bool use_write_multiple_{false};
48
48
  bool optimistic_{false};
49
- optional<transform_func_t> transform_func_;
50
- optional<write_transform_func_t> write_transform_func_;
49
+ optional<transform_func_t> transform_func_{nullopt};
50
+ optional<write_transform_func_t> write_transform_func_{nullopt};
51
51
  };
52
52
 
53
53
  } // namespace modbus_controller
@@ -80,24 +80,24 @@ void ModbusSwitch::write_state(bool state) {
80
80
  // offset for coil and discrete inputs is the coil/register number not bytes
81
81
  if (this->use_write_multiple_) {
82
82
  std::vector<bool> states{state};
83
- cmd = ModbusCommandItem::create_write_multiple_coils(parent_, this->start_address + this->offset, states);
83
+ cmd = ModbusCommandItem::create_write_multiple_coils(this->parent_, this->start_address + this->offset, states);
84
84
  } else {
85
- cmd = ModbusCommandItem::create_write_single_coil(parent_, this->start_address + this->offset, state);
85
+ cmd = ModbusCommandItem::create_write_single_coil(this->parent_, this->start_address + this->offset, state);
86
86
  }
87
87
  } else {
88
88
  // since offset is in bytes and a register is 16 bits we get the start by adding offset/2
89
89
  if (this->use_write_multiple_) {
90
90
  std::vector<uint16_t> bool_states(1, state ? (0xFFFF & this->bitmask) : 0);
91
- cmd = ModbusCommandItem::create_write_multiple_command(parent_, this->start_address + this->offset / 2, 1,
91
+ cmd = ModbusCommandItem::create_write_multiple_command(this->parent_, this->start_address + this->offset / 2, 1,
92
92
  bool_states);
93
93
  } else {
94
- cmd = ModbusCommandItem::create_write_single_command(parent_, this->start_address + this->offset / 2,
94
+ cmd = ModbusCommandItem::create_write_single_command(this->parent_, this->start_address + this->offset / 2,
95
95
  state ? 0xFFFF & this->bitmask : 0u);
96
96
  }
97
97
  }
98
98
  }
99
99
  this->parent_->queue_command(cmd);
100
- publish_state(state);
100
+ this->publish_state(state);
101
101
  }
102
102
  // ModbusSwitch end
103
103
  } // namespace modbus_controller
@@ -40,8 +40,8 @@ class ModbusSwitch : public Component, public switch_::Switch, public SensorItem
40
40
  void set_use_write_mutiple(bool use_write_multiple) { this->use_write_multiple_ = use_write_multiple; }
41
41
 
42
42
  protected:
43
- ModbusController *parent_;
44
- bool use_write_multiple_;
43
+ ModbusController *parent_{nullptr};
44
+ bool use_write_multiple_{false};
45
45
  optional<transform_func_t> publish_transform_func_{nullopt};
46
46
  optional<write_transform_func_t> write_transform_func_{nullopt};
47
47
  };
@@ -49,6 +49,7 @@ from esphome.const import (
49
49
  CONF_USE_ABBREVIATIONS,
50
50
  CONF_USERNAME,
51
51
  CONF_WILL_MESSAGE,
52
+ CONF_PUBLISH_NAN_AS_NONE,
52
53
  PLATFORM_BK72XX,
53
54
  PLATFORM_ESP32,
54
55
  PLATFORM_ESP8266,
@@ -296,6 +297,7 @@ CONFIG_SCHEMA = cv.All(
296
297
  cv.Optional(CONF_QOS, default=0): cv.mqtt_qos,
297
298
  }
298
299
  ),
300
+ cv.Optional(CONF_PUBLISH_NAN_AS_NONE, default=False): cv.boolean,
299
301
  }
300
302
  ),
301
303
  validate_config,
@@ -449,6 +451,8 @@ async def to_code(config):
449
451
  trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
450
452
  await automation.build_automation(trigger, [], conf)
451
453
 
454
+ cg.add(var.set_publish_nan_as_none(config[CONF_PUBLISH_NAN_AS_NONE]))
455
+
452
456
 
453
457
  MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema(
454
458
  {
@@ -80,8 +80,7 @@ const EntityBase *MQTTAlarmControlPanelComponent::get_entity() const { return th
80
80
 
81
81
  bool MQTTAlarmControlPanelComponent::send_initial_state() { return this->publish_state(); }
82
82
  bool MQTTAlarmControlPanelComponent::publish_state() {
83
- bool success = true;
84
- const char *state_s = "";
83
+ const char *state_s;
85
84
  switch (this->alarm_control_panel_->get_state()) {
86
85
  case ACP_STATE_DISARMED:
87
86
  state_s = "disarmed";
@@ -116,9 +115,7 @@ bool MQTTAlarmControlPanelComponent::publish_state() {
116
115
  default:
117
116
  state_s = "unknown";
118
117
  }
119
- if (!this->publish(this->get_state_topic_(), state_s))
120
- success = false;
121
- return success;
118
+ return this->publish(this->get_state_topic_(), state_s);
122
119
  }
123
120
 
124
121
  } // namespace mqtt
@@ -151,11 +151,11 @@ void MQTTBackendESP32::mqtt_event_handler_(const Event &event) {
151
151
  break;
152
152
  case MQTT_EVENT_DATA: {
153
153
  static std::string topic;
154
- if (event.topic.length() > 0) {
154
+ if (!event.topic.empty()) {
155
155
  topic = event.topic;
156
156
  }
157
157
  ESP_LOGV(TAG, "MQTT_EVENT_DATA %s", topic.c_str());
158
- this->on_message_.call(event.topic.length() > 0 ? topic.c_str() : nullptr, event.data.data(), event.data.size(),
158
+ this->on_message_.call(!event.topic.empty() ? topic.c_str() : nullptr, event.data.data(), event.data.size(),
159
159
  event.current_data_offset, event.total_data_len);
160
160
  } break;
161
161
  case MQTT_EVENT_ERROR:
@@ -184,7 +184,7 @@ void MQTTBackendESP32::mqtt_event_handler(void *handler_args, esp_event_base_t b
184
184
  // queue event to decouple processing
185
185
  if (instance) {
186
186
  auto event = *static_cast<esp_mqtt_event_t *>(event_data);
187
- instance->mqtt_events_.push(Event(event));
187
+ instance->mqtt_events_.emplace(event);
188
188
  }
189
189
  }
190
190
 
@@ -608,6 +608,10 @@ void MQTTClientComponent::set_log_message_template(MQTTMessage &&message) { this
608
608
  const MQTTDiscoveryInfo &MQTTClientComponent::get_discovery_info() const { return this->discovery_info_; }
609
609
  void MQTTClientComponent::set_topic_prefix(const std::string &topic_prefix) { this->topic_prefix_ = topic_prefix; }
610
610
  const std::string &MQTTClientComponent::get_topic_prefix() const { return this->topic_prefix_; }
611
+ void MQTTClientComponent::set_publish_nan_as_none(bool publish_nan_as_none) {
612
+ this->publish_nan_as_none_ = publish_nan_as_none;
613
+ }
614
+ bool MQTTClientComponent::is_publish_nan_as_none() const { return this->publish_nan_as_none_; }
611
615
  void MQTTClientComponent::disable_birth_message() {
612
616
  this->birth_message_.topic = "";
613
617
  this->recalculate_availability_();
@@ -263,6 +263,10 @@ class MQTTClientComponent : public Component {
263
263
  void set_on_connect(mqtt_on_connect_callback_t &&callback);
264
264
  void set_on_disconnect(mqtt_on_disconnect_callback_t &&callback);
265
265
 
266
+ // Publish None state instead of NaN for Home Assistant
267
+ void set_publish_nan_as_none(bool publish_nan_as_none);
268
+ bool is_publish_nan_as_none() const;
269
+
266
270
  protected:
267
271
  void send_device_info_();
268
272
 
@@ -328,6 +332,8 @@ class MQTTClientComponent : public Component {
328
332
  uint32_t connect_begin_;
329
333
  uint32_t last_connected_{0};
330
334
  optional<MQTTClientDisconnectReason> disconnect_reason_{};
335
+
336
+ bool publish_nan_as_none_{false};
331
337
  };
332
338
 
333
339
  extern MQTTClientComponent *global_mqtt_client; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
@@ -257,7 +257,7 @@ const EntityBase *MQTTClimateComponent::get_entity() const { return this->device
257
257
  bool MQTTClimateComponent::publish_state_() {
258
258
  auto traits = this->device_->get_traits();
259
259
  // mode
260
- const char *mode_s = "";
260
+ const char *mode_s;
261
261
  switch (this->device_->mode) {
262
262
  case CLIMATE_MODE_OFF:
263
263
  mode_s = "off";
@@ -280,6 +280,8 @@ bool MQTTClimateComponent::publish_state_() {
280
280
  case CLIMATE_MODE_HEAT_COOL:
281
281
  mode_s = "heat_cool";
282
282
  break;
283
+ default:
284
+ mode_s = "unknown";
283
285
  }
284
286
  bool success = true;
285
287
  if (!this->publish(this->get_mode_state_topic(), mode_s))
@@ -343,6 +345,8 @@ bool MQTTClimateComponent::publish_state_() {
343
345
  case CLIMATE_PRESET_ACTIVITY:
344
346
  payload = "activity";
345
347
  break;
348
+ default:
349
+ payload = "unknown";
346
350
  }
347
351
  }
348
352
  if (this->device_->custom_preset.has_value())
@@ -352,7 +356,7 @@ bool MQTTClimateComponent::publish_state_() {
352
356
  }
353
357
 
354
358
  if (traits.get_supports_action()) {
355
- const char *payload = "unknown";
359
+ const char *payload;
356
360
  switch (this->device_->action) {
357
361
  case CLIMATE_ACTION_OFF:
358
362
  payload = "off";
@@ -372,6 +376,8 @@ bool MQTTClimateComponent::publish_state_() {
372
376
  case CLIMATE_ACTION_FAN:
373
377
  payload = "fan";
374
378
  break;
379
+ default:
380
+ payload = "unknown";
375
381
  }
376
382
  if (!this->publish(this->get_action_state_topic(), payload))
377
383
  success = false;
@@ -411,6 +417,8 @@ bool MQTTClimateComponent::publish_state_() {
411
417
  case CLIMATE_FAN_QUIET:
412
418
  payload = "quiet";
413
419
  break;
420
+ default:
421
+ payload = "unknown";
414
422
  }
415
423
  }
416
424
  if (this->device_->custom_fan_mode.has_value())
@@ -420,7 +428,7 @@ bool MQTTClimateComponent::publish_state_() {
420
428
  }
421
429
 
422
430
  if (traits.get_supports_swing_modes()) {
423
- const char *payload = "";
431
+ const char *payload;
424
432
  switch (this->device_->swing_mode) {
425
433
  case CLIMATE_SWING_OFF:
426
434
  payload = "off";
@@ -434,6 +442,8 @@ bool MQTTClimateComponent::publish_state_() {
434
442
  case CLIMATE_SWING_HORIZONTAL:
435
443
  payload = "horizontal";
436
444
  break;
445
+ default:
446
+ payload = "unknown";
437
447
  }
438
448
  if (!this->publish(this->get_swing_mode_state_topic(), payload))
439
449
  success = false;
@@ -69,6 +69,8 @@ bool MQTTSensorComponent::send_initial_state() {
69
69
  }
70
70
  }
71
71
  bool MQTTSensorComponent::publish_state(float value) {
72
+ if (mqtt::global_mqtt_client->is_publish_nan_as_none() && std::isnan(value))
73
+ return this->publish(this->get_state_topic_(), "None");
72
74
  int8_t accuracy = this->sensor_->get_accuracy_decimals();
73
75
  return this->publish(this->get_state_topic_(), value_accuracy_to_string(value, accuracy));
74
76
  }
@@ -116,7 +116,7 @@ struct IPAddress {
116
116
  operator arduino_ns::IPAddress() const { return ip_addr_get_ip4_u32(&ip_addr_); }
117
117
  #endif
118
118
 
119
- bool is_set() { return !ip_addr_isany(&ip_addr_); }
119
+ bool is_set() { return !ip_addr_isany(&ip_addr_); } // NOLINT(readability-simplify-boolean-expr)
120
120
  bool is_ip4() { return IP_IS_V4(&ip_addr_); }
121
121
  bool is_ip6() { return IP_IS_V6(&ip_addr_); }
122
122
  std::string str() const { return str_lower_case(ipaddr_ntoa(&ip_addr_)); }
@@ -6,3 +6,5 @@ Nextion = nextion_ns.class_("Nextion", cg.PollingComponent, uart.UARTDevice)
6
6
  nextion_ref = Nextion.operator("ref")
7
7
 
8
8
  CONF_NEXTION_ID = "nextion_id"
9
+ CONF_PUBLISH_STATE = "publish_state"
10
+ CONF_SEND_TO_NEXTION = "send_to_nextion"