GUITION 1.8” 360x360 ESP32-S3-JC3636W518 Smart Display

Great!

You should be able to remove all the display options except model and rotation.

1 Like

removed, thanks again

1 Like

ImportError: cannot import name ‘CONF_COLOR_DEPTH’ from ‘esphome.components.const’ (/Users/yaroslav/venv/lib/python3.11/site-packages/esphome/components/const/init.py)
Failed config

Platform not found: ‘display.mipi_spi’

Are you using the latest ESPHome? 2025.8.1

i have a question related to this display driver since it works with the waveshare ESP32-S3-Touch-LCD-1.85C (and BOX), but it needs reset_pin: set to something that isn’t used because if not set, the driver will default to pin 47, and pin 47 is in use already on the waveshare devices. can it be added or is it a new driver?

display:
  - platform: mipi_spi
    id: main_display
    model: JC3636W518
    rotation: 180
    invert_colors: true
    data_rate: 40MHz
    cs_pin: 21
    reset_pin: 12 #fake pin
    update_interval: never

You can use the CUSTOM model, but will need to provide the full config, or a new model can be added with a PR.

1 Like

what i mean is the Guition 1.8" v1 works as it is, no change needed besides setting the reset pin, i added the ioextender and added the correct pin and it works perfectly without having to fake a pin so i think there’s no need for a new driver? :person_shrugging:

i2c:
  sda: 11
  scl: 10
  id: touchscreen_bus

pca9554:
  - id: pca9554a_device
    address: 0x20

spi:
  id: display_qspi
  type: quad
  clk_pin: 40
  data_pins: [46, 45, 42, 41]

display:
  - platform: mipi_spi
    id: main_display
    model: JC3636W518
    rotation: 180
    cs_pin: 21
    reset_pin:
      pca9554: pca9554a_device
      number: 1
    update_interval: never
    pages:

at least i think i got the pin right? 2 is 1, right?

2 Likes

Not really, it would just build-in the reset pin definition. Not a big deal. And yes, they seems to like to use 1-based numbering for the extender, which is confusing.

Well done!

1 Like

i had someone report that with the guition displays the image is 1 pixel down, i use the same yaml for several displays and checked, it only happens when using guition display driver, both the normal for v1 and the one from the pr for v2. i have not testet with standard yaml but can if you don’t see it?

i’m thinking it could be the driver since all other displays don’t do that with same yaml?, let me know if you want me to test with some standard yaml.

EDIT: i tried with minimal yaml:

substitutions:
  name: esphome-web-e9f624
  friendly_name: Xiaozhi Taichi Pi v1

  imagewidth: "360"
  imageheight: "360"
  rotate_display: "180"

external_components:
  - source: github://pr#10392
    components: [mipi_spi]
    refresh: 1h

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  min_version: 2025.5.0

esp32:
  board: esp32-s3-devkitc-1
  flash_size: 16MB
  cpu_frequency: 240MHz
  framework:
    type: esp-idf

psram:
  mode: octal
  speed: 80MHz

api:

ota:
  - platform: esphome
    id: ota_esphome

logger:
  hardware_uart: USB_SERIAL_JTAG

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    password: "esphome-test"

output:
  - platform: ledc
    pin: 15
    id: backlight_output

light:
  - platform: monochromatic
    id: Sled
    name: Screen
    icon: "mdi:television"
    entity_category: config
    output: backlight_output
    restore_mode: ALWAYS_ON
    default_transition_length: 250ms

spi:
  id: display_qspi
  type: quad
  clk_pin: 9
  data_pins: [11, 12, 13, 14]

image:
  - id: test_image
    file: https://github.com/RealDeco/xiaozhi-esphome/raw/main/images/Other/${imagewidth}x${imageheight}/hacker.png
    resize: ${imagewidth}x${imageheight}
    type: RGB565

display:
  - platform: mipi_spi
    id: main_display
    model: JC3636W518
    rotation: ${rotate_display}
    pages:
      - id: single_image
        lambda: |-
          const int W = it.get_width();
          const int H = it.get_height();
          it.fill(Color::BLACK);
          it.image(W / 2, H / 2, id(test_image), ImageAlign::CENTER);

and it still happens, but only when using rotate. (and only after power been unplugged/replugged), if i put rotate to 0 it’s fine, put it back to 180, it’s fine, unplug power,/replug, it’s back. :man_shrugging: (still only when using rotate)

hope this helps.

problem seems to be solved by setting the size manually in display, strangely enough :man_shrugging:

display:
  - platform: mipi_spi
    id: main_display
    model: JC3636W518
    rotation: 180
    update_interval: never
    dimensions:
        height: 360
        width: 360
    pages:
1 Like

The predefined config for the JC3636W518 has an offset of 1 since the board I used for testing seemed to require that. Providing the dimensions in the yaml overrides that and sets the offset to a default of 0.

I’m not currently able to test this.

1 Like

Yes that solves the problem :+1:

Could be nice if you’d share that Arduino code…

I made it to work with rotary encoder controlling led or curtains. Here’s wip code:

1 Like

is this code good for V2 version ?

I changed GPIO pin in the code from Marcin. now it is working on DFRobot DFR1221 V2

substitutions:
  name: "dfr1221"
  friendly_name: "DFRobot-round"
  device_description: "ESP32S3-1.8-inch JC3636K518C"
  project_name: "iritating.scrollwheel"
  project_version: "6.6.6"

esphome:
  name: "${name}"
  friendly_name: "${friendly_name}"
  project:
    name: "${project_name}"
    version: "${project_version}"
  platformio_options:
    board_build.flash_mode: dio
    board_build.f_flash: 80000000L
    board_build.f_cpu: 240000000L

esp32:
  board: esp32-s3-devkitc-1
  flash_size: 16MB
  framework:
    type: esp-idf
    sdkconfig_options:
      CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y"
      CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
      CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"
      CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
      CONFIG_SPIRAM_RODATA: y

psram:
  mode: octal

logger:

api:

ota:
  - platform: esphome

wifi:
  ssid: xxx
  password: xxx
  ap:
    ssid: "${friendly_name} Hotspot"
    password: "fallbackPassw0rd"

spi:
  id: display_qspi
  type: quad
  clk_pin: 9
  data_pins: [11, 12, 13, 14]

i2c:
  sda: 7
  scl: 8
  id: touchscreen_bus

# Deep sleep configuration - wakes up on encoder rotation
deep_sleep:
  id: deep_sleep_control
  esp32_ext1_wakeup:
    mode: ANY_LOW
    pins:
      - number: GPIO20
        allow_other_uses: true
      - number: GPIO21
        allow_other_uses: true

globals:
  - id: current_page
    type: int
    restore_value: no
    initial_value: '1'
  - id: pending_cover_position
    type: int
    restore_value: no
    initial_value: '0'
  - id: cover_update_pending
    type: bool
    restore_value: no
    initial_value: 'false'
  - id: pending_led_brightness
    type: int
    restore_value: no
    initial_value: '25' # 0 
  - id: led_update_pending
    type: bool
    restore_value: no
    initial_value: 'false'

switch:
  - platform: template
    name: Antiburn
    id: switch_antiburn
    icon: mdi:television-shimmer
    optimistic: true
    entity_category: "config"
    turn_on_action:
      - logger.log: "Starting Antiburn"
      - if:
          condition: lvgl.is_paused
          then:
            - lvgl.resume:
            - lvgl.widget.redraw:
      - lvgl.pause:
          show_snow: true
    turn_off_action:
      - logger.log: "Stopping Antiburn"
      - if:
          condition: lvgl.is_paused
          then:
            - lvgl.resume:
            - lvgl.widget.redraw:
touchscreen:
  platform: cst816
  id: my_touchscreen
  interrupt_pin: GPIO41
  reset_pin: GPIO40
  on_release:
    - if:
        condition: lvgl.is_paused
        then:
          - logger.log: "LVGL resuming from touch"
          - lvgl.resume:
          - lvgl.widget.redraw:
          - light.turn_on: display_backlight

light:
  - platform: monochromatic
    id: display_backlight
    name: "Backlight"
    output: backlight_pwm
    default_transition_length:
      milliseconds: 30
    initial_state:
      brightness: 70%
    restore_mode: ALWAYS_ON

font:
  - file: "gfonts://Roboto"
    id: roboto_20
    size: 20
    glyphsets:
      - GF_Latin_Core
    ignore_missing_glyphs: true  # Add this line
  - file: "gfonts://Roboto"
    id: roboto_32
    size: 32
    glyphsets:
      - GF_Latin_Core
    ignore_missing_glyphs: true  # Add this line
  - file: "gfonts://Roboto"
    id: roboto_88
    size: 88
    glyphsets:
      - GF_Latin_Core   
    ignore_missing_glyphs: true  # Add this line
         
output:
  - platform: ledc
    pin:
      number: GPIO15
    id: backlight_pwm

time:
  - platform: homeassistant
    id: homeassistant_time
    timezone: Europe/Warsaw
    on_time:
      - hours: 2,3,4,5
        minutes: 5
        seconds: 0
        then:
          - switch.turn_on: switch_antiburn
      - hours: 2,3,4,5
        minutes: 35
        seconds: 0
        then:
          - switch.turn_off: switch_antiburn

display:
  - platform: qspi_dbi
    id: my_display
    model: CUSTOM
    data_rate: 80MHz
    color_order: rgb
    dimensions:
      height: 360
      width: 360
    cs_pin: 10
    reset_pin: 47
    invert_colors: true
    auto_clear_enabled: false
    init_sequence:
      - [0xF0, 0x28]
      - [0xF2, 0x28]
      - [0x73, 0xF0]
      - [0x7C, 0xD1]
      - [0x83, 0xE0]
      - [0x84, 0x61]
      - [0xF2, 0x82]
      - [0xF0, 0x00]
      - [0xF0, 0x01]
      - [0xF1, 0x01]
      - [0xB0, 0x56]
      - [0xB1, 0x4D]
      - [0xB2, 0x24]
      - [0xB4, 0x87]
      - [0xB5, 0x44]
      - [0xB6, 0x8B]
      - [0xB7, 0x40]
      - [0xB8, 0x86]
      - [0xBA, 0x00]
      - [0xBB, 0x08]
      - [0xBC, 0x08]
      - [0xBD, 0x00]
      - [0xC0, 0x80]
      - [0xC1, 0x10]
      - [0xC2, 0x37]
      - [0xC3, 0x80]
      - [0xC4, 0x10]
      - [0xC5, 0x37]
      - [0xC6, 0xA9]
      - [0xC7, 0x41]
      - [0xC8, 0x01]
      - [0xC9, 0xA9]
      - [0xCA, 0x41]
      - [0xCB, 0x01]
      - [0xD0, 0x91]
      - [0xD1, 0x68]
      - [0xD2, 0x68]
      - [0xF5, 0x00, 0xA5]
      - [0xDD, 0x4F]
      - [0xDE, 0x4F]
      - [0xF1, 0x10]
      - [0xF0, 0x00]
      - [0xF0, 0x02]
      - [
          0xE0,
          0xF0,
          0x0A,
          0x10,
          0x09,
          0x09,
          0x36,
          0x35,
          0x33,
          0x4A,
          0x29,
          0x15,
          0x15,
          0x2E,
          0x34,
        ]
      - [
          0xE1,
          0xF0,
          0x0A,
          0x0F,
          0x08,
          0x08,
          0x05,
          0x34,
          0x33,
          0x4A,
          0x39,
          0x15,
          0x15,
          0x2D,
          0x33,
        ]
      - [0xF0, 0x10]
      - [0xF3, 0x10]
      - [0xE0, 0x07]
      - [0xE1, 0x00]
      - [0xE2, 0x00]
      - [0xE3, 0x00]
      - [0xE4, 0xE0]
      - [0xE5, 0x06]
      - [0xE6, 0x21]
      - [0xE7, 0x01]
      - [0xE8, 0x05]
      - [0xE9, 0x02]
      - [0xEA, 0xDA]
      - [0xEB, 0x00]
      - [0xEC, 0x00]
      - [0xED, 0x0F]
      - [0xEE, 0x00]
      - [0xEF, 0x00]
      - [0xF8, 0x00]
      - [0xF9, 0x00]
      - [0xFA, 0x00]
      - [0xFB, 0x00]
      - [0xFC, 0x00]
      - [0xFD, 0x00]
      - [0xFE, 0x00]
      - [0xFF, 0x00]
      - [0x60, 0x40]
      - [0x61, 0x04]
      - [0x62, 0x00]
      - [0x63, 0x42]
      - [0x64, 0xD9]
      - [0x65, 0x00]
      - [0x66, 0x00]
      - [0x67, 0x00]
      - [0x68, 0x00]
      - [0x69, 0x00]
      - [0x6A, 0x00]
      - [0x6B, 0x00]
      - [0x70, 0x40]
      - [0x71, 0x03]
      - [0x72, 0x00]
      - [0x73, 0x42]
      - [0x74, 0xD8]
      - [0x75, 0x00]
      - [0x76, 0x00]
      - [0x77, 0x00]
      - [0x78, 0x00]
      - [0x79, 0x00]
      - [0x7A, 0x00]
      - [0x7B, 0x00]
      - [0x80, 0x48]
      - [0x81, 0x00]
      - [0x82, 0x06]
      - [0x83, 0x02]
      - [0x84, 0xD6]
      - [0x85, 0x04]
      - [0x86, 0x00]
      - [0x87, 0x00]
      - [0x88, 0x48]
      - [0x89, 0x00]
      - [0x8A, 0x08]
      - [0x8B, 0x02]
      - [0x8C, 0xD8]
      - [0x8D, 0x04]
      - [0x8E, 0x00]
      - [0x8F, 0x00]
      - [0x90, 0x48]
      - [0x91, 0x00]
      - [0x92, 0x0A]
      - [0x93, 0x02]
      - [0x94, 0xDA]
      - [0x95, 0x04]
      - [0x96, 0x00]
      - [0x97, 0x00]
      - [0x98, 0x48]
      - [0x99, 0x00]
      - [0x9A, 0x0C]
      - [0x9B, 0x02]
      - [0x9C, 0xDC]
      - [0x9D, 0x04]
      - [0x9E, 0x00]
      - [0x9F, 0x00]
      - [0xA0, 0x48]
      - [0xA1, 0x00]
      - [0xA2, 0x05]
      - [0xA3, 0x02]
      - [0xA4, 0xD5]
      - [0xA5, 0x04]
      - [0xA6, 0x00]
      - [0xA7, 0x00]
      - [0xA8, 0x48]
      - [0xA9, 0x00]
      - [0xAA, 0x07]
      - [0xAB, 0x02]
      - [0xAC, 0xD7]
      - [0xAD, 0x04]
      - [0xAE, 0x00]
      - [0xAF, 0x00]
      - [0xB0, 0x48]
      - [0xB1, 0x00]
      - [0xB2, 0x09]
      - [0xB3, 0x02]
      - [0xB4, 0xD9]
      - [0xB5, 0x04]
      - [0xB6, 0x00]
      - [0xB7, 0x00]
      - [0xB8, 0x48]
      - [0xB9, 0x00]
      - [0xBA, 0x0B]
      - [0xBB, 0x02]
      - [0xBC, 0xDB]
      - [0xBD, 0x04]
      - [0xBE, 0x00]
      - [0xBF, 0x00]
      - [0xC0, 0x10]
      - [0xC1, 0x47]
      - [0xC2, 0x56]
      - [0xC3, 0x65]
      - [0xC4, 0x74]
      - [0xC5, 0x88]
      - [0xC6, 0x99]
      - [0xC7, 0x01]
      - [0xC8, 0xBB]
      - [0xC9, 0xAA]
      - [0xD0, 0x10]
      - [0xD1, 0x47]
      - [0xD2, 0x56]
      - [0xD3, 0x65]
      - [0xD4, 0x74]
      - [0xD5, 0x88]
      - [0xD6, 0x99]
      - [0xD7, 0x01]
      - [0xD8, 0xBB]
      - [0xD9, 0xAA]
      - [0xF3, 0x01]
      - [0xF0, 0x00]
      - [0xF0, 0x01]
      - [0xF1, 0x01]
      - [0xA0, 0x0B]
      - [0xA3, 0x2A]
      - [0xA5, 0xC3]
      - delay 1ms
      - [0xA3, 0x2B]
      - [0xA5, 0xC3]
      - delay 1ms
      - [0xA3, 0x2C]
      - [0xA5, 0xC3]
      - delay 1ms
      - [0xA3, 0x2D]
      - [0xA5, 0xC3]
      - delay 1ms
      - [0xA3, 0x2E]
      - [0xA5, 0xC3]
      - delay 1ms
      - [0xA3, 0x2F]
      - [0xA5, 0xC3]
      - delay 1ms
      - [0xA3, 0x30]
      - [0xA5, 0xC3]
      - delay 1ms
      - [0xA3, 0x31]
      - [0xA5, 0xC3]
      - delay 1ms
      - [0xA3, 0x32]
      - [0xA5, 0xC3]
      - delay 1ms
      - [0xA3, 0x33]
      - [0xA5, 0xC3]
      - delay 1ms
      - [0xA0, 0x09]
      - [0xF1, 0x10]
      - [0xF0, 0x00]
      - [0x2A, 0x00, 0x00, 0x01, 0x67]
      - [0x2B, 0x01, 0x68, 0x01, 0x68]
      - [0x4D, 0x00]
      - [0x4E, 0x00]
      - [0x4F, 0x00]
      - [0x4C, 0x01]
      - delay 10ms
      - [0x4C, 0x00]
      - [0x2A, 0x00, 0x00, 0x01, 0x67]
      - [0x2B, 0x00, 0x00, 0x01, 0x67]
      - [0x3A, 0x55]
      - [0x21, 0x00]
      - [0x11, 0x00]
      - delay 120ms
      - [0x29, 0x00]
script:
  - id: update_cover_position
    mode: restart
    then:
      - delay: 500ms
      - if:
          condition:
            lambda: 'return id(cover_update_pending);'
          then:
            - logger.log: "Sending cover position to HA"
            - homeassistant.service:
                service: cover.set_cover_position
                data:
                  entity_id: cover.zaslona_salon
                data_template:
                  position: !lambda 'return to_string(id(pending_cover_position));'
            - lambda: 'id(cover_update_pending) = false;'
  - id: update_led_brightness
    mode: restart
    then:
      - delay: 500ms
      - if:
          condition:
            lambda: 'return id(led_update_pending);'
          then:
            - logger.log: "Sending LED brightness to HA"
            - homeassistant.service:
                service: light.turn_on
                data:
                  entity_id: light.0xa4c1388e095eafba
                data_template:
                  brightness_pct: !lambda 'return to_string(id(pending_led_brightness));'
            - lambda: 'id(led_update_pending) = false;'


binary_sensor:
  - platform: gpio
    id: encoder_pin_a
    pin:
      number: GPIO20
      mode: INPUT_PULLUP
      allow_other_uses: true
    on_press:
      - if:
          condition:
            lambda: 'return id(current_page) == 1;'
          then:
            # Page 1 - LED Brightness - Update local value and trigger delayed send
            - lambda: |-
                int current_brightness = id(led_update_pending) ? id(pending_led_brightness) : (int)id(ha_led_brightness).state;
                int new_brightness = current_brightness - 5;
                if (new_brightness < 0) new_brightness = 0;
                id(pending_led_brightness) = new_brightness;
                id(led_update_pending) = true;
            - lvgl.label.update:
                id: brightness_label
                text: !lambda |-
                  static char buf[8];
                  snprintf(buf, sizeof(buf), "%d%%", id(pending_led_brightness));
                  return buf;
            - script.execute: update_led_brightness
      - if:
          condition:
            lambda: 'return id(current_page) == 2;'
          then:
            # Page 2 - Cover Position - Update local value and trigger delayed send
            - lambda: |-
                int current_pos = id(cover_update_pending) ? id(pending_cover_position) : (int)id(ha_zaslona_procent).state;
                int new_pos = current_pos - 10;
                if (new_pos < 0) new_pos = 0;
                id(pending_cover_position) = new_pos;
                id(cover_update_pending) = true;
            - lvgl.label.update:
                id: zaslona_value
                text: !lambda |-
                  static char buf[8];
                  snprintf(buf, sizeof(buf), "%d%%", id(pending_cover_position));
                  return buf;
            - script.execute: update_cover_position
      - if:
          condition: lvgl.is_paused
          then:
            - logger.log: "LVGL resuming from encoder"
            - lvgl.resume:
            - lvgl.widget.redraw:
            - light.turn_on: display_backlight

  - platform: gpio
    id: encoder_pin_b
    pin:
      number: GPIO21
      mode: INPUT_PULLUP
      allow_other_uses: true
    on_press:
      - if:
          condition:
            lambda: 'return id(current_page) == 1;'
          then:
            # Page 1 - LED Brightness - Update local value and trigger delayed send
            - lambda: |-
                int current_brightness = id(led_update_pending) ? id(pending_led_brightness) : (int)id(ha_led_brightness).state;
                int new_brightness = current_brightness + 5;
                if (new_brightness > 100) new_brightness = 100;
                id(pending_led_brightness) = new_brightness;
                id(led_update_pending) = true;
            - lvgl.label.update:
                id: brightness_label
                text: !lambda |-
                  static char buf[8];
                  snprintf(buf, sizeof(buf), "%d%%", id(pending_led_brightness));
                  return buf;
            - script.execute: update_led_brightness
      - if:
          condition:
            lambda: 'return id(current_page) == 2;'
          then:
            # Page 2 - Cover Position - Update local value and trigger delayed send
            - lambda: |-
                int current_pos = id(cover_update_pending) ? id(pending_cover_position) : (int)id(ha_zaslona_procent).state;
                int new_pos = current_pos + 10;
                if (new_pos > 100) new_pos = 100;
                id(pending_cover_position) = new_pos;
                id(cover_update_pending) = true;
            - lvgl.label.update:
                id: zaslona_value
                text: !lambda |-
                  static char buf[8];
                  snprintf(buf, sizeof(buf), "%d%%", id(pending_cover_position));
                  return buf;
            - script.execute: update_cover_position
      - if:
          condition: lvgl.is_paused
          then:
            - logger.log: "LVGL resuming from encoder"
            - lvgl.resume:
            - lvgl.widget.redraw:
            - light.turn_on: display_backlight

number:    
  - platform: template
    name: LED Brightness
    id: led_brightness
    optimistic: true
    min_value: 0
    max_value: 100
    step: 1
    unit_of_measurement: "%"
    mode: slider
  
lvgl:
  on_idle:
    timeout: 30s
    then:
      - logger.log: "LVGL is idle - preparing for deep sleep"
#      - light.turn_off: display_backlight
      - lvgl.pause:
      - delay: 1800s
      - logger.log: "Entering deep sleep"
#      - deep_sleep.enter: deep_sleep_control

  pages:

    # First Page
    - id: page_1
      widgets:
        - obj:
            id: background
            x: 0
            y: 0
            width: 360
            height: 360
            bg_color: 0x000000
            border_width: 0
            pad_all: 0

        - label:
            id: led_name
            align: top_mid
            y: 40
            text: "LED"
            text_font: roboto_32
            text_color: 0xFFFFFF

        - label:
            id: brightness_label
            align: top_mid
            y: 70
            text_font: roboto_88
            text_color: 0xFFFFFF

        - label:
            id: temperatura_name
            align: top_mid
            y: 200
            text: "Temperatura"
            text_font: roboto_20
            text_color: 0xFFFFFF
        - label:
            id: temperatura_label
            align: top_mid
            y: 230
            text_font: roboto_32
            text_color: 0xFFFFFF
        - label:
            id: bateria_label
            align: top_mid
            y: 300
            text_font: roboto_20
            text_color: 0xFFFFFF

      on_swipe_left:
        - lambda: 'id(current_page) = 2;'
        - lvgl.page.show:
            id: page_2
            animation: MOVE_LEFT

      on_swipe_right:
        - lambda: 'id(current_page) = 3;'
        - lvgl.page.show:
            id: page_3 
            animation: MOVE_RIGHT
                  
    - id: page_2
      widgets:
        - obj:
            id: background1
            x: 0
            y: 0
            width: 360
            height: 360
            bg_color: 0x000000
            border_width: 0
            pad_all: 0

        - label:
            id: zaslona_name
            align: top_mid
            y: 40
            text: "Zasłona"
            text_font: roboto_32
            text_color: 0xFFFFFF
        - label:
            id: zaslona_value
            align: top_mid
            y: 70
            text_font: roboto_88
            text_color: 0xFFFFFF

        - label:
            id: temperatura_name1
            align: top_mid
            y: 200
            text: "Temperatura"
            text_font: roboto_20
            text_color: 0xFFFFFF
        - label:
            id: temperatura_label1
            align: top_mid
            y: 230
            text_font: roboto_32
            text_color: 0xFFFFFF

        - label:
            id: bateria_label1
            align: top_mid
            y: 300
            text_font: roboto_20
            text_color: 0xFFFFFF

      on_swipe_left:
        - lambda: 'id(current_page) = 3;'
        - lvgl.page.show:
            id: page_3
            animation: MOVE_LEFT
      on_swipe_right:
        - lambda: 'id(current_page) = 1;'
        - lvgl.page.show:  
            id: page_1
            animation: MOVE_RIGHT

    # Page 3
    - id: page_3
      widgets:
        - obj:
            id: background2
            x: 0
            y: 0
            width: 360
            height: 360
            bg_color: 0x000000
            border_width: 0
            pad_all: 0
        - switch:
            align: center
            id: lampa_salon
            on_click:
              - homeassistant.service:
                  service: switch.toggle
                  data:
                    entity_id: switch.0x70b3d52b600fde27
      on_swipe_left:
        - lambda: 'id(current_page) = 1;'
        - lvgl.page.show:
            id: page_1
            animation: MOVE_LEFT

      on_swipe_right:
        - lambda: 'id(current_page) = 2;'
        - lvgl.page.show:
            id: page_2
            animation: MOVE_RIGHT

sensor:

  - platform: homeassistant
    id: ha_led_brightness
    entity_id: light.0xa4c1388e095eafba
    attribute: brightness
    filters:
      - filter_out: nan
      - multiply: 0.392156863
    on_value:
      then:
        - if:
            condition:
              lambda: 'return !isnan(x);'
            then:
              - lvgl.label.update:
                  id: brightness_label
                  text: !lambda |-
                    static char buf[8];
                    snprintf(buf, sizeof(buf), "%d%%", (int)x);
                    return buf;

  - platform: homeassistant
    id: ha_zaslona_procent
    entity_id: cover.zaslona_salon
    attribute: current_position
    filters:
      - filter_out: nan    
    on_value:
      then:
        - lvgl.label.update:
            id: zaslona_value
            text: !lambda |-
              static char buf[8];
              snprintf(buf, sizeof(buf), "%d%%", (int)x);
              return buf;

  - platform: homeassistant
    id: ha_temperatura
    entity_id: sensor.termometr_salon_temperature
    on_value:
      then:
        - lvgl.label.update:
            id: temperatura_label
            text: !lambda |-
              static char buf[16];
              snprintf(buf, sizeof(buf), "%.1f°C", (float)x);
              return buf;
        - lvgl.label.update:
            id: temperatura_label1
            text: !lambda |-
              static char buf[16];
              snprintf(buf, sizeof(buf), "%.1f°C", (float)x);
              return buf;

  - platform: adc
    pin: 1
    name: "Battery Voltage"
    id: battery_voltage
    attenuation: 12db
    accuracy_decimals: 2
    update_interval: 1s
    unit_of_measurement: "V"
    icon: mdi:battery-medium
    filters:
      - multiply: 2.0
      - median:
          window_size: 7
          send_every: 7
          send_first_at: 7
      - throttle: 1min
    on_value:
      then:
        - component.update: battery_percentage

  - platform: template
    id: battery_percentage
    name: "Battery Percentage"
    lambda: return id(battery_voltage).state;
    accuracy_decimals: 0
    unit_of_measurement: "%"
    icon: mdi:battery-medium
    filters:
      - calibrate_linear:
         method: exact
         datapoints:
          - 2.80 -> 0.0
          - 3.10 -> 10.0
          - 3.30 -> 20.0
          - 3.45 -> 30.0
          - 3.60 -> 40.0
          - 3.70 -> 50.0
          - 3.75 -> 60.0
          - 3.80 -> 70.0
          - 3.90 -> 80.0
          - 4.00 -> 90.0
          - 4.20 -> 100.0
      - lambda: |-
          if (x > 100) return 100;
          if (x < 0) return 0;
          return x;
    on_value:
      then:
        - lvgl.label.update:
            id: bateria_label
            text: !lambda |-
              static char buf[8];
              snprintf(buf, sizeof(buf), "%d%%", (int)x);
              return buf;
        - lvgl.label.update:
            id: bateria_label1
            text: !lambda |-
              static char buf[8];
              snprintf(buf, sizeof(buf), "%d%%", (int)x);
              return buf;

  - platform: homeassistant
    id: lampa_ha
    entity_id: switch.0x70b3d52b600fde27
    on_value:
      then:
        - lvgl.widget.update:
            id: lampa_salon
            state:
              checked: !lambda 'return id(lampa_ha).state != 0;'

This is my repo … I will try to add deep sleep functionality to DFR1221 V2
https://github.com/AdamM68/DFR1221-esphome-HA