esphome 2024.12.4__py3-none-any.whl → 2025.2.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +16 -3
- esphome/components/adc/__init__.py +17 -11
- esphome/components/adc/adc_sensor.h +17 -0
- esphome/components/adc/adc_sensor_common.cpp +55 -0
- esphome/components/adc/adc_sensor_esp32.cpp +8 -5
- esphome/components/adc/adc_sensor_esp8266.cpp +10 -6
- esphome/components/adc/adc_sensor_libretiny.cpp +11 -6
- esphome/components/adc/adc_sensor_rp2040.cpp +13 -10
- esphome/components/adc/sensor.py +9 -3
- esphome/components/ads1115/ads1115.cpp +56 -7
- esphome/components/ads1115/ads1115.h +13 -1
- esphome/components/ads1115/sensor/__init__.py +16 -0
- esphome/components/ads1115/sensor/ads1115_sensor.cpp +2 -1
- esphome/components/ads1115/sensor/ads1115_sensor.h +2 -0
- esphome/components/animation/__init__.py +23 -261
- esphome/components/animation/animation.cpp +2 -2
- esphome/components/animation/animation.h +2 -1
- esphome/components/api/api_pb2.cpp +14 -0
- esphome/components/api/api_pb2.h +1 -0
- esphome/components/audio/__init__.py +112 -0
- esphome/components/audio/audio.cpp +67 -0
- esphome/components/audio/audio.h +125 -7
- esphome/components/audio/audio_decoder.cpp +361 -0
- esphome/components/audio/audio_decoder.h +135 -0
- esphome/components/audio/audio_reader.cpp +308 -0
- esphome/components/audio/audio_reader.h +85 -0
- esphome/components/audio/audio_resampler.cpp +159 -0
- esphome/components/audio/audio_resampler.h +101 -0
- esphome/components/audio/audio_transfer_buffer.cpp +165 -0
- esphome/components/audio/audio_transfer_buffer.h +139 -0
- esphome/components/audio_adc/__init__.py +41 -0
- esphome/components/audio_adc/audio_adc.h +17 -0
- esphome/components/audio_adc/automation.h +23 -0
- esphome/components/bk72xx/__init__.py +1 -0
- esphome/components/ble_client/ble_client.cpp +1 -2
- esphome/components/ble_client/sensor/__init__.py +1 -1
- esphome/components/ble_client/text_sensor/__init__.py +1 -1
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +5 -0
- esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -0
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +5 -0
- esphome/components/ch422g/ch422g.h +2 -0
- esphome/components/climate/__init__.py +1 -1
- esphome/components/climate_ir/climate_ir.cpp +2 -1
- esphome/components/coolix/coolix.cpp +2 -1
- esphome/components/custom/__init__.py +0 -3
- esphome/components/custom/binary_sensor/__init__.py +2 -28
- esphome/components/custom/climate/__init__.py +2 -27
- esphome/components/custom/cover/__init__.py +2 -27
- esphome/components/custom/light/__init__.py +2 -27
- esphome/components/custom/output/__init__.py +2 -58
- esphome/components/custom/sensor/__init__.py +2 -24
- esphome/components/custom/switch/__init__.py +2 -24
- esphome/components/custom/text_sensor/__init__.py +2 -29
- esphome/components/custom_component/__init__.py +3 -27
- esphome/components/daly_bms/daly_bms.cpp +6 -0
- esphome/components/daly_bms/daly_bms.h +2 -0
- esphome/components/daly_bms/sensor.py +6 -0
- esphome/components/debug/debug_component.cpp +4 -0
- esphome/components/debug/debug_component.h +14 -0
- esphome/components/debug/debug_esp32.cpp +154 -74
- esphome/components/dfplayer/dfplayer.cpp +15 -2
- esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp +2 -1
- esphome/components/dht/dht.cpp +2 -1
- esphome/components/display/__init__.py +18 -5
- esphome/components/display/display.cpp +2 -1
- esphome/components/display/rect.cpp +2 -1
- esphome/components/es7210/__init__.py +0 -0
- esphome/components/es7210/audio_adc.py +51 -0
- esphome/components/es7210/es7210.cpp +228 -0
- esphome/components/es7210/es7210.h +62 -0
- esphome/components/es7210/es7210_const.h +129 -0
- esphome/components/es7243e/__init__.py +0 -0
- esphome/components/es7243e/audio_adc.py +34 -0
- esphome/components/es7243e/es7243e.cpp +125 -0
- esphome/components/es7243e/es7243e.h +37 -0
- esphome/components/es7243e/es7243e_const.h +54 -0
- esphome/components/es8156/__init__.py +0 -0
- esphome/components/es8156/audio_dac.py +27 -0
- esphome/components/es8156/es8156.cpp +87 -0
- esphome/components/es8156/es8156.h +51 -0
- esphome/components/es8156/es8156_const.h +68 -0
- esphome/components/es8311/audio_dac.py +1 -2
- esphome/components/esp32/__init__.py +1 -0
- esphome/components/esp32/core.cpp +5 -1
- esphome/components/esp32/gpio.h +2 -0
- esphome/components/esp32_ble/__init__.py +39 -0
- esphome/components/esp32_ble/queue.h +4 -4
- esphome/components/esp32_ble_client/ble_client_base.cpp +46 -0
- esphome/components/esp32_ble_client/ble_client_base.h +2 -0
- esphome/components/esp32_ble_server/__init__.py +582 -12
- esphome/components/esp32_ble_server/ble_characteristic.cpp +48 -60
- esphome/components/esp32_ble_server/ble_characteristic.h +24 -17
- esphome/components/esp32_ble_server/ble_descriptor.cpp +21 -9
- esphome/components/esp32_ble_server/ble_descriptor.h +17 -6
- esphome/components/esp32_ble_server/ble_server.cpp +62 -67
- esphome/components/esp32_ble_server/ble_server.h +28 -32
- esphome/components/esp32_ble_server/ble_server_automations.cpp +77 -0
- esphome/components/esp32_ble_server/ble_server_automations.h +115 -0
- esphome/components/esp32_ble_server/ble_service.cpp +17 -15
- esphome/components/esp32_ble_server/ble_service.h +10 -14
- esphome/components/esp32_ble_tracker/__init__.py +6 -39
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +33 -10
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +8 -4
- esphome/components/esp32_improv/__init__.py +2 -8
- esphome/components/esp32_improv/esp32_improv_component.cpp +21 -20
- esphome/components/esp32_improv/esp32_improv_component.h +3 -4
- esphome/components/esp32_rmt/__init__.py +28 -3
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +73 -6
- esphome/components/esp32_rmt_led_strip/led_strip.h +21 -3
- esphome/components/esp32_rmt_led_strip/light.py +72 -7
- esphome/components/esp32_touch/esp32_touch.cpp +5 -0
- esphome/components/esp8266/__init__.py +1 -0
- esphome/components/esp8266/gpio.h +1 -0
- esphome/components/ethernet/__init__.py +10 -10
- esphome/components/event/event.cpp +4 -2
- esphome/components/event/event.h +2 -0
- esphome/components/event_emitter/__init__.py +5 -0
- esphome/components/event_emitter/event_emitter.cpp +14 -0
- esphome/components/event_emitter/event_emitter.h +63 -0
- esphome/components/gcja5/gcja5.cpp +2 -1
- esphome/components/haier/haier_base.cpp +2 -1
- esphome/components/haier/hon_climate.cpp +2 -1
- esphome/components/heatpumpir/heatpumpir.cpp +2 -1
- esphome/components/host/__init__.py +1 -0
- esphome/components/host/gpio.h +1 -0
- esphome/components/http_request/http_request.h +2 -2
- esphome/components/http_request/http_request_arduino.cpp +1 -1
- esphome/components/http_request/http_request_idf.cpp +1 -1
- esphome/components/i2c/i2c_bus_esp_idf.cpp +4 -0
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +7 -5
- esphome/components/i2s_audio/speaker/__init__.py +53 -6
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +92 -46
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -0
- esphome/components/ili9xxx/display.py +29 -11
- esphome/components/ili9xxx/ili9xxx_display.cpp +2 -5
- esphome/components/ili9xxx/ili9xxx_display.h +2 -1
- esphome/components/image/__init__.py +443 -255
- esphome/components/image/image.cpp +115 -61
- esphome/components/image/image.h +15 -24
- esphome/components/json/json_util.cpp +8 -34
- esphome/components/libretiny/__init__.py +1 -0
- esphome/components/libretiny/gpio_arduino.h +1 -0
- esphome/components/light/light_color_values.h +1 -1
- esphome/components/logger/__init__.py +43 -7
- esphome/components/logger/logger.cpp +16 -11
- esphome/components/logger/logger.h +11 -7
- esphome/components/logger/select/__init__.py +29 -0
- esphome/components/logger/select/logger_level_select.cpp +27 -0
- esphome/components/logger/select/logger_level_select.h +15 -0
- esphome/components/lvgl/__init__.py +96 -73
- esphome/components/lvgl/automation.py +39 -7
- esphome/components/lvgl/defines.py +8 -2
- esphome/components/lvgl/lvgl_esphome.cpp +8 -15
- esphome/components/lvgl/lvgl_esphome.h +20 -5
- esphome/components/lvgl/schemas.py +25 -14
- esphome/components/lvgl/trigger.py +27 -3
- esphome/components/lvgl/widgets/dropdown.py +1 -1
- esphome/components/lvgl/widgets/keyboard.py +8 -1
- esphome/components/lvgl/widgets/meter.py +2 -1
- esphome/components/lvgl/widgets/msgbox.py +1 -1
- esphome/components/lvgl/widgets/obj.py +1 -12
- esphome/components/lvgl/widgets/page.py +37 -2
- esphome/components/lvgl/widgets/tabview.py +1 -1
- esphome/components/max6956/max6956.h +2 -0
- esphome/components/mcp23016/mcp23016.h +2 -0
- esphome/components/mcp23xxx_base/mcp23xxx_base.h +2 -0
- esphome/components/mdns/__init__.py +1 -1
- esphome/components/media_player/__init__.py +37 -8
- esphome/components/media_player/automation.h +11 -2
- esphome/components/media_player/media_player.cpp +8 -0
- esphome/components/media_player/media_player.h +8 -4
- esphome/components/micronova/switch/micronova_switch.cpp +4 -2
- esphome/components/midea/ac_automations.h +3 -1
- esphome/components/midea/air_conditioner.cpp +7 -5
- esphome/components/midea/air_conditioner.h +1 -1
- esphome/components/midea/climate.py +4 -2
- esphome/components/midea/ir_transmitter.h +36 -5
- esphome/components/mixer/__init__.py +0 -0
- esphome/components/mixer/speaker/__init__.py +172 -0
- esphome/components/mixer/speaker/automation.h +19 -0
- esphome/components/mixer/speaker/mixer_speaker.cpp +624 -0
- esphome/components/mixer/speaker/mixer_speaker.h +207 -0
- esphome/components/mpr121/mpr121.h +2 -0
- esphome/components/mqtt/__init__.py +1 -1
- esphome/components/mqtt/mqtt_client.cpp +7 -1
- esphome/components/mqtt/mqtt_client.h +1 -1
- esphome/components/mqtt/mqtt_climate.cpp +2 -2
- esphome/components/network/ip_address.h +2 -0
- esphome/components/nextion/automation.h +17 -0
- esphome/components/nextion/display.py +42 -17
- esphome/components/nextion/nextion.cpp +4 -10
- esphome/components/nextion/nextion.h +89 -82
- esphome/components/nextion/nextion_commands.cpp +10 -10
- esphome/components/ntc/sensor.py +2 -4
- esphome/components/online_image/__init__.py +98 -46
- esphome/components/online_image/bmp_image.cpp +101 -0
- esphome/components/online_image/bmp_image.h +40 -0
- esphome/components/online_image/image_decoder.cpp +28 -2
- esphome/components/online_image/image_decoder.h +24 -15
- esphome/components/online_image/jpeg_image.cpp +90 -0
- esphome/components/online_image/jpeg_image.h +34 -0
- esphome/components/online_image/online_image.cpp +112 -53
- esphome/components/online_image/online_image.h +24 -7
- esphome/components/online_image/png_image.cpp +7 -3
- esphome/components/online_image/png_image.h +2 -1
- esphome/components/opentherm/__init__.py +73 -7
- esphome/components/opentherm/automation.h +25 -0
- esphome/components/opentherm/const.py +1 -0
- esphome/components/opentherm/generate.py +39 -6
- esphome/components/opentherm/hub.cpp +117 -79
- esphome/components/opentherm/hub.h +31 -15
- esphome/components/opentherm/opentherm.cpp +47 -23
- esphome/components/opentherm/opentherm.h +27 -6
- esphome/components/opentherm/opentherm_macros.h +11 -0
- esphome/components/opentherm/schema.py +78 -1
- esphome/components/opentherm/validate.py +7 -2
- esphome/components/pca6416a/pca6416a.h +2 -0
- esphome/components/pca9554/pca9554.h +2 -0
- esphome/components/pcf8574/pcf8574.h +2 -0
- esphome/components/preferences/__init__.py +2 -4
- esphome/components/preferences/syncer.h +10 -3
- esphome/components/prometheus/prometheus_handler.cpp +313 -0
- esphome/components/prometheus/prometheus_handler.h +48 -7
- esphome/components/psram/psram.cpp +8 -1
- esphome/components/pulse_counter/pulse_counter_sensor.cpp +14 -9
- esphome/components/pulse_counter/pulse_counter_sensor.h +4 -4
- esphome/components/pulse_meter/pulse_meter_sensor.cpp +2 -0
- esphome/components/qspi_dbi/__init__.py +3 -0
- esphome/components/qspi_dbi/display.py +74 -47
- esphome/components/qspi_dbi/models.py +245 -2
- esphome/components/qspi_dbi/qspi_dbi.cpp +9 -16
- esphome/components/qspi_dbi/qspi_dbi.h +2 -2
- esphome/components/remote_base/__init__.py +77 -25
- esphome/components/remote_base/remote_base.cpp +1 -1
- esphome/components/remote_base/remote_base.h +20 -2
- esphome/components/remote_base/toto_protocol.cpp +100 -0
- esphome/components/remote_base/toto_protocol.h +45 -0
- esphome/components/remote_receiver/__init__.py +55 -10
- esphome/components/remote_receiver/remote_receiver.h +36 -3
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +145 -6
- esphome/components/remote_transmitter/__init__.py +62 -4
- esphome/components/remote_transmitter/remote_transmitter.h +21 -2
- esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +140 -4
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +3 -3
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +3 -3
- esphome/components/resampler/__init__.py +0 -0
- esphome/components/resampler/speaker/__init__.py +103 -0
- esphome/components/resampler/speaker/resampler_speaker.cpp +318 -0
- esphome/components/resampler/speaker/resampler_speaker.h +107 -0
- esphome/components/resistance/resistance_sensor.h +2 -3
- esphome/components/resistance/sensor.py +2 -9
- esphome/components/rotary_encoder/rotary_encoder.cpp +8 -4
- esphome/components/rp2040/__init__.py +1 -0
- esphome/components/rp2040/gpio.h +1 -0
- esphome/components/rtl87xx/__init__.py +2 -0
- esphome/components/sdl/binary_sensor.py +270 -0
- esphome/components/sdl/sdl_esphome.cpp +16 -0
- esphome/components/sdl/sdl_esphome.h +9 -0
- esphome/components/seeed_mr60bha2/binary_sensor.py +25 -0
- esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +26 -2
- esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +9 -20
- esphome/components/seeed_mr60bha2/sensor.py +9 -1
- esphome/components/sn74hc165/sn74hc165.h +3 -0
- esphome/components/sn74hc595/sn74hc595.h +3 -0
- esphome/components/speaker/__init__.py +5 -4
- esphome/components/speaker/media_player/__init__.py +458 -0
- esphome/components/speaker/media_player/audio_pipeline.cpp +568 -0
- esphome/components/speaker/media_player/audio_pipeline.h +159 -0
- esphome/components/speaker/media_player/automation.h +26 -0
- esphome/components/speaker/media_player/speaker_media_player.cpp +577 -0
- esphome/components/speaker/media_player/speaker_media_player.h +160 -0
- esphome/components/speaker/speaker.h +20 -0
- esphome/components/spi/__init__.py +1 -5
- esphome/components/spi/spi.cpp +7 -1
- esphome/components/spi/spi.h +21 -2
- esphome/components/spi_led_strip/light.py +3 -5
- esphome/components/spi_led_strip/spi_led_strip.cpp +67 -0
- esphome/components/spi_led_strip/spi_led_strip.h +8 -60
- esphome/components/sprinkler/sprinkler.cpp +3 -1
- esphome/components/sx1509/sx1509_gpio_pin.h +2 -0
- esphome/components/tca9555/tca9555.h +2 -0
- esphome/components/toshiba/toshiba.cpp +2 -1
- esphome/components/tuya/light/tuya_light.cpp +4 -2
- esphome/components/uart/uart_component_esp32_arduino.cpp +2 -2
- esphome/components/uart/uart_component_esp_idf.cpp +2 -2
- esphome/components/udp/__init__.py +8 -2
- esphome/components/udp/udp_component.cpp +25 -56
- esphome/components/udp/udp_component.h +3 -0
- esphome/components/uponor_smatrix/sensor/__init__.py +14 -4
- esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +5 -0
- esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.h +1 -0
- esphome/components/uptime/text_sensor/__init__.py +19 -0
- esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +63 -0
- esphome/components/uptime/text_sensor/uptime_text_sensor.h +25 -0
- esphome/components/voice_assistant/voice_assistant.cpp +24 -14
- esphome/components/voice_assistant/voice_assistant.h +8 -0
- esphome/components/waveshare_epaper/display.py +22 -1
- esphome/components/waveshare_epaper/waveshare_213v3.cpp +9 -3
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +1155 -44
- esphome/components/waveshare_epaper/waveshare_epaper.h +208 -7
- esphome/components/web_server/web_server.cpp +28 -6
- esphome/components/weikai/weikai.h +2 -0
- esphome/components/wifi/__init__.py +6 -6
- esphome/components/wifi/wifi_component.cpp +1 -1
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -1
- esphome/components/wireguard/__init__.py +2 -2
- esphome/components/xl9535/xl9535.h +2 -0
- esphome/components/xxtea/__init__.py +3 -0
- esphome/components/xxtea/xxtea.cpp +46 -0
- esphome/components/xxtea/xxtea.h +26 -0
- esphome/components/yashima/yashima.cpp +2 -1
- esphome/config.py +9 -5
- esphome/config_validation.py +55 -17
- esphome/const.py +7 -10
- esphome/core/__init__.py +6 -13
- esphome/core/base_automation.h +1 -0
- esphome/core/config.py +57 -72
- esphome/core/defines.h +9 -1
- esphome/core/gpio.h +7 -0
- esphome/core/helpers.cpp +19 -15
- esphome/core/helpers.h +57 -8
- esphome/core/log.h +9 -7
- esphome/cpp_generator.py +2 -2
- esphome/espota2.py +3 -2
- esphome/loader.py +12 -4
- esphome/log.py +5 -7
- esphome/yaml_util.py +2 -2
- {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/METADATA +12 -7
- {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/RECORD +338 -289
- esphome/components/custom/binary_sensor/custom_binary_sensor.cpp +0 -16
- esphome/components/custom/binary_sensor/custom_binary_sensor.h +0 -26
- esphome/components/custom/climate/custom_climate.h +0 -22
- esphome/components/custom/cover/custom_cover.h +0 -21
- esphome/components/custom/light/custom_light_output.h +0 -24
- esphome/components/custom/output/custom_output.h +0 -37
- esphome/components/custom/sensor/custom_sensor.cpp +0 -16
- esphome/components/custom/sensor/custom_sensor.h +0 -24
- esphome/components/custom/switch/custom_switch.cpp +0 -16
- esphome/components/custom/switch/custom_switch.h +0 -24
- esphome/components/custom/text_sensor/custom_text_sensor.cpp +0 -16
- esphome/components/custom/text_sensor/custom_text_sensor.h +0 -26
- esphome/components/custom_component/custom_component.h +0 -28
- esphome/components/esp32_ble_server/ble_2901.cpp +0 -18
- esphome/components/esp32_ble_server/ble_2901.h +0 -19
- esphome/components/resistance_sampler/__init__.py +0 -6
- esphome/components/resistance_sampler/resistance_sampler.h +0 -10
- esphome/components/uptime/{sensor.py → sensor/__init__.py} +3 -3
- /esphome/components/uptime/{uptime_seconds_sensor.cpp → sensor/uptime_seconds_sensor.cpp} +0 -0
- /esphome/components/uptime/{uptime_seconds_sensor.h → sensor/uptime_seconds_sensor.h} +0 -0
- /esphome/components/uptime/{uptime_timestamp_sensor.cpp → sensor/uptime_timestamp_sensor.cpp} +0 -0
- /esphome/components/uptime/{uptime_timestamp_sensor.h → sensor/uptime_timestamp_sensor.h} +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/LICENSE +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/WHEEL +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/entry_points.txt +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/top_level.txt +0 -0
@@ -10,19 +10,19 @@ static const char *const TAG = "nextion";
|
|
10
10
|
// Sleep safe commands
|
11
11
|
void Nextion::soft_reset() { this->send_command_("rest"); }
|
12
12
|
|
13
|
-
void Nextion::set_wake_up_page(uint8_t
|
14
|
-
this->
|
13
|
+
void Nextion::set_wake_up_page(uint8_t wake_up_page) {
|
14
|
+
this->wake_up_page_ = wake_up_page;
|
15
|
+
this->add_no_result_to_queue_with_set_internal_("wake_up_page", "wup", wake_up_page, true);
|
15
16
|
}
|
16
17
|
|
17
|
-
void Nextion::
|
18
|
-
|
19
|
-
void Nextion::set_touch_sleep_timeout(uint16_t timeout) {
|
20
|
-
if (timeout < 3) {
|
18
|
+
void Nextion::set_touch_sleep_timeout(uint32_t touch_sleep_timeout) {
|
19
|
+
if (touch_sleep_timeout < 3) {
|
21
20
|
ESP_LOGD(TAG, "Sleep timeout out of bounds, range 3-65535");
|
22
21
|
return;
|
23
22
|
}
|
24
23
|
|
25
|
-
this->
|
24
|
+
this->touch_sleep_timeout_ = touch_sleep_timeout;
|
25
|
+
this->add_no_result_to_queue_with_set_internal_("touch_sleep_timeout", "thsp", touch_sleep_timeout, true);
|
26
26
|
}
|
27
27
|
|
28
28
|
void Nextion::sleep(bool sleep) {
|
@@ -54,7 +54,6 @@ bool Nextion::set_protocol_reparse_mode(bool active_mode) {
|
|
54
54
|
this->ignore_is_setup_ = false;
|
55
55
|
return all_commands_sent;
|
56
56
|
}
|
57
|
-
void Nextion::set_exit_reparse_on_start(bool exit_reparse) { this->exit_reparse_on_start_ = exit_reparse; }
|
58
57
|
|
59
58
|
// Set Colors - Background
|
60
59
|
void Nextion::set_component_background_color(const char *component, uint16_t color) {
|
@@ -191,8 +190,9 @@ void Nextion::set_backlight_brightness(float brightness) {
|
|
191
190
|
this->add_no_result_to_queue_with_printf_("backlight_brightness", "dim=%d", static_cast<int>(brightness * 100));
|
192
191
|
}
|
193
192
|
|
194
|
-
void Nextion::set_auto_wake_on_touch(bool
|
195
|
-
this->
|
193
|
+
void Nextion::set_auto_wake_on_touch(bool auto_wake_on_touch) {
|
194
|
+
this->auto_wake_on_touch_ = auto_wake_on_touch;
|
195
|
+
this->add_no_result_to_queue_with_set("auto_wake_on_touch", "thup", auto_wake_on_touch ? 1 : 0);
|
196
196
|
}
|
197
197
|
|
198
198
|
// General Component
|
esphome/components/ntc/sensor.py
CHANGED
@@ -2,7 +2,7 @@ from math import log
|
|
2
2
|
|
3
3
|
import esphome.config_validation as cv
|
4
4
|
import esphome.codegen as cg
|
5
|
-
from esphome.components import sensor
|
5
|
+
from esphome.components import sensor
|
6
6
|
from esphome.const import (
|
7
7
|
CONF_CALIBRATION,
|
8
8
|
CONF_REFERENCE_RESISTANCE,
|
@@ -15,8 +15,6 @@ from esphome.const import (
|
|
15
15
|
UNIT_CELSIUS,
|
16
16
|
)
|
17
17
|
|
18
|
-
AUTO_LOAD = ["resistance_sampler"]
|
19
|
-
|
20
18
|
ntc_ns = cg.esphome_ns.namespace("ntc")
|
21
19
|
NTC = ntc_ns.class_("NTC", cg.Component, sensor.Sensor)
|
22
20
|
|
@@ -126,7 +124,7 @@ CONFIG_SCHEMA = (
|
|
126
124
|
)
|
127
125
|
.extend(
|
128
126
|
{
|
129
|
-
cv.Required(CONF_SENSOR): cv.use_id(
|
127
|
+
cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor),
|
130
128
|
cv.Required(CONF_CALIBRATION): process_calibration,
|
131
129
|
}
|
132
130
|
)
|
@@ -4,14 +4,18 @@ from esphome import automation
|
|
4
4
|
import esphome.codegen as cg
|
5
5
|
from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent
|
6
6
|
from esphome.components.image import (
|
7
|
-
|
8
|
-
|
7
|
+
CONF_INVERT_ALPHA,
|
8
|
+
CONF_TRANSPARENCY,
|
9
|
+
IMAGE_SCHEMA,
|
9
10
|
Image_,
|
10
|
-
|
11
|
+
get_image_type_enum,
|
12
|
+
get_transparency_enum,
|
11
13
|
)
|
12
14
|
import esphome.config_validation as cv
|
13
15
|
from esphome.const import (
|
14
16
|
CONF_BUFFER_SIZE,
|
17
|
+
CONF_DITHER,
|
18
|
+
CONF_FILE,
|
15
19
|
CONF_FORMAT,
|
16
20
|
CONF_ID,
|
17
21
|
CONF_ON_ERROR,
|
@@ -23,7 +27,7 @@ from esphome.const import (
|
|
23
27
|
|
24
28
|
AUTO_LOAD = ["image"]
|
25
29
|
DEPENDENCIES = ["display", "http_request"]
|
26
|
-
CODEOWNERS = ["@guillempages"]
|
30
|
+
CODEOWNERS = ["@guillempages", "@clydebarrow"]
|
27
31
|
MULTI_CONF = True
|
28
32
|
|
29
33
|
CONF_ON_DOWNLOAD_FINISHED = "on_download_finished"
|
@@ -35,9 +39,54 @@ online_image_ns = cg.esphome_ns.namespace("online_image")
|
|
35
39
|
|
36
40
|
ImageFormat = online_image_ns.enum("ImageFormat")
|
37
41
|
|
38
|
-
FORMAT_PNG = "PNG"
|
39
42
|
|
40
|
-
|
43
|
+
class Format:
|
44
|
+
def __init__(self, image_type):
|
45
|
+
self.image_type = image_type
|
46
|
+
|
47
|
+
@property
|
48
|
+
def enum(self):
|
49
|
+
return getattr(ImageFormat, self.image_type)
|
50
|
+
|
51
|
+
def actions(self):
|
52
|
+
pass
|
53
|
+
|
54
|
+
|
55
|
+
class BMPFormat(Format):
|
56
|
+
def __init__(self):
|
57
|
+
super().__init__("BMP")
|
58
|
+
|
59
|
+
def actions(self):
|
60
|
+
cg.add_define("USE_ONLINE_IMAGE_BMP_SUPPORT")
|
61
|
+
|
62
|
+
|
63
|
+
class JPEGFormat(Format):
|
64
|
+
def __init__(self):
|
65
|
+
super().__init__("JPEG")
|
66
|
+
|
67
|
+
def actions(self):
|
68
|
+
cg.add_define("USE_ONLINE_IMAGE_JPEG_SUPPORT")
|
69
|
+
cg.add_library("JPEGDEC", None, "https://github.com/bitbank2/JPEGDEC#ca1e0f2")
|
70
|
+
|
71
|
+
|
72
|
+
class PNGFormat(Format):
|
73
|
+
def __init__(self):
|
74
|
+
super().__init__("PNG")
|
75
|
+
|
76
|
+
def actions(self):
|
77
|
+
cg.add_define("USE_ONLINE_IMAGE_PNG_SUPPORT")
|
78
|
+
cg.add_library("pngle", "1.0.2")
|
79
|
+
|
80
|
+
|
81
|
+
IMAGE_FORMATS = {
|
82
|
+
x.image_type: x
|
83
|
+
for x in (
|
84
|
+
BMPFormat(),
|
85
|
+
JPEGFormat(),
|
86
|
+
PNGFormat(),
|
87
|
+
)
|
88
|
+
}
|
89
|
+
IMAGE_FORMATS.update({"JPG": IMAGE_FORMATS["JPEG"]})
|
41
90
|
|
42
91
|
OnlineImage = online_image_ns.class_("OnlineImage", cg.PollingComponent, Image_)
|
43
92
|
|
@@ -57,48 +106,54 @@ DownloadErrorTrigger = online_image_ns.class_(
|
|
57
106
|
"DownloadErrorTrigger", automation.Trigger.template()
|
58
107
|
)
|
59
108
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
cv.
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
cv.Optional(CONF_RESIZE): cv.dimensions,
|
68
|
-
cv.Optional(CONF_TYPE, default="BINARY"): cv.enum(IMAGE_TYPE, upper=True),
|
69
|
-
# Not setting default here on purpose; the default depends on the image type,
|
70
|
-
# and thus will be set in the "validate_cross_dependencies" validator.
|
71
|
-
cv.Optional(CONF_USE_TRANSPARENCY): cv.boolean,
|
72
|
-
#
|
73
|
-
# Online Image specific options
|
74
|
-
#
|
75
|
-
cv.Required(CONF_URL): cv.url,
|
76
|
-
cv.Required(CONF_FORMAT): cv.enum(IMAGE_FORMAT, upper=True),
|
77
|
-
cv.Optional(CONF_PLACEHOLDER): cv.use_id(Image_),
|
78
|
-
cv.Optional(CONF_BUFFER_SIZE, default=2048): cv.int_range(256, 65536),
|
79
|
-
cv.Optional(CONF_ON_DOWNLOAD_FINISHED): automation.validate_automation(
|
80
|
-
{
|
81
|
-
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DownloadFinishedTrigger),
|
82
|
-
}
|
83
|
-
),
|
84
|
-
cv.Optional(CONF_ON_ERROR): automation.validate_automation(
|
85
|
-
{
|
86
|
-
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DownloadErrorTrigger),
|
87
|
-
}
|
88
|
-
),
|
109
|
+
|
110
|
+
def remove_options(*options):
|
111
|
+
return {
|
112
|
+
cv.Optional(option): cv.invalid(
|
113
|
+
f"{option} is an invalid option for online_image"
|
114
|
+
)
|
115
|
+
for option in options
|
89
116
|
}
|
90
|
-
|
117
|
+
|
118
|
+
|
119
|
+
ONLINE_IMAGE_SCHEMA = (
|
120
|
+
IMAGE_SCHEMA.extend(remove_options(CONF_FILE, CONF_INVERT_ALPHA, CONF_DITHER))
|
121
|
+
.extend(
|
122
|
+
{
|
123
|
+
cv.Required(CONF_ID): cv.declare_id(OnlineImage),
|
124
|
+
cv.GenerateID(CONF_HTTP_REQUEST_ID): cv.use_id(HttpRequestComponent),
|
125
|
+
# Online Image specific options
|
126
|
+
cv.Required(CONF_URL): cv.url,
|
127
|
+
cv.Required(CONF_FORMAT): cv.one_of(*IMAGE_FORMATS, upper=True),
|
128
|
+
cv.Optional(CONF_PLACEHOLDER): cv.use_id(Image_),
|
129
|
+
cv.Optional(CONF_BUFFER_SIZE, default=65536): cv.int_range(256, 65536),
|
130
|
+
cv.Optional(CONF_ON_DOWNLOAD_FINISHED): automation.validate_automation(
|
131
|
+
{
|
132
|
+
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
133
|
+
DownloadFinishedTrigger
|
134
|
+
),
|
135
|
+
}
|
136
|
+
),
|
137
|
+
cv.Optional(CONF_ON_ERROR): automation.validate_automation(
|
138
|
+
{
|
139
|
+
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DownloadErrorTrigger),
|
140
|
+
}
|
141
|
+
),
|
142
|
+
}
|
143
|
+
)
|
144
|
+
.extend(cv.polling_component_schema("never"))
|
145
|
+
)
|
91
146
|
|
92
147
|
CONFIG_SCHEMA = cv.Schema(
|
93
148
|
cv.All(
|
94
149
|
ONLINE_IMAGE_SCHEMA,
|
95
|
-
validate_cross_dependencies,
|
96
150
|
cv.require_framework_version(
|
97
151
|
# esp8266 not supported yet; if enabled in the future, minimum version of 2.7.0 is needed
|
98
152
|
# esp8266_arduino=cv.Version(2, 7, 0),
|
99
153
|
esp32_arduino=cv.Version(0, 0, 0),
|
100
154
|
esp_idf=cv.Version(4, 0, 0),
|
101
155
|
rp2040_arduino=cv.Version(0, 0, 0),
|
156
|
+
host=cv.Version(0, 0, 0),
|
102
157
|
),
|
103
158
|
)
|
104
159
|
)
|
@@ -132,29 +187,26 @@ async def online_image_action_to_code(config, action_id, template_arg, args):
|
|
132
187
|
|
133
188
|
|
134
189
|
async def to_code(config):
|
135
|
-
|
136
|
-
|
137
|
-
cg.add_define("USE_ONLINE_IMAGE_PNG_SUPPORT")
|
138
|
-
cg.add_library("pngle", "1.0.2")
|
190
|
+
image_format = IMAGE_FORMATS[config[CONF_FORMAT]]
|
191
|
+
image_format.actions()
|
139
192
|
|
140
193
|
url = config[CONF_URL]
|
141
194
|
width, height = config.get(CONF_RESIZE, (0, 0))
|
142
|
-
transparent = config[
|
195
|
+
transparent = get_transparency_enum(config[CONF_TRANSPARENCY])
|
143
196
|
|
144
197
|
var = cg.new_Pvariable(
|
145
198
|
config[CONF_ID],
|
146
199
|
url,
|
147
200
|
width,
|
148
201
|
height,
|
149
|
-
|
150
|
-
config[CONF_TYPE],
|
202
|
+
image_format.enum,
|
203
|
+
get_image_type_enum(config[CONF_TYPE]),
|
204
|
+
transparent,
|
151
205
|
config[CONF_BUFFER_SIZE],
|
152
206
|
)
|
153
207
|
await cg.register_component(var, config)
|
154
208
|
await cg.register_parented(var, config[CONF_HTTP_REQUEST_ID])
|
155
209
|
|
156
|
-
cg.add(var.set_transparency(transparent))
|
157
|
-
|
158
210
|
if placeholder_id := config.get(CONF_PLACEHOLDER):
|
159
211
|
placeholder = await cg.get_variable(placeholder_id)
|
160
212
|
cg.add(var.set_placeholder(placeholder))
|
@@ -0,0 +1,101 @@
|
|
1
|
+
#include "bmp_image.h"
|
2
|
+
|
3
|
+
#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
|
4
|
+
|
5
|
+
#include "esphome/components/display/display.h"
|
6
|
+
#include "esphome/core/helpers.h"
|
7
|
+
#include "esphome/core/log.h"
|
8
|
+
|
9
|
+
namespace esphome {
|
10
|
+
namespace online_image {
|
11
|
+
|
12
|
+
static const char *const TAG = "online_image.bmp";
|
13
|
+
|
14
|
+
int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) {
|
15
|
+
size_t index = 0;
|
16
|
+
if (this->current_index_ == 0 && index == 0 && size > 14) {
|
17
|
+
/**
|
18
|
+
* BMP file format:
|
19
|
+
* 0-1: Signature (BM)
|
20
|
+
* 2-5: File size
|
21
|
+
* 6-9: Reserved
|
22
|
+
* 10-13: Pixel data offset
|
23
|
+
*
|
24
|
+
* Integer values are stored in little-endian format.
|
25
|
+
*/
|
26
|
+
|
27
|
+
// Check if the file is a BMP image
|
28
|
+
if (buffer[0] != 'B' || buffer[1] != 'M') {
|
29
|
+
ESP_LOGE(TAG, "Not a BMP file");
|
30
|
+
return DECODE_ERROR_INVALID_TYPE;
|
31
|
+
}
|
32
|
+
|
33
|
+
this->download_size_ = encode_uint32(buffer[5], buffer[4], buffer[3], buffer[2]);
|
34
|
+
this->data_offset_ = encode_uint32(buffer[13], buffer[12], buffer[11], buffer[10]);
|
35
|
+
|
36
|
+
this->current_index_ = 14;
|
37
|
+
index = 14;
|
38
|
+
}
|
39
|
+
if (this->current_index_ == 14 && index == 14 && size > this->data_offset_) {
|
40
|
+
/**
|
41
|
+
* BMP DIB header:
|
42
|
+
* 14-17: DIB header size
|
43
|
+
* 18-21: Image width
|
44
|
+
* 22-25: Image height
|
45
|
+
* 26-27: Number of color planes
|
46
|
+
* 28-29: Bits per pixel
|
47
|
+
* 30-33: Compression method
|
48
|
+
* 34-37: Image data size
|
49
|
+
* 38-41: Horizontal resolution
|
50
|
+
* 42-45: Vertical resolution
|
51
|
+
* 46-49: Number of colors in the color table
|
52
|
+
*/
|
53
|
+
|
54
|
+
this->width_ = encode_uint32(buffer[21], buffer[20], buffer[19], buffer[18]);
|
55
|
+
this->height_ = encode_uint32(buffer[25], buffer[24], buffer[23], buffer[22]);
|
56
|
+
this->bits_per_pixel_ = encode_uint16(buffer[29], buffer[28]);
|
57
|
+
this->compression_method_ = encode_uint32(buffer[33], buffer[32], buffer[31], buffer[30]);
|
58
|
+
this->image_data_size_ = encode_uint32(buffer[37], buffer[36], buffer[35], buffer[34]);
|
59
|
+
this->color_table_entries_ = encode_uint32(buffer[49], buffer[48], buffer[47], buffer[46]);
|
60
|
+
|
61
|
+
switch (this->bits_per_pixel_) {
|
62
|
+
case 1:
|
63
|
+
this->width_bytes_ = (this->width_ % 8 == 0) ? (this->width_ / 8) : (this->width_ / 8 + 1);
|
64
|
+
break;
|
65
|
+
default:
|
66
|
+
ESP_LOGE(TAG, "Unsupported bits per pixel: %d", this->bits_per_pixel_);
|
67
|
+
return DECODE_ERROR_UNSUPPORTED_FORMAT;
|
68
|
+
}
|
69
|
+
|
70
|
+
if (this->compression_method_ != 0) {
|
71
|
+
ESP_LOGE(TAG, "Unsupported compression method: %d", this->compression_method_);
|
72
|
+
return DECODE_ERROR_UNSUPPORTED_FORMAT;
|
73
|
+
}
|
74
|
+
|
75
|
+
if (!this->set_size(this->width_, this->height_)) {
|
76
|
+
return DECODE_ERROR_OUT_OF_MEMORY;
|
77
|
+
}
|
78
|
+
this->current_index_ = this->data_offset_;
|
79
|
+
index = this->data_offset_;
|
80
|
+
}
|
81
|
+
while (index < size) {
|
82
|
+
size_t paint_index = this->current_index_ - this->data_offset_;
|
83
|
+
|
84
|
+
uint8_t current_byte = buffer[index];
|
85
|
+
for (uint8_t i = 0; i < 8; i++) {
|
86
|
+
size_t x = (paint_index * 8) % this->width_ + i;
|
87
|
+
size_t y = (this->height_ - 1) - (paint_index / this->width_bytes_);
|
88
|
+
Color c = (current_byte & (1 << (7 - i))) ? display::COLOR_ON : display::COLOR_OFF;
|
89
|
+
this->draw(x, y, 1, 1, c);
|
90
|
+
}
|
91
|
+
this->current_index_++;
|
92
|
+
index++;
|
93
|
+
}
|
94
|
+
this->decoded_bytes_ += size;
|
95
|
+
return size;
|
96
|
+
};
|
97
|
+
|
98
|
+
} // namespace online_image
|
99
|
+
} // namespace esphome
|
100
|
+
|
101
|
+
#endif // USE_ONLINE_IMAGE_BMP_SUPPORT
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "esphome/core/defines.h"
|
4
|
+
#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
|
5
|
+
|
6
|
+
#include "image_decoder.h"
|
7
|
+
|
8
|
+
namespace esphome {
|
9
|
+
namespace online_image {
|
10
|
+
|
11
|
+
/**
|
12
|
+
* @brief Image decoder specialization for PNG images.
|
13
|
+
*/
|
14
|
+
class BmpDecoder : public ImageDecoder {
|
15
|
+
public:
|
16
|
+
/**
|
17
|
+
* @brief Construct a new BMP Decoder object.
|
18
|
+
*
|
19
|
+
* @param display The image to decode the stream into.
|
20
|
+
*/
|
21
|
+
BmpDecoder(OnlineImage *image) : ImageDecoder(image) {}
|
22
|
+
|
23
|
+
int HOT decode(uint8_t *buffer, size_t size) override;
|
24
|
+
|
25
|
+
protected:
|
26
|
+
size_t current_index_{0};
|
27
|
+
ssize_t width_{0};
|
28
|
+
ssize_t height_{0};
|
29
|
+
uint16_t bits_per_pixel_{0};
|
30
|
+
uint32_t compression_method_{0};
|
31
|
+
uint32_t image_data_size_{0};
|
32
|
+
uint32_t color_table_entries_{0};
|
33
|
+
size_t width_bytes_{0};
|
34
|
+
size_t data_offset_{0};
|
35
|
+
};
|
36
|
+
|
37
|
+
} // namespace online_image
|
38
|
+
} // namespace esphome
|
39
|
+
|
40
|
+
#endif // USE_ONLINE_IMAGE_BMP_SUPPORT
|
@@ -8,10 +8,11 @@ namespace online_image {
|
|
8
8
|
|
9
9
|
static const char *const TAG = "online_image.decoder";
|
10
10
|
|
11
|
-
|
12
|
-
this->image_->resize_(width, height);
|
11
|
+
bool ImageDecoder::set_size(int width, int height) {
|
12
|
+
bool resized = this->image_->resize_(width, height);
|
13
13
|
this->x_scale_ = static_cast<double>(this->image_->buffer_width_) / width;
|
14
14
|
this->y_scale_ = static_cast<double>(this->image_->buffer_height_) / height;
|
15
|
+
return resized;
|
15
16
|
}
|
16
17
|
|
17
18
|
void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) {
|
@@ -24,6 +25,15 @@ void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) {
|
|
24
25
|
}
|
25
26
|
}
|
26
27
|
|
28
|
+
DownloadBuffer::DownloadBuffer(size_t size) : size_(size) {
|
29
|
+
this->buffer_ = this->allocator_.allocate(size);
|
30
|
+
this->reset();
|
31
|
+
if (!this->buffer_) {
|
32
|
+
ESP_LOGE(TAG, "Initial allocation of download buffer failed!");
|
33
|
+
this->size_ = 0;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
27
37
|
uint8_t *DownloadBuffer::data(size_t offset) {
|
28
38
|
if (offset > this->size_) {
|
29
39
|
ESP_LOGE(TAG, "Tried to access beyond download buffer bounds!!!");
|
@@ -40,5 +50,21 @@ size_t DownloadBuffer::read(size_t len) {
|
|
40
50
|
return this->unread_;
|
41
51
|
}
|
42
52
|
|
53
|
+
size_t DownloadBuffer::resize(size_t size) {
|
54
|
+
if (this->size_ == size) {
|
55
|
+
return size;
|
56
|
+
}
|
57
|
+
this->allocator_.deallocate(this->buffer_, this->size_);
|
58
|
+
this->buffer_ = this->allocator_.allocate(size);
|
59
|
+
this->reset();
|
60
|
+
if (this->buffer_) {
|
61
|
+
this->size_ = size;
|
62
|
+
return size;
|
63
|
+
} else {
|
64
|
+
this->size_ = 0;
|
65
|
+
return 0;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
43
69
|
} // namespace online_image
|
44
70
|
} // namespace esphome
|
@@ -1,10 +1,15 @@
|
|
1
1
|
#pragma once
|
2
|
-
#include "esphome/core/defines.h"
|
3
2
|
#include "esphome/core/color.h"
|
4
3
|
|
5
4
|
namespace esphome {
|
6
5
|
namespace online_image {
|
7
6
|
|
7
|
+
enum DecodeError : int {
|
8
|
+
DECODE_ERROR_INVALID_TYPE = -1,
|
9
|
+
DECODE_ERROR_UNSUPPORTED_FORMAT = -2,
|
10
|
+
DECODE_ERROR_OUT_OF_MEMORY = -3,
|
11
|
+
};
|
12
|
+
|
8
13
|
class OnlineImage;
|
9
14
|
|
10
15
|
/**
|
@@ -23,9 +28,13 @@ class ImageDecoder {
|
|
23
28
|
/**
|
24
29
|
* @brief Initialize the decoder.
|
25
30
|
*
|
26
|
-
* @param download_size The total number of bytes that need to be
|
31
|
+
* @param download_size The total number of bytes that need to be downloaded for the image.
|
32
|
+
* @return int Returns 0 on success, a {@see DecodeError} value in case of an error.
|
27
33
|
*/
|
28
|
-
virtual
|
34
|
+
virtual int prepare(size_t download_size) {
|
35
|
+
this->download_size_ = download_size;
|
36
|
+
return 0;
|
37
|
+
}
|
29
38
|
|
30
39
|
/**
|
31
40
|
* @brief Decode a part of the image. It will try reading from the buffer.
|
@@ -38,7 +47,7 @@ class ImageDecoder {
|
|
38
47
|
* @return int The amount of bytes read. It can be 0 if the buffer does not have enough content to meaningfully
|
39
48
|
* decode anything, or negative in case of a decoding error.
|
40
49
|
*/
|
41
|
-
virtual int decode(uint8_t *buffer, size_t size);
|
50
|
+
virtual int decode(uint8_t *buffer, size_t size) = 0;
|
42
51
|
|
43
52
|
/**
|
44
53
|
* @brief Request the image to be resized once the actual dimensions are known.
|
@@ -46,11 +55,12 @@ class ImageDecoder {
|
|
46
55
|
*
|
47
56
|
* @param width The image's width.
|
48
57
|
* @param height The image's height.
|
58
|
+
* @return true if the image was resized, false otherwise.
|
49
59
|
*/
|
50
|
-
|
60
|
+
bool set_size(int width, int height);
|
51
61
|
|
52
62
|
/**
|
53
|
-
* @brief
|
63
|
+
* @brief Fill a rectangle on the display_buffer using the defined color.
|
54
64
|
* Will check the given coordinates for out-of-bounds, and clip the rectangle accordingly.
|
55
65
|
* In case of binary displays, the color will be converted to binary as well.
|
56
66
|
* Called by the callback functions, to be able to access the parent Image class.
|
@@ -59,7 +69,7 @@ class ImageDecoder {
|
|
59
69
|
* @param y The top-most coordinate of the rectangle.
|
60
70
|
* @param w The width of the rectangle.
|
61
71
|
* @param h The height of the rectangle.
|
62
|
-
* @param color The color
|
72
|
+
* @param color The fill color
|
63
73
|
*/
|
64
74
|
void draw(int x, int y, int w, int h, const Color &color);
|
65
75
|
|
@@ -67,20 +77,17 @@ class ImageDecoder {
|
|
67
77
|
|
68
78
|
protected:
|
69
79
|
OnlineImage *image_;
|
70
|
-
// Initializing to 1, to ensure it is
|
80
|
+
// Initializing to 1, to ensure it is distinguishable from initial "decoded_bytes_".
|
71
81
|
// Will be overwritten anyway once the download size is known.
|
72
|
-
|
73
|
-
|
82
|
+
size_t download_size_ = 1;
|
83
|
+
size_t decoded_bytes_ = 0;
|
74
84
|
double x_scale_ = 1.0;
|
75
85
|
double y_scale_ = 1.0;
|
76
86
|
};
|
77
87
|
|
78
88
|
class DownloadBuffer {
|
79
89
|
public:
|
80
|
-
DownloadBuffer(size_t size)
|
81
|
-
this->buffer_ = this->allocator_.allocate(size);
|
82
|
-
this->reset();
|
83
|
-
}
|
90
|
+
DownloadBuffer(size_t size);
|
84
91
|
|
85
92
|
virtual ~DownloadBuffer() { this->allocator_.deallocate(this->buffer_, this->size_); }
|
86
93
|
|
@@ -100,8 +107,10 @@ class DownloadBuffer {
|
|
100
107
|
|
101
108
|
void reset() { this->unread_ = 0; }
|
102
109
|
|
110
|
+
size_t resize(size_t size);
|
111
|
+
|
103
112
|
protected:
|
104
|
-
|
113
|
+
RAMAllocator<uint8_t> allocator_{};
|
105
114
|
uint8_t *buffer_;
|
106
115
|
size_t size_;
|
107
116
|
/** Total number of downloaded bytes not yet read. */
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#include "jpeg_image.h"
|
2
|
+
#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT
|
3
|
+
|
4
|
+
#include "esphome/components/display/display_buffer.h"
|
5
|
+
#include "esphome/core/application.h"
|
6
|
+
#include "esphome/core/helpers.h"
|
7
|
+
#include "esphome/core/log.h"
|
8
|
+
|
9
|
+
#include "online_image.h"
|
10
|
+
static const char *const TAG = "online_image.jpeg";
|
11
|
+
|
12
|
+
namespace esphome {
|
13
|
+
namespace online_image {
|
14
|
+
|
15
|
+
/**
|
16
|
+
* @brief Callback method that will be called by the JPEGDEC engine when a chunk
|
17
|
+
* of the image is decoded.
|
18
|
+
*
|
19
|
+
* @param jpeg The JPEGDRAW object, including the context data.
|
20
|
+
*/
|
21
|
+
static int draw_callback(JPEGDRAW *jpeg) {
|
22
|
+
ImageDecoder *decoder = (ImageDecoder *) jpeg->pUser;
|
23
|
+
|
24
|
+
// Some very big images take too long to decode, so feed the watchdog on each callback
|
25
|
+
// to avoid crashing.
|
26
|
+
App.feed_wdt();
|
27
|
+
size_t position = 0;
|
28
|
+
for (size_t y = 0; y < jpeg->iHeight; y++) {
|
29
|
+
for (size_t x = 0; x < jpeg->iWidth; x++) {
|
30
|
+
auto rg = decode_value(jpeg->pPixels[position++]);
|
31
|
+
auto ba = decode_value(jpeg->pPixels[position++]);
|
32
|
+
Color color(rg[1], rg[0], ba[1], ba[0]);
|
33
|
+
|
34
|
+
if (!decoder) {
|
35
|
+
ESP_LOGE(TAG, "Decoder pointer is null!");
|
36
|
+
return 0;
|
37
|
+
}
|
38
|
+
decoder->draw(jpeg->x + x, jpeg->y + y, 1, 1, color);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
return 1;
|
42
|
+
}
|
43
|
+
|
44
|
+
int JpegDecoder::prepare(size_t download_size) {
|
45
|
+
ImageDecoder::prepare(download_size);
|
46
|
+
auto size = this->image_->resize_download_buffer(download_size);
|
47
|
+
if (size < download_size) {
|
48
|
+
ESP_LOGE(TAG, "Download buffer resize failed!");
|
49
|
+
return DECODE_ERROR_OUT_OF_MEMORY;
|
50
|
+
}
|
51
|
+
return 0;
|
52
|
+
}
|
53
|
+
|
54
|
+
int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
|
55
|
+
if (size < this->download_size_) {
|
56
|
+
ESP_LOGV(TAG, "Download not complete. Size: %d/%d", size, this->download_size_);
|
57
|
+
return 0;
|
58
|
+
}
|
59
|
+
|
60
|
+
if (!this->jpeg_.openRAM(buffer, size, draw_callback)) {
|
61
|
+
ESP_LOGE(TAG, "Could not open image for decoding.");
|
62
|
+
return DECODE_ERROR_INVALID_TYPE;
|
63
|
+
}
|
64
|
+
auto jpeg_type = this->jpeg_.getJPEGType();
|
65
|
+
if (jpeg_type == JPEG_MODE_INVALID) {
|
66
|
+
ESP_LOGE(TAG, "Unsupported JPEG image");
|
67
|
+
return DECODE_ERROR_INVALID_TYPE;
|
68
|
+
} else if (jpeg_type == JPEG_MODE_PROGRESSIVE) {
|
69
|
+
ESP_LOGE(TAG, "Progressive JPEG images not supported");
|
70
|
+
return DECODE_ERROR_INVALID_TYPE;
|
71
|
+
}
|
72
|
+
ESP_LOGD(TAG, "Image size: %d x %d, bpp: %d", this->jpeg_.getWidth(), this->jpeg_.getHeight(), this->jpeg_.getBpp());
|
73
|
+
|
74
|
+
this->jpeg_.setUserPointer(this);
|
75
|
+
this->jpeg_.setPixelType(RGB8888);
|
76
|
+
this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight());
|
77
|
+
if (!this->jpeg_.decode(0, 0, 0)) {
|
78
|
+
ESP_LOGE(TAG, "Error while decoding.");
|
79
|
+
this->jpeg_.close();
|
80
|
+
return DECODE_ERROR_UNSUPPORTED_FORMAT;
|
81
|
+
}
|
82
|
+
this->decoded_bytes_ = size;
|
83
|
+
this->jpeg_.close();
|
84
|
+
return size;
|
85
|
+
}
|
86
|
+
|
87
|
+
} // namespace online_image
|
88
|
+
} // namespace esphome
|
89
|
+
|
90
|
+
#endif // USE_ONLINE_IMAGE_JPEG_SUPPORT
|