esphome 2024.10.3__py3-none-any.whl → 2024.11.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 (228) hide show
  1. esphome/__main__.py +22 -4
  2. esphome/automation.py +29 -2
  3. esphome/components/animation/__init__.py +5 -8
  4. esphome/components/animation/animation.cpp +1 -1
  5. esphome/components/audio/__init__.py +9 -0
  6. esphome/components/audio/audio.h +21 -0
  7. esphome/components/axs15231/__init__.py +6 -0
  8. esphome/components/axs15231/touchscreen/__init__.py +36 -0
  9. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +64 -0
  10. esphome/components/axs15231/touchscreen/axs15231_touchscreen.h +27 -0
  11. esphome/components/bme68x_bsec2/__init__.py +1 -1
  12. esphome/components/bytebuffer/__init__.py +5 -0
  13. esphome/components/bytebuffer/bytebuffer.h +421 -0
  14. esphome/components/climate/__init__.py +14 -13
  15. esphome/components/datetime/__init__.py +3 -3
  16. esphome/components/debug/debug_esp32.cpp +16 -8
  17. esphome/components/dfplayer/dfplayer.cpp +132 -6
  18. esphome/components/dfplayer/dfplayer.h +19 -53
  19. esphome/components/display/display.cpp +142 -0
  20. esphome/components/display/display.h +7 -0
  21. esphome/components/es8311/__init__.py +0 -0
  22. esphome/components/es8311/audio_dac.py +70 -0
  23. esphome/components/es8311/es8311.cpp +227 -0
  24. esphome/components/es8311/es8311.h +135 -0
  25. esphome/components/es8311/es8311_const.h +195 -0
  26. esphome/components/esp32/boards.py +199 -1
  27. esphome/components/esp32/gpio.py +3 -1
  28. esphome/components/esp32_ble/const_esp32c6.h +7 -0
  29. esphome/components/esp32_ble_client/ble_client_base.h +1 -1
  30. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -1
  31. esphome/components/esp32_rmt_led_strip/led_strip.cpp +2 -2
  32. esphome/components/esp32_rmt_led_strip/led_strip.h +2 -0
  33. esphome/components/esp32_rmt_led_strip/light.py +3 -1
  34. esphome/components/esp8266/gpio.py +7 -5
  35. esphome/components/ethernet/__init__.py +55 -1
  36. esphome/components/ethernet/ethernet_component.cpp +14 -1
  37. esphome/components/ethernet/ethernet_component.h +7 -1
  38. esphome/components/font/__init__.py +213 -108
  39. esphome/components/gp8403/output/__init__.py +1 -1
  40. esphome/components/host/gpio.py +6 -4
  41. esphome/components/http_request/__init__.py +12 -0
  42. esphome/components/http_request/http_request.h +65 -3
  43. esphome/components/http_request/http_request_arduino.cpp +2 -3
  44. esphome/components/http_request/http_request_idf.cpp +6 -14
  45. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  46. esphome/components/http_request/update/http_request_update.cpp +1 -1
  47. esphome/components/i2c_device/__init__.py +26 -0
  48. esphome/components/i2c_device/i2c_device.cpp +17 -0
  49. esphome/components/i2c_device/i2c_device.h +18 -0
  50. esphome/components/i2s_audio/__init__.py +1 -3
  51. esphome/components/i2s_audio/speaker/__init__.py +12 -4
  52. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +432 -197
  53. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +91 -32
  54. esphome/components/ili9xxx/display.py +5 -1
  55. esphome/components/image/__init__.py +5 -8
  56. esphome/components/image/image.cpp +14 -14
  57. esphome/components/image/image.h +20 -24
  58. esphome/components/internal_temperature/internal_temperature.cpp +51 -2
  59. esphome/components/internal_temperature/internal_temperature.h +1 -0
  60. esphome/components/libretiny/gpio.py +4 -2
  61. esphome/components/light/__init__.py +32 -1
  62. esphome/components/light/automation.py +39 -32
  63. esphome/components/light/effects.py +36 -36
  64. esphome/components/light/light_state.cpp +6 -16
  65. esphome/components/light/light_state.h +34 -0
  66. esphome/components/light/types.py +3 -1
  67. esphome/components/logger/logger_esp32.cpp +15 -0
  68. esphome/components/lvgl/__init__.py +202 -95
  69. esphome/components/lvgl/automation.py +42 -40
  70. esphome/components/lvgl/binary_sensor/__init__.py +8 -15
  71. esphome/components/lvgl/defines.py +14 -8
  72. esphome/components/lvgl/encoders.py +11 -8
  73. esphome/components/lvgl/keypads.py +77 -0
  74. esphome/components/lvgl/light/__init__.py +6 -8
  75. esphome/components/lvgl/lv_validation.py +2 -4
  76. esphome/components/lvgl/lvcode.py +3 -9
  77. esphome/components/lvgl/lvgl_esphome.cpp +210 -89
  78. esphome/components/lvgl/lvgl_esphome.h +113 -30
  79. esphome/components/lvgl/lvgl_proxy.h +17 -0
  80. esphome/components/lvgl/number/__init__.py +10 -15
  81. esphome/components/lvgl/schemas.py +4 -2
  82. esphome/components/lvgl/select/__init__.py +12 -37
  83. esphome/components/lvgl/select/lvgl_select.h +27 -33
  84. esphome/components/lvgl/sensor/__init__.py +8 -14
  85. esphome/components/lvgl/styles.py +3 -4
  86. esphome/components/lvgl/switch/__init__.py +8 -13
  87. esphome/components/lvgl/text/__init__.py +5 -6
  88. esphome/components/lvgl/text_sensor/__init__.py +15 -15
  89. esphome/components/lvgl/touchscreens.py +2 -3
  90. esphome/components/lvgl/trigger.py +7 -9
  91. esphome/components/lvgl/types.py +9 -3
  92. esphome/components/lvgl/widgets/__init__.py +32 -21
  93. esphome/components/lvgl/widgets/dropdown.py +22 -10
  94. esphome/components/lvgl/widgets/msgbox.py +6 -5
  95. esphome/components/lvgl/widgets/obj.py +4 -2
  96. esphome/components/lvgl/widgets/page.py +3 -2
  97. esphome/components/lvgl/widgets/qrcode.py +54 -0
  98. esphome/components/lvgl/widgets/roller.py +21 -14
  99. esphome/components/lvgl/widgets/tileview.py +2 -1
  100. esphome/components/max17043/__init__.py +1 -0
  101. esphome/components/max17043/automation.h +20 -0
  102. esphome/components/max17043/max17043.cpp +98 -0
  103. esphome/components/max17043/max17043.h +29 -0
  104. esphome/components/max17043/sensor.py +77 -0
  105. esphome/components/media_player/__init__.py +11 -0
  106. esphome/components/media_player/automation.h +10 -0
  107. esphome/components/media_player/media_player.cpp +4 -0
  108. esphome/components/midea/air_conditioner.cpp +17 -1
  109. esphome/components/mlx90393/sensor.py +1 -1
  110. esphome/components/modbus_controller/__init__.py +31 -1
  111. esphome/components/modbus_controller/automation.h +16 -0
  112. esphome/components/modbus_controller/const.py +2 -0
  113. esphome/components/modbus_controller/modbus_controller.cpp +14 -2
  114. esphome/components/modbus_controller/modbus_controller.h +9 -0
  115. esphome/components/mopeka_pro_check/mopeka_pro_check.cpp +40 -21
  116. esphome/components/mopeka_pro_check/mopeka_pro_check.h +9 -2
  117. esphome/components/mopeka_pro_check/sensor.py +41 -0
  118. esphome/components/mqtt/__init__.py +36 -0
  119. esphome/components/mqtt/mqtt_client.cpp +27 -3
  120. esphome/components/mqtt/mqtt_client.h +27 -2
  121. esphome/components/mqtt/mqtt_climate.cpp +4 -2
  122. esphome/components/mqtt/mqtt_component.cpp +6 -0
  123. esphome/components/mqtt/mqtt_component.h +4 -0
  124. esphome/components/mqtt/mqtt_const.h +6 -0
  125. esphome/components/online_image/online_image.cpp +2 -8
  126. esphome/components/online_image/online_image.h +2 -6
  127. esphome/components/opentherm/__init__.py +35 -9
  128. esphome/components/opentherm/binary_sensor/__init__.py +33 -0
  129. esphome/components/opentherm/const.py +11 -0
  130. esphome/components/opentherm/generate.py +142 -0
  131. esphome/components/opentherm/hub.cpp +130 -24
  132. esphome/components/opentherm/hub.h +62 -9
  133. esphome/components/opentherm/input.h +18 -0
  134. esphome/components/opentherm/input.py +51 -0
  135. esphome/components/opentherm/number/__init__.py +74 -0
  136. esphome/components/opentherm/number/number.cpp +40 -0
  137. esphome/components/opentherm/number/number.h +31 -0
  138. esphome/components/opentherm/opentherm.cpp +30 -0
  139. esphome/components/opentherm/opentherm.h +34 -2
  140. esphome/components/opentherm/opentherm_macros.h +151 -0
  141. esphome/components/opentherm/output/__init__.py +47 -0
  142. esphome/components/opentherm/output/output.cpp +18 -0
  143. esphome/components/opentherm/output/output.h +33 -0
  144. esphome/components/opentherm/schema.py +814 -0
  145. esphome/components/opentherm/sensor/__init__.py +51 -0
  146. esphome/components/opentherm/switch/__init__.py +43 -0
  147. esphome/components/opentherm/switch/switch.cpp +28 -0
  148. esphome/components/opentherm/switch/switch.h +20 -0
  149. esphome/components/opentherm/validate.py +31 -0
  150. esphome/components/pcd8544/display.py +8 -4
  151. esphome/components/prometheus/prometheus_handler.cpp +176 -14
  152. esphome/components/prometheus/prometheus_handler.h +25 -7
  153. esphome/components/qspi_amoled/display.py +1 -141
  154. esphome/components/qspi_dbi/display.py +185 -0
  155. esphome/components/qspi_dbi/models.py +64 -0
  156. esphome/components/{qspi_amoled/qspi_amoled.cpp → qspi_dbi/qspi_dbi.cpp} +95 -46
  157. esphome/components/{qspi_amoled/qspi_amoled.h → qspi_dbi/qspi_dbi.h} +26 -15
  158. esphome/components/rp2040/__init__.py +6 -3
  159. esphome/components/rp2040/gpio.py +5 -3
  160. esphome/components/rtttl/rtttl.cpp +4 -1
  161. esphome/components/rtttl/rtttl.h +1 -0
  162. esphome/components/sdl/sdl_esphome.cpp +22 -5
  163. esphome/components/sdl/sdl_esphome.h +1 -0
  164. esphome/components/sensor/__init__.py +18 -8
  165. esphome/components/sensor/filter.cpp +19 -18
  166. esphome/components/sensor/filter.h +9 -10
  167. esphome/components/sgp4x/sgp4x.cpp +40 -74
  168. esphome/components/sgp4x/sgp4x.h +5 -3
  169. esphome/components/speaker/__init__.py +51 -5
  170. esphome/components/speaker/automation.h +25 -0
  171. esphome/components/speaker/speaker.h +72 -1
  172. esphome/components/spi/__init__.py +15 -14
  173. esphome/components/spi_device/__init__.py +4 -15
  174. esphome/components/ssd1306_spi/display.py +6 -2
  175. esphome/components/ssd1322_spi/display.py +6 -2
  176. esphome/components/ssd1325_spi/display.py +6 -2
  177. esphome/components/ssd1327_spi/display.py +6 -2
  178. esphome/components/ssd1331_spi/display.py +6 -2
  179. esphome/components/ssd1351_spi/display.py +6 -2
  180. esphome/components/st7567_spi/display.py +6 -2
  181. esphome/components/st7701s/display.py +5 -1
  182. esphome/components/st7735/display.py +10 -5
  183. esphome/components/st7789v/display.py +12 -7
  184. esphome/components/statsd/statsd.cpp +2 -0
  185. esphome/components/statsd/statsd.h +2 -0
  186. esphome/components/sun/sun.h +3 -0
  187. esphome/components/tc74/__init__.py +1 -0
  188. esphome/components/tc74/sensor.py +32 -0
  189. esphome/components/tc74/tc74.cpp +68 -0
  190. esphome/components/tc74/tc74.h +28 -0
  191. esphome/components/touchscreen/__init__.py +41 -50
  192. esphome/components/touchscreen/touchscreen.h +4 -8
  193. esphome/components/udp/udp_component.cpp +6 -3
  194. esphome/components/udp/udp_component.h +4 -2
  195. esphome/components/waveshare_epaper/display.py +6 -2
  196. esphome/components/web_server/web_server.cpp +22 -0
  197. esphome/components/web_server/web_server.h +3 -0
  198. esphome/components/weikai/weikai.h +2 -2
  199. esphome/components/wifi/wifi_component.cpp +2 -2
  200. esphome/components/wifi/wifi_component_esp32_arduino.cpp +4 -4
  201. esphome/components/wifi/wifi_component_esp8266.cpp +4 -4
  202. esphome/components/wifi/wifi_component_esp_idf.cpp +2 -2
  203. esphome/components/xpt2046/touchscreen/__init__.py +7 -32
  204. esphome/config_validation.py +3 -1
  205. esphome/const.py +8 -1
  206. esphome/core/defines.h +8 -2
  207. esphome/core/helpers.cpp +32 -17
  208. esphome/core/helpers.h +32 -16
  209. esphome/core/ring_buffer.cpp +2 -2
  210. esphome/core/ring_buffer.h +2 -2
  211. esphome/dashboard/core.py +25 -0
  212. esphome/dashboard/status/mdns.py +3 -4
  213. esphome/dashboard/web_server.py +54 -19
  214. esphome/espota2.py +36 -35
  215. esphome/helpers.py +68 -16
  216. esphome/mqtt.py +9 -2
  217. esphome/storage_json.py +4 -0
  218. esphome/writer.py +7 -18
  219. esphome/zeroconf.py +8 -6
  220. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/METADATA +7 -5
  221. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/RECORD +226 -180
  222. esphome/core/bytebuffer.cpp +0 -167
  223. esphome/core/bytebuffer.h +0 -144
  224. /esphome/components/{qspi_amoled → qspi_dbi}/__init__.py +0 -0
  225. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/LICENSE +0 -0
  226. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/WHEEL +0 -0
  227. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/entry_points.txt +0 -0
  228. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,51 @@
1
+ from typing import Any
2
+
3
+ import esphome.codegen as cg
4
+ import esphome.config_validation as cv
5
+ from . import schema, generate
6
+
7
+ CONF_min_value = "min_value"
8
+ CONF_max_value = "max_value"
9
+ CONF_auto_min_value = "auto_min_value"
10
+ CONF_auto_max_value = "auto_max_value"
11
+ CONF_step = "step"
12
+
13
+ OpenthermInput = generate.opentherm_ns.class_("OpenthermInput")
14
+
15
+
16
+ def validate_min_value_less_than_max_value(conf):
17
+ if (
18
+ CONF_min_value in conf
19
+ and CONF_max_value in conf
20
+ and conf[CONF_min_value] > conf[CONF_max_value]
21
+ ):
22
+ raise cv.Invalid(f"{CONF_min_value} must be less than {CONF_max_value}")
23
+ return conf
24
+
25
+
26
+ def input_schema(entity: schema.InputSchema) -> cv.Schema:
27
+ result = cv.Schema(
28
+ {
29
+ cv.Optional(CONF_min_value, entity.range[0]): cv.float_range(
30
+ entity.range[0], entity.range[1]
31
+ ),
32
+ cv.Optional(CONF_max_value, entity.range[1]): cv.float_range(
33
+ entity.range[0], entity.range[1]
34
+ ),
35
+ }
36
+ )
37
+ result = result.add_extra(validate_min_value_less_than_max_value)
38
+ result = result.extend({cv.Optional(CONF_step, False): cv.float_})
39
+ if entity.auto_min_value is not None:
40
+ result = result.extend({cv.Optional(CONF_auto_min_value, False): cv.boolean})
41
+ if entity.auto_max_value is not None:
42
+ result = result.extend({cv.Optional(CONF_auto_max_value, False): cv.boolean})
43
+
44
+ return result
45
+
46
+
47
+ def generate_setters(entity: cg.MockObj, conf: dict[str, Any]) -> None:
48
+ generate.add_property_set(entity, CONF_min_value, conf)
49
+ generate.add_property_set(entity, CONF_max_value, conf)
50
+ generate.add_property_set(entity, CONF_auto_min_value, conf)
51
+ generate.add_property_set(entity, CONF_auto_max_value, conf)
@@ -0,0 +1,74 @@
1
+ from typing import Any
2
+
3
+ import esphome.codegen as cg
4
+ import esphome.config_validation as cv
5
+ from esphome.components import number
6
+ from esphome.const import (
7
+ CONF_ID,
8
+ CONF_UNIT_OF_MEASUREMENT,
9
+ CONF_STEP,
10
+ CONF_INITIAL_VALUE,
11
+ CONF_RESTORE_VALUE,
12
+ )
13
+ from .. import const, schema, validate, input, generate
14
+
15
+ DEPENDENCIES = [const.OPENTHERM]
16
+ COMPONENT_TYPE = const.NUMBER
17
+
18
+ OpenthermNumber = generate.opentherm_ns.class_(
19
+ "OpenthermNumber", number.Number, cg.Component, input.OpenthermInput
20
+ )
21
+
22
+
23
+ async def new_openthermnumber(config: dict[str, Any]) -> cg.Pvariable:
24
+ var = cg.new_Pvariable(config[CONF_ID])
25
+ await cg.register_component(var, config)
26
+ await number.register_number(
27
+ var,
28
+ config,
29
+ min_value=config[input.CONF_min_value],
30
+ max_value=config[input.CONF_max_value],
31
+ step=config[input.CONF_step],
32
+ )
33
+ input.generate_setters(var, config)
34
+
35
+ if CONF_INITIAL_VALUE in config:
36
+ cg.add(var.set_initial_value(config[CONF_INITIAL_VALUE]))
37
+ if CONF_RESTORE_VALUE in config:
38
+ cg.add(var.set_restore_value(config[CONF_RESTORE_VALUE]))
39
+
40
+ return var
41
+
42
+
43
+ def get_entity_validation_schema(entity: schema.InputSchema) -> cv.Schema:
44
+ return (
45
+ number.NUMBER_SCHEMA.extend(
46
+ {
47
+ cv.GenerateID(): cv.declare_id(OpenthermNumber),
48
+ cv.Optional(
49
+ CONF_UNIT_OF_MEASUREMENT, entity.unit_of_measurement
50
+ ): cv.string_strict,
51
+ cv.Optional(CONF_STEP, entity.step): cv.float_,
52
+ cv.Optional(CONF_INITIAL_VALUE): cv.float_,
53
+ cv.Optional(CONF_RESTORE_VALUE): cv.boolean,
54
+ }
55
+ )
56
+ .extend(input.input_schema(entity))
57
+ .extend(cv.COMPONENT_SCHEMA)
58
+ )
59
+
60
+
61
+ CONFIG_SCHEMA = validate.create_component_schema(
62
+ schema.INPUTS, get_entity_validation_schema
63
+ )
64
+
65
+
66
+ async def to_code(config: dict[str, Any]) -> None:
67
+ keys = await generate.component_to_code(
68
+ COMPONENT_TYPE,
69
+ schema.INPUTS,
70
+ OpenthermNumber,
71
+ generate.create_only_conf(new_openthermnumber),
72
+ config,
73
+ )
74
+ generate.define_readers(COMPONENT_TYPE, keys)
@@ -0,0 +1,40 @@
1
+ #include "number.h"
2
+
3
+ namespace esphome {
4
+ namespace opentherm {
5
+
6
+ static const char *const TAG = "opentherm.number";
7
+
8
+ void OpenthermNumber::control(float value) {
9
+ this->publish_state(value);
10
+
11
+ if (this->restore_value_)
12
+ this->pref_.save(&value);
13
+ }
14
+
15
+ void OpenthermNumber::setup() {
16
+ float value;
17
+ if (!this->restore_value_) {
18
+ value = this->initial_value_;
19
+ } else {
20
+ this->pref_ = global_preferences->make_preference<float>(this->get_object_id_hash());
21
+ if (!this->pref_.load(&value)) {
22
+ if (!std::isnan(this->initial_value_)) {
23
+ value = this->initial_value_;
24
+ } else {
25
+ value = this->traits.get_min_value();
26
+ }
27
+ }
28
+ }
29
+ this->publish_state(value);
30
+ }
31
+
32
+ void OpenthermNumber::dump_config() {
33
+ LOG_NUMBER("", "OpenTherm Number", this);
34
+ ESP_LOGCONFIG(TAG, " Restore value: %d", this->restore_value_);
35
+ ESP_LOGCONFIG(TAG, " Initial value: %.2f", this->initial_value_);
36
+ ESP_LOGCONFIG(TAG, " Current value: %.2f", this->state);
37
+ }
38
+
39
+ } // namespace opentherm
40
+ } // namespace esphome
@@ -0,0 +1,31 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/number/number.h"
4
+ #include "esphome/core/preferences.h"
5
+ #include "esphome/core/log.h"
6
+ #include "esphome/components/opentherm/input.h"
7
+
8
+ namespace esphome {
9
+ namespace opentherm {
10
+
11
+ // Just a simple number, which stores the number
12
+ class OpenthermNumber : public number::Number, public Component, public OpenthermInput {
13
+ protected:
14
+ void control(float value) override;
15
+ void setup() override;
16
+ void dump_config() override;
17
+
18
+ float initial_value_{NAN};
19
+ bool restore_value_{false};
20
+
21
+ ESPPreferenceObject pref_;
22
+
23
+ public:
24
+ void set_min_value(float min_value) override { this->traits.set_min_value(min_value); }
25
+ void set_max_value(float max_value) override { this->traits.set_max_value(max_value); }
26
+ void set_initial_value(float initial_value) { initial_value_ = initial_value; }
27
+ void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
28
+ };
29
+
30
+ } // namespace opentherm
31
+ } // namespace esphome
@@ -283,6 +283,9 @@ bool OpenTherm::init_esp32_timer_() {
283
283
  .clk_src = TIMER_SRC_CLK_DEFAULT,
284
284
  #endif
285
285
  .divider = 80,
286
+ #if defined(SOC_TIMER_GROUP_SUPPORT_XTAL) && ESP_IDF_VERSION_MAJOR < 5
287
+ .clk_src = TIMER_SRC_CLK_APB
288
+ #endif
286
289
  };
287
290
 
288
291
  esp_err_t result;
@@ -480,6 +483,8 @@ const char *OpenTherm::message_id_to_str(MessageId id) {
480
483
  TO_STRING_MEMBER(EXHAUST_TEMP)
481
484
  TO_STRING_MEMBER(FAN_SPEED)
482
485
  TO_STRING_MEMBER(FLAME_CURRENT)
486
+ TO_STRING_MEMBER(ROOM_TEMP_CH2)
487
+ TO_STRING_MEMBER(REL_HUMIDITY)
483
488
  TO_STRING_MEMBER(DHW_BOUNDS)
484
489
  TO_STRING_MEMBER(CH_BOUNDS)
485
490
  TO_STRING_MEMBER(OTC_CURVE_BOUNDS)
@@ -489,14 +494,39 @@ const char *OpenTherm::message_id_to_str(MessageId id) {
489
494
  TO_STRING_MEMBER(HVAC_STATUS)
490
495
  TO_STRING_MEMBER(REL_VENT_SETPOINT)
491
496
  TO_STRING_MEMBER(DEVICE_VENT)
497
+ TO_STRING_MEMBER(HVAC_VER_ID)
492
498
  TO_STRING_MEMBER(REL_VENTILATION)
493
499
  TO_STRING_MEMBER(REL_HUMID_EXHAUST)
500
+ TO_STRING_MEMBER(EXHAUST_CO2)
494
501
  TO_STRING_MEMBER(SUPPLY_INLET_TEMP)
495
502
  TO_STRING_MEMBER(SUPPLY_OUTLET_TEMP)
496
503
  TO_STRING_MEMBER(EXHAUST_INLET_TEMP)
497
504
  TO_STRING_MEMBER(EXHAUST_OUTLET_TEMP)
505
+ TO_STRING_MEMBER(EXHAUST_FAN_SPEED)
506
+ TO_STRING_MEMBER(SUPPLY_FAN_SPEED)
507
+ TO_STRING_MEMBER(REMOTE_VENTILATION_PARAM)
498
508
  TO_STRING_MEMBER(NOM_REL_VENTILATION)
509
+ TO_STRING_MEMBER(HVAC_NUM_TSP)
510
+ TO_STRING_MEMBER(HVAC_IDX_TSP)
511
+ TO_STRING_MEMBER(HVAC_FHB_SIZE)
512
+ TO_STRING_MEMBER(HVAC_FHB_IDX)
513
+ TO_STRING_MEMBER(RF_SIGNAL)
514
+ TO_STRING_MEMBER(DHW_MODE)
499
515
  TO_STRING_MEMBER(OVERRIDE_FUNC)
516
+ TO_STRING_MEMBER(SOLAR_MODE_FLAGS)
517
+ TO_STRING_MEMBER(SOLAR_ASF)
518
+ TO_STRING_MEMBER(SOLAR_VERSION_ID)
519
+ TO_STRING_MEMBER(SOLAR_PRODUCT_ID)
520
+ TO_STRING_MEMBER(SOLAR_NUM_TSP)
521
+ TO_STRING_MEMBER(SOLAR_IDX_TSP)
522
+ TO_STRING_MEMBER(SOLAR_FHB_SIZE)
523
+ TO_STRING_MEMBER(SOLAR_FHB_IDX)
524
+ TO_STRING_MEMBER(SOLAR_STARTS)
525
+ TO_STRING_MEMBER(SOLAR_HOURS)
526
+ TO_STRING_MEMBER(SOLAR_ENERGY)
527
+ TO_STRING_MEMBER(SOLAR_TOTAL_ENERGY)
528
+ TO_STRING_MEMBER(FAILED_BURNER_STARTS)
529
+ TO_STRING_MEMBER(BURNER_FLAME_LOW)
500
530
  TO_STRING_MEMBER(OEM_DIAGNOSTIC)
501
531
  TO_STRING_MEMBER(BURNER_STARTS)
502
532
  TO_STRING_MEMBER(CH_PUMP_STARTS)
@@ -20,7 +20,6 @@
20
20
  namespace esphome {
21
21
  namespace opentherm {
22
22
 
23
- // TODO: Account for immutable semantics change in hub.cpp when doing later installments of OpenTherm PR
24
23
  template<class T> constexpr T read_bit(T value, uint8_t bit) { return (value >> bit) & 0x01; }
25
24
 
26
25
  template<class T> constexpr T set_bit(T value, uint8_t bit) { return value |= (1UL << bit); }
@@ -28,7 +27,7 @@ template<class T> constexpr T set_bit(T value, uint8_t bit) { return value |= (1
28
27
  template<class T> constexpr T clear_bit(T value, uint8_t bit) { return value &= ~(1UL << bit); }
29
28
 
30
29
  template<class T> constexpr T write_bit(T value, uint8_t bit, uint8_t bit_value) {
31
- return bit_value ? setBit(value, bit) : clearBit(value, bit);
30
+ return bit_value ? set_bit(value, bit) : clear_bit(value, bit);
32
31
  }
33
32
 
34
33
  enum OperationMode {
@@ -100,6 +99,8 @@ enum MessageId {
100
99
  EXHAUST_TEMP = 33,
101
100
  FAN_SPEED = 35,
102
101
  FLAME_CURRENT = 36,
102
+ ROOM_TEMP_CH2 = 37,
103
+ REL_HUMIDITY = 38,
103
104
  DHW_BOUNDS = 48,
104
105
  CH_BOUNDS = 49,
105
106
  OTC_CURVE_BOUNDS = 50,
@@ -111,15 +112,46 @@ enum MessageId {
111
112
  HVAC_STATUS = 70,
112
113
  REL_VENT_SETPOINT = 71,
113
114
  DEVICE_VENT = 74,
115
+ HVAC_VER_ID = 75,
114
116
  REL_VENTILATION = 77,
115
117
  REL_HUMID_EXHAUST = 78,
118
+ EXHAUST_CO2 = 79,
116
119
  SUPPLY_INLET_TEMP = 80,
117
120
  SUPPLY_OUTLET_TEMP = 81,
118
121
  EXHAUST_INLET_TEMP = 82,
119
122
  EXHAUST_OUTLET_TEMP = 83,
123
+ EXHAUST_FAN_SPEED = 84,
124
+ SUPPLY_FAN_SPEED = 85,
125
+ REMOTE_VENTILATION_PARAM = 86,
120
126
  NOM_REL_VENTILATION = 87,
127
+ HVAC_NUM_TSP = 88,
128
+ HVAC_IDX_TSP = 89,
129
+ HVAC_FHB_SIZE = 90,
130
+ HVAC_FHB_IDX = 91,
121
131
 
132
+ RF_SIGNAL = 98,
133
+ DHW_MODE = 99,
122
134
  OVERRIDE_FUNC = 100,
135
+
136
+ // Solar Specific Message IDs
137
+ SOLAR_MODE_FLAGS = 101, // hb0-2 Controller storage mode
138
+ // lb0 Device fault
139
+ // lb1-3 Device mode status
140
+ // lb4-5 Device status
141
+ SOLAR_ASF = 102,
142
+ SOLAR_VERSION_ID = 103,
143
+ SOLAR_PRODUCT_ID = 104,
144
+ SOLAR_NUM_TSP = 105,
145
+ SOLAR_IDX_TSP = 106,
146
+ SOLAR_FHB_SIZE = 107,
147
+ SOLAR_FHB_IDX = 108,
148
+ SOLAR_STARTS = 109,
149
+ SOLAR_HOURS = 110,
150
+ SOLAR_ENERGY = 111,
151
+ SOLAR_TOTAL_ENERGY = 112,
152
+
153
+ FAILED_BURNER_STARTS = 113,
154
+ BURNER_FLAME_LOW = 114,
123
155
  OEM_DIAGNOSTIC = 115,
124
156
  BURNER_STARTS = 116,
125
157
  CH_PUMP_STARTS = 117,
@@ -0,0 +1,151 @@
1
+ #pragma once
2
+ namespace esphome {
3
+ namespace opentherm {
4
+
5
+ // ===== hub.h macros =====
6
+
7
+ // *_LIST macros will be generated in defines.h if at least one sensor from each platform is used.
8
+ // These lists will look like this:
9
+ // #define OPENTHERM_BINARY_SENSOR_LIST(F, sep) F(sensor_1) sep F(sensor_2)
10
+ // These lists will be used in hub.h to define sensor fields (passing macros like OPENTHERM_DECLARE_SENSOR as F)
11
+ // and setters (passing macros like OPENTHERM_SET_SENSOR as F) (see below)
12
+ // In order for things not to break, we define empty lists here in case some platforms are not used in config.
13
+ #ifndef OPENTHERM_SENSOR_LIST
14
+ #define OPENTHERM_SENSOR_LIST(F, sep)
15
+ #endif
16
+ #ifndef OPENTHERM_BINARY_SENSOR_LIST
17
+ #define OPENTHERM_BINARY_SENSOR_LIST(F, sep)
18
+ #endif
19
+ #ifndef OPENTHERM_SWITCH_LIST
20
+ #define OPENTHERM_SWITCH_LIST(F, sep)
21
+ #endif
22
+ #ifndef OPENTHERM_NUMBER_LIST
23
+ #define OPENTHERM_NUMBER_LIST(F, sep)
24
+ #endif
25
+ #ifndef OPENTHERM_OUTPUT_LIST
26
+ #define OPENTHERM_OUTPUT_LIST(F, sep)
27
+ #endif
28
+ #ifndef OPENTHERM_INPUT_SENSOR_LIST
29
+ #define OPENTHERM_INPUT_SENSOR_LIST(F, sep)
30
+ #endif
31
+
32
+ // Use macros to create fields for every entity specified in the ESPHome configuration
33
+ #define OPENTHERM_DECLARE_SENSOR(entity) sensor::Sensor *entity;
34
+ #define OPENTHERM_DECLARE_BINARY_SENSOR(entity) binary_sensor::BinarySensor *entity;
35
+ #define OPENTHERM_DECLARE_SWITCH(entity) OpenthermSwitch *entity;
36
+ #define OPENTHERM_DECLARE_NUMBER(entity) OpenthermNumber *entity;
37
+ #define OPENTHERM_DECLARE_OUTPUT(entity) OpenthermOutput *entity;
38
+ #define OPENTHERM_DECLARE_INPUT_SENSOR(entity) sensor::Sensor *entity;
39
+
40
+ // Setter macros
41
+ #define OPENTHERM_SET_SENSOR(entity) \
42
+ void set_##entity(sensor::Sensor *sensor) { this->entity = sensor; }
43
+
44
+ #define OPENTHERM_SET_BINARY_SENSOR(entity) \
45
+ void set_##entity(binary_sensor::BinarySensor *binary_sensor) { this->entity = binary_sensor; }
46
+
47
+ #define OPENTHERM_SET_SWITCH(entity) \
48
+ void set_##entity(OpenthermSwitch *sw) { this->entity = sw; }
49
+
50
+ #define OPENTHERM_SET_NUMBER(entity) \
51
+ void set_##entity(OpenthermNumber *number) { this->entity = number; }
52
+
53
+ #define OPENTHERM_SET_OUTPUT(entity) \
54
+ void set_##entity(OpenthermOutput *output) { this->entity = output; }
55
+
56
+ #define OPENTHERM_SET_INPUT_SENSOR(entity) \
57
+ void set_##entity(sensor::Sensor *sensor) { this->entity = sensor; }
58
+
59
+ // ===== hub.cpp macros =====
60
+
61
+ // *_MESSAGE_HANDLERS are generated in defines.h and look like this:
62
+ // OPENTHERM_NUMBER_MESSAGE_HANDLERS(MESSAGE, ENTITY, entity_sep, postscript, msg_sep) MESSAGE(COOLING_CONTROL)
63
+ // ENTITY(cooling_control_number, f88) postscript msg_sep They contain placeholders for message part and entities parts,
64
+ // since one message can contain multiple entities. MESSAGE part is substituted with OPENTHERM_MESSAGE_WRITE_MESSAGE,
65
+ // OPENTHERM_MESSAGE_READ_MESSAGE or OPENTHERM_MESSAGE_RESPONSE_MESSAGE. ENTITY part is substituted with
66
+ // OPENTHERM_MESSAGE_WRITE_ENTITY or OPENTHERM_MESSAGE_RESPONSE_ENTITY. OPENTHERM_IGNORE is used for sensor read
67
+ // requests since no data needs to be sent or processed, just the data id.
68
+
69
+ // In order for things not to break, we define empty lists here in case some platforms are not used in config.
70
+ #ifndef OPENTHERM_SENSOR_MESSAGE_HANDLERS
71
+ #define OPENTHERM_SENSOR_MESSAGE_HANDLERS(MESSAGE, ENTITY, entity_sep, postscript, msg_sep)
72
+ #endif
73
+ #ifndef OPENTHERM_BINARY_SENSOR_MESSAGE_HANDLERS
74
+ #define OPENTHERM_BINARY_SENSOR_MESSAGE_HANDLERS(MESSAGE, ENTITY, entity_sep, postscript, msg_sep)
75
+ #endif
76
+ #ifndef OPENTHERM_SWITCH_MESSAGE_HANDLERS
77
+ #define OPENTHERM_SWITCH_MESSAGE_HANDLERS(MESSAGE, ENTITY, entity_sep, postscript, msg_sep)
78
+ #endif
79
+ #ifndef OPENTHERM_NUMBER_MESSAGE_HANDLERS
80
+ #define OPENTHERM_NUMBER_MESSAGE_HANDLERS(MESSAGE, ENTITY, entity_sep, postscript, msg_sep)
81
+ #endif
82
+ #ifndef OPENTHERM_OUTPUT_MESSAGE_HANDLERS
83
+ #define OPENTHERM_OUTPUT_MESSAGE_HANDLERS(MESSAGE, ENTITY, entity_sep, postscript, msg_sep)
84
+ #endif
85
+ #ifndef OPENTHERM_INPUT_SENSOR_MESSAGE_HANDLERS
86
+ #define OPENTHERM_INPUT_SENSOR_MESSAGE_HANDLERS(MESSAGE, ENTITY, entity_sep, postscript, msg_sep)
87
+ #endif
88
+
89
+ // Write data request builders
90
+ #define OPENTHERM_MESSAGE_WRITE_MESSAGE(msg) \
91
+ case MessageId::msg: { \
92
+ data.type = MessageType::WRITE_DATA; \
93
+ data.id = request_id;
94
+ #define OPENTHERM_MESSAGE_WRITE_ENTITY(key, msg_data) message_data::write_##msg_data(this->key->state, data);
95
+ #define OPENTHERM_MESSAGE_WRITE_POSTSCRIPT \
96
+ return data; \
97
+ }
98
+
99
+ // Read data request builder
100
+ #define OPENTHERM_MESSAGE_READ_MESSAGE(msg) \
101
+ case MessageId::msg: \
102
+ data.type = MessageType::READ_DATA; \
103
+ data.id = request_id; \
104
+ return data;
105
+
106
+ // Data processing builders
107
+ #define OPENTHERM_MESSAGE_RESPONSE_MESSAGE(msg) case MessageId::msg:
108
+ #define OPENTHERM_MESSAGE_RESPONSE_ENTITY(key, msg_data) this->key->publish_state(message_data::parse_##msg_data(data));
109
+ #define OPENTHERM_MESSAGE_RESPONSE_POSTSCRIPT break;
110
+
111
+ #define OPENTHERM_IGNORE(x, y)
112
+
113
+ // Default macros for STATUS entities
114
+ #ifndef OPENTHERM_READ_ch_enable
115
+ #define OPENTHERM_READ_ch_enable true
116
+ #endif
117
+ #ifndef OPENTHERM_READ_dhw_enable
118
+ #define OPENTHERM_READ_dhw_enable true
119
+ #endif
120
+ #ifndef OPENTHERM_READ_t_set
121
+ #define OPENTHERM_READ_t_set 0.0
122
+ #endif
123
+ #ifndef OPENTHERM_READ_cooling_enable
124
+ #define OPENTHERM_READ_cooling_enable false
125
+ #endif
126
+ #ifndef OPENTHERM_READ_cooling_control
127
+ #define OPENTHERM_READ_cooling_control 0.0
128
+ #endif
129
+ #ifndef OPENTHERM_READ_otc_active
130
+ #define OPENTHERM_READ_otc_active false
131
+ #endif
132
+ #ifndef OPENTHERM_READ_ch2_active
133
+ #define OPENTHERM_READ_ch2_active false
134
+ #endif
135
+ #ifndef OPENTHERM_READ_t_set_ch2
136
+ #define OPENTHERM_READ_t_set_ch2 0.0
137
+ #endif
138
+ #ifndef OPENTHERM_READ_summer_mode_active
139
+ #define OPENTHERM_READ_summer_mode_active false
140
+ #endif
141
+ #ifndef OPENTHERM_READ_dhw_block
142
+ #define OPENTHERM_READ_dhw_block false
143
+ #endif
144
+
145
+ // These macros utilize the structure of *_LIST macros in order
146
+ #define ID(x) x
147
+ #define SHOW_INNER(x) #x
148
+ #define SHOW(x) SHOW_INNER(x)
149
+
150
+ } // namespace opentherm
151
+ } // namespace esphome
@@ -0,0 +1,47 @@
1
+ from typing import Any
2
+
3
+ import esphome.codegen as cg
4
+ import esphome.config_validation as cv
5
+ from esphome.components import output
6
+ from esphome.const import CONF_ID
7
+ from .. import const, schema, validate, input, generate
8
+
9
+ DEPENDENCIES = [const.OPENTHERM]
10
+ COMPONENT_TYPE = const.OUTPUT
11
+
12
+ OpenthermOutput = generate.opentherm_ns.class_(
13
+ "OpenthermOutput", output.FloatOutput, cg.Component, input.OpenthermInput
14
+ )
15
+
16
+
17
+ async def new_openthermoutput(
18
+ config: dict[str, Any], key: str, _hub: cg.MockObj
19
+ ) -> cg.Pvariable:
20
+ var = cg.new_Pvariable(config[CONF_ID])
21
+ await cg.register_component(var, config)
22
+ await output.register_output(var, config)
23
+ cg.add(getattr(var, "set_id")(cg.RawExpression(f'"{key}_{config[CONF_ID]}"')))
24
+ input.generate_setters(var, config)
25
+ return var
26
+
27
+
28
+ def get_entity_validation_schema(entity: schema.InputSchema) -> cv.Schema:
29
+ return (
30
+ output.FLOAT_OUTPUT_SCHEMA.extend(
31
+ {cv.GenerateID(): cv.declare_id(OpenthermOutput)}
32
+ )
33
+ .extend(input.input_schema(entity))
34
+ .extend(cv.COMPONENT_SCHEMA)
35
+ )
36
+
37
+
38
+ CONFIG_SCHEMA = validate.create_component_schema(
39
+ schema.INPUTS, get_entity_validation_schema
40
+ )
41
+
42
+
43
+ async def to_code(config: dict[str, Any]) -> None:
44
+ keys = await generate.component_to_code(
45
+ COMPONENT_TYPE, schema.INPUTS, OpenthermOutput, new_openthermoutput, config
46
+ )
47
+ generate.define_readers(COMPONENT_TYPE, keys)
@@ -0,0 +1,18 @@
1
+ #include "esphome/core/helpers.h" // for clamp() and lerp()
2
+ #include "output.h"
3
+
4
+ namespace esphome {
5
+ namespace opentherm {
6
+
7
+ static const char *const TAG = "opentherm.output";
8
+
9
+ void opentherm::OpenthermOutput::write_state(float state) {
10
+ ESP_LOGD(TAG, "Received state: %.2f. Min value: %.2f, max value: %.2f", state, min_value_, max_value_);
11
+ this->state = state < 0.003 && this->zero_means_zero_
12
+ ? 0.0
13
+ : clamp(lerp(state, min_value_, max_value_), min_value_, max_value_);
14
+ this->has_state_ = true;
15
+ ESP_LOGD(TAG, "Output %s set to %.2f", this->id_, this->state);
16
+ }
17
+ } // namespace opentherm
18
+ } // namespace esphome
@@ -0,0 +1,33 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/output/float_output.h"
4
+ #include "esphome/components/opentherm/input.h"
5
+ #include "esphome/core/log.h"
6
+
7
+ namespace esphome {
8
+ namespace opentherm {
9
+
10
+ class OpenthermOutput : public output::FloatOutput, public Component, public OpenthermInput {
11
+ protected:
12
+ bool has_state_ = false;
13
+ const char *id_ = nullptr;
14
+
15
+ float min_value_, max_value_;
16
+
17
+ public:
18
+ float state;
19
+
20
+ void set_id(const char *id) { this->id_ = id; }
21
+
22
+ void write_state(float state) override;
23
+
24
+ bool has_state() { return this->has_state_; };
25
+
26
+ void set_min_value(float min_value) override { this->min_value_ = min_value; }
27
+ void set_max_value(float max_value) override { this->max_value_ = max_value; }
28
+ float get_min_value() { return this->min_value_; }
29
+ float get_max_value() { return this->max_value_; }
30
+ };
31
+
32
+ } // namespace opentherm
33
+ } // namespace esphome