Using the Google Home integration
These sections show the websocket JSON sent to the device for the supported Google Home execute intents together with matching Arduino device examples from microcontroller-examples.
turn on
{
"endpointId" : "123",
"powerstate" : "TurnOn"
}
{"endpointId": "123", "powerstate": "TurnOn"}
void applyGoogleHomePowerState(const char* endpointId, const char* powerState) {
Serial.print("Apply Google Home power command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(powerState);
if (strcmp(powerState, "TurnOn") == 0) {
Serial.println("Turn your output on here");
} else if (strcmp(powerState, "TurnOff") == 0) {
Serial.println("Turn your output off here");
} else {
Serial.println("Unsupported Google Home power command");
return;
}
Serial.print("POWERSTATE=");
Serial.println(powerState);
}
void handleGoogleHomePowerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home power command");
return;
}
JsonVariantConst powerStateValue = root[offbeat::google_home::examples::kPowerStateKey];
if (powerStateValue.isNull()) {
Serial.println("No Google Home powerstate payload");
return;
}
applyGoogleHomePowerState(
offbeat::google_home::examples::readEndpointId(root),
offbeat::google_home::examples::readString(powerStateValue));
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
turn off
{
"endpointId" : "123",
"powerstate" : "TurnOff"
}
{"endpointId": "123", "powerstate": "TurnOff"}
void applyGoogleHomePowerState(const char* endpointId, const char* powerState) {
Serial.print("Apply Google Home power command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(powerState);
if (strcmp(powerState, "TurnOn") == 0) {
Serial.println("Turn your output on here");
} else if (strcmp(powerState, "TurnOff") == 0) {
Serial.println("Turn your output off here");
} else {
Serial.println("Unsupported Google Home power command");
return;
}
Serial.print("POWERSTATE=");
Serial.println(powerState);
}
void handleGoogleHomePowerCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home power command");
return;
}
JsonVariantConst powerStateValue = root[offbeat::google_home::examples::kPowerStateKey];
if (powerStateValue.isNull()) {
Serial.println("No Google Home powerstate payload");
return;
}
applyGoogleHomePowerState(
offbeat::google_home::examples::readEndpointId(root),
offbeat::google_home::examples::readString(powerStateValue));
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
adjust volume
{
"endpointId" : "123",
"volumesteps" : -1
}
{"endpointId": "123", "volumesteps": -1}
void applyGoogleHomeSetVolume(const char* endpointId, long volume) {
Serial.print("Set volume on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(volume);
Serial.print("VOLUME=");
Serial.println(volume);
}
void applyGoogleHomeAdjustVolume(const char* endpointId, long volumeSteps) {
Serial.print("Adjust volume on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(volumeSteps);
Serial.print("VOLUME_STEPS=");
Serial.println(volumeSteps);
}
void handleGoogleHomeVolumeCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home volume command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst volumeValue = root[offbeat::google_home::examples::kVolumeKey];
JsonVariantConst volumeStepsValue = root[offbeat::google_home::examples::kVolumeStepsKey];
if (!volumeValue.isNull()) {
applyGoogleHomeSetVolume(endpointId, offbeat::google_home::examples::readLong(volumeValue));
} else if (!volumeStepsValue.isNull()) {
applyGoogleHomeAdjustVolume(endpointId, offbeat::google_home::examples::readLong(volumeStepsValue));
} else {
Serial.println("No Google Home volume payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set volume
{
"volume" : 665,
"endpointId" : "123"
}
{"volume": 665, "endpointId": "123"}
void applyGoogleHomeSetVolume(const char* endpointId, long volume) {
Serial.print("Set volume on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(volume);
Serial.print("VOLUME=");
Serial.println(volume);
}
void applyGoogleHomeAdjustVolume(const char* endpointId, long volumeSteps) {
Serial.print("Adjust volume on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(volumeSteps);
Serial.print("VOLUME_STEPS=");
Serial.println(volumeSteps);
}
void handleGoogleHomeVolumeCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home volume command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst volumeValue = root[offbeat::google_home::examples::kVolumeKey];
JsonVariantConst volumeStepsValue = root[offbeat::google_home::examples::kVolumeStepsKey];
if (!volumeValue.isNull()) {
applyGoogleHomeSetVolume(endpointId, offbeat::google_home::examples::readLong(volumeValue));
} else if (!volumeStepsValue.isNull()) {
applyGoogleHomeAdjustVolume(endpointId, offbeat::google_home::examples::readLong(volumeStepsValue));
} else {
Serial.println("No Google Home volume payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set color
{
"saturation" : 123.0,
"brightness" : 456.0,
"endpointId" : "123",
"hue" : 665.0
}
{"saturation": 123.0, "brightness": 456.0, "endpointId": "123", "hue": 665.0}
void applyGoogleHomeColorCommand(const char* endpointId, double hue, double saturation, double brightness) {
Serial.print("Set color on ");
Serial.println(endpointId);
offbeat::google_home::examples::printLine("Hue: ", hue, 2);
offbeat::google_home::examples::printLine("Saturation: ", saturation, 2);
offbeat::google_home::examples::printLine("Brightness: ", brightness, 2);
Serial.print("HUE=");
Serial.println(hue, 2);
Serial.print("SATURATION=");
Serial.println(saturation, 2);
Serial.print("BRIGHTNESS=");
Serial.println(brightness, 2);
}
void handleGoogleHomeColorCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home color command");
return;
}
JsonVariantConst hueValue = root[offbeat::google_home::examples::kHueKey];
JsonVariantConst saturationValue = root[offbeat::google_home::examples::kSaturationKey];
JsonVariantConst brightnessValue = root[offbeat::google_home::examples::kBrightnessKey];
if (hueValue.isNull() || saturationValue.isNull() || brightnessValue.isNull()) {
Serial.println("Incomplete Google Home color payload");
return;
}
applyGoogleHomeColorCommand(
offbeat::google_home::examples::readEndpointId(root),
offbeat::google_home::examples::readDouble(hueValue),
offbeat::google_home::examples::readDouble(saturationValue),
offbeat::google_home::examples::readDouble(brightnessValue));
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set color temperature
{
"endpointId" : "123",
"setColorTemp" : 4000
}
{"endpointId": "123", "setColorTemp": 4000}
void applyGoogleHomeColorCommand(const char* endpointId, double hue, double saturation, double brightness) {
Serial.print("Set color on ");
Serial.println(endpointId);
offbeat::google_home::examples::printLine("Hue: ", hue, 2);
offbeat::google_home::examples::printLine("Saturation: ", saturation, 2);
offbeat::google_home::examples::printLine("Brightness: ", brightness, 2);
Serial.print("HUE=");
Serial.println(hue, 2);
Serial.print("SATURATION=");
Serial.println(saturation, 2);
Serial.print("BRIGHTNESS=");
Serial.println(brightness, 2);
}
void handleGoogleHomeColorCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home color command");
return;
}
JsonVariantConst hueValue = root[offbeat::google_home::examples::kHueKey];
JsonVariantConst saturationValue = root[offbeat::google_home::examples::kSaturationKey];
JsonVariantConst brightnessValue = root[offbeat::google_home::examples::kBrightnessKey];
if (hueValue.isNull() || saturationValue.isNull() || brightnessValue.isNull()) {
Serial.println("Incomplete Google Home color payload");
return;
}
applyGoogleHomeColorCommand(
offbeat::google_home::examples::readEndpointId(root),
offbeat::google_home::examples::readDouble(hueValue),
offbeat::google_home::examples::readDouble(saturationValue),
offbeat::google_home::examples::readDouble(brightnessValue));
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set brightness to 456
{
"brightness" : 456,
"endpointId" : "123"
}
{"brightness": 456, "endpointId": "123"}
void applyGoogleHomeBrightnessPercent(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 applyGoogleHomeBrightnessWeight(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 applyGoogleHomeBrightnessAbsolute(const char* endpointId, long brightnessValue) {
Serial.print("Set absolute brightness on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(brightnessValue);
Serial.print("BRIGHTNESS=");
Serial.println(brightnessValue);
}
void handleGoogleHomeBrightnessCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home brightness command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst percentValue = root[offbeat::google_home::examples::kAdjustBrightnessPercentKey];
JsonVariantConst weightValue = root[offbeat::google_home::examples::kAdjustBrightnessWeightKey];
JsonVariantConst brightnessValue = root[offbeat::google_home::examples::kBrightnessKey];
if (!percentValue.isNull()) {
applyGoogleHomeBrightnessPercent(endpointId, offbeat::google_home::examples::readLong(percentValue));
} else if (!weightValue.isNull()) {
applyGoogleHomeBrightnessWeight(endpointId, offbeat::google_home::examples::readLong(weightValue));
} else if (!brightnessValue.isNull()) {
applyGoogleHomeBrightnessAbsolute(endpointId, offbeat::google_home::examples::readLong(brightnessValue));
} else {
Serial.println("No Google Home brightness payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set brightness to 416
{
"brightness" : 416,
"endpointId" : "123"
}
{"brightness": 416, "endpointId": "123"}
void applyGoogleHomeBrightnessPercent(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 applyGoogleHomeBrightnessWeight(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 applyGoogleHomeBrightnessAbsolute(const char* endpointId, long brightnessValue) {
Serial.print("Set absolute brightness on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(brightnessValue);
Serial.print("BRIGHTNESS=");
Serial.println(brightnessValue);
}
void handleGoogleHomeBrightnessCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home brightness command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst percentValue = root[offbeat::google_home::examples::kAdjustBrightnessPercentKey];
JsonVariantConst weightValue = root[offbeat::google_home::examples::kAdjustBrightnessWeightKey];
JsonVariantConst brightnessValue = root[offbeat::google_home::examples::kBrightnessKey];
if (!percentValue.isNull()) {
applyGoogleHomeBrightnessPercent(endpointId, offbeat::google_home::examples::readLong(percentValue));
} else if (!weightValue.isNull()) {
applyGoogleHomeBrightnessWeight(endpointId, offbeat::google_home::examples::readLong(weightValue));
} else if (!brightnessValue.isNull()) {
applyGoogleHomeBrightnessAbsolute(endpointId, offbeat::google_home::examples::readLong(brightnessValue));
} else {
Serial.println("No Google Home brightness payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
adjust brightness percent
{
"adjustBrightnessPercent" : 20,
"endpointId" : "123"
}
{"adjustBrightnessPercent": 20, "endpointId": "123"}
void applyGoogleHomeBrightnessPercent(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 applyGoogleHomeBrightnessWeight(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 applyGoogleHomeBrightnessAbsolute(const char* endpointId, long brightnessValue) {
Serial.print("Set absolute brightness on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(brightnessValue);
Serial.print("BRIGHTNESS=");
Serial.println(brightnessValue);
}
void handleGoogleHomeBrightnessCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home brightness command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst percentValue = root[offbeat::google_home::examples::kAdjustBrightnessPercentKey];
JsonVariantConst weightValue = root[offbeat::google_home::examples::kAdjustBrightnessWeightKey];
JsonVariantConst brightnessValue = root[offbeat::google_home::examples::kBrightnessKey];
if (!percentValue.isNull()) {
applyGoogleHomeBrightnessPercent(endpointId, offbeat::google_home::examples::readLong(percentValue));
} else if (!weightValue.isNull()) {
applyGoogleHomeBrightnessWeight(endpointId, offbeat::google_home::examples::readLong(weightValue));
} else if (!brightnessValue.isNull()) {
applyGoogleHomeBrightnessAbsolute(endpointId, offbeat::google_home::examples::readLong(brightnessValue));
} else {
Serial.println("No Google Home brightness payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
adjust brightness weight
{
"endpointId" : "123",
"adjustBrightnessWeight" : -1
}
{"endpointId": "123", "adjustBrightnessWeight": -1}
void applyGoogleHomeBrightnessPercent(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 applyGoogleHomeBrightnessWeight(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 applyGoogleHomeBrightnessAbsolute(const char* endpointId, long brightnessValue) {
Serial.print("Set absolute brightness on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(brightnessValue);
Serial.print("BRIGHTNESS=");
Serial.println(brightnessValue);
}
void handleGoogleHomeBrightnessCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home brightness command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst percentValue = root[offbeat::google_home::examples::kAdjustBrightnessPercentKey];
JsonVariantConst weightValue = root[offbeat::google_home::examples::kAdjustBrightnessWeightKey];
JsonVariantConst brightnessValue = root[offbeat::google_home::examples::kBrightnessKey];
if (!percentValue.isNull()) {
applyGoogleHomeBrightnessPercent(endpointId, offbeat::google_home::examples::readLong(percentValue));
} else if (!weightValue.isNull()) {
applyGoogleHomeBrightnessWeight(endpointId, offbeat::google_home::examples::readLong(weightValue));
} else if (!brightnessValue.isNull()) {
applyGoogleHomeBrightnessAbsolute(endpointId, offbeat::google_home::examples::readLong(brightnessValue));
} else {
Serial.println("No Google Home brightness payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
media resume
{
"playerControl" : "Play",
"endpointId" : "123"
}
{"playerControl": "Play", "endpointId": "123"}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
media stop
{
"playerControl" : "Stop",
"endpointId" : "123"
}
{"playerControl": "Stop", "endpointId": "123"}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
media next
{
"playerControl" : "Next",
"endpointId" : "123"
}
{"playerControl": "Next", "endpointId": "123"}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
media previous
{
"playerControl" : "Prev",
"endpointId" : "123"
}
{"playerControl": "Prev", "endpointId": "123"}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
media pause
{
"playerControl" : "Pause",
"endpointId" : "123"
}
{"playerControl": "Pause", "endpointId": "123"}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
media seek relative
{
"endpointId" : "123",
"Seek" : -10000
}
{"endpointId": "123", "Seek": -10000}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
media seek absolute
{
"endpointId" : "123",
"SeekAbsolute" : 30000
}
{"endpointId": "123", "SeekAbsolute": 30000}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
media repeat
{
"playerControl" : "Repeat",
"endpointId" : "123"
}
{"playerControl": "Repeat", "endpointId": "123"}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
media shuffle
{
"playerControl" : "Shuffle",
"endpointId" : "123"
}
{"playerControl": "Shuffle", "endpointId": "123"}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
closed captioning on
{
"playerControl" : "CaptionsOn",
"endpointId" : "123"
}
{"playerControl": "CaptionsOn", "endpointId": "123"}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
closed captioning off
{
"playerControl" : "CaptionsOff",
"endpointId" : "123"
}
{"playerControl": "CaptionsOff", "endpointId": "123"}
void applyGoogleHomePlayerControl(const char* endpointId, const char* playerControl) {
Serial.print("Apply media command for ");
Serial.print(endpointId);
Serial.print(": ");
Serial.println(playerControl);
Serial.print("PLAYER_CONTROL=");
Serial.println(playerControl);
}
void applyGoogleHomeSeekAbsolute(const char* endpointId, long absolutePositionMs) {
Serial.print("Seek absolute on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.println(absolutePositionMs);
Serial.print("SEEK_ABSOLUTE_MS=");
Serial.println(absolutePositionMs);
}
void applyGoogleHomeSeekRelative(const char* endpointId, long relativePositionMs) {
Serial.print("Seek relative on ");
Serial.print(endpointId);
Serial.print(" by ");
Serial.println(relativePositionMs);
Serial.print("SEEK_RELATIVE_MS=");
Serial.println(relativePositionMs);
}
void handleGoogleHomeMediaCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home media command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst playerControlValue = root[offbeat::google_home::examples::kPlayerControlKey];
JsonVariantConst seekAbsoluteValue = root[offbeat::google_home::examples::kSeekAbsoluteKey];
JsonVariantConst seekRelativeValue = root[offbeat::google_home::examples::kSeekRelativeKey];
if (!playerControlValue.isNull()) {
applyGoogleHomePlayerControl(endpointId, offbeat::google_home::examples::readString(playerControlValue));
} else if (!seekAbsoluteValue.isNull()) {
applyGoogleHomeSeekAbsolute(endpointId, offbeat::google_home::examples::readLong(seekAbsoluteValue));
} else if (!seekRelativeValue.isNull()) {
applyGoogleHomeSeekRelative(endpointId, offbeat::google_home::examples::readLong(seekRelativeValue));
} else {
Serial.println("No Google Home media payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
select channel
{
"endpointId" : "123",
"SetChannel" : 9
}
{"endpointId": "123", "SetChannel": 9}
void applyGoogleHomeSetChannel(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 applyGoogleHomeSkipChannel(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 handleGoogleHomeChannelCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home channel command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst setChannelValue = root[offbeat::google_home::examples::kSetChannelKey];
JsonVariantConst skipChannelValue = root[offbeat::google_home::examples::kSkipChannelKey];
if (!setChannelValue.isNull()) {
applyGoogleHomeSetChannel(endpointId, offbeat::google_home::examples::readLong(setChannelValue));
} else if (!skipChannelValue.isNull()) {
applyGoogleHomeSkipChannel(endpointId, offbeat::google_home::examples::readLong(skipChannelValue));
} else {
Serial.println("No Google Home channel payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
relative channel
{
"skipChannel" : 1,
"endpointId" : "123"
}
{"skipChannel": 1, "endpointId": "123"}
void applyGoogleHomeSetChannel(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 applyGoogleHomeSkipChannel(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 handleGoogleHomeChannelCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home channel command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst setChannelValue = root[offbeat::google_home::examples::kSetChannelKey];
JsonVariantConst skipChannelValue = root[offbeat::google_home::examples::kSkipChannelKey];
if (!setChannelValue.isNull()) {
applyGoogleHomeSetChannel(endpointId, offbeat::google_home::examples::readLong(setChannelValue));
} else if (!skipChannelValue.isNull()) {
applyGoogleHomeSkipChannel(endpointId, offbeat::google_home::examples::readLong(skipChannelValue));
} else {
Serial.println("No Google Home channel payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
return channel
{
"skipChannel" : -1,
"endpointId" : "123"
}
{"skipChannel": -1, "endpointId": "123"}
void applyGoogleHomeSetChannel(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 applyGoogleHomeSkipChannel(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 handleGoogleHomeChannelCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home channel command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst setChannelValue = root[offbeat::google_home::examples::kSetChannelKey];
JsonVariantConst skipChannelValue = root[offbeat::google_home::examples::kSkipChannelKey];
if (!setChannelValue.isNull()) {
applyGoogleHomeSetChannel(endpointId, offbeat::google_home::examples::readLong(setChannelValue));
} else if (!skipChannelValue.isNull()) {
applyGoogleHomeSkipChannel(endpointId, offbeat::google_home::examples::readLong(skipChannelValue));
} else {
Serial.println("No Google Home channel payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set blind tilt percent
{
"setTiltPercent" : 60,
"endpointId" : "123"
}
{"setTiltPercent": 60, "endpointId": "123"}
void applyGoogleHomeBlindTiltPercent(const char* endpointId, long tiltPercent) {
long clampedTiltPercent = clampPercent(tiltPercent);
long tiltDegrees = percentToDegrees(clampedTiltPercent);
Serial.print("Set Google Home 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 applyGoogleHomeBlindTiltDegrees(const char* endpointId, long tiltDegrees) {
long clampedTiltDegrees = clampDegrees(tiltDegrees);
long tiltPercent = degreesToPercent(clampedTiltDegrees);
Serial.print("Set Google Home blind tilt on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.print(clampedTiltDegrees);
Serial.println(" degrees");
Serial.print("TILT_DEGREES=");
Serial.println(clampedTiltDegrees);
Serial.print("TILT_PERCENT=");
Serial.println(tiltPercent);
}
void handleGoogleHomeBlindTiltCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home blind tilt command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst rotationPercent = root[offbeat::google_home::examples::kRotationPercentKey];
JsonVariantConst rotationDegrees = root[offbeat::google_home::examples::kRotationDegreesKey];
if (!rotationPercent.isNull()) {
applyGoogleHomeBlindTiltPercent(
endpointId, offbeat::google_home::examples::readLong(rotationPercent));
} else if (!rotationDegrees.isNull()) {
applyGoogleHomeBlindTiltDegrees(
endpointId, offbeat::google_home::examples::readLong(rotationDegrees));
} else {
Serial.println("No Google Home blind tilt payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
set blind tilt degrees
{
"endpointId" : "123",
"setTiltDegrees" : 90
}
{"endpointId": "123", "setTiltDegrees": 90}
void applyGoogleHomeBlindTiltPercent(const char* endpointId, long tiltPercent) {
long clampedTiltPercent = clampPercent(tiltPercent);
long tiltDegrees = percentToDegrees(clampedTiltPercent);
Serial.print("Set Google Home 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 applyGoogleHomeBlindTiltDegrees(const char* endpointId, long tiltDegrees) {
long clampedTiltDegrees = clampDegrees(tiltDegrees);
long tiltPercent = degreesToPercent(clampedTiltDegrees);
Serial.print("Set Google Home blind tilt on ");
Serial.print(endpointId);
Serial.print(" to ");
Serial.print(clampedTiltDegrees);
Serial.println(" degrees");
Serial.print("TILT_DEGREES=");
Serial.println(clampedTiltDegrees);
Serial.print("TILT_PERCENT=");
Serial.println(tiltPercent);
}
void handleGoogleHomeBlindTiltCommand(uint8_t* payload, size_t length) {
StaticJsonDocument<256> document;
JsonObjectConst root;
offbeat::google_home::examples::ParseStatus status =
offbeat::google_home::examples::parseRoot(payload, length, document, root);
if (status == offbeat::google_home::examples::ParseStatus::kInvalidPayload) {
Serial.println("Unable to parse Google Home blind tilt command");
return;
}
const char* endpointId = offbeat::google_home::examples::readEndpointId(root);
JsonVariantConst rotationPercent = root[offbeat::google_home::examples::kRotationPercentKey];
JsonVariantConst rotationDegrees = root[offbeat::google_home::examples::kRotationDegreesKey];
if (!rotationPercent.isNull()) {
applyGoogleHomeBlindTiltPercent(
endpointId, offbeat::google_home::examples::readLong(rotationPercent));
} else if (!rotationDegrees.isNull()) {
applyGoogleHomeBlindTiltDegrees(
endpointId, offbeat::google_home::examples::readLong(rotationDegrees));
} else {
Serial.println("No Google Home blind tilt payload");
return;
}
offbeat::google_home::examples::printEndpoint(root);
Serial.println("TEST:PASS");
}
lock lock
{
"endpointId" : "123",
"lockstate" : "Lock"
}
{"endpointId": "123", "lockstate": "Lock"}
Unresolved directive in ../../../target/generated-doc-sections/partials/_google-home-execute-sections.adoc - include::https://raw.githubusercontent.com/Offbeat-IoT/microcontroller-examples/HEAD/examples/google-home/LockCommand/LockCommand.ino[tags=google-home-lock-command-docs,indent=0]
lock unlock
{
"endpointId" : "123",
"lockstate" : "Unlock"
}
{"endpointId": "123", "lockstate": "Unlock"}
Unresolved directive in ../../../target/generated-doc-sections/partials/_google-home-execute-sections.adoc - include::https://raw.githubusercontent.com/Offbeat-IoT/microcontroller-examples/HEAD/examples/google-home/LockCommand/LockCommand.ino[tags=google-home-lock-command-docs,indent=0]
select input
{
"endpointId" : "123",
"setInput" : "HDMI 1"
}
{"endpointId": "123", "setInput": "HDMI 1"}
Unresolved directive in ../../../target/generated-doc-sections/partials/_google-home-execute-sections.adoc - include::https://raw.githubusercontent.com/Offbeat-IoT/microcontroller-examples/HEAD/examples/google-home/LockCommand/LockCommand.ino[tags=google-home-lock-command-docs,indent=0]
toggle on
{
"CustomMute.powerstate" : "TurnOn",
"endpointId" : "123"
}
{"CustomMute.powerstate": "TurnOn", "endpointId": "123"}
Unresolved directive in ../../../target/generated-doc-sections/partials/_google-home-execute-sections.adoc - include::https://raw.githubusercontent.com/Offbeat-IoT/microcontroller-examples/HEAD/examples/google-home/LockCommand/LockCommand.ino[tags=google-home-lock-command-docs,indent=0]
set mode
{
"endpointId" : "123",
"CustomMode.setMode" : "ModeA"
}
{"endpointId": "123", "CustomMode.setMode": "ModeA"}
Unresolved directive in ../../../target/generated-doc-sections/partials/_google-home-execute-sections.adoc - include::https://raw.githubusercontent.com/Offbeat-IoT/microcontroller-examples/HEAD/examples/google-home/LockCommand/LockCommand.ino[tags=google-home-lock-command-docs,indent=0]
activate scene
{
"endpointId" : "123",
"scenestate" : "TurnOn"
}
{"endpointId": "123", "scenestate": "TurnOn"}
Unresolved directive in ../../../target/generated-doc-sections/partials/_google-home-execute-sections.adoc - include::https://raw.githubusercontent.com/Offbeat-IoT/microcontroller-examples/HEAD/examples/google-home/LockCommand/LockCommand.ino[tags=google-home-lock-command-docs,indent=0]
deactivate scene
{
"endpointId" : "123",
"scenestate" : "TurnOff"
}
{"endpointId": "123", "scenestate": "TurnOff"}
Unresolved directive in ../../../target/generated-doc-sections/partials/_google-home-execute-sections.adoc - include::https://raw.githubusercontent.com/Offbeat-IoT/microcontroller-examples/HEAD/examples/google-home/LockCommand/LockCommand.ino[tags=google-home-lock-command-docs,indent=0]
Live camera view
Google can show a live camera view on a smart display or in the Google Home app through
action.devices.traits.CameraStream. As with Alexa, the device does not talk to Google and does not
serve a stream URL: Offbeat answers action.devices.commands.GetCameraStream, asks the device to push
JPEG frames over its existing WebSocket, and returns the media gateway’s signed H.264 MPEG-TS HLS URL.
|
Note
|
One device setup, both assistants. The device contract is assistant-agnostic: the same
firmware (or mock) receives the same startVideo/stopVideo commands and pushes the same binary JPEG
frames and motion readings to Alexa and Google Home; the platform adapts. Enable the
CameraStreamController capability for Google Home on the device (exactly as for Alexa) and the same
endpoint streams to either, with no device-side change.
|
Declaring a camera
The camera capability and settings are shared with Alexa: add the CameraStreamController capability
to the device (Device integrations → Google Home → Configure), set the display type to CAMERA, and
enable the camera stream + resolution in the device’s Camera settings. Offbeat then advertises
action.devices.traits.CameraStream with cameraStreamSupportedProtocols ["hls"],
cameraStreamNeedAuthToken false and cameraStreamNeedDrmEncryption false.
Execute: GetCameraStream
When Google asks for the stream, Offbeat activates the stream, tells the device to start streaming
({"startVideo": 5}), preloads the playlist and replies with:
{
"commands": [
{
"ids": ["<endpointId>"],
"status": "SUCCESS",
"states": {
"online": true,
"cameraStreamProtocol": "hls",
"cameraStreamAccessUrl": "https://camera.offbeat-iot.com/s/<token>/index.m3u8"
}
}
]
}
cameraStreamNeedAuthToken is false because the URL is self-authorizing (the signed token is the
secret), so no cameraStreamAuthToken is returned. No Cast receiver app id is returned either, so
Google’s default receiver is used. If the camera is disabled, not provisioned, or HLS is not among the
requested protocols, the command returns status: "ERROR" with errorCode: "resourceUnavailable".
Stream requirements
Identical to the Alexa live camera view: H.264 Baseline or Main profile with in-band
SPS/PPS in every segment (High profile silently fails), served as MPEG-TS HLS over public
HTTPS:443 with a trusted certificate, produced by the media gateway. The playlist must be live
(HTTP 200) before the response, so Offbeat preloads it (bounded by alexa.camera.preload-timeout-ms,
default 3500 ms). Resolutions 640x480 and 800x600, default 5 fps. See Live camera view on the
Alexa page for the relay and debugging notes.