bridge: subscribe to discover and +/alexaDirective only
The bridge subscribed to <root>/#, so the broker sent back every discover_r, alexaResponce and changeReport
the bridge published, and the backend's <endpointId>/alexaDirective_e. It now subscribes to <root>/discover
and <root>/+/alexaDirective, both named in src/topics.ts; a directive topic is recognised by the root and the
last segment instead of by counting three segments.
The test reads the subscriptions from the broker, publishes seven other topics under the root and one
directive for each of two endpoints: the bridge receives the two directives and the discovery request,
nothing else. Tests: 148 -> 150 (the count in the body of 6789a1a, 108 -> 113, should read 143 -> 148).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
6789a1a077
commit
e0fe9d2812
11 changed files with 225 additions and 93 deletions
63
test/subscriptions.test.js
Normal file
63
test/subscriptions.test.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
"use strict";
|
||||
// What the bridge subscribes to: <root>/discover and <root>/+/alexaDirective. 1.x subscribed to <root>/#, which also
|
||||
// delivered everything the bridge published itself and the backend's <endpointId>/alexaDirective_e.
|
||||
const { test } = require("node:test");
|
||||
const assert = require("node:assert/strict");
|
||||
const { Alex2MQTT, DisplayCategory, PowerController, topics } = require("alex2node");
|
||||
const { broker, watcher, connected, directive, until, sleep } = require("./helpers/harness.js");
|
||||
|
||||
test("topics: the two filters, and the endpointId of a directive topic", () => {
|
||||
assert.deepEqual(topics.subscriptions("root"), ["root/discover", "root/+/alexaDirective"]);
|
||||
assert.equal(topics.directive("root", "lamp-1"), "root/lamp-1/alexaDirective");
|
||||
assert.equal(topics.directiveEndpoint("root", "root/lamp-1/alexaDirective"), "lamp-1");
|
||||
for (const other of [
|
||||
"root/lamp-1/alexaDirective_e", "root/lamp-1/alexaResponce", "root/alexaDirective", "root/a/b/alexaDirective",
|
||||
"root//alexaDirective", "root2/lamp-1/alexaDirective", "root/discover",
|
||||
]) {
|
||||
assert.equal(topics.directiveEndpoint("root", other), null, other);
|
||||
}
|
||||
});
|
||||
|
||||
test("the bridge subscribes to discover and +/alexaDirective: two endpoints get their directives, no other topic reaches the bridge", async () => {
|
||||
const { aedes, url } = await broker();
|
||||
const subscribed = [];
|
||||
aedes.on("subscribe", (subscriptions, client) => {
|
||||
if (client.id === "bridge-under-test") subscribed.push(...subscriptions.map((s) => s.topic));
|
||||
});
|
||||
const alexa = await watcher(url, "root/#");
|
||||
const received = [];
|
||||
const log = (line, detail) => { if (line === "MQTT Message Received") received.push(detail.topic); };
|
||||
const bridge = await connected(new Alex2MQTT("u", "p", "root", false, { host: url, log, mqtt: { clientId: "bridge-under-test" } }));
|
||||
assert.deepEqual(subscribed.sort(), ["root/+/alexaDirective", "root/discover"]);
|
||||
|
||||
const heard = [];
|
||||
for (const id of ["lamp-1", "lamp-2"]) {
|
||||
const lamp = bridge.registerDevice(id, id, DisplayCategory.LIGHT);
|
||||
const answer = (d) => {
|
||||
heard.push(`${id} ${d.header.name}`);
|
||||
return lamp.getStatusMessage(d.header.correlationToken, true).addPowerControllerProp(PowerController.ON).send();
|
||||
};
|
||||
lamp.on("Event", answer);
|
||||
lamp.on("ReportState", answer);
|
||||
}
|
||||
bridge.on("directive", ({ endpointId, name }) => heard.push(`bridge ${endpointId} ${name}`));
|
||||
|
||||
// Under the root, and none of them for the bridge: the last three are what the bridge and the backend publish
|
||||
const turnOn = directive("Alexa.PowerController", "TurnOn", "lamp-1", "not-for-the-bridge");
|
||||
for (const topic of ["root/lamp-1/alexaDirective_e", "root/lamp-1/status", "root/lamp-1/alexaDirective/more", "root/alexaDirective"]) {
|
||||
alexa.publish(topic, turnOn);
|
||||
}
|
||||
alexa.publish("root/lamp-1/alexaResponce", { event: {} });
|
||||
alexa.publish("root/changeReport", { event: {} });
|
||||
alexa.publish("root/discover_r", []);
|
||||
alexa.send("root", directive("Alexa.PowerController", "TurnOn", "lamp-1", "ct-1"));
|
||||
alexa.send("root", directive("Alexa.PowerController", "TurnOff", "lamp-2", "ct-2"));
|
||||
alexa.publish("root/discover", "");
|
||||
|
||||
const answered = (id) => alexa.on(`root/${id}/alexaResponce`).some((m) => m.event.header);
|
||||
await until(() => answered("lamp-1") && answered("lamp-2") && alexa.on("root/discover_r").length === 2, 3000, "both responses and the discovery answer");
|
||||
await sleep(100); // time for the echo of the bridge's own publishes, which must not come
|
||||
|
||||
assert.deepEqual(heard, ["bridge lamp-1 TurnOn", "lamp-1 TurnOn", "bridge lamp-2 TurnOff", "lamp-2 TurnOff"]);
|
||||
assert.deepEqual(received, ["root/lamp-1/alexaDirective", "root/lamp-2/alexaDirective", "root/discover"]);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue