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
@@ -0,0 +1,72 @@
1
+ from esphome import pins
2
+ import esphome.codegen as cg
3
+ from esphome.components import i2c
4
+ import esphome.config_validation as cv
5
+ from esphome.const import (
6
+ CONF_ID,
7
+ CONF_INPUT,
8
+ CONF_INVERTED,
9
+ CONF_MODE,
10
+ CONF_NUMBER,
11
+ CONF_OUTPUT,
12
+ )
13
+
14
+ CODEOWNERS = ["@mobrembski"]
15
+
16
+ AUTO_LOAD = ["gpio_expander"]
17
+ DEPENDENCIES = ["i2c"]
18
+ MULTI_CONF = True
19
+
20
+ tca9555_ns = cg.esphome_ns.namespace("tca9555")
21
+
22
+ TCA9555Component = tca9555_ns.class_("TCA9555Component", cg.Component, i2c.I2CDevice)
23
+ TCA9555GPIOPin = tca9555_ns.class_("TCA9555GPIOPin", cg.GPIOPin)
24
+
25
+ CONF_TCA9555 = "tca9555"
26
+ CONFIG_SCHEMA = (
27
+ cv.Schema(
28
+ {
29
+ cv.Required(CONF_ID): cv.declare_id(TCA9555Component),
30
+ }
31
+ )
32
+ .extend(cv.COMPONENT_SCHEMA)
33
+ .extend(i2c.i2c_device_schema(0x21))
34
+ )
35
+
36
+
37
+ async def to_code(config):
38
+ var = cg.new_Pvariable(config[CONF_ID])
39
+ await cg.register_component(var, config)
40
+ await i2c.register_i2c_device(var, config)
41
+
42
+
43
+ def validate_mode(value):
44
+ if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
45
+ raise cv.Invalid("Mode must be either input or output")
46
+ if value[CONF_INPUT] and value[CONF_OUTPUT]:
47
+ raise cv.Invalid("Mode must be either input or output")
48
+ return value
49
+
50
+
51
+ TCA9555_PIN_SCHEMA = pins.gpio_base_schema(
52
+ TCA9555GPIOPin,
53
+ cv.int_range(min=0, max=15),
54
+ modes=[CONF_INPUT, CONF_OUTPUT],
55
+ mode_validator=validate_mode,
56
+ invertable=True,
57
+ ).extend(
58
+ {
59
+ cv.Required(CONF_TCA9555): cv.use_id(TCA9555Component),
60
+ }
61
+ )
62
+
63
+
64
+ @pins.PIN_SCHEMA_REGISTRY.register(CONF_TCA9555, TCA9555_PIN_SCHEMA)
65
+ async def tca9555_pin_to_code(config):
66
+ var = cg.new_Pvariable(config[CONF_ID])
67
+ await cg.register_parented(var, config[CONF_TCA9555])
68
+
69
+ cg.add(var.set_pin(config[CONF_NUMBER]))
70
+ cg.add(var.set_inverted(config[CONF_INVERTED]))
71
+ cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
72
+ return var
@@ -0,0 +1,140 @@
1
+ #include "tca9555.h"
2
+ #include "esphome/core/log.h"
3
+
4
+ static const uint8_t TCA9555_INPUT_PORT_REGISTER_0 = 0x00;
5
+ static const uint8_t TCA9555_INPUT_PORT_REGISTER_1 = 0x01;
6
+ static const uint8_t TCA9555_OUTPUT_PORT_REGISTER_0 = 0x02;
7
+ static const uint8_t TCA9555_OUTPUT_PORT_REGISTER_1 = 0x03;
8
+ static const uint8_t TCA9555_POLARITY_REGISTER_0 = 0x04;
9
+ static const uint8_t TCA9555_POLARITY_REGISTER_1 = 0x05;
10
+ static const uint8_t TCA9555_CONFIGURATION_PORT_0 = 0x06;
11
+ static const uint8_t TCA9555_CONFIGURATION_PORT_1 = 0x07;
12
+
13
+ namespace esphome {
14
+ namespace tca9555 {
15
+
16
+ static const char *const TAG = "tca9555";
17
+
18
+ void TCA9555Component::setup() {
19
+ ESP_LOGCONFIG(TAG, "Setting up TCA9555...");
20
+ if (!this->read_gpio_modes_()) {
21
+ this->mark_failed();
22
+ return;
23
+ }
24
+ if (!this->read_gpio_outputs_()) {
25
+ this->mark_failed();
26
+ return;
27
+ }
28
+ }
29
+ void TCA9555Component::dump_config() {
30
+ ESP_LOGCONFIG(TAG, "TCA9555:");
31
+ LOG_I2C_DEVICE(this)
32
+ if (this->is_failed()) {
33
+ ESP_LOGE(TAG, "Communication with TCA9555 failed!");
34
+ }
35
+ }
36
+ void TCA9555Component::pin_mode(uint8_t pin, gpio::Flags flags) {
37
+ if (flags == gpio::FLAG_INPUT) {
38
+ // Set mode mask bit
39
+ this->mode_mask_ |= 1 << pin;
40
+ } else if (flags == gpio::FLAG_OUTPUT) {
41
+ // Clear mode mask bit
42
+ this->mode_mask_ &= ~(1 << pin);
43
+ }
44
+ // Write GPIO to enable input mode
45
+ this->write_gpio_modes_();
46
+ }
47
+ void TCA9555Component::loop() { this->reset_pin_cache_(); }
48
+
49
+ bool TCA9555Component::read_gpio_outputs_() {
50
+ if (this->is_failed())
51
+ return false;
52
+ uint8_t data[2];
53
+ if (!this->read_bytes(TCA9555_OUTPUT_PORT_REGISTER_0, data, 2)) {
54
+ this->status_set_warning("Failed to read output register");
55
+ return false;
56
+ }
57
+ this->output_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0);
58
+ this->status_clear_warning();
59
+ return true;
60
+ }
61
+
62
+ bool TCA9555Component::read_gpio_modes_() {
63
+ if (this->is_failed())
64
+ return false;
65
+ uint8_t data[2];
66
+ bool success = this->read_bytes(TCA9555_CONFIGURATION_PORT_0, data, 2);
67
+ if (!success) {
68
+ this->status_set_warning("Failed to read mode register");
69
+ return false;
70
+ }
71
+ this->mode_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0);
72
+
73
+ this->status_clear_warning();
74
+ return true;
75
+ }
76
+ bool TCA9555Component::digital_read_hw(uint8_t pin) {
77
+ if (this->is_failed())
78
+ return false;
79
+ bool success;
80
+ uint8_t data[2];
81
+ success = this->read_bytes(TCA9555_INPUT_PORT_REGISTER_0, data, 2);
82
+ this->input_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0);
83
+
84
+ if (!success) {
85
+ this->status_set_warning("Failed to read input register");
86
+ return false;
87
+ }
88
+
89
+ this->status_clear_warning();
90
+ return true;
91
+ }
92
+
93
+ void TCA9555Component::digital_write_hw(uint8_t pin, bool value) {
94
+ if (this->is_failed())
95
+ return;
96
+
97
+ if (value) {
98
+ this->output_mask_ |= (1 << pin);
99
+ } else {
100
+ this->output_mask_ &= ~(1 << pin);
101
+ }
102
+
103
+ uint8_t data[2];
104
+ data[0] = this->output_mask_;
105
+ data[1] = this->output_mask_ >> 8;
106
+ if (!this->write_bytes(TCA9555_OUTPUT_PORT_REGISTER_0, data, 2)) {
107
+ this->status_set_warning("Failed to write output register");
108
+ return;
109
+ }
110
+
111
+ this->status_clear_warning();
112
+ }
113
+
114
+ bool TCA9555Component::write_gpio_modes_() {
115
+ if (this->is_failed())
116
+ return false;
117
+ uint8_t data[2];
118
+
119
+ data[0] = this->mode_mask_;
120
+ data[1] = this->mode_mask_ >> 8;
121
+ if (!this->write_bytes(TCA9555_CONFIGURATION_PORT_0, data, 2)) {
122
+ this->status_set_warning("Failed to write mode register");
123
+ return false;
124
+ }
125
+ this->status_clear_warning();
126
+ return true;
127
+ }
128
+
129
+ bool TCA9555Component::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); }
130
+
131
+ float TCA9555Component::get_setup_priority() const { return setup_priority::IO; }
132
+
133
+ void TCA9555GPIOPin::setup() { this->pin_mode(this->flags_); }
134
+ void TCA9555GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
135
+ bool TCA9555GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
136
+ void TCA9555GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
137
+ std::string TCA9555GPIOPin::dump_summary() const { return str_sprintf("%u via TCA9555", this->pin_); }
138
+
139
+ } // namespace tca9555
140
+ } // namespace esphome
@@ -0,0 +1,64 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/gpio_expander/cached_gpio.h"
4
+ #include "esphome/components/i2c/i2c.h"
5
+ #include "esphome/core/component.h"
6
+ #include "esphome/core/hal.h"
7
+
8
+ namespace esphome {
9
+ namespace tca9555 {
10
+
11
+ class TCA9555Component : public Component,
12
+ public i2c::I2CDevice,
13
+ public gpio_expander::CachedGpioExpander<uint8_t, 16> {
14
+ public:
15
+ TCA9555Component() = default;
16
+
17
+ /// Check i2c availability and setup masks
18
+ void setup() override;
19
+ void pin_mode(uint8_t pin, gpio::Flags flags);
20
+
21
+ float get_setup_priority() const override;
22
+
23
+ void dump_config() override;
24
+
25
+ void loop() override;
26
+
27
+ protected:
28
+ bool digital_read_hw(uint8_t pin) override;
29
+ bool digital_read_cache(uint8_t pin) override;
30
+ void digital_write_hw(uint8_t pin, bool value) override;
31
+
32
+ /// Mask for the pin mode - 1 means output, 0 means input
33
+ uint16_t mode_mask_{0x00};
34
+ /// The mask to write as output state - 1 means HIGH, 0 means LOW
35
+ uint16_t output_mask_{0x00};
36
+ /// The state read in digital_read_hw - 1 means HIGH, 0 means LOW
37
+ uint16_t input_mask_{0x00};
38
+
39
+ bool read_gpio_modes_();
40
+ bool write_gpio_modes_();
41
+ bool read_gpio_outputs_();
42
+ };
43
+
44
+ /// Helper class to expose a TCA9555 pin as an internal input GPIO pin.
45
+ class TCA9555GPIOPin : public GPIOPin, public Parented<TCA9555Component> {
46
+ public:
47
+ void setup() override;
48
+ void pin_mode(gpio::Flags flags) override;
49
+ bool digital_read() override;
50
+ void digital_write(bool value) override;
51
+ std::string dump_summary() const override;
52
+
53
+ void set_pin(uint8_t pin) { this->pin_ = pin; }
54
+ void set_inverted(bool inverted) { this->inverted_ = inverted; }
55
+ void set_flags(gpio::Flags flags) { this->flags_ = flags; }
56
+
57
+ protected:
58
+ uint8_t pin_;
59
+ bool inverted_;
60
+ gpio::Flags flags_;
61
+ };
62
+
63
+ } // namespace tca9555
64
+ } // namespace esphome
@@ -1,6 +1,8 @@
1
1
  #include "tcs34725.h"
2
2
  #include "esphome/core/log.h"
3
3
  #include "esphome/core/hal.h"
4
+ #include <algorithm>
5
+ #include "esphome/core/helpers.h"
4
6
 
5
7
  namespace esphome {
6
8
  namespace tcs34725 {
@@ -13,10 +15,7 @@ static const uint8_t TCS34725_REGISTER_ID = TCS34725_COMMAND_BIT | 0x12;
13
15
  static const uint8_t TCS34725_REGISTER_ATIME = TCS34725_COMMAND_BIT | 0x01;
14
16
  static const uint8_t TCS34725_REGISTER_CONTROL = TCS34725_COMMAND_BIT | 0x0F;
15
17
  static const uint8_t TCS34725_REGISTER_ENABLE = TCS34725_COMMAND_BIT | 0x00;
16
- static const uint8_t TCS34725_REGISTER_CDATAL = TCS34725_COMMAND_BIT | 0x14;
17
- static const uint8_t TCS34725_REGISTER_RDATAL = TCS34725_COMMAND_BIT | 0x16;
18
- static const uint8_t TCS34725_REGISTER_GDATAL = TCS34725_COMMAND_BIT | 0x18;
19
- static const uint8_t TCS34725_REGISTER_BDATAL = TCS34725_COMMAND_BIT | 0x1A;
18
+ static const uint8_t TCS34725_REGISTER_CRGBDATAL = TCS34725_COMMAND_BIT | 0x14;
20
19
 
21
20
  void TCS34725Component::setup() {
22
21
  ESP_LOGCONFIG(TAG, "Setting up TCS34725...");
@@ -74,20 +73,21 @@ float TCS34725Component::get_setup_priority() const { return setup_priority::DAT
74
73
  * @return Color temperature in degrees Kelvin
75
74
  */
76
75
  void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, uint16_t b, uint16_t c) {
77
- float r2, g2, b2; /* RGB values minus IR component */
78
- float sat; /* Digital saturation level */
79
- float ir; /* Inferred IR content */
80
-
81
- this->illuminance_ = 0; // Assign 0 value before calculation
82
- this->color_temperature_ = 0;
83
-
84
- const float ga = this->glass_attenuation_; // Glass Attenuation Factor
85
- static const float DF = 310.f; // Device Factor
86
- static const float R_COEF = 0.136f; //
87
- static const float G_COEF = 1.f; // used in lux computation
88
- static const float B_COEF = -0.444f; //
89
- static const float CT_COEF = 3810.f; // Color Temperature Coefficient
90
- static const float CT_OFFSET = 1391.f; // Color Temperatuer Offset
76
+ float sat; /* Digital saturation level */
77
+
78
+ this->illuminance_ = NAN;
79
+ this->color_temperature_ = NAN;
80
+
81
+ const float ga = this->glass_attenuation_; // Glass Attenuation Factor
82
+ static const float DF = 310.f; // Device Factor
83
+ static const float R_COEF = 0.136f; //
84
+ static const float G_COEF = 1.f; // used in lux computation
85
+ static const float B_COEF = -0.444f; //
86
+ static const float CT_COEF = 3810.f; // Color Temperature Coefficient
87
+ static const float CT_OFFSET = 1391.f; // Color Temperatuer Offset
88
+ static const float MAX_ILLUMINANCE = 100000.0f; // Cap illuminance at 100,000 lux
89
+ static const float MAX_COLOR_TEMPERATURE = 15000.0f; // Maximum expected color temperature in Kelvin
90
+ static const float MIN_COLOR_TEMPERATURE = 1000.0f; // Maximum reasonable color temperature in Kelvin
91
91
 
92
92
  if (c == 0) {
93
93
  return;
@@ -138,69 +138,66 @@ void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, u
138
138
  if (c >= sat) {
139
139
  if (this->integration_time_auto_) {
140
140
  ESP_LOGI(TAG, "Saturation too high, sample discarded, autogain ongoing");
141
+ return;
141
142
  } else {
142
- ESP_LOGW(
143
- TAG,
144
- "Saturation too high, sample with saturation %.1f and clear %d treat values carefully or use grey filter",
145
- sat, c);
146
- }
147
- }
148
-
149
- /* AMS RGB sensors have no IR channel, so the IR content must be */
150
- /* calculated indirectly. */
151
- ir = ((r + g + b) > c) ? (r + g + b - c) / 2 : 0;
152
-
153
- /* Remove the IR component from the raw RGB values */
154
- r2 = r - ir;
155
- g2 = g - ir;
156
- b2 = b - ir;
157
-
158
- // discarding super low values? not recemmonded, and avoided by using auto gain.
159
- if (r2 == 0) {
160
- // legacy code
161
- if (!this->integration_time_auto_) {
162
143
  ESP_LOGW(TAG,
163
- "No light detected on red channel, switch to auto gain or adjust timing, values will be unreliable");
144
+ "Saturation too high, sample with saturation %.1f and clear %d lux/color temperature cannot reliably "
145
+ "calculated, reduce integration/gain or use a grey filter.",
146
+ sat, c);
164
147
  return;
165
148
  }
166
149
  }
167
150
 
168
151
  // Lux Calculation (DN40 3.2)
169
152
 
170
- float g1 = R_COEF * r2 + G_COEF * g2 + B_COEF * b2;
153
+ float g1 = R_COEF * (float) r + G_COEF * (float) g + B_COEF * (float) b;
171
154
  float cpl = (this->integration_time_ * this->gain_) / (ga * DF);
172
- this->illuminance_ = g1 / cpl;
173
155
 
174
- // Color Temperature Calculation (DN40)
175
- /* A simple method of measuring color temp is to use the ratio of blue */
176
- /* to red light, taking IR cancellation into account. */
177
- this->color_temperature_ = (CT_COEF * b2) / /** Color temp coefficient. */
178
- r2 +
179
- CT_OFFSET; /** Color temp offset. */
180
- }
156
+ this->illuminance_ = std::max(g1 / cpl, 0.0f);
181
157
 
182
- void TCS34725Component::update() {
183
- uint16_t raw_c;
184
- uint16_t raw_r;
185
- uint16_t raw_g;
186
- uint16_t raw_b;
187
-
188
- if (this->read_data_register_(TCS34725_REGISTER_CDATAL, raw_c) != i2c::ERROR_OK) {
189
- this->status_set_warning();
158
+ if (this->illuminance_ > MAX_ILLUMINANCE) {
159
+ ESP_LOGW(TAG, "Calculated illuminance greater than limit (%f), setting to NAN", this->illuminance_);
160
+ this->illuminance_ = NAN;
190
161
  return;
191
162
  }
192
- if (this->read_data_register_(TCS34725_REGISTER_RDATAL, raw_r) != i2c::ERROR_OK) {
193
- this->status_set_warning();
163
+
164
+ if (r == 0) {
165
+ ESP_LOGW(TAG, "Red channel is zero, cannot compute color temperature");
194
166
  return;
195
167
  }
196
- if (this->read_data_register_(TCS34725_REGISTER_GDATAL, raw_g) != i2c::ERROR_OK) {
197
- this->status_set_warning();
198
- return;
168
+
169
+ // Color Temperature Calculation (DN40)
170
+ /* A simple method of measuring color temp is to use the ratio of blue */
171
+ /* to red light. */
172
+
173
+ this->color_temperature_ = (CT_COEF * (float) b) / (float) r + CT_OFFSET;
174
+
175
+ // Ensure the color temperature stays within reasonable bounds
176
+ if (this->color_temperature_ < MIN_COLOR_TEMPERATURE) {
177
+ ESP_LOGW(TAG, "Calculated color temperature value too low (%f), setting to NAN", this->color_temperature_);
178
+ this->color_temperature_ = NAN;
179
+ } else if (this->color_temperature_ > MAX_COLOR_TEMPERATURE) {
180
+ ESP_LOGW(TAG, "Calculated color temperature value too high (%f), setting to NAN", this->color_temperature_);
181
+ this->color_temperature_ = NAN;
199
182
  }
200
- if (this->read_data_register_(TCS34725_REGISTER_BDATAL, raw_b) != i2c::ERROR_OK) {
183
+ }
184
+
185
+ void TCS34725Component::update() {
186
+ uint8_t data[8]; // Buffer to hold the 8 bytes (2 bytes for each of the 4 channels)
187
+
188
+ // Perform burst
189
+ if (this->read_register(TCS34725_REGISTER_CRGBDATAL, data, 8) != i2c::ERROR_OK) {
201
190
  this->status_set_warning();
191
+ ESP_LOGW(TAG, "Error reading TCS34725 sensor data");
202
192
  return;
203
193
  }
194
+
195
+ // Extract the data
196
+ uint16_t raw_c = encode_uint16(data[1], data[0]); // Clear channel
197
+ uint16_t raw_r = encode_uint16(data[3], data[2]); // Red channel
198
+ uint16_t raw_g = encode_uint16(data[5], data[4]); // Green channel
199
+ uint16_t raw_b = encode_uint16(data[7], data[6]); // Blue channel
200
+
204
201
  ESP_LOGV(TAG, "Raw values clear=%d red=%d green=%d blue=%d", raw_c, raw_r, raw_g, raw_b);
205
202
 
206
203
  float channel_c;
@@ -211,7 +208,7 @@ void TCS34725Component::update() {
211
208
  if (raw_c == 0) {
212
209
  channel_c = channel_r = channel_g = channel_b = 0.0f;
213
210
  } else {
214
- float max_count = this->integration_time_ * 1024.0f / 2.4;
211
+ float max_count = this->integration_time_ <= 153.6f ? this->integration_time_ * 1024.0f / 2.4f : 65535.0f;
215
212
  float sum = raw_c;
216
213
  channel_r = raw_r / sum * 100.0f;
217
214
  channel_g = raw_g / sum * 100.0f;
@@ -254,7 +251,8 @@ void TCS34725Component::update() {
254
251
  // change integration time an gain to achieve maximum resolution an dynamic range
255
252
  // calculate optimal integration time to achieve 70% satuaration
256
253
  float integration_time_ideal;
257
- integration_time_ideal = 60 / ((float) raw_c / 655.35) * this->integration_time_;
254
+
255
+ integration_time_ideal = 60 / ((float) std::max((uint16_t) 1, raw_c) / 655.35f) * this->integration_time_;
258
256
 
259
257
  uint8_t gain_reg_val_new = this->gain_reg_;
260
258
  // increase gain if less than 20% of white channel used and high integration time
File without changes
@@ -0,0 +1,55 @@
1
+ import esphome.codegen as cg
2
+ import esphome.config_validation as cv
3
+ from esphome.components import i2c, sensor
4
+
5
+ from esphome.const import (
6
+ CONF_ID,
7
+ CONF_TEMPERATURE,
8
+ DEVICE_CLASS_TEMPERATURE,
9
+ STATE_CLASS_MEASUREMENT,
10
+ UNIT_CELSIUS,
11
+ )
12
+
13
+ CODEOWNERS = ["@bakerkj"]
14
+ DEPENDENCIES = ["i2c"]
15
+
16
+ tem3200_ns = cg.esphome_ns.namespace("tem3200")
17
+
18
+ TEM3200Component = tem3200_ns.class_(
19
+ "TEM3200Component", cg.PollingComponent, i2c.I2CDevice
20
+ )
21
+
22
+ CONF_RAW_PRESSURE = "raw_pressure"
23
+
24
+ CONFIG_SCHEMA = (
25
+ cv.Schema(
26
+ {
27
+ cv.GenerateID(): cv.declare_id(TEM3200Component),
28
+ cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
29
+ unit_of_measurement=UNIT_CELSIUS,
30
+ accuracy_decimals=1,
31
+ device_class=DEVICE_CLASS_TEMPERATURE,
32
+ state_class=STATE_CLASS_MEASUREMENT,
33
+ ),
34
+ cv.Optional(CONF_RAW_PRESSURE): sensor.sensor_schema(
35
+ accuracy_decimals=0, state_class=STATE_CLASS_MEASUREMENT
36
+ ),
37
+ }
38
+ )
39
+ .extend(cv.polling_component_schema("60s"))
40
+ .extend(i2c.i2c_device_schema(0x28))
41
+ )
42
+
43
+
44
+ async def to_code(config):
45
+ var = cg.new_Pvariable(config[CONF_ID])
46
+ await cg.register_component(var, config)
47
+ await i2c.register_i2c_device(var, config)
48
+
49
+ if temperature_config := config.get(CONF_TEMPERATURE):
50
+ sens = await sensor.new_sensor(temperature_config)
51
+ cg.add(var.set_temperature_sensor(sens))
52
+
53
+ if raw_pressure_config := config.get(CONF_RAW_PRESSURE):
54
+ sens = await sensor.new_sensor(raw_pressure_config)
55
+ cg.add(var.set_raw_pressure_sensor(sens))
@@ -0,0 +1,151 @@
1
+ #include "tem3200.h"
2
+ #include "esphome/core/log.h"
3
+ #include "esphome/core/helpers.h"
4
+ #include "esphome/core/hal.h"
5
+
6
+ namespace esphome {
7
+ namespace tem3200 {
8
+
9
+ static const char *const TAG = "tem3200";
10
+
11
+ enum ErrorCode {
12
+ NONE = 0,
13
+ RESERVED = 1,
14
+ STALE = 2,
15
+ FAULT = 3,
16
+ };
17
+
18
+ void TEM3200Component::setup() {
19
+ ESP_LOGCONFIG(TAG, "Setting up TEM3200...");
20
+
21
+ uint8_t status(NONE);
22
+ uint16_t raw_temperature(0);
23
+ uint16_t raw_pressure(0);
24
+
25
+ i2c::ErrorCode err = this->read_(status, raw_temperature, raw_pressure);
26
+ if (err != i2c::ERROR_OK) {
27
+ ESP_LOGCONFIG(TAG, " I2C Communication Failed...");
28
+ this->mark_failed();
29
+ return;
30
+ }
31
+
32
+ switch (status) {
33
+ case RESERVED:
34
+ ESP_LOGE(TAG, "Invalid RESERVED Device Status");
35
+ this->mark_failed();
36
+ return;
37
+ case FAULT:
38
+ ESP_LOGE(TAG, "FAULT condition in the SSC or sensing element");
39
+ this->mark_failed();
40
+ return;
41
+ case STALE:
42
+ ESP_LOGE(TAG, "STALE data. Data has not been updated since last fetch");
43
+ this->status_set_warning();
44
+ break;
45
+ }
46
+ ESP_LOGCONFIG(TAG, " Success...");
47
+ }
48
+
49
+ void TEM3200Component::dump_config() {
50
+ ESP_LOGCONFIG(TAG, "TEM3200:");
51
+ LOG_I2C_DEVICE(this);
52
+ LOG_UPDATE_INTERVAL(this);
53
+ LOG_SENSOR(" ", "Raw Pressure", this->raw_pressure_sensor_);
54
+ LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
55
+ }
56
+
57
+ float TEM3200Component::get_setup_priority() const { return setup_priority::DATA; }
58
+
59
+ i2c::ErrorCode TEM3200Component::read_(uint8_t &status, uint16_t &raw_temperature, uint16_t &raw_pressure) {
60
+ uint8_t response[4] = {0x00, 0x00, 0x00, 0x00};
61
+
62
+ // initiate data read
63
+ i2c::ErrorCode err = this->read(response, 4);
64
+ if (err != i2c::ERROR_OK) {
65
+ return err;
66
+ }
67
+
68
+ // extract top 2 bits of first byte for status
69
+ status = (ErrorCode) (response[0] & 0xc0) >> 6;
70
+ if (status == RESERVED || status == FAULT) {
71
+ return i2c::ERROR_OK;
72
+ }
73
+
74
+ // if data is stale; reread
75
+ if (status == STALE) {
76
+ // wait for measurement 2ms
77
+ delay(2);
78
+
79
+ err = this->read(response, 4);
80
+ if (err != i2c::ERROR_OK) {
81
+ return err;
82
+ }
83
+ }
84
+
85
+ // extract top 2 bits of first byte for status
86
+ status = (ErrorCode) (response[0] & 0xc0) >> 6;
87
+ if (status == RESERVED || status == FAULT) {
88
+ return i2c::ERROR_OK;
89
+ }
90
+
91
+ // extract top 6 bits of first byte and all bits of second byte for pressure
92
+ raw_pressure = (((response[0] & 0x3f)) << 8 | response[1]);
93
+
94
+ // extract all bytes of 3rd byte and top 3 bits of fourth byte for temperature
95
+ raw_temperature = ((response[2] << 3) | (response[3] & 0xe0) >> 5);
96
+
97
+ return i2c::ERROR_OK;
98
+ }
99
+
100
+ inline float convert_temperature(uint16_t raw_temperature) {
101
+ const float temperature_bits_span = 2048;
102
+ const float temperature_max = 150;
103
+ const float temperature_min = -50;
104
+ const float temperature_span = temperature_max - temperature_min;
105
+
106
+ float temperature = (raw_temperature * temperature_span / temperature_bits_span) + temperature_min;
107
+
108
+ return temperature;
109
+ }
110
+
111
+ void TEM3200Component::update() {
112
+ uint8_t status(NONE);
113
+ uint16_t raw_temperature(0);
114
+ uint16_t raw_pressure(0);
115
+ i2c::ErrorCode err = this->read_(status, raw_temperature, raw_pressure);
116
+
117
+ if (err != i2c::ERROR_OK) {
118
+ ESP_LOGW(TAG, "I2C Communication Failed");
119
+ this->status_set_warning();
120
+ return;
121
+ }
122
+
123
+ switch (status) {
124
+ case RESERVED:
125
+ ESP_LOGE(TAG, "Failed: Device return RESERVED status");
126
+ this->status_set_warning();
127
+ return;
128
+ case FAULT:
129
+ ESP_LOGE(TAG, "Failed: FAULT condition in the SSC or sensing element");
130
+ this->mark_failed();
131
+ return;
132
+ case STALE:
133
+ ESP_LOGE(TAG, "Warning: STALE data. Data has not been updated since last fetch");
134
+ this->status_set_warning();
135
+ return;
136
+ }
137
+
138
+ float temperature = convert_temperature(raw_temperature);
139
+
140
+ ESP_LOGD(TAG, "Got raw pressure=%d, temperature=%.1f°C", raw_pressure, temperature);
141
+
142
+ if (this->temperature_sensor_ != nullptr)
143
+ this->temperature_sensor_->publish_state(temperature);
144
+ if (this->raw_pressure_sensor_ != nullptr)
145
+ this->raw_pressure_sensor_->publish_state(raw_pressure);
146
+
147
+ this->status_clear_warning();
148
+ }
149
+
150
+ } // namespace tem3200
151
+ } // namespace esphome