registry: ThermostatController 3.2 and ThermostatController.Schedule

The thermostat is described from its page: one, two or three setpoints with holdUntil, AdjustTargetTemperature,
SetThermostatMode with the six modes (EM_HEAT is new), ResumeSchedule, adaptiveRecoveryStatus, and its seven error
types under Alexa.ThermostatController. A declaration gives supportedModes, supportsScheduling and the properties
the device has; without them discovery is what 1.5.2 sent: HEAT, COOL, AUTO, OFF and the three setpoints with
thermostatMode. supportedModes without HEAT or COOL is refused where it is declared.

ThermostatController.Schedule replaces its stub. Wire change for a 1.x declaration of it: version 3.2 (was 1) and
scheduleEnabled listed (was nothing). SetAdaptiveRecovery is taken only with supportsAdaptiveRecovery.

24 examples of three pages are saved as fixtures; the page folds the SetWeeklySchedule example away, its payload
is tested from the tables. 207 tests pass, 191 before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
David 2026-09-28 20:34:49 +00:00
parent af1489696d
commit f555a5df70
67 changed files with 2445 additions and 58 deletions

View file

@ -30,7 +30,7 @@ test("a descriptor of tier 1 or 2 has an entry in test/fixtures/interfaces.js, a
assert.deepEqual(described.map((descriptor) => descriptor.namespace), interfaces.map((entry) => entry.namespace).sort());
});
for (const { namespace, page, declared, unfit = [] } of interfaces) {
for (const { namespace, page, declared, unfit = [], chosen = false, folded = [] } of interfaces) {
test(`${namespace}: version, properties, directive payloads and property values of ${page}.html`, () => {
const descriptor = registry.get(namespace);
assert.ok(descriptor.doc.endsWith(`/${page}.html`), descriptor.doc);
@ -43,14 +43,15 @@ for (const { namespace, page, declared, unfit = [] } of interfaces) {
assert.equal(capability.version, descriptor.version, `${example}: version`);
assert.equal("instance" in capability, descriptor.instanced, `${example}: instance`);
const supported = capability.properties ? capability.properties.supported.map((property) => property.name) : [];
assert.deepEqual(supported, Object.keys(descriptor.properties), `${example}: properties`);
const known = Object.keys(descriptor.properties);
assert.deepEqual(supported, chosen ? known.filter((name) => supported.includes(name)) : known, `${example}: properties`);
}
}
const directives = examples(page, ".directive").map((name) => doc(page, name).directive);
assert.deepEqual(
directives.map((directive) => directive.header.name).sort(),
Object.keys(descriptor.directives).filter((name) => name !== "ReportState").sort(),
[...new Set(directives.map((directive) => directive.header.name))].sort(),
Object.keys(descriptor.directives).filter((name) => name !== "ReportState" && !folded.includes(name)).sort(),
"the page has an example of every directive"
);
for (const { header, payload } of directives) {
@ -131,16 +132,18 @@ test("every AlexaInterfaceType is in the registry: described, or a stub with the
assert.deepEqual(stub.directives, {}, stub.namespace);
assert.equal(stub.instanced, false, stub.namespace);
}
const thermostat = registry.get("Alexa.ThermostatController");
assert.equal(thermostat.version, "3.2");
assert.deepEqual(Object.keys(thermostat.properties), ["targetSetpoint", "lowerSetpoint", "upperSetpoint", "thermostatMode"]);
});
test("AlexaInterface.getVersion() and getProps() read the registry", () => {
// What a thermostat lists is for its declaration to say: a 1.x declaration lists what 1.5.2 listed
const chosen = {
"Alexa.ThermostatController": ["targetSetpoint", "lowerSetpoint", "upperSetpoint", "thermostatMode"],
"Alexa.ThermostatController.Schedule": ["scheduleEnabled"],
};
for (const descriptor of registry.list().filter(({ namespace }) => namespace !== "Alexa")) {
const capability = new AlexaInterface(descriptor.namespace);
assert.equal(capability.getVersion(), descriptor.version, descriptor.namespace);
assert.deepEqual(capability.getProps(), Object.keys(descriptor.properties), descriptor.namespace);
assert.deepEqual(capability.getProps(), chosen[descriptor.namespace] ?? Object.keys(descriptor.properties), descriptor.namespace);
}
// 1.5.2 had no version for these two and put "UNKNOWN" in discovery
assert.equal(new AlexaInterface(AlexaInterfaceType.TIME_HOLD_CONTROLLER).getVersion(), "3");