Skip to content

mplogas/esphome-ui-kit

Repository files navigation

ESPHome UI Kit

Overview

This repository provides a modular framework for building LVGL user interfaces in ESPHome. It abstracts hardware complexity and provides a reusable component system. While designed for the Seeedstudio SenseCAP Indicator (D1x), the architecture is adaptable to any ESPHome-supported display.

Technical documentation is provided in INSTRUCTIONS.md and AGENTS.md to support development and widget creation.

Directory Structure

  • hardware/: Device-specific configurations.
  • src/: Custom C++ headers for advanced LVGL features (e.g., Charts).
  • templates/: Reusable logic and UI components.
    • core/: UI structural components, globals, and the Data Bridge.
    • devices/: Virtual device definitions.
    • layouts/: Page layout templates.
    • scripts/: Shared scripts and packages.
    • overlays/: Contextual UI layers.
    • tabs/: Screen definitions.
    • widgets/: Standalone UI elements.
  • theme/: UI styling and variables.

Configuration Files

  • main-dashboard.yaml: Main entry point and dashboard configuration.
  • templates/core/mapping-defaults.yaml: View 1 (Mapping) fallbacks and state defaults.
  • secrets.yaml: WiFi and API credentials.
  • theme/defaults.yaml: Global UI variables (colors, dimensions, spacing).
  • theme/style.yaml: LVGL style definitions.
  • templates/core/fonts.yaml: Font mappings.

Core Concepts

The 3-View Architecture

The framework enforces a strict separation of concerns:

  • View 1: User Configuration: Handled in main-dashboard.yaml (or testing.yaml). Maps HA entities to substitutions.
  • View 2: Design & Templates: Located in templates/widgets/, layouts/, and theme/. These are visual components that read from the Data Pool.
  • View 3: Core Logic (Data Bridge): Located in layouts/*/data_bridge.yaml and widget_logic.yaml. This layer connects HA to the Data Pool (Globals) and triggers UI refreshes.

Hardware Abstraction

Hardware-specific setup (ESP32-S3, PSRAM, display, touchscreen) is isolated in hardware/. Reference these templates in your main configuration.

Logic & Packages

Uses ESPHome packages to separate concerns:

  • hardware: Drivers and display initialization.
  • core/globals: The "Data Pool" of global variables.
  • core/data_bridge: Home Assistant entity connections to the Data Pool.
  • core/widget_logic: Scripts that sync the Data Pool to LVGL objects.
  • scripts/common: Shared UI bridge scripts and logic.

Grid-based Layout

Tabs use grid_container.yaml to implement LVGL's grid layout. Dimensions and positions are passed via substitutions.

Reusable Widgets

Widgets and Tiles are YAML snippets accepting:

  • id: Unique component identifier.
  • grid_col_pos / grid_row_pos (or col / row): Grid position.
  • grid_x_align / grid_y_align: Cell alignment (defaults to STRETCH).
  • widget_clickable: Enable/disable touch events.
  • widget_on_click: C++ lambda for touch actions.

Theme System

theme/defaults.yaml centralizes UI parameters:

  • Screen dimensions.
  • Color palette (with auto-generated variants).
  • Grid spacing and padding.
  • Font IDs.
  • Idle timeout.

Features

  • Decoupled Sync (Data Bridge): UI components don't talk directly to Home Assistant. They observe global variables, ensuring the UI remains responsive even if HA is offline.
  • Dynamic Styling: Light tiles automatically tint their icons and backgrounds based on the RGB state of the Home Assistant entity.
  • Idle Management: Configurable timeout to pause LVGL and disable backlight.
  • Clickable Cards: Any widget container can be made clickable with theme-defined visual feedback.
  • Advanced Data Visualization: Custom LVGL Chart widget for displaying sensor history with auto-scaling and value overlays.

Usage

  1. Copy main-dashboard.yaml to a new file (e.g., my-device.yaml).
  2. Update the substitutions block with your Home Assistant entity IDs (lights, scenes, weather).
  3. Compile and flash:
esphome run my-device.yaml

Adding New Graphs

The framework supports multiple independent graph widgets. To add a new one:

  1. Define a Data Buffer: In layouts/X/globals_extension.yaml, add a new std::vector<float> to store the sensor history.
    - id: my_sensor_values
      type: std::vector<float>
  2. Add the Widget: In your tab definition (e.g., layouts/X/tabs/sensors.yaml), include the graph widget with a unique widget_id.
    - <<: !include
        file: ../../../templates/widgets/graph.yaml
        vars:
          widget_id: my_new_graph
          graph_title: "My Sensor"
          graph_unit: "unit"
          # ...
  3. Initialize on Boot: In main-dashboard.yaml, add the initialization script to the on_boot trigger.
    - script.execute:
        id: init_graph
        container_obj: !lambda "return id(my_new_graph_chart_container);"
        color: 0xHEXCODE
  4. Connect the Sensor: In layouts/X/data_bridge.yaml, update your sensor to push data to the buffer and trigger the UI update.
    on_value:
      - lambda: |-
          id(my_sensor_values).push_back(x);
          if (id(my_sensor_values).size() > ${chart_max_points}) {
            id(my_sensor_values).erase(id(my_sensor_values).begin());
          }
      - script.execute:
          id: my_refresh_script # Defined in widget_logic.yaml
          # Or call update_graph directly

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages