This file provides context for AI coding agents working on this project.
A Homey smart home app (SDK v3) that integrates Amazon Echo/Alexa devices. Users can control Echo speakers and displays, send TTS messages, trigger routines, and automate playback through Homey flows. The app communicates with Amazon's Alexa API via the alexa-remote2 library and maintains a persistent WebSocket connection for real-time state updates.
- Language: TypeScript 5.9+ targeting Node.js 22
- Platform: Homey SDK v3 (
homeypackage, app runs locally on Homey Pro hub) - Core dependency:
alexa-remote2(callback-based Amazon Alexa API client) - Build:
tsccompiles to.homeybuild/directory - Linting: ESLint with
eslint-config-athom(Homey's standard config) - Formatting: Prettier
- No test framework is currently configured
| File | Purpose | LOC |
|---|---|---|
app.ts |
App lifecycle, reconnection logic, event routing between API and devices | ~195 |
api.ts (root) |
Thin HTTP endpoint wrappers exposing connect/disconnect/reset/status | ~17 |
lib/api.ts |
AlexaApi class - all Alexa communication, WebSocket listeners, device/sound/routine fetching, media control, TTS |
~614 |
lib/connection.ts |
ConnectionState enum, error categorization (categorizeError), DNS reachability check |
~108 |
lib/helpers.ts |
promisify, promisifyWithOptions, sleep utilities for callback-to-promise conversion |
~31 |
lib/logger.ts |
Logger class with Sentry integration, PII filtering, conditional diagnostic logging |
~47 |
drivers/echo/driver.ts |
Echo driver - registers 4 flow action cards (say, command, sound, routine), handles pairing | — |
drivers/echo/device.ts |
Echo device - dynamic capability management, album art, real-time state sync | — |
drivers/group/driver.ts |
Speaker group driver (same structure as echo, filters WHA family) | — |
drivers/group/device.ts |
Speaker group device (same as echo device) | — |
Source config lives in .homeycompose/ and per-driver compose files (driver.compose.json, driver.flow.compose.json, driver.settings.compose.json). The app.json in the root is generated - edit the compose sources instead.
Amazon Alexa API (WebSocket)
→ AlexaApi (lib/api.ts) emits 'device-info'
→ EchoRemoteApp (app.ts) routes to correct device via deviceEmit()
→ EchoDevice/GroupDevice updates capabilities
Group events propagate to member devices: when a group's state changes, deviceEmit() also emits to all child devices in that group.
States are defined in lib/connection.ts:
DISCONNECTED → CONNECTING → CONNECTED
CONNECTED → DISCONNECTING → DISCONNECTED
CONNECTED → RECONNECTING → CONNECTING → CONNECTED
CONNECTED → ERROR → RECONNECTING → ...
Auto-reconnect uses exponential backoff (30s → 1m → 2m → 4m → 8m → 15m cap, max 10 attempts). Auth failures (expired cookies) stop reconnection immediately since they require user re-authentication.
categorizeError() in lib/connection.ts classifies errors from alexa-remote2:
- auth (no retry): cookie expired, 401 unauthorized
- network (retry): DNS failure, connection reset, socket hang up
- transient (retry): timeout, empty response, HTTP2 session invalid
- unknown (no retry): unknown device, unrecognized errors
alexa-remote2 uses callback-style APIs. The helpers in lib/helpers.ts wrap these as promises. When adding new API calls, use promisify() or promisifyWithOptions().
node-cache with different TTLs per resource type:
- Devices: 5 minutes
- Sounds: 60 minutes
- Routines: 1 minute
Cache is cleared on disconnect/reset.
Uses alexa-remote2's proxy-based OAuth. The app starts a local proxy server on port 3081. The user opens the proxy URL in a browser to log in to Amazon. On success, cookie data is stored in Homey settings. Cookie refresh interval is set to 4 days.
Both echo and group drivers support these Homey capabilities:
speaker_playing- play/pausespeaker_next/speaker_prev- track navigationspeaker_shuffle- shuffle toggle (supports 'disabled' state)speaker_repeat- repeat modes: track, playlist, none, disabledspeaker_track/speaker_artist/speaker_album- media metadatavolume_set- volume (0-1 scale, converted to 0-100 for Alexa API)volume_set.notifications- notification volume (optional, dynamically added)
The app filters Alexa devices by deviceFamily:
ECHO,KNIGHT,ROOK→ individual Echo devices (echo driver)WHA(Whole Home Audio) → speaker groups (group driver)
40+ Echo models are mapped in DEVICES constant in lib/api.ts with name and generation number. Unknown models still work, they just don't get a specific icon.
16 regions defined in SERVERS constant in lib/api.ts. Some regions use non-standard Alexa hostnames (e.g., amazon.se and amazon.pl use layla.amazon.com).
- App UI translations in
locales/(en, de, fr, nl) - Flow card titles and capability labels translated in compose files
- Alexa API language passed via
LANG_MAPinlib/api.ts(12 languages)
- Add the Amazon page → Alexa server mapping to
SERVERSinlib/api.ts - Add a language mapping to
LANG_MAPif needed - Add the region option to the settings UI in
settings/index.html
Add an entry to the DEVICES constant in lib/api.ts with the device type ID, name, and generation. Optionally add an SVG icon to drivers/echo/assets/.
- Define the action in
drivers/echo/driver.flow.compose.json(and group equivalent if applicable) - Register the action handler in
drivers/echo/driver.tsonInit() - Implement the API method in
lib/api.tsif needed - Add translations to
locales/
- Add the capability to
drivers/echo/driver.compose.json - Register the capability listener in
drivers/echo/device.tsonInit() - Handle incoming state updates in the
device-infoevent handler - Add capability options translations if needed
npm install # Install dependencies
npm run build # Compile TypeScript → .homeybuild/
npm run lint # Run ESLint
homey app run # Deploy to Homey for development
homey app install # Install on Homey for production- Do not edit
app.jsondirectly - it is generated from.homeycompose/sources. Edit the compose files instead. - Do not edit files in
.homeybuild/- this is the compiled output directory. - The
alexa-remote2library uses callbacks with non-standard signatures (e.g.,checkAuthenticationhas reversed callback params). Always verify callback signatures when wrapping new methods. - Sentry logging (
homey-log) is currently disabled inapp.tsdue to rate limiting. ThehomeyLoggeris set toundefined. - Volume values use 0-1 scale in Homey but 0-100 in the Alexa API. Conversion happens in
lib/api.ts. - The proxy server on port 3081 is used for OAuth only. It must be cleaned up properly on reset (handled in
cleanup()). - PII filtering in
lib/api.ts(filterLogMessage) redacts customer name, email, ID, and address from log output.