homebridge-yoto 0.0.28 → 0.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -314
- package/config.schema.cjs +3 -0
- package/config.schema.json +19 -155
- package/homebridge-ui/public/client.js +428 -0
- package/homebridge-ui/public/index.html +138 -0
- package/homebridge-ui/server.js +264 -0
- package/index.js +1 -1
- package/lib/accessory.js +1870 -0
- package/lib/constants.js +8 -149
- package/lib/platform.js +303 -363
- package/lib/sanitize-name.js +49 -0
- package/lib/settings.js +16 -0
- package/lib/sync-service-names.js +34 -0
- package/package.json +28 -22
- package/.github/dependabot.yml +0 -18
- package/.github/funding.yml +0 -4
- package/.github/workflows/release.yml +0 -41
- package/.github/workflows/tests.yml +0 -37
- package/AGENTS.md +0 -253
- package/CHANGELOG.md +0 -8
- package/CONTRIBUTING.md +0 -34
- package/PLAN.md +0 -609
- package/declaration.tsconfig.json +0 -15
- package/eslint.config.js +0 -7
- package/index.test.js +0 -7
- package/lib/auth.js +0 -237
- package/lib/playerAccessory.js +0 -1724
- package/lib/types.js +0 -253
- package/lib/yotoApi.js +0 -270
- package/lib/yotoMqtt.js +0 -570
- package/tsconfig.json +0 -14
package/PLAN.md
DELETED
|
@@ -1,609 +0,0 @@
|
|
|
1
|
-
# Homebridge Yoto Plugin - Implementation Plan
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
A Homebridge plugin that integrates Yoto audio players with Apple HomeKit, providing comprehensive control over playback, volume, display settings, and status monitoring through MQTT.
|
|
6
|
-
|
|
7
|
-
## ✅ Current Status: Phase 1 Complete + Phase 2 Enhancements
|
|
8
|
-
|
|
9
|
-
**MVP Complete!** All Phase 1 features implemented and tested. Additional Phase 2 features added including display brightness control, sleep timer, and advanced control switches.
|
|
10
|
-
|
|
11
|
-
## Project Structure
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
homebridge-yoto/
|
|
15
|
-
├── lib/
|
|
16
|
-
│ ├── platform.js # Main YotoPlatform class
|
|
17
|
-
│ ├── playerAccessory.js # YotoPlayerAccessory handler
|
|
18
|
-
│ ├── yotoApi.js # Yoto REST API client wrapper
|
|
19
|
-
│ ├── yotoMqtt.js # MQTT client for real-time updates
|
|
20
|
-
│ ├── auth.js # OAuth2 authentication handler
|
|
21
|
-
│ ├── types.js # JSDoc type definitions
|
|
22
|
-
│ └── constants.js # Plugin constants and defaults
|
|
23
|
-
├── index.js # Plugin entry point
|
|
24
|
-
├── config.schema.json # Homebridge config UI schema
|
|
25
|
-
└── package.json
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Phase 1: Core Foundation (MVP) ✅ COMPLETE
|
|
29
|
-
|
|
30
|
-
### 1.1 Authentication System ✅
|
|
31
|
-
|
|
32
|
-
**Status:** COMPLETE
|
|
33
|
-
|
|
34
|
-
**Goal:** Implement OAuth2 Device Authorization Flow for Yoto API
|
|
35
|
-
|
|
36
|
-
**Files:**
|
|
37
|
-
- `lib/auth.js`
|
|
38
|
-
|
|
39
|
-
**Implementation:**
|
|
40
|
-
- Use `POST /oauth/device/code` to initiate device flow
|
|
41
|
-
- Display user_code and verification_uri in Homebridge logs
|
|
42
|
-
- Poll `POST /oauth/token` until user completes authorization
|
|
43
|
-
- Store access_token and refresh_token in platform config
|
|
44
|
-
- Implement automatic token refresh logic
|
|
45
|
-
- Handle token expiration gracefully
|
|
46
|
-
|
|
47
|
-
**API Endpoints:**
|
|
48
|
-
- `POST /oauth/device/code`
|
|
49
|
-
- `POST /oauth/token` (with grant_type: 'device_code' and 'refresh_token')
|
|
50
|
-
|
|
51
|
-
**Config Structure:**
|
|
52
|
-
```javascript
|
|
53
|
-
{
|
|
54
|
-
"platform": "Yoto",
|
|
55
|
-
"name": "Yoto",
|
|
56
|
-
"clientId": "YOUR_CLIENT_ID",
|
|
57
|
-
"accessToken": "(stored after auth)",
|
|
58
|
-
"refreshToken": "(stored after auth)",
|
|
59
|
-
"tokenExpiresAt": 0
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### 1.2 API Client ✅
|
|
64
|
-
|
|
65
|
-
**Status:** COMPLETE
|
|
66
|
-
|
|
67
|
-
**Goal:** Create robust API wrapper for Yoto endpoints
|
|
68
|
-
|
|
69
|
-
**Files:**
|
|
70
|
-
- `lib/yotoApi.js` (REST endpoints)
|
|
71
|
-
- `lib/yotoMqtt.js` (MQTT client)
|
|
72
|
-
|
|
73
|
-
**REST API Features:**
|
|
74
|
-
- Centralized fetch wrapper with auth headers
|
|
75
|
-
- Automatic token refresh on 401 responses
|
|
76
|
-
- Error handling and retry logic
|
|
77
|
-
- Rate limiting protection
|
|
78
|
-
- Request/response logging for debugging
|
|
79
|
-
|
|
80
|
-
**Key REST Methods:**
|
|
81
|
-
```javascript
|
|
82
|
-
class YotoApi {
|
|
83
|
-
async getDevices() // GET /device-v2/devices/mine
|
|
84
|
-
async getDeviceConfig(deviceId) // GET /device-v2/{deviceId}/config
|
|
85
|
-
async updateDeviceConfig(deviceId, config) // PUT /device-v2/{deviceId}/config
|
|
86
|
-
async getContent(cardId) // GET /content/{cardId}
|
|
87
|
-
async getLibraryGroups() // GET /card/family/library/groups
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
**MQTT Client Features:**
|
|
92
|
-
- Real-time device status updates via `/device/{id}/data/status`
|
|
93
|
-
- Real-time playback events via `/device/{id}/data/events`
|
|
94
|
-
- Command publishing to control devices
|
|
95
|
-
- Automatic reconnection on disconnect
|
|
96
|
-
- Per-device topic subscriptions
|
|
97
|
-
|
|
98
|
-
**Key MQTT Methods:**
|
|
99
|
-
```javascript
|
|
100
|
-
class YotoMqtt {
|
|
101
|
-
async connect(accessToken)
|
|
102
|
-
async disconnect()
|
|
103
|
-
subscribeToDevice(deviceId, callback)
|
|
104
|
-
unsubscribeFromDevice(deviceId)
|
|
105
|
-
|
|
106
|
-
// Command methods
|
|
107
|
-
async setVolume(deviceId, volume)
|
|
108
|
-
async startCard(deviceId, uri, options)
|
|
109
|
-
async pauseCard(deviceId)
|
|
110
|
-
async resumeCard(deviceId)
|
|
111
|
-
async stopCard(deviceId)
|
|
112
|
-
async setSleepTimer(deviceId, seconds)
|
|
113
|
-
async setAmbientLight(deviceId, r, g, b)
|
|
114
|
-
async requestStatus(deviceId)
|
|
115
|
-
async requestEvents(deviceId)
|
|
116
|
-
}
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### 1.3 Platform Setup ✅
|
|
120
|
-
|
|
121
|
-
**Status:** COMPLETE
|
|
122
|
-
|
|
123
|
-
**Goal:** Implement DynamicPlatformPlugin for device discovery
|
|
124
|
-
|
|
125
|
-
**Files:**
|
|
126
|
-
- `lib/platform.js`
|
|
127
|
-
- `index.js`
|
|
128
|
-
|
|
129
|
-
**Implementation:**
|
|
130
|
-
- Register platform in `index.js`
|
|
131
|
-
- Implement `configureAccessory()` to restore cached accessories
|
|
132
|
-
- Implement `discoverDevices()` called on `didFinishLaunching`
|
|
133
|
-
- Create Map to track accessories by deviceId
|
|
134
|
-
- Handle device addition/removal/updates
|
|
135
|
-
- Store device metadata in `accessory.context`
|
|
136
|
-
|
|
137
|
-
**Platform Lifecycle:**
|
|
138
|
-
1. Constructor: Initialize API client, Service/Characteristic refs
|
|
139
|
-
2. configureAccessory: Restore cached accessories from disk
|
|
140
|
-
3. didFinishLaunching: Discover devices and register new ones
|
|
141
|
-
4. Device sync: Update existing, add new, remove stale accessories
|
|
142
|
-
|
|
143
|
-
### 1.4 Player Accessory (Basic) ✅
|
|
144
|
-
|
|
145
|
-
**Status:** COMPLETE
|
|
146
|
-
|
|
147
|
-
**Goal:** Create accessory with essential playback controls
|
|
148
|
-
|
|
149
|
-
**Files:**
|
|
150
|
-
- `lib/playerAccessory.js`
|
|
151
|
-
|
|
152
|
-
**Services (Phase 1):**
|
|
153
|
-
1. **AccessoryInformation** (required)
|
|
154
|
-
- Manufacturer: "Yoto"
|
|
155
|
-
- Model: from device.deviceType
|
|
156
|
-
- SerialNumber: device.deviceId
|
|
157
|
-
- FirmwareRevision: device.releaseChannel
|
|
158
|
-
|
|
159
|
-
2. **SmartSpeaker** (primary service)
|
|
160
|
-
- CurrentMediaState: PLAYING/PAUSED/STOPPED (read-only)
|
|
161
|
-
- TargetMediaState: PLAY/PAUSE/STOP (write)
|
|
162
|
-
- Volume: 0-100 (read/write)
|
|
163
|
-
- Mute: boolean (read/write)
|
|
164
|
-
|
|
165
|
-
3. **Battery**
|
|
166
|
-
- BatteryLevel: 0-100
|
|
167
|
-
- ChargingState: NOT_CHARGING/CHARGING
|
|
168
|
-
- StatusLowBattery: NORMAL/LOW (< 20%)
|
|
169
|
-
|
|
170
|
-
**Implementation:**
|
|
171
|
-
- Constructor: Set up services and characteristics
|
|
172
|
-
- Implement onGet/onSet handlers for each characteristic
|
|
173
|
-
- Subscribe to MQTT topics for real-time updates
|
|
174
|
-
- Use `updateCharacteristic()` when MQTT messages arrive
|
|
175
|
-
- Cache last known state for onGet handlers
|
|
176
|
-
|
|
177
|
-
### 1.5 MQTT Real-Time Updates ✅
|
|
178
|
-
|
|
179
|
-
**Status:** COMPLETE
|
|
180
|
-
|
|
181
|
-
**Goal:** Keep HomeKit in sync with device state using MQTT
|
|
182
|
-
|
|
183
|
-
**Implementation:**
|
|
184
|
-
- Connect to Yoto MQTT broker on platform init
|
|
185
|
-
- Subscribe to `/device/{id}/data/status` for each device
|
|
186
|
-
- Subscribe to `/device/{id}/data/events` for playback events
|
|
187
|
-
- Update characteristics immediately when MQTT messages arrive
|
|
188
|
-
- Request initial status via `/device/{id}/command/status/request` on startup
|
|
189
|
-
- Implement reconnection logic with exponential backoff
|
|
190
|
-
- Handle offline devices (no recent MQTT messages)
|
|
191
|
-
|
|
192
|
-
**MQTT Topic Subscriptions:**
|
|
193
|
-
```javascript
|
|
194
|
-
// Per device subscriptions
|
|
195
|
-
/device/{deviceId}/data/status → Battery, volume, config state
|
|
196
|
-
/device/{deviceId}/data/events → Playback state, current track
|
|
197
|
-
/device/{deviceId}/response → Command confirmations
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
**Status Mapping:**
|
|
201
|
-
```javascript
|
|
202
|
-
// MQTT data/status → HomeKit
|
|
203
|
-
batteryLevel → BatteryLevel
|
|
204
|
-
charging (0/1) → ChargingState (NOT_CHARGING/CHARGING)
|
|
205
|
-
userVolume → Volume
|
|
206
|
-
activeCard → CurrentMediaState context
|
|
207
|
-
|
|
208
|
-
// MQTT data/events → HomeKit
|
|
209
|
-
playbackStatus ("playing"/"paused"/"stopped") → CurrentMediaState
|
|
210
|
-
volume → Volume (real-time)
|
|
211
|
-
cardId → Active content tracking
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
**Command Publishing:**
|
|
215
|
-
```javascript
|
|
216
|
-
// HomeKit actions → MQTT commands
|
|
217
|
-
Set Volume → /device/{id}/command/volume/set
|
|
218
|
-
Play/Pause → /device/{id}/command/card/pause or /resume
|
|
219
|
-
Stop → /device/{id}/command/card/stop
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
## Phase 2: Enhanced Controls (Partially Complete)
|
|
223
|
-
|
|
224
|
-
### 2.1 Display Control ✅
|
|
225
|
-
|
|
226
|
-
**Status:** COMPLETE
|
|
227
|
-
|
|
228
|
-
**Service:** Lightbulb (for brightness control)
|
|
229
|
-
|
|
230
|
-
**Characteristics:**
|
|
231
|
-
- On: Display on/off
|
|
232
|
-
- Brightness: 0-100 mapped to display brightness settings
|
|
233
|
-
|
|
234
|
-
**Implementation:**
|
|
235
|
-
- Map to `dayDisplayBrightness` and `nightDisplayBrightness`
|
|
236
|
-
- Handle "auto" mode as max brightness (100)
|
|
237
|
-
- Numeric values map directly to percentage
|
|
238
|
-
- Create separate services for day/night if needed
|
|
239
|
-
|
|
240
|
-
### 2.2 Temperature Sensor ✅
|
|
241
|
-
|
|
242
|
-
**Status:** COMPLETE
|
|
243
|
-
|
|
244
|
-
**Service:** TemperatureSensor (optional, enabled via config)
|
|
245
|
-
|
|
246
|
-
**Characteristics:**
|
|
247
|
-
- CurrentTemperature: From `temperatureCelcius`
|
|
248
|
-
|
|
249
|
-
**Config:**
|
|
250
|
-
```javascript
|
|
251
|
-
{
|
|
252
|
-
"exposeTemperature": true
|
|
253
|
-
}
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### 2.3 Connection Status ✅
|
|
257
|
-
|
|
258
|
-
**Status:** COMPLETE
|
|
259
|
-
|
|
260
|
-
**Service:** ContactSensor or OccupancySensor
|
|
261
|
-
|
|
262
|
-
**Characteristics:**
|
|
263
|
-
- ContactSensorState or OccupancyDetected: Based on `isOnline`
|
|
264
|
-
- StatusActive: `isOnline`
|
|
265
|
-
|
|
266
|
-
**Use Cases:**
|
|
267
|
-
- Automation triggers when player comes online
|
|
268
|
-
- Notifications when player goes offline
|
|
269
|
-
- Parent monitoring of device usage
|
|
270
|
-
|
|
271
|
-
### 2.4 Configuration Switches ✅
|
|
272
|
-
|
|
273
|
-
**Status:** COMPLETE
|
|
274
|
-
|
|
275
|
-
**Goal:** Expose device settings as HomeKit switches
|
|
276
|
-
|
|
277
|
-
**Switches:**
|
|
278
|
-
1. Bluetooth Enabled → `bluetoothEnabled`
|
|
279
|
-
2. Bluetooth Headphones → `btHeadphonesEnabled`
|
|
280
|
-
3. Repeat All → `repeatAll`
|
|
281
|
-
|
|
282
|
-
**Implementation:**
|
|
283
|
-
- Create Switch service for each setting
|
|
284
|
-
- onSet: Update via `PUT /device-v2/{deviceId}/config`
|
|
285
|
-
- onGet: Read from cached config or status
|
|
286
|
-
- Refresh config on status poll
|
|
287
|
-
|
|
288
|
-
**Config:**
|
|
289
|
-
```javascript
|
|
290
|
-
{
|
|
291
|
-
"exposeAdvancedControls": true
|
|
292
|
-
}
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
## Phase 3: Advanced Features
|
|
296
|
-
|
|
297
|
-
### 3.1 Volume Limits
|
|
298
|
-
|
|
299
|
-
**Implementation Options:**
|
|
300
|
-
|
|
301
|
-
**Option A: Custom Characteristics (via Eve)**
|
|
302
|
-
- Requires homebridge-lib for custom characteristics
|
|
303
|
-
- Create slider characteristics for max volume
|
|
304
|
-
|
|
305
|
-
**Option B: Additional Lightbulb Services**
|
|
306
|
-
- Use brightness as volume limit (0-16 → 0-100 scale)
|
|
307
|
-
- Name: "Max Volume Day" and "Max Volume Night"
|
|
308
|
-
|
|
309
|
-
**Settings:**
|
|
310
|
-
- Max Volume Limit (Day): `maxVolumeLimit` (0-16)
|
|
311
|
-
- Max Volume Limit (Night): `nightMaxVolumeLimit` (0-16)
|
|
312
|
-
|
|
313
|
-
### 3.2 Ambient Light Control
|
|
314
|
-
|
|
315
|
-
**Service:** Lightbulb (with color)
|
|
316
|
-
|
|
317
|
-
**Characteristics:**
|
|
318
|
-
- On: Ambient light enabled
|
|
319
|
-
- Brightness: Light intensity
|
|
320
|
-
- Hue/Saturation: Parse `ambientColour` hex to HSV
|
|
321
|
-
|
|
322
|
-
**Implementation:**
|
|
323
|
-
- Parse hex color (e.g., "#ff3900") to Hue/Saturation
|
|
324
|
-
- Separate services for day and night colors
|
|
325
|
-
- Update via config: `ambientColour`, `nightAmbientColour`
|
|
326
|
-
|
|
327
|
-
### 3.3 Card Detection ✅
|
|
328
|
-
|
|
329
|
-
**Status:** COMPLETE
|
|
330
|
-
|
|
331
|
-
**Service:** ContactSensor
|
|
332
|
-
|
|
333
|
-
**Characteristics:**
|
|
334
|
-
- ContactSensorState: DETECTED when card inserted
|
|
335
|
-
- StatusActive: true
|
|
336
|
-
|
|
337
|
-
**Status Mapping:**
|
|
338
|
-
```javascript
|
|
339
|
-
cardInsertionState === 0 → CONTACT_NOT_DETECTED
|
|
340
|
-
cardInsertionState === 1 → CONTACT_DETECTED (physical)
|
|
341
|
-
cardInsertionState === 2 → CONTACT_DETECTED (remote)
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
**Use Cases:**
|
|
345
|
-
- Trigger automations when card inserted
|
|
346
|
-
- Parent monitoring of what's playing
|
|
347
|
-
- Bedtime routine detection
|
|
348
|
-
|
|
349
|
-
### 3.4 Sleep Timer ✅
|
|
350
|
-
|
|
351
|
-
**Status:** COMPLETE
|
|
352
|
-
|
|
353
|
-
**Implementation:**
|
|
354
|
-
- ✅ Uses Fanv2 service with rotation speed as timer minutes (0-120 minutes)
|
|
355
|
-
- ✅ Active characteristic controls timer on/off
|
|
356
|
-
- ✅ Real-time updates from MQTT events
|
|
357
|
-
- Or use Valve service with duration
|
|
358
|
-
- Map to `shutdownTimeout` setting (in seconds)
|
|
359
|
-
- Convert minutes to seconds for API
|
|
360
|
-
|
|
361
|
-
## Phase 4: Content Integration
|
|
362
|
-
|
|
363
|
-
### 4.1 Active Content Info
|
|
364
|
-
|
|
365
|
-
**Goal:** Display currently playing content information
|
|
366
|
-
|
|
367
|
-
**Implementation:**
|
|
368
|
-
- When `activeCard` changes, fetch via `GET /content/{cardId}`
|
|
369
|
-
- Store card metadata in accessory context
|
|
370
|
-
- Display title/author in logs or as custom characteristics
|
|
371
|
-
- Update accessory display name with current content (optional)
|
|
372
|
-
|
|
373
|
-
### 4.2 Shortcuts (Future)
|
|
374
|
-
|
|
375
|
-
**Goal:** Expose device shortcuts as programmable switches
|
|
376
|
-
|
|
377
|
-
**API Endpoint:**
|
|
378
|
-
- `PUT /device-v2/{deviceId}/shortcuts`
|
|
379
|
-
|
|
380
|
-
**Service:** StatelessProgrammableSwitch
|
|
381
|
-
|
|
382
|
-
**Implementation:**
|
|
383
|
-
- Create button for each configured shortcut
|
|
384
|
-
- Press triggers associated content/command
|
|
385
|
-
- Separate buttons for day/night mode shortcuts
|
|
386
|
-
- Read from device config: `dayYotoDaily`, `nightYotoRadio`, etc.
|
|
387
|
-
|
|
388
|
-
**Note:** Library groups functionality has been removed from the plan as it's not essential for MVP.
|
|
389
|
-
|
|
390
|
-
## Configuration Schema
|
|
391
|
-
|
|
392
|
-
### Basic Config
|
|
393
|
-
```json
|
|
394
|
-
{
|
|
395
|
-
"platform": "Yoto",
|
|
396
|
-
"name": "Yoto",
|
|
397
|
-
"clientId": "",
|
|
398
|
-
"accessToken": "",
|
|
399
|
-
"refreshToken": "",
|
|
400
|
-
"tokenExpiresAt": 0
|
|
401
|
-
}
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
### Advanced Config
|
|
405
|
-
```json
|
|
406
|
-
{
|
|
407
|
-
"platform": "Yoto",
|
|
408
|
-
"name": "Yoto",
|
|
409
|
-
"clientId": "",
|
|
410
|
-
"mqttBroker": "mqtt://mqtt.yotoplay.com:1883",
|
|
411
|
-
"exposeTemperature": true,
|
|
412
|
-
"exposeBattery": true,
|
|
413
|
-
"exposeAdvancedControls": false,
|
|
414
|
-
"exposeConnectionStatus": true,
|
|
415
|
-
"exposeCardDetection": false,
|
|
416
|
-
"volumeControlType": "speaker",
|
|
417
|
-
"statusTimeoutSeconds": 120,
|
|
418
|
-
"debug": false
|
|
419
|
-
}
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
### config.schema.json Structure
|
|
423
|
-
- OAuth setup instructions in description
|
|
424
|
-
- clientId field (required)
|
|
425
|
-
- MQTT broker URL (with default)
|
|
426
|
-
- Feature toggles for optional sensors
|
|
427
|
-
- Status timeout slider (60-300 seconds) - mark device offline if no updates
|
|
428
|
-
- Debug mode toggle
|
|
429
|
-
|
|
430
|
-
## Error Handling Strategy
|
|
431
|
-
|
|
432
|
-
### API Errors
|
|
433
|
-
- 401 Unauthorized → Trigger token refresh
|
|
434
|
-
- 403 Forbidden → Log error, mark device unavailable
|
|
435
|
-
- 404 Not Found → Device may be deleted, unregister accessory
|
|
436
|
-
- 429 Too Many Requests → Implement exponential backoff
|
|
437
|
-
- 500+ Server Errors → Retry with backoff, log for user
|
|
438
|
-
|
|
439
|
-
### Device Offline
|
|
440
|
-
- Mark services as "No Response" in HomeKit if no MQTT updates for statusTimeoutSeconds
|
|
441
|
-
- MQTT client will automatically attempt reconnection
|
|
442
|
-
- Resume normal operation when MQTT messages resume
|
|
443
|
-
- Log connection status changes
|
|
444
|
-
|
|
445
|
-
### MQTT Connection Issues
|
|
446
|
-
- Implement exponential backoff for reconnection attempts
|
|
447
|
-
- Use Last Will and Testament (LWT) if supported by broker
|
|
448
|
-
- Maintain connection state per device
|
|
449
|
-
- Gracefully handle broker unavailability
|
|
450
|
-
|
|
451
|
-
### Token Expiration
|
|
452
|
-
- Proactively refresh before expiration
|
|
453
|
-
- If refresh fails, require user re-authentication
|
|
454
|
-
- Clear tokens from config on auth failure
|
|
455
|
-
- Display clear instructions in logs
|
|
456
|
-
|
|
457
|
-
### Homebridge Crashes
|
|
458
|
-
- Persist all state in accessory.context
|
|
459
|
-
- Gracefully restore on restart
|
|
460
|
-
- Re-establish API connection
|
|
461
|
-
- Resume polling from last known state
|
|
462
|
-
|
|
463
|
-
## Testing Strategy
|
|
464
|
-
|
|
465
|
-
### Unit Tests
|
|
466
|
-
- API client methods (mock fetch)
|
|
467
|
-
- Token refresh logic
|
|
468
|
-
- Status mapping functions
|
|
469
|
-
- Config validation
|
|
470
|
-
|
|
471
|
-
### Integration Tests
|
|
472
|
-
- OAuth flow (with mock server)
|
|
473
|
-
- Device discovery
|
|
474
|
-
- Characteristic updates
|
|
475
|
-
- Error recovery
|
|
476
|
-
|
|
477
|
-
### Manual Testing Checklist
|
|
478
|
-
- [ ] Initial OAuth setup flow
|
|
479
|
-
- [ ] Device discovery and registration
|
|
480
|
-
- [ ] Play/pause control
|
|
481
|
-
- [ ] Volume adjustment
|
|
482
|
-
- [ ] Battery status display
|
|
483
|
-
- [ ] MQTT connection establishment
|
|
484
|
-
- [ ] Real-time status updates via MQTT
|
|
485
|
-
- [ ] Device offline handling
|
|
486
|
-
- [ ] Token refresh
|
|
487
|
-
- [ ] Homebridge restart recovery
|
|
488
|
-
- [ ] Multiple device support
|
|
489
|
-
- [ ] Device removal from account
|
|
490
|
-
|
|
491
|
-
## Documentation
|
|
492
|
-
|
|
493
|
-
### README.md
|
|
494
|
-
- Overview and features
|
|
495
|
-
- Prerequisites (Yoto account, Homebridge)
|
|
496
|
-
- Installation instructions
|
|
497
|
-
- OAuth setup guide with screenshots
|
|
498
|
-
- Configuration options
|
|
499
|
-
- Troubleshooting common issues
|
|
500
|
-
- Supported devices
|
|
501
|
-
|
|
502
|
-
### CHANGELOG.md
|
|
503
|
-
- Version history
|
|
504
|
-
- Feature additions
|
|
505
|
-
- Bug fixes
|
|
506
|
-
- Breaking changes
|
|
507
|
-
|
|
508
|
-
### Contributing Guide
|
|
509
|
-
- Development setup
|
|
510
|
-
- Code style (JSDoc, ESLint)
|
|
511
|
-
- Testing requirements
|
|
512
|
-
- Pull request process
|
|
513
|
-
|
|
514
|
-
## Future Enhancements (Post-MVP)
|
|
515
|
-
|
|
516
|
-
### Content Management
|
|
517
|
-
- [ ] Recently played content tracking
|
|
518
|
-
- [ ] MYO card management
|
|
519
|
-
- [ ] Active content information display
|
|
520
|
-
|
|
521
|
-
### Advanced Device Control
|
|
522
|
-
- [ ] Alarm management
|
|
523
|
-
- [ ] Clock face selection
|
|
524
|
-
- [ ] Scheduled ambient light changes
|
|
525
|
-
- [ ] Audio output routing
|
|
526
|
-
|
|
527
|
-
### Multi-Device Features
|
|
528
|
-
- [ ] Synchronized playback
|
|
529
|
-
- [ ] Family dashboard accessory
|
|
530
|
-
- [ ] Group controls
|
|
531
|
-
|
|
532
|
-
### Parental Controls
|
|
533
|
-
- [ ] Time-based restrictions
|
|
534
|
-
- [ ] Content filtering
|
|
535
|
-
- [ ] Usage monitoring
|
|
536
|
-
|
|
537
|
-
### Automation Integration
|
|
538
|
-
- [ ] Bedtime scene triggers
|
|
539
|
-
- [ ] Presence detection
|
|
540
|
-
- [ ] Weather-based content
|
|
541
|
-
- [ ] HomeKit Secure Video integration (if camera added)
|
|
542
|
-
|
|
543
|
-
## Success Metrics
|
|
544
|
-
|
|
545
|
-
### MVP Success Criteria
|
|
546
|
-
- [ ] Successfully authenticate with Yoto API
|
|
547
|
-
- [ ] Discover and register all user devices
|
|
548
|
-
- [ ] Control play/pause from Home app
|
|
549
|
-
- [ ] Adjust volume from Home app
|
|
550
|
-
- [ ] Display accurate battery status
|
|
551
|
-
- [ ] Status updates within 60 seconds
|
|
552
|
-
- [ ] Survive Homebridge restart
|
|
553
|
-
- [ ] Handle device offline gracefully
|
|
554
|
-
|
|
555
|
-
### Phase 2 Success Criteria
|
|
556
|
-
- [ ] Brightness control functional
|
|
557
|
-
- [ ] Temperature sensor (if enabled)
|
|
558
|
-
- [ ] Connection status monitoring
|
|
559
|
-
- [ ] Configuration switches work
|
|
560
|
-
|
|
561
|
-
### User Satisfaction Goals
|
|
562
|
-
- Setup time under 5 minutes
|
|
563
|
-
- No more than 2 second latency for controls
|
|
564
|
-
- Clear error messages and recovery steps
|
|
565
|
-
- Stable over 7 days continuous operation
|
|
566
|
-
|
|
567
|
-
## Development Phases Timeline
|
|
568
|
-
|
|
569
|
-
### Week 1: Foundation
|
|
570
|
-
- Day 1-2: Project setup, REST API client, auth
|
|
571
|
-
- Day 3-4: MQTT client implementation
|
|
572
|
-
- Day 5-7: Platform implementation with MQTT integration
|
|
573
|
-
|
|
574
|
-
### Week 2: Core Features
|
|
575
|
-
- Day 1-2: Basic accessory with playback/volume controls via MQTT
|
|
576
|
-
- Day 3-4: Battery service, real-time status updates
|
|
577
|
-
- Day 5-7: Display control, temperature sensor
|
|
578
|
-
|
|
579
|
-
### Week 3: Advanced Features
|
|
580
|
-
- Day 1-3: Advanced controls, volume limits
|
|
581
|
-
- Day 4-5: Card detection, connection status
|
|
582
|
-
- Day 6-7: Integration testing, polish
|
|
583
|
-
|
|
584
|
-
### Week 4: Release Prep
|
|
585
|
-
- Day 1-3: Documentation, examples
|
|
586
|
-
- Day 4-5: Beta testing with users
|
|
587
|
-
- Day 6-7: Bug fixes, npm publish
|
|
588
|
-
|
|
589
|
-
## Next Steps
|
|
590
|
-
|
|
591
|
-
1. ✅ Review and approve plan
|
|
592
|
-
2. ✅ Discover MQTT integration capability
|
|
593
|
-
3. ✅ Set up project structure and dependencies (including MQTT library)
|
|
594
|
-
4. ✅ Implement auth.js with OAuth flow
|
|
595
|
-
5. ✅ Create REST API client wrapper
|
|
596
|
-
6. ✅ Create MQTT client wrapper with subscriptions
|
|
597
|
-
7. ✅ Build platform foundation with MQTT connection
|
|
598
|
-
8. ✅ Implement basic player accessory with real-time updates
|
|
599
|
-
9. ✅ Add display brightness control
|
|
600
|
-
10. ✅ Add sleep timer control
|
|
601
|
-
11. ✅ Add advanced control switches
|
|
602
|
-
12. ✅ Improve MQTT reconnection logic
|
|
603
|
-
13. 🔄 Test with real Yoto devices (PRIORITY)
|
|
604
|
-
14. 🔄 Add volume limit controls (IN PROGRESS)
|
|
605
|
-
15. 🔄 Add ambient light color control (IN PROGRESS)
|
|
606
|
-
16. ⏳ Add active content information display
|
|
607
|
-
17. ⏳ Add shortcuts support (future)
|
|
608
|
-
18. ⏳ Publish to npm
|
|
609
|
-
19. ⏳ Iterate based on user feedback
|
package/eslint.config.js
DELETED