esphome 2024.7.3__py3-none-any.whl → 2024.8.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 +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 +79 -51
- 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 +9 -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/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/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 +504 -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 +279 -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 +426 -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 +400 -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/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 +10 -11
- 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/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/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 +5 -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/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 +41 -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.3.dist-info → esphome-2024.8.0b1.dist-info}/METADATA +3 -3
- {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/RECORD +341 -235
- {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/LICENSE +0 -0
- {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/WHEEL +0 -0
- {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/entry_points.txt +0 -0
- {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
from esphome.components import light
|
3
|
+
from esphome.components.light import LightOutput
|
4
|
+
import esphome.config_validation as cv
|
5
|
+
from esphome.const import CONF_GAMMA_CORRECT, CONF_LED, CONF_OUTPUT_ID
|
6
|
+
|
7
|
+
from ..defines import CONF_LVGL_ID
|
8
|
+
from ..lvcode import LvContext
|
9
|
+
from ..schemas import LVGL_SCHEMA
|
10
|
+
from ..types import LvType, lvgl_ns
|
11
|
+
from ..widgets import get_widgets
|
12
|
+
|
13
|
+
lv_led_t = LvType("lv_led_t")
|
14
|
+
LVLight = lvgl_ns.class_("LVLight", LightOutput)
|
15
|
+
CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend(
|
16
|
+
{
|
17
|
+
cv.Optional(CONF_GAMMA_CORRECT, default=0.0): cv.positive_float,
|
18
|
+
cv.Required(CONF_LED): cv.use_id(lv_led_t),
|
19
|
+
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(LVLight),
|
20
|
+
}
|
21
|
+
).extend(LVGL_SCHEMA)
|
22
|
+
|
23
|
+
|
24
|
+
async def to_code(config):
|
25
|
+
var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
|
26
|
+
await light.register_light(var, config)
|
27
|
+
|
28
|
+
paren = await cg.get_variable(config[CONF_LVGL_ID])
|
29
|
+
widget = await get_widgets(config, CONF_LED)
|
30
|
+
widget = widget[0]
|
31
|
+
async with LvContext(paren) as ctx:
|
32
|
+
ctx.add(var.set_obj(widget.obj))
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "esphome/core/component.h"
|
4
|
+
#include "esphome/components/light/light_output.h"
|
5
|
+
#include "../lvgl_esphome.h"
|
6
|
+
|
7
|
+
namespace esphome {
|
8
|
+
namespace lvgl {
|
9
|
+
|
10
|
+
class LVLight : public light::LightOutput {
|
11
|
+
public:
|
12
|
+
light::LightTraits get_traits() override {
|
13
|
+
auto traits = light::LightTraits();
|
14
|
+
traits.set_supported_color_modes({light::ColorMode::RGB});
|
15
|
+
return traits;
|
16
|
+
}
|
17
|
+
void write_state(light::LightState *state) override {
|
18
|
+
float red, green, blue;
|
19
|
+
state->current_values_as_rgb(&red, &green, &blue, false);
|
20
|
+
auto color = lv_color_make(red * 255, green * 255, blue * 255);
|
21
|
+
if (this->obj_ != nullptr) {
|
22
|
+
this->set_value_(color);
|
23
|
+
} else {
|
24
|
+
this->initial_value_ = color;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
void set_obj(lv_obj_t *obj) {
|
29
|
+
this->obj_ = obj;
|
30
|
+
if (this->initial_value_) {
|
31
|
+
lv_led_set_color(obj, this->initial_value_.value());
|
32
|
+
lv_led_on(obj);
|
33
|
+
this->initial_value_.reset();
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
protected:
|
38
|
+
void set_value_(lv_color_t value) {
|
39
|
+
lv_led_set_color(this->obj_, value);
|
40
|
+
lv_led_on(this->obj_);
|
41
|
+
lv_event_send(this->obj_, lv_api_event, nullptr);
|
42
|
+
}
|
43
|
+
lv_obj_t *obj_{};
|
44
|
+
optional<lv_color_t> initial_value_{};
|
45
|
+
};
|
46
|
+
|
47
|
+
} // namespace lvgl
|
48
|
+
} // namespace esphome
|
@@ -0,0 +1,279 @@
|
|
1
|
+
from typing import Union
|
2
|
+
|
3
|
+
import esphome.codegen as cg
|
4
|
+
from esphome.components.binary_sensor import BinarySensor
|
5
|
+
from esphome.components.color import ColorStruct
|
6
|
+
from esphome.components.font import Font
|
7
|
+
from esphome.components.image import Image_
|
8
|
+
from esphome.components.sensor import Sensor
|
9
|
+
from esphome.components.text_sensor import TextSensor
|
10
|
+
import esphome.config_validation as cv
|
11
|
+
from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT, CONF_VALUE
|
12
|
+
from esphome.core import HexInt
|
13
|
+
from esphome.cpp_generator import MockObj
|
14
|
+
from esphome.cpp_types import uint32
|
15
|
+
from esphome.helpers import cpp_string_escape
|
16
|
+
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
17
|
+
|
18
|
+
from . import types as ty
|
19
|
+
from .defines import (
|
20
|
+
CONF_END_VALUE,
|
21
|
+
CONF_START_VALUE,
|
22
|
+
LV_FONTS,
|
23
|
+
LValidator,
|
24
|
+
LvConstant,
|
25
|
+
literal,
|
26
|
+
)
|
27
|
+
from .helpers import (
|
28
|
+
esphome_fonts_used,
|
29
|
+
lv_fonts_used,
|
30
|
+
lvgl_components_required,
|
31
|
+
requires_component,
|
32
|
+
)
|
33
|
+
from .lvcode import lv_expr
|
34
|
+
from .types import lv_font_t, lv_img_t
|
35
|
+
|
36
|
+
opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER")
|
37
|
+
|
38
|
+
|
39
|
+
@schema_extractor("one_of")
|
40
|
+
def opacity_validator(value):
|
41
|
+
if value == SCHEMA_EXTRACT:
|
42
|
+
return opacity_consts.choices
|
43
|
+
value = cv.Any(cv.percentage, opacity_consts.one_of)(value)
|
44
|
+
if isinstance(value, float):
|
45
|
+
return int(value * 255)
|
46
|
+
return value
|
47
|
+
|
48
|
+
|
49
|
+
opacity = LValidator(opacity_validator, uint32, retmapper=literal)
|
50
|
+
|
51
|
+
|
52
|
+
@schema_extractor("one_of")
|
53
|
+
def color(value):
|
54
|
+
if value == SCHEMA_EXTRACT:
|
55
|
+
return ["hex color value", "color ID"]
|
56
|
+
if isinstance(value, int):
|
57
|
+
return value
|
58
|
+
return cv.use_id(ColorStruct)(value)
|
59
|
+
|
60
|
+
|
61
|
+
def color_retmapper(value):
|
62
|
+
if isinstance(value, cv.Lambda):
|
63
|
+
return cv.returning_lambda(value)
|
64
|
+
if isinstance(value, int):
|
65
|
+
hexval = HexInt(value)
|
66
|
+
return lv_expr.color_hex(hexval)
|
67
|
+
# Must be an id
|
68
|
+
lvgl_components_required.add(CONF_COLOR)
|
69
|
+
return lv_expr.color_from(MockObj(value))
|
70
|
+
|
71
|
+
|
72
|
+
def option_string(value):
|
73
|
+
value = cv.string(value).strip()
|
74
|
+
if value.find("\n") != -1:
|
75
|
+
raise cv.Invalid("Options strings must not contain newlines")
|
76
|
+
return value
|
77
|
+
|
78
|
+
|
79
|
+
lv_color = LValidator(color, ty.lv_color_t, retmapper=color_retmapper)
|
80
|
+
|
81
|
+
|
82
|
+
def pixels_or_percent_validator(value):
|
83
|
+
"""A length in one axis - either a number (pixels) or a percentage"""
|
84
|
+
if value == SCHEMA_EXTRACT:
|
85
|
+
return ["pixels", "..%"]
|
86
|
+
if isinstance(value, int):
|
87
|
+
return cv.int_(value)
|
88
|
+
# Will throw an exception if not a percentage.
|
89
|
+
return f"lv_pct({int(cv.percentage(value) * 100)})"
|
90
|
+
|
91
|
+
|
92
|
+
pixels_or_percent = LValidator(pixels_or_percent_validator, uint32, retmapper=literal)
|
93
|
+
|
94
|
+
|
95
|
+
def zoom(value):
|
96
|
+
value = cv.float_range(0.1, 10.0)(value)
|
97
|
+
return int(value * 256)
|
98
|
+
|
99
|
+
|
100
|
+
def angle(value):
|
101
|
+
"""
|
102
|
+
Validation for an angle in degrees, converted to an integer representing 0.1deg units
|
103
|
+
:param value: The input in the range 0..360
|
104
|
+
:return: An angle in 1/10 degree units.
|
105
|
+
"""
|
106
|
+
return int(cv.float_range(0.0, 360.0)(cv.angle(value)) * 10)
|
107
|
+
|
108
|
+
|
109
|
+
@schema_extractor("one_of")
|
110
|
+
def size_validator(value):
|
111
|
+
"""A size in one axis - one of "size_content", a number (pixels) or a percentage"""
|
112
|
+
if value == SCHEMA_EXTRACT:
|
113
|
+
return ["size_content", "pixels", "..%"]
|
114
|
+
if isinstance(value, str) and value.lower().endswith("px"):
|
115
|
+
value = cv.int_(value[:-2])
|
116
|
+
if isinstance(value, str) and not value.endswith("%"):
|
117
|
+
if value.upper() == "SIZE_CONTENT":
|
118
|
+
return "LV_SIZE_CONTENT"
|
119
|
+
raise cv.Invalid("must be 'size_content', a pixel position or a percentage")
|
120
|
+
if isinstance(value, int):
|
121
|
+
return cv.int_(value)
|
122
|
+
# Will throw an exception if not a percentage.
|
123
|
+
return f"lv_pct({int(cv.percentage(value) * 100)})"
|
124
|
+
|
125
|
+
|
126
|
+
size = LValidator(size_validator, uint32, retmapper=literal)
|
127
|
+
|
128
|
+
radius_consts = LvConstant("LV_RADIUS_", "CIRCLE")
|
129
|
+
|
130
|
+
|
131
|
+
@schema_extractor("one_of")
|
132
|
+
def radius_validator(value):
|
133
|
+
if value == SCHEMA_EXTRACT:
|
134
|
+
return radius_consts.choices
|
135
|
+
value = cv.Any(size, cv.percentage, radius_consts.one_of)(value)
|
136
|
+
if isinstance(value, float):
|
137
|
+
return int(value * 255)
|
138
|
+
return value
|
139
|
+
|
140
|
+
|
141
|
+
radius = LValidator(radius_validator, uint32, retmapper=literal)
|
142
|
+
|
143
|
+
|
144
|
+
def id_name(value):
|
145
|
+
if value == SCHEMA_EXTRACT:
|
146
|
+
return "id"
|
147
|
+
return cv.validate_id_name(value)
|
148
|
+
|
149
|
+
|
150
|
+
def stop_value(value):
|
151
|
+
return cv.int_range(0, 255)(value)
|
152
|
+
|
153
|
+
|
154
|
+
lv_images_used = set()
|
155
|
+
|
156
|
+
|
157
|
+
def image_validator(value):
|
158
|
+
value = requires_component("image")(value)
|
159
|
+
value = cv.use_id(Image_)(value)
|
160
|
+
lv_images_used.add(value)
|
161
|
+
return value
|
162
|
+
|
163
|
+
|
164
|
+
lv_image = LValidator(
|
165
|
+
image_validator,
|
166
|
+
lv_img_t,
|
167
|
+
retmapper=lambda x: lv_expr.img_from(MockObj(x)),
|
168
|
+
requires="image",
|
169
|
+
)
|
170
|
+
lv_bool = LValidator(
|
171
|
+
cv.boolean, cg.bool_, BinarySensor, "get_state()", retmapper=literal
|
172
|
+
)
|
173
|
+
|
174
|
+
|
175
|
+
def lv_pct(value: Union[int, float]):
|
176
|
+
if isinstance(value, float):
|
177
|
+
value = int(value * 100)
|
178
|
+
return literal(f"lv_pct({value})")
|
179
|
+
|
180
|
+
|
181
|
+
def lvms_validator_(value):
|
182
|
+
if value == "never":
|
183
|
+
value = "2147483647ms"
|
184
|
+
return cv.positive_time_period_milliseconds(value)
|
185
|
+
|
186
|
+
|
187
|
+
lv_milliseconds = LValidator(
|
188
|
+
lvms_validator_,
|
189
|
+
cg.int32,
|
190
|
+
retmapper=lambda x: x.total_milliseconds,
|
191
|
+
)
|
192
|
+
|
193
|
+
|
194
|
+
class TextValidator(LValidator):
|
195
|
+
def __init__(self):
|
196
|
+
super().__init__(
|
197
|
+
cv.string,
|
198
|
+
cg.const_char_ptr,
|
199
|
+
TextSensor,
|
200
|
+
"get_state().c_str()",
|
201
|
+
lambda s: cg.safe_exp(f"{s}"),
|
202
|
+
)
|
203
|
+
|
204
|
+
def __call__(self, value):
|
205
|
+
if isinstance(value, dict):
|
206
|
+
return value
|
207
|
+
return super().__call__(value)
|
208
|
+
|
209
|
+
async def process(self, value, args=()):
|
210
|
+
if isinstance(value, dict):
|
211
|
+
args = [str(x) for x in value[CONF_ARGS]]
|
212
|
+
arg_expr = cg.RawExpression(",".join(args))
|
213
|
+
format_str = cpp_string_escape(value[CONF_FORMAT])
|
214
|
+
return literal(f"str_sprintf({format_str}, {arg_expr}).c_str()")
|
215
|
+
return await super().process(value, args)
|
216
|
+
|
217
|
+
|
218
|
+
lv_text = TextValidator()
|
219
|
+
lv_float = LValidator(cv.float_, cg.float_, Sensor, "get_state()")
|
220
|
+
lv_int = LValidator(cv.int_, cg.int_, Sensor, "get_state()")
|
221
|
+
lv_brightness = LValidator(
|
222
|
+
cv.percentage, cg.float_, Sensor, "get_state()", retmapper=lambda x: int(x * 255)
|
223
|
+
)
|
224
|
+
|
225
|
+
|
226
|
+
def is_lv_font(font):
|
227
|
+
return isinstance(font, str) and font.lower() in LV_FONTS
|
228
|
+
|
229
|
+
|
230
|
+
class LvFont(LValidator):
|
231
|
+
def __init__(self):
|
232
|
+
def lv_builtin_font(value):
|
233
|
+
fontval = cv.one_of(*LV_FONTS, lower=True)(value)
|
234
|
+
lv_fonts_used.add(fontval)
|
235
|
+
return fontval
|
236
|
+
|
237
|
+
def validator(value):
|
238
|
+
if value == SCHEMA_EXTRACT:
|
239
|
+
return LV_FONTS
|
240
|
+
if is_lv_font(value):
|
241
|
+
return lv_builtin_font(value)
|
242
|
+
fontval = cv.use_id(Font)(value)
|
243
|
+
esphome_fonts_used.add(fontval)
|
244
|
+
return requires_component("font")(fontval)
|
245
|
+
|
246
|
+
super().__init__(validator, lv_font_t)
|
247
|
+
|
248
|
+
async def process(self, value, args=()):
|
249
|
+
if is_lv_font(value):
|
250
|
+
return literal(f"&lv_font_{value}")
|
251
|
+
return literal(f"{value}_engine->get_lv_font()")
|
252
|
+
|
253
|
+
|
254
|
+
lv_font = LvFont()
|
255
|
+
|
256
|
+
|
257
|
+
def animated(value):
|
258
|
+
if isinstance(value, bool):
|
259
|
+
value = "ON" if value else "OFF"
|
260
|
+
return LvConstant("LV_ANIM_", "OFF", "ON").one_of(value)
|
261
|
+
|
262
|
+
|
263
|
+
def key_code(value):
|
264
|
+
value = cv.Any(cv.All(cv.string_strict, cv.Length(min=1, max=1)), cv.uint8_t)(value)
|
265
|
+
if isinstance(value, str):
|
266
|
+
return ord(value[0])
|
267
|
+
return value
|
268
|
+
|
269
|
+
|
270
|
+
async def get_end_value(config):
|
271
|
+
return await lv_int.process(config.get(CONF_END_VALUE))
|
272
|
+
|
273
|
+
|
274
|
+
async def get_start_value(config):
|
275
|
+
if CONF_START_VALUE in config:
|
276
|
+
value = config[CONF_START_VALUE]
|
277
|
+
else:
|
278
|
+
value = config.get(CONF_VALUE)
|
279
|
+
return await lv_int.process(value)
|
@@ -0,0 +1,349 @@
|
|
1
|
+
import abc
|
2
|
+
from typing import Union
|
3
|
+
|
4
|
+
from esphome import codegen as cg
|
5
|
+
from esphome.config import Config
|
6
|
+
from esphome.core import CORE, ID, Lambda
|
7
|
+
from esphome.cpp_generator import (
|
8
|
+
AssignmentExpression,
|
9
|
+
CallExpression,
|
10
|
+
Expression,
|
11
|
+
ExpressionStatement,
|
12
|
+
LambdaExpression,
|
13
|
+
MockObj,
|
14
|
+
RawExpression,
|
15
|
+
RawStatement,
|
16
|
+
SafeExpType,
|
17
|
+
Statement,
|
18
|
+
VariableDeclarationExpression,
|
19
|
+
statement,
|
20
|
+
)
|
21
|
+
from esphome.yaml_util import ESPHomeDataBase
|
22
|
+
|
23
|
+
from .defines import literal, lvgl_ns
|
24
|
+
|
25
|
+
LVGL_COMP = "lv_component" # used as a lambda argument in lvgl_comp()
|
26
|
+
|
27
|
+
# Argument tuple for use in lambdas
|
28
|
+
LvglComponent = lvgl_ns.class_("LvglComponent", cg.PollingComponent)
|
29
|
+
LVGL_COMP_ARG = [(LvglComponent.operator("ptr"), LVGL_COMP)]
|
30
|
+
lv_event_t_ptr = cg.global_ns.namespace("lv_event_t").operator("ptr")
|
31
|
+
EVENT_ARG = [(lv_event_t_ptr, "ev")]
|
32
|
+
# Two custom events; API_EVENT is fired when an entity is updated remotely by an API interaction;
|
33
|
+
# UPDATE_EVENT is fired when an entity is programmatically updated locally.
|
34
|
+
# VALUE_CHANGED is the event generated by LVGL when an entity's value changes through user interaction.
|
35
|
+
API_EVENT = literal("lvgl::lv_api_event")
|
36
|
+
UPDATE_EVENT = literal("lvgl::lv_update_event")
|
37
|
+
|
38
|
+
|
39
|
+
def get_line_marks(value) -> list:
|
40
|
+
"""
|
41
|
+
If possible, return a preprocessor directive to identify the line number where the given id was defined.
|
42
|
+
:param value: The id or other token to get the line number for
|
43
|
+
:return: A list containing zero or more line directives
|
44
|
+
"""
|
45
|
+
path = None
|
46
|
+
if isinstance(value, ESPHomeDataBase):
|
47
|
+
path = value.esp_range
|
48
|
+
elif isinstance(value, ID) and isinstance(CORE.config, Config):
|
49
|
+
path = CORE.config.get_path_for_id(value)[:-1]
|
50
|
+
path = CORE.config.get_deepest_document_range_for_path(path)
|
51
|
+
if path is None:
|
52
|
+
return []
|
53
|
+
return [path.start_mark.as_line_directive]
|
54
|
+
|
55
|
+
|
56
|
+
class IndentedStatement(Statement):
|
57
|
+
def __init__(self, stmt: Statement, indent: int):
|
58
|
+
self.statement = stmt
|
59
|
+
self.indent = indent
|
60
|
+
|
61
|
+
def __str__(self):
|
62
|
+
result = " " * self.indent * 4 + str(self.statement).strip()
|
63
|
+
if not isinstance(self.statement, RawStatement):
|
64
|
+
result += ";"
|
65
|
+
return result
|
66
|
+
|
67
|
+
|
68
|
+
class CodeContext(abc.ABC):
|
69
|
+
"""
|
70
|
+
A class providing a context for code generation. Generated code will be added to the
|
71
|
+
current context. A new context will stack on the current context, and restore it
|
72
|
+
when done. Used with the `with` statement.
|
73
|
+
"""
|
74
|
+
|
75
|
+
code_context = None
|
76
|
+
|
77
|
+
@abc.abstractmethod
|
78
|
+
def add(self, expression: Union[Expression, Statement]):
|
79
|
+
pass
|
80
|
+
|
81
|
+
@staticmethod
|
82
|
+
def start_block():
|
83
|
+
CodeContext.append(RawStatement("{"))
|
84
|
+
CodeContext.code_context.indent()
|
85
|
+
|
86
|
+
@staticmethod
|
87
|
+
def end_block():
|
88
|
+
CodeContext.code_context.detent()
|
89
|
+
CodeContext.append(RawStatement("}"))
|
90
|
+
|
91
|
+
@staticmethod
|
92
|
+
def append(expression: Union[Expression, Statement]):
|
93
|
+
if CodeContext.code_context is not None:
|
94
|
+
CodeContext.code_context.add(expression)
|
95
|
+
return expression
|
96
|
+
|
97
|
+
def __init__(self):
|
98
|
+
self.previous: Union[CodeContext | None] = None
|
99
|
+
self.indent_level = 0
|
100
|
+
|
101
|
+
async def __aenter__(self):
|
102
|
+
self.previous = CodeContext.code_context
|
103
|
+
CodeContext.code_context = self
|
104
|
+
return self
|
105
|
+
|
106
|
+
async def __aexit__(self, *args):
|
107
|
+
CodeContext.code_context = self.previous
|
108
|
+
|
109
|
+
def indent(self):
|
110
|
+
self.indent_level += 1
|
111
|
+
|
112
|
+
def detent(self):
|
113
|
+
self.indent_level -= 1
|
114
|
+
|
115
|
+
def indented_statement(self, stmt):
|
116
|
+
return IndentedStatement(stmt, self.indent_level)
|
117
|
+
|
118
|
+
|
119
|
+
class MainContext(CodeContext):
|
120
|
+
"""
|
121
|
+
Code generation into the main() function
|
122
|
+
"""
|
123
|
+
|
124
|
+
def add(self, expression: Union[Expression, Statement]):
|
125
|
+
return cg.add(self.indented_statement(expression))
|
126
|
+
|
127
|
+
|
128
|
+
class LambdaContext(CodeContext):
|
129
|
+
"""
|
130
|
+
A context that will accumlate code for use in a lambda.
|
131
|
+
"""
|
132
|
+
|
133
|
+
def __init__(
|
134
|
+
self,
|
135
|
+
parameters: list[tuple[SafeExpType, str]] = None,
|
136
|
+
return_type: SafeExpType = cg.void,
|
137
|
+
capture: str = "",
|
138
|
+
where=None,
|
139
|
+
):
|
140
|
+
super().__init__()
|
141
|
+
self.code_list: list[Statement] = []
|
142
|
+
self.parameters = parameters or []
|
143
|
+
self.return_type = return_type
|
144
|
+
self.capture = capture
|
145
|
+
self.where = where
|
146
|
+
|
147
|
+
def add(self, expression: Union[Expression, Statement]):
|
148
|
+
self.code_list.append(self.indented_statement(expression))
|
149
|
+
return expression
|
150
|
+
|
151
|
+
async def get_lambda(self) -> LambdaExpression:
|
152
|
+
code_text = self.get_code()
|
153
|
+
return await cg.process_lambda(
|
154
|
+
Lambda("\n".join(code_text) + "\n"),
|
155
|
+
self.parameters,
|
156
|
+
capture=self.capture,
|
157
|
+
return_type=self.return_type,
|
158
|
+
)
|
159
|
+
|
160
|
+
def get_code(self):
|
161
|
+
code_text = []
|
162
|
+
for exp in self.code_list:
|
163
|
+
text = str(statement(exp))
|
164
|
+
text = text.rstrip()
|
165
|
+
code_text.append(text)
|
166
|
+
return code_text
|
167
|
+
|
168
|
+
async def __aenter__(self):
|
169
|
+
await super().__aenter__()
|
170
|
+
add_line_marks(self.where)
|
171
|
+
return self
|
172
|
+
|
173
|
+
|
174
|
+
class LvContext(LambdaContext):
|
175
|
+
"""
|
176
|
+
Code generation into the LVGL initialisation code (called in `setup()`)
|
177
|
+
"""
|
178
|
+
|
179
|
+
def __init__(self, lv_component, args=None):
|
180
|
+
self.args = args or LVGL_COMP_ARG
|
181
|
+
super().__init__(parameters=self.args)
|
182
|
+
self.lv_component = lv_component
|
183
|
+
|
184
|
+
async def add_init_lambda(self):
|
185
|
+
cg.add(self.lv_component.add_init_lambda(await self.get_lambda()))
|
186
|
+
|
187
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
188
|
+
await super().__aexit__(exc_type, exc_val, exc_tb)
|
189
|
+
await self.add_init_lambda()
|
190
|
+
|
191
|
+
def add(self, expression: Union[Expression, Statement]):
|
192
|
+
self.code_list.append(self.indented_statement(expression))
|
193
|
+
return expression
|
194
|
+
|
195
|
+
def __call__(self, *args):
|
196
|
+
return self.add(*args)
|
197
|
+
|
198
|
+
|
199
|
+
class LocalVariable(MockObj):
|
200
|
+
"""
|
201
|
+
Create a local variable and enclose the code using it within a block.
|
202
|
+
"""
|
203
|
+
|
204
|
+
def __init__(self, name, type, rhs=None, modifier="*"):
|
205
|
+
base = ID(name + "_VAR_", True, type)
|
206
|
+
super().__init__(base, "")
|
207
|
+
self.modifier = modifier
|
208
|
+
self.rhs = rhs
|
209
|
+
|
210
|
+
def __enter__(self):
|
211
|
+
CodeContext.start_block()
|
212
|
+
CodeContext.append(
|
213
|
+
VariableDeclarationExpression(self.base.type, self.modifier, self.base.id)
|
214
|
+
)
|
215
|
+
if self.rhs is not None:
|
216
|
+
CodeContext.append(AssignmentExpression(None, "", self.base, self.rhs))
|
217
|
+
return MockObj(self.base)
|
218
|
+
|
219
|
+
def __exit__(self, *args):
|
220
|
+
CodeContext.end_block()
|
221
|
+
|
222
|
+
|
223
|
+
class MockLv:
|
224
|
+
"""
|
225
|
+
A mock object that can be used to generate LVGL calls.
|
226
|
+
"""
|
227
|
+
|
228
|
+
def __init__(self, base):
|
229
|
+
self.base = base
|
230
|
+
|
231
|
+
def __getattr__(self, attr: str) -> "MockLv":
|
232
|
+
return MockLv(f"{self.base}{attr}")
|
233
|
+
|
234
|
+
def append(self, expression):
|
235
|
+
CodeContext.append(expression)
|
236
|
+
|
237
|
+
def __call__(self, *args: SafeExpType) -> "MockObj":
|
238
|
+
call = CallExpression(self.base, *args)
|
239
|
+
result = MockObj(call, "")
|
240
|
+
self.append(result)
|
241
|
+
return result
|
242
|
+
|
243
|
+
def __str__(self):
|
244
|
+
return str(self.base)
|
245
|
+
|
246
|
+
def __repr__(self):
|
247
|
+
return f"MockLv<{str(self.base)}>"
|
248
|
+
|
249
|
+
def call(self, prop, *args):
|
250
|
+
call = CallExpression(RawExpression(f"{self.base}{prop}"), *args)
|
251
|
+
result = MockObj(call, "")
|
252
|
+
self.append(result)
|
253
|
+
return result
|
254
|
+
|
255
|
+
|
256
|
+
class LvConditional:
|
257
|
+
def __init__(self, condition):
|
258
|
+
self.condition = condition
|
259
|
+
|
260
|
+
def __enter__(self):
|
261
|
+
if self.condition is not None:
|
262
|
+
CodeContext.append(RawStatement(f"if ({self.condition}) {{"))
|
263
|
+
CodeContext.code_context.indent()
|
264
|
+
return self
|
265
|
+
|
266
|
+
def __exit__(self, *args):
|
267
|
+
if self.condition is not None:
|
268
|
+
CodeContext.code_context.detent()
|
269
|
+
CodeContext.append(RawStatement("}"))
|
270
|
+
|
271
|
+
def else_(self):
|
272
|
+
assert self.condition is not None
|
273
|
+
CodeContext.code_context.detent()
|
274
|
+
CodeContext.append(RawStatement("} else {"))
|
275
|
+
CodeContext.code_context.indent()
|
276
|
+
|
277
|
+
|
278
|
+
class ReturnStatement(ExpressionStatement):
|
279
|
+
def __str__(self):
|
280
|
+
return f"return {self.expression};"
|
281
|
+
|
282
|
+
|
283
|
+
class LvExpr(MockLv):
|
284
|
+
def __getattr__(self, attr: str) -> "MockLv":
|
285
|
+
return LvExpr(f"{self.base}{attr}")
|
286
|
+
|
287
|
+
def append(self, expression):
|
288
|
+
pass
|
289
|
+
|
290
|
+
|
291
|
+
# Top level mock for generic lv_ calls to be recorded
|
292
|
+
lv = MockLv("lv_")
|
293
|
+
# Just generate an expression
|
294
|
+
lv_expr = LvExpr("lv_")
|
295
|
+
# Mock for lv_obj_ calls
|
296
|
+
lv_obj = MockLv("lv_obj_")
|
297
|
+
# Operations on the LVGL component
|
298
|
+
lvgl_comp = MockObj(LVGL_COMP, "->")
|
299
|
+
|
300
|
+
|
301
|
+
# equivalent to cg.add() for the current code context
|
302
|
+
def lv_add(expression: Union[Expression, Statement]):
|
303
|
+
return CodeContext.append(expression)
|
304
|
+
|
305
|
+
|
306
|
+
def add_line_marks(where):
|
307
|
+
"""
|
308
|
+
Add line marks for the current code context
|
309
|
+
:param where: An object to identify the source of the line marks
|
310
|
+
:return:
|
311
|
+
"""
|
312
|
+
for mark in get_line_marks(where):
|
313
|
+
lv_add(cg.RawStatement(mark))
|
314
|
+
|
315
|
+
|
316
|
+
def lv_assign(target, expression):
|
317
|
+
lv_add(AssignmentExpression("", "", target, expression))
|
318
|
+
|
319
|
+
|
320
|
+
def lv_Pvariable(type, name):
|
321
|
+
"""
|
322
|
+
Create but do not initialise a pointer variable
|
323
|
+
:param type: Type of the variable target
|
324
|
+
:param name: name of the variable, or an ID
|
325
|
+
:return: A MockObj of the variable
|
326
|
+
"""
|
327
|
+
if isinstance(name, str):
|
328
|
+
name = ID(name, True, type)
|
329
|
+
decl = VariableDeclarationExpression(type, "*", name)
|
330
|
+
CORE.add_global(decl)
|
331
|
+
var = MockObj(name, "->")
|
332
|
+
CORE.register_variable(name, var)
|
333
|
+
return var
|
334
|
+
|
335
|
+
|
336
|
+
def lv_variable(type, name):
|
337
|
+
"""
|
338
|
+
Create but do not initialise a variable
|
339
|
+
:param type: Type of the variable target
|
340
|
+
:param name: name of the variable, or an ID
|
341
|
+
:return: A MockObj of the variable
|
342
|
+
"""
|
343
|
+
if isinstance(name, str):
|
344
|
+
name = ID(name, True, type)
|
345
|
+
decl = VariableDeclarationExpression(type, "", name)
|
346
|
+
CORE.add_global(decl)
|
347
|
+
var = MockObj(name, ".")
|
348
|
+
CORE.register_variable(name, var)
|
349
|
+
return var
|