TRMNL HA

repository·main·Indexed 41 days ago

https://github.com/usetrmnl/trmnl-home-assistant

A tool for capturing screenshots of Home Assistant dashboards or any website and optimizing them for e-ink displays using advanced dithering. It supports automatic uploads to TRMNL devices via webhooks, on-demand pull requests via URL, and scheduled captures. Available as a Home Assistant OS add-on or Docker container (version 0.10.3), featuring presets for over 24 e-ink displays and support for Floyd-Steinberg and Ordered dithering algorithms.

Tokens
21.7K
Snippets
53
Records
93
Agent score
45%

What's inside TRMNL HA

  1. Overview of TRMNL HA features

    main

    TRMNL HA allows you to send Home Assistant dashboard screenshots (or any website screenshots) to TRMNL e-ink displays. Key capabilities include:

    • E-ink optimized dithering: Uses Floyd-Steinberg and Ordered algorithms for high-quality e-paper rendering.
    • TRMNL webhook integration: Automatically uploads dashboards to TRMNL devices.
    • Fetch URL (pull mode): Provides a direct URL for on-demand screenshots, compatible with ESPHome and custom e-ink setups.
    • Scheduled captures: Supports cron-based automation managed via a Web UI.
    • Device presets: Includes pre-configured settings for over 24 popular e-ink displays.
    • High performance: Built on the Bun runtime for fast startup and low memory footprint.
  2. Secure your TRMNL HA installation

    main

    The TRMNL HA Web UI (running on port 10000) does not have built-in authentication. To maintain security:

    • Use Ingress: Access the interface via the Home Assistant sidebar integration (Ingress) rather than direct port access.
    • Do not expose port 10000: Never expose this port directly to the internet.
    • Trusted Networks: This add-on is designed to be used within trusted home networks.
  3. How session expiration works in Terminus

    main

    By default, session expiration is off.

    If you enable session_expiration_enabled, Terminus expires a session after 30 minutes of inactivity (session_inactivity_limit) and 24 hours in total (session_lifetime_limit). API tokens are tied to these sessions.

    Important considerations for scheduled pushes:

    • Refreshing a session resets the inactivity timer but never the lifetime cap.
    • A session will lapse exactly one day after login, regardless of how often the token is refreshed.
    • When the session lapses, all scheduled pushes will fail until a user manually signs in again.
    • To extend session duration, you must move api_access_token_period, session_inactivity_limit, and session_lifetime_limit together, as the shortest of the three determines the expiration.

    If you enable expiration because the server is reachable outside your trusted network, you can use the TRMNL add-on to automatically save and re-authenticate logins.

  4. Security considerations for the Terminus Server add-on

    main

    The Terminus Server add-on is designed for use on trusted home networks.

    Key Security Details:

    • Authentication: While the underlying Terminus server includes authentication features, this Home Assistant add-on wrapper does not provide additional security layers for port or database credential access.
    • Sandboxing: The container is confined by an AppArmor profile. It is denied access to:
      • Home Assistant directories: /config, /ssl, /backup, /share, and /media.
      • Other add-ons.
      • Raw sockets.
    • Default Port: The server is exposed to port 2300 by default.
  5. Understand Pull vs Push modes in TRMNL HA

    main

    TRMNL HA supports two distinct data delivery architectures:

    Pull (Fetch URL)

    • Mechanism: The client (e.g., ESPHome, custom e-ink device) requests the image via an HTTP GET request.
    • Behavior: A fresh screenshot is generated on every request. The browser launches automatically if not already running.
    • Use Case: On-demand updates, testing, or devices that initiate communication.

    Push (Webhook)

    • Mechanism: The TRMNL HA add-on POSTs the captured image to a pre-configured webhook URL.
    • Behavior: Captures are performed based on a defined cron schedule.
    • Use Case: Standard TRMNL devices and automated scheduled updates.

    Note: You can use both modes simultaneously on the same schedule.

  6. Security and Data Persistence

    main

    Security Model

    This add-on is designed for trusted home networks. It does not provide special security wrappers for port or database credential access.

    However, the container is confined by an AppArmor profile (apparmor.txt) which denies access to:

    • Home Assistant's /config, /ssl, /backup, /share, and /media directories.
    • Other add-ons.
    • Raw sockets.

    To check for AppArmor denials after deployment, run the following command via SSH on your Home Assistant instance:

    journalctl _TRANSPORT="audit" | grep 'apparmor="DENIED"' | grep trmnl-terminus

    Data Persistence and Backups

    All persistent data is stored under /data inside the add-on container and includes:

    • PostgreSQL database files
    • Valkey (cache/queue) data
    • Uploaded images and fonts
    • Application secret key

    This data is included in Home Assistant backups. The add-on is automatically stopped during backups to ensure data consistency. Logs and temporary files are excluded from backups.

  7. Understand TRMNL HA mounted volumes

    main

    The TRMNL HA add-on uses specific directories for persistent storage and temporary processing. Understanding these is crucial for managing data and logs:

    • /data: Add-on persistent storage. Contains options.json (user configuration), schedules.json (saved screenshot schedules), logs/ (application logs), and output/ (generated screenshots).
    • /tmp: Temporary files used for browser operations and image processing.
  8. Configure Webhook formats for screenshots

    main

    Schedules can deliver screenshots using one of two formats:

    1. Raw Image (Default): Sends the binary image directly. Best for TRMNL devices or custom endpoints.
    2. Terminus: Sends a short message naming the screen to a Terminus server, which then fetches the image from the add-on.

    Note for Terminus users: The Add-on URL must be an address reachable by your Terminus server (often not localhost).

  9. Install TRMNL HA via Docker Compose

    main

    For users running Home Assistant in a container, add TRMNL HA as a separate service in your docker-compose.yml.

    Important: You MUST use your device's actual IP address (e.g., http://192.168.1.100:8123) for HOME_ASSISTANT_URL because .local mDNS names do not resolve inside Docker containers.

    Architecture Note: Use the ghcr.io/usetrmnl/trmnl-ha-aarch64:latest image for ARM64 devices (Raspberry Pi 4/5, Apple Silicon) and ghcr.io/usetrmnl/trmnl-ha-amd64:latest for standard x86_64 hardware.

    services:
      homeassistant:
        image: ghcr.io/home-assistant/home-assistant:stable
        container_name: homeassistant
        volumes:
          - /PATH_TO_YOUR_CONFIG:/config
          - /etc/localtime:/etc/localtime:ro
        restart: unless-stopped
        privileged: true
        network_mode: host
    
      trmnl-ha:
        image: ghcr.io/usetrmnl/trmnl-ha-amd64:latest
        # For ARM64: ghcr.io/usetrmnl/trmnl-ha-aarch64:latest
        container_name: trmnl-ha
        restart: unless-stopped
        ports:
          - "10000:10000"
        environment:
          - HOME_ASSISTANT_URL=http://192.168.1.x:8123
          - ACCESS_TOKEN=your_long_lived_access_token
          - KEEP_BROWSER_OPEN=true
          - TZ=America/New_York
        volumes:
          - ./trmnl-data:/data
    
    volumes:
      trmnl-data:
  10. Install TRMNL HA via Docker

    main

    If you are running Home Assistant in a Docker container, you can run TRMNL HA as a separate container.

    Important Requirements:

    • Use your machine's actual IP address for HOME_ASSISTANT_URL (e.g., 192.168.1.100). Do not use localhost or container names like homeassistant because Home Assistant requires host networking.
    • For ARM64 architectures (Raspberry Pi 4/5, Apple Silicon), use the aarch64 image.

    Run Command:

    docker run -d --name trmnl-ha \
      --restart unless-stopped \
      -e HOME_ASSISTANT_URL=http://YOUR_HOST_IP:8123 \
      -e ACCESS_TOKEN=your_token_here \
      -p 10000:10000 \
      -v ./trmnl-data:/data \
      ghcr.io/usetrmnl/trmnl-ha-amd64:latest

    After running, access the Web UI at http://localhost:10000.

    docker run -d --name trmnl-ha \
      --restart unless-stopped \
      -e HOME_ASSISTANT_URL=http://YOUR_HOST_IP:8123 \
      -e ACCESS_TOKEN=your_token_here \
      -p 10000:10000 \
      -v ./trmnl-data:/data \
      ghcr.io/usetrmnl/trmnl-ha-amd64:latest # ARM64 (Pi 4/5, Apple Silicon): ghcr.io/usetrmnl/trmnl-ha-aarch64:latest
  11. Trigger On-Demand Captures from Home Assistant Automations

    main

    You can trigger a TRMNL HA capture using a Home Assistant rest_command. This is useful for capturing a dashboard immediately when a specific event occurs.

    1. Define a rest_command in your configuration.yaml using the schedule's send endpoint.
    2. Use the add-on's hostname (e.g., local-trmnl-ha for Supervisor add-ons).
    3. Call the action in your automation.

    Tip: Create a 'disabled' schedule in the TRMNL HA Web UI. This schedule will never run on its own cron, but it allows you to trigger a capture manually via the API whenever you call the action.

    # configuration.yaml
    rest_command:
      trmnl_capture:
        url: "http://local-trmnl-ha:10000/api/schedules/{{ schedule_id }}/send"
        method: POST
    
    # automation.yaml
    actions:
      - action: rest_command.trmnl_capture
        data:
          schedule_id: "your_schedule_id"  # from the add-on's schedule list
  12. Set up local development environment

    main

    To develop on trmnl-ha, you need Bun 1.3.5+, Docker, and VS Code with the Dev Containers extension.

    Quick Start Setup

    1. Navigate to the package directory: cd trmnl-ha/ha-trmnl
    2. Copy the example options file: cp options-dev.json.example options-dev.json
    3. Edit options-dev.json with your target URL.

    Running Development Modes

    Hot-Reload (Docker - Recommended):

    ./scripts/docker-dev.sh

    Hot-Reload (Native Bun - Faster, requires local Chrome):

    # From trmnl-ha/ha-trmnl
    bun install && bun run dev

    Production Testing:

    ./scripts/docker-build.sh && ./scripts/docker-run.sh

    Testing Commands

    bun test              # All tests
    bun test --coverage   # With coverage
    bun run lint          # ESLint