Home Assistant Automated Puppet
A specialized skill for working with the Automated Puppet add-on repository — a Puppeteer-based scheduled screenshot service that automatically captures Home Assistant dashboards and saves them to disk, optimized for e-ink displays.
What This Skill Does
This skill helps you understand, develop, and debug the Automated Puppet add-on. It provides context about the scheduler-based architecture, browser lifecycle management, e-ink optimization techniques, and Home Assistant integration patterns.
Key Architecture Components
Core Modules
When working with this codebase, understand these key files:
**scheduler.js**: Main entry point managing scheduled jobs from JSON config**screenshot.js**: Puppeteer wrapper handling Chromium lifecycle and screenshot capture**file-manager.js**: Saves screenshots to `/config/www/screenshots/` with organized folders**bmp.js**: Custom BMP encoder supporting 1-bit and 24-bit for e-ink compatibility**const.js**: Options loader for dev (`options-dev.json`) vs production (`/data/options.json`)**error.js**: Custom error types for page loading failuresCritical Patterns
**Busy Flag Pattern** — Prevents concurrent browser operations:
```javascript
if (this.busy) throw new Error("Browser is busy");
this.busy = true;
try { /* work */ } finally { this.busy = false; }
```
**Environment Detection** — Adjusts behavior between dev and production:
```javascript
const isAddOn = optionsFile === "/data/options.json";
```
**Browser Lifecycle** — Single browser instance shared across all jobs, stays alive for scheduler lifetime (no automatic cleanup)
Development Setup Instructions
Local Development
1. Copy configuration templates:
```bash
cp puppet/ha-puppet/options-dev.json.sample puppet/ha-puppet/options-dev.json
cp puppet/ha-puppet/screenshots-example.json puppet/ha-puppet/screenshots-dev.json
```
2. Configure `options-dev.json` with:
- Home Assistant URL
- Long-lived access token
- `chromium_executable` path (defaults to Google Chrome on macOS)
3. Configure desired screenshots in `screenshots-dev.json`
4. Install dependencies and run:
```bash
cd puppet/ha-puppet && npm ci
node puppet/ha-puppet/scheduler.js
```
5. Screenshots saved to `puppet/ha-puppet/output/`
Docker Build & Run
From repository root:
```bash
docker build -t puppet -f puppet/Dockerfile .
docker run \
-v /path/to/options.json:/data/options.json \
-v /path/to/screenshots.json:/data/screenshots.json \
-v /path/to/www:/config/www \
puppet
```
Screenshot Configuration Schema
Create `screenshots-dev.json` or `/config/screenshots.json` with:
**Required Fields**:
`name`: Unique identifier for folder/file organization`path`: Home Assistant path (e.g., `/lovelace/0`)`viewport`: Object with `width` and `height``interval`: Refresh interval in seconds**Optional Fields**:
`format`: Output format (PNG, BMP, etc.)`eink`: Enable e-ink optimization (BMP/PNG only)`invert`: Invert colors for e-ink`zoom`: Zoom level`rotate`: Rotation angle`lang`: Language override`theme`: Theme name`dark`: Dark mode boolean`wait`: Extra wait time in msSee `screenshots-example.json` for complete examples.
E-ink Optimization Details
When debugging e-ink output issues:
**2-color mode**: Threshold at 220, optional invert, outputs as b-w colorspace**Supported bit depths**: 1-bit, 2-bit, 4-bit, 8-bit BMP encoding**Format restrictions**: Only BMP and PNG when `eink` parameter enabled**Pipeline**: Puppeteer PNG → Sharp processing (rotate, color reduction) → Custom BMP encoding → Header crop (56px)Home Assistant Integration
Authentication
Uses long-lived access token via `localStorage.hassTokens`Injected via `evaluateOnNewDocument` before navigationDOM Waiting Strategy
Waits for element chain:
```
home-assistant → home-assistant-main → partial-panel-resolver → panel
```
Then monitors `_loading` property on panel elements for readiness
File Access
Screenshots accessible at:
```
/local/screenshots/<name>/latest.<format>
```
Performance Considerations
**Home Assistant Green**: ~10s cold start, ~0.6s same-page, ~1.5s different page**Cold start wait**: 2.5s extra; warm start 750ms (add-on) or 500ms (dev)**Optimizations**: `--enable-low-end-device-mode` on add-on, shared browser instance**Navigation**: Uses `location-changed` event instead of full reloadTroubleshooting Guidance
Browser Won't Start
Check Chromium installation in containerVerify Puppeteer args in `screenshot.js:16-52`Enable watchdog in Home Assistant supervisorScreenshots Fail to Save
Verify `/config/www/screenshots/` exists and is writableCheck FileManager path construction in `file-manager.js`Confirm `screenshots.json` has valid configE-ink Output Issues
Ensure format is BMP or PNGCheck threshold value (220) in Sharp processingVerify custom BMP encoder in `bmp.js`Authentication Failures
Validate long-lived access token in `options.json`Check `home_assistant_url` override if using SSL/custom portsInspect browser console for token injection errorsDependencies
**puppeteer** (^24.26.1): Chromium automation**sharp** (^0.34.4): Image processing**Node.js 23.x**: Runtime**Chromium**: Browser engine**fonts-noto-cjk**: CJK font supportArchitecture History
**v2.0.0 Changes** (scheduler-based architecture):
**Removed**: HTTP server, RequestHandler class, port 10000**Added**: Scheduler, FileManager, screenshot configuration system**Changed**: Browser lifecycle (no cleanup), file-based output**Migration**: Users must create `/config/screenshots.json` and use `/local/screenshots/` URLsConstraints
Browser instance never automatically cleaned up (lives for scheduler lifetime)All jobs share single Browser to minimize resourcesFormat restrictions when `eink` enabled (BMP/PNG only)Header always cropped at 56px (HEADER_HEIGHT constant)Each screenshot gets dedicated folder with `latest.<format>` naming