0
votes

I'm trying to build a home automation system by myself. For this, I use the Blynk server to control my hardware. I can control my hardware by requesting the URL of the blynk server.

For example: When I make a request to https://139.59.206.133/myprivatekey/update/V1?value=1 and update a Virtual Pin to "1" and my light turns on.

I used this to make an Alexa custom skill which is able to turn my light on by making an HTTPS request to the Blynk server. For example when I say "Alexa ask my Room to turn the light on". The custom Skill is working how it should.

But a Custom skill is not really what I was looking for, so I decided to build an Alexa Smart Home Skill. So I set one up and simply tried to make an HTTPS request when "TurnON" or "TurnOFF" is called.

My problem is that every time I try to make an HTTPS request Alexa says that the device is not responding.

I tried a lot of things, but I couldn't solve my problem on my own.

Code:

The Code is from the node.js Alexa Smart Home Example.

    exports.handler = function (request, context) {
    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));
            handlePowerControl(request, context);
        }
    }

    function handleDiscovery(request, context) {
        var payload = {
            "endpoints":
            [
                {
                    "endpointId": "demo_id",
                    "manufacturerName": "Smart Device Company",
                    "friendlyName": "Zimmerlicht",
                    "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;
        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") {
            const Http = new XMLHttpRequest();
            const url='https://139.59.206.133/myprivatekey/update/V1?value=1';
            Http.open("GET", url);
            Http.send();
            // Make the call to your device cloud for control
            // powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
            powerResult = "ON";
        }
       else if (requestMethod === "TurnOff") {
            var xmlHttp = new XMLHttpRequest();
            xmlHttp.open( "GET", 'http://myprivatekey/update/V0?value=0', false ); // false for synchronous request
            xmlHttp.send( null );
            // Make the call to your device cloud for control and check for success
            // powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
            powerResult = "OFF";
        }
        var contextResult = {
            "properties": [{
                "namespace": "Alexa.PowerController",
                "name": "powerState",
                "value": powerResult,
                "timeOfSample": "2017-09-03T16:20:50.52Z", //retrieve from result.
                "uncertaintyInMilliseconds": 50
            }]
        };
        var response = {
            context: contextResult,
            event: {
                header: responseHeader,
                endpoint: {
                    scope: {
                        type: "BearerToken",
                        token: requestToken
                    },
                    endpointId: "demo_id"
                },
                payload: {}
            }
        };
        log("DEBUG", "Alexa.PowerController ", JSON.stringify(response));
        context.succeed(response);
    }
};

My Requests:

    if (requestMethod === "TurnOn") {
            const Http = new XMLHttpRequest();
            const url='https://139.59.206.133/myprivatekey/update/V1?value=1';
            Http.open("GET", url);
            Http.send();
            // Make the call to your device cloud for control
            // powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
            powerResult = "ON";
        }
       else if (requestMethod === "TurnOff") {
            var xmlHttp = new XMLHttpRequest();
            xmlHttp.open( "GET", 'http://myprivatekey/update/V0?value=0', false ); // false for synchronous request
            xmlHttp.send( null );
            // Make the call to your device cloud for control and check for success
            // powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
            powerResult = "OFF";
        }

Additional Info:

  • Programming language node.js
  • account linking, IAM role, and everything to create a smart home skill should be set up right

I am rather new to Alexa Skill building, and I'm also not very good at JavaScript.

1
Dies the light turns on/off? I mean does https request go through?Tarlog

1 Answers

0
votes

If the request went through, I mean your code is being called, and light is being turned on/off, the problem is with the response.

My guess is that you are missing correlation id.

you need to add something like:

responseHeader.correlationToken = request.directive.header.correlationToken;

You should also implement the EndpointHealth: https://developer.amazon.com/en-US/docs/alexa/device-apis/alexa-endpointhealth.html