homebridge-yoto 0.0.36 → 0.0.37
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/accessory.js +52 -43
- package/lib/platform.js +2 -2
- package/lib/sync-service-names.js +10 -7
- package/package.json +1 -1
package/lib/accessory.js
CHANGED
|
@@ -129,15 +129,15 @@ export class YotoPlayerAccessory {
|
|
|
129
129
|
: {}
|
|
130
130
|
|
|
131
131
|
return {
|
|
132
|
-
playback: getBooleanSetting(serviceConfig
|
|
133
|
-
volume: getBooleanSetting(serviceConfig
|
|
134
|
-
temperature: getBooleanSetting(serviceConfig
|
|
135
|
-
nightlight: getBooleanSetting(serviceConfig
|
|
136
|
-
cardSlot: getBooleanSetting(serviceConfig
|
|
137
|
-
nightMode: getBooleanSetting(serviceConfig
|
|
138
|
-
sleepTimer: getBooleanSetting(serviceConfig
|
|
139
|
-
bluetooth: getBooleanSetting(serviceConfig
|
|
140
|
-
volumeLimits: getBooleanSetting(serviceConfig
|
|
132
|
+
playback: getBooleanSetting(serviceConfig['playback'], getServiceDefault('playback')),
|
|
133
|
+
volume: getBooleanSetting(serviceConfig['volume'], getServiceDefault('volume')),
|
|
134
|
+
temperature: getBooleanSetting(serviceConfig['temperature'], getServiceDefault('temperature')),
|
|
135
|
+
nightlight: getBooleanSetting(serviceConfig['nightlight'], getServiceDefault('nightlight')),
|
|
136
|
+
cardSlot: getBooleanSetting(serviceConfig['cardSlot'], getServiceDefault('cardSlot')),
|
|
137
|
+
nightMode: getBooleanSetting(serviceConfig['nightMode'], getServiceDefault('nightMode')),
|
|
138
|
+
sleepTimer: getBooleanSetting(serviceConfig['sleepTimer'], getServiceDefault('sleepTimer')),
|
|
139
|
+
bluetooth: getBooleanSetting(serviceConfig['bluetooth'], getServiceDefault('bluetooth')),
|
|
140
|
+
volumeLimits: getBooleanSetting(serviceConfig['volumeLimits'], getServiceDefault('volumeLimits')),
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -663,10 +663,6 @@ export class YotoPlayerAccessory {
|
|
|
663
663
|
this.updateFirmwareVersionCharacteristic(status.firmwareVersion)
|
|
664
664
|
break
|
|
665
665
|
|
|
666
|
-
case 'maxVolume':
|
|
667
|
-
this.updateVolumeLimitProps(status.maxVolume)
|
|
668
|
-
break
|
|
669
|
-
|
|
670
666
|
case 'temperatureCelsius':
|
|
671
667
|
if (this.#deviceModel.capabilities.hasTemperatureSensor && status.temperatureCelsius !== null) {
|
|
672
668
|
this.updateTemperatureCharacteristic(status.temperatureCelsius)
|
|
@@ -687,8 +683,6 @@ export class YotoPlayerAccessory {
|
|
|
687
683
|
if (this.#deviceModel.capabilities.hasColoredNightlight) {
|
|
688
684
|
this.updateNightlightStatusCharacteristics()
|
|
689
685
|
}
|
|
690
|
-
// Day/night mode affects which volume limit is active
|
|
691
|
-
this.updateVolumeLimitProps(status.maxVolume)
|
|
692
686
|
break
|
|
693
687
|
|
|
694
688
|
case 'cardInsertionState':
|
|
@@ -697,6 +691,7 @@ export class YotoPlayerAccessory {
|
|
|
697
691
|
|
|
698
692
|
// Available but not yet mapped to characteristics
|
|
699
693
|
case 'activeCardId':
|
|
694
|
+
case 'maxVolume':
|
|
700
695
|
case 'powerSource':
|
|
701
696
|
case 'wifiStrength':
|
|
702
697
|
case 'freeDiskSpaceBytes':
|
|
@@ -873,12 +868,12 @@ export class YotoPlayerAccessory {
|
|
|
873
868
|
})
|
|
874
869
|
|
|
875
870
|
// Lifecycle events
|
|
876
|
-
this.#deviceModel.on('online', ({ reason }) => {
|
|
871
|
+
this.#deviceModel.on('online', ({ reason: _reason }) => {
|
|
877
872
|
// Platform logs online/offline events to avoid duplicate output.
|
|
878
873
|
this.updateOnlineStatusCharacteristic(true)
|
|
879
874
|
})
|
|
880
875
|
|
|
881
|
-
this.#deviceModel.on('offline', ({ reason }) => {
|
|
876
|
+
this.#deviceModel.on('offline', ({ reason: _reason }) => {
|
|
882
877
|
// Platform logs online/offline events to avoid duplicate output.
|
|
883
878
|
this.updateOnlineStatusCharacteristic(false)
|
|
884
879
|
})
|
|
@@ -926,6 +921,7 @@ export class YotoPlayerAccessory {
|
|
|
926
921
|
* @returns {Promise<CharacteristicValue>}
|
|
927
922
|
*/
|
|
928
923
|
async getVolume () {
|
|
924
|
+
this.#log.debug(LOG_PREFIX.ACCESSORY, `[${this.#device.name}] Get volume`)
|
|
929
925
|
return this.#deviceModel.status.volume
|
|
930
926
|
}
|
|
931
927
|
|
|
@@ -949,6 +945,10 @@ export class YotoPlayerAccessory {
|
|
|
949
945
|
? deviceModel.status.maxVolume
|
|
950
946
|
: 16
|
|
951
947
|
const steps = Math.max(0, Math.min(Math.round(requestedSteps), maxVolumeSteps))
|
|
948
|
+
this.#log.debug(
|
|
949
|
+
LOG_PREFIX.ACCESSORY,
|
|
950
|
+
`[${this.#device.name}] Set volume raw=${value} steps=${requestedSteps} -> ${steps} (max ${maxVolumeSteps}/16)`
|
|
951
|
+
)
|
|
952
952
|
|
|
953
953
|
// Track last non-zero volume for unmute
|
|
954
954
|
if (steps > 0) {
|
|
@@ -1560,6 +1560,10 @@ export class YotoPlayerAccessory {
|
|
|
1560
1560
|
*/
|
|
1561
1561
|
async getDayMaxVolume () {
|
|
1562
1562
|
const limit = this.#deviceModel.config.maxVolumeLimit
|
|
1563
|
+
this.#log.debug(
|
|
1564
|
+
LOG_PREFIX.ACCESSORY,
|
|
1565
|
+
`[${this.#device.name}] Get day max volume limit: ${limit}`
|
|
1566
|
+
)
|
|
1563
1567
|
return Number.isFinite(limit) ? limit : 16
|
|
1564
1568
|
}
|
|
1565
1569
|
|
|
@@ -1576,7 +1580,10 @@ export class YotoPlayerAccessory {
|
|
|
1576
1580
|
}
|
|
1577
1581
|
|
|
1578
1582
|
const limit = Math.max(0, Math.min(Math.round(requested), 16))
|
|
1579
|
-
this.#log.debug(
|
|
1583
|
+
this.#log.debug(
|
|
1584
|
+
LOG_PREFIX.ACCESSORY,
|
|
1585
|
+
`[${this.#device.name}] Set day max volume limit raw=${value} requested=${requested} -> ${limit}/16`
|
|
1586
|
+
)
|
|
1580
1587
|
await this.#deviceModel.updateConfig({ maxVolumeLimit: limit })
|
|
1581
1588
|
}
|
|
1582
1589
|
|
|
@@ -1586,6 +1593,10 @@ export class YotoPlayerAccessory {
|
|
|
1586
1593
|
*/
|
|
1587
1594
|
async getNightMaxVolume () {
|
|
1588
1595
|
const limit = this.#deviceModel.config.nightMaxVolumeLimit
|
|
1596
|
+
this.#log.debug(
|
|
1597
|
+
LOG_PREFIX.ACCESSORY,
|
|
1598
|
+
`[${this.#device.name}] Get night max volume limit: ${limit}`
|
|
1599
|
+
)
|
|
1589
1600
|
return Number.isFinite(limit) ? limit : 10
|
|
1590
1601
|
}
|
|
1591
1602
|
|
|
@@ -1602,7 +1613,10 @@ export class YotoPlayerAccessory {
|
|
|
1602
1613
|
}
|
|
1603
1614
|
|
|
1604
1615
|
const limit = Math.max(0, Math.min(Math.round(requested), 16))
|
|
1605
|
-
this.#log.debug(
|
|
1616
|
+
this.#log.debug(
|
|
1617
|
+
LOG_PREFIX.ACCESSORY,
|
|
1618
|
+
`[${this.#device.name}] Set night max volume limit raw=${value} requested=${requested} -> ${limit}/16`
|
|
1619
|
+
)
|
|
1606
1620
|
await this.#deviceModel.updateConfig({ nightMaxVolumeLimit: limit })
|
|
1607
1621
|
}
|
|
1608
1622
|
|
|
@@ -1634,30 +1648,15 @@ export class YotoPlayerAccessory {
|
|
|
1634
1648
|
this.#lastNonZeroVolume = volumeSteps
|
|
1635
1649
|
}
|
|
1636
1650
|
|
|
1651
|
+
const normalizedVolume = Number.isFinite(volumeSteps) ? volumeSteps : 0
|
|
1652
|
+
const clampedVolume = Math.max(0, Math.min(normalizedVolume, 16))
|
|
1653
|
+
this.#log.debug(
|
|
1654
|
+
LOG_PREFIX.ACCESSORY,
|
|
1655
|
+
`[${this.#device.name}] Update volume characteristic raw=${volumeSteps} -> ${clampedVolume}`
|
|
1656
|
+
)
|
|
1637
1657
|
this.volumeService
|
|
1638
1658
|
.getCharacteristic(Characteristic.Brightness)
|
|
1639
|
-
.updateValue(
|
|
1640
|
-
}
|
|
1641
|
-
|
|
1642
|
-
/**
|
|
1643
|
-
* Update volume limit props - adjusts max value based on day/night mode
|
|
1644
|
-
* @param {number} maxVolume - Maximum volume limit (0-16)
|
|
1645
|
-
*/
|
|
1646
|
-
updateVolumeLimitProps (maxVolume) {
|
|
1647
|
-
if (!this.volumeService) return
|
|
1648
|
-
|
|
1649
|
-
const { Characteristic } = this.#platform
|
|
1650
|
-
const maxVolumeSteps = Number.isFinite(maxVolume) ? maxVolume : 16
|
|
1651
|
-
const clampedMaxVolume = Math.max(0, Math.min(maxVolumeSteps, 16))
|
|
1652
|
-
this.volumeService
|
|
1653
|
-
.getCharacteristic(Characteristic.Brightness)
|
|
1654
|
-
.setProps({
|
|
1655
|
-
minValue: 0,
|
|
1656
|
-
maxValue: clampedMaxVolume,
|
|
1657
|
-
minStep: 1,
|
|
1658
|
-
})
|
|
1659
|
-
|
|
1660
|
-
this.#log.debug(`[${this.#device.name}] Volume max is ${clampedMaxVolume}/16`)
|
|
1659
|
+
.updateValue(clampedVolume)
|
|
1661
1660
|
}
|
|
1662
1661
|
|
|
1663
1662
|
/**
|
|
@@ -1920,16 +1919,26 @@ export class YotoPlayerAccessory {
|
|
|
1920
1919
|
|
|
1921
1920
|
if (this.dayMaxVolumeService) {
|
|
1922
1921
|
const limit = Number.isFinite(config.maxVolumeLimit) ? config.maxVolumeLimit : 16
|
|
1922
|
+
const clampedLimit = Math.max(0, Math.min(limit, 16))
|
|
1923
|
+
this.#log.debug(
|
|
1924
|
+
LOG_PREFIX.ACCESSORY,
|
|
1925
|
+
`[${this.#device.name}] Update day max volume characteristic raw=${limit} -> ${clampedLimit}`
|
|
1926
|
+
)
|
|
1923
1927
|
this.dayMaxVolumeService
|
|
1924
1928
|
.getCharacteristic(Characteristic.Brightness)
|
|
1925
|
-
.updateValue(
|
|
1929
|
+
.updateValue(clampedLimit)
|
|
1926
1930
|
}
|
|
1927
1931
|
|
|
1928
1932
|
if (this.nightMaxVolumeService) {
|
|
1929
1933
|
const limit = Number.isFinite(config.nightMaxVolumeLimit) ? config.nightMaxVolumeLimit : 10
|
|
1934
|
+
const clampedLimit = Math.max(0, Math.min(limit, 16))
|
|
1935
|
+
this.#log.debug(
|
|
1936
|
+
LOG_PREFIX.ACCESSORY,
|
|
1937
|
+
`[${this.#device.name}] Update night max volume characteristic raw=${limit} -> ${clampedLimit}`
|
|
1938
|
+
)
|
|
1930
1939
|
this.nightMaxVolumeService
|
|
1931
1940
|
.getCharacteristic(Characteristic.Brightness)
|
|
1932
|
-
.updateValue(
|
|
1941
|
+
.updateValue(clampedLimit)
|
|
1933
1942
|
}
|
|
1934
1943
|
}
|
|
1935
1944
|
|
package/lib/platform.js
CHANGED
|
@@ -70,7 +70,7 @@ export class YotoPlatform {
|
|
|
70
70
|
return
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
log.
|
|
73
|
+
log.debug('Authentication tokens found, initializing Yoto account...')
|
|
74
74
|
|
|
75
75
|
const { updateHomebridgeConfig, sessionId } = this
|
|
76
76
|
|
|
@@ -158,7 +158,7 @@ export class YotoPlatform {
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
try {
|
|
161
|
-
this.log.
|
|
161
|
+
this.log.debug('Starting Yoto account...')
|
|
162
162
|
|
|
163
163
|
// Listen for devices being added
|
|
164
164
|
this.yotoAccount.on('deviceAdded', async ({ deviceId }) => {
|
|
@@ -22,13 +22,16 @@ export function syncServiceNames ({
|
|
|
22
22
|
|
|
23
23
|
service.updateCharacteristic(Characteristic.Name, sanitizedName)
|
|
24
24
|
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
// Add ConfiguredName when missing so we avoid HAP warnings on update.
|
|
26
|
+
const configuredNameUuid = Characteristic.ConfiguredName.UUID
|
|
27
|
+
const hasConfiguredNameCharacteristic = service.characteristics
|
|
28
|
+
.some((characteristic) => characteristic.UUID === configuredNameUuid)
|
|
29
|
+
const hasConfiguredNameOptional = service.optionalCharacteristics
|
|
30
|
+
.some((characteristic) => characteristic.UUID === configuredNameUuid)
|
|
31
|
+
|
|
32
|
+
if (!hasConfiguredNameCharacteristic && !hasConfiguredNameOptional) {
|
|
33
|
+
service.addOptionalCharacteristic(Characteristic.ConfiguredName)
|
|
34
|
+
}
|
|
32
35
|
|
|
33
36
|
service.updateCharacteristic(Characteristic.ConfiguredName, sanitizedName)
|
|
34
37
|
}
|
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.37",
|
|
5
5
|
"author": "Bret Comnes <bcomnes@gmail.com> (https://bret.io)",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/bcomnes/homebridge-yoto/issues"
|