esphome 2024.8.2__py3-none-any.whl → 2024.9.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/__main__.py +6 -2
- esphome/components/api/api_connection.cpp +53 -0
- esphome/components/api/api_connection.h +4 -0
- esphome/components/api/api_pb2.cpp +280 -0
- esphome/components/api/api_pb2.h +91 -0
- esphome/components/api/api_pb2_service.cpp +85 -0
- esphome/components/api/api_pb2_service.h +28 -0
- esphome/components/async_tcp/__init__.py +3 -3
- esphome/components/atm90e26/sensor.py +10 -10
- esphome/components/atm90e32/sensor.py +1 -1
- esphome/components/bl0906/__init__.py +1 -0
- esphome/components/bl0906/bl0906.cpp +238 -0
- esphome/components/bl0906/bl0906.h +96 -0
- esphome/components/bl0906/const.py +4 -0
- esphome/components/bl0906/constants.h +122 -0
- esphome/components/bl0906/sensor.py +184 -0
- esphome/components/bl0942/__init__.py +1 -1
- esphome/components/bl0942/bl0942.cpp +127 -34
- esphome/components/bl0942/bl0942.h +87 -3
- esphome/components/bl0942/sensor.py +46 -8
- esphome/components/ble_client/__init__.py +1 -3
- esphome/components/ble_presence/binary_sensor.py +2 -2
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +5 -0
- esphome/components/bmp280/sensor.py +2 -93
- esphome/components/bmp280_base/__init__.py +88 -0
- esphome/components/{bmp280/bmp280.cpp → bmp280_base/bmp280_base.cpp} +11 -4
- esphome/components/{bmp280/bmp280.h → bmp280_base/bmp280_base.h} +9 -5
- esphome/components/bmp280_i2c/__init__.py +0 -0
- esphome/components/bmp280_i2c/bmp280_i2c.cpp +27 -0
- esphome/components/bmp280_i2c/bmp280_i2c.h +22 -0
- esphome/components/bmp280_i2c/sensor.py +22 -0
- esphome/components/bmp280_spi/__init__.py +0 -0
- esphome/components/bmp280_spi/bmp280_spi.cpp +65 -0
- esphome/components/bmp280_spi/bmp280_spi.h +20 -0
- esphome/components/bmp280_spi/sensor.py +22 -0
- esphome/components/captive_portal/captive_portal.cpp +2 -0
- esphome/components/captive_portal/captive_portal.h +3 -1
- esphome/components/ch422g/__init__.py +67 -0
- esphome/components/ch422g/ch422g.cpp +122 -0
- esphome/components/ch422g/ch422g.h +70 -0
- esphome/components/debug/debug_esp32.cpp +3 -1
- esphome/components/display/__init__.py +5 -4
- esphome/components/dsmr/dsmr.cpp +6 -0
- esphome/components/dsmr/dsmr.h +6 -0
- esphome/components/dsmr/text_sensor.py +7 -2
- esphome/components/e131/e131.cpp +2 -0
- esphome/components/e131/e131.h +3 -1
- esphome/components/e131/e131_addressable_light_effect.cpp +2 -0
- esphome/components/e131/e131_addressable_light_effect.h +2 -1
- esphome/components/e131/e131_packet.cpp +2 -0
- esphome/components/esp32_ble/ble_uuid.cpp +7 -0
- esphome/components/esp32_ble/ble_uuid.h +1 -0
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +11 -9
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +3 -3
- esphome/components/esp32_camera/__init__.py +4 -0
- esphome/components/esp32_camera/esp32_camera.cpp +9 -1
- esphome/components/esp32_camera/esp32_camera.h +3 -0
- esphome/components/esp32_can/canbus.py +18 -7
- esphome/components/esp32_can/esp32_can.cpp +8 -0
- esphome/components/esp32_can/esp32_can.h +4 -0
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +14 -2
- esphome/components/esp32_rmt_led_strip/led_strip.h +3 -2
- esphome/components/esp32_rmt_led_strip/light.py +21 -4
- esphome/components/esphome/ota/ota_esphome.cpp +2 -1
- esphome/components/esphome/ota/ota_esphome.h +2 -0
- esphome/components/font/__init__.py +11 -22
- esphome/components/font/font.cpp +3 -2
- esphome/components/font/font.h +12 -3
- esphome/components/gree/climate.py +2 -1
- esphome/components/gree/gree.cpp +54 -3
- esphome/components/gree/gree.h +10 -2
- esphome/components/gt911/touchscreen/__init__.py +6 -4
- esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +17 -0
- esphome/components/gt911/touchscreen/gt911_touchscreen.h +2 -0
- esphome/components/hmac_md5/__init__.py +2 -0
- esphome/components/hmac_md5/hmac_md5.cpp +56 -0
- esphome/components/hmac_md5/hmac_md5.h +48 -0
- esphome/components/homeassistant/__init__.py +13 -0
- esphome/components/homeassistant/switch/__init__.py +15 -2
- esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
- esphome/components/i2s_audio/__init__.py +88 -9
- esphome/components/i2s_audio/i2s_audio.h +20 -2
- esphome/components/i2s_audio/media_player/__init__.py +8 -4
- esphome/components/i2s_audio/media_player/i2s_audio_media_player.h +1 -1
- esphome/components/i2s_audio/microphone/__init__.py +19 -51
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +18 -15
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +0 -12
- esphome/components/i2s_audio/speaker/__init__.py +39 -27
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +49 -37
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +3 -4
- esphome/components/ili9xxx/display.py +16 -17
- esphome/components/ili9xxx/ili9xxx_display.cpp +1 -1
- esphome/components/ili9xxx/ili9xxx_display.h +18 -18
- esphome/components/ili9xxx/ili9xxx_init.h +0 -3
- esphome/components/improv_serial/improv_serial_component.cpp +2 -1
- esphome/components/improv_serial/improv_serial_component.h +2 -1
- esphome/components/ledc/ledc_output.cpp +11 -7
- esphome/components/libretiny/__init__.py +8 -13
- esphome/components/ltr501/__init__.py +1 -0
- esphome/components/ltr501/ltr501.cpp +542 -0
- esphome/components/ltr501/ltr501.h +184 -0
- esphome/components/ltr501/ltr_definitions_501.h +260 -0
- esphome/components/ltr501/sensor.py +274 -0
- esphome/components/ltr_als_ps/sensor.py +2 -2
- esphome/components/lvgl/__init__.py +19 -16
- esphome/components/lvgl/automation.py +90 -9
- esphome/components/lvgl/defines.py +29 -2
- esphome/components/lvgl/gradient.py +61 -0
- esphome/components/lvgl/lv_validation.py +45 -27
- esphome/components/lvgl/lvcode.py +8 -3
- esphome/components/lvgl/lvgl_esphome.cpp +54 -0
- esphome/components/lvgl/lvgl_esphome.h +9 -3
- esphome/components/lvgl/number/__init__.py +1 -0
- esphome/components/lvgl/number/lvgl_number.h +3 -1
- esphome/components/lvgl/schemas.py +16 -11
- esphome/components/lvgl/select/__init__.py +1 -0
- esphome/components/lvgl/select/lvgl_select.h +3 -1
- esphome/components/lvgl/switch/__init__.py +2 -1
- esphome/components/lvgl/switch/lvgl_switch.h +3 -1
- esphome/components/lvgl/text/__init__.py +1 -0
- esphome/components/lvgl/text/lvgl_text.h +3 -1
- esphome/components/lvgl/trigger.py +3 -2
- esphome/components/lvgl/types.py +2 -1
- esphome/components/lvgl/widgets/__init__.py +23 -8
- esphome/components/lvgl/widgets/arc.py +5 -1
- esphome/components/lvgl/widgets/buttonmatrix.py +5 -1
- esphome/components/lvgl/widgets/checkbox.py +8 -3
- esphome/components/lvgl/widgets/meter.py +8 -1
- esphome/components/lvgl/widgets/msgbox.py +26 -15
- esphome/components/lvgl/widgets/page.py +51 -7
- esphome/components/lvgl/widgets/tileview.py +2 -8
- esphome/components/max31856/max31856.cpp +12 -1
- esphome/components/max31856/max31856.h +5 -2
- esphome/components/max31856/sensor.py +20 -0
- esphome/components/mcp9600/sensor.py +2 -2
- esphome/components/mdns/__init__.py +6 -6
- esphome/components/media_player/media_player.h +16 -0
- esphome/components/micro_wake_word/__init__.py +2 -25
- esphome/components/microphone/microphone.h +1 -1
- esphome/components/mics_4514/mics_4514.cpp +26 -36
- esphome/components/modbus_controller/__init__.py +6 -0
- esphome/components/modbus_controller/const.py +2 -0
- esphome/components/modbus_controller/modbus_controller.cpp +30 -27
- esphome/components/modbus_controller/modbus_controller.h +22 -4
- esphome/components/network/__init__.py +11 -8
- esphome/components/pipsolar/pipsolar.cpp +3 -0
- esphome/components/pipsolar/pipsolar.h +1 -0
- esphome/components/pipsolar/switch/__init__.py +2 -0
- esphome/components/prometheus/prometheus_handler.cpp +2 -0
- esphome/components/prometheus/prometheus_handler.h +3 -1
- esphome/components/rp2040/__init__.py +7 -8
- esphome/components/rpi_dpi_rgb/display.py +20 -17
- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +36 -6
- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h +4 -0
- esphome/components/socket/socket.cpp +2 -0
- esphome/components/socket/socket.h +2 -0
- esphome/components/speaker/speaker.h +1 -1
- esphome/components/st7701s/display.py +35 -37
- esphome/components/st7701s/st7701s.cpp +11 -6
- esphome/components/st7701s/st7701s.h +1 -0
- esphome/components/statsd/__init__.py +65 -0
- esphome/components/statsd/statsd.cpp +156 -0
- esphome/components/statsd/statsd.h +86 -0
- esphome/components/tuya/__init__.py +1 -0
- esphome/components/tuya/number/__init__.py +39 -2
- esphome/components/tuya/number/tuya_number.cpp +58 -2
- esphome/components/tuya/number/tuya_number.h +12 -3
- esphome/components/udp/__init__.py +158 -0
- esphome/components/udp/binary_sensor.py +27 -0
- esphome/components/udp/sensor.py +27 -0
- esphome/components/udp/udp_component.cpp +616 -0
- esphome/components/udp/udp_component.h +158 -0
- esphome/components/uponor_smatrix/uponor_smatrix.cpp +4 -6
- esphome/components/uponor_smatrix/uponor_smatrix.h +0 -1
- esphome/components/veml7700/sensor.py +2 -2
- esphome/components/voice_assistant/__init__.py +6 -0
- esphome/components/voice_assistant/voice_assistant.cpp +24 -2
- esphome/components/voice_assistant/voice_assistant.h +20 -0
- esphome/components/web_server/__init__.py +11 -11
- esphome/components/web_server/list_entities.cpp +2 -0
- esphome/components/web_server/list_entities.h +3 -1
- esphome/components/web_server/web_server.cpp +2 -1
- esphome/components/web_server/web_server.h +2 -0
- esphome/components/web_server_base/web_server_base.cpp +2 -0
- esphome/components/web_server_base/web_server_base.h +3 -1
- esphome/components/wifi/wifi_component_libretiny.cpp +15 -1
- esphome/components/wireguard/__init__.py +9 -6
- esphome/components/wireguard/wireguard.cpp +2 -1
- esphome/components/wireguard/wireguard.h +3 -1
- esphome/config_validation.py +8 -0
- esphome/const.py +8 -1
- esphome/core/bytebuffer.cpp +117 -84
- esphome/core/bytebuffer.h +69 -21
- esphome/core/config.py +0 -3
- esphome/core/defines.h +2 -0
- esphome/core/ring_buffer.cpp +13 -2
- esphome/core/ring_buffer.h +56 -0
- esphome/external_files.py +5 -3
- {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/METADATA +1 -1
- {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/RECORD +204 -169
- {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/LICENSE +0 -0
- {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/WHEEL +0 -0
- {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/entry_points.txt +0 -0
- {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/top_level.txt +0 -0
@@ -1,47 +1,39 @@
|
|
1
|
-
import esphome.codegen as cg
|
2
|
-
import esphome.config_validation as cv
|
3
1
|
from esphome import pins
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
import esphome.codegen as cg
|
3
|
+
from esphome.components import display, spi
|
4
|
+
from esphome.components.esp32 import const, only_on_variant
|
5
|
+
from esphome.components.rpi_dpi_rgb.display import (
|
6
|
+
CONF_PCLK_FREQUENCY,
|
7
|
+
CONF_PCLK_INVERTED,
|
7
8
|
)
|
9
|
+
import esphome.config_validation as cv
|
8
10
|
from esphome.const import (
|
9
|
-
|
10
|
-
|
11
|
-
CONF_RESET_PIN,
|
11
|
+
CONF_BLUE,
|
12
|
+
CONF_COLOR_ORDER,
|
12
13
|
CONF_DATA_PINS,
|
13
|
-
|
14
|
+
CONF_DC_PIN,
|
14
15
|
CONF_DIMENSIONS,
|
15
|
-
|
16
|
-
CONF_WIDTH,
|
16
|
+
CONF_GREEN,
|
17
17
|
CONF_HEIGHT,
|
18
|
+
CONF_HSYNC_PIN,
|
19
|
+
CONF_ID,
|
20
|
+
CONF_IGNORE_STRAPPING_WARNING,
|
21
|
+
CONF_INVERT_COLORS,
|
18
22
|
CONF_LAMBDA,
|
19
23
|
CONF_MIRROR_X,
|
20
24
|
CONF_MIRROR_Y,
|
21
|
-
|
22
|
-
CONF_TRANSFORM,
|
25
|
+
CONF_NUMBER,
|
23
26
|
CONF_OFFSET_HEIGHT,
|
24
27
|
CONF_OFFSET_WIDTH,
|
25
|
-
CONF_INVERT_COLORS,
|
26
28
|
CONF_RED,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
CONF_RESET_PIN,
|
30
|
+
CONF_TRANSFORM,
|
31
|
+
CONF_VSYNC_PIN,
|
32
|
+
CONF_WIDTH,
|
31
33
|
)
|
34
|
+
from esphome.core import TimePeriod
|
32
35
|
|
33
|
-
from
|
34
|
-
only_on_variant,
|
35
|
-
const,
|
36
|
-
)
|
37
|
-
from esphome.components.rpi_dpi_rgb.display import (
|
38
|
-
CONF_PCLK_FREQUENCY,
|
39
|
-
CONF_PCLK_INVERTED,
|
40
|
-
)
|
41
|
-
from .init_sequences import (
|
42
|
-
ST7701S_INITS,
|
43
|
-
cmd,
|
44
|
-
)
|
36
|
+
from .init_sequences import ST7701S_INITS, cmd
|
45
37
|
|
46
38
|
CONF_INIT_SEQUENCE = "init_sequence"
|
47
39
|
CONF_DE_PIN = "de_pin"
|
@@ -59,6 +51,7 @@ DEPENDENCIES = ["spi", "esp32"]
|
|
59
51
|
st7701s_ns = cg.esphome_ns.namespace("st7701s")
|
60
52
|
ST7701S = st7701s_ns.class_("ST7701S", display.Display, cg.Component, spi.SPIDevice)
|
61
53
|
ColorOrder = display.display_ns.enum("ColorMode")
|
54
|
+
ST7701S_DELAY_FLAG = 0xFF
|
62
55
|
|
63
56
|
COLOR_ORDERS = {
|
64
57
|
"RGB": ColorOrder.COLOR_ORDER_RGB,
|
@@ -93,18 +86,23 @@ def map_sequence(value):
|
|
93
86
|
"""
|
94
87
|
An initialisation sequence can be selected from one of the pre-defined sequences in init_sequences.py,
|
95
88
|
or can be a literal array of data bytes.
|
96
|
-
The format is a repeated sequence of [CMD,
|
89
|
+
The format is a repeated sequence of [CMD, <data>] where <data> is s a sequence of bytes. The length is inferred
|
90
|
+
from the length of the sequence and should not be explicit.
|
91
|
+
A delay can be inserted by specifying "- delay N" where N is in ms
|
97
92
|
"""
|
93
|
+
if isinstance(value, str) and value.lower().startswith("delay "):
|
94
|
+
value = value.lower()[6:]
|
95
|
+
delay = cv.All(
|
96
|
+
cv.positive_time_period_milliseconds,
|
97
|
+
cv.Range(TimePeriod(milliseconds=1), TimePeriod(milliseconds=255)),
|
98
|
+
)(value)
|
99
|
+
return [delay, ST7701S_DELAY_FLAG]
|
98
100
|
if not isinstance(value, list):
|
99
101
|
value = cv.int_(value)
|
100
102
|
value = cv.one_of(*ST7701S_INITS)(value)
|
101
103
|
return ST7701S_INITS[value]
|
102
|
-
|
103
|
-
|
104
|
-
if data_length == 0:
|
105
|
-
raise cv.Invalid("Empty sequence")
|
106
|
-
value = cmd(*value)
|
107
|
-
return value
|
104
|
+
value = cv.Length(min=1, max=254)(value)
|
105
|
+
return cmd(*value)
|
108
106
|
|
109
107
|
|
110
108
|
CONFIG_SCHEMA = cv.All(
|
@@ -138,11 +138,16 @@ void ST7701S::write_init_sequence_() {
|
|
138
138
|
for (size_t i = 0; i != this->init_sequence_.size();) {
|
139
139
|
uint8_t cmd = this->init_sequence_[i++];
|
140
140
|
size_t len = this->init_sequence_[i++];
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
141
|
+
if (len == ST7701S_DELAY_FLAG) {
|
142
|
+
ESP_LOGV(TAG, "Delay %dms", cmd);
|
143
|
+
delay(cmd);
|
144
|
+
} else {
|
145
|
+
this->write_sequence_(cmd, len, &this->init_sequence_[i]);
|
146
|
+
i += len;
|
147
|
+
ESP_LOGV(TAG, "Command %X, %d bytes", cmd, len);
|
148
|
+
if (cmd == SW_RESET_CMD)
|
149
|
+
delay(6);
|
150
|
+
}
|
146
151
|
}
|
147
152
|
// st7701 does not appear to support axis swapping
|
148
153
|
this->write_sequence_(CMD2_BKSEL, sizeof(CMD2_BK0), CMD2_BK0);
|
@@ -153,7 +158,7 @@ void ST7701S::write_init_sequence_() {
|
|
153
158
|
val |= 0x10;
|
154
159
|
this->write_command_(MADCTL_CMD);
|
155
160
|
this->write_data_(val);
|
156
|
-
|
161
|
+
ESP_LOGD(TAG, "write MADCTL %X", val);
|
157
162
|
this->write_command_(this->invert_colors_ ? INVERT_ON : INVERT_OFF);
|
158
163
|
this->set_timeout(120, [this] {
|
159
164
|
this->write_command_(SLEEP_OUT);
|
@@ -25,6 +25,7 @@ const uint8_t INVERT_ON = 0x21;
|
|
25
25
|
const uint8_t DISPLAY_ON = 0x29;
|
26
26
|
const uint8_t CMD2_BKSEL = 0xFF;
|
27
27
|
const uint8_t CMD2_BK0[5] = {0x77, 0x01, 0x00, 0x00, 0x10};
|
28
|
+
const uint8_t ST7701S_DELAY_FLAG = 0xFF;
|
28
29
|
|
29
30
|
class ST7701S : public display::Display,
|
30
31
|
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
import esphome.config_validation as cv
|
3
|
+
from esphome.components import sensor, binary_sensor
|
4
|
+
from esphome.const import (
|
5
|
+
CONF_ID,
|
6
|
+
CONF_PORT,
|
7
|
+
CONF_NAME,
|
8
|
+
CONF_SENSORS,
|
9
|
+
CONF_BINARY_SENSORS,
|
10
|
+
)
|
11
|
+
|
12
|
+
AUTO_LOAD = ["socket"]
|
13
|
+
CODEOWNERS = ["@Links2004"]
|
14
|
+
DEPENDENCIES = ["network"]
|
15
|
+
|
16
|
+
CONF_HOST = "host"
|
17
|
+
CONF_PREFIX = "prefix"
|
18
|
+
|
19
|
+
statsd_component_ns = cg.esphome_ns.namespace("statsd")
|
20
|
+
StatsdComponent = statsd_component_ns.class_("StatsdComponent", cg.PollingComponent)
|
21
|
+
|
22
|
+
CONFIG_SENSORS_SCHEMA = cv.Schema(
|
23
|
+
{
|
24
|
+
cv.Required(CONF_ID): cv.use_id(sensor.Sensor),
|
25
|
+
cv.Required(CONF_NAME): cv.string_strict,
|
26
|
+
}
|
27
|
+
)
|
28
|
+
|
29
|
+
CONFIG_BINARY_SENSORS_SCHEMA = cv.Schema(
|
30
|
+
{
|
31
|
+
cv.Required(CONF_ID): cv.use_id(binary_sensor.BinarySensor),
|
32
|
+
cv.Required(CONF_NAME): cv.string_strict,
|
33
|
+
}
|
34
|
+
)
|
35
|
+
|
36
|
+
CONFIG_SCHEMA = cv.Schema(
|
37
|
+
{
|
38
|
+
cv.GenerateID(): cv.declare_id(StatsdComponent),
|
39
|
+
cv.Required(CONF_HOST): cv.string_strict,
|
40
|
+
cv.Optional(CONF_PORT, default=8125): cv.port,
|
41
|
+
cv.Optional(CONF_PREFIX, default=""): cv.string_strict,
|
42
|
+
cv.Optional(CONF_SENSORS): cv.ensure_list(CONFIG_SENSORS_SCHEMA),
|
43
|
+
cv.Optional(CONF_BINARY_SENSORS): cv.ensure_list(CONFIG_BINARY_SENSORS_SCHEMA),
|
44
|
+
}
|
45
|
+
).extend(cv.polling_component_schema("10s"))
|
46
|
+
|
47
|
+
|
48
|
+
async def to_code(config):
|
49
|
+
var = cg.new_Pvariable(config[CONF_ID])
|
50
|
+
await cg.register_component(var, config)
|
51
|
+
cg.add(
|
52
|
+
var.configure(
|
53
|
+
config.get(CONF_HOST),
|
54
|
+
config.get(CONF_PORT),
|
55
|
+
config.get(CONF_PREFIX),
|
56
|
+
)
|
57
|
+
)
|
58
|
+
|
59
|
+
for sensor_cfg in config.get(CONF_SENSORS, []):
|
60
|
+
s = await cg.get_variable(sensor_cfg[CONF_ID])
|
61
|
+
cg.add(var.register_sensor(sensor_cfg[CONF_NAME], s))
|
62
|
+
|
63
|
+
for sensor_cfg in config.get(CONF_BINARY_SENSORS, []):
|
64
|
+
s = await cg.get_variable(sensor_cfg[CONF_ID])
|
65
|
+
cg.add(var.register_binary_sensor(sensor_cfg[CONF_NAME], s))
|
@@ -0,0 +1,156 @@
|
|
1
|
+
#include "esphome/core/log.h"
|
2
|
+
|
3
|
+
#include "statsd.h"
|
4
|
+
|
5
|
+
namespace esphome {
|
6
|
+
namespace statsd {
|
7
|
+
|
8
|
+
// send UDP packet if we reach 1Kb packed size
|
9
|
+
// this is needed since statsD does not support fragmented UDP packets
|
10
|
+
static const uint16_t SEND_THRESHOLD = 1024;
|
11
|
+
|
12
|
+
static const char *const TAG = "statsD";
|
13
|
+
|
14
|
+
void StatsdComponent::setup() {
|
15
|
+
#ifndef USE_ESP8266
|
16
|
+
this->sock_ = esphome::socket::socket(AF_INET, SOCK_DGRAM, 0);
|
17
|
+
|
18
|
+
struct sockaddr_in source;
|
19
|
+
source.sin_family = AF_INET;
|
20
|
+
source.sin_addr.s_addr = htonl(INADDR_ANY);
|
21
|
+
source.sin_port = htons(this->port_);
|
22
|
+
this->sock_->bind((struct sockaddr *) &source, sizeof(source));
|
23
|
+
|
24
|
+
this->destination_.sin_family = AF_INET;
|
25
|
+
this->destination_.sin_port = htons(this->port_);
|
26
|
+
this->destination_.sin_addr.s_addr = inet_addr(this->host_);
|
27
|
+
#endif
|
28
|
+
}
|
29
|
+
|
30
|
+
StatsdComponent::~StatsdComponent() {
|
31
|
+
#ifndef USE_ESP8266
|
32
|
+
if (!this->sock_) {
|
33
|
+
return;
|
34
|
+
}
|
35
|
+
this->sock_->close();
|
36
|
+
#endif
|
37
|
+
}
|
38
|
+
|
39
|
+
void StatsdComponent::dump_config() {
|
40
|
+
ESP_LOGCONFIG(TAG, "statsD:");
|
41
|
+
ESP_LOGCONFIG(TAG, " host: %s", this->host_);
|
42
|
+
ESP_LOGCONFIG(TAG, " port: %d", this->port_);
|
43
|
+
if (this->prefix_) {
|
44
|
+
ESP_LOGCONFIG(TAG, " prefix: %s", this->prefix_);
|
45
|
+
}
|
46
|
+
|
47
|
+
ESP_LOGCONFIG(TAG, " metrics:");
|
48
|
+
for (sensors_t s : this->sensors_) {
|
49
|
+
ESP_LOGCONFIG(TAG, " - name: %s", s.name);
|
50
|
+
ESP_LOGCONFIG(TAG, " type: %d", s.type);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
float StatsdComponent::get_setup_priority() const { return esphome::setup_priority::AFTER_WIFI; }
|
55
|
+
|
56
|
+
#ifdef USE_SENSOR
|
57
|
+
void StatsdComponent::register_sensor(const char *name, esphome::sensor::Sensor *sensor) {
|
58
|
+
sensors_t s;
|
59
|
+
s.name = name;
|
60
|
+
s.sensor = sensor;
|
61
|
+
s.type = TYPE_SENSOR;
|
62
|
+
this->sensors_.push_back(s);
|
63
|
+
}
|
64
|
+
#endif
|
65
|
+
|
66
|
+
#ifdef USE_BINARY_SENSOR
|
67
|
+
void StatsdComponent::register_binary_sensor(const char *name, esphome::binary_sensor::BinarySensor *binary_sensor) {
|
68
|
+
sensors_t s;
|
69
|
+
s.name = name;
|
70
|
+
s.binary_sensor = binary_sensor;
|
71
|
+
s.type = TYPE_BINARY_SENSOR;
|
72
|
+
this->sensors_.push_back(s);
|
73
|
+
}
|
74
|
+
#endif
|
75
|
+
|
76
|
+
void StatsdComponent::update() {
|
77
|
+
std::string out;
|
78
|
+
out.reserve(SEND_THRESHOLD);
|
79
|
+
|
80
|
+
for (sensors_t s : this->sensors_) {
|
81
|
+
double val = 0;
|
82
|
+
switch (s.type) {
|
83
|
+
#ifdef USE_SENSOR
|
84
|
+
case TYPE_SENSOR:
|
85
|
+
if (!s.sensor->has_state()) {
|
86
|
+
continue;
|
87
|
+
}
|
88
|
+
val = s.sensor->state;
|
89
|
+
break;
|
90
|
+
#endif
|
91
|
+
#ifdef USE_BINARY_SENSOR
|
92
|
+
case TYPE_BINARY_SENSOR:
|
93
|
+
if (!s.binary_sensor->has_state()) {
|
94
|
+
continue;
|
95
|
+
}
|
96
|
+
// map bool to double
|
97
|
+
if (s.binary_sensor->state) {
|
98
|
+
val = 1;
|
99
|
+
}
|
100
|
+
break;
|
101
|
+
#endif
|
102
|
+
default:
|
103
|
+
ESP_LOGE(TAG, "type not known, name: %s type: %d", s.name, s.type);
|
104
|
+
continue;
|
105
|
+
}
|
106
|
+
|
107
|
+
// statsD gauge:
|
108
|
+
// https://github.com/statsd/statsd/blob/master/docs/metric_types.md
|
109
|
+
// This implies you can't explicitly set a gauge to a negative number without first setting it to zero.
|
110
|
+
if (val < 0) {
|
111
|
+
if (this->prefix_) {
|
112
|
+
out.append(str_sprintf("%s.", this->prefix_));
|
113
|
+
}
|
114
|
+
out.append(str_sprintf("%s:0|g\n", s.name));
|
115
|
+
}
|
116
|
+
if (this->prefix_) {
|
117
|
+
out.append(str_sprintf("%s.", this->prefix_));
|
118
|
+
}
|
119
|
+
out.append(str_sprintf("%s:%f|g\n", s.name, val));
|
120
|
+
|
121
|
+
if (out.length() > SEND_THRESHOLD) {
|
122
|
+
this->send_(&out);
|
123
|
+
out.clear();
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
this->send_(&out);
|
128
|
+
}
|
129
|
+
|
130
|
+
void StatsdComponent::send_(std::string *out) {
|
131
|
+
if (out->empty()) {
|
132
|
+
return;
|
133
|
+
}
|
134
|
+
#ifdef USE_ESP8266
|
135
|
+
IPAddress ip;
|
136
|
+
ip.fromString(this->host_);
|
137
|
+
|
138
|
+
this->sock_.beginPacket(ip, this->port_);
|
139
|
+
this->sock_.write((const uint8_t *) out->c_str(), out->length());
|
140
|
+
this->sock_.endPacket();
|
141
|
+
|
142
|
+
#else
|
143
|
+
if (!this->sock_) {
|
144
|
+
return;
|
145
|
+
}
|
146
|
+
|
147
|
+
int n_bytes = this->sock_->sendto(out->c_str(), out->length(), 0, reinterpret_cast<sockaddr *>(&this->destination_),
|
148
|
+
sizeof(this->destination_));
|
149
|
+
if (n_bytes != out->length()) {
|
150
|
+
ESP_LOGE(TAG, "Failed to send UDP packed (%d of %d)", n_bytes, out->length());
|
151
|
+
}
|
152
|
+
#endif
|
153
|
+
}
|
154
|
+
|
155
|
+
} // namespace statsd
|
156
|
+
} // namespace esphome
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <vector>
|
4
|
+
|
5
|
+
#include "esphome/core/defines.h"
|
6
|
+
#include "esphome/core/component.h"
|
7
|
+
#include "esphome/components/socket/socket.h"
|
8
|
+
#include "esphome/components/network/ip_address.h"
|
9
|
+
|
10
|
+
#ifdef USE_SENSOR
|
11
|
+
#include "esphome/components/sensor/sensor.h"
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#ifdef USE_BINARY_SENSOR
|
15
|
+
#include "esphome/components/binary_sensor/binary_sensor.h"
|
16
|
+
#endif
|
17
|
+
|
18
|
+
#ifdef USE_LOGGER
|
19
|
+
#include "esphome/components/logger/logger.h"
|
20
|
+
#endif
|
21
|
+
|
22
|
+
#ifdef USE_ESP8266
|
23
|
+
#include "WiFiUdp.h"
|
24
|
+
#include "IPAddress.h"
|
25
|
+
#endif
|
26
|
+
|
27
|
+
namespace esphome {
|
28
|
+
namespace statsd {
|
29
|
+
|
30
|
+
using sensor_type_t = enum { TYPE_SENSOR, TYPE_BINARY_SENSOR };
|
31
|
+
|
32
|
+
using sensors_t = struct {
|
33
|
+
const char *name;
|
34
|
+
sensor_type_t type;
|
35
|
+
union {
|
36
|
+
#ifdef USE_SENSOR
|
37
|
+
esphome::sensor::Sensor *sensor;
|
38
|
+
#endif
|
39
|
+
#ifdef USE_BINARY_SENSOR
|
40
|
+
esphome::binary_sensor::BinarySensor *binary_sensor;
|
41
|
+
#endif
|
42
|
+
};
|
43
|
+
};
|
44
|
+
|
45
|
+
class StatsdComponent : public PollingComponent {
|
46
|
+
public:
|
47
|
+
~StatsdComponent();
|
48
|
+
|
49
|
+
void setup() override;
|
50
|
+
void dump_config() override;
|
51
|
+
void update() override;
|
52
|
+
float get_setup_priority() const override;
|
53
|
+
|
54
|
+
void configure(const char *host, uint16_t port, const char *prefix) {
|
55
|
+
this->host_ = host;
|
56
|
+
this->port_ = port;
|
57
|
+
this->prefix_ = prefix;
|
58
|
+
}
|
59
|
+
|
60
|
+
#ifdef USE_SENSOR
|
61
|
+
void register_sensor(const char *name, esphome::sensor::Sensor *sensor);
|
62
|
+
#endif
|
63
|
+
|
64
|
+
#ifdef USE_BINARY_SENSOR
|
65
|
+
void register_binary_sensor(const char *name, esphome::binary_sensor::BinarySensor *binary_sensor);
|
66
|
+
#endif
|
67
|
+
|
68
|
+
private:
|
69
|
+
const char *host_;
|
70
|
+
const char *prefix_;
|
71
|
+
uint16_t port_;
|
72
|
+
|
73
|
+
std::vector<sensors_t> sensors_;
|
74
|
+
|
75
|
+
#ifdef USE_ESP8266
|
76
|
+
WiFiUDP sock_;
|
77
|
+
#else
|
78
|
+
std::unique_ptr<esphome::socket::Socket> sock_;
|
79
|
+
struct sockaddr_in destination_;
|
80
|
+
#endif
|
81
|
+
|
82
|
+
void send_(std::string *out);
|
83
|
+
};
|
84
|
+
|
85
|
+
} // namespace statsd
|
86
|
+
} // namespace esphome
|
@@ -15,6 +15,7 @@ CONF_DATAPOINT_TYPE = "datapoint_type"
|
|
15
15
|
CONF_STATUS_PIN = "status_pin"
|
16
16
|
|
17
17
|
tuya_ns = cg.esphome_ns.namespace("tuya")
|
18
|
+
TuyaDatapointType = tuya_ns.enum("TuyaDatapointType", is_class=True)
|
18
19
|
Tuya = tuya_ns.class_("Tuya", cg.Component, uart.UARTDevice)
|
19
20
|
|
20
21
|
DPTYPE_ANY = "any"
|
@@ -8,18 +8,37 @@ from esphome.const import (
|
|
8
8
|
CONF_MIN_VALUE,
|
9
9
|
CONF_MULTIPLY,
|
10
10
|
CONF_STEP,
|
11
|
+
CONF_INITIAL_VALUE,
|
12
|
+
CONF_RESTORE_VALUE,
|
11
13
|
)
|
12
|
-
from .. import tuya_ns, CONF_TUYA_ID, Tuya
|
14
|
+
from .. import tuya_ns, CONF_TUYA_ID, Tuya, TuyaDatapointType
|
13
15
|
|
14
16
|
DEPENDENCIES = ["tuya"]
|
15
17
|
CODEOWNERS = ["@frankiboy1"]
|
16
18
|
|
19
|
+
CONF_DATAPOINT_HIDDEN = "datapoint_hidden"
|
20
|
+
CONF_DATAPOINT_TYPE = "datapoint_type"
|
21
|
+
|
17
22
|
TuyaNumber = tuya_ns.class_("TuyaNumber", number.Number, cg.Component)
|
18
23
|
|
24
|
+
DATAPOINT_TYPES = {
|
25
|
+
"int": TuyaDatapointType.INTEGER,
|
26
|
+
"uint": TuyaDatapointType.INTEGER,
|
27
|
+
"enum": TuyaDatapointType.ENUM,
|
28
|
+
}
|
29
|
+
|
19
30
|
|
20
31
|
def validate_min_max(config):
|
21
|
-
|
32
|
+
max_value = config[CONF_MAX_VALUE]
|
33
|
+
min_value = config[CONF_MIN_VALUE]
|
34
|
+
if max_value <= min_value:
|
22
35
|
raise cv.Invalid("max_value must be greater than min_value")
|
36
|
+
if hidden_config := config.get(CONF_DATAPOINT_HIDDEN):
|
37
|
+
if (initial_value := hidden_config.get(CONF_INITIAL_VALUE, None)) is not None:
|
38
|
+
if (initial_value > max_value) or (initial_value < min_value):
|
39
|
+
raise cv.Invalid(
|
40
|
+
f"{CONF_INITIAL_VALUE} must be a value between {CONF_MAX_VALUE} and {CONF_MIN_VALUE}"
|
41
|
+
)
|
23
42
|
return config
|
24
43
|
|
25
44
|
|
@@ -33,6 +52,17 @@ CONFIG_SCHEMA = cv.All(
|
|
33
52
|
cv.Required(CONF_MIN_VALUE): cv.float_,
|
34
53
|
cv.Required(CONF_STEP): cv.positive_float,
|
35
54
|
cv.Optional(CONF_MULTIPLY, default=1.0): cv.float_,
|
55
|
+
cv.Optional(CONF_DATAPOINT_HIDDEN): cv.All(
|
56
|
+
cv.Schema(
|
57
|
+
{
|
58
|
+
cv.Required(CONF_DATAPOINT_TYPE): cv.enum(
|
59
|
+
DATAPOINT_TYPES, lower=True
|
60
|
+
),
|
61
|
+
cv.Optional(CONF_INITIAL_VALUE): cv.float_,
|
62
|
+
cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean,
|
63
|
+
}
|
64
|
+
)
|
65
|
+
),
|
36
66
|
}
|
37
67
|
)
|
38
68
|
.extend(cv.COMPONENT_SCHEMA),
|
@@ -56,3 +86,10 @@ async def to_code(config):
|
|
56
86
|
cg.add(var.set_tuya_parent(parent))
|
57
87
|
|
58
88
|
cg.add(var.set_number_id(config[CONF_NUMBER_DATAPOINT]))
|
89
|
+
if hidden_config := config.get(CONF_DATAPOINT_HIDDEN):
|
90
|
+
cg.add(var.set_datapoint_type(hidden_config[CONF_DATAPOINT_TYPE]))
|
91
|
+
if (
|
92
|
+
hidden_init_value := hidden_config.get(CONF_INITIAL_VALUE, None)
|
93
|
+
) is not None:
|
94
|
+
cg.add(var.set_datapoint_initial_value(hidden_init_value))
|
95
|
+
cg.add(var.set_restore_value(hidden_config[CONF_RESTORE_VALUE]))
|
@@ -7,16 +7,58 @@ namespace tuya {
|
|
7
7
|
static const char *const TAG = "tuya.number";
|
8
8
|
|
9
9
|
void TuyaNumber::setup() {
|
10
|
+
if (this->restore_value_) {
|
11
|
+
this->pref_ = global_preferences->make_preference<float>(this->get_object_id_hash());
|
12
|
+
}
|
13
|
+
|
10
14
|
this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) {
|
11
15
|
if (datapoint.type == TuyaDatapointType::INTEGER) {
|
12
16
|
ESP_LOGV(TAG, "MCU reported number %u is: %d", datapoint.id, datapoint.value_int);
|
13
|
-
|
17
|
+
float value = datapoint.value_int / multiply_by_;
|
18
|
+
this->publish_state(value);
|
19
|
+
if (this->restore_value_)
|
20
|
+
this->pref_.save(&value);
|
14
21
|
} else if (datapoint.type == TuyaDatapointType::ENUM) {
|
15
22
|
ESP_LOGV(TAG, "MCU reported number %u is: %u", datapoint.id, datapoint.value_enum);
|
16
|
-
|
23
|
+
float value = datapoint.value_enum;
|
24
|
+
this->publish_state(value);
|
25
|
+
if (this->restore_value_)
|
26
|
+
this->pref_.save(&value);
|
27
|
+
} else {
|
28
|
+
ESP_LOGW(TAG, "Reported type (%d) is not a number!", static_cast<int>(datapoint.type));
|
29
|
+
return;
|
30
|
+
}
|
31
|
+
|
32
|
+
if ((this->type_) && (this->type_ != datapoint.type)) {
|
33
|
+
ESP_LOGW(TAG, "Reported type (%d) different than previously set (%d)!", static_cast<int>(datapoint.type),
|
34
|
+
static_cast<int>(*this->type_));
|
17
35
|
}
|
18
36
|
this->type_ = datapoint.type;
|
19
37
|
});
|
38
|
+
|
39
|
+
this->parent_->add_on_initialized_callback([this] {
|
40
|
+
if (this->type_) {
|
41
|
+
float value;
|
42
|
+
if (!this->restore_value_) {
|
43
|
+
if (this->initial_value_) {
|
44
|
+
value = *this->initial_value_;
|
45
|
+
} else {
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
} else {
|
49
|
+
if (!this->pref_.load(&value)) {
|
50
|
+
if (this->initial_value_) {
|
51
|
+
value = *this->initial_value_;
|
52
|
+
} else {
|
53
|
+
value = this->traits.get_min_value();
|
54
|
+
ESP_LOGW(TAG, "Failed to restore and there is no initial value defined. Setting min_value (%f)", value);
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
this->control(value);
|
60
|
+
}
|
61
|
+
});
|
20
62
|
}
|
21
63
|
|
22
64
|
void TuyaNumber::control(float value) {
|
@@ -28,11 +70,25 @@ void TuyaNumber::control(float value) {
|
|
28
70
|
this->parent_->set_enum_datapoint_value(this->number_id_, value);
|
29
71
|
}
|
30
72
|
this->publish_state(value);
|
73
|
+
|
74
|
+
if (this->restore_value_)
|
75
|
+
this->pref_.save(&value);
|
31
76
|
}
|
32
77
|
|
33
78
|
void TuyaNumber::dump_config() {
|
34
79
|
LOG_NUMBER("", "Tuya Number", this);
|
35
80
|
ESP_LOGCONFIG(TAG, " Number has datapoint ID %u", this->number_id_);
|
81
|
+
if (this->type_) {
|
82
|
+
ESP_LOGCONFIG(TAG, " Datapoint type is %d", static_cast<int>(*this->type_));
|
83
|
+
} else {
|
84
|
+
ESP_LOGCONFIG(TAG, " Datapoint type is unknown");
|
85
|
+
}
|
86
|
+
|
87
|
+
if (this->initial_value_) {
|
88
|
+
ESP_LOGCONFIG(TAG, " Initial Value: %f", *this->initial_value_);
|
89
|
+
}
|
90
|
+
|
91
|
+
ESP_LOGCONFIG(TAG, " Restore Value: %s", YESNO(this->restore_value_));
|
36
92
|
}
|
37
93
|
|
38
94
|
} // namespace tuya
|
@@ -1,8 +1,10 @@
|
|
1
1
|
#pragma once
|
2
2
|
|
3
|
-
#include "esphome/core/component.h"
|
4
|
-
#include "esphome/components/tuya/tuya.h"
|
5
3
|
#include "esphome/components/number/number.h"
|
4
|
+
#include "esphome/components/tuya/tuya.h"
|
5
|
+
#include "esphome/core/component.h"
|
6
|
+
#include "esphome/core/optional.h"
|
7
|
+
#include "esphome/core/preferences.h"
|
6
8
|
|
7
9
|
namespace esphome {
|
8
10
|
namespace tuya {
|
@@ -13,6 +15,9 @@ class TuyaNumber : public number::Number, public Component {
|
|
13
15
|
void dump_config() override;
|
14
16
|
void set_number_id(uint8_t number_id) { this->number_id_ = number_id; }
|
15
17
|
void set_write_multiply(float factor) { multiply_by_ = factor; }
|
18
|
+
void set_datapoint_type(TuyaDatapointType type) { type_ = type; }
|
19
|
+
void set_datapoint_initial_value(float value) { this->initial_value_ = value; }
|
20
|
+
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
|
16
21
|
|
17
22
|
void set_tuya_parent(Tuya *parent) { this->parent_ = parent; }
|
18
23
|
|
@@ -22,7 +27,11 @@ class TuyaNumber : public number::Number, public Component {
|
|
22
27
|
Tuya *parent_;
|
23
28
|
uint8_t number_id_{0};
|
24
29
|
float multiply_by_{1.0};
|
25
|
-
TuyaDatapointType type_{};
|
30
|
+
optional<TuyaDatapointType> type_{};
|
31
|
+
optional<float> initial_value_{};
|
32
|
+
bool restore_value_{false};
|
33
|
+
|
34
|
+
ESPPreferenceObject pref_;
|
26
35
|
};
|
27
36
|
|
28
37
|
} // namespace tuya
|