homebridge-sonos-scenes 0.1.3 → 0.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/README.md +5 -0
- package/broker/.env.example +5 -0
- package/broker/README.md +41 -0
- package/broker/package.json +15 -0
- package/broker/src/server.mjs +151 -0
- package/dist/src/accessories/sceneSpeaker.d.ts +18 -0
- package/dist/src/accessories/sceneSpeaker.js +83 -0
- package/dist/src/accessories/sceneSpeaker.js.map +1 -0
- package/dist/src/cloud/brokerClient.d.ts +3 -0
- package/dist/src/cloud/brokerClient.js.map +1 -1
- package/dist/src/platform.d.ts +11 -1
- package/dist/src/platform.js +94 -22
- package/dist/src/platform.js.map +1 -1
- package/dist/src/transports/localTransport.d.ts +9 -0
- package/dist/src/transports/localTransport.js +97 -0
- package/dist/src/transports/localTransport.js.map +1 -1
- package/dist/src/types.d.ts +6 -0
- package/dist/src/ui/serverApi.d.ts +7 -0
- package/dist/src/ui/serverApi.js +26 -0
- package/dist/src/ui/serverApi.js.map +1 -1
- package/docs/cloud-broker.md +2 -0
- package/homebridge-ui/public/index.html +566 -36
- package/homebridge-ui/server.js +9 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -41,6 +41,9 @@ examples/
|
|
|
41
41
|
sample-topology.json
|
|
42
42
|
docs/
|
|
43
43
|
cloud-broker.md
|
|
44
|
+
broker/
|
|
45
|
+
README.md
|
|
46
|
+
src/server.mjs
|
|
44
47
|
test/
|
|
45
48
|
```
|
|
46
49
|
|
|
@@ -97,6 +100,8 @@ This project does not host that broker for users. The goal is an optional self-h
|
|
|
97
100
|
|
|
98
101
|
The config model already reserves a `cloud` section so advanced users and future versions do not need a breaking config redesign later. The broker contract is documented in [docs/cloud-broker.md](docs/cloud-broker.md).
|
|
99
102
|
|
|
103
|
+
There is also an early self-hosted broker scaffold in [broker/README.md](broker/README.md). It is not wired into scene execution yet, but it gives self-hosters a concrete service shape and a live `/v1/status` endpoint to target.
|
|
104
|
+
|
|
100
105
|
## Official Sonos References
|
|
101
106
|
|
|
102
107
|
These docs informed the product boundaries and future cloud-adapter shape:
|
package/broker/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# sonos-scenes-broker
|
|
2
|
+
|
|
3
|
+
This is the first self-hosted broker scaffold for `homebridge-sonos-scenes`.
|
|
4
|
+
|
|
5
|
+
It is intentionally small:
|
|
6
|
+
|
|
7
|
+
- it starts a local HTTP server
|
|
8
|
+
- it exposes `GET /healthz`
|
|
9
|
+
- it exposes `GET /v1/status`
|
|
10
|
+
- it reserves the future Sonos broker routes with `501 Not Implemented` responses
|
|
11
|
+
|
|
12
|
+
It does **not** implement Sonos OAuth or Sonos cloud playback yet. The point of this scaffold is to give self-hosters a concrete package and endpoint shape to build from.
|
|
13
|
+
|
|
14
|
+
## Run It
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
cd broker
|
|
18
|
+
node src/server.mjs
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
With environment variables:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
BROKER_PORT=8787
|
|
25
|
+
BROKER_HOST=127.0.0.1
|
|
26
|
+
BROKER_API_KEY=replace-me
|
|
27
|
+
node src/server.mjs
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Current Endpoints
|
|
31
|
+
|
|
32
|
+
- `GET /healthz`
|
|
33
|
+
- `GET /v1/status`
|
|
34
|
+
- `GET /v1/households`
|
|
35
|
+
- `GET /v1/households/:householdId/groups`
|
|
36
|
+
- `GET /v1/households/:householdId/favorites`
|
|
37
|
+
- `GET /v1/households/:householdId/playlists`
|
|
38
|
+
- `POST /v1/groups/:groupId/favorites/load`
|
|
39
|
+
- `POST /v1/groups/:groupId/playlists/load`
|
|
40
|
+
|
|
41
|
+
The `status` endpoint is meant to be usable by the Homebridge plugin right away for configuration checks. The other endpoints are placeholders for the future Sonos OAuth and cloud-control work.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sonos-scenes-broker",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Self-hosted Sonos cloud broker scaffold for homebridge-sonos-scenes.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node src/server.mjs",
|
|
9
|
+
"dev": "node --watch src/server.mjs"
|
|
10
|
+
},
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=18.20.0"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT"
|
|
15
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
|
|
3
|
+
const port = Number(process.env.BROKER_PORT || 8787);
|
|
4
|
+
const host = process.env.BROKER_HOST || "127.0.0.1";
|
|
5
|
+
const brokerName = process.env.BROKER_NAME || "sonos-scenes-broker";
|
|
6
|
+
const apiKey = (process.env.BROKER_API_KEY || "").trim();
|
|
7
|
+
const docsUrl = process.env.BROKER_DOCS_URL || "https://github.com/applemanj/homebridge-sonos-scenes/blob/main/docs/cloud-broker.md";
|
|
8
|
+
|
|
9
|
+
function writeJson(response, statusCode, payload) {
|
|
10
|
+
response.writeHead(statusCode, {
|
|
11
|
+
"content-type": "application/json; charset=utf-8",
|
|
12
|
+
"cache-control": "no-store",
|
|
13
|
+
});
|
|
14
|
+
response.end(JSON.stringify(payload, null, 2));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function bearerToken(request) {
|
|
18
|
+
const header = request.headers.authorization || "";
|
|
19
|
+
const match = /^Bearer\s+(.+)$/i.exec(header);
|
|
20
|
+
return match?.[1]?.trim() || "";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isAuthorized(request) {
|
|
24
|
+
if (!apiKey) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return bearerToken(request) === apiKey;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function readJsonBody(request) {
|
|
32
|
+
const chunks = [];
|
|
33
|
+
for await (const chunk of request) {
|
|
34
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (chunks.length === 0) {
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const raw = Buffer.concat(chunks).toString("utf8");
|
|
42
|
+
return raw.trim().length > 0 ? JSON.parse(raw) : {};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function notImplemented(response, route, extra = {}) {
|
|
46
|
+
writeJson(response, 501, {
|
|
47
|
+
ok: false,
|
|
48
|
+
route,
|
|
49
|
+
mode: "scaffold",
|
|
50
|
+
message: "This broker scaffold reserves the route, but Sonos OAuth and cloud playback are not implemented yet.",
|
|
51
|
+
...extra,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const server = createServer(async (request, response) => {
|
|
56
|
+
const url = new URL(request.url || "/", `http://${request.headers.host || `${host}:${port}`}`);
|
|
57
|
+
const pathname = url.pathname;
|
|
58
|
+
const method = request.method || "GET";
|
|
59
|
+
|
|
60
|
+
if (method === "GET" && pathname === "/healthz") {
|
|
61
|
+
writeJson(response, 200, {
|
|
62
|
+
ok: true,
|
|
63
|
+
name: brokerName,
|
|
64
|
+
mode: "scaffold",
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (method === "GET" && pathname === "/v1/status") {
|
|
70
|
+
writeJson(response, 200, {
|
|
71
|
+
ok: true,
|
|
72
|
+
name: brokerName,
|
|
73
|
+
version: "0.0.1",
|
|
74
|
+
mode: "scaffold",
|
|
75
|
+
oauthConfigured: false,
|
|
76
|
+
features: ["favorites", "playlists"],
|
|
77
|
+
docsUrl,
|
|
78
|
+
message: "Broker scaffold is running. Sonos OAuth is not configured yet.",
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!isAuthorized(request)) {
|
|
84
|
+
writeJson(response, 401, {
|
|
85
|
+
ok: false,
|
|
86
|
+
message: "Unauthorized. Supply the configured broker bearer token.",
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
if (method === "GET" && pathname === "/v1/households") {
|
|
93
|
+
notImplemented(response, pathname, {
|
|
94
|
+
households: [],
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (method === "GET" && /^\/v1\/households\/[^/]+\/groups$/.test(pathname)) {
|
|
100
|
+
notImplemented(response, pathname, {
|
|
101
|
+
groups: [],
|
|
102
|
+
players: [],
|
|
103
|
+
});
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (method === "GET" && /^\/v1\/households\/[^/]+\/favorites$/.test(pathname)) {
|
|
108
|
+
notImplemented(response, pathname, {
|
|
109
|
+
favorites: [],
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (method === "GET" && /^\/v1\/households\/[^/]+\/playlists$/.test(pathname)) {
|
|
115
|
+
notImplemented(response, pathname, {
|
|
116
|
+
playlists: [],
|
|
117
|
+
});
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (method === "POST" && /^\/v1\/groups\/[^/]+\/favorites\/load$/.test(pathname)) {
|
|
122
|
+
const body = await readJsonBody(request);
|
|
123
|
+
notImplemented(response, pathname, {
|
|
124
|
+
received: body,
|
|
125
|
+
});
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (method === "POST" && /^\/v1\/groups\/[^/]+\/playlists\/load$/.test(pathname)) {
|
|
130
|
+
const body = await readJsonBody(request);
|
|
131
|
+
notImplemented(response, pathname, {
|
|
132
|
+
received: body,
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
writeJson(response, 404, {
|
|
138
|
+
ok: false,
|
|
139
|
+
message: `No route matched ${method} ${pathname}.`,
|
|
140
|
+
});
|
|
141
|
+
} catch (error) {
|
|
142
|
+
writeJson(response, 500, {
|
|
143
|
+
ok: false,
|
|
144
|
+
message: error instanceof Error ? error.message : String(error),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
server.listen(port, host, () => {
|
|
150
|
+
console.log(`${brokerName} listening on http://${host}:${port}`);
|
|
151
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PlatformAccessory } from "homebridge";
|
|
2
|
+
import type { SceneDefinition } from "../types";
|
|
3
|
+
import type { SonosScenesPlatform } from "../platform";
|
|
4
|
+
export declare class SceneSpeakerAccessory {
|
|
5
|
+
private readonly platform;
|
|
6
|
+
private readonly accessory;
|
|
7
|
+
private service;
|
|
8
|
+
private scene;
|
|
9
|
+
private lastKnownVolume;
|
|
10
|
+
private lastKnownMuted;
|
|
11
|
+
constructor(platform: SonosScenesPlatform, accessory: PlatformAccessory, scene: SceneDefinition);
|
|
12
|
+
updateScene(scene: SceneDefinition): void;
|
|
13
|
+
private displayNameFor;
|
|
14
|
+
private handleVolumeGet;
|
|
15
|
+
private handleVolumeSet;
|
|
16
|
+
private handleMuteGet;
|
|
17
|
+
private handleMuteSet;
|
|
18
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SceneSpeakerAccessory = void 0;
|
|
4
|
+
class SceneSpeakerAccessory {
|
|
5
|
+
platform;
|
|
6
|
+
accessory;
|
|
7
|
+
service;
|
|
8
|
+
scene;
|
|
9
|
+
lastKnownVolume;
|
|
10
|
+
lastKnownMuted = false;
|
|
11
|
+
constructor(platform, accessory, scene) {
|
|
12
|
+
this.platform = platform;
|
|
13
|
+
this.accessory = accessory;
|
|
14
|
+
this.scene = scene;
|
|
15
|
+
this.lastKnownVolume = scene.coordinatorVolume ?? 0;
|
|
16
|
+
this.accessory.context.sceneId = scene.id;
|
|
17
|
+
this.accessory.context.kind = "speaker";
|
|
18
|
+
this.accessory.displayName = this.displayNameFor(scene);
|
|
19
|
+
this.accessory.category = 26 /* this.platform.api.hap.Categories.SPEAKER */;
|
|
20
|
+
this.service =
|
|
21
|
+
this.accessory.getService(this.platform.Service.Speaker)
|
|
22
|
+
?? this.accessory.addService(this.platform.Service.Speaker);
|
|
23
|
+
if (!this.service.testCharacteristic(this.platform.Characteristic.Volume)) {
|
|
24
|
+
this.service.addCharacteristic(this.platform.Characteristic.Volume);
|
|
25
|
+
}
|
|
26
|
+
this.service.setCharacteristic(this.platform.Characteristic.Name, this.displayNameFor(scene));
|
|
27
|
+
this.service.getCharacteristic(this.platform.Characteristic.Mute)
|
|
28
|
+
.onGet(this.handleMuteGet.bind(this))
|
|
29
|
+
.onSet(this.handleMuteSet.bind(this));
|
|
30
|
+
this.service.getCharacteristic(this.platform.Characteristic.Volume)
|
|
31
|
+
.onGet(this.handleVolumeGet.bind(this))
|
|
32
|
+
.onSet(this.handleVolumeSet.bind(this));
|
|
33
|
+
const accessoryInformation = this.accessory.getService(this.platform.Service.AccessoryInformation)
|
|
34
|
+
?? this.accessory.addService(this.platform.Service.AccessoryInformation);
|
|
35
|
+
accessoryInformation
|
|
36
|
+
.setCharacteristic(this.platform.Characteristic.Manufacturer, "homebridge-sonos-scenes")
|
|
37
|
+
.setCharacteristic(this.platform.Characteristic.Model, "Sonos Scene Speaker")
|
|
38
|
+
.setCharacteristic(this.platform.Characteristic.SerialNumber, `${scene.id}:speaker`);
|
|
39
|
+
}
|
|
40
|
+
updateScene(scene) {
|
|
41
|
+
this.scene = scene;
|
|
42
|
+
this.lastKnownVolume = scene.coordinatorVolume ?? this.lastKnownVolume;
|
|
43
|
+
this.accessory.context.sceneId = scene.id;
|
|
44
|
+
this.accessory.context.kind = "speaker";
|
|
45
|
+
this.accessory.displayName = this.displayNameFor(scene);
|
|
46
|
+
this.service.setCharacteristic(this.platform.Characteristic.Name, this.displayNameFor(scene));
|
|
47
|
+
}
|
|
48
|
+
displayNameFor(scene) {
|
|
49
|
+
return `${scene.name} Volume`;
|
|
50
|
+
}
|
|
51
|
+
async handleVolumeGet() {
|
|
52
|
+
try {
|
|
53
|
+
this.lastKnownVolume = await this.platform.getSceneVolume(this.scene.id);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
void 0;
|
|
57
|
+
}
|
|
58
|
+
return this.lastKnownVolume;
|
|
59
|
+
}
|
|
60
|
+
async handleVolumeSet(value) {
|
|
61
|
+
const nextVolume = Math.max(0, Math.min(100, Math.round(Number(value))));
|
|
62
|
+
await this.platform.setSceneVolume(this.scene.id, nextVolume);
|
|
63
|
+
this.lastKnownVolume = nextVolume;
|
|
64
|
+
this.service.updateCharacteristic(this.platform.Characteristic.Volume, nextVolume);
|
|
65
|
+
}
|
|
66
|
+
async handleMuteGet() {
|
|
67
|
+
try {
|
|
68
|
+
this.lastKnownMuted = await this.platform.getSceneMuted(this.scene.id);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
void 0;
|
|
72
|
+
}
|
|
73
|
+
return this.lastKnownMuted;
|
|
74
|
+
}
|
|
75
|
+
async handleMuteSet(value) {
|
|
76
|
+
const nextMuted = value === true;
|
|
77
|
+
await this.platform.setSceneMuted(this.scene.id, nextMuted);
|
|
78
|
+
this.lastKnownMuted = nextMuted;
|
|
79
|
+
this.service.updateCharacteristic(this.platform.Characteristic.Mute, nextMuted);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.SceneSpeakerAccessory = SceneSpeakerAccessory;
|
|
83
|
+
//# sourceMappingURL=sceneSpeaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sceneSpeaker.js","sourceRoot":"","sources":["../../../src/accessories/sceneSpeaker.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,9 @@ export interface CloudBrokerStatus {
|
|
|
6
6
|
version?: string;
|
|
7
7
|
features: CloudBrokerFeature[];
|
|
8
8
|
docsUrl?: string;
|
|
9
|
+
mode?: "scaffold" | "live";
|
|
10
|
+
oauthConfigured?: boolean;
|
|
11
|
+
message?: string;
|
|
9
12
|
}
|
|
10
13
|
export declare class CloudBrokerClient {
|
|
11
14
|
private readonly config;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brokerClient.js","sourceRoot":"","sources":["../../../src/cloud/brokerClient.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"brokerClient.js","sourceRoot":"","sources":["../../../src/cloud/brokerClient.ts"],"names":[],"mappings":";;;AAeA,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC;AAED,MAAa,iBAAiB;IACC;IAA7B,YAA6B,MAAyB;QAAzB,WAAM,GAAN,MAAM,CAAmB;IAAG,CAAC;IAE1D,IAAI,UAAU;QACZ,OAAO,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAClF,CAAC;IAED,IAAI,OAAO;QACT,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,GAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,OAAO,CAAoB,YAAY,EAAE;YACnD,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,IAAiB;QACtD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAE5E,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;gBACrD,GAAG,IAAI;gBACP,OAAO,EAAE;oBACP,MAAM,EAAE,kBAAkB;oBAC1B,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM;wBACpB,CAAC,CAAC;4BACE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;yBAC9C;wBACH,CAAC,CAAC,EAAE,CAAC;oBACP,GAAG,IAAI,CAAC,OAAO;iBAChB;gBACD,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YAC5F,CAAC;YAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAO,CAAC;QACpC,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;CACF;AArDD,8CAqDC"}
|
package/dist/src/platform.d.ts
CHANGED
|
@@ -14,10 +14,20 @@ export declare class SonosScenesPlatform implements DynamicPlatformPlugin {
|
|
|
14
14
|
private readonly sceneRunner;
|
|
15
15
|
private readonly transport;
|
|
16
16
|
private readonly cachedAccessories;
|
|
17
|
-
private readonly
|
|
17
|
+
private readonly switchAccessories;
|
|
18
|
+
private readonly speakerAccessories;
|
|
18
19
|
constructor(log: Logger, rawConfig: PlatformConfig, api: API);
|
|
19
20
|
configureAccessory(accessory: PlatformAccessory): void;
|
|
20
21
|
runScene(sceneId: string, trigger: SceneTrigger): Promise<SceneRunResult>;
|
|
21
22
|
getScene(sceneId: string): SceneDefinition | undefined;
|
|
23
|
+
getSceneVolume(sceneId: string): Promise<number>;
|
|
24
|
+
setSceneVolume(sceneId: string, volume: number): Promise<void>;
|
|
25
|
+
getSceneMuted(sceneId: string): Promise<boolean>;
|
|
26
|
+
setSceneMuted(sceneId: string, muted: boolean): Promise<void>;
|
|
22
27
|
private syncAccessories;
|
|
28
|
+
private syncSwitchAccessory;
|
|
29
|
+
private syncSpeakerAccessory;
|
|
30
|
+
private pruneWrapperMaps;
|
|
31
|
+
private getRequiredScene;
|
|
32
|
+
private usesGroupAudio;
|
|
23
33
|
}
|
package/dist/src/platform.js
CHANGED
|
@@ -5,6 +5,7 @@ const config_1 = require("./config");
|
|
|
5
5
|
const discoveryService_1 = require("./discoveryService");
|
|
6
6
|
const logger_1 = require("./logger");
|
|
7
7
|
const sceneRunner_1 = require("./sceneRunner");
|
|
8
|
+
const sceneSpeaker_1 = require("./accessories/sceneSpeaker");
|
|
8
9
|
const sceneSwitch_1 = require("./accessories/sceneSwitch");
|
|
9
10
|
const transports_1 = require("./transports");
|
|
10
11
|
const types_1 = require("./types");
|
|
@@ -22,7 +23,8 @@ class SonosScenesPlatform {
|
|
|
22
23
|
sceneRunner;
|
|
23
24
|
transport;
|
|
24
25
|
cachedAccessories = new Map();
|
|
25
|
-
|
|
26
|
+
switchAccessories = new Map();
|
|
27
|
+
speakerAccessories = new Map();
|
|
26
28
|
constructor(log, rawConfig, api) {
|
|
27
29
|
this.log = log;
|
|
28
30
|
this.rawConfig = rawConfig;
|
|
@@ -63,25 +65,47 @@ class SonosScenesPlatform {
|
|
|
63
65
|
getScene(sceneId) {
|
|
64
66
|
return this.config.scenes.find((scene) => scene.id === sceneId);
|
|
65
67
|
}
|
|
68
|
+
async getSceneVolume(sceneId) {
|
|
69
|
+
const scene = this.getRequiredScene(sceneId);
|
|
70
|
+
if (this.usesGroupAudio(scene)) {
|
|
71
|
+
return this.transport.getGroupVolume(scene.householdId, scene.coordinatorPlayerId);
|
|
72
|
+
}
|
|
73
|
+
return this.transport.getPlayerVolume(scene.householdId, scene.coordinatorPlayerId);
|
|
74
|
+
}
|
|
75
|
+
async setSceneVolume(sceneId, volume) {
|
|
76
|
+
const scene = this.getRequiredScene(sceneId);
|
|
77
|
+
if (this.usesGroupAudio(scene)) {
|
|
78
|
+
await this.transport.setGroupVolume(scene.householdId, scene.coordinatorPlayerId, volume);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
await this.transport.setPlayerVolume(scene.householdId, scene.coordinatorPlayerId, volume);
|
|
82
|
+
}
|
|
83
|
+
async getSceneMuted(sceneId) {
|
|
84
|
+
const scene = this.getRequiredScene(sceneId);
|
|
85
|
+
if (this.usesGroupAudio(scene)) {
|
|
86
|
+
return this.transport.getGroupMuted(scene.householdId, scene.coordinatorPlayerId);
|
|
87
|
+
}
|
|
88
|
+
return this.transport.getPlayerMuted(scene.householdId, scene.coordinatorPlayerId);
|
|
89
|
+
}
|
|
90
|
+
async setSceneMuted(sceneId, muted) {
|
|
91
|
+
const scene = this.getRequiredScene(sceneId);
|
|
92
|
+
if (this.usesGroupAudio(scene)) {
|
|
93
|
+
await this.transport.setGroupMuted(scene.householdId, scene.coordinatorPlayerId, muted);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
await this.transport.setPlayerMuted(scene.householdId, scene.coordinatorPlayerId, muted);
|
|
97
|
+
}
|
|
66
98
|
async syncAccessories() {
|
|
67
99
|
this.logger.info(`Syncing ${this.config.scenes.length} configured Sonos scene accessory(s).`);
|
|
68
100
|
const activeAccessoryIds = new Set();
|
|
69
101
|
for (const scene of this.config.scenes) {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.sceneAccessories.set(scene.id, wrapper);
|
|
78
|
-
this.api.registerPlatformAccessories(types_1.PLUGIN_NAME, types_1.PLATFORM_NAME, [accessory]);
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
const wrapper = this.sceneAccessories.get(scene.id) ?? new sceneSwitch_1.SceneSwitchAccessory(this, accessory, scene);
|
|
82
|
-
wrapper.updateScene(scene);
|
|
83
|
-
this.sceneAccessories.set(scene.id, wrapper);
|
|
84
|
-
this.api.updatePlatformAccessories([accessory]);
|
|
102
|
+
const switchUuid = this.api.hap.uuid.generate(`${types_1.PLUGIN_NAME}:${scene.id}:switch`);
|
|
103
|
+
const speakerUuid = this.api.hap.uuid.generate(`${types_1.PLUGIN_NAME}:${scene.id}:speaker`);
|
|
104
|
+
activeAccessoryIds.add(switchUuid);
|
|
105
|
+
activeAccessoryIds.add(speakerUuid);
|
|
106
|
+
const switchAccessory = this.syncSwitchAccessory(scene, switchUuid);
|
|
107
|
+
const speakerAccessory = this.syncSpeakerAccessory(scene, speakerUuid);
|
|
108
|
+
this.api.updatePlatformAccessories([switchAccessory, speakerAccessory]);
|
|
85
109
|
}
|
|
86
110
|
const staleAccessories = Array.from(this.cachedAccessories.entries())
|
|
87
111
|
.filter(([uuid]) => !activeAccessoryIds.has(uuid))
|
|
@@ -91,12 +115,7 @@ class SonosScenesPlatform {
|
|
|
91
115
|
for (const accessory of staleAccessories) {
|
|
92
116
|
this.cachedAccessories.delete(accessory.UUID);
|
|
93
117
|
}
|
|
94
|
-
|
|
95
|
-
if (!this.config.scenes.some((scene) => scene.id === sceneId)) {
|
|
96
|
-
void wrapper;
|
|
97
|
-
this.sceneAccessories.delete(sceneId);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
118
|
+
this.pruneWrapperMaps();
|
|
100
119
|
}
|
|
101
120
|
try {
|
|
102
121
|
const snapshot = await this.discoveryService.refresh();
|
|
@@ -106,6 +125,59 @@ class SonosScenesPlatform {
|
|
|
106
125
|
this.logger.warn(`Initial discovery failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
107
126
|
}
|
|
108
127
|
}
|
|
128
|
+
syncSwitchAccessory(scene, uuid) {
|
|
129
|
+
let accessory = this.cachedAccessories.get(uuid);
|
|
130
|
+
if (!accessory) {
|
|
131
|
+
accessory = new this.api.platformAccessory(scene.name, uuid);
|
|
132
|
+
this.cachedAccessories.set(uuid, accessory);
|
|
133
|
+
const wrapper = new sceneSwitch_1.SceneSwitchAccessory(this, accessory, scene);
|
|
134
|
+
this.switchAccessories.set(scene.id, wrapper);
|
|
135
|
+
this.api.registerPlatformAccessories(types_1.PLUGIN_NAME, types_1.PLATFORM_NAME, [accessory]);
|
|
136
|
+
return accessory;
|
|
137
|
+
}
|
|
138
|
+
const wrapper = this.switchAccessories.get(scene.id) ?? new sceneSwitch_1.SceneSwitchAccessory(this, accessory, scene);
|
|
139
|
+
wrapper.updateScene(scene);
|
|
140
|
+
this.switchAccessories.set(scene.id, wrapper);
|
|
141
|
+
return accessory;
|
|
142
|
+
}
|
|
143
|
+
syncSpeakerAccessory(scene, uuid) {
|
|
144
|
+
let accessory = this.cachedAccessories.get(uuid);
|
|
145
|
+
if (!accessory) {
|
|
146
|
+
accessory = new this.api.platformAccessory(`${scene.name} Volume`, uuid);
|
|
147
|
+
this.cachedAccessories.set(uuid, accessory);
|
|
148
|
+
const wrapper = new sceneSpeaker_1.SceneSpeakerAccessory(this, accessory, scene);
|
|
149
|
+
this.speakerAccessories.set(scene.id, wrapper);
|
|
150
|
+
this.api.registerPlatformAccessories(types_1.PLUGIN_NAME, types_1.PLATFORM_NAME, [accessory]);
|
|
151
|
+
return accessory;
|
|
152
|
+
}
|
|
153
|
+
const wrapper = this.speakerAccessories.get(scene.id) ?? new sceneSpeaker_1.SceneSpeakerAccessory(this, accessory, scene);
|
|
154
|
+
wrapper.updateScene(scene);
|
|
155
|
+
this.speakerAccessories.set(scene.id, wrapper);
|
|
156
|
+
return accessory;
|
|
157
|
+
}
|
|
158
|
+
pruneWrapperMaps() {
|
|
159
|
+
const activeSceneIds = new Set(this.config.scenes.map((scene) => scene.id));
|
|
160
|
+
for (const sceneId of this.switchAccessories.keys()) {
|
|
161
|
+
if (!activeSceneIds.has(sceneId)) {
|
|
162
|
+
this.switchAccessories.delete(sceneId);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
for (const sceneId of this.speakerAccessories.keys()) {
|
|
166
|
+
if (!activeSceneIds.has(sceneId)) {
|
|
167
|
+
this.speakerAccessories.delete(sceneId);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
getRequiredScene(sceneId) {
|
|
172
|
+
const scene = this.getScene(sceneId);
|
|
173
|
+
if (!scene) {
|
|
174
|
+
throw new Error(`Scene "${sceneId}" is not configured.`);
|
|
175
|
+
}
|
|
176
|
+
return scene;
|
|
177
|
+
}
|
|
178
|
+
usesGroupAudio(scene) {
|
|
179
|
+
return scene.memberPlayerIds.length > 0;
|
|
180
|
+
}
|
|
109
181
|
}
|
|
110
182
|
exports.SonosScenesPlatform = SonosScenesPlatform;
|
|
111
183
|
//# sourceMappingURL=platform.js.map
|
package/dist/src/platform.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/platform.ts"],"names":[],"mappings":";;;AACA,qCAAmD;AACnD,yDAAsD;AACtD,qCAA4C;AAC5C,+CAA4C;AAC5C,2DAAiE;AACjE,6CAA+C;AAE/C,mCAAqD;AAE5C,8FAFA,qBAAa,OAEA;AAAE,4FAFA,mBAAW,OAEA;AAEnC,MAAa,mBAAmB;
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ export declare class LocalSonosTransport implements SonosTransport {
|
|
|
6
6
|
readonly kind = "local";
|
|
7
7
|
private livePlayers;
|
|
8
8
|
private fixtureState;
|
|
9
|
+
private fixturePlayerAudio;
|
|
9
10
|
private fixtureLoaded;
|
|
10
11
|
private householdRoots;
|
|
11
12
|
private lastSnapshot;
|
|
@@ -22,7 +23,13 @@ export declare class LocalSonosTransport implements SonosTransport {
|
|
|
22
23
|
loadFavorite(householdId: string, coordinatorPlayerId: string, favoriteId: string): Promise<void>;
|
|
23
24
|
loadTv(householdId: string, coordinatorPlayerId: string, deviceId: string, playOnCompletion?: boolean): Promise<void>;
|
|
24
25
|
setGroupVolume(householdId: string, coordinatorPlayerId: string, volume: number): Promise<void>;
|
|
26
|
+
getGroupVolume(householdId: string, coordinatorPlayerId: string): Promise<number>;
|
|
27
|
+
getPlayerVolume(householdId: string, playerId: string): Promise<number>;
|
|
25
28
|
setPlayerVolume(householdId: string, playerId: string, volume: number): Promise<void>;
|
|
29
|
+
getGroupMuted(householdId: string, coordinatorPlayerId: string): Promise<boolean>;
|
|
30
|
+
setGroupMuted(householdId: string, coordinatorPlayerId: string, muted: boolean): Promise<void>;
|
|
31
|
+
getPlayerMuted(householdId: string, playerId: string): Promise<boolean>;
|
|
32
|
+
setPlayerMuted(householdId: string, playerId: string, muted: boolean): Promise<void>;
|
|
26
33
|
ungroup(householdId: string, coordinatorPlayerId: string, memberPlayerIds?: string[]): Promise<void>;
|
|
27
34
|
private tryLiveDiscovery;
|
|
28
35
|
private loadFixtureSnapshot;
|
|
@@ -33,4 +40,6 @@ export declare class LocalSonosTransport implements SonosTransport {
|
|
|
33
40
|
private fetchFavorites;
|
|
34
41
|
private setFixtureGroupMembers;
|
|
35
42
|
private touchFixture;
|
|
43
|
+
private fixtureAudioState;
|
|
44
|
+
private audioDevice;
|
|
36
45
|
}
|