esphome 2024.7.2__py3-none-any.whl → 2024.8.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 +15 -81
- esphome/automation.py +1 -1
- esphome/codegen.py +53 -53
- esphome/components/ade7953/sensor.py +1 -1
- esphome/components/ade7953_spi/ade7953_spi.cpp +1 -1
- esphome/components/airthings_wave_plus/airthings_wave_plus.cpp +5 -2
- esphome/components/airthings_wave_plus/airthings_wave_plus.h +2 -0
- esphome/components/airthings_wave_plus/sensor.py +12 -0
- esphome/components/alarm_control_panel/__init__.py +75 -66
- esphome/components/apds9306/__init__.py +4 -0
- esphome/components/apds9306/apds9306.cpp +151 -0
- esphome/components/apds9306/apds9306.h +66 -0
- esphome/components/apds9306/sensor.py +95 -0
- esphome/components/api/__init__.py +80 -52
- esphome/components/api/api_connection.cpp +14 -1
- esphome/components/api/api_pb2.cpp +33 -4
- esphome/components/api/api_pb2.h +8 -1
- esphome/components/api/api_server.cpp +10 -0
- esphome/components/api/api_server.h +3 -0
- esphome/components/atm90e32/__init__.py +7 -0
- esphome/components/atm90e32/atm90e32.cpp +68 -16
- esphome/components/atm90e32/atm90e32.h +20 -7
- esphome/components/atm90e32/atm90e32_reg.h +2 -0
- esphome/components/atm90e32/button/__init__.py +43 -0
- esphome/components/atm90e32/button/atm90e32_button.cpp +20 -0
- esphome/components/atm90e32/button/atm90e32_button.h +27 -0
- esphome/components/atm90e32/sensor.py +15 -11
- esphome/components/bedjet/bedjet_codec.h +1 -1
- esphome/components/binary/light/binary_light_output.h +3 -2
- esphome/components/binary_sensor/__init__.py +5 -5
- esphome/components/ble_client/__init__.py +3 -3
- esphome/components/ble_client/output/__init__.py +1 -1
- esphome/components/ble_client/sensor/__init__.py +4 -3
- esphome/components/ble_client/switch/__init__.py +2 -1
- esphome/components/ble_client/text_sensor/__init__.py +4 -3
- esphome/components/ble_presence/binary_sensor.py +3 -3
- esphome/components/ble_rssi/sensor.py +2 -2
- esphome/components/ble_scanner/text_sensor.py +1 -1
- esphome/components/bluetooth_proxy/__init__.py +3 -3
- esphome/components/bme68x_bsec2/__init__.py +196 -0
- esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +523 -0
- esphome/components/bme68x_bsec2/bme68x_bsec2.h +163 -0
- esphome/components/bme68x_bsec2/sensor.py +130 -0
- esphome/components/bme68x_bsec2/text_sensor.py +33 -0
- esphome/components/bme68x_bsec2_i2c/__init__.py +28 -0
- esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.cpp +53 -0
- esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.h +28 -0
- esphome/components/bmp3xx/sensor.py +1 -1
- esphome/components/button/__init__.py +4 -4
- esphome/components/climate/__init__.py +5 -5
- esphome/components/climate/climate.h +1 -1
- esphome/components/cover/__init__.py +8 -8
- esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +11 -7
- esphome/components/cst226/touchscreen/cst226_touchscreen.h +1 -1
- esphome/components/datetime/__init__.py +11 -13
- esphome/components/demo/demo_sensor.h +3 -2
- esphome/components/display/display.cpp +31 -0
- esphome/components/display/display.h +3 -0
- esphome/components/display_menu_base/__init__.py +14 -13
- esphome/components/ens160/sensor.py +1 -1
- esphome/components/esp32/__init__.py +22 -10
- esphome/components/esp32/boards.py +1 -1
- esphome/components/esp32/gpio.py +12 -13
- esphome/components/esp32/gpio_esp32.py +1 -2
- esphome/components/esp32/gpio_esp32_c2.py +1 -2
- esphome/components/esp32/gpio_esp32_c3.py +1 -5
- esphome/components/esp32/gpio_esp32_c6.py +1 -2
- esphome/components/esp32/gpio_esp32_h2.py +1 -2
- esphome/components/esp32/gpio_esp32_s2.py +1 -2
- esphome/components/esp32/gpio_esp32_s3.py +1 -6
- esphome/components/esp32_ble/__init__.py +20 -3
- esphome/components/esp32_ble/ble.cpp +9 -1
- esphome/components/esp32_ble/ble.h +9 -0
- esphome/components/esp32_ble/ble_advertising.cpp +42 -9
- esphome/components/esp32_ble/ble_advertising.h +21 -1
- esphome/components/esp32_ble_beacon/__init__.py +17 -7
- esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +45 -113
- esphome/components/esp32_ble_beacon/esp32_ble_beacon.h +17 -19
- esphome/components/esp32_ble_client/__init__.py +0 -1
- esphome/components/esp32_ble_server/__init__.py +2 -3
- esphome/components/esp32_ble_tracker/__init__.py +2 -2
- esphome/components/esp32_improv/__init__.py +2 -4
- esphome/components/ethernet/__init__.py +17 -17
- esphome/components/ethernet_info/text_sensor.py +2 -2
- esphome/components/event/__init__.py +5 -5
- esphome/components/fan/__init__.py +14 -14
- esphome/components/fan/fan.cpp +2 -2
- esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
- esphome/components/fingerprint_grow/fingerprint_grow.h +1 -1
- esphome/components/graphical_display_menu/__init__.py +11 -8
- esphome/components/haier/haier_base.h +2 -2
- esphome/components/homeassistant/__init__.py +8 -1
- esphome/components/homeassistant/number/__init__.py +33 -0
- esphome/components/homeassistant/number/homeassistant_number.cpp +100 -0
- esphome/components/homeassistant/number/homeassistant_number.h +31 -0
- esphome/components/homeassistant/switch/__init__.py +30 -0
- esphome/components/homeassistant/switch/homeassistant_switch.cpp +59 -0
- esphome/components/homeassistant/switch/homeassistant_switch.h +22 -0
- esphome/components/host/__init__.py +3 -7
- esphome/components/http_request/__init__.py +12 -1
- esphome/components/http_request/http_request_arduino.cpp +2 -2
- esphome/components/http_request/http_request_idf.cpp +11 -2
- esphome/components/http_request/http_request_idf.h +10 -0
- esphome/components/http_request/ota/ota_http_request.cpp +1 -1
- esphome/components/http_request/update/http_request_update.cpp +2 -2
- esphome/components/http_request/update/http_request_update.h +2 -1
- esphome/components/hx711/hx711.cpp +10 -1
- esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +1 -1
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +11 -2
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +2 -0
- esphome/components/ili9xxx/ili9xxx_defines.h +3 -1
- esphome/components/ili9xxx/ili9xxx_display.cpp +9 -22
- esphome/components/ili9xxx/ili9xxx_display.h +5 -7
- esphome/components/ili9xxx/ili9xxx_init.h +4 -4
- esphome/components/improv_base/__init__.py +2 -3
- esphome/components/improv_serial/__init__.py +4 -10
- esphome/components/improv_serial/improv_serial_component.cpp +4 -0
- esphome/components/jsn_sr04t/jsn_sr04t.cpp +18 -1
- esphome/components/jsn_sr04t/jsn_sr04t.h +7 -1
- esphome/components/jsn_sr04t/sensor.py +13 -0
- esphome/components/kalman_combinator/sensor.py +1 -1
- esphome/components/light/__init__.py +16 -15
- esphome/components/light/addressable_light_effect.h +12 -8
- esphome/components/light/automation.h +16 -1
- esphome/components/light/automation.py +21 -0
- esphome/components/light/base_light_effects.h +5 -5
- esphome/components/light/esp_color_correction.h +8 -8
- esphome/components/light/types.py +7 -0
- esphome/components/lock/__init__.py +3 -3
- esphome/components/logger/__init__.py +15 -18
- esphome/components/lvgl/__init__.py +346 -0
- esphome/components/lvgl/automation.py +226 -0
- esphome/components/lvgl/binary_sensor/__init__.py +43 -0
- esphome/components/lvgl/defines.py +508 -0
- esphome/components/lvgl/encoders.py +77 -0
- esphome/components/lvgl/font.cpp +76 -0
- esphome/components/lvgl/helpers.py +49 -0
- esphome/components/lvgl/light/__init__.py +32 -0
- esphome/components/lvgl/light/lvgl_light.h +48 -0
- esphome/components/lvgl/lv_validation.py +303 -0
- esphome/components/lvgl/lvcode.py +349 -0
- esphome/components/lvgl/lvgl_esphome.cpp +407 -0
- esphome/components/lvgl/lvgl_esphome.h +274 -0
- esphome/components/lvgl/lvgl_hal.h +21 -0
- esphome/components/lvgl/number/__init__.py +66 -0
- esphome/components/lvgl/number/lvgl_number.h +34 -0
- esphome/components/lvgl/schemas.py +436 -0
- esphome/components/lvgl/select/__init__.py +55 -0
- esphome/components/lvgl/select/lvgl_select.h +62 -0
- esphome/components/lvgl/sensor/__init__.py +47 -0
- esphome/components/lvgl/styles.py +58 -0
- esphome/components/lvgl/switch/__init__.py +56 -0
- esphome/components/lvgl/switch/lvgl_switch.h +34 -0
- esphome/components/lvgl/text/__init__.py +50 -0
- esphome/components/lvgl/text/lvgl_text.h +34 -0
- esphome/components/lvgl/text_sensor/__init__.py +42 -0
- esphome/components/lvgl/touchscreens.py +45 -0
- esphome/components/lvgl/trigger.py +74 -0
- esphome/components/lvgl/types.py +191 -0
- esphome/components/lvgl/widgets/__init__.py +419 -0
- esphome/components/lvgl/widgets/animimg.py +117 -0
- esphome/components/lvgl/widgets/arc.py +78 -0
- esphome/components/lvgl/widgets/button.py +20 -0
- esphome/components/lvgl/widgets/buttonmatrix.py +275 -0
- esphome/components/lvgl/widgets/checkbox.py +27 -0
- esphome/components/lvgl/widgets/dropdown.py +76 -0
- esphome/components/lvgl/widgets/img.py +85 -0
- esphome/components/lvgl/widgets/keyboard.py +49 -0
- esphome/components/lvgl/widgets/label.py +42 -0
- esphome/components/lvgl/widgets/led.py +29 -0
- esphome/components/lvgl/widgets/line.py +50 -0
- esphome/components/lvgl/widgets/lv_bar.py +55 -0
- esphome/components/lvgl/widgets/meter.py +302 -0
- esphome/components/lvgl/widgets/msgbox.py +134 -0
- esphome/components/lvgl/widgets/obj.py +28 -0
- esphome/components/lvgl/widgets/page.py +113 -0
- esphome/components/lvgl/widgets/roller.py +77 -0
- esphome/components/lvgl/widgets/slider.py +63 -0
- esphome/components/lvgl/widgets/spinbox.py +178 -0
- esphome/components/lvgl/widgets/spinner.py +43 -0
- esphome/components/lvgl/widgets/switch.py +20 -0
- esphome/components/lvgl/widgets/tabview.py +114 -0
- esphome/components/lvgl/widgets/textarea.py +66 -0
- esphome/components/lvgl/widgets/tileview.py +128 -0
- esphome/components/m5stack_8angle/__init__.py +33 -0
- esphome/components/m5stack_8angle/binary_sensor/__init__.py +30 -0
- esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp +17 -0
- esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.h +19 -0
- esphome/components/m5stack_8angle/light/__init__.py +31 -0
- esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +45 -0
- esphome/components/m5stack_8angle/light/m5stack_8angle_light.h +37 -0
- esphome/components/m5stack_8angle/m5stack_8angle.cpp +74 -0
- esphome/components/m5stack_8angle/m5stack_8angle.h +34 -0
- esphome/components/m5stack_8angle/sensor/__init__.py +66 -0
- esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp +24 -0
- esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.h +27 -0
- esphome/components/matrix_keypad/matrix_keypad.cpp +2 -0
- esphome/components/max31856/sensor.py +5 -5
- esphome/components/media_player/__init__.py +3 -5
- esphome/components/media_player/automation.h +31 -27
- esphome/components/micro_wake_word/__init__.py +20 -25
- esphome/components/micro_wake_word/streaming_model.cpp +6 -4
- esphome/components/microphone/microphone.h +4 -1
- esphome/components/mitsubishi/mitsubishi.cpp +7 -1
- esphome/components/modbus_controller/__init__.py +26 -2
- esphome/components/modbus_controller/automation.h +19 -0
- esphome/components/modbus_controller/const.py +1 -0
- esphome/components/modbus_controller/modbus_controller.cpp +8 -0
- esphome/components/modbus_controller/modbus_controller.h +3 -0
- esphome/components/mqtt/__init__.py +20 -9
- esphome/components/mqtt/mqtt_alarm_control_panel.cpp +128 -0
- esphome/components/mqtt/mqtt_alarm_control_panel.h +39 -0
- esphome/components/mqtt/mqtt_backend.h +3 -1
- esphome/components/mqtt/mqtt_backend_esp32.cpp +4 -1
- esphome/components/mqtt/mqtt_backend_esp32.h +3 -1
- esphome/components/mqtt/mqtt_backend_esp8266.h +3 -1
- esphome/components/mqtt/mqtt_backend_libretiny.h +3 -1
- esphome/components/mqtt/mqtt_client.cpp +16 -3
- esphome/components/mqtt/mqtt_client.h +5 -1
- esphome/components/mqtt/mqtt_component.cpp +32 -4
- esphome/components/mqtt/mqtt_const.h +2 -0
- esphome/components/network/__init__.py +15 -12
- esphome/components/network/ip_address.h +3 -0
- esphome/components/network/util.cpp +2 -1
- esphome/components/network/util.h +3 -1
- esphome/components/nextion/base_component.py +5 -8
- esphome/components/number/__init__.py +7 -8
- esphome/components/online_image/__init__.py +167 -0
- esphome/components/online_image/image_decoder.cpp +44 -0
- esphome/components/online_image/image_decoder.h +112 -0
- esphome/components/online_image/online_image.cpp +283 -0
- esphome/components/online_image/online_image.h +195 -0
- esphome/components/online_image/png_image.cpp +68 -0
- esphome/components/online_image/png_image.h +33 -0
- esphome/components/ota/__init__.py +8 -4
- esphome/components/pid/pid_climate.h +2 -0
- esphome/components/pmwcs3/pmwcs3.cpp +31 -30
- esphome/components/remote_base/pronto_protocol.cpp +0 -3
- esphome/components/remote_transmitter/remote_transmitter.h +1 -1
- esphome/components/rgbct/rgbct_light_output.h +3 -2
- esphome/components/rgbw/rgbw_light_output.h +3 -2
- esphome/components/rgbww/rgbww_light_output.h +3 -2
- esphome/components/rp2040_pio_led_strip/led_strip.cpp +31 -5
- esphome/components/rp2040_pio_led_strip/led_strip.h +5 -0
- esphome/components/rtttl/rtttl.cpp +108 -21
- esphome/components/rtttl/rtttl.h +15 -6
- esphome/components/select/__init__.py +7 -7
- esphome/components/sensor/__init__.py +29 -10
- esphome/components/sensor/filter.cpp +8 -0
- esphome/components/sensor/filter.h +9 -0
- esphome/components/sml/sml_parser.cpp +48 -22
- esphome/components/socket/socket.cpp +11 -14
- esphome/components/speaker/__init__.py +14 -5
- esphome/components/speaker/automation.h +10 -0
- esphome/components/speaker/speaker.h +9 -0
- esphome/components/spi/spi.cpp +0 -6
- esphome/components/spi/spi.h +2 -19
- esphome/components/spi_led_strip/spi_led_strip.h +5 -4
- esphome/components/sprinkler/sprinkler.cpp +2 -2
- esphome/components/sprinkler/sprinkler.h +1 -1
- esphome/components/switch/__init__.py +3 -3
- esphome/components/text/__init__.py +5 -5
- esphome/components/text_sensor/__init__.py +7 -7
- esphome/components/time/__init__.py +8 -8
- esphome/components/touchscreen/binary_sensor/__init__.py +24 -10
- esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp +3 -2
- esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h +4 -2
- esphome/components/uart/uart_component_host.cpp +6 -2
- esphome/components/update/__init__.py +33 -15
- esphome/components/update/automation.h +23 -0
- esphome/components/update/update_entity.h +3 -1
- esphome/components/valve/__init__.py +3 -3
- esphome/components/voice_assistant/__init__.py +7 -8
- esphome/components/wake_on_lan/wake_on_lan.cpp +2 -0
- esphome/components/wake_on_lan/wake_on_lan.h +3 -1
- esphome/components/watchdog/__init__.py +1 -0
- esphome/components/{http_request → watchdog}/watchdog.cpp +0 -2
- esphome/components/{http_request → watchdog}/watchdog.h +0 -2
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +5 -5
- esphome/components/web_server/server_index_v3.h +3615 -3603
- esphome/components/web_server/web_server.cpp +0 -209
- esphome/components/web_server/web_server.h +1 -1
- esphome/components/web_server/web_server_v1.cpp +217 -0
- esphome/components/web_server_base/web_server_base.h +1 -0
- esphome/components/wifi/__init__.py +15 -14
- esphome/components/wifi/wifi_component.cpp +2 -0
- esphome/components/wifi/wifi_component.h +7 -1
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +5 -2
- esphome/components/wifi/wifi_component_esp8266.cpp +2 -0
- esphome/components/wifi/wifi_component_esp_idf.cpp +43 -7
- esphome/components/wifi/wifi_component_libretiny.cpp +2 -0
- esphome/components/wifi/wifi_component_pico_w.cpp +2 -0
- esphome/components/wifi/wpa2_eap.py +6 -7
- esphome/components/wifi_info/text_sensor.py +3 -3
- esphome/components/wifi_info/wifi_info_text_sensor.cpp +2 -0
- esphome/components/wifi_info/wifi_info_text_sensor.h +2 -0
- esphome/components/wifi_signal/sensor.py +1 -1
- esphome/components/wifi_signal/wifi_signal_sensor.cpp +2 -0
- esphome/components/wifi_signal/wifi_signal_sensor.h +2 -1
- esphome/components/xiaomi_ble/xiaomi_ble.cpp +20 -3
- esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
- esphome/components/xiaomi_lywsd02mmc/__init__.py +0 -0
- esphome/components/xiaomi_lywsd02mmc/sensor.py +77 -0
- esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.cpp +73 -0
- esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +37 -0
- esphome/config.py +17 -19
- esphome/config_validation.py +55 -23
- esphome/const.py +25 -9
- esphome/core/__init__.py +17 -14
- esphome/core/application.h +42 -21
- esphome/core/automation.h +5 -3
- esphome/core/base_automation.h +3 -2
- esphome/core/bytebuffer.cpp +134 -0
- esphome/core/bytebuffer.h +96 -0
- esphome/core/color.h +24 -16
- esphome/core/config.py +3 -3
- esphome/core/defines.h +14 -1
- esphome/core/entity_base.h +2 -2
- esphome/core/entity_helpers.py +1 -2
- esphome/core/gpio.h +0 -18
- esphome/core/helpers.h +1 -1
- esphome/core/optional.h +15 -16
- esphome/coroutine.py +1 -1
- esphome/cpp_generator.py +1 -1
- esphome/cpp_helpers.py +3 -5
- esphome/dashboard/core.py +3 -3
- esphome/dashboard/dashboard.py +3 -3
- esphome/dashboard/entries.py +1 -1
- esphome/dashboard/util/file.py +1 -1
- esphome/dashboard/web_server.py +3 -3
- esphome/external_files.py +5 -3
- esphome/final_validate.py +2 -2
- esphome/git.py +4 -4
- esphome/helpers.py +5 -5
- esphome/loader.py +15 -10
- esphome/mqtt.py +4 -8
- esphome/pins.py +6 -6
- esphome/platformio_api.py +5 -5
- esphome/storage_json.py +2 -1
- esphome/types.py +1 -1
- esphome/util.py +2 -3
- esphome/voluptuous_schema.py +1 -0
- esphome/vscode.py +5 -4
- esphome/wizard.py +1 -1
- esphome/writer.py +7 -7
- esphome/yaml_util.py +3 -3
- esphome/zeroconf.py +1 -1
- {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/METADATA +3 -3
- {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/RECORD +353 -247
- {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/LICENSE +0 -0
- {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/WHEEL +0 -0
- {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/entry_points.txt +0 -0
- {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,523 @@
|
|
1
|
+
#include "esphome/core/defines.h"
|
2
|
+
#include "esphome/core/helpers.h"
|
3
|
+
#include "esphome/core/log.h"
|
4
|
+
|
5
|
+
#ifdef USE_BSEC2
|
6
|
+
#include "bme68x_bsec2.h"
|
7
|
+
|
8
|
+
#include <string>
|
9
|
+
|
10
|
+
namespace esphome {
|
11
|
+
namespace bme68x_bsec2 {
|
12
|
+
|
13
|
+
#define BME68X_BSEC2_ALGORITHM_OUTPUT_LOG(a) (a == ALGORITHM_OUTPUT_CLASSIFICATION ? "Classification" : "Regression")
|
14
|
+
#define BME68X_BSEC2_OPERATING_AGE_LOG(o) (o == OPERATING_AGE_4D ? "4 days" : "28 days")
|
15
|
+
#define BME68X_BSEC2_SAMPLE_RATE_LOG(r) (r == SAMPLE_RATE_DEFAULT ? "Default" : (r == SAMPLE_RATE_ULP ? "ULP" : "LP"))
|
16
|
+
#define BME68X_BSEC2_VOLTAGE_LOG(v) (v == VOLTAGE_3_3V ? "3.3V" : "1.8V")
|
17
|
+
|
18
|
+
static const char *const TAG = "bme68x_bsec2.sensor";
|
19
|
+
|
20
|
+
static const std::string IAQ_ACCURACY_STATES[4] = {"Stabilizing", "Uncertain", "Calibrating", "Calibrated"};
|
21
|
+
|
22
|
+
void BME68xBSEC2Component::setup() {
|
23
|
+
ESP_LOGCONFIG(TAG, "Setting up BME68X via BSEC2...");
|
24
|
+
|
25
|
+
this->bsec_status_ = bsec_init_m(&this->bsec_instance_);
|
26
|
+
if (this->bsec_status_ != BSEC_OK) {
|
27
|
+
this->mark_failed();
|
28
|
+
ESP_LOGE(TAG, "bsec_init_m failed: status %d", this->bsec_status_);
|
29
|
+
return;
|
30
|
+
}
|
31
|
+
|
32
|
+
bsec_get_version_m(&this->bsec_instance_, &this->version_);
|
33
|
+
|
34
|
+
this->bme68x_status_ = bme68x_init(&this->bme68x_);
|
35
|
+
if (this->bme68x_status_ != BME68X_OK) {
|
36
|
+
this->mark_failed();
|
37
|
+
ESP_LOGE(TAG, "bme68x_init failed: status %d", this->bme68x_status_);
|
38
|
+
return;
|
39
|
+
}
|
40
|
+
if (this->bsec2_configuration_ != nullptr && this->bsec2_configuration_length_) {
|
41
|
+
this->set_config_(this->bsec2_configuration_, this->bsec2_configuration_length_);
|
42
|
+
if (this->bsec_status_ != BSEC_OK) {
|
43
|
+
this->mark_failed();
|
44
|
+
ESP_LOGE(TAG, "bsec_set_configuration_m failed: status %d", this->bsec_status_);
|
45
|
+
return;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
this->update_subscription_();
|
50
|
+
if (this->bsec_status_ != BSEC_OK) {
|
51
|
+
this->mark_failed();
|
52
|
+
ESP_LOGE(TAG, "bsec_update_subscription_m failed: status %d", this->bsec_status_);
|
53
|
+
return;
|
54
|
+
}
|
55
|
+
|
56
|
+
this->load_state_();
|
57
|
+
}
|
58
|
+
|
59
|
+
void BME68xBSEC2Component::dump_config() {
|
60
|
+
ESP_LOGCONFIG(TAG, "BME68X via BSEC2:");
|
61
|
+
|
62
|
+
ESP_LOGCONFIG(TAG, " BSEC2 version: %d.%d.%d.%d", this->version_.major, this->version_.minor,
|
63
|
+
this->version_.major_bugfix, this->version_.minor_bugfix);
|
64
|
+
|
65
|
+
ESP_LOGCONFIG(TAG, " BSEC2 configuration blob:");
|
66
|
+
ESP_LOGCONFIG(TAG, " Configured: %s", YESNO(this->bsec2_blob_configured_));
|
67
|
+
if (this->bsec2_configuration_ != nullptr && this->bsec2_configuration_length_) {
|
68
|
+
ESP_LOGCONFIG(TAG, " Size: %" PRIu32, this->bsec2_configuration_length_);
|
69
|
+
}
|
70
|
+
|
71
|
+
if (this->is_failed()) {
|
72
|
+
ESP_LOGE(TAG, "Communication failed (BSEC2 status: %d, BME68X status: %d)", this->bsec_status_,
|
73
|
+
this->bme68x_status_);
|
74
|
+
}
|
75
|
+
|
76
|
+
if (this->algorithm_output_ != ALGORITHM_OUTPUT_IAQ) {
|
77
|
+
ESP_LOGCONFIG(TAG, " Algorithm output: %s", BME68X_BSEC2_ALGORITHM_OUTPUT_LOG(this->algorithm_output_));
|
78
|
+
}
|
79
|
+
ESP_LOGCONFIG(TAG, " Operating age: %s", BME68X_BSEC2_OPERATING_AGE_LOG(this->operating_age_));
|
80
|
+
ESP_LOGCONFIG(TAG, " Sample rate: %s", BME68X_BSEC2_SAMPLE_RATE_LOG(this->sample_rate_));
|
81
|
+
ESP_LOGCONFIG(TAG, " Voltage: %s", BME68X_BSEC2_VOLTAGE_LOG(this->voltage_));
|
82
|
+
ESP_LOGCONFIG(TAG, " State save interval: %ims", this->state_save_interval_ms_);
|
83
|
+
ESP_LOGCONFIG(TAG, " Temperature offset: %.2f", this->temperature_offset_);
|
84
|
+
|
85
|
+
#ifdef USE_SENSOR
|
86
|
+
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
|
87
|
+
ESP_LOGCONFIG(TAG, " Sample rate: %s", BME68X_BSEC2_SAMPLE_RATE_LOG(this->temperature_sample_rate_));
|
88
|
+
LOG_SENSOR(" ", "Pressure", this->pressure_sensor_);
|
89
|
+
ESP_LOGCONFIG(TAG, " Sample rate: %s", BME68X_BSEC2_SAMPLE_RATE_LOG(this->pressure_sample_rate_));
|
90
|
+
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
|
91
|
+
ESP_LOGCONFIG(TAG, " Sample rate: %s", BME68X_BSEC2_SAMPLE_RATE_LOG(this->humidity_sample_rate_));
|
92
|
+
LOG_SENSOR(" ", "Gas resistance", this->gas_resistance_sensor_);
|
93
|
+
LOG_SENSOR(" ", "CO2 equivalent", this->co2_equivalent_sensor_);
|
94
|
+
LOG_SENSOR(" ", "Breath VOC equivalent", this->breath_voc_equivalent_sensor_);
|
95
|
+
LOG_SENSOR(" ", "IAQ", this->iaq_sensor_);
|
96
|
+
LOG_SENSOR(" ", "IAQ static", this->iaq_static_sensor_);
|
97
|
+
LOG_SENSOR(" ", "Numeric IAQ accuracy", this->iaq_accuracy_sensor_);
|
98
|
+
#endif
|
99
|
+
#ifdef USE_TEXT_SENSOR
|
100
|
+
LOG_TEXT_SENSOR(" ", "IAQ accuracy", this->iaq_accuracy_text_sensor_);
|
101
|
+
#endif
|
102
|
+
}
|
103
|
+
|
104
|
+
float BME68xBSEC2Component::get_setup_priority() const { return setup_priority::DATA; }
|
105
|
+
|
106
|
+
void BME68xBSEC2Component::loop() {
|
107
|
+
this->run_();
|
108
|
+
|
109
|
+
if (this->bsec_status_ < BSEC_OK || this->bme68x_status_ < BME68X_OK) {
|
110
|
+
this->status_set_error();
|
111
|
+
} else {
|
112
|
+
this->status_clear_error();
|
113
|
+
}
|
114
|
+
if (this->bsec_status_ > BSEC_OK || this->bme68x_status_ > BME68X_OK) {
|
115
|
+
this->status_set_warning();
|
116
|
+
} else {
|
117
|
+
this->status_clear_warning();
|
118
|
+
}
|
119
|
+
// Process a single action from the queue. These are primarily sensor state publishes
|
120
|
+
// that in totality take too long to send in a single call.
|
121
|
+
if (this->queue_.size()) {
|
122
|
+
auto action = std::move(this->queue_.front());
|
123
|
+
this->queue_.pop();
|
124
|
+
action();
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
void BME68xBSEC2Component::set_config_(const uint8_t *config, uint32_t len) {
|
129
|
+
if (len > BSEC_MAX_PROPERTY_BLOB_SIZE) {
|
130
|
+
ESP_LOGE(TAG, "Configuration is larger than BSEC_MAX_PROPERTY_BLOB_SIZE");
|
131
|
+
this->mark_failed();
|
132
|
+
return;
|
133
|
+
}
|
134
|
+
uint8_t work_buffer[BSEC_MAX_PROPERTY_BLOB_SIZE];
|
135
|
+
this->bsec_status_ = bsec_set_configuration_m(&this->bsec_instance_, config, len, work_buffer, sizeof(work_buffer));
|
136
|
+
if (this->bsec_status_ == BSEC_OK) {
|
137
|
+
this->bsec2_blob_configured_ = true;
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
float BME68xBSEC2Component::calc_sensor_sample_rate_(SampleRate sample_rate) {
|
142
|
+
if (sample_rate == SAMPLE_RATE_DEFAULT) {
|
143
|
+
sample_rate = this->sample_rate_;
|
144
|
+
}
|
145
|
+
return sample_rate == SAMPLE_RATE_ULP ? BSEC_SAMPLE_RATE_ULP : BSEC_SAMPLE_RATE_LP;
|
146
|
+
}
|
147
|
+
|
148
|
+
void BME68xBSEC2Component::update_subscription_() {
|
149
|
+
bsec_sensor_configuration_t virtual_sensors[BSEC_NUMBER_OUTPUTS];
|
150
|
+
uint8_t num_virtual_sensors = 0;
|
151
|
+
#ifdef USE_SENSOR
|
152
|
+
if (this->iaq_sensor_) {
|
153
|
+
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_IAQ;
|
154
|
+
virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT);
|
155
|
+
num_virtual_sensors++;
|
156
|
+
}
|
157
|
+
|
158
|
+
if (this->iaq_static_sensor_) {
|
159
|
+
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_STATIC_IAQ;
|
160
|
+
virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT);
|
161
|
+
num_virtual_sensors++;
|
162
|
+
}
|
163
|
+
|
164
|
+
if (this->co2_equivalent_sensor_) {
|
165
|
+
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_CO2_EQUIVALENT;
|
166
|
+
virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT);
|
167
|
+
num_virtual_sensors++;
|
168
|
+
}
|
169
|
+
|
170
|
+
if (this->breath_voc_equivalent_sensor_) {
|
171
|
+
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_BREATH_VOC_EQUIVALENT;
|
172
|
+
virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT);
|
173
|
+
num_virtual_sensors++;
|
174
|
+
}
|
175
|
+
|
176
|
+
if (this->pressure_sensor_) {
|
177
|
+
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_PRESSURE;
|
178
|
+
virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(this->pressure_sample_rate_);
|
179
|
+
num_virtual_sensors++;
|
180
|
+
}
|
181
|
+
|
182
|
+
if (this->gas_resistance_sensor_) {
|
183
|
+
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_GAS;
|
184
|
+
virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT);
|
185
|
+
num_virtual_sensors++;
|
186
|
+
}
|
187
|
+
|
188
|
+
if (this->temperature_sensor_) {
|
189
|
+
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE;
|
190
|
+
virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(this->temperature_sample_rate_);
|
191
|
+
num_virtual_sensors++;
|
192
|
+
}
|
193
|
+
|
194
|
+
if (this->humidity_sensor_) {
|
195
|
+
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY;
|
196
|
+
virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(this->humidity_sample_rate_);
|
197
|
+
num_virtual_sensors++;
|
198
|
+
}
|
199
|
+
#endif
|
200
|
+
bsec_sensor_configuration_t sensor_settings[BSEC_MAX_PHYSICAL_SENSOR];
|
201
|
+
uint8_t num_sensor_settings = BSEC_MAX_PHYSICAL_SENSOR;
|
202
|
+
this->bsec_status_ = bsec_update_subscription_m(&this->bsec_instance_, virtual_sensors, num_virtual_sensors,
|
203
|
+
sensor_settings, &num_sensor_settings);
|
204
|
+
}
|
205
|
+
|
206
|
+
void BME68xBSEC2Component::run_() {
|
207
|
+
int64_t curr_time_ns = this->get_time_ns_();
|
208
|
+
if (curr_time_ns < this->next_call_ns_) {
|
209
|
+
return;
|
210
|
+
}
|
211
|
+
this->op_mode_ = this->bsec_settings_.op_mode;
|
212
|
+
uint8_t status;
|
213
|
+
|
214
|
+
ESP_LOGV(TAG, "Performing sensor run");
|
215
|
+
|
216
|
+
struct bme68x_conf bme68x_conf;
|
217
|
+
this->bsec_status_ = bsec_sensor_control_m(&this->bsec_instance_, curr_time_ns, &this->bsec_settings_);
|
218
|
+
if (this->bsec_status_ < BSEC_OK) {
|
219
|
+
ESP_LOGW(TAG, "Failed to fetch sensor control settings (BSEC2 error code %d)", this->bsec_status_);
|
220
|
+
return;
|
221
|
+
}
|
222
|
+
this->next_call_ns_ = this->bsec_settings_.next_call;
|
223
|
+
|
224
|
+
if (this->bsec_settings_.trigger_measurement) {
|
225
|
+
bme68x_get_conf(&bme68x_conf, &this->bme68x_);
|
226
|
+
|
227
|
+
bme68x_conf.os_hum = this->bsec_settings_.humidity_oversampling;
|
228
|
+
bme68x_conf.os_temp = this->bsec_settings_.temperature_oversampling;
|
229
|
+
bme68x_conf.os_pres = this->bsec_settings_.pressure_oversampling;
|
230
|
+
bme68x_set_conf(&bme68x_conf, &this->bme68x_);
|
231
|
+
|
232
|
+
switch (this->bsec_settings_.op_mode) {
|
233
|
+
case BME68X_FORCED_MODE:
|
234
|
+
this->bme68x_heatr_conf_.enable = BME68X_ENABLE;
|
235
|
+
this->bme68x_heatr_conf_.heatr_temp = this->bsec_settings_.heater_temperature;
|
236
|
+
this->bme68x_heatr_conf_.heatr_dur = this->bsec_settings_.heater_duration;
|
237
|
+
|
238
|
+
status = bme68x_set_op_mode(this->bsec_settings_.op_mode, &this->bme68x_);
|
239
|
+
status = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &this->bme68x_heatr_conf_, &this->bme68x_);
|
240
|
+
status = bme68x_set_op_mode(BME68X_FORCED_MODE, &this->bme68x_);
|
241
|
+
this->op_mode_ = BME68X_FORCED_MODE;
|
242
|
+
this->sleep_mode_ = false;
|
243
|
+
ESP_LOGV(TAG, "Using forced mode");
|
244
|
+
|
245
|
+
break;
|
246
|
+
case BME68X_PARALLEL_MODE:
|
247
|
+
if (this->op_mode_ != this->bsec_settings_.op_mode) {
|
248
|
+
this->bme68x_heatr_conf_.enable = BME68X_ENABLE;
|
249
|
+
this->bme68x_heatr_conf_.heatr_temp_prof = this->bsec_settings_.heater_temperature_profile;
|
250
|
+
this->bme68x_heatr_conf_.heatr_dur_prof = this->bsec_settings_.heater_duration_profile;
|
251
|
+
this->bme68x_heatr_conf_.profile_len = this->bsec_settings_.heater_profile_len;
|
252
|
+
this->bme68x_heatr_conf_.shared_heatr_dur =
|
253
|
+
BSEC_TOTAL_HEAT_DUR -
|
254
|
+
(bme68x_get_meas_dur(BME68X_PARALLEL_MODE, &bme68x_conf, &this->bme68x_) / INT64_C(1000));
|
255
|
+
|
256
|
+
status = bme68x_set_heatr_conf(BME68X_PARALLEL_MODE, &this->bme68x_heatr_conf_, &this->bme68x_);
|
257
|
+
|
258
|
+
status = bme68x_set_op_mode(BME68X_PARALLEL_MODE, &this->bme68x_);
|
259
|
+
this->op_mode_ = BME68X_PARALLEL_MODE;
|
260
|
+
this->sleep_mode_ = false;
|
261
|
+
ESP_LOGV(TAG, "Using parallel mode");
|
262
|
+
}
|
263
|
+
break;
|
264
|
+
case BME68X_SLEEP_MODE:
|
265
|
+
if (!this->sleep_mode_) {
|
266
|
+
bme68x_set_op_mode(BME68X_SLEEP_MODE, &this->bme68x_);
|
267
|
+
this->sleep_mode_ = true;
|
268
|
+
ESP_LOGV(TAG, "Using sleep mode");
|
269
|
+
}
|
270
|
+
break;
|
271
|
+
}
|
272
|
+
|
273
|
+
uint32_t meas_dur = 0;
|
274
|
+
meas_dur = bme68x_get_meas_dur(this->op_mode_, &bme68x_conf, &this->bme68x_);
|
275
|
+
ESP_LOGV(TAG, "Queueing read in %uus", meas_dur);
|
276
|
+
this->set_timeout("read", meas_dur / 1000, [this, curr_time_ns]() { this->read_(curr_time_ns); });
|
277
|
+
} else {
|
278
|
+
ESP_LOGV(TAG, "Measurement not required");
|
279
|
+
this->read_(curr_time_ns);
|
280
|
+
}
|
281
|
+
}
|
282
|
+
|
283
|
+
void BME68xBSEC2Component::read_(int64_t trigger_time_ns) {
|
284
|
+
ESP_LOGV(TAG, "Reading data");
|
285
|
+
|
286
|
+
if (this->bsec_settings_.trigger_measurement) {
|
287
|
+
uint8_t current_op_mode;
|
288
|
+
this->bme68x_status_ = bme68x_get_op_mode(¤t_op_mode, &this->bme68x_);
|
289
|
+
|
290
|
+
if (current_op_mode == BME68X_SLEEP_MODE) {
|
291
|
+
ESP_LOGV(TAG, "Still in sleep mode, doing nothing");
|
292
|
+
return;
|
293
|
+
}
|
294
|
+
}
|
295
|
+
|
296
|
+
if (!this->bsec_settings_.process_data) {
|
297
|
+
ESP_LOGV(TAG, "Data processing not required");
|
298
|
+
return;
|
299
|
+
}
|
300
|
+
|
301
|
+
struct bme68x_data data[3];
|
302
|
+
uint8_t nFields = 0;
|
303
|
+
this->bme68x_status_ = bme68x_get_data(this->op_mode_, &data[0], &nFields, &this->bme68x_);
|
304
|
+
|
305
|
+
if (this->bme68x_status_ != BME68X_OK) {
|
306
|
+
ESP_LOGW(TAG, "Failed to get sensor data (BME68X error code %d)", this->bme68x_status_);
|
307
|
+
return;
|
308
|
+
}
|
309
|
+
if (nFields < 1) {
|
310
|
+
ESP_LOGD(TAG, "BME68X did not provide new data");
|
311
|
+
return;
|
312
|
+
}
|
313
|
+
|
314
|
+
for (uint8_t i = 0; i < nFields; i++) {
|
315
|
+
bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temperature, Pressure, Humidity & Gas Resistance
|
316
|
+
uint8_t num_inputs = 0;
|
317
|
+
|
318
|
+
if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_TEMPERATURE)) {
|
319
|
+
inputs[num_inputs].sensor_id = BSEC_INPUT_TEMPERATURE;
|
320
|
+
inputs[num_inputs].signal = data[i].temperature;
|
321
|
+
inputs[num_inputs].time_stamp = trigger_time_ns;
|
322
|
+
num_inputs++;
|
323
|
+
}
|
324
|
+
if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_HEATSOURCE)) {
|
325
|
+
inputs[num_inputs].sensor_id = BSEC_INPUT_HEATSOURCE;
|
326
|
+
inputs[num_inputs].signal = this->temperature_offset_;
|
327
|
+
inputs[num_inputs].time_stamp = trigger_time_ns;
|
328
|
+
num_inputs++;
|
329
|
+
}
|
330
|
+
if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_HUMIDITY)) {
|
331
|
+
inputs[num_inputs].sensor_id = BSEC_INPUT_HUMIDITY;
|
332
|
+
inputs[num_inputs].signal = data[i].humidity;
|
333
|
+
inputs[num_inputs].time_stamp = trigger_time_ns;
|
334
|
+
num_inputs++;
|
335
|
+
}
|
336
|
+
if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_PRESSURE)) {
|
337
|
+
inputs[num_inputs].sensor_id = BSEC_INPUT_PRESSURE;
|
338
|
+
inputs[num_inputs].signal = data[i].pressure;
|
339
|
+
inputs[num_inputs].time_stamp = trigger_time_ns;
|
340
|
+
num_inputs++;
|
341
|
+
}
|
342
|
+
if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_GASRESISTOR)) {
|
343
|
+
if (data[i].status & BME68X_GASM_VALID_MSK) {
|
344
|
+
inputs[num_inputs].sensor_id = BSEC_INPUT_GASRESISTOR;
|
345
|
+
inputs[num_inputs].signal = data[i].gas_resistance;
|
346
|
+
inputs[num_inputs].time_stamp = trigger_time_ns;
|
347
|
+
num_inputs++;
|
348
|
+
} else {
|
349
|
+
ESP_LOGD(TAG, "BME68X did not report gas data");
|
350
|
+
}
|
351
|
+
}
|
352
|
+
if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_PROFILE_PART) &&
|
353
|
+
(data[i].status & BME68X_GASM_VALID_MSK)) {
|
354
|
+
inputs[num_inputs].sensor_id = BSEC_INPUT_PROFILE_PART;
|
355
|
+
inputs[num_inputs].signal = (this->op_mode_ == BME68X_FORCED_MODE) ? 0 : data[i].gas_index;
|
356
|
+
inputs[num_inputs].time_stamp = trigger_time_ns;
|
357
|
+
num_inputs++;
|
358
|
+
}
|
359
|
+
|
360
|
+
if (num_inputs < 1) {
|
361
|
+
ESP_LOGD(TAG, "No signal inputs available for BSEC2");
|
362
|
+
return;
|
363
|
+
}
|
364
|
+
|
365
|
+
bsec_output_t outputs[BSEC_NUMBER_OUTPUTS];
|
366
|
+
uint8_t num_outputs = BSEC_NUMBER_OUTPUTS;
|
367
|
+
this->bsec_status_ = bsec_do_steps_m(&this->bsec_instance_, inputs, num_inputs, outputs, &num_outputs);
|
368
|
+
if (this->bsec_status_ != BSEC_OK) {
|
369
|
+
ESP_LOGW(TAG, "BSEC2 failed to process signals (BSEC2 error code %d)", this->bsec_status_);
|
370
|
+
return;
|
371
|
+
}
|
372
|
+
if (num_outputs < 1) {
|
373
|
+
ESP_LOGD(TAG, "No signal outputs provided by BSEC2");
|
374
|
+
return;
|
375
|
+
}
|
376
|
+
|
377
|
+
this->publish_(outputs, num_outputs);
|
378
|
+
}
|
379
|
+
}
|
380
|
+
|
381
|
+
void BME68xBSEC2Component::publish_(const bsec_output_t *outputs, uint8_t num_outputs) {
|
382
|
+
ESP_LOGV(TAG, "Publishing sensor states");
|
383
|
+
bool update_accuracy = false;
|
384
|
+
uint8_t max_accuracy = 0;
|
385
|
+
for (uint8_t i = 0; i < num_outputs; i++) {
|
386
|
+
float signal = outputs[i].signal;
|
387
|
+
switch (outputs[i].sensor_id) {
|
388
|
+
case BSEC_OUTPUT_IAQ:
|
389
|
+
max_accuracy = std::max(outputs[i].accuracy, max_accuracy);
|
390
|
+
update_accuracy = true;
|
391
|
+
#ifdef USE_SENSOR
|
392
|
+
this->queue_push_([this, signal]() { this->publish_sensor_(this->iaq_sensor_, signal); });
|
393
|
+
#endif
|
394
|
+
break;
|
395
|
+
case BSEC_OUTPUT_STATIC_IAQ:
|
396
|
+
max_accuracy = std::max(outputs[i].accuracy, max_accuracy);
|
397
|
+
update_accuracy = true;
|
398
|
+
#ifdef USE_SENSOR
|
399
|
+
this->queue_push_([this, signal]() { this->publish_sensor_(this->iaq_static_sensor_, signal); });
|
400
|
+
#endif
|
401
|
+
break;
|
402
|
+
case BSEC_OUTPUT_CO2_EQUIVALENT:
|
403
|
+
#ifdef USE_SENSOR
|
404
|
+
this->queue_push_([this, signal]() { this->publish_sensor_(this->co2_equivalent_sensor_, signal); });
|
405
|
+
#endif
|
406
|
+
break;
|
407
|
+
case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
|
408
|
+
#ifdef USE_SENSOR
|
409
|
+
this->queue_push_([this, signal]() { this->publish_sensor_(this->breath_voc_equivalent_sensor_, signal); });
|
410
|
+
#endif
|
411
|
+
break;
|
412
|
+
case BSEC_OUTPUT_RAW_PRESSURE:
|
413
|
+
#ifdef USE_SENSOR
|
414
|
+
this->queue_push_([this, signal]() { this->publish_sensor_(this->pressure_sensor_, signal / 100.0f); });
|
415
|
+
#endif
|
416
|
+
break;
|
417
|
+
case BSEC_OUTPUT_RAW_GAS:
|
418
|
+
#ifdef USE_SENSOR
|
419
|
+
this->queue_push_([this, signal]() { this->publish_sensor_(this->gas_resistance_sensor_, signal); });
|
420
|
+
#endif
|
421
|
+
break;
|
422
|
+
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
|
423
|
+
#ifdef USE_SENSOR
|
424
|
+
this->queue_push_([this, signal]() { this->publish_sensor_(this->temperature_sensor_, signal); });
|
425
|
+
#endif
|
426
|
+
break;
|
427
|
+
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
|
428
|
+
#ifdef USE_SENSOR
|
429
|
+
this->queue_push_([this, signal]() { this->publish_sensor_(this->humidity_sensor_, signal); });
|
430
|
+
#endif
|
431
|
+
break;
|
432
|
+
}
|
433
|
+
}
|
434
|
+
if (update_accuracy) {
|
435
|
+
#ifdef USE_SENSOR
|
436
|
+
this->queue_push_(
|
437
|
+
[this, max_accuracy]() { this->publish_sensor_(this->iaq_accuracy_sensor_, max_accuracy, true); });
|
438
|
+
#endif
|
439
|
+
#ifdef USE_TEXT_SENSOR
|
440
|
+
this->queue_push_([this, max_accuracy]() {
|
441
|
+
this->publish_sensor_(this->iaq_accuracy_text_sensor_, IAQ_ACCURACY_STATES[max_accuracy]);
|
442
|
+
});
|
443
|
+
#endif
|
444
|
+
// Queue up an opportunity to save state
|
445
|
+
this->queue_push_([this, max_accuracy]() { this->save_state_(max_accuracy); });
|
446
|
+
}
|
447
|
+
}
|
448
|
+
|
449
|
+
int64_t BME68xBSEC2Component::get_time_ns_() {
|
450
|
+
int64_t time_ms = millis();
|
451
|
+
if (this->last_time_ms_ > time_ms) {
|
452
|
+
this->millis_overflow_counter_++;
|
453
|
+
}
|
454
|
+
this->last_time_ms_ = time_ms;
|
455
|
+
|
456
|
+
return (time_ms + ((int64_t) this->millis_overflow_counter_ << 32)) * INT64_C(1000000);
|
457
|
+
}
|
458
|
+
|
459
|
+
#ifdef USE_SENSOR
|
460
|
+
void BME68xBSEC2Component::publish_sensor_(sensor::Sensor *sensor, float value, bool change_only) {
|
461
|
+
if (!sensor || (change_only && sensor->has_state() && sensor->state == value)) {
|
462
|
+
return;
|
463
|
+
}
|
464
|
+
sensor->publish_state(value);
|
465
|
+
}
|
466
|
+
#endif
|
467
|
+
|
468
|
+
#ifdef USE_TEXT_SENSOR
|
469
|
+
void BME68xBSEC2Component::publish_sensor_(text_sensor::TextSensor *sensor, const std::string &value) {
|
470
|
+
if (!sensor || (sensor->has_state() && sensor->state == value)) {
|
471
|
+
return;
|
472
|
+
}
|
473
|
+
sensor->publish_state(value);
|
474
|
+
}
|
475
|
+
#endif
|
476
|
+
|
477
|
+
void BME68xBSEC2Component::load_state_() {
|
478
|
+
uint32_t hash = this->get_hash();
|
479
|
+
this->bsec_state_ = global_preferences->make_preference<uint8_t[BSEC_MAX_STATE_BLOB_SIZE]>(hash, true);
|
480
|
+
|
481
|
+
uint8_t state[BSEC_MAX_STATE_BLOB_SIZE];
|
482
|
+
if (this->bsec_state_.load(&state)) {
|
483
|
+
ESP_LOGV(TAG, "Loading state");
|
484
|
+
uint8_t work_buffer[BSEC_MAX_WORKBUFFER_SIZE];
|
485
|
+
this->bsec_status_ =
|
486
|
+
bsec_set_state_m(&this->bsec_instance_, state, BSEC_MAX_STATE_BLOB_SIZE, work_buffer, sizeof(work_buffer));
|
487
|
+
if (this->bsec_status_ != BSEC_OK) {
|
488
|
+
ESP_LOGW(TAG, "Failed to load state (BSEC2 error code %d)", this->bsec_status_);
|
489
|
+
}
|
490
|
+
ESP_LOGI(TAG, "Loaded state");
|
491
|
+
}
|
492
|
+
}
|
493
|
+
|
494
|
+
void BME68xBSEC2Component::save_state_(uint8_t accuracy) {
|
495
|
+
if (accuracy < 3 || (millis() - this->last_state_save_ms_ < this->state_save_interval_ms_)) {
|
496
|
+
return;
|
497
|
+
}
|
498
|
+
|
499
|
+
ESP_LOGV(TAG, "Saving state");
|
500
|
+
|
501
|
+
uint8_t state[BSEC_MAX_STATE_BLOB_SIZE];
|
502
|
+
uint8_t work_buffer[BSEC_MAX_STATE_BLOB_SIZE];
|
503
|
+
uint32_t num_serialized_state = BSEC_MAX_STATE_BLOB_SIZE;
|
504
|
+
|
505
|
+
this->bsec_status_ = bsec_get_state_m(&this->bsec_instance_, 0, state, BSEC_MAX_STATE_BLOB_SIZE, work_buffer,
|
506
|
+
BSEC_MAX_STATE_BLOB_SIZE, &num_serialized_state);
|
507
|
+
if (this->bsec_status_ != BSEC_OK) {
|
508
|
+
ESP_LOGW(TAG, "Failed fetch state for save (BSEC2 error code %d)", this->bsec_status_);
|
509
|
+
return;
|
510
|
+
}
|
511
|
+
|
512
|
+
if (!this->bsec_state_.save(&state)) {
|
513
|
+
ESP_LOGW(TAG, "Failed to save state");
|
514
|
+
return;
|
515
|
+
}
|
516
|
+
this->last_state_save_ms_ = millis();
|
517
|
+
|
518
|
+
ESP_LOGI(TAG, "Saved state");
|
519
|
+
}
|
520
|
+
|
521
|
+
} // namespace bme68x_bsec2
|
522
|
+
} // namespace esphome
|
523
|
+
#endif
|
@@ -0,0 +1,163 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "esphome/core/component.h"
|
4
|
+
#include "esphome/core/defines.h"
|
5
|
+
#include "esphome/core/preferences.h"
|
6
|
+
|
7
|
+
#ifdef USE_BSEC2
|
8
|
+
|
9
|
+
#ifdef USE_SENSOR
|
10
|
+
#include "esphome/components/sensor/sensor.h"
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#ifdef USE_TEXT_SENSOR
|
14
|
+
#include "esphome/components/text_sensor/text_sensor.h"
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#include <cinttypes>
|
18
|
+
#include <queue>
|
19
|
+
|
20
|
+
#include <bsec2.h>
|
21
|
+
|
22
|
+
namespace esphome {
|
23
|
+
namespace bme68x_bsec2 {
|
24
|
+
|
25
|
+
enum AlgorithmOutput {
|
26
|
+
ALGORITHM_OUTPUT_IAQ,
|
27
|
+
ALGORITHM_OUTPUT_CLASSIFICATION,
|
28
|
+
ALGORITHM_OUTPUT_REGRESSION,
|
29
|
+
};
|
30
|
+
|
31
|
+
enum OperatingAge {
|
32
|
+
OPERATING_AGE_4D,
|
33
|
+
OPERATING_AGE_28D,
|
34
|
+
};
|
35
|
+
|
36
|
+
enum SampleRate {
|
37
|
+
SAMPLE_RATE_LP = 0,
|
38
|
+
SAMPLE_RATE_ULP = 1,
|
39
|
+
SAMPLE_RATE_DEFAULT = 2,
|
40
|
+
};
|
41
|
+
|
42
|
+
enum Voltage {
|
43
|
+
VOLTAGE_1_8V,
|
44
|
+
VOLTAGE_3_3V,
|
45
|
+
};
|
46
|
+
|
47
|
+
class BME68xBSEC2Component : public Component {
|
48
|
+
public:
|
49
|
+
void setup() override;
|
50
|
+
void dump_config() override;
|
51
|
+
float get_setup_priority() const override;
|
52
|
+
void loop() override;
|
53
|
+
|
54
|
+
void set_algorithm_output(AlgorithmOutput algorithm_output) { this->algorithm_output_ = algorithm_output; }
|
55
|
+
void set_operating_age(OperatingAge operating_age) { this->operating_age_ = operating_age; }
|
56
|
+
void set_temperature_offset(float offset) { this->temperature_offset_ = offset; }
|
57
|
+
void set_voltage(Voltage voltage) { this->voltage_ = voltage; }
|
58
|
+
|
59
|
+
void set_sample_rate(SampleRate sample_rate) { this->sample_rate_ = sample_rate; }
|
60
|
+
void set_temperature_sample_rate(SampleRate sample_rate) { this->temperature_sample_rate_ = sample_rate; }
|
61
|
+
void set_pressure_sample_rate(SampleRate sample_rate) { this->pressure_sample_rate_ = sample_rate; }
|
62
|
+
void set_humidity_sample_rate(SampleRate sample_rate) { this->humidity_sample_rate_ = sample_rate; }
|
63
|
+
|
64
|
+
void set_bsec2_configuration(const uint8_t *data, const uint32_t len) {
|
65
|
+
this->bsec2_configuration_ = data;
|
66
|
+
this->bsec2_configuration_length_ = len;
|
67
|
+
}
|
68
|
+
|
69
|
+
void set_state_save_interval(uint32_t interval) { this->state_save_interval_ms_ = interval; }
|
70
|
+
|
71
|
+
#ifdef USE_SENSOR
|
72
|
+
void set_temperature_sensor(sensor::Sensor *sensor) { this->temperature_sensor_ = sensor; }
|
73
|
+
void set_pressure_sensor(sensor::Sensor *sensor) { this->pressure_sensor_ = sensor; }
|
74
|
+
void set_humidity_sensor(sensor::Sensor *sensor) { this->humidity_sensor_ = sensor; }
|
75
|
+
void set_gas_resistance_sensor(sensor::Sensor *sensor) { this->gas_resistance_sensor_ = sensor; }
|
76
|
+
void set_iaq_sensor(sensor::Sensor *sensor) { this->iaq_sensor_ = sensor; }
|
77
|
+
void set_iaq_static_sensor(sensor::Sensor *sensor) { this->iaq_static_sensor_ = sensor; }
|
78
|
+
void set_iaq_accuracy_sensor(sensor::Sensor *sensor) { this->iaq_accuracy_sensor_ = sensor; }
|
79
|
+
void set_co2_equivalent_sensor(sensor::Sensor *sensor) { this->co2_equivalent_sensor_ = sensor; }
|
80
|
+
void set_breath_voc_equivalent_sensor(sensor::Sensor *sensor) { this->breath_voc_equivalent_sensor_ = sensor; }
|
81
|
+
#endif
|
82
|
+
#ifdef USE_TEXT_SENSOR
|
83
|
+
void set_iaq_accuracy_text_sensor(text_sensor::TextSensor *sensor) { this->iaq_accuracy_text_sensor_ = sensor; }
|
84
|
+
#endif
|
85
|
+
virtual uint32_t get_hash() = 0;
|
86
|
+
|
87
|
+
protected:
|
88
|
+
void set_config_(const uint8_t *config, u_int32_t len);
|
89
|
+
float calc_sensor_sample_rate_(SampleRate sample_rate);
|
90
|
+
void update_subscription_();
|
91
|
+
|
92
|
+
void run_();
|
93
|
+
void read_(int64_t trigger_time_ns);
|
94
|
+
void publish_(const bsec_output_t *outputs, uint8_t num_outputs);
|
95
|
+
int64_t get_time_ns_();
|
96
|
+
|
97
|
+
#ifdef USE_SENSOR
|
98
|
+
void publish_sensor_(sensor::Sensor *sensor, float value, bool change_only = false);
|
99
|
+
#endif
|
100
|
+
#ifdef USE_TEXT_SENSOR
|
101
|
+
void publish_sensor_(text_sensor::TextSensor *sensor, const std::string &value);
|
102
|
+
#endif
|
103
|
+
|
104
|
+
void load_state_();
|
105
|
+
void save_state_(uint8_t accuracy);
|
106
|
+
|
107
|
+
void queue_push_(std::function<void()> &&f) { this->queue_.push(std::move(f)); }
|
108
|
+
|
109
|
+
struct bme68x_dev bme68x_;
|
110
|
+
bsec_bme_settings_t bsec_settings_;
|
111
|
+
bsec_version_t version_;
|
112
|
+
uint8_t bsec_instance_[BSEC_INSTANCE_SIZE];
|
113
|
+
|
114
|
+
struct bme68x_heatr_conf bme68x_heatr_conf_;
|
115
|
+
uint8_t op_mode_; // operating mode of sensor
|
116
|
+
bool sleep_mode_;
|
117
|
+
bsec_library_return_t bsec_status_{BSEC_OK};
|
118
|
+
int8_t bme68x_status_{BME68X_OK};
|
119
|
+
|
120
|
+
int64_t last_time_ms_{0};
|
121
|
+
uint32_t millis_overflow_counter_{0};
|
122
|
+
int64_t next_call_ns_{0};
|
123
|
+
|
124
|
+
std::queue<std::function<void()>> queue_;
|
125
|
+
|
126
|
+
uint8_t const *bsec2_configuration_{nullptr};
|
127
|
+
uint32_t bsec2_configuration_length_{0};
|
128
|
+
bool bsec2_blob_configured_{false};
|
129
|
+
|
130
|
+
ESPPreferenceObject bsec_state_;
|
131
|
+
uint32_t state_save_interval_ms_{21600000}; // 6 hours - 4 times a day
|
132
|
+
uint32_t last_state_save_ms_ = 0;
|
133
|
+
|
134
|
+
float temperature_offset_{0};
|
135
|
+
|
136
|
+
AlgorithmOutput algorithm_output_{ALGORITHM_OUTPUT_IAQ};
|
137
|
+
OperatingAge operating_age_{OPERATING_AGE_28D};
|
138
|
+
Voltage voltage_{VOLTAGE_3_3V};
|
139
|
+
|
140
|
+
SampleRate sample_rate_{SAMPLE_RATE_LP}; // Core/gas sample rate
|
141
|
+
SampleRate temperature_sample_rate_{SAMPLE_RATE_DEFAULT};
|
142
|
+
SampleRate pressure_sample_rate_{SAMPLE_RATE_DEFAULT};
|
143
|
+
SampleRate humidity_sample_rate_{SAMPLE_RATE_DEFAULT};
|
144
|
+
|
145
|
+
#ifdef USE_SENSOR
|
146
|
+
sensor::Sensor *temperature_sensor_{nullptr};
|
147
|
+
sensor::Sensor *pressure_sensor_{nullptr};
|
148
|
+
sensor::Sensor *humidity_sensor_{nullptr};
|
149
|
+
sensor::Sensor *gas_resistance_sensor_{nullptr};
|
150
|
+
sensor::Sensor *iaq_sensor_{nullptr};
|
151
|
+
sensor::Sensor *iaq_static_sensor_{nullptr};
|
152
|
+
sensor::Sensor *iaq_accuracy_sensor_{nullptr};
|
153
|
+
sensor::Sensor *co2_equivalent_sensor_{nullptr};
|
154
|
+
sensor::Sensor *breath_voc_equivalent_sensor_{nullptr};
|
155
|
+
#endif
|
156
|
+
#ifdef USE_TEXT_SENSOR
|
157
|
+
text_sensor::TextSensor *iaq_accuracy_text_sensor_{nullptr};
|
158
|
+
#endif
|
159
|
+
};
|
160
|
+
|
161
|
+
} // namespace bme68x_bsec2
|
162
|
+
} // namespace esphome
|
163
|
+
#endif
|