homebridge-yoto 0.0.18 → 0.0.19
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/lib/auth.js +2 -2
- package/lib/platform.js +8 -8
- package/lib/playerAccessory.js +16 -16
- package/lib/yotoApi.js +1 -1
- package/lib/yotoMqtt.js +7 -7
- package/package.json +1 -1
package/lib/auth.js
CHANGED
|
@@ -35,7 +35,7 @@ export class YotoAuth {
|
|
|
35
35
|
* @returns {Promise<YotoApiDeviceCodeResponse>}
|
|
36
36
|
*/
|
|
37
37
|
async initiateDeviceFlow () {
|
|
38
|
-
this.log.
|
|
38
|
+
this.log.debug(LOG_PREFIX.AUTH, 'Initiating device authorization flow...')
|
|
39
39
|
this.log.debug(LOG_PREFIX.AUTH, `Client ID: ${this.clientId}`)
|
|
40
40
|
this.log.debug(LOG_PREFIX.AUTH, `Endpoint: ${YOTO_OAUTH_DEVICE_CODE_URL}`)
|
|
41
41
|
this.log.debug(LOG_PREFIX.AUTH, `Scope: ${OAUTH_SCOPE}`)
|
|
@@ -97,7 +97,7 @@ export class YotoAuth {
|
|
|
97
97
|
const startTime = Date.now()
|
|
98
98
|
const timeout = OAUTH_DEVICE_CODE_TIMEOUT
|
|
99
99
|
|
|
100
|
-
this.log.
|
|
100
|
+
this.log.debug(LOG_PREFIX.AUTH, 'Waiting for user authorization...')
|
|
101
101
|
|
|
102
102
|
while (Date.now() - startTime < timeout) {
|
|
103
103
|
try {
|
package/lib/platform.js
CHANGED
|
@@ -219,7 +219,7 @@ export class YotoPlatform {
|
|
|
219
219
|
*/
|
|
220
220
|
async performDeviceFlow () {
|
|
221
221
|
this.log.warn(LOG_PREFIX.PLATFORM, ERROR_MESSAGES.NO_AUTH)
|
|
222
|
-
this.log.
|
|
222
|
+
this.log.debug(LOG_PREFIX.PLATFORM, 'Starting OAuth flow...')
|
|
223
223
|
|
|
224
224
|
const tokenResponse = await this.auth.authorize()
|
|
225
225
|
|
|
@@ -258,7 +258,7 @@ export class YotoPlatform {
|
|
|
258
258
|
* @param {number} expiresAt - New expiration timestamp
|
|
259
259
|
*/
|
|
260
260
|
handleTokenRefresh (accessToken, refreshToken, expiresAt) {
|
|
261
|
-
this.log.
|
|
261
|
+
this.log.debug(LOG_PREFIX.PLATFORM, 'Token refreshed')
|
|
262
262
|
this.config.accessToken = accessToken
|
|
263
263
|
this.config.refreshToken = refreshToken
|
|
264
264
|
this.config.tokenExpiresAt = expiresAt
|
|
@@ -329,7 +329,7 @@ export class YotoPlatform {
|
|
|
329
329
|
* @param {PlatformAccessory<YotoAccessoryContext>} accessory - Cached accessory
|
|
330
330
|
*/
|
|
331
331
|
configureAccessory (accessory) {
|
|
332
|
-
this.log.
|
|
332
|
+
this.log.debug(LOG_PREFIX.PLATFORM, 'Loading accessory from cache:', accessory.displayName)
|
|
333
333
|
|
|
334
334
|
// Add to our tracking map
|
|
335
335
|
this.accessories.set(accessory.UUID, accessory)
|
|
@@ -341,7 +341,7 @@ export class YotoPlatform {
|
|
|
341
341
|
*/
|
|
342
342
|
async discoverDevices () {
|
|
343
343
|
try {
|
|
344
|
-
this.log.
|
|
344
|
+
this.log.debug(LOG_PREFIX.PLATFORM, 'Discovering Yoto devices...')
|
|
345
345
|
|
|
346
346
|
// Fetch devices from API
|
|
347
347
|
const devices = await this.yotoApi.getDevices()
|
|
@@ -381,7 +381,7 @@ export class YotoPlatform {
|
|
|
381
381
|
|
|
382
382
|
if (existingAccessory) {
|
|
383
383
|
// Accessory exists - update it
|
|
384
|
-
this.log.
|
|
384
|
+
this.log.debug(LOG_PREFIX.PLATFORM, 'Restoring existing accessory:', device.name)
|
|
385
385
|
|
|
386
386
|
// Update context with fresh device data
|
|
387
387
|
const typedAccessory = /** @type {PlatformAccessory<YotoAccessoryContext>} */ (existingAccessory)
|
|
@@ -403,7 +403,7 @@ export class YotoPlatform {
|
|
|
403
403
|
})
|
|
404
404
|
} else {
|
|
405
405
|
// Create new accessory
|
|
406
|
-
this.log.
|
|
406
|
+
this.log.debug(LOG_PREFIX.PLATFORM, 'Adding new accessory:', device.name)
|
|
407
407
|
|
|
408
408
|
// Create platform accessory
|
|
409
409
|
// eslint-disable-next-line new-cap
|
|
@@ -447,7 +447,7 @@ export class YotoPlatform {
|
|
|
447
447
|
|
|
448
448
|
for (const [uuid, accessory] of this.accessories) {
|
|
449
449
|
if (!this.discoveredUUIDs.includes(uuid)) {
|
|
450
|
-
this.log.
|
|
450
|
+
this.log.debug(LOG_PREFIX.PLATFORM, 'Removing stale accessory:', accessory.displayName)
|
|
451
451
|
staleAccessories.push(accessory)
|
|
452
452
|
}
|
|
453
453
|
}
|
|
@@ -473,7 +473,7 @@ export class YotoPlatform {
|
|
|
473
473
|
* Shutdown handler - cleanup connections
|
|
474
474
|
*/
|
|
475
475
|
async shutdown () {
|
|
476
|
-
this.log.
|
|
476
|
+
this.log.debug(LOG_PREFIX.PLATFORM, 'Shutting down...')
|
|
477
477
|
|
|
478
478
|
// Stop status polling
|
|
479
479
|
this.stopStatusPolling()
|
package/lib/playerAccessory.js
CHANGED
|
@@ -514,14 +514,14 @@ export class YotoPlayerAccessory {
|
|
|
514
514
|
* @param {YotoDeviceStatus | {status: YotoDeviceStatus}} statusMessage - Status data or wrapped status
|
|
515
515
|
*/
|
|
516
516
|
handleStatusUpdate (statusMessage) {
|
|
517
|
-
this.log.
|
|
517
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Raw MQTT status message:`, JSON.stringify(statusMessage, null, 2))
|
|
518
518
|
|
|
519
519
|
// Unwrap status if it's nested under a 'status' property
|
|
520
520
|
const status = /** @type {YotoDeviceStatus} */ ('status' in statusMessage ? statusMessage.status : statusMessage)
|
|
521
521
|
|
|
522
|
-
this.log.
|
|
523
|
-
this.log.
|
|
524
|
-
this.log.
|
|
522
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Unwrapped status - batteryLevel:`, status.batteryLevel)
|
|
523
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Unwrapped status - userVolume:`, status.userVolume)
|
|
524
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Unwrapped status - volume:`, status.volume)
|
|
525
525
|
|
|
526
526
|
this.currentStatus = status
|
|
527
527
|
this.lastUpdateTime = Date.now()
|
|
@@ -536,12 +536,12 @@ export class YotoPlayerAccessory {
|
|
|
536
536
|
* @param {YotoPlaybackEvents | {events: YotoPlaybackEvents}} eventsMessage - Playback events or wrapped events
|
|
537
537
|
*/
|
|
538
538
|
handleEventsUpdate (eventsMessage) {
|
|
539
|
-
this.log.
|
|
539
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Raw MQTT events message:`, JSON.stringify(eventsMessage, null, 2))
|
|
540
540
|
|
|
541
541
|
// Unwrap events if it's nested under an 'events' property
|
|
542
542
|
const events = /** @type {YotoPlaybackEvents} */ ('events' in eventsMessage ? eventsMessage.events : eventsMessage)
|
|
543
543
|
|
|
544
|
-
this.log.
|
|
544
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Unwrapped events - cardId:`, events.cardId)
|
|
545
545
|
this.currentEvents = events
|
|
546
546
|
this.lastUpdateTime = Date.now()
|
|
547
547
|
this.accessory.context.lastEvents = events
|
|
@@ -560,7 +560,7 @@ export class YotoPlayerAccessory {
|
|
|
560
560
|
* @param {import('./types.js').MqttCommandResponse} response - Command response
|
|
561
561
|
*/
|
|
562
562
|
handleCommandResponse (response) {
|
|
563
|
-
this.log.
|
|
563
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Command response:`, response)
|
|
564
564
|
}
|
|
565
565
|
|
|
566
566
|
/**
|
|
@@ -799,16 +799,16 @@ export class YotoPlayerAccessory {
|
|
|
799
799
|
* @returns {Promise<CharacteristicValue>}
|
|
800
800
|
*/
|
|
801
801
|
async getVolume () {
|
|
802
|
-
this.log.
|
|
803
|
-
this.log.
|
|
802
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getVolume - currentEvents:`, this.currentEvents)
|
|
803
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getVolume - events.volume:`, this.currentEvents?.volume)
|
|
804
804
|
|
|
805
805
|
// Volume comes from events, not status
|
|
806
806
|
if (!this.currentEvents || this.currentEvents.volume === undefined) {
|
|
807
|
-
this.log.
|
|
807
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getVolume - no volume in events, returning default: 50`)
|
|
808
808
|
return 50
|
|
809
809
|
}
|
|
810
810
|
const volume = Number(this.currentEvents.volume) || 50
|
|
811
|
-
this.log.
|
|
811
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getVolume - returning volume:`, volume)
|
|
812
812
|
return volume
|
|
813
813
|
}
|
|
814
814
|
|
|
@@ -871,15 +871,15 @@ export class YotoPlayerAccessory {
|
|
|
871
871
|
* @returns {Promise<CharacteristicValue>}
|
|
872
872
|
*/
|
|
873
873
|
async getBatteryLevel () {
|
|
874
|
-
this.log.
|
|
875
|
-
this.log.
|
|
874
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getBatteryLevel - currentStatus:`, this.currentStatus)
|
|
875
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getBatteryLevel - batteryLevel:`, this.currentStatus?.batteryLevel)
|
|
876
876
|
|
|
877
877
|
if (!this.currentStatus || this.currentStatus.batteryLevel === undefined) {
|
|
878
|
-
this.log.
|
|
878
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getBatteryLevel - returning default: 100`)
|
|
879
879
|
return 100
|
|
880
880
|
}
|
|
881
881
|
const battery = Number(this.currentStatus.batteryLevel) || 100
|
|
882
|
-
this.log.
|
|
882
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getBatteryLevel - returning:`, battery)
|
|
883
883
|
return battery
|
|
884
884
|
}
|
|
885
885
|
|
|
@@ -1599,7 +1599,7 @@ export class YotoPlayerAccessory {
|
|
|
1599
1599
|
// Optionally update accessory display name with current content
|
|
1600
1600
|
if (this.platform.config.updateAccessoryName) {
|
|
1601
1601
|
this.accessory.displayName = `${this.device.name} - ${title}`
|
|
1602
|
-
this.log.
|
|
1602
|
+
this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Updated display name`)
|
|
1603
1603
|
}
|
|
1604
1604
|
}
|
|
1605
1605
|
|
package/lib/yotoApi.js
CHANGED
|
@@ -59,7 +59,7 @@ export class YotoApi {
|
|
|
59
59
|
|
|
60
60
|
// Check if token needs refresh
|
|
61
61
|
if (this.auth.isTokenExpired(this.tokenExpiresAt)) {
|
|
62
|
-
this.log.
|
|
62
|
+
this.log.debug(LOG_PREFIX.API, ERROR_MESSAGES.TOKEN_EXPIRED)
|
|
63
63
|
|
|
64
64
|
if (!this.refreshToken) {
|
|
65
65
|
throw new Error(ERROR_MESSAGES.TOKEN_REFRESH_FAILED)
|
package/lib/yotoMqtt.js
CHANGED
|
@@ -65,7 +65,7 @@ export class YotoMqtt extends EventEmitter {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
return new Promise((resolve, reject) => {
|
|
68
|
-
this.log.
|
|
68
|
+
this.log.debug(LOG_PREFIX.MQTT, `Connecting to ${this.brokerUrl}...`)
|
|
69
69
|
|
|
70
70
|
const clientId = `DASH${deviceId}`
|
|
71
71
|
const username = `${deviceId}?x-amz-customauthorizer-name=${YOTO_MQTT_AUTH_NAME}`
|
|
@@ -144,7 +144,7 @@ export class YotoMqtt extends EventEmitter {
|
|
|
144
144
|
|
|
145
145
|
this.client.on('reconnect', () => {
|
|
146
146
|
this.reconnectAttempts++
|
|
147
|
-
this.log.
|
|
147
|
+
this.log.debug(LOG_PREFIX.MQTT, `Reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}`)
|
|
148
148
|
|
|
149
149
|
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
150
150
|
this.log.error(LOG_PREFIX.MQTT, 'Max reconnection attempts reached, stopping reconnection')
|
|
@@ -201,14 +201,14 @@ export class YotoMqtt extends EventEmitter {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
return new Promise((resolve) => {
|
|
204
|
-
this.log.
|
|
204
|
+
this.log.debug(LOG_PREFIX.MQTT, 'Disconnecting from MQTT broker...')
|
|
205
205
|
|
|
206
206
|
if (this.client) {
|
|
207
207
|
this.client.end(false, {}, () => {
|
|
208
208
|
this.connected = false
|
|
209
209
|
this.client = null
|
|
210
210
|
this.subscribedDevices.clear()
|
|
211
|
-
this.log.
|
|
211
|
+
this.log.debug(LOG_PREFIX.MQTT, 'Disconnected')
|
|
212
212
|
resolve()
|
|
213
213
|
})
|
|
214
214
|
} else {
|
|
@@ -246,7 +246,7 @@ export class YotoMqtt extends EventEmitter {
|
|
|
246
246
|
return
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
this.log.
|
|
249
|
+
this.log.debug(LOG_PREFIX.MQTT, `Resubscribing to ${this.subscribedDevices.size} device(s)...`)
|
|
250
250
|
|
|
251
251
|
for (const deviceId of this.subscribedDevices) {
|
|
252
252
|
const callbacks = this.deviceCallbacks.get(deviceId)
|
|
@@ -281,7 +281,7 @@ export class YotoMqtt extends EventEmitter {
|
|
|
281
281
|
return
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
this.log.
|
|
284
|
+
this.log.debug(LOG_PREFIX.MQTT, `Subscribing to device ${deviceId}...`)
|
|
285
285
|
|
|
286
286
|
const topics = [
|
|
287
287
|
this.buildTopic(MQTT_TOPIC_DATA_STATUS, deviceId),
|
|
@@ -331,7 +331,7 @@ export class YotoMqtt extends EventEmitter {
|
|
|
331
331
|
return
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
-
this.log.
|
|
334
|
+
this.log.debug(LOG_PREFIX.MQTT, `Unsubscribing from device ${deviceId}...`)
|
|
335
335
|
|
|
336
336
|
const topics = [
|
|
337
337
|
this.buildTopic(MQTT_TOPIC_DATA_STATUS, deviceId),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-yoto",
|
|
3
3
|
"description": "Control your Yoto players through Apple HomeKit with real-time MQTT updates",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.19",
|
|
5
5
|
"author": "Bret Comnes <bcomnes@gmail.com> (https://bret.io)",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/bcomnes/homebridge-yoto/issues"
|