### Install and Run Development Server Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Installs dependencies and starts the hot-reload development server for the TRMNL Home Assistant add-on. ```bash cd trmnl-ha/ha-trmnl bun install bun run dev ``` -------------------------------- ### Native Bun Development Setup Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Set up TRMNL HA for native development using Bun. This involves installing dependencies, copying configuration, and running the development server. ```bash cd trmnl-ha/ha-trmnl bun install cp options-dev.json.example options-dev.json bun run dev ``` -------------------------------- ### Setup Local Development Environment Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Navigate to the project directory and copy the development options file. Remember to edit the file with your target URL. ```bash cd trmnl-ha/ha-trmnl cp options-dev.json.example options-dev.json # Edit with your target URL ``` -------------------------------- ### Mock HA Server and Development Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Starts a mock Home Assistant server for local development and runs the application using it. ```bash bun run mock:server MOCK_HA=true bun run dev ``` -------------------------------- ### Release Script Examples Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/scripts/README.md Demonstrates common release scenarios including previewing changes, creating patch releases, and pushing minor/major releases. ```bash # Preview a patch release npm run release:dry ``` ```bash # Create a patch release (bug fixes) npm run release:patch ``` ```bash # Create a minor release (new features) and push bun scripts/release.js minor --push ``` ```bash # Create a major release (breaking changes) npm run release:major ``` -------------------------------- ### Cron Expression Examples Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Provides common examples of cron expressions for various scheduling needs. These can be used to configure automated captures. ```cron */15 * * * * ``` ```cron 0 * * * * ``` ```cron 0 6-22 * * * ``` ```cron 0 8,18 * * * ``` -------------------------------- ### Run Development Server with Native Bun Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md For a faster development cycle, you can run the application natively using Bun. This requires a local Chrome installation. ```bash # Native Bun (faster, requires local Chrome) bun install && bun run dev ``` -------------------------------- ### Run Development Server with Docker Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Use these commands to build and run the development server using Docker. The first command is for the initial setup, and subsequent runs use the second command. ```bash # Docker (recommended) ./scripts/docker-dev.sh --build # First time ./scripts/docker-dev.sh # Subsequent runs ``` -------------------------------- ### Generic Mode URL Format Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Example URL format for fetching screenshots of any website. ```url http://:10000/?url=https://example.com&viewport=800x480&dithering&palette=bw ``` -------------------------------- ### Install ImageMagick on macOS Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Install ImageMagick using Homebrew on macOS. This is a prerequisite for running the application natively with Bun. ```bash brew install imagemagick ``` -------------------------------- ### Run Mock HA Server Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Start a mock Home Assistant server in a separate terminal. This allows for development without connecting to a real HA instance. ```bash bun run mock:server ``` -------------------------------- ### URI Mode Request Example Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md Example of a POST request to the /api/screens endpoint using URI mode. This mode sends a reference to a screenshot endpoint on the add-on itself. ```http POST /api/screens Content-Type: application/json Authorization: { "screen": { "uri": "http://192.168.1.100:10000/lovelace/0?viewport=800x480&dithering=&dither_method=floyd-steinberg&palette=gray-4", "label": "Home Assistant", "name": "ha-dashboard", "model_id": "1", "preprocessed": true } } ``` -------------------------------- ### One-off Fetch with cURL Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Example using cURL to fetch a dashboard screenshot and save it as a BMP file. ```bash # One-off fetch curl "http://192.168.1.x:10000/lovelace/0?viewport=800x480&dithering&palette=bw&format=bmp" -o dashboard.bmp ``` -------------------------------- ### Verify ImageMagick Version Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Check the installed ImageMagick version to ensure it meets the Q16-HDRI requirement for native Bun development. The output should start with 'Version: ImageMagick 7.x.x Q16-HDRI'. ```bash convert -version | head -1 ``` -------------------------------- ### Log Format Example Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Illustrates the structured, timestamped log format used by LogTape. ```log [2025-12-30T11:19:53.454Z] [INFO ] [scheduler] Starting scheduler... [2025-12-30T11:19:53.454Z] [INFO ] [app] Server started at http://localhost:10000 ``` -------------------------------- ### Development Configuration for TRMNL HA Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Configure TRMNL HA for development by copying an example options file and editing it. This setup allows for hot-reloading. ```bash cd trmnl-ha cp ha-trmnl/options-dev.json.example ha-trmnl/options-dev.json ``` ```json { "home_assistant_url": "https://your-website.com", "keep_browser_open": true } ``` -------------------------------- ### Docker Development Setup for Trmnl Home Assistant Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Use this script to run the application inside Docker, ensuring identical ImageMagick versions to production for consistent dithering output. It includes hot-reloading. ```bash cd trmnl-ha/ha-trmnl cp options-dev.json.example options-dev.json # Edit options-dev.json with your HA URL and token ./scripts/docker-dev.sh ``` -------------------------------- ### Legacy Base64 Mode Request Example Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md Example of a POST request to the /api/screens endpoint using Legacy Base64 mode. This mode embeds the image data directly within the JSON payload. ```http POST /api/screens Content-Type: application/json Authorization: { "screen": { "data": "", "label": "Home Assistant", "name": "ha-dashboard", "model_id": "1", "file_name": "ha-dashboard.png", "preprocessed": true } } ``` -------------------------------- ### HA Mode URL Format Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Example URL format for fetching Home Assistant dashboard screenshots. ```url http://:10000/?viewport=800x480&dithering&dither_method=floyd-steinberg&palette=gray-4 ``` -------------------------------- ### Cron Job for Dashboard Screenshots (Linux/macOS) Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md A cron job example to save a dashboard screenshot every 15 minutes. ```bash # Save a screenshot every 15 minutes */15 * * * * curl -s "http://192.168.1.x:10000/lovelace/0?viewport=800x480&dithering" -o /tmp/dashboard.png ``` -------------------------------- ### Docker Run Command for TRMNL HA Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Quick setup for TRMNL HA using a single docker run command. This is an alternative to using docker-compose. ```bash docker run -d --name trmnl-ha \ --restart unless-stopped \ -e HOME_ASSISTANT_URL=http://192.168.1.x:8123 \ -e ACCESS_TOKEN=your_long_lived_access_token \ -e TZ=America/New_York \ -p 10000:10000 \ -v ./trmnl-data:/data \ ghcr.io/usetrmnl/trmnl-ha-amd64:latest ``` -------------------------------- ### Home Assistant Automation for Screenshot Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/docs/HA_ADDON_IMPROVEMENTS.md Example YAML automation for Home Assistant to trigger a TRMNL screenshot on demand. This demonstrates calling a custom service with specific data parameters. ```yaml automation: - alias: "Send energy dashboard at sunset" trigger: - platform: sun event: sunset action: - service: trmnl_ha.capture_screenshot data: path: /lovelace/energy viewport: "800x480" webhook_url: "https://usetrmnl.com/api/custom_plugins/..." ``` -------------------------------- ### TRMNL Health Response Example Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md This is an example of the JSON response received from the TRMNL health endpoint. It includes status, uptime, and browser health details. ```json { "status": "ok", "uptime": 3600, "browser": { "healthy": true, "consecutiveFailures": 0, "totalRecoveries": 0 } } ``` -------------------------------- ### Install TRMNL HA via Docker Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/README.md Run the TRMNL HA add-on using Docker. Ensure to replace placeholder values for Home Assistant URL and access token. The command also maps the necessary port and volume. ```bash 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 ``` -------------------------------- ### Browser Health Recovery Stages Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Outlines the multi-stage recovery process for the browser component, starting with a process restart and escalating to a container restart if necessary. ```text 1. **Stage 1:** Restart browser process 2. **Stage 2:** Full container restart if Stage 1 fails repeatedly ``` -------------------------------- ### Integrate Event Publishing in Schedule Executor Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/docs/HA_ADDON_IMPROVEMENTS.md Examples of integrating the `fireEvent` function within `schedule-executor.ts` to publish events after screenshot capture and webhook delivery. ```typescript import { fireEvent } from '../ha-events.js'; // After successful screenshot await fireEvent('trmnl_screenshot_captured', { schedule_name: schedule.name, schedule_id: schedule.id, path: savedPath, timestamp: new Date().toISOString(), }); // After webhook success await fireEvent('trmnl_webhook_sent', { schedule_name: schedule.name, webhook_url: schedule.webhookUrl, status: response.status, timestamp: new Date().toISOString(), }); ``` -------------------------------- ### Dockerfile Multi-stage Build Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/docs/HA_ADDON_IMPROVEMENTS.md Illustrates a multi-stage Dockerfile pattern for building an add-on, separating build dependencies from the runtime environment to optimize image size and include necessary components like Chromium. ```dockerfile # Multi-stage build pattern - Stage 1: Builder with Bun and dependencies - Stage 2: Runtime with Chromium and fonts - Health check with proper intervals - BuildKit cache optimization ``` -------------------------------- ### Mock Home Assistant Frontend Initialization Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/tests/mocks/pages/lovelace-0.html Initializes mock behavior for the Home Assistant frontend, including simulating WebSocket messages, language setting, and theme changes. This script is intended for testing or development purposes. ```javascript (function() { const haEl = document.querySelector('home-assistant'); if (!haEl) { console.error('\\[Mock\\] home-assistant element not found'); return; } // Mock hass.connection for theme persistence interception (HA 2026.2+) haEl.hass = { connection: { sendMessage: function(msg) { console.log(`\\[Mock\\] WS sendMessage: ${JSON.stringify(msg)}`); }, sendMessagePromise: function(msg) { console.log(`\\[Mock\\] WS sendMessagePromise: ${JSON.stringify(msg)}`); return Promise.resolve(null); } } }; haEl._selectLanguage = function(lang, saveToStorage = true) { const language = lang || 'en'; document.documentElement.lang = language; console.log(`\\[Mock\\] Language set to: ${language}`); }; haEl.addEventListener('settheme', function(e) { const { theme, dark } = e.detail || {}; document.body.classList.toggle('dark-mode', dark === true); if (theme) { document.body.setAttribute('data-theme', theme); } console.log(`\\[Mock\\] Theme set: ${theme || 'default'}, dark mode: ${dark ? 'on' : 'off'}`); }); const panelResolver = haEl.shadowRoot ?.querySelector('home-assistant-main') ?.shadowRoot ?.querySelector('partial-panel-resolver'); if (panelResolver) { panelResolver._loading = false; console.log('\\[Mock\\] Panel resolver marked as loaded'); } console.log('\\[Mock\\] Dashboard 0 initialized'); })(); ``` -------------------------------- ### Build and Run Production Image Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md These commands are used to build the production Docker image and then run it. This is suitable for testing the application in a production-like environment. ```bash ./scripts/docker-build.sh && ./scripts/docker-run.sh ``` -------------------------------- ### Mock Home Assistant Element Initialization Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/tests/mocks/pages/lovelace-1.html Initializes a mock 'home-assistant' element, simulating WebSocket connection messages, language setting, theme changes, and panel loading for testing. ```javascript (function() { const haEl = document.querySelector('home-assistant'); if (!haEl) { console.error('\\[Mock\\] home-assistant element not found'); return; } // Mock hass.connection for theme persistence interception (HA 2026.2+) haEl.hass = { connection: { sendMessage: function(msg) { console.log(`\\[Mock\\] WS sendMessage: ${JSON.stringify(msg)}`); }, sendMessagePromise: function(msg) { console.log(`\\[Mock\\] WS sendMessagePromise: ${JSON.stringify(msg)}`); return Promise.resolve(null); } } }; haEl._selectLanguage = function(lang, saveToStorage = true) { const language = lang || 'en'; document.documentElement.lang = language; console.log(`\\[Mock\\] Language set to: ${language}`); }; haEl.addEventListener('settheme', function(e) { const { theme, dark } = e.detail || {}; document.body.classList.toggle('dark-mode', dark === true); if (theme) { document.body.setAttribute('data-theme', theme); } console.log(`\\[Mock\\] Theme set: ${theme || 'default'}, dark mode: ${dark ? 'on' : 'off'}`); }); const panelResolver = haEl.shadowRoot ?.querySelector('home-assistant-main') ?.shadowRoot ?.querySelector('partial-panel-resolver'); if (panelResolver) { panelResolver._loading = false; console.log('\\[Mock\\] Panel resolver marked as loaded'); } console.log('\\[Mock\\] Dashboard 1 initialized'); })(); ``` -------------------------------- ### Docker Development Workflow Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Builds and runs the add-on within a Docker container, recommended for development. Also includes commands to build or run the container separately. ```bash ./scripts/docker-dev.sh ./scripts/docker-build.sh ./scripts/docker-run.sh ``` -------------------------------- ### config.yaml Add-on Configuration Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/docs/HA_ADDON_IMPROVEMENTS.md This snippet highlights key configuration parameters for a Home Assistant add-on, including name, version, ingress integration, watchdog monitoring, and backup exclusions. ```yaml # Current implementation highlights: - name, description, version, slug, url - Multi-arch support (aarch64, amd64) - Ingress integration with sidebar panel - Watchdog health monitoring - Options with schema validation - Backup exclusions for regeneratable data ``` -------------------------------- ### Run All Tests Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Executes all unit and integration tests for the project. Use MOCK_HA=true for integration tests without a real HA instance. ```bash bun test bun test tests/unit bun test tests/integration bun test --coverage bun test --watch ``` -------------------------------- ### Run Tests and Linting Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Execute all unit tests, run tests with coverage reporting, or perform an ESLint linting check using these Bun commands. ```bash bun test # All tests bun test --coverage # With coverage bun run lint # ESLint ``` -------------------------------- ### CI/CD Pipeline Overview Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/docs/HA_ADDON_IMPROVEMENTS.md Overview of the CI/CD pipeline stages for an add-on, including linting, testing, multi-arch builds, and release processes for GitHub Container Registry. ```yaml ci.yml → Lint + Test + Build (multi-arch) release.yml → Build & Push to GHCR cache-warm.yml → Daily cache refresh cache-cleanup.yml → PR cache cleanup ``` -------------------------------- ### Run Trmnl Home Assistant with Mock Server Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Launch the Trmnl Home Assistant application in mock mode by setting the MOCK_HA environment variable. This connects the app to the mock HA server. ```bash MOCK_HA=true bun run dev ``` -------------------------------- ### Mock Home Assistant API Initialization Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/tests/mocks/pages/base.html Initializes a mock Home Assistant element and its associated 'hass' object, including simulated WebSocket connection methods. This mock is used to intercept and log messages sent by the client. ```javascript const haEl = document.querySelector('home-assistant'); if (!haEl) { console.error('[Mock] home-assistant element not found'); return; } haEl.hass = { connection: { sendMessage: function(msg) { console.log(`[Mock] WS sendMessage: ${JSON.stringify(msg)}`); }, sendMessagePromise: function(msg) { console.log(`[Mock] WS sendMessagePromise: ${JSON.stringify(msg)}`); return Promise.resolve(null); } } }; haEl._selectLanguage = function(lang, saveToStorage = true) { const language = lang || 'en'; document.documentElement.lang = language; console.log(`[Mock] Language set to: ${language}`); }; haEl.addEventListener('settheme', function(e) { const { theme, dark } = e.detail || {}; document.body.classList.toggle('dark-mode', dark === true); if (theme) { document.body.setAttribute('data-theme', theme); } console.log(`[Mock] Theme set: ${theme || 'default'}, dark mode: ${dark ? 'on' : 'off'}`); }); const panelResolver = haEl.shadowRoot ?.querySelector('home-assistant-main') ?.shadowRoot ?.querySelector('partial-panel-resolver'); if (panelResolver) { panelResolver._loading = false; console.log('[Mock] Panel resolver marked as loaded'); } console.log('[Mock] Home Assistant client-side API initialized'); ``` -------------------------------- ### Automated Release Commands Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/scripts/README.md Use npm scripts for automated version bumping (patch, minor, major) and dry runs. Alternatively, execute the release script directly with bun. ```bash # Using npm scripts (recommended) cd trmnl-ha/ha-trmnl npm run release:patch # 0.0.1 -> 0.0.2 npm run release:minor # 0.0.1 -> 0.1.0 npm run release:major # 0.0.1 -> 1.0.0 npm run release:dry # See what would change ``` ```bash # Direct script usage bun scripts/release.js patch bun scripts/release.js minor --dry-run bun scripts/release.js major --push ``` -------------------------------- ### Build Configuration for HA Add-on Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/docs/HA_ADDON_IMPROVEMENTS.md Defines build settings for the Home Assistant add-on, specifying base images per architecture, build arguments, and OCI labels. ```yaml build_from: aarch64: debian:bookworm-slim amd64: debian:bookworm-slim args: PUPPETEER_SKIP_DOWNLOAD: "true" labels: org.opencontainers.image.title: "TRMNL HA" org.opencontainers.image.description: "Send Home Assistant dashboards to TRMNL e-ink displays" org.opencontainers.image.source: "https://github.com/usetrmnl/trmnl-home-assistant" org.opencontainers.image.licenses: "Apache-2.0" org.opencontainers.image.vendor: "TRMNL" ``` -------------------------------- ### Documentation for Mounted Volumes in HA Add-on Config Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/docs/HA_ADDON_IMPROVEMENTS.md Documents the purpose and contents of mounted volumes within the Home Assistant add-on's configuration file. ```yaml # ============================================================================= # MOUNTED VOLUMES (Documentation) # ============================================================================= # /data - Add-on persistent storage # - options.json: User configuration (mounted by Supervisor) # - schedules.json: Saved screenshot schedules # - logs/: Application logs # - output/: Generated screenshots # /tmp - Temporary files for browser and image processing # ============================================================================= ``` -------------------------------- ### Run Single Test File Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Executes tests from a specific file, useful for focused debugging. ```bash bun test tests/unit/dithering.test.ts ``` -------------------------------- ### TypeScript Logging Usage Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Demonstrates how to import and use different loggers for various application modules. Ensure the logger modules are correctly imported from './lib/logger.js'. ```typescript import { appLogger, browserLogger, schedulerLogger } from './lib/logger.js' const log = appLogger() log.info`Server started at ${url}` log.debug`Processing ${count} items` log.error`Failed: ${error.message}` ``` -------------------------------- ### Cron Syntax Explanation Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Explains the structure of cron expressions used for scheduling. Each field represents a time unit from minute to day of the week. ```cron ┌─ minute (0-59) │ ┌─ hour (0-23) │ │ ┌─ day of month (1-31) │ │ │ ┌─ month (1-12) │ │ │ │ ┌─ day of week (0-6, Sun=0) * * * * * ``` -------------------------------- ### Generic Website Screenshot with Dithering Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Curl request to capture a screenshot of any website in generic mode with dithering enabled. Uses the 'url' parameter to specify the target website. ```bash curl "http://localhost:10000/?url=https://grafana.local/dashboard&viewport=800x480&dithering" ``` -------------------------------- ### English Translations for HA Add-on Configuration Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/docs/HA_ADDON_IMPROVEMENTS.md Provides English translations for Home Assistant add-on configuration options, including names and descriptions for various settings. ```yaml configuration: access_token: name: Access Token description: >- Home Assistant long-lived access token. Create one at your Profile page under "Long-Lived Access Tokens". home_assistant_url: name: Home Assistant URL description: >- Override the default Home Assistant URL (http://homeassistant:8123). Only change this if you have a custom setup or SSL requirements. keep_browser_open: name: Keep Browser Open description: >- Keep the browser instance alive between screenshot requests. Enables faster captures but uses more memory. Recommended for frequent scheduled screenshots. network: 10000/tcp: Web interface (use Ingress instead for security) ``` -------------------------------- ### Generic Mode Endpoint Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Fetches a screenshot of any given URL. This mode is useful for capturing external websites or resources. ```APIDOC ## GET /?url=&viewport=... ### Description Fetches a screenshot of any specified URL. This generic endpoint allows capturing content from any web address, overriding the default dashboard path. ### Method GET ### Endpoint `GET /?url=&viewport=` ### Parameters #### Query Parameters - **url** (string) - Optional - Full URL to capture (overrides dashboard path, enables generic mode) - **viewport** (string) - Required - Viewport dimensions (e.g., `800x480`) - **dithering** (boolean) - Optional - Enable e-ink dithering - **dither_method** (string) - Optional - Dithering algorithm (`floyd-steinberg`, `ordered`, `none`, default: `floyd-steinberg`) - **palette** (string) - Optional - Color palette (`bw`, `gray-4`, `gray-16`, `gray-256`) - **compression_level** (integer) - Optional - PNG compression level (`1-9`, default: `9`) - **levels_enabled** (boolean) - Optional - Enable black/white level adjustments - **black_level** (integer) - Optional - Black point (`0-100`, requires `levels_enabled`) - **white_level** (integer) - Optional - White point (`0-100`, requires `levels_enabled`) - **format** (string) - Optional - Output format (`png`, `jpeg`, `bmp`, default: `png`) - **rotate** (integer) - Optional - Rotation degrees (`90`, `180`, `270`) - **wait** (integer) - Optional - Wait after page load in milliseconds (default: `750`) - **zoom** (number) - Optional - Page zoom (default: `1.0`) - **invert** (boolean) - Optional - Invert colors ### Request Example ```bash curl "http://localhost:10000/?url=https://grafana.local/dashboard&viewport=800x480&dithering" ``` ### Response #### Success Response (200) - **image** (binary) - The generated image in the specified format. ``` -------------------------------- ### Request Flow Diagram Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Illustrates the sequence of operations from an HTTP request to the final image response, including screenshot capture and image processing. ```text HTTP Request → HttpRouter → RequestHandler → Browser (Puppeteer) ↓ screenshotPage() ↓ processImage() (dithering via ImageMagick) ↓ HTTP Response (PNG/JPEG/BMP) ``` -------------------------------- ### VS Code Devcontainer Configuration Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/docs/HA_ADDON_IMPROVEMENTS.md JSON configuration file for setting up a standardized VS Code development environment using devcontainers. Includes build instructions, post-creation commands, and recommended VS Code extensions and settings. ```json { "name": "TRMNL HA Development", "build": { "dockerfile": "Dockerfile" }, "postCreateCommand": "cd trmnl-ha/ha-trmnl && bun install", "customizations": { "vscode": { "extensions": [ "oven.bun-vscode", "esbenp.prettier-vscode", "dbaeumer.vscode-eslint" ], "settings": { "editor.formatOnSave": true } } }, "forwardPorts": [10000, 8123], "remoteUser": "vscode" } ``` -------------------------------- ### TRMNL HA Add-on Full Configuration Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/ha-trmnl/docs/HA_ADDON_IMPROVEMENTS.md This is the complete reference configuration for the TRMNL HA add-on. It includes all recommended options for metadata, Home Assistant integration, container settings, health monitoring, ingress, network ports, user options, and backup exclusions. Ensure all fields are correctly set according to your Home Assistant environment and desired add-on behavior. ```yaml # ============================================================================= # ADD-ON METADATA # ============================================================================= name: "TRMNL HA" description: "Send dashboard screens to your TRMNL e-ink display" version: "0.2.1" slug: "trmnl-ha" url: "https://github.com/usetrmnl/trmnl-home-assistant" # Container image (supports {arch} placeholder) image: ghcr.io/usetrmnl/trmnl-ha-{arch} # ============================================================================= # HOME ASSISTANT INTEGRATION # ============================================================================= # Enable HA API proxy (http://supervisor/core/api) homeassistant_api: true # ============================================================================= # CONTAINER CONFIGURATION # ============================================================================= # Disable S6 overlay init (we use our own entrypoint) init: false # Supported architectures arch: - aarch64 - amd64 # Add-on stability stage stage: stable # ============================================================================= # HEALTH MONITORING # ============================================================================= watchdog: "http://[HOST]:10000/health" # ============================================================================= # INGRESS (RECOMMENDED ACCESS METHOD) # ============================================================================= ingress: true ingress_port: 10000 ingress_stream: false # Sidebar integration panel_icon: "mdi:monitor" panel_title: "TRMNL HA" # ============================================================================= # NETWORK PORTS (OPTIONAL DIRECT ACCESS) # ============================================================================= ports: 10000/tcp: null # Disabled by default (use ingress) ports_description: 10000/tcp: "Web UI (use Ingress for security)" # ============================================================================= # USER CONFIGURATION # ============================================================================= options: access_token: "" home_assistant_url: "http://homeassistant:8123" keep_browser_open: false schema: access_token: str home_assistant_url: str? keep_browser_open: bool? # ============================================================================= # BACKUP CONFIGURATION # ============================================================================= # Exclude regeneratable data from HA backups backup_exclude: - "*/logs/*" - "*/output/*" # ============================================================================= # MOUNTED VOLUMES (Documentation) # ============================================================================= # /data - Add-on persistent storage # - options.json: User configuration # - schedules.json: Saved screenshot schedules # /tmp - Temporary browser/processing files # ============================================================================= ``` -------------------------------- ### Verify Add-on URL Reachability Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md Shell into the Terminus container to verify if it can reach the add-on's screenshot endpoint. This is a crucial step for debugging connectivity issues in URI mode. ```sh docker compose -p terminus-development exec web \ curl -sI http://host.docker.internal:10000/health # Expected: HTTP/1.1 200 OK ``` -------------------------------- ### POST /api/screens (Legacy Base64 Mode) Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md Sends screen data to the /api/screens endpoint using Legacy Base64 mode. This mode embeds the image directly in the JSON body. Keep this selected only if your Terminus is ≤ 0.51.0. ```APIDOC ## POST /api/screens (Legacy Base64 Mode) ### Description Sends screen data to the /api/screens endpoint using Legacy Base64 mode. This mode embeds the image directly in the JSON body. Keep this selected only if your Terminus is ≤ 0.51.0. ### Method POST ### Endpoint /api/screens ### Request Body - **screen** (object) - Required - Contains screen details. - **data** (string) - Required - Base64-encoded image data. - **label** (string) - Required - Display name shown in BYOS UI. - **name** (string) - Required - Unique screen identifier (slug format). - **model_id** (string) - Required - BYOS device model ID. - **file_name** (string) - Required - The name of the file. - **preprocessed** (boolean) - Required - Whether the image is already optimized for e-ink (always `true` from the add-on). ### Request Example ```json { "screen": { "data": "", "label": "Home Assistant", "name": "ha-dashboard", "model_id": "1", "file_name": "ha-dashboard.png", "preprocessed": true } } ``` ### Response (Success and error responses are not explicitly detailed in the source, but the endpoint is expected to process the request.) ``` -------------------------------- ### POST /api/screens (URI Mode) Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md Sends screen data to the /api/screens endpoint using URI mode. This mode references a screenshot endpoint on the add-on itself, allowing Terminus to download the dithered image. ```APIDOC ## POST /api/screens (URI Mode) ### Description Sends screen data to the /api/screens endpoint using URI mode. This mode references a screenshot endpoint on the add-on itself, allowing Terminus to download the dithered image. ### Method POST ### Endpoint /api/screens ### Request Body - **screen** (object) - Required - Contains screen details. - **uri** (string) - Required - The URI of the screenshot endpoint on the add-on. - **label** (string) - Required - Display name shown in BYOS UI. - **name** (string) - Required - Unique screen identifier (slug format). - **model_id** (string) - Required - BYOS device model ID. - **preprocessed** (boolean) - Required - Whether the image is already optimized for e-ink (always `true` from the add-on). ### Request Example ```json { "screen": { "uri": "http://192.168.1.100:10000/lovelace/0?viewport=800x480&dithering=&dither_method=floyd-steinberg&palette=gray-4", "label": "Home Assistant", "name": "ha-dashboard", "model_id": "1", "preprocessed": true } } ``` ### Response (Success and error responses are not explicitly detailed in the source, but the endpoint is expected to process the request.) ``` -------------------------------- ### Webhook Architecture Flow Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md Illustrates the execution flow for schedule-based webhook calls, including image transformation and uploading. This flow is relevant for understanding how data is processed and sent to webhooks. ```mermaid graph TD Schedule_Execution --> ScheduleExecutor_call ScheduleExecutor_call --> buildScreenshotUrl buildScreenshotUrl --> uploadToWebhook uploadToWebhook --> getTransformer getTransformer --> transformer_transform transformer_transform --> fetch ``` -------------------------------- ### HA Dashboard E-Ink Optimized Request Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Curl request for a Home Assistant dashboard optimized for e-ink displays using dithering. Requires the 'dithering' parameter and a specified dither method. ```bash curl "http://localhost:10000/lovelace/0?viewport=800x480&dithering&dither_method=floyd-steinberg" ``` -------------------------------- ### Create a Custom Format Transformer Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md Implement the `FormatTransformer` interface to handle the transformation of image buffers into the desired webhook payload format. This includes defining the `transform` method. ```typescript import type { FormatTransformer, WebhookPayload } from './webhook-formats.js' import type { ImageFormat } from '../../types/domain.js' export class YourFormatTransformer implements FormatTransformer { transform( imageBuffer: Buffer, format: ImageFormat, config?: YourFormatConfig, screenshotUrl?: string, ): WebhookPayload { // Transform the image buffer into your payload format. // `screenshotUrl` is only set for URI-mode formats (see BYOS Hanami). // Formats that inline the image can ignore it. return { body: JSON.stringify({ image: imageBuffer.toString('base64'), // ... your format's structure }), contentType: 'application/json', } } } ``` -------------------------------- ### Add UI Controls for Custom Format Configuration Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md If your custom format requires user-configurable settings, add corresponding form fields to the UI renderer in `html/js/ui-renderer.ts`. This allows users to input configuration values through the interface. ```typescript // In #renderWebhookFormatSection() if (format === 'your-format') { html += `
` } ``` -------------------------------- ### Manual Git Push Commands Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/scripts/README.md Commands to manually push commits and tags to the remote repository if the automated push option was not used. ```bash git push && git push --tags ``` -------------------------------- ### HA Mode Endpoint Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Fetches a screenshot of a Home Assistant dashboard. This mode supports theming, language, and dark mode. ```APIDOC ## GET /?viewport=... ### Description Fetches a screenshot of a specific Home Assistant dashboard path. This endpoint is designed for use within the Home Assistant environment and supports various customization options. ### Method GET ### Endpoint `GET /?viewport=` ### Parameters #### Query Parameters - **viewport** (string) - Required - Viewport dimensions (e.g., `800x480`) - **theme** (string) - Optional - HA theme name - **lang** (string) - Optional - UI language code - **dark** (boolean) - Optional - Enable dark mode - **dithering** (boolean) - Optional - Enable e-ink dithering - **dither_method** (string) - Optional - Dithering algorithm (`floyd-steinberg`, `ordered`, `none`, default: `floyd-steinberg`) - **palette** (string) - Optional - Color palette (`bw`, `gray-4`, `gray-16`, `gray-256`) - **compression_level** (integer) - Optional - PNG compression level (`1-9`, default: `9`) - **levels_enabled** (boolean) - Optional - Enable black/white level adjustments - **black_level** (integer) - Optional - Black point (`0-100`, requires `levels_enabled`) - **white_level** (integer) - Optional - White point (`0-100`, requires `levels_enabled`) - **format** (string) - Optional - Output format (`png`, `jpeg`, `bmp`, default: `png`) - **rotate** (integer) - Optional - Rotation degrees (`90`, `180`, `270`) - **wait** (integer) - Optional - Wait after page load in milliseconds (default: `750`) - **zoom** (number) - Optional - Page zoom (default: `1.0`) - **invert** (boolean) - Optional - Invert colors ### Request Example ```bash curl "http://localhost:10000/lovelace/0?viewport=800x480" ``` ### Response #### Success Response (200) - **image** (binary) - The generated image in the specified format. ``` -------------------------------- ### Write Unit Tests for Custom Transformer Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md Create unit tests in `tests/unit/webhook-formats.test.ts` to verify that your custom transformer correctly transforms image data into the expected payload structure. Ensure content type and payload details are validated. ```typescript describe('YourFormatTransformer', () => { it('transforms image to your format', () => { const transformer = new YourFormatTransformer() const result = transformer.transform(testBuffer, 'png', { apiKey: 'test' }) expect(result.contentType).toBe('application/json') // ... verify payload structure }) }) ``` -------------------------------- ### Docker Compose for TRMNL HA Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Integrate TRMNL HA as a service in your existing docker-compose.yml. Ensure to use your host's IP address for HOME_ASSISTANT_URL when HA uses network_mode: host. ```yaml services: # Your existing HA service (typically uses network_mode: host) 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 # Add TRMNL HA alongside your other services trmnl-ha: image: ghcr.io/usetrmnl/trmnl-ha-amd64:latest # ARM64 (Pi 4/5, Apple Silicon): ghcr.io/usetrmnl/trmnl-ha-aarch64:latest container_name: trmnl-ha restart: unless-stopped ports: - "10000:10000" environment: # Use your host's IP since HA uses network_mode: host (see note below) - 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: ``` -------------------------------- ### Define New Webhook Format Type Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md Add your custom format to the `WebhookFormat` union type in `types/domain.ts`. Define a configuration interface if your format requires specific settings. ```typescript // Add to WebhookFormat union type export type WebhookFormat = 'raw' | 'byos-hanami' | 'your-format' // Add config interface if needed export interface YourFormatConfig { apiKey: string // ... other fields } ``` -------------------------------- ### ESPHome e-ink Display Integration Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Configuration for an ESPHome e-ink display to fetch and show a TRMNL HA screenshot. ```yaml display: - platform: waveshare_epaper # ... lambda: |- # Fetch image from TRMNL HA it.image(0, 0, id(ha_screenshot)); http_request: - url: "http://192.168.1.x:10000/lovelace/0?viewport=800x480&dithering&palette=gray-4" method: GET ``` -------------------------------- ### HA Dashboard Themed and Dark Mode Request Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Curl request for a Home Assistant dashboard with a specific theme, dark mode enabled, and rotated output. Supports 'theme', 'dark', and 'rotate' parameters. ```bash curl "http://localhost:10000/lovelace/energy?viewport=480x800&theme=Graphite&dark&rotate=90" ``` -------------------------------- ### Dithering Strategy Interface Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/CLAUDE.md Defines the `DitheringStrategy` interface implemented by different dithering algorithms. ```typescript lib/dithering/ ├── floyd-steinberg-strategy.ts # Error diffusion (best quality) ├── ordered-strategy.ts # Pattern-based (fastest) └── threshold-strategy.ts # Simple binary (smallest files) ``` -------------------------------- ### Raw Image Upload Webhook Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/docs/webhook-formats.md Use this format for direct binary image uploads to TRMNL devices or custom webhook endpoints. It requires the appropriate Content-Type header. ```http POST /your-webhook-endpoint Content-Type: image/png Authorization: Bearer ``` -------------------------------- ### Development Scripts for TRMNL HA Source: https://github.com/usetrmnl/trmnl-home-assistant/blob/main/trmnl-ha/DOCS.md Scripts to run TRMNL HA in development mode with hot-reloading or build and run for production. ```bash # Development (hot-reload) ./ha-trmnl/scripts/docker-dev.sh # Production (background) ./ha-trmnl/scripts/docker-build.sh && ./ha-trmnl/scripts/docker-run.sh ```