Using the Alexa integration
These sections show the websocket JSON sent to the device for the supported Alexa directives together with matching Arduino device examples from microcontroller-examples.
set brightness
{
"brightness" : 59,
"endpointId" : "the endpoint id"
}
{"brightness": 59, "endpointId": "the endpoint id"}
void applyAlexaBrightnessPercent(const char* endpointId, long brightnessPercent) {
Serial.print("Set brightness percent on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(brightnessPercent);
Serial.print("BRIGHTNESS_PERCENT=");
Serial.println(brightnessPercent);
}
void applyAlexaBrightnessWeight(const char* endpointId, long brightnessWeight) {
Serial.print("Adjust brightness weight on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(brightnessWeight);
Serial.print("BRIGHTNESS_WEIGHT=");
Serial.println(brightnessWeight);
}
void handleAlexaBrightnessCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa brightness command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst brightnessPercent = root[offbeat::alexa::examples::kAdjustBrightnessPercentKey];
JsonVariantConst brightnessWeight = root[offbeat::alexa::examples::kAdjustBrightnessWeightKey];
if (!brightnessPercent.isNull()) {
applyAlexaBrightnessPercent(endpointId, offbeat::alexa::examples::readLong(brightnessPercent));
} else if (!brightnessWeight.isNull()) {
applyAlexaBrightnessWeight(endpointId, offbeat::alexa::examples::readLong(brightnessWeight));
} else {
Serial.println("No Alexa brightness payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
adjust brightness
{
"endpointId" : "the endpoint id",
"adjustBrightnessWeight" : -3
}
{"endpointId": "the endpoint id", "adjustBrightnessWeight": -3}
void applyAlexaBrightnessPercent(const char* endpointId, long brightnessPercent) {
Serial.print("Set brightness percent on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(brightnessPercent);
Serial.print("BRIGHTNESS_PERCENT=");
Serial.println(brightnessPercent);
}
void applyAlexaBrightnessWeight(const char* endpointId, long brightnessWeight) {
Serial.print("Adjust brightness weight on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(brightnessWeight);
Serial.print("BRIGHTNESS_WEIGHT=");
Serial.println(brightnessWeight);
}
void handleAlexaBrightnessCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa brightness command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst brightnessPercent = root[offbeat::alexa::examples::kAdjustBrightnessPercentKey];
JsonVariantConst brightnessWeight = root[offbeat::alexa::examples::kAdjustBrightnessWeightKey];
if (!brightnessPercent.isNull()) {
applyAlexaBrightnessPercent(endpointId, offbeat::alexa::examples::readLong(brightnessPercent));
} else if (!brightnessWeight.isNull()) {
applyAlexaBrightnessWeight(endpointId, offbeat::alexa::examples::readLong(brightnessWeight));
} else {
Serial.println("No Alexa brightness payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set color
{
"saturation" : 0.7138,
"brightness" : 0.6524,
"endpointId" : "the endpoint id",
"hue" : 350.5
}
{"saturation": 0.7138, "brightness": 0.6524, "endpointId": "the endpoint id", "hue": 350.5}
void applyAlexaColorCommand(const char* endpointId, double hue, double saturation, double brightness) {
Serial.print("Set color on ");
Serial.println(endpointId);
offbeat::alexa::examples::printLine("Hue: ", hue, 4);
offbeat::alexa::examples::printLine("Saturation: ", saturation, 4);
offbeat::alexa::examples::printLine("Brightness: ", brightness, 4);
Serial.print("HUE=");
Serial.println(hue, 4);
Serial.print("SATURATION=");
Serial.println(saturation, 4);
Serial.print("BRIGHTNESS=");
Serial.println(brightness, 4);
}
void handleAlexaColorCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa color command");
return;
}
JsonVariantConst hueValue = root[offbeat::alexa::examples::kHueKey];
JsonVariantConst saturationValue = root[offbeat::alexa::examples::kSaturationKey];
JsonVariantConst brightnessValue = root[offbeat::alexa::examples::kBrightnessKey];
if (hueValue.isNull() || saturationValue.isNull() || brightnessValue.isNull()) {
Serial.println("Incomplete Alexa color payload");
return;
}
applyAlexaColorCommand(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readDouble(hueValue),
offbeat::alexa::examples::readDouble(saturationValue),
offbeat::alexa::examples::readDouble(brightnessValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
turn on
{
"endpointId" : "the endpoint id",
"powerstate" : "TurnOn"
}
{"endpointId": "the endpoint id", "powerstate": "TurnOn"}
void applyAlexaPowerState(const char* endpointId, const char* powerState) {
Serial.print("Apply Alexa power command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(powerState);
if (strcmp(powerState, "TurnOn") == 0) {
Serial.println("Turn your relay or transistor on here");
} else if (strcmp(powerState, "TurnOff") == 0) {
Serial.println("Turn your relay or transistor off here");
} else {
Serial.println("Unsupported Alexa power command");
return;
}
Serial.print("POWERSTATE=");
Serial.println(powerState);
}
void handleAlexaPowerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa power command");
return;
}
JsonVariantConst powerStateValue = root[offbeat::alexa::examples::kPowerStateKey];
if (powerStateValue.isNull()) {
Serial.println("No Alexa powerstate payload");
return;
}
applyAlexaPowerState(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(powerStateValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
turn off
{
"endpointId" : "the endpoint id",
"powerstate" : "TurnOff"
}
{"endpointId": "the endpoint id", "powerstate": "TurnOff"}
void applyAlexaPowerState(const char* endpointId, const char* powerState) {
Serial.print("Apply Alexa power command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(powerState);
if (strcmp(powerState, "TurnOn") == 0) {
Serial.println("Turn your relay or transistor on here");
} else if (strcmp(powerState, "TurnOff") == 0) {
Serial.println("Turn your relay or transistor off here");
} else {
Serial.println("Unsupported Alexa power command");
return;
}
Serial.print("POWERSTATE=");
Serial.println(powerState);
}
void handleAlexaPowerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa power command");
return;
}
JsonVariantConst powerStateValue = root[offbeat::alexa::examples::kPowerStateKey];
if (powerStateValue.isNull()) {
Serial.println("No Alexa powerstate payload");
return;
}
applyAlexaPowerState(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(powerStateValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
turn on a toggle controller
{
"endpointId" : "the endpoint id",
"petdoor.powerstate" : "TurnOn"
}
{"endpointId": "the endpoint id", "petdoor.powerstate": "TurnOn"}
void applyAlexaPowerState(const char* endpointId, const char* powerState) {
Serial.print("Apply Alexa power command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(powerState);
if (strcmp(powerState, "TurnOn") == 0) {
Serial.println("Turn your relay or transistor on here");
} else if (strcmp(powerState, "TurnOff") == 0) {
Serial.println("Turn your relay or transistor off here");
} else {
Serial.println("Unsupported Alexa power command");
return;
}
Serial.print("POWERSTATE=");
Serial.println(powerState);
}
void handleAlexaPowerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa power command");
return;
}
JsonVariantConst powerStateValue = root[offbeat::alexa::examples::kPowerStateKey];
if (powerStateValue.isNull()) {
Serial.println("No Alexa powerstate payload");
return;
}
applyAlexaPowerState(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(powerStateValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
turn off a toggle controller
{
"endpointId" : "the endpoint id",
"petdoor.powerstate" : "TurnOff"
}
{"endpointId": "the endpoint id", "petdoor.powerstate": "TurnOff"}
void applyAlexaPowerState(const char* endpointId, const char* powerState) {
Serial.print("Apply Alexa power command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(powerState);
if (strcmp(powerState, "TurnOn") == 0) {
Serial.println("Turn your relay or transistor on here");
} else if (strcmp(powerState, "TurnOff") == 0) {
Serial.println("Turn your relay or transistor off here");
} else {
Serial.println("Unsupported Alexa power command");
return;
}
Serial.print("POWERSTATE=");
Serial.println(powerState);
}
void handleAlexaPowerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa power command");
return;
}
JsonVariantConst powerStateValue = root[offbeat::alexa::examples::kPowerStateKey];
if (powerStateValue.isNull()) {
Serial.println("No Alexa powerstate payload");
return;
}
applyAlexaPowerState(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(powerStateValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
adjust speaker volume using Alexa.StepSpeaker
{
"endpointId" : "the endpoint id",
"volumesteps" : 20
}
{"endpointId": "the endpoint id", "volumesteps": 20}
void applyAlexaSpeakerVolume(const char* endpointId, long volumePercent) {
Serial.print("Set speaker volume on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(volumePercent);
Serial.print("VOLUME=");
Serial.println(volumePercent);
}
void applyAlexaSpeakerVolumeSteps(const char* endpointId, long volumeSteps) {
Serial.print("Adjust speaker volume steps on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(volumeSteps);
Serial.print("VOLUME_STEPS=");
Serial.println(volumeSteps);
}
void applyAlexaSpeakerMute(const char* endpointId, bool muted) {
Serial.print("Set mute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(muted ? "true" : "false");
Serial.print("MUTE=");
Serial.println(muted ? "true" : "false");
}
void handleAlexaSpeakerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa speaker command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst volumeValue = root[offbeat::alexa::examples::kVolumeKey];
JsonVariantConst volumeStepsValue = root[offbeat::alexa::examples::kVolumeStepsKey];
JsonVariantConst muteValue = root[offbeat::alexa::examples::kMuteKey];
if (!volumeValue.isNull()) {
applyAlexaSpeakerVolume(endpointId, offbeat::alexa::examples::readLong(volumeValue));
} else if (!volumeStepsValue.isNull()) {
applyAlexaSpeakerVolumeSteps(endpointId, offbeat::alexa::examples::readLong(volumeStepsValue));
} else if (!muteValue.isNull()) {
applyAlexaSpeakerMute(endpointId, offbeat::alexa::examples::readBool(muteValue));
} else {
Serial.println("No Alexa speaker payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
adjust speaker volume using Alexa.Speaker
{
"endpointId" : "the endpoint id",
"volumesteps" : 20
}
{"endpointId": "the endpoint id", "volumesteps": 20}
void applyAlexaSpeakerVolume(const char* endpointId, long volumePercent) {
Serial.print("Set speaker volume on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(volumePercent);
Serial.print("VOLUME=");
Serial.println(volumePercent);
}
void applyAlexaSpeakerVolumeSteps(const char* endpointId, long volumeSteps) {
Serial.print("Adjust speaker volume steps on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(volumeSteps);
Serial.print("VOLUME_STEPS=");
Serial.println(volumeSteps);
}
void applyAlexaSpeakerMute(const char* endpointId, bool muted) {
Serial.print("Set mute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(muted ? "true" : "false");
Serial.print("MUTE=");
Serial.println(muted ? "true" : "false");
}
void handleAlexaSpeakerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa speaker command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst volumeValue = root[offbeat::alexa::examples::kVolumeKey];
JsonVariantConst volumeStepsValue = root[offbeat::alexa::examples::kVolumeStepsKey];
JsonVariantConst muteValue = root[offbeat::alexa::examples::kMuteKey];
if (!volumeValue.isNull()) {
applyAlexaSpeakerVolume(endpointId, offbeat::alexa::examples::readLong(volumeValue));
} else if (!volumeStepsValue.isNull()) {
applyAlexaSpeakerVolumeSteps(endpointId, offbeat::alexa::examples::readLong(volumeStepsValue));
} else if (!muteValue.isNull()) {
applyAlexaSpeakerMute(endpointId, offbeat::alexa::examples::readBool(muteValue));
} else {
Serial.println("No Alexa speaker payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
mute speaker using Alexa.StepSpeaker
{
"endpointId" : "the endpoint id",
"mute" : false
}
{"endpointId": "the endpoint id", "mute": false}
void applyAlexaSpeakerVolume(const char* endpointId, long volumePercent) {
Serial.print("Set speaker volume on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(volumePercent);
Serial.print("VOLUME=");
Serial.println(volumePercent);
}
void applyAlexaSpeakerVolumeSteps(const char* endpointId, long volumeSteps) {
Serial.print("Adjust speaker volume steps on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(volumeSteps);
Serial.print("VOLUME_STEPS=");
Serial.println(volumeSteps);
}
void applyAlexaSpeakerMute(const char* endpointId, bool muted) {
Serial.print("Set mute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(muted ? "true" : "false");
Serial.print("MUTE=");
Serial.println(muted ? "true" : "false");
}
void handleAlexaSpeakerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa speaker command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst volumeValue = root[offbeat::alexa::examples::kVolumeKey];
JsonVariantConst volumeStepsValue = root[offbeat::alexa::examples::kVolumeStepsKey];
JsonVariantConst muteValue = root[offbeat::alexa::examples::kMuteKey];
if (!volumeValue.isNull()) {
applyAlexaSpeakerVolume(endpointId, offbeat::alexa::examples::readLong(volumeValue));
} else if (!volumeStepsValue.isNull()) {
applyAlexaSpeakerVolumeSteps(endpointId, offbeat::alexa::examples::readLong(volumeStepsValue));
} else if (!muteValue.isNull()) {
applyAlexaSpeakerMute(endpointId, offbeat::alexa::examples::readBool(muteValue));
} else {
Serial.println("No Alexa speaker payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set speaker volume
{
"volume" : 30,
"endpointId" : "the endpoint id"
}
{"volume": 30, "endpointId": "the endpoint id"}
void applyAlexaSpeakerVolume(const char* endpointId, long volumePercent) {
Serial.print("Set speaker volume on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(volumePercent);
Serial.print("VOLUME=");
Serial.println(volumePercent);
}
void applyAlexaSpeakerVolumeSteps(const char* endpointId, long volumeSteps) {
Serial.print("Adjust speaker volume steps on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(volumeSteps);
Serial.print("VOLUME_STEPS=");
Serial.println(volumeSteps);
}
void applyAlexaSpeakerMute(const char* endpointId, bool muted) {
Serial.print("Set mute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(muted ? "true" : "false");
Serial.print("MUTE=");
Serial.println(muted ? "true" : "false");
}
void handleAlexaSpeakerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa speaker command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst volumeValue = root[offbeat::alexa::examples::kVolumeKey];
JsonVariantConst volumeStepsValue = root[offbeat::alexa::examples::kVolumeStepsKey];
JsonVariantConst muteValue = root[offbeat::alexa::examples::kMuteKey];
if (!volumeValue.isNull()) {
applyAlexaSpeakerVolume(endpointId, offbeat::alexa::examples::readLong(volumeValue));
} else if (!volumeStepsValue.isNull()) {
applyAlexaSpeakerVolumeSteps(endpointId, offbeat::alexa::examples::readLong(volumeStepsValue));
} else if (!muteValue.isNull()) {
applyAlexaSpeakerMute(endpointId, offbeat::alexa::examples::readBool(muteValue));
} else {
Serial.println("No Alexa speaker payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
adjust speaker volume using Alexa.Speaker volume
{
"endpointId" : "the endpoint id",
"volumesteps" : 30
}
{"endpointId": "the endpoint id", "volumesteps": 30}
void applyAlexaSpeakerVolume(const char* endpointId, long volumePercent) {
Serial.print("Set speaker volume on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(volumePercent);
Serial.print("VOLUME=");
Serial.println(volumePercent);
}
void applyAlexaSpeakerVolumeSteps(const char* endpointId, long volumeSteps) {
Serial.print("Adjust speaker volume steps on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(volumeSteps);
Serial.print("VOLUME_STEPS=");
Serial.println(volumeSteps);
}
void applyAlexaSpeakerMute(const char* endpointId, bool muted) {
Serial.print("Set mute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(muted ? "true" : "false");
Serial.print("MUTE=");
Serial.println(muted ? "true" : "false");
}
void handleAlexaSpeakerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa speaker command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst volumeValue = root[offbeat::alexa::examples::kVolumeKey];
JsonVariantConst volumeStepsValue = root[offbeat::alexa::examples::kVolumeStepsKey];
JsonVariantConst muteValue = root[offbeat::alexa::examples::kMuteKey];
if (!volumeValue.isNull()) {
applyAlexaSpeakerVolume(endpointId, offbeat::alexa::examples::readLong(volumeValue));
} else if (!volumeStepsValue.isNull()) {
applyAlexaSpeakerVolumeSteps(endpointId, offbeat::alexa::examples::readLong(volumeStepsValue));
} else if (!muteValue.isNull()) {
applyAlexaSpeakerMute(endpointId, offbeat::alexa::examples::readBool(muteValue));
} else {
Serial.println("No Alexa speaker payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
mute speaker using Alexa.Speaker
{
"endpointId" : "the endpoint id",
"mute" : false
}
{"endpointId": "the endpoint id", "mute": false}
void applyAlexaSpeakerVolume(const char* endpointId, long volumePercent) {
Serial.print("Set speaker volume on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(volumePercent);
Serial.print("VOLUME=");
Serial.println(volumePercent);
}
void applyAlexaSpeakerVolumeSteps(const char* endpointId, long volumeSteps) {
Serial.print("Adjust speaker volume steps on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(volumeSteps);
Serial.print("VOLUME_STEPS=");
Serial.println(volumeSteps);
}
void applyAlexaSpeakerMute(const char* endpointId, bool muted) {
Serial.print("Set mute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(muted ? "true" : "false");
Serial.print("MUTE=");
Serial.println(muted ? "true" : "false");
}
void handleAlexaSpeakerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa speaker command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst volumeValue = root[offbeat::alexa::examples::kVolumeKey];
JsonVariantConst volumeStepsValue = root[offbeat::alexa::examples::kVolumeStepsKey];
JsonVariantConst muteValue = root[offbeat::alexa::examples::kMuteKey];
if (!volumeValue.isNull()) {
applyAlexaSpeakerVolume(endpointId, offbeat::alexa::examples::readLong(volumeValue));
} else if (!volumeStepsValue.isNull()) {
applyAlexaSpeakerVolumeSteps(endpointId, offbeat::alexa::examples::readLong(volumeStepsValue));
} else if (!muteValue.isNull()) {
applyAlexaSpeakerMute(endpointId, offbeat::alexa::examples::readBool(muteValue));
} else {
Serial.println("No Alexa speaker payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
playback fast forward
{
"playerControl" : "Next",
"endpointId" : "the endpoint id"
}
{"playerControl": "Next", "endpointId": "the endpoint id"}
void applyAlexaPlaybackCommand(const char* endpointId, const char* playerControl) {
Serial.print("Apply playback command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
if (strcmp(playerControl, "Play") == 0) {
Serial.println("Start playback here");
} else if (strcmp(playerControl, "Pause") == 0) {
Serial.println("Pause playback here");
} else if (strcmp(playerControl, "Stop") == 0) {
Serial.println("Stop playback here");
} else if (strcmp(playerControl, "Next") == 0) {
Serial.println("Skip to the next item here");
} else if (strcmp(playerControl, "Prev") == 0) {
Serial.println("Go to the previous item here");
} else {
Serial.println("Unsupported Alexa playback command");
return;
}
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void handleAlexaPlaybackCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa playback command");
return;
}
JsonVariantConst playerControlValue = root[offbeat::alexa::examples::kPlayerControlKey];
if (playerControlValue.isNull()) {
Serial.println("No Alexa playback payload");
return;
}
applyAlexaPlaybackCommand(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(playerControlValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
playback next
{
"playerControl" : "Next",
"endpointId" : "the endpoint id"
}
{"playerControl": "Next", "endpointId": "the endpoint id"}
void applyAlexaPlaybackCommand(const char* endpointId, const char* playerControl) {
Serial.print("Apply playback command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
if (strcmp(playerControl, "Play") == 0) {
Serial.println("Start playback here");
} else if (strcmp(playerControl, "Pause") == 0) {
Serial.println("Pause playback here");
} else if (strcmp(playerControl, "Stop") == 0) {
Serial.println("Stop playback here");
} else if (strcmp(playerControl, "Next") == 0) {
Serial.println("Skip to the next item here");
} else if (strcmp(playerControl, "Prev") == 0) {
Serial.println("Go to the previous item here");
} else {
Serial.println("Unsupported Alexa playback command");
return;
}
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void handleAlexaPlaybackCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa playback command");
return;
}
JsonVariantConst playerControlValue = root[offbeat::alexa::examples::kPlayerControlKey];
if (playerControlValue.isNull()) {
Serial.println("No Alexa playback payload");
return;
}
applyAlexaPlaybackCommand(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(playerControlValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
playback pause
{
"playerControl" : "Pause",
"endpointId" : "the endpoint id"
}
{"playerControl": "Pause", "endpointId": "the endpoint id"}
void applyAlexaPlaybackCommand(const char* endpointId, const char* playerControl) {
Serial.print("Apply playback command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
if (strcmp(playerControl, "Play") == 0) {
Serial.println("Start playback here");
} else if (strcmp(playerControl, "Pause") == 0) {
Serial.println("Pause playback here");
} else if (strcmp(playerControl, "Stop") == 0) {
Serial.println("Stop playback here");
} else if (strcmp(playerControl, "Next") == 0) {
Serial.println("Skip to the next item here");
} else if (strcmp(playerControl, "Prev") == 0) {
Serial.println("Go to the previous item here");
} else {
Serial.println("Unsupported Alexa playback command");
return;
}
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void handleAlexaPlaybackCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa playback command");
return;
}
JsonVariantConst playerControlValue = root[offbeat::alexa::examples::kPlayerControlKey];
if (playerControlValue.isNull()) {
Serial.println("No Alexa playback payload");
return;
}
applyAlexaPlaybackCommand(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(playerControlValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
playback play
{
"playerControl" : "Play",
"endpointId" : "the endpoint id"
}
{"playerControl": "Play", "endpointId": "the endpoint id"}
void applyAlexaPlaybackCommand(const char* endpointId, const char* playerControl) {
Serial.print("Apply playback command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
if (strcmp(playerControl, "Play") == 0) {
Serial.println("Start playback here");
} else if (strcmp(playerControl, "Pause") == 0) {
Serial.println("Pause playback here");
} else if (strcmp(playerControl, "Stop") == 0) {
Serial.println("Stop playback here");
} else if (strcmp(playerControl, "Next") == 0) {
Serial.println("Skip to the next item here");
} else if (strcmp(playerControl, "Prev") == 0) {
Serial.println("Go to the previous item here");
} else {
Serial.println("Unsupported Alexa playback command");
return;
}
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void handleAlexaPlaybackCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa playback command");
return;
}
JsonVariantConst playerControlValue = root[offbeat::alexa::examples::kPlayerControlKey];
if (playerControlValue.isNull()) {
Serial.println("No Alexa playback payload");
return;
}
applyAlexaPlaybackCommand(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(playerControlValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
playback previous
{
"playerControl" : "Prev",
"endpointId" : "the endpoint id"
}
{"playerControl": "Prev", "endpointId": "the endpoint id"}
void applyAlexaPlaybackCommand(const char* endpointId, const char* playerControl) {
Serial.print("Apply playback command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
if (strcmp(playerControl, "Play") == 0) {
Serial.println("Start playback here");
} else if (strcmp(playerControl, "Pause") == 0) {
Serial.println("Pause playback here");
} else if (strcmp(playerControl, "Stop") == 0) {
Serial.println("Stop playback here");
} else if (strcmp(playerControl, "Next") == 0) {
Serial.println("Skip to the next item here");
} else if (strcmp(playerControl, "Prev") == 0) {
Serial.println("Go to the previous item here");
} else {
Serial.println("Unsupported Alexa playback command");
return;
}
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void handleAlexaPlaybackCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa playback command");
return;
}
JsonVariantConst playerControlValue = root[offbeat::alexa::examples::kPlayerControlKey];
if (playerControlValue.isNull()) {
Serial.println("No Alexa playback payload");
return;
}
applyAlexaPlaybackCommand(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(playerControlValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
playback rewind
{
"playerControl" : "Prev",
"endpointId" : "the endpoint id"
}
{"playerControl": "Prev", "endpointId": "the endpoint id"}
void applyAlexaPlaybackCommand(const char* endpointId, const char* playerControl) {
Serial.print("Apply playback command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
if (strcmp(playerControl, "Play") == 0) {
Serial.println("Start playback here");
} else if (strcmp(playerControl, "Pause") == 0) {
Serial.println("Pause playback here");
} else if (strcmp(playerControl, "Stop") == 0) {
Serial.println("Stop playback here");
} else if (strcmp(playerControl, "Next") == 0) {
Serial.println("Skip to the next item here");
} else if (strcmp(playerControl, "Prev") == 0) {
Serial.println("Go to the previous item here");
} else {
Serial.println("Unsupported Alexa playback command");
return;
}
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void handleAlexaPlaybackCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa playback command");
return;
}
JsonVariantConst playerControlValue = root[offbeat::alexa::examples::kPlayerControlKey];
if (playerControlValue.isNull()) {
Serial.println("No Alexa playback payload");
return;
}
applyAlexaPlaybackCommand(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(playerControlValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
playback start over
{
"playerControl" : "Prev",
"endpointId" : "the endpoint id"
}
{"playerControl": "Prev", "endpointId": "the endpoint id"}
void applyAlexaPlaybackCommand(const char* endpointId, const char* playerControl) {
Serial.print("Apply playback command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
if (strcmp(playerControl, "Play") == 0) {
Serial.println("Start playback here");
} else if (strcmp(playerControl, "Pause") == 0) {
Serial.println("Pause playback here");
} else if (strcmp(playerControl, "Stop") == 0) {
Serial.println("Stop playback here");
} else if (strcmp(playerControl, "Next") == 0) {
Serial.println("Skip to the next item here");
} else if (strcmp(playerControl, "Prev") == 0) {
Serial.println("Go to the previous item here");
} else {
Serial.println("Unsupported Alexa playback command");
return;
}
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void handleAlexaPlaybackCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa playback command");
return;
}
JsonVariantConst playerControlValue = root[offbeat::alexa::examples::kPlayerControlKey];
if (playerControlValue.isNull()) {
Serial.println("No Alexa playback payload");
return;
}
applyAlexaPlaybackCommand(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(playerControlValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
playback stop
{
"playerControl" : "Stop",
"endpointId" : "the endpoint id"
}
{"playerControl": "Stop", "endpointId": "the endpoint id"}
void applyAlexaPlaybackCommand(const char* endpointId, const char* playerControl) {
Serial.print("Apply playback command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
if (strcmp(playerControl, "Play") == 0) {
Serial.println("Start playback here");
} else if (strcmp(playerControl, "Pause") == 0) {
Serial.println("Pause playback here");
} else if (strcmp(playerControl, "Stop") == 0) {
Serial.println("Stop playback here");
} else if (strcmp(playerControl, "Next") == 0) {
Serial.println("Skip to the next item here");
} else if (strcmp(playerControl, "Prev") == 0) {
Serial.println("Go to the previous item here");
} else {
Serial.println("Unsupported Alexa playback command");
return;
}
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void handleAlexaPlaybackCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa playback command");
return;
}
JsonVariantConst playerControlValue = root[offbeat::alexa::examples::kPlayerControlKey];
if (playerControlValue.isNull()) {
Serial.println("No Alexa playback payload");
return;
}
applyAlexaPlaybackCommand(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(playerControlValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
skip channels
{
"skipChannel" : 1,
"endpointId" : "the endpoint id"
}
{"skipChannel": 1, "endpointId": "the endpoint id"}
void applyAlexaSetChannel(const char* endpointId, long channelNumber) {
Serial.print("Set channel on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(channelNumber);
Serial.print("SET_CHANNEL=");
Serial.println(channelNumber);
}
void applyAlexaSkipChannel(const char* endpointId, long channelOffset) {
Serial.print("Skip channel on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(channelOffset);
Serial.print("SKIP_CHANNEL=");
Serial.println(channelOffset);
}
void handleAlexaChannelCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa channel command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst setChannelValue = root[offbeat::alexa::examples::kSetChannelKey];
JsonVariantConst skipChannelValue = root[offbeat::alexa::examples::kSkipChannelKey];
if (!setChannelValue.isNull()) {
applyAlexaSetChannel(endpointId, offbeat::alexa::examples::readLong(setChannelValue));
} else if (!skipChannelValue.isNull()) {
applyAlexaSkipChannel(endpointId, offbeat::alexa::examples::readLong(skipChannelValue));
} else {
Serial.println("No Alexa channel payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
change channel
{
"endpointId" : "the endpoint id",
"SetChannel" : 1
}
{"endpointId": "the endpoint id", "SetChannel": 1}
void applyAlexaSetChannel(const char* endpointId, long channelNumber) {
Serial.print("Set channel on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(channelNumber);
Serial.print("SET_CHANNEL=");
Serial.println(channelNumber);
}
void applyAlexaSkipChannel(const char* endpointId, long channelOffset) {
Serial.print("Skip channel on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(channelOffset);
Serial.print("SKIP_CHANNEL=");
Serial.println(channelOffset);
}
void handleAlexaChannelCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa channel command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst setChannelValue = root[offbeat::alexa::examples::kSetChannelKey];
JsonVariantConst skipChannelValue = root[offbeat::alexa::examples::kSkipChannelKey];
if (!setChannelValue.isNull()) {
applyAlexaSetChannel(endpointId, offbeat::alexa::examples::readLong(setChannelValue));
} else if (!skipChannelValue.isNull()) {
applyAlexaSkipChannel(endpointId, offbeat::alexa::examples::readLong(skipChannelValue));
} else {
Serial.println("No Alexa channel payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set blind tilt
{
"setTiltPercent" : 60,
"endpointId" : "the endpoint id"
}
{"setTiltPercent": 60, "endpointId": "the endpoint id"}
void applyAlexaBlindTiltPercent(const char* endpointId, long tiltPercent) {
long clampedTiltPercent = clampPercent(tiltPercent);
long tiltDegrees = percentToDegrees(clampedTiltPercent);
Serial.print("Set blind tilt on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.print(clampedTiltPercent);
Serial.println("%");
Serial.print("TILT_PERCENT=");
Serial.println(clampedTiltPercent);
Serial.print("TILT_DEGREES=");
Serial.println(tiltDegrees);
}
void adjustAlexaBlindTiltPercent(const char* endpointId, long tiltPercentDelta) {
Serial.print("Adjust blind tilt on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.print(tiltPercentDelta);
Serial.println("%");
Serial.print("TILT_DELTA_PERCENT=");
Serial.println(tiltPercentDelta);
Serial.println("Update your tracked tilt state before driving the motor.");
}
void handleAlexaBlindTiltCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa blind tilt command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst rangeValue = root[offbeat::alexa::examples::kRangeValueKey];
JsonVariantConst rangeValueDelta = root[offbeat::alexa::examples::kRangeValueDeltaKey];
if (!rangeValue.isNull()) {
applyAlexaBlindTiltPercent(
endpointId, offbeat::alexa::examples::readLong(rangeValue));
} else if (!rangeValueDelta.isNull()) {
adjustAlexaBlindTiltPercent(
endpointId, offbeat::alexa::examples::readLong(rangeValueDelta));
} else {
Serial.println("No Alexa blind tilt payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
adjust blind tilt
{
"adjustTiltPercent" : 10,
"endpointId" : "the endpoint id"
}
{"adjustTiltPercent": 10, "endpointId": "the endpoint id"}
void applyAlexaBlindTiltPercent(const char* endpointId, long tiltPercent) {
long clampedTiltPercent = clampPercent(tiltPercent);
long tiltDegrees = percentToDegrees(clampedTiltPercent);
Serial.print("Set blind tilt on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.print(clampedTiltPercent);
Serial.println("%");
Serial.print("TILT_PERCENT=");
Serial.println(clampedTiltPercent);
Serial.print("TILT_DEGREES=");
Serial.println(tiltDegrees);
}
void adjustAlexaBlindTiltPercent(const char* endpointId, long tiltPercentDelta) {
Serial.print("Adjust blind tilt on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.print(tiltPercentDelta);
Serial.println("%");
Serial.print("TILT_DELTA_PERCENT=");
Serial.println(tiltPercentDelta);
Serial.println("Update your tracked tilt state before driving the motor.");
}
void handleAlexaBlindTiltCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa blind tilt command");
return;
}
const char* endpointId = offbeat::alexa::examples::readEndpointId(root);
JsonVariantConst rangeValue = root[offbeat::alexa::examples::kRangeValueKey];
JsonVariantConst rangeValueDelta = root[offbeat::alexa::examples::kRangeValueDeltaKey];
if (!rangeValue.isNull()) {
applyAlexaBlindTiltPercent(
endpointId, offbeat::alexa::examples::readLong(rangeValue));
} else if (!rangeValueDelta.isNull()) {
adjustAlexaBlindTiltPercent(
endpointId, offbeat::alexa::examples::readLong(rangeValueDelta));
} else {
Serial.println("No Alexa blind tilt payload");
return;
}
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
activate scene
{
"endpointId" : "the endpoint id",
"scenestate" : "TurnOn"
}
{"endpointId": "the endpoint id", "scenestate": "TurnOn"}
void applyAlexaSceneState(const char* endpointId, const char* sceneState) {
Serial.print("Apply scene command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(sceneState);
if (strcmp(sceneState, "TurnOn") == 0) {
Serial.println("Activate the scene here");
} else if (strcmp(sceneState, "TurnOff") == 0) {
Serial.println("Deactivate the scene here");
} else {
Serial.println("Unsupported Alexa scene command");
return;
}
Serial.print("SCENESTATE=");
Serial.println(sceneState);
}
void handleAlexaSceneCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa scene command");
return;
}
JsonVariantConst sceneStateValue = root[offbeat::alexa::examples::kSceneStateKey];
if (sceneStateValue.isNull()) {
Serial.println("No Alexa scene payload");
return;
}
applyAlexaSceneState(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(sceneStateValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
deactivate scene
{
"endpointId" : "the endpoint id",
"scenestate" : "TurnOff"
}
{"endpointId": "the endpoint id", "scenestate": "TurnOff"}
void applyAlexaSceneState(const char* endpointId, const char* sceneState) {
Serial.print("Apply scene command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(sceneState);
if (strcmp(sceneState, "TurnOn") == 0) {
Serial.println("Activate the scene here");
} else if (strcmp(sceneState, "TurnOff") == 0) {
Serial.println("Deactivate the scene here");
} else {
Serial.println("Unsupported Alexa scene command");
return;
}
Serial.print("SCENESTATE=");
Serial.println(sceneState);
}
void handleAlexaSceneCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa scene command");
return;
}
JsonVariantConst sceneStateValue = root[offbeat::alexa::examples::kSceneStateKey];
if (sceneStateValue.isNull()) {
Serial.println("No Alexa scene payload");
return;
}
applyAlexaSceneState(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(sceneStateValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set thermostat mode
{
"thermMode" : "COOL",
"endpointId" : "the endpoint id"
}
{"thermMode": "COOL", "endpointId": "the endpoint id"}
void applyAlexaPowerState(const char* endpointId, const char* powerState) {
Serial.print("Apply Alexa power command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(powerState);
if (strcmp(powerState, "TurnOn") == 0) {
Serial.println("Turn your relay or transistor on here");
} else if (strcmp(powerState, "TurnOff") == 0) {
Serial.println("Turn your relay or transistor off here");
} else {
Serial.println("Unsupported Alexa power command");
return;
}
Serial.print("POWERSTATE=");
Serial.println(powerState);
}
void handleAlexaPowerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa power command");
return;
}
JsonVariantConst powerStateValue = root[offbeat::alexa::examples::kPowerStateKey];
if (powerStateValue.isNull()) {
Serial.println("No Alexa powerstate payload");
return;
}
applyAlexaPowerState(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(powerStateValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set target temperature
{
"setTargetTemp" : "20.0;CELSIUS",
"endpointId" : "the endpoint id"
}
{"setTargetTemp": "20.0;CELSIUS", "endpointId": "the endpoint id"}
void applyAlexaPowerState(const char* endpointId, const char* powerState) {
Serial.print("Apply Alexa power command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(powerState);
if (strcmp(powerState, "TurnOn") == 0) {
Serial.println("Turn your relay or transistor on here");
} else if (strcmp(powerState, "TurnOff") == 0) {
Serial.println("Turn your relay or transistor off here");
} else {
Serial.println("Unsupported Alexa power command");
return;
}
Serial.print("POWERSTATE=");
Serial.println(powerState);
}
void handleAlexaPowerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa power command");
return;
}
JsonVariantConst powerStateValue = root[offbeat::alexa::examples::kPowerStateKey];
if (powerStateValue.isNull()) {
Serial.println("No Alexa powerstate payload");
return;
}
applyAlexaPowerState(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(powerStateValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
adjust target temperature
{
"adjTargetTemp" : "-3.0;CELSIUS",
"endpointId" : "the endpoint id"
}
{"adjTargetTemp": "-3.0;CELSIUS", "endpointId": "the endpoint id"}
void applyAlexaPowerState(const char* endpointId, const char* powerState) {
Serial.print("Apply Alexa power command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(powerState);
if (strcmp(powerState, "TurnOn") == 0) {
Serial.println("Turn your relay or transistor on here");
} else if (strcmp(powerState, "TurnOff") == 0) {
Serial.println("Turn your relay or transistor off here");
} else {
Serial.println("Unsupported Alexa power command");
return;
}
Serial.print("POWERSTATE=");
Serial.println(powerState);
}
void handleAlexaPowerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa power command");
return;
}
JsonVariantConst powerStateValue = root[offbeat::alexa::examples::kPowerStateKey];
if (powerStateValue.isNull()) {
Serial.println("No Alexa powerstate payload");
return;
}
applyAlexaPowerState(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(powerStateValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set mode
{
"endpointId" : "the endpoint id",
"setMode" : "normal"
}
{"endpointId": "the endpoint id", "setMode": "normal"}
void applyAlexaPowerState(const char* endpointId, const char* powerState) {
Serial.print("Apply Alexa power command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(powerState);
if (strcmp(powerState, "TurnOn") == 0) {
Serial.println("Turn your relay or transistor on here");
} else if (strcmp(powerState, "TurnOff") == 0) {
Serial.println("Turn your relay or transistor off here");
} else {
Serial.println("Unsupported Alexa power command");
return;
}
Serial.print("POWERSTATE=");
Serial.println(powerState);
}
void handleAlexaPowerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::alexa::examples::ParseStatus status =
offbeat::alexa::examples::parseRoot(payload, length, document, root);
if (status == offbeat::alexa::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Alexa power command");
return;
}
JsonVariantConst powerStateValue = root[offbeat::alexa::examples::kPowerStateKey];
if (powerStateValue.isNull()) {
Serial.println("No Alexa powerstate payload");
return;
}
applyAlexaPowerState(
offbeat::alexa::examples::readEndpointId(root),
offbeat::alexa::examples::readString(powerStateValue));
offbeat::alexa::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
Live camera view
Offbeat’s Alexa integration can show a live camera view on an Echo Show through
Alexa.CameraStreamController.
The device does not talk to Alexa directly and does not serve a stream URL. Offbeat handles the
InitializeCameraStreams directive, asks the device to push JPEG frames over its existing WebSocket,
relays those frames to the media gateway, and the gateway transcodes them to H.264 MPEG-TS HLS and
serves a short-lived, signed HTTPS URL that Alexa fetches.
|
Note
|
This is Alexa.CameraStreamController (HLS), not Alexa.RTCSessionController (WebRTC).
|
|
Note
|
The device contract is assistant-agnostic. The same firmware (or mock) streams identically
whether the device is linked to Alexa or Google Home: it receives the same startVideo/stopVideo
commands and pushes the same binary JPEG frames and motion readings. The platform adapts the stream to
each assistant. To use one camera with both, link the device to each assistant and enable the
CameraStreamController capability for each - no device-side change is required (see Live camera
view on the Google Home page).
|
Declaring a camera
A device is treated as a camera when the operator, in the app:
-
opens the device and adds the
CameraStreamControllercapability (Your devices → device → Device integrations → Alexa → Configure → checkCameraStreamController→ Update), -
sets the device’s display category to
CAMERA, and -
opens the camera settings for the device and enables the camera stream and its resolution.
The device id used on the WebSocket connection (?device=<endpointId>) is the endpoint id Alexa sees.
Once declared, Offbeat advertises Alexa.CameraStreamController with a cameraStreamConfigurations
block (protocol HLS, the configured resolution, authorizationTypes NONE, videoCodecs H264,
audioCodecs NONE) so Alexa discovers the camera.
Device commands (server to device)
Offbeat sends these over the device’s existing WebSocket connection.
Start live view
Sent when Alexa starts a live view. The value is the requested frame rate in frames per second
(default 5).
{"startVideo": 5}
The device must start sending JPEG frames (see Camera frames) until it receives stopVideo.
Stop live view
Sent when the live view ends (or when the stream is torn down).
{"stopVideo": ""}
The device must stop sending frames.
Device notifications (device to server)
Camera frames
While streaming, send each captured frame as a binary WebSocket message: the raw JPEG bytes, not JSON, on the same connection, at roughly the requested frame rate.
Do not publish a stream URL and do not upload snapshots - Offbeat relays the frames to the
media gateway, which produces the HLS stream and the still image Alexa needs. The imageUri (still)
is served by Offbeat from the live frame, so the device never provides it.
Typical settings: MJPEG 640x480 (configurable to 800x600) at 5 fps.
Motion detected
Report motion with the motion reading on the same connection.
{"motion": "ON"}
ON (case-insensitive) means motion detected. Report on change; the reference firmware also repeats
it roughly every 30 seconds.
Motion cleared
{"motion": "OFF"}
Any value other than ON is treated as "not detected". Offbeat maps this reading to
Alexa.MotionSensor (DETECTED / NOT_DETECTED) and reports it to Alexa.
Message envelope and connection
-
Device-to-server messages are bare
{"<key>": <value>}objects. -
The device is identified by its WebSocket connection (
wss://www.offbeat-iot.com/ws?device=<endpointId>). If a payload must carry the device explicitly, use"deviceId"- not"endpointId":
{"deviceId": "YOUR_DEVICE_ID", "motion": "ON"}
-
Prefer one device per connection. Reconnect with backoff if the socket drops.
-
The device only needs outbound
wss://access; it never exposes a public URL. Offbeat and the media gateway provide the HTTPS stream that Alexa fetches.
Codec, profile and resolution
The device sends MJPEG (JPEG frames); the media gateway transcodes them to H.264 MPEG-TS HLS,
which is what the Echo Show plays. Discovery and the InitializeCameraStreams response both
advertise the codec as H264 (the codec only - the profile is not part of the advertisement).
Amazon’s camera relay is strict about the H.264 profile:
-
It decodes only the Baseline or Main profile. libx264’s default (High) is not decodable and fails silently: the Echo shows the still, then "the camera isn’t responding".
-
Every segment must carry in-band SPS/PPS (parameter sets repeated in each segment); without them the relay cannot begin decoding mid-stream.
The media gateway therefore encodes with:
ffmpeg -c:v libx264 -profile:v baseline -x264-params repeat-headers=1 ...
Resolutions 640x480 and 800x600 are supported (within Alexa’s 480-1080 px range); the default
frame rate is 5.
Startup and preload
Amazon’s relay fetches the signed uri immediately after the InitializeCameraStreams response,
within a ~6 second budget. If the playlist is not live yet, the relay gets the gateway’s 404
("no active stream"), fetches nothing else, and the Echo shows the still followed by
"the camera isn’t responding".
The server must therefore have the playlist live (HTTP 200) before responding to
InitializeCameraStreams. Offbeat does this in CameraStreamInitializeHandler: after telling the
device to start streaming it polls the signed stream URI until it returns 200, bounded by
alexa.camera.preload-timeout-ms (default 3500 ms, kept under the 6 second budget), then responds.
On timeout it still responds so the flow is never blocked. The device’s first frame should therefore
arrive within a couple of seconds of startVideo.
Relay access (for debugging)
The stream must be reachable by Amazon’s camera relay over public HTTPS on port 443 with a trusted
certificate (the signed URL is self-authorizing: authorizationType NONE). A relay fetch looks like
this in an access log:
98.94.44.153 - - [10/Oct/2026:10:51:00 +0000] "GET /s/<token>/index.m3u8 HTTP/1.1" 200 0 "-" "GStreamer souphttpsrc libsoup/2.48.1"
-
User agent:
GStreamer souphttpsrc libsoup/2.48.1. -
Source addresses: Amazon AWS ASNs 16509 and 14618.
-
After
index.m3u8returns200, the relay fetchesseg*.tscontinuously; the still (snapshot.jpg) is fetched separately.
If the playlist is fetched once and returns 404, that is the startup race above. If the playlist
returns 200 but no segments are requested, suspect the H.264 profile or the in-band SPS/PPS.