esphome 2024.11.2__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 (192) hide show
  1. esphome/__main__.py +1 -1
  2. esphome/components/adc/adc_sensor.h +7 -8
  3. esphome/components/adc/adc_sensor_common.cpp +24 -0
  4. esphome/components/adc/{adc_sensor.cpp → adc_sensor_esp32.cpp} +10 -179
  5. esphome/components/adc/adc_sensor_esp8266.cpp +58 -0
  6. esphome/components/adc/adc_sensor_libretiny.cpp +48 -0
  7. esphome/components/adc/adc_sensor_rp2040.cpp +93 -0
  8. esphome/components/alarm_control_panel/alarm_control_panel_call.cpp +3 -4
  9. esphome/components/animation/__init__.py +1 -2
  10. esphome/components/apds9306/apds9306.cpp +2 -1
  11. esphome/components/audio/audio.h +1 -1
  12. esphome/components/bk72xx/__init__.py +1 -1
  13. esphome/components/cse7766/cse7766.cpp +1 -1
  14. esphome/components/datetime/datetime_entity.cpp +1 -3
  15. esphome/components/deep_sleep/deep_sleep_esp32.cpp +2 -2
  16. esphome/components/dht/dht.cpp +2 -1
  17. esphome/components/display/display.cpp +10 -6
  18. esphome/components/display/display.h +14 -0
  19. esphome/components/display_menu_base/__init__.py +0 -2
  20. esphome/components/display_menu_base/display_menu_base.cpp +1 -1
  21. esphome/components/dsmr/dsmr.cpp +1 -1
  22. esphome/components/esp32/__init__.py +100 -22
  23. esphome/components/esp32/boards.py +222 -14
  24. esphome/components/esp32_ble/__init__.py +22 -2
  25. esphome/components/esp32_ble/ble.cpp +39 -12
  26. esphome/components/esp32_ble/ble.h +2 -0
  27. esphome/components/esp32_ble/ble_advertising.cpp +1 -1
  28. esphome/components/esp32_ble/ble_uuid.cpp +9 -10
  29. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +4 -1
  30. esphome/components/esp32_camera_web_server/camera_web_server.h +1 -1
  31. esphome/components/esp32_rmt_led_strip/light.py +3 -3
  32. esphome/components/esp8266/__init__.py +5 -7
  33. esphome/components/ezo/ezo.cpp +14 -26
  34. esphome/components/font/__init__.py +10 -25
  35. esphome/components/font/font.cpp +5 -3
  36. esphome/components/graphical_display_menu/__init__.py +2 -0
  37. esphome/components/haier/hon_climate.cpp +79 -80
  38. esphome/components/hbridge/switch/__init__.py +44 -0
  39. esphome/components/hbridge/switch/hbridge_switch.cpp +95 -0
  40. esphome/components/hbridge/switch/hbridge_switch.h +50 -0
  41. esphome/components/hitachi_ac344/hitachi_ac344.cpp +4 -2
  42. esphome/components/hitachi_ac424/hitachi_ac424.cpp +4 -2
  43. esphome/components/homeassistant/number/homeassistant_number.cpp +3 -0
  44. esphome/components/hx711/hx711.cpp +1 -1
  45. esphome/components/hx711/hx711.h +1 -1
  46. esphome/components/i2c/i2c_bus_esp_idf.cpp +2 -2
  47. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +61 -59
  48. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -17
  49. esphome/components/ili9xxx/display.py +1 -2
  50. esphome/components/ili9xxx/ili9xxx_display.cpp +3 -2
  51. esphome/components/image/__init__.py +1 -2
  52. esphome/components/logger/logger.cpp +1 -1
  53. esphome/components/ltr501/ltr501.cpp +1 -1
  54. esphome/components/lvgl/defines.py +9 -2
  55. esphome/components/lvgl/lv_validation.py +8 -3
  56. esphome/components/lvgl/lvgl_esphome.cpp +1 -1
  57. esphome/components/lvgl/lvgl_esphome.h +19 -0
  58. esphome/components/lvgl/widgets/animimg.py +12 -17
  59. esphome/components/lvgl/widgets/img.py +1 -3
  60. esphome/components/lvgl/widgets/line.py +6 -0
  61. esphome/components/lvgl/widgets/msgbox.py +2 -1
  62. esphome/components/matrix_keypad/__init__.py +15 -3
  63. esphome/components/matrix_keypad/matrix_keypad.cpp +4 -0
  64. esphome/components/matrix_keypad/matrix_keypad.h +5 -0
  65. esphome/components/max31865/max31865.cpp +4 -2
  66. esphome/components/modbus_controller/modbus_controller.cpp +24 -24
  67. esphome/components/modbus_controller/modbus_controller.h +22 -22
  68. esphome/components/modbus_controller/number/modbus_number.cpp +8 -8
  69. esphome/components/modbus_controller/number/modbus_number.h +4 -4
  70. esphome/components/modbus_controller/output/modbus_output.cpp +7 -6
  71. esphome/components/modbus_controller/output/modbus_output.h +5 -5
  72. esphome/components/modbus_controller/select/modbus_select.cpp +4 -3
  73. esphome/components/modbus_controller/select/modbus_select.h +4 -4
  74. esphome/components/modbus_controller/switch/modbus_switch.cpp +5 -5
  75. esphome/components/modbus_controller/switch/modbus_switch.h +2 -2
  76. esphome/components/mqtt/__init__.py +4 -0
  77. esphome/components/mqtt/mqtt_alarm_control_panel.cpp +2 -5
  78. esphome/components/mqtt/mqtt_backend_esp32.cpp +3 -3
  79. esphome/components/mqtt/mqtt_client.cpp +4 -0
  80. esphome/components/mqtt/mqtt_client.h +6 -0
  81. esphome/components/mqtt/mqtt_climate.cpp +13 -3
  82. esphome/components/mqtt/mqtt_sensor.cpp +2 -0
  83. esphome/components/network/ip_address.h +1 -1
  84. esphome/components/nextion/__init__.py +2 -0
  85. esphome/components/nextion/automation.h +76 -0
  86. esphome/components/nextion/base_component.py +1 -0
  87. esphome/components/nextion/binary_sensor/__init__.py +43 -2
  88. esphome/components/nextion/display.py +15 -0
  89. esphome/components/nextion/nextion.cpp +8 -5
  90. esphome/components/nextion/nextion.h +7 -0
  91. esphome/components/nextion/nextion_upload_idf.cpp +2 -2
  92. esphome/components/nextion/sensor/__init__.py +38 -5
  93. esphome/components/nextion/switch/__init__.py +38 -2
  94. esphome/components/nextion/text_sensor/__init__.py +37 -2
  95. esphome/components/nfc/ndef_record.cpp +3 -3
  96. esphome/components/online_image/__init__.py +1 -0
  97. esphome/components/online_image/png_image.cpp +4 -0
  98. esphome/components/opentherm/hub.cpp +6 -7
  99. esphome/components/opentherm/opentherm.cpp +18 -34
  100. esphome/components/opentherm/opentherm.h +4 -5
  101. esphome/components/ota/automation.h +1 -1
  102. esphome/components/output/float_output.cpp +1 -1
  103. esphome/components/pca6416a/pca6416a.cpp +5 -3
  104. esphome/components/pca9554/pca9554.cpp +4 -4
  105. esphome/components/pipsolar/pipsolar.cpp +2 -2
  106. esphome/components/pipsolar/switch/pipsolar_switch.cpp +2 -2
  107. esphome/components/pn532/pn532_mifare_ultralight.cpp +2 -2
  108. esphome/components/pn7150/pn7150_mifare_ultralight.cpp +2 -2
  109. esphome/components/pn7160/pn7160_mifare_ultralight.cpp +2 -2
  110. esphome/components/qmc5883l/qmc5883l.cpp +45 -19
  111. esphome/components/qmc5883l/qmc5883l.h +1 -1
  112. esphome/components/qspi_dbi/qspi_dbi.cpp +2 -1
  113. esphome/components/remote_base/raw_protocol.cpp +1 -1
  114. esphome/components/remote_receiver/__init__.py +5 -6
  115. esphome/components/rotary_encoder/rotary_encoder.cpp +3 -1
  116. esphome/components/rp2040/__init__.py +1 -1
  117. esphome/components/rtl87xx/__init__.py +1 -1
  118. esphome/components/safe_mode/automation.h +1 -1
  119. esphome/components/seeed_mr60bha2/__init__.py +41 -0
  120. esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +173 -0
  121. esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +61 -0
  122. esphome/components/seeed_mr60bha2/sensor.py +57 -0
  123. esphome/components/seeed_mr60fda2/__init__.py +41 -0
  124. esphome/components/seeed_mr60fda2/binary_sensor.py +33 -0
  125. esphome/components/seeed_mr60fda2/button/__init__.py +45 -0
  126. esphome/components/seeed_mr60fda2/button/get_radar_parameters_button.cpp +9 -0
  127. esphome/components/seeed_mr60fda2/button/get_radar_parameters_button.h +18 -0
  128. esphome/components/seeed_mr60fda2/button/reset_radar_button.cpp +9 -0
  129. esphome/components/seeed_mr60fda2/button/reset_radar_button.h +18 -0
  130. esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +368 -0
  131. esphome/components/seeed_mr60fda2/seeed_mr60fda2.h +101 -0
  132. esphome/components/seeed_mr60fda2/select/__init__.py +59 -0
  133. esphome/components/seeed_mr60fda2/select/height_threshold_select.cpp +15 -0
  134. esphome/components/seeed_mr60fda2/select/height_threshold_select.h +18 -0
  135. esphome/components/seeed_mr60fda2/select/install_height_select.cpp +15 -0
  136. esphome/components/seeed_mr60fda2/select/install_height_select.h +18 -0
  137. esphome/components/seeed_mr60fda2/select/sensitivity_select.cpp +15 -0
  138. esphome/components/seeed_mr60fda2/select/sensitivity_select.h +18 -0
  139. esphome/components/sen5x/sensor.py +5 -6
  140. esphome/components/sgp30/sensor.py +8 -9
  141. esphome/components/sgp30/sgp30.cpp +2 -6
  142. esphome/components/shelly_dimmer/shelly_dimmer.cpp +1 -1
  143. esphome/components/sim800l/sim800l.cpp +1 -1
  144. esphome/components/sntp/sntp_component.cpp +14 -20
  145. esphome/components/sntp/sntp_component.h +6 -9
  146. esphome/components/sntp/time.py +4 -7
  147. esphome/components/sprinkler/sprinkler.cpp +2 -2
  148. esphome/components/st7735/st7735.cpp +1 -1
  149. esphome/components/st7789v/st7789v.cpp +1 -1
  150. esphome/components/st7920/st7920.cpp +2 -3
  151. esphome/components/stepper/stepper.h +0 -1
  152. esphome/components/sun_gtil2/sun_gtil2.cpp +1 -1
  153. esphome/components/switch/binary_sensor/__init__.py +31 -0
  154. esphome/components/switch/binary_sensor/switch_binary_sensor.cpp +17 -0
  155. esphome/components/switch/binary_sensor/switch_binary_sensor.h +22 -0
  156. esphome/components/sx1509/sx1509_gpio_pin.cpp +2 -1
  157. esphome/components/sx1509/sx1509_gpio_pin.h +5 -5
  158. esphome/components/uart/uart.h +1 -1
  159. esphome/components/udp/udp_component.cpp +32 -16
  160. esphome/components/ufire_ec/sensor.py +4 -4
  161. esphome/components/uln2003/uln2003.cpp +4 -1
  162. esphome/components/waveshare_epaper/display.py +8 -0
  163. esphome/components/waveshare_epaper/waveshare_epaper.cpp +191 -0
  164. esphome/components/waveshare_epaper/waveshare_epaper.h +56 -0
  165. esphome/components/wiegand/__init__.py +3 -4
  166. esphome/components/wifi/__init__.py +42 -0
  167. esphome/components/wifi/wifi_component.cpp +2 -2
  168. esphome/components/wifi/wifi_component.h +82 -1
  169. esphome/components/wifi/wifi_component_esp32_arduino.cpp +1 -1
  170. esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
  171. esphome/components/wifi/wifi_component_esp_idf.cpp +1 -1
  172. esphome/components/wifi/wifi_component_libretiny.cpp +1 -1
  173. esphome/components/wifi/wifi_component_pico_w.cpp +1 -1
  174. esphome/components/wireguard/wireguard.cpp +2 -2
  175. esphome/components/xiaomi_ble/xiaomi_ble.cpp +1 -1
  176. esphome/config_validation.py +15 -11
  177. esphome/const.py +11 -1
  178. esphome/core/component.cpp +1 -1
  179. esphome/core/config.py +1 -2
  180. esphome/core/defines.h +3 -1
  181. esphome/core/helpers.cpp +20 -2
  182. esphome/core/helpers.h +10 -1
  183. esphome/core/optional.h +2 -2
  184. esphome/core/time.cpp +19 -15
  185. esphome/core/time.h +1 -3
  186. esphome/dashboard/web_server.py +6 -0
  187. {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/METADATA +4 -4
  188. {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/RECORD +192 -162
  189. {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/LICENSE +0 -0
  190. {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/WHEEL +0 -0
  191. {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/entry_points.txt +0 -0
  192. {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/top_level.txt +0 -0
@@ -279,7 +279,7 @@ std::string LvSelectable::get_selected_text() {
279
279
  static std::string join_string(std::vector<std::string> options) {
280
280
  return std::accumulate(
281
281
  options.begin(), options.end(), std::string(),
282
- [](const std::string &a, const std::string &b) -> std::string { return a + (a.length() > 0 ? "\n" : "") + b; });
282
+ [](const std::string &a, const std::string &b) -> std::string { return a + (!a.empty() ? "\n" : "") + b; });
283
283
  }
284
284
 
285
285
  void LvSelectable::set_selected_text(const std::string &text, lv_anim_enable_t anim) {
@@ -56,7 +56,26 @@ static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BIT
56
56
  inline void lv_img_set_src(lv_obj_t *obj, esphome::image::Image *image) {
57
57
  lv_img_set_src(obj, image->get_lv_img_dsc());
58
58
  }
59
+ inline void lv_disp_set_bg_image(lv_disp_t *disp, esphome::image::Image *image) {
60
+ lv_disp_set_bg_image(disp, image->get_lv_img_dsc());
61
+ }
59
62
  #endif // USE_LVGL_IMAGE
63
+ #ifdef USE_LVGL_ANIMIMG
64
+ inline void lv_animimg_set_src(lv_obj_t *img, std::vector<image::Image *> images) {
65
+ auto *dsc = static_cast<std::vector<lv_img_dsc_t *> *>(lv_obj_get_user_data(img));
66
+ if (dsc == nullptr) {
67
+ // object will be lazily allocated but never freed.
68
+ dsc = new std::vector<lv_img_dsc_t *>(images.size()); // NOLINT
69
+ lv_obj_set_user_data(img, dsc);
70
+ }
71
+ dsc->clear();
72
+ for (auto &image : images) {
73
+ dsc->push_back(image->get_lv_img_dsc());
74
+ }
75
+ lv_animimg_set_src(img, (const void **) dsc->data(), dsc->size());
76
+ }
77
+
78
+ #endif // USE_LVGL_ANIMIMG
60
79
 
61
80
  // Parent class for things that wrap an LVGL object
62
81
  class LvCompound {
@@ -1,20 +1,18 @@
1
1
  from esphome import automation
2
- import esphome.codegen as cg
3
2
  import esphome.config_validation as cv
4
3
  from esphome.const import CONF_DURATION, CONF_ID
5
4
 
6
5
  from ..automation import action_to_code
7
6
  from ..defines import CONF_AUTO_START, CONF_MAIN, CONF_REPEAT_COUNT, CONF_SRC
8
7
  from ..helpers import lvgl_components_required
9
- from ..lv_validation import lv_image, lv_milliseconds
8
+ from ..lv_validation import lv_image_list, lv_milliseconds
10
9
  from ..lvcode import lv
11
- from ..types import LvType, ObjUpdateAction, void_ptr
10
+ from ..types import LvType, ObjUpdateAction
12
11
  from . import Widget, WidgetType, get_widgets
13
12
  from .img import CONF_IMAGE
14
13
  from .label import CONF_LABEL
15
14
 
16
15
  CONF_ANIMIMG = "animimg"
17
- CONF_SRC_LIST_ID = "src_list_id"
18
16
 
19
17
 
20
18
  def lv_repeat_count(value):
@@ -32,14 +30,14 @@ ANIMIMG_BASE_SCHEMA = cv.Schema(
32
30
  ANIMIMG_SCHEMA = ANIMIMG_BASE_SCHEMA.extend(
33
31
  {
34
32
  cv.Required(CONF_DURATION): lv_milliseconds,
35
- cv.Required(CONF_SRC): cv.ensure_list(lv_image),
36
- cv.GenerateID(CONF_SRC_LIST_ID): cv.declare_id(void_ptr),
33
+ cv.Required(CONF_SRC): lv_image_list,
37
34
  }
38
35
  )
39
36
 
40
37
  ANIMIMG_MODIFY_SCHEMA = ANIMIMG_BASE_SCHEMA.extend(
41
38
  {
42
39
  cv.Optional(CONF_DURATION): lv_milliseconds,
40
+ cv.Optional(CONF_SRC): lv_image_list,
43
41
  }
44
42
  )
45
43
 
@@ -59,17 +57,14 @@ class AnimimgType(WidgetType):
59
57
  async def to_code(self, w: Widget, config):
60
58
  lvgl_components_required.add(CONF_IMAGE)
61
59
  lvgl_components_required.add(CONF_ANIMIMG)
62
- if CONF_SRC in config:
63
- srcs = [
64
- await lv_image.process(await cg.get_variable(x))
65
- for x in config[CONF_SRC]
66
- ]
67
- src_id = cg.static_const_array(config[CONF_SRC_LIST_ID], srcs)
68
- count = len(config[CONF_SRC])
69
- lv.animimg_set_src(w.obj, src_id, count)
70
- lv.animimg_set_repeat_count(w.obj, config[CONF_REPEAT_COUNT])
71
- lv.animimg_set_duration(w.obj, config[CONF_DURATION])
72
- if config.get(CONF_AUTO_START):
60
+ if srcs := config.get(CONF_SRC):
61
+ srcs = await lv_image_list.process(srcs)
62
+ lv.animimg_set_src(w.obj, srcs)
63
+ if repeat_count := config.get(CONF_REPEAT_COUNT):
64
+ lv.animimg_set_repeat_count(w.obj, repeat_count)
65
+ if duration := config.get(CONF_DURATION):
66
+ lv.animimg_set_duration(w.obj, duration)
67
+ if config[CONF_AUTO_START]:
73
68
  lv.animimg_start(w.obj)
74
69
 
75
70
  def get_uses(self):
@@ -1,4 +1,3 @@
1
- import esphome.codegen as cg
2
1
  import esphome.config_validation as cv
3
2
  from esphome.const import CONF_ANGLE, CONF_MODE
4
3
 
@@ -65,7 +64,6 @@ class ImgType(WidgetType):
65
64
 
66
65
  async def to_code(self, w: Widget, config):
67
66
  if src := config.get(CONF_SRC):
68
- src = await cg.get_variable(src)
69
67
  lv.img_set_src(w.obj, await lv_image.process(src))
70
68
  if (cf_angle := config.get(CONF_ANGLE)) is not None:
71
69
  pivot_x = config[CONF_PIVOT_X]
@@ -81,7 +79,7 @@ class ImgType(WidgetType):
81
79
  if CONF_ANTIALIAS in config:
82
80
  lv.img_set_antialias(w.obj, config[CONF_ANTIALIAS])
83
81
  if mode := config.get(CONF_MODE):
84
- lv.img_set_mode(w.obj, mode)
82
+ await w.set_property("size_mode", mode)
85
83
 
86
84
 
87
85
  img_spec = ImgType()
@@ -35,6 +35,11 @@ LINE_SCHEMA = {
35
35
  cv.GenerateID(CONF_POINT_LIST_ID): cv.declare_id(lv_point_t),
36
36
  }
37
37
 
38
+ LINE_MODIFY_SCHEMA = {
39
+ cv.Optional(CONF_POINTS): cv_point_list,
40
+ cv.GenerateID(CONF_POINT_LIST_ID): cv.declare_id(lv_point_t),
41
+ }
42
+
38
43
 
39
44
  class LineType(WidgetType):
40
45
  def __init__(self):
@@ -43,6 +48,7 @@ class LineType(WidgetType):
43
48
  LvType("lv_line_t"),
44
49
  (CONF_MAIN,),
45
50
  LINE_SCHEMA,
51
+ modify_schema=LINE_MODIFY_SCHEMA,
46
52
  )
47
53
 
48
54
  async def to_code(self, w: Widget, config):
@@ -29,7 +29,7 @@ from ..lvcode import (
29
29
  )
30
30
  from ..schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema, part_schema
31
31
  from ..types import LV_EVENT, char_ptr, lv_obj_t
32
- from . import Widget, set_obj_properties
32
+ from . import Widget, add_widgets, set_obj_properties
33
33
  from .button import button_spec
34
34
  from .buttonmatrix import (
35
35
  BUTTONMATRIX_BUTTON_SCHEMA,
@@ -119,6 +119,7 @@ async def msgbox_to_code(top_layer, conf):
119
119
  button_style = {CONF_ITEMS: button_style}
120
120
  await set_obj_properties(buttonmatrix_widget, button_style)
121
121
  await set_obj_properties(msgbox_widget, conf)
122
+ await add_widgets(msgbox_widget, conf)
122
123
  async with LambdaContext(EVENT_ARG, where=messagebox_id) as close_action:
123
124
  outer_widget.add_flag("LV_OBJ_FLAG_HIDDEN")
124
125
  if close_button:
@@ -1,8 +1,8 @@
1
+ from esphome import automation, pins
1
2
  import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
- from esphome import pins
4
3
  from esphome.components import key_provider
5
- from esphome.const import CONF_ID, CONF_PIN
4
+ import esphome.config_validation as cv
5
+ from esphome.const import CONF_ID, CONF_ON_KEY, CONF_PIN, CONF_TRIGGER_ID
6
6
 
7
7
  CODEOWNERS = ["@ssieb"]
8
8
 
@@ -14,6 +14,9 @@ matrix_keypad_ns = cg.esphome_ns.namespace("matrix_keypad")
14
14
  MatrixKeypad = matrix_keypad_ns.class_(
15
15
  "MatrixKeypad", key_provider.KeyProvider, cg.Component
16
16
  )
17
+ MatrixKeyTrigger = matrix_keypad_ns.class_(
18
+ "MatrixKeyTrigger", automation.Trigger.template(cg.uint8)
19
+ )
17
20
 
18
21
  CONF_KEYPAD_ID = "keypad_id"
19
22
  CONF_ROWS = "rows"
@@ -47,6 +50,11 @@ CONFIG_SCHEMA = cv.All(
47
50
  cv.Optional(CONF_DEBOUNCE_TIME, default=1): cv.int_range(min=1, max=100),
48
51
  cv.Optional(CONF_HAS_DIODES): cv.boolean,
49
52
  cv.Optional(CONF_HAS_PULLDOWNS): cv.boolean,
53
+ cv.Optional(CONF_ON_KEY): automation.validate_automation(
54
+ {
55
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MatrixKeyTrigger),
56
+ }
57
+ ),
50
58
  }
51
59
  ),
52
60
  check_keys,
@@ -73,3 +81,7 @@ async def to_code(config):
73
81
  cg.add(var.set_has_diodes(config[CONF_HAS_DIODES]))
74
82
  if CONF_HAS_PULLDOWNS in config:
75
83
  cg.add(var.set_has_pulldowns(config[CONF_HAS_PULLDOWNS]))
84
+ for conf in config.get(CONF_ON_KEY, []):
85
+ trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID])
86
+ cg.add(var.register_key_trigger(trigger))
87
+ await automation.build_automation(trigger, [(cg.uint8, "x")], conf)
@@ -86,6 +86,8 @@ void MatrixKeypad::loop() {
86
86
  if (!this->keys_.empty()) {
87
87
  uint8_t keycode = this->keys_[key];
88
88
  ESP_LOGD(TAG, "key '%c' pressed", keycode);
89
+ for (auto &trigger : this->key_triggers_)
90
+ trigger->trigger(keycode);
89
91
  for (auto &listener : this->listeners_)
90
92
  listener->key_pressed(keycode);
91
93
  this->send_key_(keycode);
@@ -107,5 +109,7 @@ void MatrixKeypad::dump_config() {
107
109
 
108
110
  void MatrixKeypad::register_listener(MatrixKeypadListener *listener) { this->listeners_.push_back(listener); }
109
111
 
112
+ void MatrixKeypad::register_key_trigger(MatrixKeyTrigger *trig) { this->key_triggers_.push_back(trig); }
113
+
110
114
  } // namespace matrix_keypad
111
115
  } // namespace esphome
@@ -1,6 +1,7 @@
1
1
  #pragma once
2
2
 
3
3
  #include "esphome/components/key_provider/key_provider.h"
4
+ #include "esphome/core/automation.h"
4
5
  #include "esphome/core/component.h"
5
6
  #include "esphome/core/hal.h"
6
7
  #include "esphome/core/helpers.h"
@@ -18,6 +19,8 @@ class MatrixKeypadListener {
18
19
  virtual void key_released(uint8_t key){};
19
20
  };
20
21
 
22
+ class MatrixKeyTrigger : public Trigger<uint8_t> {};
23
+
21
24
  class MatrixKeypad : public key_provider::KeyProvider, public Component {
22
25
  public:
23
26
  void setup() override;
@@ -31,6 +34,7 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component {
31
34
  void set_has_pulldowns(int has_pulldowns) { has_pulldowns_ = has_pulldowns; };
32
35
 
33
36
  void register_listener(MatrixKeypadListener *listener);
37
+ void register_key_trigger(MatrixKeyTrigger *trig);
34
38
 
35
39
  protected:
36
40
  std::vector<GPIOPin *> rows_;
@@ -42,6 +46,7 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component {
42
46
  int pressed_key_ = -1;
43
47
 
44
48
  std::vector<MatrixKeypadListener *> listeners_{};
49
+ std::vector<MatrixKeyTrigger *> key_triggers_;
45
50
  };
46
51
 
47
52
  } // namespace matrix_keypad
@@ -106,7 +106,8 @@ void MAX31865Sensor::read_data_() {
106
106
 
107
107
  // Check faults
108
108
  const uint8_t faults = this->read_register_(FAULT_STATUS_REG);
109
- if ((has_fault_ = faults & 0b00111100)) {
109
+ has_fault_ = faults & 0b00111100;
110
+ if (has_fault_) {
110
111
  if (faults & (1 << 2)) {
111
112
  ESP_LOGE(TAG, "Overvoltage/undervoltage fault");
112
113
  }
@@ -125,7 +126,8 @@ void MAX31865Sensor::read_data_() {
125
126
  } else {
126
127
  this->status_clear_error();
127
128
  }
128
- if ((has_warn_ = faults & 0b11000000)) {
129
+ has_warn_ = faults & 0b11000000;
130
+ if (has_warn_) {
129
131
  if (faults & (1 << 6)) {
130
132
  ESP_LOGW(TAG, "RTD Low Threshold");
131
133
  }
@@ -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);