ich habe ein Verhalten, welches ich nicht verstehe. Ich habe einmal das Beispiel von Amazon unter developer.amazon ausprobiert.
Der Skill funktionierte soweit, also habe ich das Script etwas erweitert und einen Aufruf meines Servers eingefügt. Meine Lambdafunktion sieht jetzt so aus:
Code: Alles auswählen
exports.handler = function (request, context) {
console.log("es folgt request");
console.log(request);
if (request.directive.header.namespace === 'Alexa.Discovery' && request.directive.header.name === 'Discover') {
log("DEBUG:", "Discover request", JSON.stringify(request));
handleDiscovery(request, context, "");
}
else if (request.directive.header.namespace === 'Alexa.PowerController') {
if (request.directive.header.name === 'TurnOn' || request.directive.header.name === 'TurnOff') {
log("DEBUG:", "TurnOn or TurnOff Request", JSON.stringify(request));
myHttp("s=esstisch " + (request.directive.header.name == 'TurnOn' ? "an" : "aus" ) );
handlePowerControl(request, context);
}
}
function handleDiscovery(request, context) {
var payload = {
"endpoints":
[
{
"endpointId": "demo_id",
"manufacturerName": "Smart Device Company",
"friendlyName": "Bedroom Outlet",
"description": "Smart Device Switch",
"displayCategories": ["SWITCH"],
"cookie": {
"key1": "arbitrary key/value pairs for skill to reference this endpoint.",
"key2": "There can be multiple entries",
"key3": "but they should only be used for reference purposes.",
"key4": "This is not a suitable place to maintain current endpoint state."
},
"capabilities":
[
{
"type": "AlexaInterface",
"interface": "Alexa",
"version": "3"
},
{
"interface": "Alexa.PowerController",
"version": "3",
"type": "AlexaInterface",
"properties": {
"supported": [{
"name": "powerState"
}],
"retrievable": true
}
}
]
},
{
"endpointId": "sz_licht_id",
"manufacturerName": "Smart Device Company",
"friendlyName": "Schlafzimmer licht",
"description": "Smart Device Switch",
"displayCategories": ["SWITCH"],
"cookie": {
"key1": "arbitrary key/value pairs for skill to reference this endpoint.",
"key2": "There can be multiple entries",
"key3": "but they should only be used for reference purposes.",
"key4": "This is not a suitable place to maintain current endpoint state."
},
"capabilities":
[
{
"type": "AlexaInterface",
"interface": "Alexa",
"version": "3"
},
{
"interface": "Alexa.PowerController",
"version": "3",
"type": "AlexaInterface",
"properties": {
"supported": [{
"name": "powerState"
}],
"retrievable": true
}
}
]
}
]
};
var header = request.directive.header;
header.name = "Discover.Response";
log("DEBUG", "Discovery Response: ", JSON.stringify({ header: header, payload: payload }));
context.succeed({ event: { header: header, payload: payload } });
}
function log(message, message1, message2) {
console.log(message + message1 + message2);
}
function handlePowerControl(request, context) {
// get device ID passed in during discovery
var requestMethod = request.directive.header.name;
var responseHeader = request.directive.header;
var endpointid = request.directive.endpoint.endpointId;
responseHeader.namespace = "Alexa";
responseHeader.name = "Response";
responseHeader.messageId = responseHeader.messageId + "-R";
// get user token pass in request
var requestToken = request.directive.endpoint.scope.token;
var powerResult;
if (requestMethod === "TurnOn") {
// Make the call to your device cloud for control
// powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
myHttp("start=handlePowerControl&endpointid="+endpointid+"&request="+powerResult+"&s=esstisch an");
powerResult = "ON";
}
else if (requestMethod === "TurnOff") {
// Make the call to your device cloud for control and check for success
// powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
myHttp("start=handlePowerControl&endpointid="+endpointid+"&request="+powerResult+"&s=esstisch aus");
powerResult = "OFF";
}
var contextResult = {
"properties": [{
"namespace": "Alexa.PowerController",
"name": "powerState",
"value": powerResult,
"timeOfSample": "2017-09-03T16:20:50.52Z", //retrieve from result.
"uncertaintyInMilliseconds": 5000
}]
};
var response = {
context: contextResult,
event: {
header: responseHeader,
endpoint: {
scope: {
type: "BearerToken",
token: requestToken
},
endpointId: endpointid
},
payload:{
}
}
};
log("DEBUG", "Alexa.PowerController ", JSON.stringify(response));
context.succeed(response);
}
function myHttp(parameter) {
console.log("Starte myHttp "+parameter);
var https = require('https');
var req = https.get('https://hier steht die korrekte url?'+parameter, (response) => {
response.setEncoding('utf8');
console.log("req myHttp");
var returnData = "";
response.on('data', chunk => {returnData += chunk;});
response.on('end', () => {
console.log(returnData);
});
});
console.log("Ende myHttp Daten https get sh nächste zeile");
console.log(req);
req.end();
}
};
Um ein Gerät zu schalten wird ein Befehl an meinen Server gesendet. Im Moment liefert der Server noch einen normalen Text und kein JSON als Antwort zurück. Zum Testen sollte das aber reichen.
Auch mit den Änderungen funktionierte die Lambda-Funktion. Ich konnte die Lampe über die App (per Schalter) ein- und ausschalten. Danach habe ich es per Sprache probiert, auch das klappte problemlos über die App.
Die Logeinträge für diesen Aufruf sehen so aus:
Schlafzimmer ausschalten über die App 2018-12-08T09:55:48.001Z [[aaa-fac-bbb]] es folgt request 2018-12-08T09:55:48.019Z [[aaa-fac-bbb]] { directive: { header: { namespace: 'Alexa', name: 'ReportState', payloadVersion: '3', messageId: '[[message_id1]]', correlationToken: '[[correlationToken1]]' }, endpoint: { scope: [Object], endpointId: 'sz_licht_id', cookie: [Object] }, payload: {} } } END RequestId: [[aaa-fac-bbb]] REPORT RequestId: [[aaa-fac-bbb]] Duration: 108.31 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 18 MB START RequestId: [[ccc-fac-ddd]] Version: $LATEST 2018-12-08T09:55:54.405Z [[ccc-fac-ddd]] es folgt request 2018-12-08T09:55:54.405Z [[ccc-fac-ddd]] { directive: { header: { namespace: 'Alexa.PowerController', name: 'TurnOff', payloadVersion: '3', messageId: '[[message_id2]]', correlationToken: '[[correlationToken2]]' }, endpoint: { scope: [Object], endpointId: 'sz_licht_id', cookie: [Object] }, payload: {} } } 2018-12-08T09:55:54.405Z [[ccc-fac-ddd]] DEBUG:TurnOn or TurnOff Request { "directive": { "header": { "namespace": "Alexa.PowerController", "name": "TurnOff", "payloadVersion": "3", "messageId": "[[message_id2]]", "correlationToken": "[[correlationToken2]]" }, "endpoint": { "scope": { "type": "BearerToken", "token": "[[token1]]" }, "endpointId": "sz_licht_id", "cookie": { "key1": "arbitrary key/value pairs for skill to reference this endpoint.", "key2": "There can be multiple entries", "key3": "but they should only be used for reference purposes.", "key4": "This is not a suitable place to maintain current endpoint state." } }, "payload": {} } } 2018-12-08T09:55:54.406Z [[ccc-fac-ddd]] Starte myHttp s=esstisch aus 2018-12-08T09:55:54.922Z [[ccc-fac-ddd]] Ende myHttp Daten https get sh nächste zeile 2018-12-08T09:55:54.939Z [[ccc-fac-ddd]] ClientRequest { domain: null, _events: { response: { [Function: g] listener: [Function] }, socket: { [Function: g] listener: [Function: onSocket] } }, _eventsCount: 2, _maxListeners: undefined, output: [ 'GET /[[script]].php?s=esstisch%20aus HTTP/1.1\r\nHost: [[host]]\r\nConnection: close\r\n\r\n' ], outputEncodings: [ 'latin1' ], outputCallbacks: [ [Function: finish] ], outputSize: 104, writable: true, _last: true, upgrading: false, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: false, sendDate: false, _removedHeader: {}, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: null, connection: null, _header: 'GET /[[script]].php?s=esstisch%20aus HTTP/1.1\r\nHost: [[host]]\r\nConnection: close\r\n\r\n', _headers: { host: '[[host]]' }, _headerNames: { host: 'Host' }, _onPendingData: null, agent: Agent { domain: null, _events: { free: [Function] }, _eventsCount: 1, _maxListeners: undefined, defaultPort: 443, protocol: 'https:', options: { path: null }, requests: {}, sockets: { '[[host]]:443::::::::': [Object] }, freeSockets: {}, keepAliveMsecs: 1000, keepAlive: false, maxSockets: Infinity, maxFreeSockets: 256, maxCachedSessions: 100, _sessionCache: { map: {}, list: [] } }, socketPath: undefined, timeout: undefined, method: 'GET', path: '/[[script]].php?s=esstisch%20aus', _ended: false } 2018-12-08T09:55:55.039Z [[ccc-fac-ddd]] Starte myHttp start=handlePowerControl&endpointid=sz_licht_id&request=undefined&s=esstisch aus 2018-12-08T09:55:55.080Z [[ccc-fac-ddd]] Ende myHttp Daten https get sh nächste zeile 2018-12-08T09:55:55.080Z [[ccc-fac-ddd]] ClientRequest { domain: null, _events: { response: { [Function: g] listener: [Function] }, socket: { [Function: g] listener: [Function: onSocket] } }, _eventsCount: 2, _maxListeners: undefined, output: [ 'GET /[[script]].php?start=handlePowerControl&endpointid=sz_licht_id&request=undefined&s=esstisch%20aus HTTP/1.1\r\nHost: [[host]]\r\nConnection: close\r\n\r\n' ], outputEncodings: [ 'latin1' ], outputCallbacks: [ [Function: finish] ], outputSize: 170, writable: true, _last: true, upgrading: false, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: false, sendDate: false, _removedHeader: {}, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: null, connection: null, _header: 'GET /[[script]].php?start=handlePowerControl&endpointid=sz_licht_id&request=undefined&s=esstisch%20aus HTTP/1.1\r\nHost: [[host]]\r\nConnection: close\r\n\r\n', _headers: { host: '[[host]]' }, _headerNames: { host: 'Host' }, _onPendingData: null, agent: Agent { domain: null, _events: { free: [Function] }, _eventsCount: 1, _maxListeners: undefined, defaultPort: 443, protocol: 'https:', options: { path: null }, requests: {}, sockets: { '[[host]]:443::::::::': [Object] }, freeSockets: {}, keepAliveMsecs: 1000, keepAlive: false, maxSockets: Infinity, maxFreeSockets: 256, maxCachedSessions: 100, _sessionCache: { map: {}, list: [] } }, socketPath: undefined, timeout: undefined, method: 'GET', path: '/[[script]].php?start=handlePowerControl&endpointid=sz_licht_id&request=undefined&s=esstisch%20aus', _ended: false } 2018-12-08T09:55:55.140Z [[ccc-fac-ddd]] DEBUGAlexa.PowerController { "context": { "properties": [ { "namespace": "Alexa.PowerController", "name": "powerState", "value": "OFF", "timeOfSample": "2017-09-03T16:20:50.52Z", "uncertaintyInMilliseconds": 5000 } ] }, "event": { "header": { "namespace": "Alexa", "name": "Response", "payloadVersion": "3", "messageId": "[[message_id2]]-R", "correlationToken": "[[correlationToken2]]" }, "endpoint": { "scope": { "type": "BearerToken", "token": "[[token1]]" }, "endpointId": "sz_licht_id" }, "payload": {} } } END RequestId: [[ccc-fac-ddd]] REPORT RequestId: [[ccc-fac-ddd]] Duration: 796.18 ms Billed Duration: 800 ms Memory Size: 128 MB Max Memory Used: 20 MB START RequestId: [[eee-fac-fff]] Version: $LATEST 2018-12-08T09:55:57.311Z [[eee-fac-fff]] es folgt request 2018-12-08T09:55:57.311Z [[eee-fac-fff]] { directive: { header: { namespace: 'Alexa', name: 'ReportState', payloadVersion: '3', messageId: '[[message_id3]]', correlationToken: '[[correlationToken3]]' }, endpoint: { scope: [Object], endpointId: 'sz_licht_id', cookie: [Object] }, payload: {} } } 2018-12-08T09:55:59.839Z [[eee-fac-fff]] req myHttp 2018-12-08T09:55:59.842Z [[eee-fac-fff]] Das Script hat die Lampe am Esstisch ausgeschaltet END RequestId: [[eee-fac-fff]] REPORT RequestId: [[eee-fac-fff]] Duration: 3003.27 ms Billed Duration: 3000 ms Memory Size: 128 MB Max Memory Used: 21 MB 2018-12-08T09:56:00.314Z [[eee-fac-fff]] Task timed out after 3.00 secondsHier sieht man sehr schön, welche Befehle abgearbeitet werden. Das Ergebnis "Das Script hat die Lampe am Esstisch ausgeschaltet" zeigt, dass mein Server die Lampe korrekt ausgeschaltet hat.
Soweit so gut. Gebe ich einen Befehl über einen Echo, dann erhalte ich zwar als Ergebnis "ok" zurück, die Lampe wird aber nicht geschaltet.
Das Logfile sieht dann so aus:
Aufruf per Echo START RequestId: aaaa-xxxxxxxxxxxx Version: $LATEST 2018-12-07T18:51:54.529Z aaaa-xxxxxxxxxxxx es folgt request 2018-12-07T18:51:54.534Z aaaa-xxxxxxxxxxxx { directive: { header: { namespace: 'Alexa.PowerController', name: 'TurnOn', payloadVersion: '3', messageId: 'yyyyyyyyyyyyy-ccc-yyyyyyyyyyyyy', correlationToken: 'ttttttttttttttttttttt==' }, endpoint: { scope: [Object], endpointId: 'sz_licht_id', cookie: [Object] }, payload: {} } } 2018-12-07T18:51:54.594Z aaaa-xxxxxxxxxxxx DEBUG:TurnOn or TurnOff Request { "directive": { "header": { "namespace": "Alexa.PowerController", "name": "TurnOn", "payloadVersion": "3", "messageId": "yyyyyyyyyyyyy-ccc-yyyyyyyyyyyyy", "correlationToken": "ttttttttttttttttttttt==" }, "endpoint": { "scope": { "type": "BearerToken", "token": "tttttttttttttttttttttrrrrrrrrrrrrrrrrrr" }, "endpointId": "sz_licht_id", "cookie": { "key1": "arbitrary key/value pairs for skill to reference this endpoint.", "key2": "There can be multiple entries", "key3": "but they should only be used for reference purposes.", "key4": "This is not a suitable place to maintain current endpoint state." } }, "payload": {} } } 2018-12-07T18:51:54.594Z aaaa-xxxxxxxxxxxx Starte myHttp s=esstisch an 2018-12-07T18:51:55.135Z aaaa-xxxxxxxxxxxx Ende myHttp Daten https get sh nächste zeile 2018-12-07T18:51:55.135Z aaaa-xxxxxxxxxxxx ClientRequest { domain: null, _events: { response: { [Function: g] listener: [Function] }, socket: { [Function: g] listener: [Function: onSocket] } }, _eventsCount: 2, _maxListeners: undefined, output: [ 'GET /script.php?s=esstisch%20an HTTP/1.1\r\nHost: myurl\r\nConnection: close\r\n\r\n' ], outputEncodings: [ 'latin1' ], outputCallbacks: [ [Function: finish] ], outputSize: 103, writable: true, _last: true, upgrading: false, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: false, sendDate: false, _removedHeader: {}, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: null, connection: null, _header: 'GET /script.php?s=esstisch%20an HTTP/1.1\r\nHost: myurl\r\nConnection: close\r\n\r\n', _headers: { host: 'myurl' }, _headerNames: { host: 'Host' }, _onPendingData: null, agent: Agent { domain: null, _events: { free: [Function] }, _eventsCount: 1, _maxListeners: undefined, defaultPort: 443, protocol: 'https:', options: { path: null }, requests: {}, sockets: { 'myurl:443::::::::': [Object] }, freeSockets: {}, keepAliveMsecs: 1000, keepAlive: false, maxSockets: Infinity, maxFreeSockets: 256, maxCachedSessions: 100, _sessionCache: { map: {}, list: [] } }, socketPath: undefined, timeout: undefined, method: 'GET', path: '/script.php?s=esstisch%20an', _ended: false } 2018-12-07T18:51:55.194Z aaaa-xxxxxxxxxxxx Starte myHttp start=handlePowerControl&endpointid=sz_licht_id&request=undefined&s=esstisch an 2018-12-07T18:51:55.254Z aaaa-xxxxxxxxxxxx Ende myHttp Daten https get sh nächste zeile 2018-12-07T18:51:55.254Z aaaa-xxxxxxxxxxxx ClientRequest { domain: null, _events: { response: { [Function: g] listener: [Function] }, socket: { [Function: g] listener: [Function: onSocket] } }, _eventsCount: 2, _maxListeners: undefined, output: [ 'GET /script.php?start=handlePowerControl&endpointid=sz_licht_id&request=undefined&s=esstisch%20an HTTP/1.1\r\nHost: myurl\r\nConnection: close\r\n\r\n' ], outputEncodings: [ 'latin1' ], outputCallbacks: [ [Function: finish] ], outputSize: 169, writable: true, _last: true, upgrading: false, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: false, sendDate: false, _removedHeader: {}, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: null, connection: null, _header: 'GET /script.php?start=handlePowerControl&endpointid=sz_licht_id&request=undefined&s=esstisch%20an HTTP/1.1\r\nHost: myurl\r\nConnection: close\r\n\r\n', _headers: { host: 'myurl' }, _headerNames: { host: 'Host' }, _onPendingData: null, agent: Agent { domain: null, _events: { free: [Function] }, _eventsCount: 1, _maxListeners: undefined, defaultPort: 443, protocol: 'https:', options: { path: null }, requests: {}, sockets: { 'myurl:443::::::::': [Object] }, freeSockets: {}, keepAliveMsecs: 1000, keepAlive: false, maxSockets: Infinity, maxFreeSockets: 256, maxCachedSessions: 100, _sessionCache: { map: {}, list: [] } }, socketPath: undefined, timeout: undefined, method: 'GET', path: '/script.php?start=handlePowerControl&endpointid=sz_licht_id&request=undefined&s=esstisch%20an', _ended: false } 2018-12-07T18:51:55.314Z aaaa-xxxxxxxxxxxx DEBUGAlexa.PowerController { "context": { "properties": [ { "namespace": "Alexa.PowerController", "name": "powerState", "value": "ON", "timeOfSample": "2017-09-03T16:20:50.52Z", "uncertaintyInMilliseconds": 5000 } ] }, "event": { "header": { "namespace": "Alexa", "name": "Response", "payloadVersion": "3", "messageId": "yyyyyyyyyyyyy-ccc-yyyyyyyyyyyyy-R", "correlationToken": "ttttttttttttttttttttt==" }, "endpoint": { "scope": { "type": "BearerToken", "token": "tttttttttttttttttttttrrrrrrrrrrrrrrrrrr" }, "endpointId": "sz_licht_id" }, "payload": {} } } END RequestId: aaaa-xxxxxxxxxxxx REPORT RequestId: aaaa-xxxxxxxxxxxx Duration: 847.94 ms Billed Duration: 900 ms Memory Size: 128 MB Max Memory Used: 23 MBWie zu sehen, wird auch hier die Funktion myHttp() mit den korrekten Parametern aufgerufen. Der Aufruf kommt aber nicht an meinem Server an.
Woran liegt das? Was muss ich ändern, damit der Befehl auch über den Echo abgesetzt werden kann?
Sorry für den langen Text, aber ich bin ratlos.