esphome 2024.9.2__py3-none-any.whl → 2024.10.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.
- esphome/components/aic3204/__init__.py +0 -0
- esphome/components/aic3204/aic3204.cpp +173 -0
- esphome/components/aic3204/aic3204.h +88 -0
- esphome/components/aic3204/audio_dac.py +52 -0
- esphome/components/aic3204/automation.h +23 -0
- esphome/components/alarm_control_panel/__init__.py +3 -4
- esphome/components/animation/__init__.py +16 -12
- esphome/components/api/api_connection.cpp +2 -0
- esphome/components/api/api_connection.h +3 -1
- esphome/components/api/api_frame_helper.cpp +2 -1
- esphome/components/api/api_frame_helper.h +2 -1
- esphome/components/api/api_server.cpp +2 -0
- esphome/components/api/api_server.h +3 -1
- esphome/components/api/custom_api_device.h +3 -2
- esphome/components/api/homeassistant_service.h +4 -3
- esphome/components/api/list_entities.cpp +2 -0
- esphome/components/api/list_entities.h +3 -2
- esphome/components/api/subscribe_state.cpp +2 -0
- esphome/components/api/subscribe_state.h +3 -2
- esphome/components/audio_dac/__init__.py +57 -0
- esphome/components/audio_dac/audio_dac.h +23 -0
- esphome/components/audio_dac/automation.h +43 -0
- esphome/components/bang_bang/bang_bang_climate.cpp +5 -2
- esphome/components/bedjet/bedjet_codec.cpp +4 -2
- esphome/components/binary_sensor/__init__.py +3 -4
- esphome/components/button/__init__.py +3 -4
- esphome/components/ch422g/__init__.py +26 -17
- esphome/components/ch422g/ch422g.cpp +66 -49
- esphome/components/ch422g/ch422g.h +17 -19
- esphome/components/climate/__init__.py +3 -4
- esphome/components/cover/__init__.py +4 -5
- esphome/components/cse7766/cse7766.cpp +12 -1
- esphome/components/cse7766/cse7766.h +4 -0
- esphome/components/cse7766/sensor.py +13 -1
- esphome/components/cst816/touchscreen/__init__.py +7 -4
- esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +20 -19
- esphome/components/cst816/touchscreen/cst816_touchscreen.h +2 -0
- esphome/components/datetime/__init__.py +21 -14
- esphome/components/datetime/datetime_base.h +8 -1
- esphome/components/datetime/datetime_entity.cpp +2 -0
- esphome/components/datetime/datetime_entity.h +2 -0
- esphome/components/datetime/time_entity.cpp +2 -0
- esphome/components/datetime/time_entity.h +2 -0
- esphome/components/esp32/__init__.py +20 -4
- esphome/components/esp32_improv/__init__.py +82 -1
- esphome/components/esp32_improv/automation.h +72 -0
- esphome/components/esp32_improv/esp32_improv_component.cpp +13 -5
- esphome/components/esp32_improv/esp32_improv_component.h +15 -0
- esphome/components/ethernet/__init__.py +5 -0
- esphome/components/ethernet/ethernet_component.cpp +13 -0
- esphome/components/ethernet/ethernet_component.h +1 -0
- esphome/components/event/__init__.py +20 -12
- esphome/components/fan/__init__.py +3 -4
- esphome/components/gp2y1010au0f/__init__.py +0 -0
- esphome/components/gp2y1010au0f/gp2y1010au0f.cpp +67 -0
- esphome/components/gp2y1010au0f/gp2y1010au0f.h +52 -0
- esphome/components/gp2y1010au0f/sensor.py +61 -0
- esphome/components/gpio_expander/__init__.py +0 -0
- esphome/components/gpio_expander/cached_gpio.h +38 -0
- esphome/components/grove_gas_mc_v2/__init__.py +0 -0
- esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +88 -0
- esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +39 -0
- esphome/components/grove_gas_mc_v2/sensor.py +77 -0
- esphome/components/haier/climate.py +4 -3
- esphome/components/haier/haier_base.cpp +63 -8
- esphome/components/haier/haier_base.h +29 -3
- esphome/components/haier/hon_climate.cpp +122 -65
- esphome/components/haier/hon_climate.h +18 -2
- esphome/components/haier/smartair2_climate.cpp +21 -21
- esphome/components/haier/switch/__init__.py +91 -0
- esphome/components/haier/switch/beeper.cpp +14 -0
- esphome/components/haier/switch/beeper.h +18 -0
- esphome/components/haier/switch/display.cpp +14 -0
- esphome/components/haier/switch/display.h +18 -0
- esphome/components/haier/switch/health_mode.cpp +14 -0
- esphome/components/haier/switch/health_mode.h +18 -0
- esphome/components/haier/switch/quiet_mode.cpp +14 -0
- esphome/components/haier/switch/quiet_mode.h +18 -0
- esphome/components/hmac_md5/hmac_md5.cpp +2 -0
- esphome/components/hmac_md5/hmac_md5.h +2 -1
- esphome/components/i2s_audio/speaker/__init__.py +19 -0
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +2 -0
- esphome/components/ili9xxx/ili9xxx_display.h +1 -0
- esphome/components/image/__init__.py +12 -12
- esphome/components/image/image.cpp +44 -0
- esphome/components/image/image.h +17 -2
- esphome/components/inkplate6/display.py +2 -0
- esphome/components/inkplate6/inkplate.h +30 -2
- esphome/components/light/__init__.py +3 -4
- esphome/components/lock/__init__.py +3 -4
- esphome/components/lvgl/__init__.py +16 -5
- esphome/components/lvgl/defines.py +1 -0
- esphome/components/lvgl/hello_world.py +64 -0
- esphome/components/lvgl/lv_validation.py +159 -3
- esphome/components/lvgl/lvgl_esphome.cpp +0 -43
- esphome/components/lvgl/lvgl_esphome.h +0 -4
- esphome/components/lvgl/styles.py +3 -2
- esphome/components/lvgl/text/__init__.py +3 -3
- esphome/components/lvgl/widgets/__init__.py +2 -0
- esphome/components/lvgl/widgets/animimg.py +3 -4
- esphome/components/lvgl/widgets/dropdown.py +5 -1
- esphome/components/lvgl/widgets/meter.py +16 -11
- esphome/components/md5/__init__.py +6 -0
- esphome/components/md5/md5.cpp +2 -0
- esphome/components/md5/md5.h +2 -0
- esphome/components/micro_wake_word/__init__.py +7 -0
- esphome/components/mics_4514/sensor.py +11 -26
- esphome/components/modbus_controller/__init__.py +7 -5
- esphome/components/modbus_controller/binary_sensor/__init__.py +6 -6
- esphome/components/modbus_controller/number/__init__.py +5 -6
- esphome/components/modbus_controller/output/__init__.py +10 -14
- esphome/components/modbus_controller/select/__init__.py +1 -1
- esphome/components/modbus_controller/sensor/__init__.py +7 -7
- esphome/components/modbus_controller/switch/__init__.py +6 -7
- esphome/components/modbus_controller/text_sensor/__init__.py +8 -9
- esphome/components/mqtt/__init__.py +3 -0
- esphome/components/mqtt/mqtt_client.cpp +2 -0
- esphome/components/mqtt/mqtt_client.h +2 -0
- esphome/components/nau7802/__init__.py +0 -0
- esphome/components/nau7802/nau7802.cpp +323 -0
- esphome/components/nau7802/nau7802.h +121 -0
- esphome/components/nau7802/sensor.py +134 -0
- esphome/components/nextion/base_component.py +1 -0
- esphome/components/nextion/display.py +4 -0
- esphome/components/nextion/nextion.cpp +19 -4
- esphome/components/nextion/nextion.h +16 -0
- esphome/components/npi19/__init__.py +0 -0
- esphome/components/npi19/npi19.cpp +111 -0
- esphome/components/npi19/npi19.h +30 -0
- esphome/components/npi19/sensor.py +52 -0
- esphome/components/number/__init__.py +3 -5
- esphome/components/online_image/__init__.py +1 -1
- esphome/components/online_image/online_image.h +1 -2
- esphome/components/opentherm/__init__.py +57 -0
- esphome/components/opentherm/hub.cpp +277 -0
- esphome/components/opentherm/hub.h +110 -0
- esphome/components/opentherm/opentherm.cpp +568 -0
- esphome/components/opentherm/opentherm.h +347 -0
- esphome/components/pulse_counter/pulse_counter_sensor.cpp +8 -1
- esphome/components/pulse_counter/pulse_counter_sensor.h +1 -0
- esphome/components/radon_eye_ble/radon_eye_listener.cpp +10 -3
- esphome/components/remote_transmitter/__init__.py +18 -2
- esphome/components/remote_transmitter/remote_transmitter.h +6 -0
- esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +2 -0
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
- esphome/components/select/__init__.py +3 -4
- esphome/components/sensor/__init__.py +3 -4
- esphome/components/shelly_dimmer/shelly_dimmer.cpp +32 -32
- esphome/components/shelly_dimmer/shelly_dimmer.h +2 -0
- esphome/components/st7701s/st7701s.cpp +21 -8
- esphome/components/st7701s/st7701s.h +2 -0
- esphome/components/switch/__init__.py +3 -4
- esphome/components/tca9555/__init__.py +72 -0
- esphome/components/tca9555/tca9555.cpp +140 -0
- esphome/components/tca9555/tca9555.h +64 -0
- esphome/components/tcs34725/tcs34725.cpp +62 -64
- esphome/components/tem3200/__init__.py +0 -0
- esphome/components/tem3200/sensor.py +55 -0
- esphome/components/tem3200/tem3200.cpp +151 -0
- esphome/components/tem3200/tem3200.h +30 -0
- esphome/components/template/binary_sensor/__init__.py +19 -6
- esphome/components/text/__init__.py +3 -4
- esphome/components/text_sensor/__init__.py +3 -4
- esphome/components/thermostat/climate.py +11 -9
- esphome/components/thermostat/thermostat_climate.cpp +21 -15
- esphome/components/tm1638/binary_sensor/__init__.py +3 -2
- esphome/components/tm1638/display.py +5 -5
- esphome/components/tm1638/output/__init__.py +3 -2
- esphome/components/tm1638/switch/__init__.py +3 -2
- esphome/components/touchscreen/touchscreen.cpp +2 -2
- esphome/components/update/__init__.py +3 -4
- esphome/components/valve/__init__.py +3 -4
- esphome/components/web_server/__init__.py +78 -22
- esphome/components/web_server/server_index_v3.h +3989 -3979
- esphome/components/web_server/web_server.cpp +219 -34
- esphome/components/web_server/web_server.h +10 -1
- esphome/components/wifi/wifi_component_esp_idf.cpp +4 -5
- esphome/config_validation.py +1 -0
- esphome/const.py +12 -2
- esphome/core/defines.h +4 -2
- esphome/core/helpers.cpp +46 -10
- esphome/core/helpers.h +8 -0
- esphome/core/ring_buffer.cpp +12 -2
- esphome/core/ring_buffer.h +3 -0
- {esphome-2024.9.2.dist-info → esphome-2024.10.0.dist-info}/METADATA +5 -3
- {esphome-2024.9.2.dist-info → esphome-2024.10.0.dist-info}/RECORD +192 -143
- {esphome-2024.9.2.dist-info → esphome-2024.10.0.dist-info}/LICENSE +0 -0
- {esphome-2024.9.2.dist-info → esphome-2024.10.0.dist-info}/WHEEL +0 -0
- {esphome-2024.9.2.dist-info → esphome-2024.10.0.dist-info}/entry_points.txt +0 -0
- {esphome-2024.9.2.dist-info → esphome-2024.10.0.dist-info}/top_level.txt +0 -0
@@ -8,8 +8,14 @@ namespace st7701s {
|
|
8
8
|
void ST7701S::setup() {
|
9
9
|
esph_log_config(TAG, "Setting up ST7701S");
|
10
10
|
this->spi_setup();
|
11
|
+
this->write_init_sequence_();
|
12
|
+
|
11
13
|
esp_lcd_rgb_panel_config_t config{};
|
12
14
|
config.flags.fb_in_psram = 1;
|
15
|
+
#if ESP_IDF_VERSION_MAJOR >= 5
|
16
|
+
config.bounce_buffer_size_px = this->width_ * 10;
|
17
|
+
config.num_fbs = 1;
|
18
|
+
#endif // ESP_IDF_VERSION_MAJOR
|
13
19
|
config.timings.h_res = this->width_;
|
14
20
|
config.timings.v_res = this->height_;
|
15
21
|
config.timings.hsync_pulse_width = this->hsync_pulse_width_;
|
@@ -21,7 +27,6 @@ void ST7701S::setup() {
|
|
21
27
|
config.timings.flags.pclk_active_neg = this->pclk_inverted_;
|
22
28
|
config.timings.pclk_hz = this->pclk_frequency_;
|
23
29
|
config.clk_src = LCD_CLK_SRC_PLL160M;
|
24
|
-
config.sram_trans_align = 64;
|
25
30
|
config.psram_trans_align = 64;
|
26
31
|
size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]);
|
27
32
|
for (size_t i = 0; i != data_pin_count; i++) {
|
@@ -34,15 +39,21 @@ void ST7701S::setup() {
|
|
34
39
|
config.de_gpio_num = this->de_pin_->get_pin();
|
35
40
|
config.pclk_gpio_num = this->pclk_pin_->get_pin();
|
36
41
|
esp_err_t err = esp_lcd_new_rgb_panel(&config, &this->handle_);
|
42
|
+
ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_));
|
43
|
+
ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_));
|
37
44
|
if (err != ESP_OK) {
|
38
45
|
esph_log_e(TAG, "lcd_new_rgb_panel failed: %s", esp_err_to_name(err));
|
39
46
|
}
|
40
|
-
ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_));
|
41
|
-
ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_));
|
42
|
-
this->write_init_sequence_();
|
43
47
|
esph_log_config(TAG, "ST7701S setup complete");
|
44
48
|
}
|
45
49
|
|
50
|
+
void ST7701S::loop() {
|
51
|
+
#if ESP_IDF_VERSION_MAJOR >= 5
|
52
|
+
if (this->handle_ != nullptr)
|
53
|
+
esp_lcd_rgb_panel_restart(this->handle_);
|
54
|
+
#endif // ESP_IDF_VERSION_MAJOR
|
55
|
+
}
|
56
|
+
|
46
57
|
void ST7701S::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order,
|
47
58
|
display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) {
|
48
59
|
if (w <= 0 || h <= 0)
|
@@ -160,10 +171,12 @@ void ST7701S::write_init_sequence_() {
|
|
160
171
|
this->write_data_(val);
|
161
172
|
ESP_LOGD(TAG, "write MADCTL %X", val);
|
162
173
|
this->write_command_(this->invert_colors_ ? INVERT_ON : INVERT_OFF);
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
174
|
+
// can't avoid this inline delay due to the need to complete setup before anything else tries to draw.
|
175
|
+
delay(120); // NOLINT
|
176
|
+
this->write_command_(SLEEP_OUT);
|
177
|
+
this->write_command_(DISPLAY_ON);
|
178
|
+
this->spi_teardown(); // SPI not needed after this
|
179
|
+
delay(10);
|
167
180
|
}
|
168
181
|
|
169
182
|
void ST7701S::dump_config() {
|
@@ -33,6 +33,8 @@ class ST7701S : public display::Display,
|
|
33
33
|
public:
|
34
34
|
void update() override { this->do_update_(); }
|
35
35
|
void setup() override;
|
36
|
+
void complete_setup_();
|
37
|
+
void loop() override;
|
36
38
|
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order,
|
37
39
|
display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override;
|
38
40
|
|
@@ -14,7 +14,7 @@ from esphome.const import (
|
|
14
14
|
CONF_ON_TURN_ON,
|
15
15
|
CONF_RESTORE_MODE,
|
16
16
|
CONF_TRIGGER_ID,
|
17
|
-
|
17
|
+
CONF_WEB_SERVER,
|
18
18
|
DEVICE_CLASS_EMPTY,
|
19
19
|
DEVICE_CLASS_OUTLET,
|
20
20
|
DEVICE_CLASS_SWITCH,
|
@@ -156,9 +156,8 @@ async def setup_switch_core_(var, config):
|
|
156
156
|
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
157
157
|
await mqtt.register_mqtt_component(mqtt_, config)
|
158
158
|
|
159
|
-
if
|
160
|
-
|
161
|
-
web_server.add_entity_to_sorting_list(web_server_, var, config)
|
159
|
+
if web_server_config := config.get(CONF_WEB_SERVER):
|
160
|
+
await web_server.add_entity_config(var, web_server_config)
|
162
161
|
|
163
162
|
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
164
163
|
cg.add(var.set_device_class(device_class))
|
@@ -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
|
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
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
this->
|
83
|
-
|
84
|
-
const float
|
85
|
-
static const float
|
86
|
-
static const float
|
87
|
-
static const float
|
88
|
-
static const float
|
89
|
-
static const float
|
90
|
-
static const float
|
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
|
-
"
|
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 *
|
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
|
-
|
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
|
-
|
183
|
-
|
184
|
-
|
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
|
-
|
193
|
-
|
163
|
+
|
164
|
+
if (r == 0) {
|
165
|
+
ESP_LOGW(TAG, "Red channel is zero, cannot compute color temperature");
|
194
166
|
return;
|
195
167
|
}
|
196
|
-
|
197
|
-
|
198
|
-
|
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
|
-
|
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.
|
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
|
-
|
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))
|