DFROBOT DFR1221 1.85inch Round Display ESP32-S3

Just bought new device DFROBOT DFR1221 1.85" round display - I can not find any info how to install esphome on it - any yaml examples ? thanks for help

https://wiki.dfrobot.com/SKU_DFR1221_ESP32_S3_1_85inch_Round_Display_Development_Board

I found this repo :slight_smile: - should work with DFR1221 V2.
When I opened it, there is sign :Guition JC3636W518" marked on the board.

The code from Marcin is for different hw. my model is V2 so I had to change GPIO for display and touch. below code with changed pins - this one is working ! :slight_smile:

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 fork - repository …I will try fo add deep sleep functionality to DFR1221 V2
https://github.com/AdamM68/DFR1221-esphome-HA