Alex2Node/CHANGELOG.md
David dd071548bc 2.0.0
The interface registry, generated and checked discovery, typed dispatch with
automatic error answers, message builders, proactive events and typed
helpers for every error type; the 1.x API is kept and the examples of 1.5.2
run unchanged. docs/wire-changes.md lists what a 1.x caller can observe.

On 2026-09-28 a real Alexa account drove 33 test devices on this API through
the public Alex2MQTT service: Alexa accepted the discovery of all of them,
50 of 58 cases passed, 4 had no action in the control call and 4 failed on
what the check could see, none on an answer of the library. The readme table
names the interfaces that run covered. Voice commands were not tested yet.

307 tests.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 22:55:23 +00:00

5.9 KiB

Changelog

The format is that of Keep a Changelog, and the versions follow Semantic Versioning.

[2.0.0] - 2026-09-28

Every call of 1.5.2 is kept. What a 1.x program can observe is under "Changed", and docs/wire-changes.md has each row with the test that pins it.

Added

  • A registry that describes each Alexa interface as data: version, properties, directives, events, options. 32 interfaces are described, 39 are named with the version 1.5.2 announced. The readme has the table.
  • Discovery is written from the registry. bridge.addDevice() and device.add() throw a DeclarationError for what Alexa would reject, and device.check() lists it for a device declared the 1.x way.
  • RangeController, ModeController and ToggleController with instances, friendly names from asset() and text(), presets, and semantics() for open, close, raise and lower.
  • Handlers: capability.on(), device.onDirective(), device.onReportState(), with ctx.respond(), ctx.report(), ctx.defer() and ctx.error(). device.state() gives the context of every answer.
  • device.changeReport(cause, fill) for a ChangeReport, and device.raise() for DoorbellPress and the events of SimpleEventSource and WakeOnLANController, published to <root>/event.
  • AlexaError, and AlexaErrors with a function for each of the 73 error types.
  • Message builders under messages, and StateBuilder.
  • MemoryPublisher, the publisher option and bridge.receive(), to test a device without a broker.
  • The options alexaInterface, answerWithinMs and answerUnknownEndpoints; the events unanswered and unknownEndpoint.
  • An ES module build next to the CommonJS one, each with its declarations.
  • One example file for each recipe on the 2.0 API. The examples of 1.5.2 are in examples/legacy.

Changed

  • Node.js 18 is the oldest version the package runs on.
  • Discovery lists the Alexa interface on every endpoint. Alexa is told of every endpoint once more.
  • Alexa.EndpointHealth is announced with version 3.1, not 3.3.
  • Speaker, StepSpeaker, EqualizerController, PlaybackController, PlaybackStateReporter, InputController, ChannelController, LockController, MotionSensor and PowerLevelController are announced with the version and the properties of their interface.
  • addSupportedModes() with strings announces { value } objects, with a warning.
  • new ActionMapping() with a string as payload parses a JSON string, with a warning, and throws for another.
  • The bridge subscribes to <root>/discover and <root>/+/alexaDirective, not to <root>/#.
  • A directive or a discovery request with the messageId of one of the last 60 seconds is dropped.
  • A second answer for one correlationToken is refused.
  • A directive that nothing answers is answered with INTERNAL_ERROR after 6.5 seconds.
  • A listener that throws or rejects answers the directive with INTERNAL_ERROR, and the error event has what was thrown.
  • A directive for a device without a listener or a handler is answered with INVALID_DIRECTIVE.
  • An ErrorResponse goes under the namespace its type is documented under, not always under Alexa.
  • getErrorMessage(token).send() without setErrorMessage() sends INTERNAL_ERROR, not an empty payload.
  • A ChangeReport without a changed property is not published. A property that changed is not listed in the context as well.
  • A DeferredResponse has no context key, and a ChangeReport no empty correlationToken.
  • registerDevice() before connect() returns the device.
  • The fourth argument of new AlexaStatusMessage() and new AlexaErrorResponse() is a Publisher, not the mqtt client.
  • uuid is no longer a dependency.

Deprecated

  • The client argument of new Device(client, ...): it is ignored, with a warning once. Removed in 3.0.
  • device.setMqttClient(): it does nothing, with a warning once. Removed in 3.0.

1.5.2 - 2026-09-28

Added

  • Type declarations ship with the package.
  • A LICENSE file (MIT).

Changed

  • send() never rejects: it resolves with the topic, or with "" when the publish failed, and the error goes to the error event of the bridge.
  • registerDevice() with an endpointId that is registered returns the existing device, with a warning.
  • ThermostatController discovery lists targetSetpoint and no longer adaptiveRecoveryStatus.
  • An interface without a property list is noted through the log hook, not printed to stderr.

Fixed

  • Devices registered before disconnect() publish through the connection of the next connect().
  • The examples: require("alex2node"), an error listener in each, the correlationToken read from the header in BlindControl, Fahrenheit reported as Fahrenheit in the thermostat.

1.5.1 - 2026-09-22

Added

  • The events connect, offline, reconnect and close, and bridge.connected.
  • The options host, mqtt and log.
  • device.getChangeReport(cause), published to <root>/changeReport.
  • SceneController in discovery, and device.sendSceneResponse().
  • addCapability(type, { retrievable, proactivelyReported, instance }).
  • unregisterDevice(), clearDevices(), getDevices(), getDevice(), disconnect(), the events discover and directive, and lastDiscoveryAt.
  • Tests against a broker in the test process.

Changed

  • send() returns a promise and no longer logs to the console.

Fixed

  • A broker that is away no longer ends the process: error is emitted only when there is a listener.

1.5.0

As it was published to npm. It came into this repository on 2026-09-22.

Changed

  • The power example reports brightness and mode.

Before 1.5.0

Not tagged in this repository. The history has the initial release on 2025-04-20, and in May 2025 the thermostat, deferred responses, error responses, the error event, ModeController and ToggleController.