homebridge-bluos 1.1.3 → 1.1.5
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/CHANGELOG.md +14 -0
- package/README.md +1 -1
- package/homebridge-ui/public/index.html +35 -1
- package/homebridge-ui/public/index.js +37 -8
- package/homebridge-ui/server.js +8 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.1.5](https://github.com/tbaur/homebridge-bluos/compare/v1.1.4...v1.1.5) (2026-08-31)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* keep discover progress in view and leave volume opt-in ([#33](https://github.com/tbaur/homebridge-bluos/issues/33)) ([1dec836](https://github.com/tbaur/homebridge-bluos/commit/1dec8361f2a82d2a1c355f74c4258078bcb945d2))
|
|
9
|
+
|
|
10
|
+
## [1.1.4](https://github.com/tbaur/homebridge-bluos/compare/v1.1.3...v1.1.4) (2026-08-31)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* put the reboot switch on its own line ([#31](https://github.com/tbaur/homebridge-bluos/issues/31)) ([d721851](https://github.com/tbaur/homebridge-bluos/commit/d721851480d1d2e243b90ccfb1105087aed8aaa1))
|
|
16
|
+
|
|
3
17
|
## [1.1.3](https://github.com/tbaur/homebridge-bluos/compare/v1.1.2...v1.1.3) (2026-08-30)
|
|
4
18
|
|
|
5
19
|
|
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ Nothing needs enabling on the player, because the BluOS LAN API is always on. A
|
|
|
56
56
|
|
|
57
57
|
### 3. Configure
|
|
58
58
|
|
|
59
|
-
**Homebridge UI** (recommended): open the plugin settings and press **Discover Players**. Every zone that answers is listed
|
|
59
|
+
**Homebridge UI** (recommended): open the plugin settings and press **Discover Players**. Every zone that answers is listed. Tick the players and accessories you want, then press the Homebridge Save button.
|
|
60
60
|
|
|
61
61
|
Or in `config.json`:
|
|
62
62
|
|
|
@@ -10,7 +10,39 @@
|
|
|
10
10
|
-->
|
|
11
11
|
<style>
|
|
12
12
|
.bluos-intro { margin-bottom: 1rem; }
|
|
13
|
-
.bluos-toolbar {
|
|
13
|
+
.bluos-toolbar {
|
|
14
|
+
display: flex;
|
|
15
|
+
gap: .5rem;
|
|
16
|
+
align-items: flex-end;
|
|
17
|
+
flex-wrap: wrap;
|
|
18
|
+
position: sticky;
|
|
19
|
+
top: 0;
|
|
20
|
+
z-index: 5;
|
|
21
|
+
margin: 0 0 1rem;
|
|
22
|
+
padding: .55rem 0;
|
|
23
|
+
/* Frosted so cards do not show through while this bar stays on screen. */
|
|
24
|
+
background: rgba(128, 128, 128, .12);
|
|
25
|
+
backdrop-filter: blur(10px);
|
|
26
|
+
}
|
|
27
|
+
.bluos-busy {
|
|
28
|
+
display: inline-flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
align-self: center;
|
|
31
|
+
gap: .4rem;
|
|
32
|
+
font-size: .85rem;
|
|
33
|
+
white-space: nowrap;
|
|
34
|
+
}
|
|
35
|
+
.bluos-busy[hidden] { display: none !important; }
|
|
36
|
+
.bluos-busy::before {
|
|
37
|
+
content: '';
|
|
38
|
+
width: .85rem;
|
|
39
|
+
height: .85rem;
|
|
40
|
+
border: 2px solid currentColor;
|
|
41
|
+
border-right-color: transparent;
|
|
42
|
+
border-radius: 50%;
|
|
43
|
+
animation: bluos-spin .7s linear infinite;
|
|
44
|
+
}
|
|
45
|
+
@keyframes bluos-spin { to { transform: rotate(360deg); } }
|
|
14
46
|
.bluos-toolbar .form-group { margin-bottom: 0; }
|
|
15
47
|
.bluos-card { border: 1px solid rgba(128, 128, 128, .3); border-radius: .5rem; padding: .85rem 1rem; margin-bottom: .75rem; }
|
|
16
48
|
.bluos-card.is-selected { border-color: #007bff; box-shadow: 0 0 0 1px rgba(0, 123, 255, .35); }
|
|
@@ -20,6 +52,7 @@
|
|
|
20
52
|
.bluos-badge { font-size: .7rem; text-transform: uppercase; letter-spacing: .03em; padding: .12rem .4rem; border-radius: .25rem; background: rgba(128, 128, 128, .2); }
|
|
21
53
|
.bluos-badge.warn { background: rgba(255, 193, 7, .28); }
|
|
22
54
|
.bluos-options { display: flex; gap: 1.1rem; flex-wrap: wrap; margin-top: .6rem; }
|
|
55
|
+
.bluos-options-reboot { flex-basis: 100%; }
|
|
23
56
|
.bluos-check { display: inline-flex; align-items: center; gap: .4rem; margin: 0; }
|
|
24
57
|
.bluos-check input { margin: 0; }
|
|
25
58
|
.bluos-check label { margin: 0; }
|
|
@@ -45,6 +78,7 @@
|
|
|
45
78
|
|
|
46
79
|
<div class="bluos-toolbar">
|
|
47
80
|
<button class="btn btn-primary" id="discover">Discover Players</button>
|
|
81
|
+
<span id="discover-status" class="bluos-busy text-muted" hidden></span>
|
|
48
82
|
<div class="form-group">
|
|
49
83
|
<label for="timeout" class="mb-0" style="font-size: .8rem;">Listen for</label>
|
|
50
84
|
<select class="form-control form-control-sm" id="timeout">
|
|
@@ -157,7 +157,10 @@
|
|
|
157
157
|
derivedIdentity: player.derivedIdentity,
|
|
158
158
|
online: true,
|
|
159
159
|
selected: false,
|
|
160
|
-
|
|
160
|
+
// Discover listing a zone is not a request for a HomeKit accessory.
|
|
161
|
+
// Volume is a fan tile; leaving it ticked on every new player would
|
|
162
|
+
// mint one per zone the moment the user pressed Save.
|
|
163
|
+
volumeSlider: false,
|
|
161
164
|
mute: player.suggested.mute,
|
|
162
165
|
battery: player.suggested.battery,
|
|
163
166
|
reboot: player.suggested.reboot,
|
|
@@ -396,12 +399,14 @@
|
|
|
396
399
|
(value) => { player.battery = value },
|
|
397
400
|
))
|
|
398
401
|
}
|
|
399
|
-
|
|
400
|
-
'Reboot switch (reboots this player, and any zone
|
|
402
|
+
const reboot = checkbox(
|
|
403
|
+
'Reboot switch (reboots this player, and any zone on the same device)',
|
|
401
404
|
player.reboot,
|
|
402
405
|
false,
|
|
403
406
|
(value) => { player.reboot = value },
|
|
404
|
-
)
|
|
407
|
+
)
|
|
408
|
+
reboot.className += ' bluos-options-reboot'
|
|
409
|
+
options.append(reboot)
|
|
405
410
|
card.append(options)
|
|
406
411
|
|
|
407
412
|
if (player.selected) {
|
|
@@ -452,9 +457,30 @@
|
|
|
452
457
|
|
|
453
458
|
// --- Actions ------------------------------------------------------------
|
|
454
459
|
|
|
460
|
+
let requestInFlight = false
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Show progress next to Discover, which is where the user just pressed.
|
|
464
|
+
*
|
|
465
|
+
* Homebridge's spinner is centred on the whole settings page. With a long
|
|
466
|
+
* list of players that centre sits below the fold, so a user who pressed
|
|
467
|
+
* Discover would see nothing happen for several seconds.
|
|
468
|
+
*/
|
|
469
|
+
function setBusy(isBusy, message) {
|
|
470
|
+
requestInFlight = isBusy
|
|
471
|
+
byId('discover').disabled = isBusy
|
|
472
|
+
byId('manual-probe').disabled = isBusy
|
|
473
|
+
const status = byId('discover-status')
|
|
474
|
+
status.hidden = !isBusy
|
|
475
|
+
status.textContent = isBusy ? message : ''
|
|
476
|
+
}
|
|
477
|
+
|
|
455
478
|
async function discover() {
|
|
479
|
+
if (requestInFlight) {
|
|
480
|
+
return
|
|
481
|
+
}
|
|
456
482
|
const timeoutSec = Number(byId('timeout').value) || DEFAULT_TIMEOUT_SEC
|
|
457
|
-
|
|
483
|
+
setBusy(true, 'Listening for players…')
|
|
458
484
|
try {
|
|
459
485
|
const response = await homebridge.request('/discover', { timeoutSec })
|
|
460
486
|
const found = Array.isArray(response && response.players) ? response.players : []
|
|
@@ -479,11 +505,14 @@
|
|
|
479
505
|
} catch (error) {
|
|
480
506
|
homebridge.toast.error(describeError(error), 'Discovery failed')
|
|
481
507
|
} finally {
|
|
482
|
-
|
|
508
|
+
setBusy(false)
|
|
483
509
|
}
|
|
484
510
|
}
|
|
485
511
|
|
|
486
512
|
async function probe() {
|
|
513
|
+
if (requestInFlight) {
|
|
514
|
+
return
|
|
515
|
+
}
|
|
487
516
|
const host = byId('manual-host').value.trim()
|
|
488
517
|
const portValue = byId('manual-port').value.trim()
|
|
489
518
|
if (host.length === 0) {
|
|
@@ -494,7 +523,7 @@
|
|
|
494
523
|
if (portValue.length > 0) {
|
|
495
524
|
payload.port = Number(portValue)
|
|
496
525
|
}
|
|
497
|
-
|
|
526
|
+
setBusy(true, 'Probing…')
|
|
498
527
|
try {
|
|
499
528
|
const response = await homebridge.request('/probe', payload)
|
|
500
529
|
const found = Array.isArray(response && response.players) ? response.players : []
|
|
@@ -510,7 +539,7 @@
|
|
|
510
539
|
} catch (error) {
|
|
511
540
|
homebridge.toast.error(describeError(error), 'Probe failed')
|
|
512
541
|
} finally {
|
|
513
|
-
|
|
542
|
+
setBusy(false)
|
|
514
543
|
}
|
|
515
544
|
}
|
|
516
545
|
|
package/homebridge-ui/server.js
CHANGED
|
@@ -155,11 +155,14 @@ class BluOSUiServer extends HomebridgePluginUiServer {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
/**
|
|
158
|
-
* Shape a discovered player for the page, including
|
|
158
|
+
* Shape a discovered player for the page, including opt-in accessory defaults.
|
|
159
159
|
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
160
|
+
* Volume, mute and reboot stay off until the user asks for them: Discover
|
|
161
|
+
* listing a zone is not a request for a HomeKit accessory. A player with a
|
|
162
|
+
* battery pack is offered that sensor, because it is a reading rather than a
|
|
163
|
+
* control. A player that reports a fixed output cannot take a slider at all,
|
|
164
|
+
* which the page learns from `fixedVolume`. A player with no usable MAC is
|
|
165
|
+
* given a generated identity here, once, so that it stays stable from then on.
|
|
163
166
|
*/
|
|
164
167
|
describe(player) {
|
|
165
168
|
const api = this.loadApi()
|
|
@@ -176,7 +179,7 @@ class BluOSUiServer extends HomebridgePluginUiServer {
|
|
|
176
179
|
hasBattery: player.hasBattery === true,
|
|
177
180
|
derivedIdentity: !(player.mac && player.mac.length > 0),
|
|
178
181
|
suggested: {
|
|
179
|
-
volumeSlider:
|
|
182
|
+
volumeSlider: false,
|
|
180
183
|
mute: false,
|
|
181
184
|
battery: player.hasBattery === true,
|
|
182
185
|
// Never suggested. Restarting a player interrupts whatever it is doing,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-bluos",
|
|
3
3
|
"displayName": "Homebridge BluOS",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.5",
|
|
5
5
|
"description": "Homebridge plugin for BluOS players — per-zone volume, mute, volume-preset and battery accessories over the LAN Custom Integration API. Verified on NAD and Bluesound hardware",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|