Describe interfaces with PROGMEM descriptor rows; drop the switch tables
AlexaInterfaces.h/.cpp hold one row per interface in program memory (28: namespace, version, property names, flags, type), each row and string an object of its own, so the linker keeps only the rows a sketch names. addCapability(AlexaInterfaceType) is an always-inline switch that folds to one row; a type without a row is refused with an error. The Event handler gets its type from the capabilities of the device. Versions follow the interface pages (EndpointHealth 3.1, ThermostatController 3.2), HumiditySensor is new, the two withdrawn interfaces and AlexaInterfaceUtils are gone. Display category names are in flash. The discovery objects of the five examples are unchanged: 14 new host tests compare them with what the previous commit announced. basicLight on a D1 mini: static RAM 34,508 -> 30,788, flash 338,533 -> 330,509; it links two rows, EndpointHealth and PowerController. Host tests: 47 -> 61. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
d534f23f27
commit
8b11cc2394
13 changed files with 909 additions and 777 deletions
|
|
@ -6,7 +6,6 @@
|
|||
#include "AlexaInterface.h"
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include "AlexaStatusMessage.h"
|
||||
|
|
@ -16,137 +15,16 @@
|
|||
|
||||
#define MAX_EVENTS 10
|
||||
|
||||
enum class DisplayCategory {
|
||||
ACTIVITY_TRIGGER,
|
||||
AIR_CONDITIONER,
|
||||
AIR_FRESHENER,
|
||||
AIR_PURIFIER,
|
||||
AIR_QUALITY_MONITOR,
|
||||
ALEXA_VOICE_ENABLED,
|
||||
AUTO_ACCESSORY,
|
||||
BLUETOOTH_SPEAKER,
|
||||
CAMERA,
|
||||
CHRISTMAS_TREE,
|
||||
COFFEE_MAKER,
|
||||
COMPUTER,
|
||||
CONTACT_SENSOR,
|
||||
DISHWASHER,
|
||||
DOOR,
|
||||
DOORBELL,
|
||||
DRYER,
|
||||
EXTERIOR_BLIND,
|
||||
FAN,
|
||||
GAME_CONSOLE,
|
||||
GARAGE_DOOR,
|
||||
HEADPHONES,
|
||||
HUB,
|
||||
INTERIOR_BLIND,
|
||||
LAPTOP,
|
||||
LIGHT,
|
||||
MICROWAVE,
|
||||
MOBILE_PHONE,
|
||||
MOTION_SENSOR,
|
||||
MUSIC_SYSTEM,
|
||||
NETWORK_HARDWARE,
|
||||
OTHER,
|
||||
OVEN,
|
||||
PHONE,
|
||||
PRINTER,
|
||||
REMOTE,
|
||||
ROUTER,
|
||||
SCENE_TRIGGER,
|
||||
SCREEN,
|
||||
SECURITY_PANEL,
|
||||
SECURITY_SYSTEM,
|
||||
SLOW_COOKER,
|
||||
SMARTLOCK,
|
||||
SMARTPLUG,
|
||||
SPEAKER,
|
||||
STREAMING_DEVICE,
|
||||
SWITCH,
|
||||
TABLET,
|
||||
TEMPERATURE_SENSOR,
|
||||
THERMOSTAT,
|
||||
TV,
|
||||
VACUUM_CLEANER,
|
||||
VEHICLE,
|
||||
WASHER,
|
||||
WATER_HEATER,
|
||||
WEARABLE
|
||||
};
|
||||
|
||||
class DisplayCategoryUtils {
|
||||
public:
|
||||
static String toString(DisplayCategory category) {
|
||||
static const std::unordered_map<DisplayCategory, String> categoryMap = {
|
||||
{DisplayCategory::ACTIVITY_TRIGGER, "ACTIVITY_TRIGGER"},
|
||||
{DisplayCategory::AIR_CONDITIONER, "AIR_CONDITIONER"},
|
||||
{DisplayCategory::AIR_FRESHENER, "AIR_FRESHENER"},
|
||||
{DisplayCategory::AIR_PURIFIER, "AIR_PURIFIER"},
|
||||
{DisplayCategory::AIR_QUALITY_MONITOR, "AIR_QUALITY_MONITOR"},
|
||||
{DisplayCategory::ALEXA_VOICE_ENABLED, "ALEXA_VOICE_ENABLED"},
|
||||
{DisplayCategory::AUTO_ACCESSORY, "AUTO_ACCESSORY"},
|
||||
{DisplayCategory::BLUETOOTH_SPEAKER, "BLUETOOTH_SPEAKER"},
|
||||
{DisplayCategory::CAMERA, "CAMERA"},
|
||||
{DisplayCategory::CHRISTMAS_TREE, "CHRISTMAS_TREE"},
|
||||
{DisplayCategory::COFFEE_MAKER, "COFFEE_MAKER"},
|
||||
{DisplayCategory::COMPUTER, "COMPUTER"},
|
||||
{DisplayCategory::CONTACT_SENSOR, "CONTACT_SENSOR"},
|
||||
{DisplayCategory::DISHWASHER, "DISHWASHER"},
|
||||
{DisplayCategory::DOOR, "DOOR"},
|
||||
{DisplayCategory::DOORBELL, "DOORBELL"},
|
||||
{DisplayCategory::DRYER, "DRYER"},
|
||||
{DisplayCategory::EXTERIOR_BLIND, "EXTERIOR_BLIND"},
|
||||
{DisplayCategory::FAN, "FAN"},
|
||||
{DisplayCategory::GAME_CONSOLE, "GAME_CONSOLE"},
|
||||
{DisplayCategory::GARAGE_DOOR, "GARAGE_DOOR"},
|
||||
{DisplayCategory::HEADPHONES, "HEADPHONES"},
|
||||
{DisplayCategory::HUB, "HUB"},
|
||||
{DisplayCategory::INTERIOR_BLIND, "INTERIOR_BLIND"},
|
||||
{DisplayCategory::LAPTOP, "LAPTOP"},
|
||||
{DisplayCategory::LIGHT, "LIGHT"},
|
||||
{DisplayCategory::MICROWAVE, "MICROWAVE"},
|
||||
{DisplayCategory::MOBILE_PHONE, "MOBILE_PHONE"},
|
||||
{DisplayCategory::MOTION_SENSOR, "MOTION_SENSOR"},
|
||||
{DisplayCategory::MUSIC_SYSTEM, "MUSIC_SYSTEM"},
|
||||
{DisplayCategory::NETWORK_HARDWARE, "NETWORK_HARDWARE"},
|
||||
{DisplayCategory::OTHER, "OTHER"},
|
||||
{DisplayCategory::OVEN, "OVEN"},
|
||||
{DisplayCategory::PHONE, "PHONE"},
|
||||
{DisplayCategory::PRINTER, "PRINTER"},
|
||||
{DisplayCategory::REMOTE, "REMOTE"},
|
||||
{DisplayCategory::ROUTER, "ROUTER"},
|
||||
{DisplayCategory::SCENE_TRIGGER, "SCENE_TRIGGER"},
|
||||
{DisplayCategory::SCREEN, "SCREEN"},
|
||||
{DisplayCategory::SECURITY_PANEL, "SECURITY_PANEL"},
|
||||
{DisplayCategory::SECURITY_SYSTEM, "SECURITY_SYSTEM"},
|
||||
{DisplayCategory::SLOW_COOKER, "SLOW_COOKER"},
|
||||
{DisplayCategory::SMARTLOCK, "SMARTLOCK"},
|
||||
{DisplayCategory::SMARTPLUG, "SMARTPLUG"},
|
||||
{DisplayCategory::SPEAKER, "SPEAKER"},
|
||||
{DisplayCategory::STREAMING_DEVICE, "STREAMING_DEVICE"},
|
||||
{DisplayCategory::SWITCH, "SWITCH"},
|
||||
{DisplayCategory::TABLET, "TABLET"},
|
||||
{DisplayCategory::TEMPERATURE_SENSOR, "TEMPERATURE_SENSOR"},
|
||||
{DisplayCategory::THERMOSTAT, "THERMOSTAT"},
|
||||
{DisplayCategory::TV, "TV"},
|
||||
{DisplayCategory::VACUUM_CLEANER, "VACUUM_CLEANER"},
|
||||
{DisplayCategory::VEHICLE, "VEHICLE"},
|
||||
{DisplayCategory::WASHER, "WASHER"},
|
||||
{DisplayCategory::WATER_HEATER, "WATER_HEATER"},
|
||||
{DisplayCategory::WEARABLE, "WEARABLE"}
|
||||
};
|
||||
|
||||
auto it = categoryMap.find(category);
|
||||
if (it != categoryMap.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return "UNKNOWN";
|
||||
return String(FPSTR(alexaDisplayCategoryName(category)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class AlexaDevice {
|
||||
public:
|
||||
// Devices are created by Alex2ESP::getDevice(), which passes the bridge as the transport that publishes the
|
||||
|
|
@ -180,9 +58,23 @@ public:
|
|||
|
||||
JsonDocument getDeviceJSON() const;
|
||||
|
||||
// Returns the capability of this type, creating it on first use. The pointer stays valid for the lifetime of
|
||||
// the device: capabilities live in a std::deque, which never relocates its elements when another one is added.
|
||||
AlexaInterface* addCapability(AlexaInterfaceType type);
|
||||
// Returns the capability that describes this interface, creating it on first use. The pointer stays valid for
|
||||
// the lifetime of the device: capabilities live in a std::deque, which never relocates its elements when
|
||||
// another one is added.
|
||||
AlexaInterface* addCapability(const AlexaInterfaceDesc& row);
|
||||
|
||||
// The same by the type of the interface, as 1.x sketches write it. A type without a row in AlexaInterfaces
|
||||
// cannot be described: nothing is added, the reason is printed and nullptr returned. Inlined, so that a type
|
||||
// written out in the sketch links its row only (alexaInterfaceRow).
|
||||
__attribute__((always_inline)) AlexaInterface* addCapability(AlexaInterfaceType type) {
|
||||
const AlexaInterfaceDesc* row = alexaInterfaceRow(type);
|
||||
return row != nullptr ? addCapability(*row) : refuseCapability(type);
|
||||
}
|
||||
|
||||
// The type of the capability of this device with the namespace of a directive ("Alexa.PowerController"),
|
||||
// UNKNOWN when the device has none
|
||||
AlexaInterfaceType getInterfaceType(const char* interfaceName) const;
|
||||
|
||||
|
||||
void registerEvent(const char* eventName, void (*callback)(const JsonDocument&, const AlexaInterfaceType&));
|
||||
|
||||
|
|
@ -194,6 +86,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
AlexaInterface* refuseCapability(AlexaInterfaceType type);
|
||||
|
||||
String name;
|
||||
String endpointId;
|
||||
String rootTopic;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue