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
@@ -9,6 +9,10 @@
|
|
9
9
|
#include "esphome/components/esp32_ble_server/ble_server.h"
|
10
10
|
#include "esphome/components/wifi/wifi_component.h"
|
11
11
|
|
12
|
+
#ifdef USE_ESP32_IMPROV_STATE_CALLBACK
|
13
|
+
#include "esphome/core/automation.h"
|
14
|
+
#endif
|
15
|
+
|
12
16
|
#ifdef USE_BINARY_SENSOR
|
13
17
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
14
18
|
#endif
|
@@ -42,6 +46,11 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent {
|
|
42
46
|
void stop() override;
|
43
47
|
bool is_active() const { return this->state_ != improv::STATE_STOPPED; }
|
44
48
|
|
49
|
+
#ifdef USE_ESP32_IMPROV_STATE_CALLBACK
|
50
|
+
void add_on_state_callback(std::function<void(improv::State, improv::Error)> &&callback) {
|
51
|
+
this->state_callback_.add(std::move(callback));
|
52
|
+
}
|
53
|
+
#endif
|
45
54
|
#ifdef USE_BINARY_SENSOR
|
46
55
|
void set_authorizer(binary_sensor::BinarySensor *authorizer) { this->authorizer_ = authorizer; }
|
47
56
|
#endif
|
@@ -54,6 +63,9 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent {
|
|
54
63
|
void set_wifi_timeout(uint32_t wifi_timeout) { this->wifi_timeout_ = wifi_timeout; }
|
55
64
|
uint32_t get_wifi_timeout() const { return this->wifi_timeout_; }
|
56
65
|
|
66
|
+
improv::State get_improv_state() const { return this->state_; }
|
67
|
+
improv::Error get_improv_error_state() const { return this->error_state_; }
|
68
|
+
|
57
69
|
protected:
|
58
70
|
bool should_start_{false};
|
59
71
|
bool setup_complete_{false};
|
@@ -84,6 +96,9 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent {
|
|
84
96
|
|
85
97
|
improv::State state_{improv::STATE_STOPPED};
|
86
98
|
improv::Error error_state_{improv::ERROR_NONE};
|
99
|
+
#ifdef USE_ESP32_IMPROV_STATE_CALLBACK
|
100
|
+
CallbackManager<void(improv::State, improv::Error)> state_callback_{};
|
101
|
+
#endif
|
87
102
|
|
88
103
|
bool status_indicator_state_{false};
|
89
104
|
void set_status_indicator_state_(bool state);
|
@@ -59,6 +59,7 @@ ETHERNET_TYPES = {
|
|
59
59
|
"KSZ8081": EthernetType.ETHERNET_TYPE_KSZ8081,
|
60
60
|
"KSZ8081RNA": EthernetType.ETHERNET_TYPE_KSZ8081RNA,
|
61
61
|
"W5500": EthernetType.ETHERNET_TYPE_W5500,
|
62
|
+
"OPENETH": EthernetType.ETHERNET_TYPE_OPENETH,
|
62
63
|
}
|
63
64
|
|
64
65
|
SPI_ETHERNET_TYPES = ["W5500"]
|
@@ -171,6 +172,7 @@ CONFIG_SCHEMA = cv.All(
|
|
171
172
|
"KSZ8081": RMII_SCHEMA,
|
172
173
|
"KSZ8081RNA": RMII_SCHEMA,
|
173
174
|
"W5500": SPI_SCHEMA,
|
175
|
+
"OPENETH": BASE_SCHEMA,
|
174
176
|
},
|
175
177
|
upper=True,
|
176
178
|
),
|
@@ -240,6 +242,9 @@ async def to_code(config):
|
|
240
242
|
if CORE.using_esp_idf:
|
241
243
|
add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True)
|
242
244
|
add_idf_sdkconfig_option("CONFIG_ETH_SPI_ETHERNET_W5500", True)
|
245
|
+
elif config[CONF_TYPE] == "OPENETH":
|
246
|
+
cg.add_define("USE_ETHERNET_OPENETH")
|
247
|
+
add_idf_sdkconfig_option("CONFIG_ETH_USE_OPENETH", True)
|
243
248
|
else:
|
244
249
|
cg.add(var.set_phy_addr(config[CONF_PHY_ADDR]))
|
245
250
|
cg.add(var.set_mdc_pin(config[CONF_MDC_PIN]))
|
@@ -120,6 +120,8 @@ void EthernetComponent::setup() {
|
|
120
120
|
phy_config.reset_gpio_num = this->reset_pin_;
|
121
121
|
|
122
122
|
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
123
|
+
#elif defined(USE_ETHERNET_OPENETH)
|
124
|
+
esp_eth_mac_t *mac = esp_eth_mac_new_openeth(&mac_config);
|
123
125
|
#else
|
124
126
|
phy_config.phy_addr = this->phy_addr_;
|
125
127
|
phy_config.reset_gpio_num = this->power_pin_;
|
@@ -143,6 +145,13 @@ void EthernetComponent::setup() {
|
|
143
145
|
#endif
|
144
146
|
|
145
147
|
switch (this->type_) {
|
148
|
+
#ifdef USE_ETHERNET_OPENETH
|
149
|
+
case ETHERNET_TYPE_OPENETH: {
|
150
|
+
phy_config.autonego_timeout_ms = 1000;
|
151
|
+
this->phy_ = esp_eth_phy_new_dp83848(&phy_config);
|
152
|
+
break;
|
153
|
+
}
|
154
|
+
#endif
|
146
155
|
#if CONFIG_ETH_USE_ESP32_EMAC
|
147
156
|
case ETHERNET_TYPE_LAN8720: {
|
148
157
|
this->phy_ = esp_eth_phy_new_lan87xx(&phy_config);
|
@@ -302,6 +311,10 @@ void EthernetComponent::dump_config() {
|
|
302
311
|
eth_type = "W5500";
|
303
312
|
break;
|
304
313
|
|
314
|
+
case ETHERNET_TYPE_OPENETH:
|
315
|
+
eth_type = "OPENETH";
|
316
|
+
break;
|
317
|
+
|
305
318
|
default:
|
306
319
|
eth_type = "Unknown";
|
307
320
|
break;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from esphome import automation
|
2
2
|
import esphome.codegen as cg
|
3
|
-
from esphome.components import mqtt
|
3
|
+
from esphome.components import mqtt, web_server
|
4
4
|
import esphome.config_validation as cv
|
5
5
|
from esphome.const import (
|
6
6
|
CONF_DEVICE_CLASS,
|
@@ -11,6 +11,7 @@ from esphome.const import (
|
|
11
11
|
CONF_MQTT_ID,
|
12
12
|
CONF_ON_EVENT,
|
13
13
|
CONF_TRIGGER_ID,
|
14
|
+
CONF_WEB_SERVER,
|
14
15
|
DEVICE_CLASS_BUTTON,
|
15
16
|
DEVICE_CLASS_DOORBELL,
|
16
17
|
DEVICE_CLASS_EMPTY,
|
@@ -40,17 +41,21 @@ EventTrigger = event_ns.class_("EventTrigger", automation.Trigger.template())
|
|
40
41
|
|
41
42
|
validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
|
42
43
|
|
43
|
-
EVENT_SCHEMA =
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
44
|
+
EVENT_SCHEMA = (
|
45
|
+
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
|
46
|
+
.extend(cv.MQTT_COMPONENT_SCHEMA)
|
47
|
+
.extend(
|
48
|
+
{
|
49
|
+
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTEventComponent),
|
50
|
+
cv.GenerateID(): cv.declare_id(Event),
|
51
|
+
cv.Optional(CONF_DEVICE_CLASS): validate_device_class,
|
52
|
+
cv.Optional(CONF_ON_EVENT): automation.validate_automation(
|
53
|
+
{
|
54
|
+
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(EventTrigger),
|
55
|
+
}
|
56
|
+
),
|
57
|
+
}
|
58
|
+
)
|
54
59
|
)
|
55
60
|
|
56
61
|
_UNDEF = object()
|
@@ -97,6 +102,9 @@ async def setup_event_core_(var, config, *, event_types: list[str]):
|
|
97
102
|
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
98
103
|
await mqtt.register_mqtt_component(mqtt_, config)
|
99
104
|
|
105
|
+
if web_server_config := config.get(CONF_WEB_SERVER):
|
106
|
+
await web_server.add_entity_config(var, web_server_config)
|
107
|
+
|
100
108
|
|
101
109
|
async def register_event(var, config, *, event_types: list[str]):
|
102
110
|
if not CORE.has_id(config[CONF_ID]):
|
@@ -25,7 +25,7 @@ from esphome.const import (
|
|
25
25
|
CONF_SPEED_LEVEL_STATE_TOPIC,
|
26
26
|
CONF_SPEED_STATE_TOPIC,
|
27
27
|
CONF_TRIGGER_ID,
|
28
|
-
|
28
|
+
CONF_WEB_SERVER,
|
29
29
|
)
|
30
30
|
from esphome.core import CORE, coroutine_with_priority
|
31
31
|
from esphome.cpp_helpers import setup_entity
|
@@ -218,9 +218,8 @@ async def setup_fan_core_(var, config):
|
|
218
218
|
if (speed_command_topic := config.get(CONF_SPEED_COMMAND_TOPIC)) is not None:
|
219
219
|
cg.add(mqtt_.set_custom_speed_command_topic(speed_command_topic))
|
220
220
|
|
221
|
-
if
|
222
|
-
|
223
|
-
web_server.add_entity_to_sorting_list(web_server_, var, config)
|
221
|
+
if web_server_config := config.get(CONF_WEB_SERVER):
|
222
|
+
await web_server.add_entity_config(var, web_server_config)
|
224
223
|
|
225
224
|
for conf in config.get(CONF_ON_STATE, []):
|
226
225
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
File without changes
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#include "gp2y1010au0f.h"
|
2
|
+
#include "esphome/core/hal.h"
|
3
|
+
#include "esphome/core/log.h"
|
4
|
+
|
5
|
+
#include <cinttypes>
|
6
|
+
|
7
|
+
namespace esphome {
|
8
|
+
namespace gp2y1010au0f {
|
9
|
+
|
10
|
+
static const char *const TAG = "gp2y1010au0f";
|
11
|
+
static const float MIN_VOLTAGE = 0.0f;
|
12
|
+
static const float MAX_VOLTAGE = 4.0f;
|
13
|
+
|
14
|
+
void GP2Y1010AU0FSensor::dump_config() {
|
15
|
+
LOG_SENSOR("", "Sharp GP2Y1010AU0F PM2.5 Sensor", this);
|
16
|
+
ESP_LOGCONFIG(TAG, " Sampling duration: %" PRId32 " ms", this->sample_duration_);
|
17
|
+
ESP_LOGCONFIG(TAG, " ADC voltage multiplier: %.3f", this->voltage_multiplier_);
|
18
|
+
LOG_UPDATE_INTERVAL(this);
|
19
|
+
}
|
20
|
+
|
21
|
+
void GP2Y1010AU0FSensor::update() {
|
22
|
+
is_sampling_ = true;
|
23
|
+
|
24
|
+
this->set_timeout("read", this->sample_duration_, [this]() {
|
25
|
+
this->is_sampling_ = false;
|
26
|
+
if (this->num_samples_ == 0)
|
27
|
+
return;
|
28
|
+
|
29
|
+
float mean = this->sample_sum_ / float(this->num_samples_);
|
30
|
+
ESP_LOGD(TAG, "ADC read voltage: %.3f V (mean from %" PRId32 " samples)", mean, this->num_samples_);
|
31
|
+
|
32
|
+
// PM2.5 calculation
|
33
|
+
// ref: https://www.howmuchsnow.com/arduino/airquality/
|
34
|
+
int16_t pm_2_5_value = 170 * mean;
|
35
|
+
this->publish_state(pm_2_5_value);
|
36
|
+
});
|
37
|
+
|
38
|
+
// reset readings
|
39
|
+
this->num_samples_ = 0;
|
40
|
+
this->sample_sum_ = 0.0f;
|
41
|
+
}
|
42
|
+
|
43
|
+
void GP2Y1010AU0FSensor::loop() {
|
44
|
+
if (!this->is_sampling_)
|
45
|
+
return;
|
46
|
+
|
47
|
+
// enable the internal IR LED
|
48
|
+
this->led_output_->turn_on();
|
49
|
+
// wait for the sensor to stabilize
|
50
|
+
delayMicroseconds(this->sample_wait_before_);
|
51
|
+
// perform a single sample
|
52
|
+
float read_voltage = this->source_->sample();
|
53
|
+
// disable the internal IR LED
|
54
|
+
this->led_output_->turn_off();
|
55
|
+
|
56
|
+
if (std::isnan(read_voltage))
|
57
|
+
return;
|
58
|
+
read_voltage = read_voltage * this->voltage_multiplier_ - this->voltage_offset_;
|
59
|
+
if (read_voltage < MIN_VOLTAGE || read_voltage > MAX_VOLTAGE)
|
60
|
+
return;
|
61
|
+
|
62
|
+
this->num_samples_++;
|
63
|
+
this->sample_sum_ += read_voltage;
|
64
|
+
}
|
65
|
+
|
66
|
+
} // namespace gp2y1010au0f
|
67
|
+
} // namespace esphome
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "esphome/core/component.h"
|
4
|
+
#include "esphome/components/sensor/sensor.h"
|
5
|
+
#include "esphome/components/voltage_sampler/voltage_sampler.h"
|
6
|
+
#include "esphome/components/output/binary_output.h"
|
7
|
+
|
8
|
+
namespace esphome {
|
9
|
+
namespace gp2y1010au0f {
|
10
|
+
|
11
|
+
class GP2Y1010AU0FSensor : public sensor::Sensor, public PollingComponent {
|
12
|
+
public:
|
13
|
+
void update() override;
|
14
|
+
void loop() override;
|
15
|
+
void dump_config() override;
|
16
|
+
float get_setup_priority() const override {
|
17
|
+
// after the base sensor has been initialized
|
18
|
+
return setup_priority::DATA - 1.0f;
|
19
|
+
}
|
20
|
+
|
21
|
+
void set_adc_source(voltage_sampler::VoltageSampler *source) { source_ = source; }
|
22
|
+
void set_voltage_refs(float offset, float multiplier) {
|
23
|
+
this->voltage_offset_ = offset;
|
24
|
+
this->voltage_multiplier_ = multiplier;
|
25
|
+
}
|
26
|
+
void set_led_output(output::BinaryOutput *output) { led_output_ = output; }
|
27
|
+
|
28
|
+
protected:
|
29
|
+
// duration in ms of the sampling phase
|
30
|
+
uint32_t sample_duration_ = 100;
|
31
|
+
// duration in us of the wait before sampling
|
32
|
+
// ref: https://global.sharp/products/device/lineup/data/pdf/datasheet/gp2y1010au_appl_e.pdf
|
33
|
+
uint32_t sample_wait_before_ = 280;
|
34
|
+
// duration in us of the wait after sampling
|
35
|
+
// it seems no need to delay on purpose since one ADC sampling takes longer than that (300-400 us on ESP8266)
|
36
|
+
// uint32_t sample_wait_after_ = 40;
|
37
|
+
// the sampling source to read voltage from
|
38
|
+
voltage_sampler::VoltageSampler *source_;
|
39
|
+
// ADC voltage reading offset
|
40
|
+
float voltage_offset_ = 0.0f;
|
41
|
+
// ADC voltage reading multiplier
|
42
|
+
float voltage_multiplier_ = 1.0f;
|
43
|
+
// the binary output to control the sampling LED
|
44
|
+
output::BinaryOutput *led_output_;
|
45
|
+
|
46
|
+
float sample_sum_ = 0.0f;
|
47
|
+
uint32_t num_samples_ = 0;
|
48
|
+
bool is_sampling_ = false;
|
49
|
+
};
|
50
|
+
|
51
|
+
} // namespace gp2y1010au0f
|
52
|
+
} // namespace esphome
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
import esphome.config_validation as cv
|
3
|
+
from esphome.components import sensor, voltage_sampler, output
|
4
|
+
from esphome.const import (
|
5
|
+
CONF_SENSOR,
|
6
|
+
CONF_OUTPUT,
|
7
|
+
DEVICE_CLASS_PM25,
|
8
|
+
STATE_CLASS_MEASUREMENT,
|
9
|
+
UNIT_MICROGRAMS_PER_CUBIC_METER,
|
10
|
+
ICON_CHEMICAL_WEAPON,
|
11
|
+
)
|
12
|
+
|
13
|
+
DEPENDENCIES = ["output"]
|
14
|
+
AUTO_LOAD = ["voltage_sampler"]
|
15
|
+
CODEOWNERS = ["@zry98"]
|
16
|
+
|
17
|
+
CONF_ADC_VOLTAGE_OFFSET = "adc_voltage_offset"
|
18
|
+
CONF_ADC_VOLTAGE_MULTIPLIER = "adc_voltage_multiplier"
|
19
|
+
|
20
|
+
gp2y1010au0f_ns = cg.esphome_ns.namespace("gp2y1010au0f")
|
21
|
+
GP2Y1010AU0FSensor = gp2y1010au0f_ns.class_(
|
22
|
+
"GP2Y1010AU0FSensor", sensor.Sensor, cg.PollingComponent
|
23
|
+
)
|
24
|
+
|
25
|
+
CONFIG_SCHEMA = (
|
26
|
+
sensor.sensor_schema(
|
27
|
+
GP2Y1010AU0FSensor,
|
28
|
+
unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER,
|
29
|
+
accuracy_decimals=0,
|
30
|
+
device_class=DEVICE_CLASS_PM25,
|
31
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
32
|
+
icon=ICON_CHEMICAL_WEAPON,
|
33
|
+
)
|
34
|
+
.extend(
|
35
|
+
{
|
36
|
+
cv.Required(CONF_SENSOR): cv.use_id(voltage_sampler.VoltageSampler),
|
37
|
+
cv.Optional(CONF_ADC_VOLTAGE_OFFSET, default=0.0): cv.float_,
|
38
|
+
cv.Optional(CONF_ADC_VOLTAGE_MULTIPLIER, default=1.0): cv.float_,
|
39
|
+
cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput),
|
40
|
+
}
|
41
|
+
)
|
42
|
+
.extend(cv.polling_component_schema("60s"))
|
43
|
+
)
|
44
|
+
|
45
|
+
|
46
|
+
async def to_code(config):
|
47
|
+
var = await sensor.new_sensor(config)
|
48
|
+
await cg.register_component(var, config)
|
49
|
+
|
50
|
+
# the ADC sensor to read voltage from
|
51
|
+
adc_sensor = await cg.get_variable(config[CONF_SENSOR])
|
52
|
+
cg.add(var.set_adc_source(adc_sensor))
|
53
|
+
cg.add(
|
54
|
+
var.set_voltage_refs(
|
55
|
+
config[CONF_ADC_VOLTAGE_OFFSET], config[CONF_ADC_VOLTAGE_MULTIPLIER]
|
56
|
+
)
|
57
|
+
)
|
58
|
+
|
59
|
+
# the binary output to control the module's internal IR LED
|
60
|
+
led_output = await cg.get_variable(config[CONF_OUTPUT])
|
61
|
+
cg.add(var.set_led_output(led_output))
|
File without changes
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <array>
|
4
|
+
#include <cstdint>
|
5
|
+
#include "esphome/core/hal.h"
|
6
|
+
|
7
|
+
namespace esphome {
|
8
|
+
namespace gpio_expander {
|
9
|
+
|
10
|
+
/// @brief A class to cache the read state of a GPIO expander.
|
11
|
+
template<typename T, T N> class CachedGpioExpander {
|
12
|
+
public:
|
13
|
+
bool digital_read(T pin) {
|
14
|
+
if (!this->read_cache_invalidated_[pin]) {
|
15
|
+
this->read_cache_invalidated_[pin] = true;
|
16
|
+
return this->digital_read_cache(pin);
|
17
|
+
}
|
18
|
+
return this->digital_read_hw(pin);
|
19
|
+
}
|
20
|
+
|
21
|
+
void digital_write(T pin, bool value) { this->digital_write_hw(pin, value); }
|
22
|
+
|
23
|
+
protected:
|
24
|
+
virtual bool digital_read_hw(T pin) = 0;
|
25
|
+
virtual bool digital_read_cache(T pin) = 0;
|
26
|
+
virtual void digital_write_hw(T pin, bool value) = 0;
|
27
|
+
|
28
|
+
void reset_pin_cache_() {
|
29
|
+
for (T i = 0; i < N; i++) {
|
30
|
+
this->read_cache_invalidated_[i] = false;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
std::array<bool, N> read_cache_invalidated_{};
|
35
|
+
};
|
36
|
+
|
37
|
+
} // namespace gpio_expander
|
38
|
+
} // namespace esphome
|
File without changes
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#include "grove_gas_mc_v2.h"
|
2
|
+
#include "esphome/core/hal.h"
|
3
|
+
#include "esphome/core/log.h"
|
4
|
+
|
5
|
+
namespace esphome {
|
6
|
+
namespace grove_gas_mc_v2 {
|
7
|
+
|
8
|
+
static const char *const TAG = "grove_gas_mc_v2";
|
9
|
+
|
10
|
+
// I2C Commands for Grove Gas Multichannel V2 Sensor
|
11
|
+
// Taken from:
|
12
|
+
// https://github.com/Seeed-Studio/Seeed_Arduino_MultiGas/blob/master/src/Multichannel_Gas_GroveGasMultichannelV2.h
|
13
|
+
static const uint8_t GROVE_GAS_MC_V2_HEAT_ON = 0xFE;
|
14
|
+
static const uint8_t GROVE_GAS_MC_V2_HEAT_OFF = 0xFF;
|
15
|
+
static const uint8_t GROVE_GAS_MC_V2_READ_GM102B = 0x01;
|
16
|
+
static const uint8_t GROVE_GAS_MC_V2_READ_GM302B = 0x03;
|
17
|
+
static const uint8_t GROVE_GAS_MC_V2_READ_GM502B = 0x05;
|
18
|
+
static const uint8_t GROVE_GAS_MC_V2_READ_GM702B = 0x07;
|
19
|
+
|
20
|
+
bool GroveGasMultichannelV2Component::read_sensor_(uint8_t address, sensor::Sensor *sensor) {
|
21
|
+
if (sensor == nullptr) {
|
22
|
+
return true;
|
23
|
+
}
|
24
|
+
uint32_t value = 0;
|
25
|
+
if (!this->read_bytes(address, (uint8_t *) &value, 4)) {
|
26
|
+
ESP_LOGW(TAG, "Reading Grove Gas Sensor data failed!");
|
27
|
+
this->error_code_ = COMMUNICATION_FAILED;
|
28
|
+
this->status_set_warning();
|
29
|
+
return false;
|
30
|
+
}
|
31
|
+
sensor->publish_state(value);
|
32
|
+
return true;
|
33
|
+
}
|
34
|
+
|
35
|
+
void GroveGasMultichannelV2Component::setup() {
|
36
|
+
ESP_LOGCONFIG(TAG, "Setting up Grove Multichannel Gas Sensor V2...");
|
37
|
+
|
38
|
+
// Before reading sensor values, must preheat sensor
|
39
|
+
if (!(this->write_bytes(GROVE_GAS_MC_V2_HEAT_ON, {}))) {
|
40
|
+
this->mark_failed();
|
41
|
+
this->error_code_ = APP_START_FAILED;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
void GroveGasMultichannelV2Component::update() {
|
46
|
+
// Read from each of the gas sensors
|
47
|
+
if (!this->read_sensor_(GROVE_GAS_MC_V2_READ_GM102B, this->nitrogen_dioxide_sensor_))
|
48
|
+
return;
|
49
|
+
if (!this->read_sensor_(GROVE_GAS_MC_V2_READ_GM302B, this->ethanol_sensor_))
|
50
|
+
return;
|
51
|
+
if (!this->read_sensor_(GROVE_GAS_MC_V2_READ_GM502B, this->tvoc_sensor_))
|
52
|
+
return;
|
53
|
+
if (!this->read_sensor_(GROVE_GAS_MC_V2_READ_GM702B, this->carbon_monoxide_sensor_))
|
54
|
+
return;
|
55
|
+
|
56
|
+
this->status_clear_warning();
|
57
|
+
}
|
58
|
+
|
59
|
+
void GroveGasMultichannelV2Component::dump_config() {
|
60
|
+
ESP_LOGCONFIG(TAG, "Grove Multichannel Gas Sensor V2");
|
61
|
+
LOG_I2C_DEVICE(this)
|
62
|
+
LOG_UPDATE_INTERVAL(this)
|
63
|
+
LOG_SENSOR(" ", "Nitrogen Dioxide", this->nitrogen_dioxide_sensor_)
|
64
|
+
LOG_SENSOR(" ", "Ethanol", this->ethanol_sensor_)
|
65
|
+
LOG_SENSOR(" ", "Carbon Monoxide", this->carbon_monoxide_sensor_)
|
66
|
+
LOG_SENSOR(" ", "TVOC", this->tvoc_sensor_)
|
67
|
+
|
68
|
+
if (this->is_failed()) {
|
69
|
+
switch (this->error_code_) {
|
70
|
+
case COMMUNICATION_FAILED:
|
71
|
+
ESP_LOGW(TAG, "Communication failed! Is the sensor connected?");
|
72
|
+
break;
|
73
|
+
case APP_INVALID:
|
74
|
+
ESP_LOGW(TAG, "Sensor reported invalid APP installed.");
|
75
|
+
break;
|
76
|
+
case APP_START_FAILED:
|
77
|
+
ESP_LOGW(TAG, "Sensor reported APP start failed.");
|
78
|
+
break;
|
79
|
+
case UNKNOWN:
|
80
|
+
default:
|
81
|
+
ESP_LOGW(TAG, "Unknown setup error!");
|
82
|
+
break;
|
83
|
+
}
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
} // namespace grove_gas_mc_v2
|
88
|
+
} // namespace esphome
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "esphome/components/i2c/i2c.h"
|
4
|
+
#include "esphome/components/sensor/sensor.h"
|
5
|
+
#include "esphome/core/component.h"
|
6
|
+
#include "esphome/core/preferences.h"
|
7
|
+
|
8
|
+
namespace esphome {
|
9
|
+
namespace grove_gas_mc_v2 {
|
10
|
+
|
11
|
+
class GroveGasMultichannelV2Component : public PollingComponent, public i2c::I2CDevice {
|
12
|
+
SUB_SENSOR(tvoc)
|
13
|
+
SUB_SENSOR(carbon_monoxide)
|
14
|
+
SUB_SENSOR(nitrogen_dioxide)
|
15
|
+
SUB_SENSOR(ethanol)
|
16
|
+
|
17
|
+
public:
|
18
|
+
/// Setup the sensor and test for a connection.
|
19
|
+
void setup() override;
|
20
|
+
/// Schedule temperature+pressure readings.
|
21
|
+
void update() override;
|
22
|
+
|
23
|
+
void dump_config() override;
|
24
|
+
|
25
|
+
float get_setup_priority() const override { return setup_priority::DATA; }
|
26
|
+
|
27
|
+
protected:
|
28
|
+
enum ErrorCode {
|
29
|
+
UNKNOWN,
|
30
|
+
COMMUNICATION_FAILED,
|
31
|
+
APP_INVALID,
|
32
|
+
APP_START_FAILED,
|
33
|
+
} error_code_{UNKNOWN};
|
34
|
+
|
35
|
+
bool read_sensor_(uint8_t address, sensor::Sensor *sensor);
|
36
|
+
};
|
37
|
+
|
38
|
+
} // namespace grove_gas_mc_v2
|
39
|
+
} // namespace esphome
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
from esphome.components import i2c, sensor
|
3
|
+
import esphome.config_validation as cv
|
4
|
+
from esphome.const import (
|
5
|
+
CONF_CARBON_MONOXIDE,
|
6
|
+
CONF_ETHANOL,
|
7
|
+
CONF_ID,
|
8
|
+
CONF_NITROGEN_DIOXIDE,
|
9
|
+
CONF_TVOC,
|
10
|
+
DEVICE_CLASS_CARBON_MONOXIDE,
|
11
|
+
DEVICE_CLASS_NITROGEN_DIOXIDE,
|
12
|
+
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
|
13
|
+
ICON_AIR_FILTER,
|
14
|
+
ICON_FLASK_ROUND_BOTTOM,
|
15
|
+
ICON_GAS_CYLINDER,
|
16
|
+
ICON_MOLECULE_CO,
|
17
|
+
STATE_CLASS_MEASUREMENT,
|
18
|
+
UNIT_MICROGRAMS_PER_CUBIC_METER,
|
19
|
+
UNIT_PARTS_PER_MILLION,
|
20
|
+
)
|
21
|
+
|
22
|
+
CODEOWNERS = ["@YorkshireIoT"]
|
23
|
+
DEPENDENCIES = ["i2c"]
|
24
|
+
|
25
|
+
grove_gas_mc_v2_ns = cg.esphome_ns.namespace("grove_gas_mc_v2")
|
26
|
+
|
27
|
+
GroveGasMultichannelV2Component = grove_gas_mc_v2_ns.class_(
|
28
|
+
"GroveGasMultichannelV2Component", cg.PollingComponent, i2c.I2CDevice
|
29
|
+
)
|
30
|
+
|
31
|
+
CONFIG_SCHEMA = (
|
32
|
+
cv.Schema(
|
33
|
+
{
|
34
|
+
cv.GenerateID(): cv.declare_id(GroveGasMultichannelV2Component),
|
35
|
+
cv.Optional(CONF_TVOC): sensor.sensor_schema(
|
36
|
+
unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER,
|
37
|
+
icon=ICON_AIR_FILTER,
|
38
|
+
accuracy_decimals=0,
|
39
|
+
device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
|
40
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
41
|
+
),
|
42
|
+
cv.Optional(CONF_CARBON_MONOXIDE): sensor.sensor_schema(
|
43
|
+
unit_of_measurement=UNIT_PARTS_PER_MILLION,
|
44
|
+
icon=ICON_MOLECULE_CO,
|
45
|
+
accuracy_decimals=0,
|
46
|
+
device_class=DEVICE_CLASS_CARBON_MONOXIDE,
|
47
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
48
|
+
),
|
49
|
+
cv.Optional(CONF_NITROGEN_DIOXIDE): sensor.sensor_schema(
|
50
|
+
unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER,
|
51
|
+
icon=ICON_GAS_CYLINDER,
|
52
|
+
accuracy_decimals=0,
|
53
|
+
device_class=DEVICE_CLASS_NITROGEN_DIOXIDE,
|
54
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
55
|
+
),
|
56
|
+
cv.Optional(CONF_ETHANOL): sensor.sensor_schema(
|
57
|
+
unit_of_measurement=UNIT_PARTS_PER_MILLION,
|
58
|
+
icon=ICON_FLASK_ROUND_BOTTOM,
|
59
|
+
accuracy_decimals=0,
|
60
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
61
|
+
),
|
62
|
+
}
|
63
|
+
)
|
64
|
+
.extend(cv.polling_component_schema("60s"))
|
65
|
+
.extend(i2c.i2c_device_schema(0x08))
|
66
|
+
)
|
67
|
+
|
68
|
+
|
69
|
+
async def to_code(config):
|
70
|
+
var = cg.new_Pvariable(config[CONF_ID])
|
71
|
+
await cg.register_component(var, config)
|
72
|
+
await i2c.register_i2c_device(var, config)
|
73
|
+
|
74
|
+
for key in [CONF_TVOC, CONF_CARBON_MONOXIDE, CONF_NITROGEN_DIOXIDE, CONF_ETHANOL]:
|
75
|
+
if sensor_config := config.get(key):
|
76
|
+
sensor_ = await sensor.new_sensor(sensor_config)
|
77
|
+
cg.add(getattr(var, f"set_{key}_sensor")(sensor_))
|
@@ -114,7 +114,6 @@ SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS = {
|
|
114
114
|
SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS = {
|
115
115
|
"AWAY": ClimatePreset.CLIMATE_PRESET_AWAY,
|
116
116
|
"BOOST": ClimatePreset.CLIMATE_PRESET_BOOST,
|
117
|
-
"ECO": ClimatePreset.CLIMATE_PRESET_ECO,
|
118
117
|
"SLEEP": ClimatePreset.CLIMATE_PRESET_SLEEP,
|
119
118
|
}
|
120
119
|
|
@@ -240,7 +239,9 @@ CONFIG_SCHEMA = cv.All(
|
|
240
239
|
): cv.ensure_list(
|
241
240
|
cv.enum(SUPPORTED_HON_CONTROL_METHODS, upper=True)
|
242
241
|
),
|
243
|
-
cv.Optional(CONF_BEEPER
|
242
|
+
cv.Optional(CONF_BEEPER): cv.invalid(
|
243
|
+
f"The {CONF_BEEPER} option is deprecated, use beeper_on/beeper_off actions or beeper switch for a haier platform instead"
|
244
|
+
),
|
244
245
|
cv.Optional(
|
245
246
|
CONF_CONTROL_PACKET_SIZE, default=PROTOCOL_CONTROL_PACKET_SIZE
|
246
247
|
): cv.int_range(min=PROTOCOL_CONTROL_PACKET_SIZE, max=50),
|
@@ -254,7 +255,7 @@ CONFIG_SCHEMA = cv.All(
|
|
254
255
|
): cv.int_range(min=PROTOCOL_STATUS_MESSAGE_HEADER_SIZE),
|
255
256
|
cv.Optional(
|
256
257
|
CONF_SUPPORTED_PRESETS,
|
257
|
-
default=["BOOST", "
|
258
|
+
default=["BOOST", "SLEEP"], # No AWAY by default
|
258
259
|
): cv.ensure_list(
|
259
260
|
cv.enum(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS, upper=True)
|
260
261
|
),
|