我们能够链接我们的技能并发现已连接的设备,但发现后,所有设备都设置为“关闭”,并且顶部显示错误消息“存在问题”。
这是我们的 lambda 函数:(当前仅处理发现和状态响应):
/**
*
*/
var AUTH_KEY = process.env.AUTH_KEY;
var SET_DEVICE_CONFIG_URL = process.env.SET_DEVICE_CONFIG_URL;
var GET_DEVICE_STATE_URL = process.env.GET_DEVICE_STATE_URL;
var axios = require('axios')
var rp = require('request-promise');
const CONTROL_POWER = 'Alexa.PowerController';
// const TURNOFF_OR_ON = 'Alexa.ConnectedHome.Control';
const CONTROL_LOCK = 'Alexa.LockController';
const DISCOVERY = 'Alexa.Discovery';
const DISCOVERY_RESPONSE = 'Discover.Response';
const ALEXA = 'Alexa';
const RESPONSE = 'Response';
const STATE_REPORT = 'Alexa.ReportState';
const ERROR_RESPONSE = 'ErrorResponse';
const PAYLOAD_V = '3';
/**
* Main entry point.
* Incoming events from Alexa Lighting APIs are processed via this method.
*/
exports.handler = async function(request, context) {
let namespace = "";
let header = "";
console.log('Input', request);
// console.log('Payload', request.directive.payload);
if(request.directive) {
namespace = request.directive.header.namespace;
header = request.directive.header;
}
else if (request.header.namespace) {
namespace = request.header.namespace
header = request.header;
}
console.log(namespace, header);
switch (namespace) {
case DISCOVERY:
let response = await handleDiscovery(request, context);
console.log(response.data);
return response;
break;
case CONTROL_POWER:
console.log("HEADER", header);
console.log("CONTROL POWER HIT");
break;
case CONTROL_LOCK:
handleControl(request, context);
break;
case ALEXA:
let sr_response = await handleStateRequest(request, context);
console.log(sr_response);
return sr_response
break;
case STATE_REPORT:
console.log("STATE REPORT");
console.log("SR REQUEST", request);
handleStateRequest(request, context);
default:
console.log('Err', 'No supported namespace: ' + namespace);
// callback('Something went wrong');
break;
}
};
/**
* This method is invoked when we receive a "Discovery" message from Alexa Smart Home Skill.
* We are expected to respond back with a list of appliances that we have discovered for a given
* customer.
*/
async function handleDiscovery(request, context) {
let accessToken = request.directive.payload.scope.token;
var event = {
header: {
namespace: DISCOVERY,
name: DISCOVERY_RESPONSE,
payloadVersion: PAYLOAD_V,
messageId: createMessageId()
},
payload: {
endpoints: ""
}
};
try {
let URL = `https://MYURL/api/getdevices?accessToken=${accessToken}`;
console.log(URL);
const response = await axios.get(URL);
console.log(response);
event.payload.endpoints = response.data.devices;
return {
event
};
} catch (error) {
console.log(error);
return {
statusCode: 500,
body: JSON.stringify({ message: 'Error occurred while processing the request.' })
};
}
}
/**
* STATE REQUEST HANDLER
* */
async function handleStateRequest(request, context) {
console.log("REQUEST : ", request);
try {
// Extract the directive from the event
const directive = request.directive;
const scope_ = request.directive.endpoint.scope;
const cookie_ = request.directive.endpoint.cookie;
const accessToken = request.directive.endpoint.scope.token;
// Check if the directive type is Alexa.ReportState
if (directive.header.namespace === 'Alexa' && directive.header.name === 'ReportState') {
// Handle the ReportState directive
const payload = directive.payload;
const {correlationToken} = directive.header;
const {endpointId} = directive.endpoint;
const URL = `https://MYURL/api/reportstate?accessToken=${accessToken}`;
const url_response = await axios.post(URL, directive);
// Handle the response from the external URL if necessary
console.log('Response:', url_response);
console.log('Response:', url_response.data);
// Build the response
const response = {
event: {
header: {
namespace: 'Alexa',
name: 'StateReport',
messageId: createMessageId(),
correlationToken: correlationToken,
payloadVersion: '3'
},
endpoint: {
scope: scope_,
endpointId: endpointId,
cookie: cookie_,
},
payload: {},
context: {
properties: [
{
namespace: "Alexa.PowerController",
name: "powerState",
value: url_response.data.data.value,
timeOfSample: url_response.data.data.time,
uncertaintyInMilliseconds: 1000
},
{
namespace: "Alexa.EndpointHealth",
name: "connectivity",
value: {
value: "OK"
},
timeOfSample: url_response.data.data.time,
uncertaintyInMilliseconds: 1000
}
]
}
}
};
console.log(response);
console.log(response.event.endpoint);
console.log(response.event.context);
return response;
}
// If the directive is not Alexa.ReportState, return an error response
return createErrorResponse('INVALID_DIRECTIVE', 'This skill only supports Alexa.ReportState directives.');
} catch (error) {
console.error('Error handling directive:', error);
return createErrorResponse('INTERNAL_ERROR', 'An internal error occurred while handling the directive.');
}
};
//TRUNCATED FOR READABILITY
这是我们的指示性回应:
{
header: {
namespace: Alexa.Discovery,
name: Discover.Response,
payloadVersion: 3,
messageId: createMessageId()
},
payload: {
endpoints: [
{
"endpointId": "632d46a5f6755c965fa7e4df",
"manufacturerName": "TESTABC",
"modelName": "STS001",
"version": "VER01",
"friendlyName": "SOCKET 1",
"description": "Wifi Socket",
"displayCategories": [
"SMARTPLUG"
],
"capabilities": [
{
"type": "AlexaInterface",
"interface": "Alexa.PowerController",
"version": "3",
"properties": {
"supported": [
{
"name": "powerState"
}
],
"proactivelyReported": true,
"retrievable": true
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.EndpointHealth",
"version": "3",
"properties": {
"supported": [
{
"name": "connectivity"
}
],
"proactivelyReported": true,
"retrievable": true
}
}
],
"cookie": {}
}
}]}
这是我们的状态响应:
{
event: {
header: {
namespace: 'Alexa',
name: 'StateReport',
messageId: '0693d096-2d13-442d-8d9f-41c65de4592e',
correlationToken: 'REMOVED FOR BREVITY',
payloadVersion: '3'
},
endpoint: {
scope:
{
type: 'BearerToken',
token: 'REMOVED FOR BREVITY'
},
endpointId: '632d46a5f6755c965fa7e4df',
cookie: {}
},
payload: {},
context: { properties: [ {
namespace: 'Alexa.PowerController',
name: 'powerState',
value: 'OFF',
timeOfSample: '2023-05-17T09:24:31.562Z',
uncertaintyInMilliseconds: 1000
},
{
namespace: 'Alexa.EndpointHealth',
name: 'connectivity',
value: {
value : 'OK'
},
timeOfSample: '2023-05-17T09:24:31.562Z',
uncertaintyInMilliseconds: 1000
}] }
}
}
问题是,在您的技能的
'StateReport'
JSON 响应中,所有内容都嵌套在 'event'
对象下。
简而言之,期望技能的 JSON 响应包含两个单独的顶级对象
'event'
和 'context'
,而在此示例中,您的 'context'
对象错误地位于 'event'
内,为 'event.context'
。
使用您的 JSON 响应作为起点,我对其进行了修改,以将
'event'
和 'context'
对象彼此分开,如下所示:
{
"context": {
"properties": [
{
"name": "powerState",
"namespace": "Alexa.PowerController",
"timeOfSample": "2023-05-17T09:24:31.562Z",
"uncertaintyInMilliseconds": 1000,
"value": "OFF"
},
{
"name": "connectivity",
"namespace": "Alexa.EndpointHealth",
"timeOfSample": "2023-05-17T09:24:31.562Z",
"uncertaintyInMilliseconds": 1000,
"value": {
"value": "OK"
}
}
]
},
"event": {
"endpoint": {
"cookie": {},
"endpointId": "632d46a5f6755c965fa7e4df",
"scope": {
"token": "REMOVED FOR BREVITY",
"type": "BearerToken"
}
},
"header": {
"correlationToken": "REMOVED FOR BREVITY",
"messageId": "0693d096-2d13-442d-8d9f-41c65de4592e",
"name": "StateReport",
"namespace": "Alexa",
"payloadVersion": "3"
},
"payload": {}
}
}
希望有帮助!