esphome 2024.9.2__py3-none-any.whl → 2024.10.0b1__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 (188) hide show
  1. esphome/components/aic3204/__init__.py +0 -0
  2. esphome/components/aic3204/aic3204.cpp +173 -0
  3. esphome/components/aic3204/aic3204.h +88 -0
  4. esphome/components/aic3204/audio_dac.py +52 -0
  5. esphome/components/aic3204/automation.h +23 -0
  6. esphome/components/alarm_control_panel/__init__.py +3 -4
  7. esphome/components/animation/__init__.py +16 -12
  8. esphome/components/api/api_connection.cpp +2 -0
  9. esphome/components/api/api_connection.h +3 -1
  10. esphome/components/api/api_frame_helper.cpp +2 -1
  11. esphome/components/api/api_frame_helper.h +2 -1
  12. esphome/components/api/api_server.cpp +2 -0
  13. esphome/components/api/api_server.h +3 -1
  14. esphome/components/api/custom_api_device.h +3 -2
  15. esphome/components/api/homeassistant_service.h +4 -3
  16. esphome/components/api/list_entities.cpp +2 -0
  17. esphome/components/api/list_entities.h +3 -2
  18. esphome/components/api/subscribe_state.cpp +2 -0
  19. esphome/components/api/subscribe_state.h +3 -2
  20. esphome/components/audio_dac/__init__.py +57 -0
  21. esphome/components/audio_dac/audio_dac.h +23 -0
  22. esphome/components/audio_dac/automation.h +43 -0
  23. esphome/components/bang_bang/bang_bang_climate.cpp +5 -2
  24. esphome/components/bedjet/bedjet_codec.cpp +4 -2
  25. esphome/components/binary_sensor/__init__.py +3 -4
  26. esphome/components/button/__init__.py +3 -4
  27. esphome/components/ch422g/__init__.py +26 -17
  28. esphome/components/ch422g/ch422g.cpp +66 -49
  29. esphome/components/ch422g/ch422g.h +17 -19
  30. esphome/components/climate/__init__.py +3 -4
  31. esphome/components/cover/__init__.py +4 -5
  32. esphome/components/cse7766/cse7766.cpp +11 -0
  33. esphome/components/cse7766/cse7766.h +4 -0
  34. esphome/components/cse7766/sensor.py +13 -1
  35. esphome/components/cst816/touchscreen/__init__.py +7 -4
  36. esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +20 -19
  37. esphome/components/cst816/touchscreen/cst816_touchscreen.h +2 -0
  38. esphome/components/datetime/__init__.py +21 -14
  39. esphome/components/datetime/datetime_base.h +8 -1
  40. esphome/components/datetime/datetime_entity.cpp +2 -0
  41. esphome/components/datetime/datetime_entity.h +2 -0
  42. esphome/components/datetime/time_entity.cpp +2 -0
  43. esphome/components/datetime/time_entity.h +2 -0
  44. esphome/components/esp32/__init__.py +20 -4
  45. esphome/components/esp32_improv/__init__.py +82 -1
  46. esphome/components/esp32_improv/automation.h +72 -0
  47. esphome/components/esp32_improv/esp32_improv_component.cpp +13 -5
  48. esphome/components/esp32_improv/esp32_improv_component.h +15 -0
  49. esphome/components/ethernet/__init__.py +5 -0
  50. esphome/components/ethernet/ethernet_component.cpp +13 -0
  51. esphome/components/ethernet/ethernet_component.h +1 -0
  52. esphome/components/fan/__init__.py +3 -4
  53. esphome/components/gp2y1010au0f/__init__.py +0 -0
  54. esphome/components/gp2y1010au0f/gp2y1010au0f.cpp +67 -0
  55. esphome/components/gp2y1010au0f/gp2y1010au0f.h +52 -0
  56. esphome/components/gp2y1010au0f/sensor.py +61 -0
  57. esphome/components/gpio_expander/__init__.py +0 -0
  58. esphome/components/gpio_expander/cached_gpio.h +38 -0
  59. esphome/components/grove_gas_mc_v2/__init__.py +0 -0
  60. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +88 -0
  61. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +39 -0
  62. esphome/components/grove_gas_mc_v2/sensor.py +77 -0
  63. esphome/components/haier/climate.py +4 -3
  64. esphome/components/haier/haier_base.cpp +63 -8
  65. esphome/components/haier/haier_base.h +29 -3
  66. esphome/components/haier/hon_climate.cpp +122 -65
  67. esphome/components/haier/hon_climate.h +18 -2
  68. esphome/components/haier/smartair2_climate.cpp +21 -21
  69. esphome/components/haier/switch/__init__.py +91 -0
  70. esphome/components/haier/switch/beeper.cpp +14 -0
  71. esphome/components/haier/switch/beeper.h +18 -0
  72. esphome/components/haier/switch/display.cpp +14 -0
  73. esphome/components/haier/switch/display.h +18 -0
  74. esphome/components/haier/switch/health_mode.cpp +14 -0
  75. esphome/components/haier/switch/health_mode.h +18 -0
  76. esphome/components/haier/switch/quiet_mode.cpp +14 -0
  77. esphome/components/haier/switch/quiet_mode.h +18 -0
  78. esphome/components/hmac_md5/hmac_md5.cpp +2 -0
  79. esphome/components/hmac_md5/hmac_md5.h +2 -1
  80. esphome/components/i2s_audio/speaker/__init__.py +19 -0
  81. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  82. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +2 -0
  83. esphome/components/ili9xxx/ili9xxx_display.h +1 -0
  84. esphome/components/image/__init__.py +12 -12
  85. esphome/components/image/image.cpp +44 -0
  86. esphome/components/image/image.h +17 -2
  87. esphome/components/inkplate6/display.py +2 -0
  88. esphome/components/inkplate6/inkplate.h +30 -2
  89. esphome/components/light/__init__.py +3 -4
  90. esphome/components/lock/__init__.py +3 -4
  91. esphome/components/lvgl/__init__.py +16 -5
  92. esphome/components/lvgl/defines.py +1 -0
  93. esphome/components/lvgl/hello_world.py +64 -0
  94. esphome/components/lvgl/lv_validation.py +159 -3
  95. esphome/components/lvgl/lvgl_esphome.cpp +0 -43
  96. esphome/components/lvgl/lvgl_esphome.h +0 -4
  97. esphome/components/lvgl/styles.py +3 -2
  98. esphome/components/lvgl/text/__init__.py +3 -3
  99. esphome/components/lvgl/widgets/__init__.py +2 -0
  100. esphome/components/lvgl/widgets/animimg.py +3 -4
  101. esphome/components/lvgl/widgets/dropdown.py +5 -1
  102. esphome/components/lvgl/widgets/meter.py +16 -11
  103. esphome/components/md5/__init__.py +6 -0
  104. esphome/components/md5/md5.cpp +2 -0
  105. esphome/components/md5/md5.h +2 -0
  106. esphome/components/micro_wake_word/__init__.py +7 -0
  107. esphome/components/mics_4514/sensor.py +11 -26
  108. esphome/components/modbus_controller/__init__.py +7 -5
  109. esphome/components/modbus_controller/binary_sensor/__init__.py +6 -6
  110. esphome/components/modbus_controller/number/__init__.py +5 -6
  111. esphome/components/modbus_controller/output/__init__.py +10 -14
  112. esphome/components/modbus_controller/select/__init__.py +1 -1
  113. esphome/components/modbus_controller/sensor/__init__.py +7 -7
  114. esphome/components/modbus_controller/switch/__init__.py +6 -7
  115. esphome/components/modbus_controller/text_sensor/__init__.py +8 -9
  116. esphome/components/mqtt/__init__.py +3 -0
  117. esphome/components/mqtt/mqtt_client.cpp +2 -0
  118. esphome/components/mqtt/mqtt_client.h +2 -0
  119. esphome/components/nau7802/__init__.py +0 -0
  120. esphome/components/nau7802/nau7802.cpp +323 -0
  121. esphome/components/nau7802/nau7802.h +121 -0
  122. esphome/components/nau7802/sensor.py +134 -0
  123. esphome/components/nextion/base_component.py +1 -0
  124. esphome/components/nextion/display.py +4 -0
  125. esphome/components/nextion/nextion.cpp +19 -4
  126. esphome/components/nextion/nextion.h +16 -0
  127. esphome/components/npi19/__init__.py +0 -0
  128. esphome/components/npi19/npi19.cpp +111 -0
  129. esphome/components/npi19/npi19.h +30 -0
  130. esphome/components/npi19/sensor.py +52 -0
  131. esphome/components/number/__init__.py +3 -5
  132. esphome/components/online_image/__init__.py +1 -1
  133. esphome/components/online_image/online_image.h +1 -2
  134. esphome/components/opentherm/__init__.py +57 -0
  135. esphome/components/opentherm/hub.cpp +277 -0
  136. esphome/components/opentherm/hub.h +110 -0
  137. esphome/components/opentherm/opentherm.cpp +568 -0
  138. esphome/components/opentherm/opentherm.h +347 -0
  139. esphome/components/pulse_counter/pulse_counter_sensor.cpp +8 -1
  140. esphome/components/pulse_counter/pulse_counter_sensor.h +1 -0
  141. esphome/components/radon_eye_ble/radon_eye_listener.cpp +10 -3
  142. esphome/components/remote_transmitter/__init__.py +18 -2
  143. esphome/components/remote_transmitter/remote_transmitter.h +6 -0
  144. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +2 -0
  145. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
  146. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
  147. esphome/components/select/__init__.py +3 -4
  148. esphome/components/sensor/__init__.py +3 -4
  149. esphome/components/st7701s/st7701s.cpp +21 -8
  150. esphome/components/st7701s/st7701s.h +2 -0
  151. esphome/components/switch/__init__.py +3 -4
  152. esphome/components/tca9555/__init__.py +72 -0
  153. esphome/components/tca9555/tca9555.cpp +140 -0
  154. esphome/components/tca9555/tca9555.h +64 -0
  155. esphome/components/tcs34725/tcs34725.cpp +62 -64
  156. esphome/components/tem3200/__init__.py +0 -0
  157. esphome/components/tem3200/sensor.py +55 -0
  158. esphome/components/tem3200/tem3200.cpp +151 -0
  159. esphome/components/tem3200/tem3200.h +30 -0
  160. esphome/components/template/binary_sensor/__init__.py +19 -6
  161. esphome/components/text/__init__.py +3 -4
  162. esphome/components/text_sensor/__init__.py +3 -4
  163. esphome/components/thermostat/climate.py +11 -9
  164. esphome/components/thermostat/thermostat_climate.cpp +21 -15
  165. esphome/components/tm1638/binary_sensor/__init__.py +3 -2
  166. esphome/components/tm1638/display.py +5 -5
  167. esphome/components/tm1638/output/__init__.py +3 -2
  168. esphome/components/tm1638/switch/__init__.py +3 -2
  169. esphome/components/update/__init__.py +3 -4
  170. esphome/components/valve/__init__.py +3 -4
  171. esphome/components/web_server/__init__.py +78 -22
  172. esphome/components/web_server/server_index_v3.h +3989 -3979
  173. esphome/components/web_server/web_server.cpp +212 -33
  174. esphome/components/web_server/web_server.h +10 -1
  175. esphome/components/wifi/wifi_component_esp_idf.cpp +4 -5
  176. esphome/config_validation.py +1 -0
  177. esphome/const.py +12 -2
  178. esphome/core/defines.h +4 -2
  179. esphome/core/helpers.cpp +46 -10
  180. esphome/core/helpers.h +8 -0
  181. esphome/core/ring_buffer.cpp +12 -2
  182. esphome/core/ring_buffer.h +3 -0
  183. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/METADATA +5 -3
  184. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/RECORD +188 -139
  185. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/LICENSE +0 -0
  186. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/WHEEL +0 -0
  187. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/entry_points.txt +0 -0
  188. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/top_level.txt +0 -0
@@ -105,6 +105,14 @@ void WebServer::setup() {
105
105
  // Configure reconnect timeout and send config
106
106
  client->send(this->get_config_json().c_str(), "ping", millis(), 30000);
107
107
 
108
+ for (auto &group : this->sorting_groups_) {
109
+ client->send(json::build_json([group](JsonObject root) {
110
+ root["name"] = group.second.name;
111
+ root["sorting_weight"] = group.second.weight;
112
+ }).c_str(),
113
+ "sorting_group");
114
+ }
115
+
108
116
  this->entities_iterator_.begin(this->include_internal_);
109
117
  });
110
118
 
@@ -219,9 +227,16 @@ void WebServer::handle_sensor_request(AsyncWebServerRequest *request, const UrlM
219
227
  for (sensor::Sensor *obj : App.get_sensors()) {
220
228
  if (obj->get_object_id() != match.id)
221
229
  continue;
222
- std::string data = this->sensor_json(obj, obj->state, DETAIL_STATE);
223
- request->send(200, "application/json", data.c_str());
224
- return;
230
+ if (request->method() == HTTP_GET && match.method.empty()) {
231
+ auto detail = DETAIL_STATE;
232
+ auto *param = request->getParam("detail");
233
+ if (param && param->value() == "all") {
234
+ detail = DETAIL_ALL;
235
+ }
236
+ std::string data = this->sensor_json(obj, obj->state, detail);
237
+ request->send(200, "application/json", data.c_str());
238
+ return;
239
+ }
225
240
  }
226
241
  request->send(404);
227
242
  }
@@ -239,6 +254,9 @@ std::string WebServer::sensor_json(sensor::Sensor *obj, float value, JsonDetail
239
254
  if (start_config == DETAIL_ALL) {
240
255
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
241
256
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
257
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
258
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
259
+ }
242
260
  }
243
261
  if (!obj->get_unit_of_measurement().empty())
244
262
  root["uom"] = obj->get_unit_of_measurement();
@@ -257,9 +275,16 @@ void WebServer::handle_text_sensor_request(AsyncWebServerRequest *request, const
257
275
  for (text_sensor::TextSensor *obj : App.get_text_sensors()) {
258
276
  if (obj->get_object_id() != match.id)
259
277
  continue;
260
- std::string data = this->text_sensor_json(obj, obj->state, DETAIL_STATE);
261
- request->send(200, "application/json", data.c_str());
262
- return;
278
+ if (request->method() == HTTP_GET && match.method.empty()) {
279
+ auto detail = DETAIL_STATE;
280
+ auto *param = request->getParam("detail");
281
+ if (param && param->value() == "all") {
282
+ detail = DETAIL_ALL;
283
+ }
284
+ std::string data = this->text_sensor_json(obj, obj->state, detail);
285
+ request->send(200, "application/json", data.c_str());
286
+ return;
287
+ }
263
288
  }
264
289
  request->send(404);
265
290
  }
@@ -270,6 +295,9 @@ std::string WebServer::text_sensor_json(text_sensor::TextSensor *obj, const std:
270
295
  if (start_config == DETAIL_ALL) {
271
296
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
272
297
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
298
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
299
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
300
+ }
273
301
  }
274
302
  }
275
303
  });
@@ -288,7 +316,12 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM
288
316
  continue;
289
317
 
290
318
  if (request->method() == HTTP_GET && match.method.empty()) {
291
- std::string data = this->switch_json(obj, obj->state, DETAIL_STATE);
319
+ auto detail = DETAIL_STATE;
320
+ auto *param = request->getParam("detail");
321
+ if (param && param->value() == "all") {
322
+ detail = DETAIL_ALL;
323
+ }
324
+ std::string data = this->switch_json(obj, obj->state, detail);
292
325
  request->send(200, "application/json", data.c_str());
293
326
  } else if (match.method == "toggle") {
294
327
  this->schedule_([obj]() { obj->toggle(); });
@@ -313,6 +346,9 @@ std::string WebServer::switch_json(switch_::Switch *obj, bool value, JsonDetail
313
346
  root["assumed_state"] = obj->assumed_state();
314
347
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
315
348
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
349
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
350
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
351
+ }
316
352
  }
317
353
  }
318
354
  });
@@ -324,7 +360,15 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM
324
360
  for (button::Button *obj : App.get_buttons()) {
325
361
  if (obj->get_object_id() != match.id)
326
362
  continue;
327
- if (match.method == "press") {
363
+ if (request->method() == HTTP_GET && match.method.empty()) {
364
+ auto detail = DETAIL_STATE;
365
+ auto *param = request->getParam("detail");
366
+ if (param && param->value() == "all") {
367
+ detail = DETAIL_ALL;
368
+ }
369
+ std::string data = this->button_json(obj, detail);
370
+ request->send(200, "application/json", data.c_str());
371
+ } else if (match.method == "press") {
328
372
  this->schedule_([obj]() { obj->press(); });
329
373
  request->send(200);
330
374
  return;
@@ -341,6 +385,9 @@ std::string WebServer::button_json(button::Button *obj, JsonDetail start_config)
341
385
  if (start_config == DETAIL_ALL) {
342
386
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
343
387
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
388
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
389
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
390
+ }
344
391
  }
345
392
  }
346
393
  });
@@ -357,9 +404,16 @@ void WebServer::handle_binary_sensor_request(AsyncWebServerRequest *request, con
357
404
  for (binary_sensor::BinarySensor *obj : App.get_binary_sensors()) {
358
405
  if (obj->get_object_id() != match.id)
359
406
  continue;
360
- std::string data = this->binary_sensor_json(obj, obj->state, DETAIL_STATE);
361
- request->send(200, "application/json", data.c_str());
362
- return;
407
+ if (request->method() == HTTP_GET && match.method.empty()) {
408
+ auto detail = DETAIL_STATE;
409
+ auto *param = request->getParam("detail");
410
+ if (param && param->value() == "all") {
411
+ detail = DETAIL_ALL;
412
+ }
413
+ std::string data = this->binary_sensor_json(obj, obj->state, detail);
414
+ request->send(200, "application/json", data.c_str());
415
+ return;
416
+ }
363
417
  }
364
418
  request->send(404);
365
419
  }
@@ -370,6 +424,9 @@ std::string WebServer::binary_sensor_json(binary_sensor::BinarySensor *obj, bool
370
424
  if (start_config == DETAIL_ALL) {
371
425
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
372
426
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
427
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
428
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
429
+ }
373
430
  }
374
431
  }
375
432
  });
@@ -388,7 +445,12 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc
388
445
  continue;
389
446
 
390
447
  if (request->method() == HTTP_GET && match.method.empty()) {
391
- std::string data = this->fan_json(obj, DETAIL_STATE);
448
+ auto detail = DETAIL_STATE;
449
+ auto *param = request->getParam("detail");
450
+ if (param && param->value() == "all") {
451
+ detail = DETAIL_ALL;
452
+ }
453
+ std::string data = this->fan_json(obj, detail);
392
454
  request->send(200, "application/json", data.c_str());
393
455
  } else if (match.method == "toggle") {
394
456
  this->schedule_([obj]() { obj->toggle().perform(); });
@@ -448,6 +510,9 @@ std::string WebServer::fan_json(fan::Fan *obj, JsonDetail start_config) {
448
510
  if (start_config == DETAIL_ALL) {
449
511
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
450
512
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
513
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
514
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
515
+ }
451
516
  }
452
517
  }
453
518
  });
@@ -466,7 +531,12 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa
466
531
  continue;
467
532
 
468
533
  if (request->method() == HTTP_GET && match.method.empty()) {
469
- std::string data = this->light_json(obj, DETAIL_STATE);
534
+ auto detail = DETAIL_STATE;
535
+ auto *param = request->getParam("detail");
536
+ if (param && param->value() == "all") {
537
+ detail = DETAIL_ALL;
538
+ }
539
+ std::string data = this->light_json(obj, detail);
470
540
  request->send(200, "application/json", data.c_str());
471
541
  } else if (match.method == "toggle") {
472
542
  this->schedule_([obj]() { obj->toggle().perform(); });
@@ -559,6 +629,9 @@ std::string WebServer::light_json(light::LightState *obj, JsonDetail start_confi
559
629
  }
560
630
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
561
631
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
632
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
633
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
634
+ }
562
635
  }
563
636
  }
564
637
  });
@@ -577,9 +650,14 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa
577
650
  continue;
578
651
 
579
652
  if (request->method() == HTTP_GET && match.method.empty()) {
580
- std::string data = this->cover_json(obj, DETAIL_STATE);
653
+ auto detail = DETAIL_STATE;
654
+ auto *param = request->getParam("detail");
655
+ if (param && param->value() == "all") {
656
+ detail = DETAIL_ALL;
657
+ }
658
+ std::string data = this->cover_json(obj, detail);
581
659
  request->send(200, "application/json", data.c_str());
582
- continue;
660
+ return;
583
661
  }
584
662
 
585
663
  auto call = obj->make_call();
@@ -635,6 +713,9 @@ std::string WebServer::cover_json(cover::Cover *obj, JsonDetail start_config) {
635
713
  if (start_config == DETAIL_ALL) {
636
714
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
637
715
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
716
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
717
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
718
+ }
638
719
  }
639
720
  }
640
721
  });
@@ -653,7 +734,12 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM
653
734
  continue;
654
735
 
655
736
  if (request->method() == HTTP_GET && match.method.empty()) {
656
- std::string data = this->number_json(obj, obj->state, DETAIL_STATE);
737
+ auto detail = DETAIL_STATE;
738
+ auto *param = request->getParam("detail");
739
+ if (param && param->value() == "all") {
740
+ detail = DETAIL_ALL;
741
+ }
742
+ std::string data = this->number_json(obj, obj->state, detail);
657
743
  request->send(200, "application/json", data.c_str());
658
744
  return;
659
745
  }
@@ -691,6 +777,9 @@ std::string WebServer::number_json(number::Number *obj, float value, JsonDetail
691
777
  root["uom"] = obj->traits.get_unit_of_measurement();
692
778
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
693
779
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
780
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
781
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
782
+ }
694
783
  }
695
784
  }
696
785
  if (std::isnan(value)) {
@@ -717,8 +806,13 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat
717
806
  for (auto *obj : App.get_dates()) {
718
807
  if (obj->get_object_id() != match.id)
719
808
  continue;
720
- if (request->method() == HTTP_GET) {
721
- std::string data = this->date_json(obj, DETAIL_STATE);
809
+ if (request->method() == HTTP_GET && match.method.empty()) {
810
+ auto detail = DETAIL_STATE;
811
+ auto *param = request->getParam("detail");
812
+ if (param && param->value() == "all") {
813
+ detail = DETAIL_ALL;
814
+ }
815
+ std::string data = this->date_json(obj, detail);
722
816
  request->send(200, "application/json", data.c_str());
723
817
  return;
724
818
  }
@@ -755,6 +849,9 @@ std::string WebServer::date_json(datetime::DateEntity *obj, JsonDetail start_con
755
849
  if (start_config == DETAIL_ALL) {
756
850
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
757
851
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
852
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
853
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
854
+ }
758
855
  }
759
856
  }
760
857
  });
@@ -772,7 +869,12 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat
772
869
  if (obj->get_object_id() != match.id)
773
870
  continue;
774
871
  if (request->method() == HTTP_GET && match.method.empty()) {
775
- std::string data = this->time_json(obj, DETAIL_STATE);
872
+ auto detail = DETAIL_STATE;
873
+ auto *param = request->getParam("detail");
874
+ if (param && param->value() == "all") {
875
+ detail = DETAIL_ALL;
876
+ }
877
+ std::string data = this->time_json(obj, detail);
776
878
  request->send(200, "application/json", data.c_str());
777
879
  return;
778
880
  }
@@ -808,6 +910,9 @@ std::string WebServer::time_json(datetime::TimeEntity *obj, JsonDetail start_con
808
910
  if (start_config == DETAIL_ALL) {
809
911
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
810
912
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
913
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
914
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
915
+ }
811
916
  }
812
917
  }
813
918
  });
@@ -825,7 +930,12 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur
825
930
  if (obj->get_object_id() != match.id)
826
931
  continue;
827
932
  if (request->method() == HTTP_GET && match.method.empty()) {
828
- std::string data = this->datetime_json(obj, DETAIL_STATE);
933
+ auto detail = DETAIL_STATE;
934
+ auto *param = request->getParam("detail");
935
+ if (param && param->value() == "all") {
936
+ detail = DETAIL_ALL;
937
+ }
938
+ std::string data = this->datetime_json(obj, detail);
829
939
  request->send(200, "application/json", data.c_str());
830
940
  return;
831
941
  }
@@ -862,6 +972,9 @@ std::string WebServer::datetime_json(datetime::DateTimeEntity *obj, JsonDetail s
862
972
  if (start_config == DETAIL_ALL) {
863
973
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
864
974
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
975
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
976
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
977
+ }
865
978
  }
866
979
  }
867
980
  });
@@ -880,8 +993,13 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat
880
993
  continue;
881
994
 
882
995
  if (request->method() == HTTP_GET && match.method.empty()) {
883
- std::string data = this->text_json(obj, obj->state, DETAIL_STATE);
884
- request->send(200, "text/json", data.c_str());
996
+ auto detail = DETAIL_STATE;
997
+ auto *param = request->getParam("detail");
998
+ if (param && param->value() == "all") {
999
+ detail = DETAIL_ALL;
1000
+ }
1001
+ std::string data = this->text_json(obj, obj->state, detail);
1002
+ request->send(200, "application/json", data.c_str());
885
1003
  return;
886
1004
  }
887
1005
  if (match.method != "set") {
@@ -918,6 +1036,9 @@ std::string WebServer::text_json(text::Text *obj, const std::string &value, Json
918
1036
  root["mode"] = (int) obj->traits.get_mode();
919
1037
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
920
1038
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
1039
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1040
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
1041
+ }
921
1042
  }
922
1043
  }
923
1044
  });
@@ -974,6 +1095,9 @@ std::string WebServer::select_json(select::Select *obj, const std::string &value
974
1095
  }
975
1096
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
976
1097
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
1098
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1099
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
1100
+ }
977
1101
  }
978
1102
  }
979
1103
  });
@@ -995,11 +1119,15 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url
995
1119
  continue;
996
1120
 
997
1121
  if (request->method() == HTTP_GET && match.method.empty()) {
998
- std::string data = this->climate_json(obj, DETAIL_STATE);
1122
+ auto detail = DETAIL_STATE;
1123
+ auto *param = request->getParam("detail");
1124
+ if (param && param->value() == "all") {
1125
+ detail = DETAIL_ALL;
1126
+ }
1127
+ std::string data = this->climate_json(obj, detail);
999
1128
  request->send(200, "application/json", data.c_str());
1000
1129
  return;
1001
1130
  }
1002
-
1003
1131
  if (match.method != "set") {
1004
1132
  request->send(404);
1005
1133
  return;
@@ -1012,6 +1140,16 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url
1012
1140
  call.set_mode(mode.c_str());
1013
1141
  }
1014
1142
 
1143
+ if (request->hasParam("fan_mode")) {
1144
+ auto mode = request->getParam("fan_mode")->value();
1145
+ call.set_fan_mode(mode.c_str());
1146
+ }
1147
+
1148
+ if (request->hasParam("swing_mode")) {
1149
+ auto mode = request->getParam("swing_mode")->value();
1150
+ call.set_swing_mode(mode.c_str());
1151
+ }
1152
+
1015
1153
  if (request->hasParam("target_temperature_high")) {
1016
1154
  auto target_temperature_high = parse_number<float>(request->getParam("target_temperature_high")->value().c_str());
1017
1155
  if (target_temperature_high.has_value())
@@ -1076,6 +1214,9 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf
1076
1214
  }
1077
1215
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
1078
1216
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
1217
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1218
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
1219
+ }
1079
1220
  }
1080
1221
  }
1081
1222
 
@@ -1139,7 +1280,12 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat
1139
1280
  continue;
1140
1281
 
1141
1282
  if (request->method() == HTTP_GET && match.method.empty()) {
1142
- std::string data = this->lock_json(obj, obj->state, DETAIL_STATE);
1283
+ auto detail = DETAIL_STATE;
1284
+ auto *param = request->getParam("detail");
1285
+ if (param && param->value() == "all") {
1286
+ detail = DETAIL_ALL;
1287
+ }
1288
+ std::string data = this->lock_json(obj, obj->state, detail);
1143
1289
  request->send(200, "application/json", data.c_str());
1144
1290
  } else if (match.method == "lock") {
1145
1291
  this->schedule_([obj]() { obj->lock(); });
@@ -1164,6 +1310,9 @@ std::string WebServer::lock_json(lock::Lock *obj, lock::LockState value, JsonDet
1164
1310
  if (start_config == DETAIL_ALL) {
1165
1311
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
1166
1312
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
1313
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1314
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
1315
+ }
1167
1316
  }
1168
1317
  }
1169
1318
  });
@@ -1182,9 +1331,14 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa
1182
1331
  continue;
1183
1332
 
1184
1333
  if (request->method() == HTTP_GET && match.method.empty()) {
1185
- std::string data = this->valve_json(obj, DETAIL_STATE);
1334
+ auto detail = DETAIL_STATE;
1335
+ auto *param = request->getParam("detail");
1336
+ if (param && param->value() == "all") {
1337
+ detail = DETAIL_ALL;
1338
+ }
1339
+ std::string data = this->valve_json(obj, detail);
1186
1340
  request->send(200, "application/json", data.c_str());
1187
- continue;
1341
+ return;
1188
1342
  }
1189
1343
 
1190
1344
  auto call = obj->make_call();
@@ -1228,8 +1382,13 @@ std::string WebServer::valve_json(valve::Valve *obj, JsonDetail start_config) {
1228
1382
 
1229
1383
  if (obj->get_traits().get_supports_position())
1230
1384
  root["position"] = obj->position;
1231
- if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
1232
- root["sorting_weight"] = this->sorting_entitys_[obj].weight;
1385
+ if (start_config == DETAIL_ALL) {
1386
+ if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
1387
+ root["sorting_weight"] = this->sorting_entitys_[obj].weight;
1388
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1389
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
1390
+ }
1391
+ }
1233
1392
  }
1234
1393
  });
1235
1394
  }
@@ -1247,7 +1406,12 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques
1247
1406
  continue;
1248
1407
 
1249
1408
  if (request->method() == HTTP_GET && match.method.empty()) {
1250
- std::string data = this->alarm_control_panel_json(obj, obj->get_state(), DETAIL_STATE);
1409
+ auto detail = DETAIL_STATE;
1410
+ auto *param = request->getParam("detail");
1411
+ if (param && param->value() == "all") {
1412
+ detail = DETAIL_ALL;
1413
+ }
1414
+ std::string data = this->alarm_control_panel_json(obj, obj->get_state(), detail);
1251
1415
  request->send(200, "application/json", data.c_str());
1252
1416
  return;
1253
1417
  }
@@ -1264,6 +1428,9 @@ std::string WebServer::alarm_control_panel_json(alarm_control_panel::AlarmContro
1264
1428
  if (start_config == DETAIL_ALL) {
1265
1429
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
1266
1430
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
1431
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1432
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
1433
+ }
1267
1434
  }
1268
1435
  }
1269
1436
  });
@@ -1304,7 +1471,12 @@ void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlM
1304
1471
  continue;
1305
1472
 
1306
1473
  if (request->method() == HTTP_GET && match.method.empty()) {
1307
- std::string data = this->update_json(obj, DETAIL_STATE);
1474
+ auto detail = DETAIL_STATE;
1475
+ auto *param = request->getParam("detail");
1476
+ if (param && param->value() == "all") {
1477
+ detail = DETAIL_ALL;
1478
+ }
1479
+ std::string data = this->update_json(obj, detail);
1308
1480
  request->send(200, "application/json", data.c_str());
1309
1481
  return;
1310
1482
  }
@@ -1345,6 +1517,9 @@ std::string WebServer::update_json(update::UpdateEntity *obj, JsonDetail start_c
1345
1517
  root["release_url"] = obj->update_info.release_url;
1346
1518
  if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
1347
1519
  root["sorting_weight"] = this->sorting_entitys_[obj].weight;
1520
+ if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1521
+ root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
1522
+ }
1348
1523
  }
1349
1524
  }
1350
1525
  });
@@ -1643,8 +1818,12 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) {
1643
1818
 
1644
1819
  bool WebServer::isRequestHandlerTrivial() { return false; }
1645
1820
 
1646
- void WebServer::add_entity_to_sorting_list(EntityBase *entity, float weight) {
1647
- this->sorting_entitys_[entity] = SortingComponents{weight};
1821
+ void WebServer::add_entity_config(EntityBase *entity, float weight, uint64_t group) {
1822
+ this->sorting_entitys_[entity] = SortingComponents{weight, group};
1823
+ }
1824
+
1825
+ void WebServer::add_sorting_group(uint64_t group_id, const std::string &group_name, float weight) {
1826
+ this->sorting_groups_[group_id] = SortingGroup{group_name, weight};
1648
1827
  }
1649
1828
 
1650
1829
  void WebServer::schedule_(std::function<void()> &&f) {
@@ -44,6 +44,12 @@ struct UrlMatch {
44
44
 
45
45
  struct SortingComponents {
46
46
  float weight;
47
+ uint64_t group_id;
48
+ };
49
+
50
+ struct SortingGroup {
51
+ std::string name;
52
+ float weight;
47
53
  };
48
54
 
49
55
  enum JsonDetail { DETAIL_ALL, DETAIL_STATE };
@@ -337,7 +343,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
337
343
  /// This web handle is not trivial.
338
344
  bool isRequestHandlerTrivial() override; // NOLINT(readability-identifier-naming)
339
345
 
340
- void add_entity_to_sorting_list(EntityBase *entity, float weight);
346
+ void add_entity_config(EntityBase *entity, float weight, uint64_t group);
347
+ void add_sorting_group(uint64_t group_id, const std::string &group_name, float weight);
341
348
 
342
349
  protected:
343
350
  void schedule_(std::function<void()> &&f);
@@ -346,6 +353,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
346
353
  AsyncEventSource events_{"/events"};
347
354
  ListEntitiesIterator entities_iterator_;
348
355
  std::map<EntityBase *, SortingComponents> sorting_entitys_;
356
+ std::map<uint64_t, SortingGroup> sorting_groups_;
357
+
349
358
  #if USE_WEBSERVER_VERSION == 1
350
359
  const char *css_url_{nullptr};
351
360
  const char *js_url_{nullptr};
@@ -130,12 +130,11 @@ void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, voi
130
130
  }
131
131
 
132
132
  void WiFiComponent::wifi_pre_setup_() {
133
- #ifdef USE_ESP32_IGNORE_EFUSE_MAC_CRC
134
133
  uint8_t mac[6];
135
- get_mac_address_raw(mac);
136
- set_mac_address(mac);
137
- ESP_LOGV(TAG, "Use EFuse MAC without checking CRC: %s", get_mac_address_pretty().c_str());
138
- #endif
134
+ if (has_custom_mac_address()) {
135
+ get_mac_address_raw(mac);
136
+ set_mac_address(mac);
137
+ }
139
138
  esp_err_t err = esp_netif_init();
140
139
  if (err != ERR_OK) {
141
140
  ESP_LOGE(TAG, "esp_netif_init failed: %s", esp_err_to_name(err));
@@ -750,6 +750,7 @@ def time_period_str_unit(value):
750
750
  "ns": "nanoseconds",
751
751
  "nanoseconds": "nanoseconds",
752
752
  "us": "microseconds",
753
+ "µs": "microseconds",
753
754
  "microseconds": "microseconds",
754
755
  "ms": "milliseconds",
755
756
  "milliseconds": "milliseconds",
esphome/const.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Constants used by esphome."""
2
2
 
3
- __version__ = "2024.9.2"
3
+ __version__ = "2024.10.0b1"
4
4
 
5
5
  ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
6
6
  VALID_SUBSTITUTIONS_CHARACTERS = (
@@ -53,6 +53,7 @@ CONF_ALLOW_OTHER_USES = "allow_other_uses"
53
53
  CONF_ALPHA = "alpha"
54
54
  CONF_ALTITUDE = "altitude"
55
55
  CONF_AMBIENT_LIGHT = "ambient_light"
56
+ CONF_AMMONIA = "ammonia"
56
57
  CONF_ANALOG = "analog"
57
58
  CONF_AND = "and"
58
59
  CONF_ANGLE = "angle"
@@ -110,6 +111,7 @@ CONF_CALIBRATE_LINEAR = "calibrate_linear"
110
111
  CONF_CALIBRATION = "calibration"
111
112
  CONF_CAPACITANCE = "capacitance"
112
113
  CONF_CAPACITY = "capacity"
114
+ CONF_CARBON_MONOXIDE = "carbon_monoxide"
113
115
  CONF_CARRIER_DUTY_PERCENT = "carrier_duty_percent"
114
116
  CONF_CARRIER_FREQUENCY = "carrier_frequency"
115
117
  CONF_CERTIFICATE = "certificate"
@@ -120,6 +122,7 @@ CONF_CHANNELS = "channels"
120
122
  CONF_CHARACTERISTIC_UUID = "characteristic_uuid"
121
123
  CONF_CHECK = "check"
122
124
  CONF_CHIPSET = "chipset"
125
+ CONF_CLEAN_SESSION = "clean_session"
123
126
  CONF_CLEAR_IMPEDANCE = "clear_impedance"
124
127
  CONF_CLIENT_CERTIFICATE = "client_certificate"
125
128
  CONF_CLIENT_CERTIFICATE_KEY = "client_certificate_key"
@@ -262,6 +265,7 @@ CONF_ENUM_DATAPOINT = "enum_datapoint"
262
265
  CONF_EQUATION = "equation"
263
266
  CONF_ESP8266_DISABLE_SSL_SUPPORT = "esp8266_disable_ssl_support"
264
267
  CONF_ESPHOME = "esphome"
268
+ CONF_ETHANOL = "ethanol"
265
269
  CONF_ETHERNET = "ethernet"
266
270
  CONF_EVENT = "event"
267
271
  CONF_EVENT_TYPE = "event_type"
@@ -360,6 +364,7 @@ CONF_HOURS = "hours"
360
364
  CONF_HSYNC_PIN = "hsync_pin"
361
365
  CONF_HUMIDITY = "humidity"
362
366
  CONF_HUMIDITY_SENSOR = "humidity_sensor"
367
+ CONF_HYDROGEN = "hydrogen"
363
368
  CONF_HYSTERESIS = "hysteresis"
364
369
  CONF_I2C = "i2c"
365
370
  CONF_I2C_ID = "i2c_id"
@@ -375,6 +380,7 @@ CONF_IDLE_ACTION = "idle_action"
375
380
  CONF_IDLE_LEVEL = "idle_level"
376
381
  CONF_IDLE_TIME = "idle_time"
377
382
  CONF_IF = "if"
383
+ CONF_IGNORE_EFUSE_CUSTOM_MAC = "ignore_efuse_custom_mac"
378
384
  CONF_IGNORE_EFUSE_MAC_CRC = "ignore_efuse_mac_crc"
379
385
  CONF_IGNORE_OUT_OF_RANGE = "ignore_out_of_range"
380
386
  CONF_IGNORE_PIN_VALIDATION_ERROR = "ignore_pin_validation_error"
@@ -475,6 +481,7 @@ CONF_MEDIA_PLAYER = "media_player"
475
481
  CONF_MEDIUM = "medium"
476
482
  CONF_MEMORY_BLOCKS = "memory_blocks"
477
483
  CONF_MESSAGE = "message"
484
+ CONF_METHANE = "methane"
478
485
  CONF_METHOD = "method"
479
486
  CONF_MICROPHONE = "microphone"
480
487
  CONF_MIN_BRIGHTNESS = "min_brightness"
@@ -521,6 +528,7 @@ CONF_NBITS = "nbits"
521
528
  CONF_NEC = "nec"
522
529
  CONF_NETWORKS = "networks"
523
530
  CONF_NEW_PASSWORD = "new_password"
531
+ CONF_NITROGEN_DIOXIDE = "nitrogen_dioxide"
524
532
  CONF_NOISE_LEVEL = "noise_level"
525
533
  CONF_NUM_ATTEMPTS = "num_attempts"
526
534
  CONF_NUM_CHANNELS = "num_channels"
@@ -926,7 +934,6 @@ CONF_WARM_WHITE_COLOR_TEMPERATURE = "warm_white_color_temperature"
926
934
  CONF_WATCHDOG_THRESHOLD = "watchdog_threshold"
927
935
  CONF_WEB_SERVER = "web_server"
928
936
  CONF_WEB_SERVER_ID = "web_server_id"
929
- CONF_WEB_SERVER_SORTING_WEIGHT = "web_server_sorting_weight"
930
937
  CONF_WEIGHT = "weight"
931
938
  CONF_WHILE = "while"
932
939
  CONF_WHITE = "white"
@@ -954,6 +961,7 @@ ICON_ACCELERATION_Y = "mdi:axis-y-arrow"
954
961
  ICON_ACCELERATION_Z = "mdi:axis-z-arrow"
955
962
  ICON_ACCOUNT = "mdi:account"
956
963
  ICON_ACCOUNT_CHECK = "mdi:account-check"
964
+ ICON_AIR_FILTER = "mdi:air-filter"
957
965
  ICON_ARROW_EXPAND_VERTICAL = "mdi:arrow-expand-vertical"
958
966
  ICON_BATTERY = "mdi:battery"
959
967
  ICON_BLUETOOTH = "mdi:bluetooth"
@@ -975,6 +983,7 @@ ICON_FINGERPRINT = "mdi:fingerprint"
975
983
  ICON_FLASH = "mdi:flash"
976
984
  ICON_FLASK = "mdi:flask"
977
985
  ICON_FLASK_OUTLINE = "mdi:flask-outline"
986
+ ICON_FLASK_ROUND_BOTTOM = "mdi:flask-round-bottom"
978
987
  ICON_FLOWER = "mdi:flower"
979
988
  ICON_GAS_CYLINDER = "mdi:gas-cylinder"
980
989
  ICON_GAUGE = "mdi:gauge"
@@ -987,6 +996,7 @@ ICON_KEY_PLUS = "mdi:key-plus"
987
996
  ICON_LIGHTBULB = "mdi:lightbulb"
988
997
  ICON_MAGNET = "mdi:magnet"
989
998
  ICON_MEMORY = "mdi:memory"
999
+ ICON_MOLECULE_CO = "mdi:molecule-co"
990
1000
  ICON_MOLECULE_CO2 = "mdi:molecule-co2"
991
1001
  ICON_MOTION_SENSOR = "mdi:motion-sensor"
992
1002
  ICON_NEW_BOX = "mdi:new-box"