New boards Wishlist

Add support for Hosyond 2.8" ESP32-S3 Touchscreen (320×240)

sebblmahrSuggested this wish ·

Hi Max,

I'd love to see support for the Hosyond 2.8-inch ESP32-S3 touchscreen display in Tessera.

I already use this display as a Home Assistant desk control panel with ESPHome and LVGL. It works with my existing configuration, and I'd like to switch to Tessera for easier dashboard design and maintenance.

Hardware details:

Manufacturer: Hosyond

Display size: 2.8 inches

Resolution: 320 × 240 pixels

Microcontroller: ESP32-S3

Touch controller: FT63X6 (I²C)

External PSRAM available

Current software: ESPHome with LVGL

Current use case: A small Home Assistant desk panel controlling lights, heating and other smart-home devices, with indoor and outdoor temperature readings.

Additional information: I can provide my existing working ESPHome YAML configuration, including the display, touchscreen and GPIO settings, to help with integration and testing.

Thanks for developing Tessera!

Hardware testing

We often do not have this board ourselves. Community testing helps establish what actually works. A successful report is evidence for the maintainer to review, not an automatic compatibility claim.

Board details & configuration
Model
Hosyond 2.8-inch ESP32-S3
Chip, RAM and flash
ESP32-S3
Display and touch
FT63X6 (I²C)
Already tried
Tried own Yaml which is working, find this attached
Configuration status
working
View shared configuration
esphome:
  name: schreibtisch-panel
  friendly_name: Schreibtisch Panel

esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  flash_size: 16MB
  framework:
    type: esp-idf

psram:
  mode: octal
  speed: 80MHz

logger:
  level: DEBUG

wifi:
  networks:
    - ssid: 
      password: 
      bssid: 
  min_auth_mode: WPA2

api:

ota:
  - platform: esphome


# ==========================================
# SCHRIFTEN
# ==========================================

font:
  - file: "gfonts://Material+Symbols+Outlined"
    id: icon_34
    size: 34
    bpp: 4
    glyphs:
      - "\U0000E01D"
      - "\U0000E90F"
      - "\U0000F076"
      - "\U0000EA65"

  - file: "gfonts://Roboto"
    id: temperature_font
    size: 23
    bpp: 4
    glyphs:
      - "0123456789.- °C"


# ==========================================
# HOME ASSISTANT: SCHALTER
# ==========================================

binary_sensor:

  # LED-BARS
  - platform: homeassistant
    id: ha_ledbars
    entity_id: input_boolean.ledbars

    on_state:
      then:
        - lvgl.widget.update:
            id: led_bars_button
            bg_color: !lambda |-
              return x ? lv_color_hex(0x35150D) : lv_color_hex(0x211A17);
            border_color: !lambda |-
              return x ? lv_color_hex(0xFF4300) : lv_color_hex(0x514741);

        - lvgl.widget.update:
            id: led_bars_icon
            text_color: !lambda |-
              return x ? lv_color_hex(0xFF4300) : lv_color_hex(0xB9B1AC);


  # PARTY-MODUS
  - platform: homeassistant
    id: ha_party
    entity_id: input_boolean.party_modus

    on_state:
      then:
        - lvgl.widget.update:
            id: party_button
            bg_color: !lambda |-
              return x ? lv_color_hex(0x35150D) : lv_color_hex(0x211A17);
            border_color: !lambda |-
              return x ? lv_color_hex(0xFF4300) : lv_color_hex(0x514741);

        - lvgl.widget.update:
            id: party_icon
            text_color: !lambda |-
              return x ? lv_color_hex(0xFF4300) : lv_color_hex(0xB9B1AC);


  # RAUM-LICHT / BACKLIGHT
  - platform: homeassistant
    id: ha_room_light
    entity_id: binary_sensor.musikzimmer_ls_musikzimmer_eingang_0

    on_state:
      then:
        - if:
            condition:
              binary_sensor.is_on: ha_room_light
            then:
              - light.turn_on:
                  id: backlight
                  brightness: 75%
                  transition_length: 300ms
            else:
              - light.turn_off:
                  id: backlight
                  transition_length: 300ms


# ==========================================
# HOME ASSISTANT: STATUS
# ==========================================

text_sensor:

  # LAMPE
  - platform: homeassistant
    id: ha_lamp
    entity_id: switch.trompetenlampe_2

    on_value:
      then:
        - lvgl.widget.update:
            id: lamp_button
            bg_color: !lambda |-
              return x == "on" ? lv_color_hex(0x3A2508) : lv_color_hex(0x211A17);
            border_color: !lambda |-
              return x == "on" ? lv_color_hex(0xFFB52E) : lv_color_hex(0x514741);

        - lvgl.widget.update:
            id: lamp_icon
            text_color: !lambda |-
              return x == "on" ? lv_color_hex(0xFFB52E) : lv_color_hex(0xB9B1AC);


  # HEIZUNG
  - platform: homeassistant
    id: ha_heating_state
    entity_id: climate.hz_musikzimmer_ir_heizung

    on_value:
      then:
        - lvgl.widget.update:
            id: heating_button
            bg_color: !lambda |-
              return x != "off" ? lv_color_hex(0x35150D) : lv_color_hex(0x211A17);
            border_color: !lambda |-
              return x != "off" ? lv_color_hex(0xFF4300) : lv_color_hex(0x514741);

        - lvgl.widget.update:
            id: heating_icon
            text_color: !lambda |-
              return x != "off" ? lv_color_hex(0xFF4300) : lv_color_hex(0xB9B1AC);


# ==========================================
# TEMPERATUREN
# ==========================================

sensor:

  - platform: homeassistant
    id: ha_temperature_inside
    entity_id: sensor.temperatur_musikzimmer

  - platform: homeassistant
    id: ha_temperature_outside
    entity_id: sensor.aussentemperatur


# ==========================================
# TEMPERATUR-UPDATE
# Ohne Debug-Logging
# ==========================================

interval:
  - interval: 5s
    then:
      - lvgl.label.update:
          id: temperature_inside
          text:
            format: "%.1f °C"
            args:
              - id(ha_temperature_inside).state
            if_nan: "--.- °C"

      - lvgl.label.update:
          id: temperature_outside
          text:
            format: "%.1f °C"
            args:
              - id(ha_temperature_outside).state
            if_nan: "--.- °C"


# ==========================================
# DISPLAY
# ==========================================

spi:
  clk_pin: GPIO12
  mosi_pin: GPIO11
  miso_pin: GPIO13

display:
  - platform: ili9xxx
    model: ili9341
    id: my_display

    cs_pin: GPIO10
    dc_pin: GPIO46

    dimensions:
      width: 240
      height: 320

    # KORREKTUR:
    # Invertierung bleibt aktiv.
    # BGR statt RGB fuer warme Akzentfarben.
    invert_colors: true
    color_order: BGR

    pixel_mode: 16bit
    data_rate: 40MHz

    auto_clear_enabled: false
    update_interval: never


# ==========================================
# BACKLIGHT
# ==========================================

output:
  - platform: ledc
    pin: GPIO45
    frequency: 1000Hz
    id: display_backlight

light:
  - platform: monochromatic
    name: "Display Backlight"
    id: backlight
    output: display_backlight
    restore_mode: ALWAYS_OFF


# ==========================================
# TOUCH / I2C
# ==========================================

i2c:
  sda: GPIO16
  scl: GPIO15
  scan: true
  frequency: 400kHz

touchscreen:
  - platform: ft63x6
    id: my_touchscreen
    display: my_display
    interrupt_pin: GPIO17
    reset_pin: GPIO18

    on_release:
      then:
        - if:
            condition:
              binary_sensor.is_on: ha_room_light
            then:
              - light.turn_on:
                  id: backlight
                  brightness: 75%
                  transition_length: 200ms
            else:
              - light.turn_on:
                  id: backlight
                  brightness: 75%
                  transition_length: 100ms


# ==========================================
# LVGL
# ==========================================

lvgl:
  displays:
    - my_display

  touchscreens:
    - touchscreen_id: my_touchscreen

  rotation: 90

  bg_color: 0x151515

  # AUTOMATISCHE HELLIGKEIT
  on_idle:
    - timeout: 5s
      then:
        - if:
            condition:
              binary_sensor.is_off: ha_room_light
            then:
              - light.turn_on:
                  id: backlight
                  brightness: 25%
                  transition_length: 500ms

    - timeout: 10s
      then:
        - if:
            condition:
              binary_sensor.is_off: ha_room_light
            then:
              - light.turn_off:
                  id: backlight
                  transition_length: 500ms


  # ========================================
  # DARKMODE-THEME
  # ========================================

  theme:
    button:
      bg_color: 0x211A17
      bg_opa: COVER
      text_color: 0xF4EDE7
      border_width: 2
      border_color: 0x514741
      radius: 14
      shadow_width: 0
      shadow_opa: 0

      pressed:
        bg_color: 0x3A2118
        border_color: 0xFF4300
        text_color: 0xFFF1E8

    label:
      text_color: 0xF4EDE7


  # ========================================
  # WIDGETS
  # ========================================

  widgets:

    # --------------------------------------
    # LED-BARS
    # --------------------------------------

    - button:
        id: led_bars_button
        x: 2
        y: 2
        width: 156
        height: 82

        bg_color: 0x211A17
        bg_opa: COVER
        border_color: 0x514741
        border_width: 2
        radius: 14
        pad_all: 0

        on_click:
          then:
            - homeassistant.action:
                action: input_boolean.toggle
                data:
                  entity_id: input_boolean.ledbars

        widgets:
          - label:
              id: led_bars_icon
              x: 0
              y: 6
              width: 156
              height: 38
              text: "\U0000E01D"
              text_font: icon_34
              text_align: CENTER
              text_color: 0xB9B1AC

          - label:
              x: 0
              y: 49
              width: 156
              height: 25
              text: "LED-BARS"
              text_font: montserrat_18
              text_align: CENTER
              text_color: 0xF4EDE7


    # --------------------------------------
    # PARTY-MODUS
    # --------------------------------------

    - button:
        id: party_button
        x: 162
        y: 2
        width: 156
        height: 82

        bg_color: 0x211A17
        bg_opa: COVER
        border_color: 0x514741
        border_width: 2
        radius: 14
        pad_all: 0

        on_click:
          then:
            - homeassistant.action:
                action: input_boolean.toggle
                data:
                  entity_id: input_boolean.party_modus

        widgets:
          - label:
              id: party_icon
              x: 0
              y: 6
              width: 156
              height: 38
              text: "\U0000EA65"
              text_font: icon_34
              text_align: CENTER
              text_color: 0xB9B1AC

          - label:
              x: 0
              y: 49
              width: 156
              height: 25
              text: "PARTY-MODUS"
              text_font: montserrat_18
              text_align: CENTER
              text_color: 0xF4EDE7


    # --------------------------------------
    # HEIZUNG
    # --------------------------------------

    - button:
        id: heating_button
        x: 2
        y: 88
        width: 156
        height: 82

        bg_color: 0x211A17
        bg_opa: COVER
        border_color: 0x514741
        border_width: 2
        radius: 14
        pad_all: 0

        on_click:
          then:
            - if:
                condition:
                  lambda: |-
                    return id(ha_heating_state).state != "off";
                then:
                  - homeassistant.action:
                      action: climate.turn_off
                      data:
                        entity_id: climate.hz_musikzimmer_ir_heizung
                else:
                  - homeassistant.action:
                      action: climate.turn_on
                      data:
                        entity_id: climate.hz_musikzimmer_ir_heizung

        widgets:
          - label:
              id: heating_icon
              x: 0
              y: 6
              width: 156
              height: 38
              text: "\U0000F076"
              text_font: icon_34
              text_align: CENTER
              text_color: 0xB9B1AC

          - label:
              x: 0
              y: 49
              width: 156
              height: 25
              text: "HEIZUNG"
              text_font: montserrat_18
              text_align: CENTER
              text_color: 0xF4EDE7


    # --------------------------------------
    # LAMPE
    # --------------------------------------

    - button:
        id: lamp_button
        x: 162
        y: 88
        width: 156
        height: 82

        bg_color: 0x211A17
        bg_opa: COVER
        border_color: 0x514741
        border_width: 2
        radius: 14
        pad_all: 0

        on_click:
          then:
            - homeassistant.action:
                action: switch.toggle
                data:
                  entity_id: switch.trompetenlampe_2

        widgets:
          - label:
              id: lamp_icon
              x: 0
              y: 6
              width: 156
              height: 38
              text: "\U0000E90F"
              text_font: icon_34
              text_align: CENTER
              text_color: 0xB9B1AC

          - label:
              x: 0
              y: 49
              width: 156
              height: 25
              text: "LAMPE"
              text_font: montserrat_18
              text_align: CENTER
              text_color: 0xF4EDE7


    # ========================================
    # TEMPERATURBEREICH
    # ========================================

    - obj:
        id: temperature_panel

        x: 2
        y: 176
        width: 316
        height: 62

        bg_color: 0x181818
        bg_opa: COVER
        border_width: 0
        radius: 0
        pad_all: 0

        widgets:

          # TRENNLINIE
          - obj:
              x: 8
              y: 0
              width: 300
              height: 2
              bg_color: 0x8A2A12
              bg_opa: COVER
              border_width: 0
              radius: 0


          # INNEN
          - label:
              x: 8
              y: 5
              width: 142
              height: 20
              text: "INNEN"
              text_font: montserrat_18
              text_align: CENTER
              text_color: 0xB9B1AC

          - label:
              id: temperature_inside
              x: 8
              y: 27
              width: 142
              height: 30
              text: "TEST"
              text_font: temperature_font
              text_align: CENTER
              text_color: 0xFFF1E8
              bg_opa: TRANSP


          # AUSSEN
          - label:
              x: 166
              y: 5
              width: 142
              height: 20
              text: "AUSSEN"
              text_font: montserrat_18
              text_align: CENTER
              text_color: 0xB9B1AC

          - label:
              id: temperature_outside
              x: 166
              y: 27
              width: 142
              height: 30
              text: "TEST"
              text_font: temperature_font
              text_align: CENTER
              text_color: 0xFFF1E8
              bg_opa: TRANSP

1 owner has volunteered to test.

Sign in to volunteer

Discussion 0

Add a comment

Start the conversation

Share an example, ask a question or explain how you would use this.

Add your thoughts, a screenshot or a useful link.

Markdown & basic HTML
Paste or drop images · URLs on their own line become previews0 / 10,000
Create your account to join in

We need a verified email address to reach you about your contribution. Your address stays private.

Continue with GitHub

Your draft stays in this tab. Return here after verification.