esphome: name: lilka friendly_name: lilka on_boot: priority: 600 then: - output.turn_on: display_power - delay: 100ms esp32: board: esp32-s3-devkitc-1 framework: type: arduino wifi: ssid: !secret wifi_ssid password: !secret wifi_password ap: ssid: "Lilka Fallback Hotspot" password: "hnYImYM4O6I0" captive_portal: web_server: port: 80 api: encryption: key: "Yw3yq8lxsaze+jdggjAwxKpV4GD6gNZptvw4d6OPfOc=" logger: ota: - platform: esphome password: "bb198feb99159fdaefc8092f10039acd" output: - platform: gpio pin: 46 id: display_power inverted: false substitutions: i2s_lrclk: GPIO1 # LRC Pin of the Max98357 i2s_bclk: GPIO42 # BCLK Pin of the Max98357 spk: GPIO2 # DIN Pin of the Max98357 i2s_audio: - id: i2s_in i2s_lrclk_pin: ${i2s_lrclk} # LRC Pin of the Max98357 i2s_bclk_pin: ${i2s_bclk} # BCLK Pin of the Max98357 media_player: - platform: i2s_audio name: "Lilka Speaker" id: media_player_speaker i2s_audio_id: i2s_in dac_type: external i2s_dout_pin: ${spk} # DIN Pin of the MAX98357A Audio Amplifier mode: mono on_play: - logger.log: "Media playing!" - media_player.volume_set: id: media_player_speaker volume: 100% # --------------------------------------------------- # СЕНСОРИ # --------------------------------------------------- sensor: - platform: adc pin: GPIO3 id: battery_voltage name: "Battery Voltage" icon: "mdi:lightning-bolt" update_interval: 10s attenuation: 12db filters: - multiply: 1.33 - platform: template id: battery_level name: "Battery Level" icon: "mdi:battery" unit_of_measurement: "%" accuracy_decimals: 0 update_interval: 10s lambda: |- float voltage = id(battery_voltage).state; float percent = (voltage - 3.0) / (4.2 - 3.0) * 100.0; if (percent > 100) percent = 100; if (percent < 0) percent = 0; return percent; # --------------------------------------------------- # ДИСПЛЕЙ ST7789V + LVGL # --------------------------------------------------- spi: clk_pin: 18 mosi_pin: 17 display: - platform: mipi_spi model: ST7789V id: my_display dc_pin: 15 cs_pin: 7 update_interval: 1s rotation: 270 invert_colors: true color_order: BGR pixel_mode: 16bit dimensions: width: 280 height: 240 offset_width: 20 offset_height: 0 auto_clear_enabled: false lvgl: log_level: INFO style_definitions: - id: default_style bg_color: 0x000000 text_color: 0xFFFFFF - id: focused_style border_color: 0xFFFFFF border_width: 3 pages: - id: main_page bg_color: 0x000000 widgets: - button: id: red_button align: CENTER y: -40 width: 180 height: 50 bg_color: 0xFF0000 widgets: - label: id: battery_label text: "Battery: --" align: CENTER - button: id: green_button align: CENTER y: 20 width: 180 height: 50 bg_color: 0x00FF00 widgets: - label: id: voltage_label text: "Voltage: --" align: CENTER text_color: 0x000000 - button: id: blue_button align: CENTER y: 80 width: 180 height: 50 bg_color: 0x0000FF widgets: - label: text: "Lilka LVGL" align: CENTER text_color: 0xFFFFFF # --------------------------------------------------- # ГЛОБАЛЬНІ ЗМІННІ ТА СКРИПТ ФОКУСУ # --------------------------------------------------- globals: - id: current_button_index type: int restore_value: no initial_value: '0' script: - id: update_focus then: - lvgl.widget.update: id: red_button border_width: !lambda 'return id(current_button_index) == 0 ? 3 : 0;' - lvgl.widget.update: id: green_button border_width: !lambda 'return id(current_button_index) == 1 ? 3 : 0;' - lvgl.widget.update: id: blue_button border_width: !lambda 'return id(current_button_index) == 2 ? 3 : 0;' # --------------------------------------------------- # КНОПКИ (ВСІ ВИДИМІ У HOME ASSISTANT) # --------------------------------------------------- binary_sensor: # D-Pad - platform: gpio pin: number: 38 mode: INPUT_PULLUP inverted: true id: button_up name: "Button Up" icon: "mdi:arrow-up-circle" filters: - delayed_on_off: 50ms on_press: - lambda: |- id(current_button_index)--; if (id(current_button_index) < 0) id(current_button_index) = 2; - script.execute: update_focus - platform: gpio pin: number: 41 mode: INPUT_PULLUP inverted: true id: button_down name: "Button Down" icon: "mdi:arrow-down-circle" filters: - delayed_on_off: 50ms on_press: - lambda: |- id(current_button_index)++; if (id(current_button_index) > 2) id(current_button_index) = 0; - script.execute: update_focus - platform: gpio pin: number: 39 mode: INPUT_PULLUP inverted: true id: button_left name: "Button Left" icon: "mdi:arrow-left-circle" filters: - delayed_on_off: 50ms - platform: gpio pin: number: 40 mode: INPUT_PULLUP inverted: true id: button_right name: "Button Right" icon: "mdi:arrow-right-circle" filters: - delayed_on_off: 50ms # A B C D - platform: gpio pin: number: 5 mode: INPUT_PULLUP inverted: true id: button_a name: "Button A" icon: "mdi:alpha-a-circle" filters: - delayed_on_off: 50ms - platform: gpio pin: number: 6 mode: INPUT_PULLUP inverted: true id: button_b name: "Button B" icon: "mdi:alpha-b-circle" filters: - delayed_on_off: 50ms - platform: gpio pin: number: 10 mode: INPUT_PULLUP inverted: true id: button_c name: "Button C" icon: "mdi:alpha-c-circle" filters: - delayed_on_off: 50ms - platform: gpio pin: number: 9 mode: INPUT_PULLUP inverted: true id: button_d name: "Button D" icon: "mdi:alpha-d-circle" filters: - delayed_on_off: 50ms # Start / Select - platform: gpio pin: number: 4 mode: INPUT_PULLUP inverted: true id: button_start name: "Button Start" icon: "mdi:play-circle" filters: - delayed_on_off: 50ms - platform: gpio pin: number: 0 mode: INPUT_PULLUP inverted: true id: button_select name: "Button Select" icon: "mdi:checkbox-marked-circle" filters: - delayed_on_off: 50ms # --------------------------------------------------- # ОНОВЛЕННЯ СТАТУСУ БАТАРЕЇ НА ЕКРАНІ # --------------------------------------------------- interval: - interval: 5s then: - lvgl.label.update: id: battery_label text: !lambda |- return std::string("Battery: ") + to_string((int)id(battery_level).state) + "%"; - lvgl.label.update: id: voltage_label text: !lambda |- char buf[20]; snprintf(buf, sizeof(buf), "Voltage: %.2fV", id(battery_voltage).state); return std::string(buf);