homebridge-yoto 0.0.15 → 0.0.17
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/playerAccessory.js +70 -38
- package/lib/types.js +53 -33
- package/package.json +1 -1
package/lib/playerAccessory.js
CHANGED
|
@@ -511,13 +511,17 @@ export class YotoPlayerAccessory {
|
|
|
511
511
|
|
|
512
512
|
/**
|
|
513
513
|
* Handle status update from MQTT
|
|
514
|
-
* @param {YotoDeviceStatus
|
|
514
|
+
* @param {YotoDeviceStatus | {status: YotoDeviceStatus}} statusMessage - Status data or wrapped status
|
|
515
515
|
*/
|
|
516
|
-
handleStatusUpdate (
|
|
517
|
-
this.log.
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
516
|
+
handleStatusUpdate (statusMessage) {
|
|
517
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Raw MQTT status message:`, JSON.stringify(statusMessage, null, 2))
|
|
518
|
+
|
|
519
|
+
// Unwrap status if it's nested under a 'status' property
|
|
520
|
+
const status = /** @type {YotoDeviceStatus} */ ('status' in statusMessage ? statusMessage.status : statusMessage)
|
|
521
|
+
|
|
522
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Unwrapped status - batteryLevel:`, status.batteryLevel)
|
|
523
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Unwrapped status - userVolume:`, status.userVolume)
|
|
524
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Unwrapped status - volume:`, status.volume)
|
|
521
525
|
|
|
522
526
|
this.currentStatus = status
|
|
523
527
|
this.lastUpdateTime = Date.now()
|
|
@@ -529,10 +533,15 @@ export class YotoPlayerAccessory {
|
|
|
529
533
|
|
|
530
534
|
/**
|
|
531
535
|
* Handle playback events update from MQTT
|
|
532
|
-
* @param {YotoPlaybackEvents
|
|
536
|
+
* @param {YotoPlaybackEvents | {events: YotoPlaybackEvents}} eventsMessage - Playback events or wrapped events
|
|
533
537
|
*/
|
|
534
|
-
handleEventsUpdate (
|
|
535
|
-
this.log.
|
|
538
|
+
handleEventsUpdate (eventsMessage) {
|
|
539
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Raw MQTT events message:`, JSON.stringify(eventsMessage, null, 2))
|
|
540
|
+
|
|
541
|
+
// Unwrap events if it's nested under an 'events' property
|
|
542
|
+
const events = /** @type {YotoPlaybackEvents} */ ('events' in eventsMessage ? eventsMessage.events : eventsMessage)
|
|
543
|
+
|
|
544
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Unwrapped events - cardId:`, events.cardId)
|
|
536
545
|
this.currentEvents = events
|
|
537
546
|
this.lastUpdateTime = Date.now()
|
|
538
547
|
this.accessory.context.lastEvents = events
|
|
@@ -551,7 +560,7 @@ export class YotoPlayerAccessory {
|
|
|
551
560
|
* @param {import('./types.js').MqttCommandResponse} response - Command response
|
|
552
561
|
*/
|
|
553
562
|
handleCommandResponse (response) {
|
|
554
|
-
this.log.
|
|
563
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Command response:`, response)
|
|
555
564
|
}
|
|
556
565
|
|
|
557
566
|
/**
|
|
@@ -562,16 +571,17 @@ export class YotoPlayerAccessory {
|
|
|
562
571
|
return
|
|
563
572
|
}
|
|
564
573
|
|
|
565
|
-
// Update volume
|
|
566
|
-
if (this.speakerService) {
|
|
574
|
+
// Update volume from events, not status
|
|
575
|
+
if (this.speakerService && this.currentEvents?.volume !== undefined) {
|
|
576
|
+
const volume = Number(this.currentEvents.volume) || 0
|
|
567
577
|
this.speakerService.updateCharacteristic(
|
|
568
578
|
this.platform.Characteristic.Volume,
|
|
569
|
-
|
|
579
|
+
volume
|
|
570
580
|
)
|
|
571
581
|
}
|
|
572
582
|
|
|
573
583
|
// Update battery
|
|
574
|
-
if (this.batteryService) {
|
|
584
|
+
if (this.batteryService && this.currentStatus.batteryLevel !== undefined) {
|
|
575
585
|
this.batteryService.updateCharacteristic(
|
|
576
586
|
this.platform.Characteristic.BatteryLevel,
|
|
577
587
|
this.currentStatus.batteryLevel
|
|
@@ -603,7 +613,7 @@ export class YotoPlayerAccessory {
|
|
|
603
613
|
}
|
|
604
614
|
|
|
605
615
|
// Update display brightness
|
|
606
|
-
if (this.displayService) {
|
|
616
|
+
if (this.displayService && this.currentStatus.dnowBrightness !== undefined) {
|
|
607
617
|
const isOn = this.currentStatus.dnowBrightness > 0
|
|
608
618
|
this.displayService.updateCharacteristic(
|
|
609
619
|
this.platform.Characteristic.On,
|
|
@@ -619,7 +629,7 @@ export class YotoPlayerAccessory {
|
|
|
619
629
|
}
|
|
620
630
|
|
|
621
631
|
// Update advanced control switches
|
|
622
|
-
if (this.bluetoothSwitch) {
|
|
632
|
+
if (this.bluetoothSwitch && this.currentStatus.bluetoothHp !== undefined) {
|
|
623
633
|
const bluetoothEnabled = this.currentStatus.bluetoothHp
|
|
624
634
|
this.bluetoothSwitch.updateCharacteristic(
|
|
625
635
|
this.platform.Characteristic.On,
|
|
@@ -627,7 +637,7 @@ export class YotoPlayerAccessory {
|
|
|
627
637
|
)
|
|
628
638
|
}
|
|
629
639
|
|
|
630
|
-
if (this.btHeadphonesSwitch) {
|
|
640
|
+
if (this.btHeadphonesSwitch && this.currentStatus.bluetoothHp !== undefined) {
|
|
631
641
|
const btHeadphonesEnabled = this.currentStatus.bluetoothHp
|
|
632
642
|
this.btHeadphonesSwitch.updateCharacteristic(
|
|
633
643
|
this.platform.Characteristic.On,
|
|
@@ -789,15 +799,16 @@ export class YotoPlayerAccessory {
|
|
|
789
799
|
* @returns {Promise<CharacteristicValue>}
|
|
790
800
|
*/
|
|
791
801
|
async getVolume () {
|
|
792
|
-
this.log.
|
|
793
|
-
this.log.
|
|
802
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getVolume - currentEvents:`, this.currentEvents)
|
|
803
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getVolume - events.volume:`, this.currentEvents?.volume)
|
|
794
804
|
|
|
795
|
-
|
|
796
|
-
|
|
805
|
+
// Volume comes from events, not status
|
|
806
|
+
if (!this.currentEvents || this.currentEvents.volume === undefined) {
|
|
807
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getVolume - no volume in events, returning default: 50`)
|
|
797
808
|
return 50
|
|
798
809
|
}
|
|
799
|
-
const volume = Number(this.
|
|
800
|
-
this.log.
|
|
810
|
+
const volume = Number(this.currentEvents.volume) || 50
|
|
811
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getVolume - returning volume:`, volume)
|
|
801
812
|
return volume
|
|
802
813
|
}
|
|
803
814
|
|
|
@@ -823,10 +834,11 @@ export class YotoPlayerAccessory {
|
|
|
823
834
|
* @returns {Promise<CharacteristicValue>}
|
|
824
835
|
*/
|
|
825
836
|
async getMute () {
|
|
826
|
-
|
|
837
|
+
// Volume comes from events, not status
|
|
838
|
+
if (!this.currentEvents || this.currentEvents.volume === undefined) {
|
|
827
839
|
return false
|
|
828
840
|
}
|
|
829
|
-
return Number(this.
|
|
841
|
+
return Number(this.currentEvents.volume) === 0
|
|
830
842
|
}
|
|
831
843
|
|
|
832
844
|
/**
|
|
@@ -842,7 +854,7 @@ export class YotoPlayerAccessory {
|
|
|
842
854
|
await this.mqtt.setVolume(this.device.deviceId, 0)
|
|
843
855
|
} else {
|
|
844
856
|
// Unmute - restore to a reasonable volume if currently 0
|
|
845
|
-
const currentVolume = this.
|
|
857
|
+
const currentVolume = this.currentEvents?.volume ? Number(this.currentEvents.volume) : 0
|
|
846
858
|
const targetVolume = currentVolume === 0 ? 50 : currentVolume
|
|
847
859
|
await this.mqtt.setVolume(this.device.deviceId, targetVolume)
|
|
848
860
|
}
|
|
@@ -859,15 +871,15 @@ export class YotoPlayerAccessory {
|
|
|
859
871
|
* @returns {Promise<CharacteristicValue>}
|
|
860
872
|
*/
|
|
861
873
|
async getBatteryLevel () {
|
|
862
|
-
this.log.
|
|
863
|
-
this.log.
|
|
874
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getBatteryLevel - currentStatus:`, this.currentStatus)
|
|
875
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getBatteryLevel - batteryLevel:`, this.currentStatus?.batteryLevel)
|
|
864
876
|
|
|
865
877
|
if (!this.currentStatus || this.currentStatus.batteryLevel === undefined) {
|
|
866
|
-
this.log.
|
|
878
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getBatteryLevel - returning default: 100`)
|
|
867
879
|
return 100
|
|
868
880
|
}
|
|
869
881
|
const battery = Number(this.currentStatus.batteryLevel) || 100
|
|
870
|
-
this.log.
|
|
882
|
+
this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] getBatteryLevel - returning:`, battery)
|
|
871
883
|
return battery
|
|
872
884
|
}
|
|
873
885
|
|
|
@@ -951,7 +963,7 @@ export class YotoPlayerAccessory {
|
|
|
951
963
|
* @returns {Promise<CharacteristicValue>}
|
|
952
964
|
*/
|
|
953
965
|
async getDisplayOn () {
|
|
954
|
-
if (!this.currentStatus) {
|
|
966
|
+
if (!this.currentStatus || this.currentStatus.dnowBrightness === undefined) {
|
|
955
967
|
return true
|
|
956
968
|
}
|
|
957
969
|
return this.currentStatus.dnowBrightness > 0
|
|
@@ -992,12 +1004,16 @@ export class YotoPlayerAccessory {
|
|
|
992
1004
|
* @returns {Promise<CharacteristicValue>}
|
|
993
1005
|
*/
|
|
994
1006
|
async getDisplayBrightness () {
|
|
995
|
-
if (!this.currentStatus) {
|
|
1007
|
+
if (!this.currentStatus || this.currentStatus.dnowBrightness === undefined) {
|
|
996
1008
|
return 100
|
|
997
1009
|
}
|
|
998
1010
|
|
|
999
1011
|
// Use current brightness value (0-100)
|
|
1000
|
-
|
|
1012
|
+
const brightness = Number(this.currentStatus.dnowBrightness)
|
|
1013
|
+
if (isNaN(brightness)) {
|
|
1014
|
+
return 100
|
|
1015
|
+
}
|
|
1016
|
+
return Math.min(100, Math.max(0, brightness))
|
|
1001
1017
|
}
|
|
1002
1018
|
|
|
1003
1019
|
/**
|
|
@@ -1031,7 +1047,7 @@ export class YotoPlayerAccessory {
|
|
|
1031
1047
|
* @returns {Promise<CharacteristicValue>}
|
|
1032
1048
|
*/
|
|
1033
1049
|
async getBluetoothEnabled () {
|
|
1034
|
-
if (!this.currentStatus) {
|
|
1050
|
+
if (!this.currentStatus || this.currentStatus.bluetoothHp === undefined) {
|
|
1035
1051
|
return false
|
|
1036
1052
|
}
|
|
1037
1053
|
return this.currentStatus.bluetoothHp
|
|
@@ -1091,7 +1107,7 @@ export class YotoPlayerAccessory {
|
|
|
1091
1107
|
* @returns {Promise<CharacteristicValue>}
|
|
1092
1108
|
*/
|
|
1093
1109
|
async getBtHeadphonesEnabled () {
|
|
1094
|
-
if (!this.currentStatus) {
|
|
1110
|
+
if (!this.currentStatus || this.currentStatus.bluetoothHp === undefined) {
|
|
1095
1111
|
return false
|
|
1096
1112
|
}
|
|
1097
1113
|
return this.currentStatus.bluetoothHp
|
|
@@ -1220,6 +1236,9 @@ export class YotoPlayerAccessory {
|
|
|
1220
1236
|
try {
|
|
1221
1237
|
const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
|
|
1222
1238
|
const limit = parseInt(config.config.maxVolumeLimit || '16')
|
|
1239
|
+
if (isNaN(limit)) {
|
|
1240
|
+
return 100
|
|
1241
|
+
}
|
|
1223
1242
|
// Map 0-16 to 0-100
|
|
1224
1243
|
return Math.round((limit / 16) * 100)
|
|
1225
1244
|
} catch (error) {
|
|
@@ -1275,6 +1294,9 @@ export class YotoPlayerAccessory {
|
|
|
1275
1294
|
try {
|
|
1276
1295
|
const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
|
|
1277
1296
|
const limit = parseInt(config.config.nightMaxVolumeLimit || '16')
|
|
1297
|
+
if (isNaN(limit)) {
|
|
1298
|
+
return 100
|
|
1299
|
+
}
|
|
1278
1300
|
// Map 0-16 to 0-100
|
|
1279
1301
|
return Math.round((limit / 16) * 100)
|
|
1280
1302
|
} catch (error) {
|
|
@@ -1352,6 +1374,9 @@ export class YotoPlayerAccessory {
|
|
|
1352
1374
|
const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
|
|
1353
1375
|
const hex = config.config.ambientColour || '#000000'
|
|
1354
1376
|
const { h } = this.hexToHsv(hex)
|
|
1377
|
+
if (isNaN(h)) {
|
|
1378
|
+
return 0
|
|
1379
|
+
}
|
|
1355
1380
|
return h
|
|
1356
1381
|
} catch (error) {
|
|
1357
1382
|
this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to get ambient light hue:`, error)
|
|
@@ -1379,6 +1404,9 @@ export class YotoPlayerAccessory {
|
|
|
1379
1404
|
const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
|
|
1380
1405
|
const hex = config.config.ambientColour || '#000000'
|
|
1381
1406
|
const { s } = this.hexToHsv(hex)
|
|
1407
|
+
if (isNaN(s)) {
|
|
1408
|
+
return 0
|
|
1409
|
+
}
|
|
1382
1410
|
return s
|
|
1383
1411
|
} catch (error) {
|
|
1384
1412
|
this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to get ambient light saturation:`, error)
|
|
@@ -1404,11 +1432,15 @@ export class YotoPlayerAccessory {
|
|
|
1404
1432
|
async getAmbientLightBrightness () {
|
|
1405
1433
|
try {
|
|
1406
1434
|
const config = await this.platform.yotoApi.getDeviceConfig(this.device.deviceId)
|
|
1407
|
-
const hex = config.config.ambientColour
|
|
1435
|
+
const hex = config.config.ambientColour
|
|
1408
1436
|
const { v } = this.hexToHsv(hex)
|
|
1409
|
-
|
|
1437
|
+
const brightness = Math.round(v)
|
|
1438
|
+
if (isNaN(brightness)) {
|
|
1439
|
+
return 100
|
|
1440
|
+
}
|
|
1441
|
+
return brightness
|
|
1410
1442
|
} catch (error) {
|
|
1411
|
-
this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to get ambient
|
|
1443
|
+
this.log.error(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Failed to get ambient brightness:`, error)
|
|
1412
1444
|
return 100
|
|
1413
1445
|
}
|
|
1414
1446
|
}
|
package/lib/types.js
CHANGED
|
@@ -15,43 +15,63 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
+
* YotoDeviceStatus - ACTUAL structure from MQTT /device/{id}/data/status
|
|
19
|
+
* Note: This differs from the documented API schema
|
|
18
20
|
* @typedef {Object} YotoDeviceStatus
|
|
19
|
-
* @property {number}
|
|
20
|
-
* @property {string}
|
|
21
|
-
* @property {
|
|
22
|
-
* @property {number}
|
|
23
|
-
* @property {
|
|
24
|
-
* @property {number}
|
|
25
|
-
* @property {number}
|
|
26
|
-
* @property {number}
|
|
27
|
-
* @property {number}
|
|
28
|
-
* @property {
|
|
29
|
-
* @property {number}
|
|
30
|
-
* @property {number}
|
|
31
|
-
* @property {
|
|
32
|
-
* @property {number}
|
|
33
|
-
* @property {number}
|
|
34
|
-
* @property {
|
|
35
|
-
* @property {
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* @property {
|
|
40
|
-
* @property {string}
|
|
41
|
-
* @property {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
21
|
+
* @property {number} battery - Raw battery voltage (e.g., 3693)
|
|
22
|
+
* @property {string} [powerCaps] - Power capability flags (e.g., '0x02')
|
|
23
|
+
* @property {number} batteryLevel - Battery level percentage (0-100)
|
|
24
|
+
* @property {number} batteryTemp - Battery temperature
|
|
25
|
+
* @property {string} batteryData - Battery data string (e.g., '0:0:0')
|
|
26
|
+
* @property {number} batteryLevelRaw - Raw battery level value
|
|
27
|
+
* @property {number} free - Free memory
|
|
28
|
+
* @property {number} freeDMA - Free DMA memory
|
|
29
|
+
* @property {number} free32 - Free 32-bit memory
|
|
30
|
+
* @property {number} upTime - Device uptime in seconds
|
|
31
|
+
* @property {number} utcTime - Current UTC time (Unix timestamp)
|
|
32
|
+
* @property {number} aliveTime - Time device has been alive
|
|
33
|
+
* @property {number} accelTemp - Accelerometer temperature in Celsius
|
|
34
|
+
* @property {number} [qiOtp] - Qi charging related field
|
|
35
|
+
* @property {number} [errorsLogged] - Number of errors logged
|
|
36
|
+
* @property {string} nightlightMode - Nightlight mode (e.g., 'off')
|
|
37
|
+
* @property {string} temp - Temperature data string (e.g., '1014:23:318')
|
|
38
|
+
*
|
|
39
|
+
* Note: Volume information comes from events, not status!
|
|
40
|
+
* The following documented fields may exist but haven't been observed in v3 players:
|
|
41
|
+
* @property {number} [statusVersion] - Status data version
|
|
42
|
+
* @property {string} [fwVersion] - Firmware version
|
|
43
|
+
* @property {string} [productType] - Product type identifier
|
|
44
|
+
* @property {number} [als] - Ambient light sensor reading
|
|
45
|
+
* @property {number} [freeDisk] - Free disk space in bytes
|
|
46
|
+
* @property {number} [shutdownTimeout] - Auto-shutdown timeout in seconds
|
|
47
|
+
* @property {number} [dbatTimeout] - Display battery timeout
|
|
48
|
+
* @property {number} [charging] - Charging state (0=not charging, 1=charging)
|
|
49
|
+
* @property {string | null} [activeCard] - Currently active card ID or null
|
|
50
|
+
* @property {number} [cardInserted] - Card insertion state (0=none, 1=physical, 2=remote)
|
|
51
|
+
* @property {number} [playingStatus] - Playing status code
|
|
52
|
+
* @property {boolean} [headphones] - Whether headphones are connected
|
|
53
|
+
* @property {number} [dnowBrightness] - Current display brightness
|
|
54
|
+
* @property {number} [dayBright] - Day mode brightness setting
|
|
55
|
+
* @property {number} [nightBright] - Night mode brightness setting
|
|
56
|
+
* @property {boolean} [bluetoothHp] - Bluetooth headphones enabled
|
|
57
|
+
* @property {number} [volume] - System volume level (may be in events instead)
|
|
58
|
+
* @property {number} [userVolume] - User volume level 0-100 (may be in events instead)
|
|
59
|
+
* @property {'12' | '24'} [timeFormat] - Time format preference
|
|
60
|
+
* @property {number} [day] - Day mode (0=night, 1=day, -1=unknown)
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* YotoPlaybackEvents - From MQTT /device/{id}/data/events
|
|
45
65
|
* @typedef {Object} YotoPlaybackEvents
|
|
46
66
|
* @property {string} repeatAll - Repeat all setting ("true" or "false")
|
|
47
67
|
* @property {string} streaming - Streaming active ("true" or "false")
|
|
48
|
-
* @property {string} volume - Current volume level
|
|
49
|
-
* @property {string} volumeMax - Maximum volume level
|
|
68
|
+
* @property {string} volume - Current volume level (0-100 as string)
|
|
69
|
+
* @property {string} volumeMax - Maximum volume level (0-100 as string)
|
|
50
70
|
* @property {string} playbackWait - Playback wait state ("true" or "false")
|
|
51
71
|
* @property {string} sleepTimerActive - Sleep timer active ("true" or "false")
|
|
52
|
-
* @property {string} eventUtc - Event timestamp (Unix timestamp)
|
|
53
|
-
* @property {string} trackLength - Track duration in seconds
|
|
54
|
-
* @property {string} position - Current playback position in seconds
|
|
72
|
+
* @property {string} eventUtc - Event timestamp (Unix timestamp as string)
|
|
73
|
+
* @property {string} trackLength - Track duration in seconds (as string)
|
|
74
|
+
* @property {string} position - Current playback position in seconds (as string)
|
|
55
75
|
* @property {string} cardId - Active card ID
|
|
56
76
|
* @property {string} source - Playback source (e.g., "card", "remote", "MQTT")
|
|
57
77
|
* @property {string} cardUpdatedAt - Card last updated timestamp (ISO8601)
|
|
@@ -59,8 +79,8 @@
|
|
|
59
79
|
* @property {string} chapterKey - Current chapter key
|
|
60
80
|
* @property {string} trackTitle - Current track title
|
|
61
81
|
* @property {string} trackKey - Current track key
|
|
62
|
-
* @property {string} playbackStatus - Playback status ("playing", "paused", "stopped")
|
|
63
|
-
* @property {string} sleepTimerSeconds -
|
|
82
|
+
* @property {string} playbackStatus - Playback status (e.g., "playing", "paused", "stopped")
|
|
83
|
+
* @property {string} sleepTimerSeconds - Remaining sleep timer seconds (as string)
|
|
64
84
|
*/
|
|
65
85
|
|
|
66
86
|
/**
|
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.17",
|
|
5
5
|
"author": "Bret Comnes <bcomnes@gmail.com> (https://bret.io)",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/bcomnes/homebridge-yoto/issues"
|