URL aus SmartHomeSkill funktioniert nur über die App

Hier wird über die Entwicklung von Skills diskutiert.
Antworten
Benutzeravatar

Themenstarter
Susi
Beiträge: 8
Registriert: Fr 31. Mär 2017, 23:19

Sa 8. Dez 2018, 11:30

Hallo zusammen,
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();
}

    
};
Bitte nicht wundern, als Gerät hatte ich die Schlafzimmerlampe eingestellt, dann aber beim Aufruf die Esstischlampe fest eingestellt, damit ich niemanden beim Schlafen störe.

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 seconds
Hier 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 MB 
Wie 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.
0 x
Benutzeravatar

Themenstarter
Susi
Beiträge: 8
Registriert: Fr 31. Mär 2017, 23:19

So 9. Dez 2018, 15:29

Hallo,

ich habe es jetzt inzwischen hinbekommen, indem ich context.succeed(response); in die Funktion myHTTP() eingefügt habe und den Timeout der Lambdafunktion auf 10 Sekunden erhöht habe.

Ich würde jetzt gerne erkennen, über welchen Echo ein Befehl an den Skill weitergeleitet wird, um z. B. Befehle wie "Licht aus" auf den Raum zu beschränken, in dem der Echo steht. Weiß jemand, wie ich an diese Information komme? Beim Customskill ging dies über den Deviceeintrag.

Inzwischen können Sprachprofile angelegt werden. Lassen sich auch diese Informationen in einem Smarthome-Skill abrufen?
0 x
Antworten

Zurück zu „Fähigkeiten (Skills) entwickeln“

  • Information