Announce a doorbell with proactivelyReported and a scene with supportsDeactivation
An interface without properties says beside its name what Alexa has to know of it; the library left both out. With a board and Alexa on 2026-09-28 the discovery of a doorbell was accepted (202), the endpoint was not listed, and its DoorbellPress was answered with 500 INTERNAL_SERVICE_EXCEPTION. DoorbellEventSource now always carries "proactivelyReported": true. SceneController carries "supportsDeactivation", false until the sketch calls setSupportsDeactivation(true); on another interface the call is refused and logged. The Scene example says that it can be undone. 148 host tests. Light: static RAM 30,616 B, flash 332,705 B (+140 B). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
1b8a5ff806
commit
c3d02f462e
11 changed files with 65 additions and 18 deletions
|
|
@ -88,7 +88,7 @@ AlexaCapabilityName::AlexaCapabilityName(const AlexaInterfaceDesc &row, const ch
|
|||
}
|
||||
|
||||
AlexaCapability::AlexaCapability(const AlexaInterfaceDesc &row, const char *instance)
|
||||
: row(&row), retrievable(true), proactivelyReported(false), nonControllable(false), valid(true)
|
||||
: row(&row), retrievable(true), proactivelyReported(false), nonControllable(false), deactivation(false), valid(true)
|
||||
{
|
||||
setInstance(instance);
|
||||
}
|
||||
|
|
@ -185,6 +185,18 @@ AlexaCapability &AlexaCapability::setNonControllable(bool value)
|
|||
return *this;
|
||||
}
|
||||
|
||||
AlexaCapability &AlexaCapability::setSupportsDeactivation(bool value)
|
||||
{
|
||||
if (!row->has(AIF_DEACTIVATION))
|
||||
{
|
||||
const AlexaCapabilityName name(*row, instance);
|
||||
ALEX2ESP_LOGE("%s: setSupportsDeactivation() ignored: only a SceneController can be deactivated", name.text);
|
||||
return refused();
|
||||
}
|
||||
deactivation = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AlexaCapability &AlexaCapability::setConfiguration(AlexaConfigurationFiller fill, void *context)
|
||||
{
|
||||
fillConfiguration = fill;
|
||||
|
|
@ -354,6 +366,17 @@ bool AlexaCapability::toJson(JsonArray capabilities, const char *endpointId) con
|
|||
properties[F("nonControllable")] = true;
|
||||
}
|
||||
}
|
||||
// An interface without properties says beside its name what Alexa has to know of it. Without these Alexa
|
||||
// accepts the discovery and leaves the endpoint out: a doorbell announced without proactivelyReported was not
|
||||
// listed, and its DoorbellPress was answered with an error.
|
||||
if (row->has(AIF_EVENTS))
|
||||
{
|
||||
capability[F("proactivelyReported")] = true;
|
||||
}
|
||||
if (row->has(AIF_DEACTIVATION))
|
||||
{
|
||||
capability[F("supportsDeactivation")] = static_cast<bool>(deactivation);
|
||||
}
|
||||
|
||||
writeSemantics(capability);
|
||||
if (instance != nullptr)
|
||||
|
|
|
|||
|
|
@ -128,6 +128,10 @@ public:
|
|||
// true: Alexa reports the state and sends no directive that changes it
|
||||
AlexaCapability &setNonControllable(bool value);
|
||||
|
||||
// For a scene: true when it can be undone, and Alexa then sends Deactivate as well as Activate. A scene is
|
||||
// announced with "supportsDeactivation": false until this is called.
|
||||
AlexaCapability &setSupportsDeactivation(bool value);
|
||||
|
||||
AlexaCapability &setConfiguration(AlexaConfigurationFiller fill, void *context = nullptr);
|
||||
|
||||
// Only for an interface that takes semantics: RangeController, ModeController, ToggleController
|
||||
|
|
@ -200,6 +204,7 @@ private:
|
|||
bool retrievable : 1;
|
||||
bool proactivelyReported : 1;
|
||||
bool nonControllable : 1;
|
||||
bool deactivation : 1;
|
||||
bool valid : 1;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -103,10 +103,10 @@ ALEXA_ROW(ThermostatController, NS_THERMOSTAT, VERSION_3_2, PROPS_THERMOSTAT, 4,
|
|||
ALEXA_ROW(TemperatureSensor, NS_TEMPERATURE_SENSOR, VERSION_3, PROPS_TEMPERATURE_SENSOR, 1, AIF_NONE, TEMPERATURE_SENSOR);
|
||||
ALEXA_ROW(HumiditySensor, NS_HUMIDITY_SENSOR, VERSION_3, PROPS_HUMIDITY_SENSOR, 1, AIF_NONE, HUMIDITY_SENSOR);
|
||||
ALEXA_ROW(LockController, NS_LOCK, VERSION_3, PROPS_LOCK, 1, AIF_NONE, LOCK_CONTROLLER);
|
||||
ALEXA_ROW(SceneController, NS_SCENE, VERSION_3, nullptr, 0, AIF_NO_PROPERTIES, SCENE_CONTROLLER);
|
||||
ALEXA_ROW(SceneController, NS_SCENE, VERSION_3, nullptr, 0, AIF_NO_PROPERTIES | AIF_DEACTIVATION, SCENE_CONTROLLER);
|
||||
ALEXA_ROW(ContactSensor, NS_CONTACT_SENSOR, VERSION_3, PROPS_DETECTION, 1, AIF_NONE, CONTACT_SENSOR);
|
||||
ALEXA_ROW(MotionSensor, NS_MOTION_SENSOR, VERSION_3, PROPS_DETECTION, 1, AIF_NONE, MOTION_SENSOR);
|
||||
ALEXA_ROW(DoorbellEventSource, NS_DOORBELL, VERSION_3, nullptr, 0, AIF_NO_PROPERTIES, DOORBELL_EVENT_SOURCE);
|
||||
ALEXA_ROW(DoorbellEventSource, NS_DOORBELL, VERSION_3, nullptr, 0, AIF_NO_PROPERTIES | AIF_EVENTS, DOORBELL_EVENT_SOURCE);
|
||||
ALEXA_ROW(TimeHoldController, NS_TIME_HOLD, VERSION_3, PROPS_TIME_HOLD, 2, AIF_NONE, TIME_HOLD_CONTROLLER);
|
||||
ALEXA_ROW(Speaker, NS_SPEAKER, VERSION_3, PROPS_SPEAKER, 2, AIF_NONE, SPEAKER);
|
||||
ALEXA_ROW(StepSpeaker, NS_STEP_SPEAKER, VERSION_3, nullptr, 0, AIF_NO_PROPERTIES, STEP_SPEAKER);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,9 @@ enum AlexaInterfaceFlags : uint8_t
|
|||
AIF_INSTANCED = 1, // a device may have several: each needs an instance and a friendly name
|
||||
AIF_NO_PROPERTIES = 2, // the discovery object has no "properties" (scenes, doorbells, step speakers)
|
||||
AIF_SEMANTICS = 4, // may carry action and state mappings
|
||||
AIF_EMPTY_PROPERTIES = 8 // the discovery object has "properties": {}, as the page of the interface shows it
|
||||
AIF_EMPTY_PROPERTIES = 8, // the discovery object has "properties": {}, as the page of the interface shows it
|
||||
AIF_EVENTS = 16, // what it reports are events: "proactivelyReported": true beside the interface (doorbell)
|
||||
AIF_DEACTIVATION = 32 // says whether it can be undone: "supportsDeactivation" beside the interface (scene)
|
||||
};
|
||||
|
||||
// 16 bytes in program memory. The ESP8266 reads flash in whole words only: the pointers can be read as they are,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue