homebridge-yoto 0.0.19 → 0.0.21

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.
@@ -38,6 +38,9 @@ export class YotoPlayerAccessory {
38
38
  this.currentEvents = accessory.context.lastEvents || null
39
39
  this.lastUpdateTime = Date.now()
40
40
 
41
+ // Cache for device config
42
+ this.deviceConfig = null
43
+
41
44
  // Create dedicated MQTT client for this device
42
45
  this.mqtt = new YotoMqtt(this.log)
43
46
 
@@ -110,6 +113,15 @@ export class YotoPlayerAccessory {
110
113
  * @returns {Promise<void>}
111
114
  */
112
115
  async initialize () {
116
+ // Fetch device config for cached access
117
+ try {
118
+ this.deviceConfig = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
119
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Device config loaded`)
120
+ } catch (error) {
121
+ this.log.warn(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to load device config:`, error)
122
+ // Continue without config - getters will return defaults
123
+ }
124
+
113
125
  await this.connectMqtt()
114
126
  // Status polling is handled at platform level
115
127
  }
@@ -455,7 +467,7 @@ export class YotoPlayerAccessory {
455
467
  try {
456
468
  // Check if device is online first
457
469
  if (!this.device.online) {
458
- this.log.warn(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Device is offline, skipping MQTT connection`)
470
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Device is offline, skipping MQTT connection`)
459
471
  return
460
472
  }
461
473
 
@@ -465,12 +477,7 @@ export class YotoPlayerAccessory {
465
477
  return
466
478
  }
467
479
 
468
- // TEMPORARY: Debug logging for MQTT troubleshooting
469
- this.log.warn(LOG_PREFIX.ACCESSORY, `[${this.device.name}] MQTT Connection Details:`)
470
- this.log.warn(LOG_PREFIX.ACCESSORY, ` Device Online: ${this.device.online}`)
471
- this.log.warn(LOG_PREFIX.ACCESSORY, ` Device ID: ${this.device.deviceId}`)
472
- this.log.warn(LOG_PREFIX.ACCESSORY, ` Access Token: ${this.platform.config.accessToken}`)
473
- this.log.warn(LOG_PREFIX.ACCESSORY, ` Token Length: ${this.platform.config.accessToken.length}`)
480
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Connecting to MQTT (device online: ${this.device.online})`)
474
481
 
475
482
  // Connect MQTT with device ID and access token
476
483
  await this.mqtt.connect(
@@ -491,12 +498,12 @@ export class YotoPlayerAccessory {
491
498
  // Set up MQTT event listeners
492
499
  this.mqtt.on('disconnected', () => {
493
500
  this.mqttConnected = false
494
- this.log.warn(LOG_PREFIX.ACCESSORY, `[${this.device.name}] MQTT disconnected`)
501
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] MQTT disconnected`)
495
502
  })
496
503
 
497
504
  this.mqtt.on('offline', () => {
498
505
  this.mqttConnected = false
499
- this.log.warn(LOG_PREFIX.ACCESSORY, `[${this.device.name}] MQTT offline`)
506
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] MQTT offline`)
500
507
  })
501
508
 
502
509
  this.mqtt.on('connected', () => {
@@ -604,12 +611,18 @@ export class YotoPlayerAccessory {
604
611
 
605
612
  // Update temperature
606
613
  if (this.temperatureService && this.currentStatus.temp) {
607
- const temp = parseFloat(this.currentStatus.temp)
608
- if (!isNaN(temp)) {
609
- this.temperatureService.updateCharacteristic(
610
- this.platform.Characteristic.CurrentTemperature,
611
- temp
612
- )
614
+ // Parse temp string format "x:temp:y" to get middle value
615
+ const tempParts = this.currentStatus.temp.split(':')
616
+ if (tempParts.length >= 2) {
617
+ const temp = Number(tempParts[1])
618
+ if (!isNaN(temp)) {
619
+ // Clamp to HomeKit's valid range: 0-100°C
620
+ const clampedTemp = Math.max(0, Math.min(100, temp))
621
+ this.temperatureService.updateCharacteristic(
622
+ this.platform.Characteristic.CurrentTemperature,
623
+ clampedTemp
624
+ )
625
+ }
613
626
  }
614
627
 
615
628
  // Update display brightness
@@ -917,11 +930,22 @@ export class YotoPlayerAccessory {
917
930
  */
918
931
  async getCurrentTemperature () {
919
932
  if (!this.currentStatus || !this.currentStatus.temp) {
933
+ return 20 // Default room temperature
934
+ }
935
+
936
+ // Parse temp string format "x:temp:y" to get middle value (actual temperature)
937
+ const tempParts = this.currentStatus.temp.split(':')
938
+ if (tempParts.length < 2) {
939
+ return 20
940
+ }
941
+
942
+ const temp = Number(tempParts[1])
943
+ if (isNaN(temp)) {
920
944
  return 20
921
945
  }
922
946
 
923
- const temp = parseFloat(this.currentStatus.temp)
924
- return isNaN(temp) ? 20 : temp
947
+ // Clamp to HomeKit's valid range: 0-100°C
948
+ return Math.max(0, Math.min(100, temp))
925
949
  }
926
950
 
927
951
  /**
@@ -977,20 +1001,23 @@ export class YotoPlayerAccessory {
977
1001
  this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Set display on:`, value)
978
1002
 
979
1003
  try {
980
- // Get current config to update brightness settings
981
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1004
+ // Refresh config if not cached
1005
+ if (!this.deviceConfig) {
1006
+ this.deviceConfig = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1007
+ }
982
1008
 
983
1009
  if (value) {
984
- // Turn on - restore to auto or previous brightness
985
- config.config.dayDisplayBrightness = 'auto'
986
- config.config.nightDisplayBrightness = 'auto'
1010
+ // Turn on - restore to previous brightness or default
1011
+ const brightness = this.currentStatus?.dnowBrightness || 100
1012
+ this.deviceConfig.config.dayDisplayBrightness = String(brightness)
1013
+ this.deviceConfig.config.nightDisplayBrightness = String(brightness)
987
1014
  } else {
988
1015
  // Turn off - set brightness to 0
989
- config.config.dayDisplayBrightness = '0'
990
- config.config.nightDisplayBrightness = '0'
1016
+ this.deviceConfig.config.dayDisplayBrightness = '0'
1017
+ this.deviceConfig.config.nightDisplayBrightness = '0'
991
1018
  }
992
1019
 
993
- await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, config)
1020
+ await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, this.deviceConfig)
994
1021
  } catch (error) {
995
1022
  this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to set display on:`, error)
996
1023
  throw new this.platform.api.hap.HapStatusError(
@@ -1024,16 +1051,19 @@ export class YotoPlayerAccessory {
1024
1051
  this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Set display brightness:`, value)
1025
1052
 
1026
1053
  try {
1027
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1054
+ // Refresh config if not cached
1055
+ if (!this.deviceConfig) {
1056
+ this.deviceConfig = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1057
+ }
1028
1058
 
1029
- // Map 0-100 to brightness string
1030
- const brightness = String(Math.round(Number(value)))
1059
+ // Clamp brightness to 0-100
1060
+ const brightness = Math.max(0, Math.min(100, Number(value)))
1031
1061
 
1032
1062
  // Update both day and night brightness
1033
- config.config.dayDisplayBrightness = brightness
1034
- config.config.nightDisplayBrightness = brightness
1063
+ this.deviceConfig.config.dayDisplayBrightness = String(brightness)
1064
+ this.deviceConfig.config.nightDisplayBrightness = String(brightness)
1035
1065
 
1036
- await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, config)
1066
+ await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, this.deviceConfig)
1037
1067
  } catch (error) {
1038
1068
  this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to set display brightness:`, error)
1039
1069
  throw new this.platform.api.hap.HapStatusError(
@@ -1058,12 +1088,16 @@ export class YotoPlayerAccessory {
1058
1088
  * @param {CharacteristicValue} value - Enabled state
1059
1089
  */
1060
1090
  async setBluetoothEnabled (value) {
1061
- this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Set Bluetooth enabled:`, value)
1091
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Set Bluetooth:`, value)
1062
1092
 
1063
1093
  try {
1064
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1065
- config.config.bluetoothEnabled = value ? '1' : '0'
1066
- await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, config)
1094
+ // Refresh config if not cached
1095
+ if (!this.deviceConfig) {
1096
+ this.deviceConfig = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1097
+ }
1098
+
1099
+ this.deviceConfig.config.bluetoothEnabled = value ? 'true' : 'false'
1100
+ await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, this.deviceConfig)
1067
1101
  } catch (error) {
1068
1102
  this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to set Bluetooth:`, error)
1069
1103
  throw new this.platform.api.hap.HapStatusError(
@@ -1091,11 +1125,15 @@ export class YotoPlayerAccessory {
1091
1125
  this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Set repeat all:`, value)
1092
1126
 
1093
1127
  try {
1094
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1095
- config.config.repeatAll = Boolean(value)
1096
- await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, config)
1128
+ // Refresh config if not cached
1129
+ if (!this.deviceConfig) {
1130
+ this.deviceConfig = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1131
+ }
1132
+
1133
+ this.deviceConfig.config.repeatAll = Boolean(value)
1134
+ await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, this.deviceConfig)
1097
1135
  } catch (error) {
1098
- this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to set repeat:`, error)
1136
+ this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to set repeat all:`, error)
1099
1137
  throw new this.platform.api.hap.HapStatusError(
1100
1138
  this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE
1101
1139
  )
@@ -1118,12 +1156,16 @@ export class YotoPlayerAccessory {
1118
1156
  * @param {CharacteristicValue} value - Enabled state
1119
1157
  */
1120
1158
  async setBtHeadphonesEnabled (value) {
1121
- this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Set BT headphones enabled:`, value)
1159
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Set BT headphones:`, value)
1122
1160
 
1123
1161
  try {
1124
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1125
- config.config.btHeadphonesEnabled = Boolean(value)
1126
- await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, config)
1162
+ // Refresh config if not cached
1163
+ if (!this.deviceConfig) {
1164
+ this.deviceConfig = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1165
+ }
1166
+
1167
+ this.deviceConfig.config.btHeadphonesEnabled = Boolean(value)
1168
+ await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, this.deviceConfig)
1127
1169
  } catch (error) {
1128
1170
  this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to set BT headphones:`, error)
1129
1171
  throw new this.platform.api.hap.HapStatusError(
@@ -1233,16 +1275,19 @@ export class YotoPlayerAccessory {
1233
1275
  * @returns {Promise<CharacteristicValue>}
1234
1276
  */
1235
1277
  async getDayVolumeLimit () {
1278
+ if (!this.deviceConfig) {
1279
+ return 100 // Default to max
1280
+ }
1281
+
1236
1282
  try {
1237
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1238
- const limit = parseInt(config.config.maxVolumeLimit || '16')
1283
+ const limit = parseInt(this.deviceConfig.config.maxVolumeLimit || '16')
1239
1284
  if (isNaN(limit)) {
1240
1285
  return 100
1241
1286
  }
1242
1287
  // Map 0-16 to 0-100
1243
1288
  return Math.round((limit / 16) * 100)
1244
1289
  } catch (error) {
1245
- this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to get day volume limit:`, error)
1290
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to parse day volume limit:`, error)
1246
1291
  return 100
1247
1292
  }
1248
1293
  }
@@ -1255,11 +1300,15 @@ export class YotoPlayerAccessory {
1255
1300
  this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Set day volume limit:`, value)
1256
1301
 
1257
1302
  try {
1258
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1303
+ // Refresh config if not cached
1304
+ if (!this.deviceConfig) {
1305
+ this.deviceConfig = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1306
+ }
1307
+
1259
1308
  // Map 0-100 to 0-16
1260
1309
  const limit = Math.round((Number(value) / 100) * 16)
1261
- config.config.maxVolumeLimit = String(limit)
1262
- await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, config)
1310
+ this.deviceConfig.config.maxVolumeLimit = String(limit)
1311
+ await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, this.deviceConfig)
1263
1312
  } catch (error) {
1264
1313
  this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to set day volume limit:`, error)
1265
1314
  throw new this.platform.api.hap.HapStatusError(
@@ -1291,16 +1340,19 @@ export class YotoPlayerAccessory {
1291
1340
  * @returns {Promise<CharacteristicValue>}
1292
1341
  */
1293
1342
  async getNightVolumeLimit () {
1343
+ if (!this.deviceConfig) {
1344
+ return 100 // Default to max
1345
+ }
1346
+
1294
1347
  try {
1295
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1296
- const limit = parseInt(config.config.nightMaxVolumeLimit || '16')
1348
+ const limit = parseInt(this.deviceConfig.config.nightMaxVolumeLimit || '16')
1297
1349
  if (isNaN(limit)) {
1298
1350
  return 100
1299
1351
  }
1300
1352
  // Map 0-16 to 0-100
1301
1353
  return Math.round((limit / 16) * 100)
1302
1354
  } catch (error) {
1303
- this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to get night volume limit:`, error)
1355
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to parse night volume limit:`, error)
1304
1356
  return 100
1305
1357
  }
1306
1358
  }
@@ -1313,11 +1365,15 @@ export class YotoPlayerAccessory {
1313
1365
  this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Set night volume limit:`, value)
1314
1366
 
1315
1367
  try {
1316
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1368
+ // Refresh config if not cached
1369
+ if (!this.deviceConfig) {
1370
+ this.deviceConfig = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1371
+ }
1372
+
1317
1373
  // Map 0-100 to 0-16
1318
1374
  const limit = Math.round((Number(value) / 100) * 16)
1319
- config.config.nightMaxVolumeLimit = String(limit)
1320
- await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, config)
1375
+ this.deviceConfig.config.nightMaxVolumeLimit = String(limit)
1376
+ await this.platform.yotoApi.updateDeviceConfig(this.device.deviceId, this.deviceConfig)
1321
1377
  } catch (error) {
1322
1378
  this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to set night volume limit:`, error)
1323
1379
  throw new this.platform.api.hap.HapStatusError(
@@ -1331,13 +1387,16 @@ export class YotoPlayerAccessory {
1331
1387
  * @returns {Promise<CharacteristicValue>}
1332
1388
  */
1333
1389
  async getAmbientLightOn () {
1390
+ if (!this.deviceConfig) {
1391
+ return false // Default to off
1392
+ }
1393
+
1334
1394
  try {
1335
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1336
- const color = config.config.ambientColour || '#000000'
1337
- // Off if color is black (#000000)
1338
- return color !== '#000000' && color !== 'off'
1395
+ const color = this.deviceConfig.config.ambientColour || '000000'
1396
+ // Consider light "on" if not pure black
1397
+ return color !== '000000'
1339
1398
  } catch (error) {
1340
- this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to get ambient light state:`, error)
1399
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to parse ambient light state:`, error)
1341
1400
  return false
1342
1401
  }
1343
1402
  }
@@ -1350,11 +1409,16 @@ export class YotoPlayerAccessory {
1350
1409
  this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Set ambient light on:`, value)
1351
1410
 
1352
1411
  try {
1412
+ // Refresh config if not cached
1413
+ if (!this.deviceConfig) {
1414
+ this.deviceConfig = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1415
+ }
1416
+
1353
1417
  if (value) {
1354
- // Turn on - set to white or previous color
1355
- await this.mqtt.setAmbientLight(this.device.deviceId, 255, 255, 255)
1418
+ // Restore to a default color (warm white) when turning on
1419
+ await this.updateAmbientLightColor()
1356
1420
  } else {
1357
- // Turn off - set to black
1421
+ // Turn off by setting to black
1358
1422
  await this.mqtt.setAmbientLight(this.device.deviceId, 0, 0, 0)
1359
1423
  }
1360
1424
  } catch (error) {
@@ -1370,16 +1434,19 @@ export class YotoPlayerAccessory {
1370
1434
  * @returns {Promise<CharacteristicValue>}
1371
1435
  */
1372
1436
  async getAmbientLightHue () {
1437
+ if (!this.deviceConfig) {
1438
+ return 0 // Default hue
1439
+ }
1440
+
1373
1441
  try {
1374
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1375
- const hex = config.config.ambientColour || '#000000'
1442
+ const hex = this.deviceConfig.config.ambientColour || '000000'
1376
1443
  const { h } = this.hexToHsv(hex)
1377
1444
  if (isNaN(h)) {
1378
1445
  return 0
1379
1446
  }
1380
1447
  return h
1381
1448
  } catch (error) {
1382
- this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to get ambient light hue:`, error)
1449
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to parse ambient light hue:`, error)
1383
1450
  return 0
1384
1451
  }
1385
1452
  }
@@ -1400,16 +1467,19 @@ export class YotoPlayerAccessory {
1400
1467
  * @returns {Promise<CharacteristicValue>}
1401
1468
  */
1402
1469
  async getAmbientLightSaturation () {
1470
+ if (!this.deviceConfig) {
1471
+ return 0 // Default saturation
1472
+ }
1473
+
1403
1474
  try {
1404
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1405
- const hex = config.config.ambientColour || '#000000'
1475
+ const hex = this.deviceConfig.config.ambientColour || '000000'
1406
1476
  const { s } = this.hexToHsv(hex)
1407
1477
  if (isNaN(s)) {
1408
1478
  return 0
1409
1479
  }
1410
1480
  return s
1411
1481
  } catch (error) {
1412
- this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to get ambient light saturation:`, error)
1482
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to parse ambient light saturation:`, error)
1413
1483
  return 0
1414
1484
  }
1415
1485
  }
@@ -1430,18 +1500,21 @@ export class YotoPlayerAccessory {
1430
1500
  * @returns {Promise<CharacteristicValue>}
1431
1501
  */
1432
1502
  async getAmbientLightBrightness () {
1503
+ if (!this.deviceConfig) {
1504
+ return 0 // Default brightness
1505
+ }
1506
+
1433
1507
  try {
1434
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1435
- const hex = config.config.ambientColour
1508
+ const hex = this.deviceConfig.config.ambientColour || '000000'
1436
1509
  const { v } = this.hexToHsv(hex)
1437
1510
  const brightness = Math.round(v)
1438
1511
  if (isNaN(brightness)) {
1439
- return 100
1512
+ return 0
1440
1513
  }
1441
1514
  return brightness
1442
1515
  } catch (error) {
1443
- this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to get ambient brightness:`, error)
1444
- return 100
1516
+ this.log.debug(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to parse ambient brightness:`, error)
1517
+ return 0
1445
1518
  }
1446
1519
  }
1447
1520
 
@@ -1461,9 +1534,12 @@ export class YotoPlayerAccessory {
1461
1534
  */
1462
1535
  async updateAmbientLightColor () {
1463
1536
  try {
1464
- // Get current config to read existing HSV values
1465
- const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1466
- const currentHex = config.config.ambientColour || '#ffffff'
1537
+ // Refresh config if not cached
1538
+ if (!this.deviceConfig) {
1539
+ this.deviceConfig = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
1540
+ }
1541
+
1542
+ const currentHex = this.deviceConfig.config.ambientColour || '000000'
1467
1543
  const currentHsv = this.hexToHsv(currentHex)
1468
1544
 
1469
1545
  // Use pending values or current values
package/lib/yotoMqtt.js CHANGED
@@ -60,7 +60,7 @@ export class YotoMqtt extends EventEmitter {
60
60
  */
61
61
  async connect (accessToken, deviceId) {
62
62
  if (this.client) {
63
- this.log.warn(LOG_PREFIX.MQTT, 'Already connected, disconnecting first...')
63
+ this.log.debug(LOG_PREFIX.MQTT, 'Already connected, disconnecting first...')
64
64
  await this.disconnect()
65
65
  }
66
66
 
@@ -70,21 +70,7 @@ export class YotoMqtt extends EventEmitter {
70
70
  const clientId = `DASH${deviceId}`
71
71
  const username = `${deviceId}?x-amz-customauthorizer-name=${YOTO_MQTT_AUTH_NAME}`
72
72
 
73
- // TEMPORARY: Detailed debug logging for MQTT troubleshooting
74
- this.log.warn(LOG_PREFIX.MQTT, '='.repeat(60))
75
- this.log.warn(LOG_PREFIX.MQTT, 'MQTT CONNECTION DETAILS')
76
- this.log.warn(LOG_PREFIX.MQTT, '='.repeat(60))
77
- this.log.warn(LOG_PREFIX.MQTT, `Broker URL: ${this.brokerUrl}`)
78
- this.log.warn(LOG_PREFIX.MQTT, `Client ID: ${clientId}`)
79
- this.log.warn(LOG_PREFIX.MQTT, `Username: ${username}`)
80
- this.log.warn(LOG_PREFIX.MQTT, `Device ID: ${deviceId}`)
81
- this.log.warn(LOG_PREFIX.MQTT, `Token: ${accessToken}`)
82
- this.log.warn(LOG_PREFIX.MQTT, `Token length: ${accessToken.length}`)
83
- this.log.warn(LOG_PREFIX.MQTT, 'Port: 443')
84
- this.log.warn(LOG_PREFIX.MQTT, 'Protocol: wss')
85
- this.log.warn(LOG_PREFIX.MQTT, 'Keepalive: 300')
86
- this.log.warn(LOG_PREFIX.MQTT, `Connect Timeout: ${MQTT_CONNECT_TIMEOUT}ms`)
87
- this.log.warn(LOG_PREFIX.MQTT, '='.repeat(60))
73
+ this.log.debug(LOG_PREFIX.MQTT, `Connecting with client ID: ${clientId}`)
88
74
 
89
75
  this.client = mqtt.connect(this.brokerUrl, {
90
76
  keepalive: 300,
@@ -135,7 +121,7 @@ export class YotoMqtt extends EventEmitter {
135
121
  this.emit('disconnected')
136
122
 
137
123
  if (wasConnected) {
138
- this.log.warn(LOG_PREFIX.MQTT, ERROR_MESSAGES.MQTT_DISCONNECTED)
124
+ this.log.info(LOG_PREFIX.MQTT, ERROR_MESSAGES.MQTT_DISCONNECTED)
139
125
  this.handleReconnect()
140
126
  } else {
141
127
  this.log.error(LOG_PREFIX.MQTT, 'Connection closed before establishing connection')
@@ -156,18 +142,18 @@ export class YotoMqtt extends EventEmitter {
156
142
 
157
143
  this.client.on('offline', () => {
158
144
  this.connected = false
159
- this.log.warn(LOG_PREFIX.MQTT, 'MQTT client offline - connection failed or lost')
145
+ this.log.debug(LOG_PREFIX.MQTT, 'MQTT client offline - connection failed or lost')
160
146
 
161
147
  // Emit offline event
162
148
  this.emit('offline')
163
149
  })
164
150
 
165
151
  this.client.on('end', () => {
166
- this.log.warn(LOG_PREFIX.MQTT, 'MQTT client ended')
152
+ this.log.debug(LOG_PREFIX.MQTT, 'MQTT client ended')
167
153
  })
168
154
 
169
155
  this.client.on('disconnect', (packet) => {
170
- this.log.warn(LOG_PREFIX.MQTT, 'MQTT client disconnected:', packet)
156
+ this.log.debug(LOG_PREFIX.MQTT, 'MQTT client disconnected:', packet)
171
157
  })
172
158
 
173
159
  this.client.on('packetreceive', (packet) => {
@@ -309,10 +295,10 @@ export class YotoMqtt extends EventEmitter {
309
295
  // Request initial status after a short delay
310
296
  setTimeout(() => {
311
297
  this.requestStatus(deviceId).catch(err => {
312
- this.log.warn(LOG_PREFIX.MQTT, `Failed to request initial status for ${deviceId}:`, err)
298
+ this.log.debug(LOG_PREFIX.MQTT, `Failed to request initial status for ${deviceId}:`, err)
313
299
  })
314
300
  this.requestEvents(deviceId).catch(err => {
315
- this.log.warn(LOG_PREFIX.MQTT, `Failed to request initial events for ${deviceId}:`, err)
301
+ this.log.debug(LOG_PREFIX.MQTT, `Failed to request initial events for ${deviceId}:`, err)
316
302
  })
317
303
  }, INITIAL_STATUS_REQUEST_DELAY)
318
304
 
@@ -371,7 +357,7 @@ export class YotoMqtt extends EventEmitter {
371
357
  const deviceId = this.extractDeviceId(topic)
372
358
 
373
359
  if (!deviceId) {
374
- this.log.warn(LOG_PREFIX.MQTT, `Could not extract device ID from topic: ${topic}`)
360
+ this.log.debug(LOG_PREFIX.MQTT, `Could not extract device ID from topic: ${topic}`)
375
361
  return
376
362
  }
377
363
 
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.19",
4
+ "version": "0.0.21",
5
5
  "author": "Bret Comnes <bcomnes@gmail.com> (https://bret.io)",
6
6
  "bugs": {
7
7
  "url": "https://github.com/bcomnes/homebridge-yoto/issues"