The table of DESIGN 6.1 with what the work since added: 26 rows in four groups (discovery, messages, directives, calls and types), each with the behaviour of 1.5.2, the one of 2.0, what to do and the test that pins it. Three rows are pinned by no test and say so: the order of the keys in the JSON text and the two toJSON() types. One change of the design is listed as not done: the 1.x temperature helpers do not round the converted Celsius value. The file feeds the migration section of the readme and the changelog. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
7.7 KiB
7.7 KiB
What a 1.x caller can observe in 2.0
Every call shape of 1.5.2 is kept. This file lists what behaves differently: on the wire, in what a call returns,
and in the types. It is the source of the migration section of the readme and of the 2.0.0 changelog. "Test" names
the file under test/ that pins the row; a row with - is pinned by none.
The topics are unchanged: <root>/discover, <root>/discover_r, <root>/<endpointId>/alexaDirective,
<root>/<endpointId>/alexaResponce, <root>/<endpointId>/deferredResponse, <root>/changeReport.
Discovery
| Change | 1.5.2 | 2.0 | What to do | Test |
|---|---|---|---|---|
The Alexa interface is announced |
not listed | every endpoint ends with { "type": "AlexaInterface", "interface": "Alexa", "version": "3" }, which Amazon requires |
a test that compares the capability list gets one more entry; new Alex2MQTT(..., { alexaInterface: false }) leaves it out. Alexa is told of every endpoint once more |
device/discovery.test.js |
Version of Alexa.EndpointHealth |
3.3 |
3.1, the version of the interface page |
nothing | discovery.test.js |
Interfaces that 1.5.2 announced with version 1 or with no property |
Alexa.Speaker, Alexa.StepSpeaker, Alexa.EqualizerController, Alexa.PlaybackController, Alexa.PlaybackStateReporter, Alexa.InputController, Alexa.ChannelController: version 1 and no property; Alexa.LockController, Alexa.MotionSensor, Alexa.PowerLevelController: no property |
the version and the properties of the interface page | a caller that replaced getJSON() to correct the capability can drop the replacement; a replaced getJSON() is still what discovery lists |
registry/entertainment.test.js, device/discovery.test.js, compat/capabilities.test.js |
addSupportedModes(["a", "b"]) |
the strings were announced as they were | [{ "value": "a" }, { "value": "b" }], and a warning through the log hook |
pass { value, modeResources } |
device/discovery.test.js |
new ActionMapping(actions, name, payload) with a string as payload |
the string was announced, quoted | a JSON string is parsed, with a warning through the log hook; any other string throws a DeclarationError |
pass the object | compat/capabilities.test.js |
| A discovery request that arrives twice | answered twice | a request with the messageId of one that came in the last 60 s is dropped; a request without a messageId is answered every time |
nothing | transport.test.js |
| What Alexa would reject in a declaration | published as declared | published as declared, and each problem is logged once through the log hook at discovery; device.check() returns the lines |
read the log after the first discovery | device/validate.test.js |
Messages
| Change | 1.5.2 | 2.0 | What to do | Test |
|---|---|---|---|---|
| DeferredResponse | "context": null |
no context key |
nothing | compat/messages.test.js |
| ChangeReport header | "correlationToken": "" |
no correlationToken |
nothing; the backend builds its own header | compat/messages.test.js |
| ChangeReport without a changed property | published, and dropped by the backend | not published: send() resolves "" and the error event names the endpoint |
add the changed property before unchanged(); send no report when nothing changed |
compat/messages.test.js |
| A property that is both changed and in the context of a ChangeReport | listed in both | listed in payload.change.properties only |
nothing | messages/build.test.js |
| Namespace of an ErrorResponse | always Alexa |
the namespace the error type is documented under: THERMOSTAT_IS_OFF goes under Alexa.ThermostatController, UNAUTHORIZED under Alexa.SecurityPanelController, OBSTACLE_DETECTED under Alexa.Safety |
setErrorMessage(type, message, extra, { namespace }) names another |
compat/messages.test.js, messages/errors.test.js |
getErrorMessage(token).send() without setErrorMessage() |
an ErrorResponse with an empty payload | INTERNAL_ERROR with the message "the device answered with an error and did not say which" |
call setErrorMessage() |
compat/messages.test.js |
| Order of the keys in the JSON text | context before event |
event before context |
compare the parsed message, not its text | - |
Directives
| Change | 1.5.2 | 2.0 | What to do | Test |
|---|---|---|---|---|
| Subscriptions | <root>/# |
<root>/discover and <root>/+/alexaDirective |
nothing; the log hook no longer sees what the bridge itself published | subscriptions.test.js |
A second answer for one correlationToken |
published | refused: send() resolves "" and the error event says the directive was answered before. One DeferredResponse and one answer after it pass |
answer once | dispatch/dispatch.test.js |
| A directive that arrives twice | handled twice | a directive with the messageId of one that came for the endpoint in the last 60 s is dropped |
nothing | dispatch/dispatch.test.js |
| A directive nothing answers | Alexa waits until the backend gives up after 7 s | INTERNAL_ERROR after 6.5 s, and the bridge emits unanswered and error |
answer in the listener, or send a DeferredResponse first; answerWithinMs: 0 turns it off |
dispatch/dispatch.test.js |
| A listener that throws or rejects | the exception left the library and could end the process | the directive is answered with INTERNAL_ERROR and the error event carries what was thrown |
nothing | dispatch/dispatch.test.js |
A directive for a device with no Event or ReportState listener and no handler |
no answer | INVALID_DIRECTIVE. A device with a 1.x listener keeps the answer to itself |
nothing | dispatch/dispatch.test.js |
Calls and types
| Change | 1.5.2 | 2.0 | What to do | Test |
|---|---|---|---|---|
registerDevice() before connect() |
threw | returns the device; what it sends before the bridge is connected resolves "" and the error event says to call connect() |
nothing | connection.test.js |
new Device(client, ...) |
the device published through client |
client is ignored. A client that is not null is reported once: through the log hook of the bridge, or as a DeprecationWarning with the code ALEX2NODE_DEVICE_CLIENT |
make the device with addDevice() or registerDevice(), or set device.publisher. Removed in 3.0 |
compat/deprecations.test.js |
device.setMqttClient(client) |
gave the device the client of a new connection | does nothing, and says so once (code ALEX2NODE_SET_MQTT_CLIENT): the devices of a bridge publish over disconnect() and connect() without it |
remove the call. Removed in 3.0 | compat/deprecations.test.js |
new AlexaStatusMessage(token, root, endpointId, client, ...), new AlexaErrorResponse(token, root, endpointId, client) |
the fourth argument was the mqtt client | it is a Publisher: an object with publish(topic, message) that resolves { ok, topic, error? } |
build the messages with device.getStatusMessage(), getErrorMessage() and getChangeReport(), which are unchanged |
compat/messages.test.js |
Type of AlexaStatusMessage.toJSON() |
{ event: any; context: { properties } | null } |
{ event: any; context?: { properties } } |
read context as optional |
- |
Type of AlexaErrorResponse.toJSON() |
{ event: any } |
ErrorResponseMessage, typed down to the payload |
nothing | - |
capability.on(name, handler) without a function |
- | throws a DeclarationError that says what it got |
2.0 API only | dispatch/dispatch.test.js |
In the design, not in the code
| Change | State |
|---|---|
addThermostatControllerProp and addTemperatureSensorProp round the converted Celsius value to two decimals |
not done: 68 °F is sent as 20, 70 °F as 21.11111111111111, as in 1.5.2 |