Lambda

    In true Amazon fashion, everything has to be overly complex.

    All I want is to build an Alexa ‘skill’ using Lambda to send an SMS via AWS SNS Topic. Triggered with ‘Alarm’ or similar.

    /* eslint-disable  func-names */
    /* eslint quote-props: ["error", "consistent"]*/
    /**
     * This sample demonstrates a sample skill built with Amazon Alexa Skills nodejs
     * skill development kit.
     * This sample supports multiple languages (en-US, en-GB, de-GB).
     * The Intent Schema, Custom Slot and Sample Utterances for this skill, as well
     * as testing instructions are located at https://github.com/alexa/skill-sample-nodejs-howto
     **/
    
    'use strict';
    
    const Alexa = require('alexa-sdk');
    const AWS = require('aws-sdk');
    const recipes = require('./recipes');
    const APP_ID = undefined; // TODO replace with your app ID (OPTIONAL).
    
    const languageStrings = {
        'en': {
            translation: {
                RECIPES: recipes.RECIPE_EN_US,
                SKILL_NAME: 'Minecraft Helper',
                WELCOME_MESSAGE: "Welcome to %s. You can ask a question like, what\'s the recipe for a chest? ... Now, what can I help you with?",
                WELCOME_REPROMT: 'For instructions on what you can say, please say help me.',
                DISPLAY_CARD_TITLE: '%s  - Recipe for %s.',
                HELP_MESSAGE: "You can ask questions such as, what\'s the recipe, or, you can say exit...Now, what can I help you with?",
                HELP_REPROMT: "You can say things like, what\'s the recipe, or you can say exit...Now, what can I help you with?",
                STOP_MESSAGE: 'Goodbye!',
                RECIPE_REPEAT_MESSAGE: 'Try saying repeat.',
                RECIPE_NOT_FOUND_MESSAGE: "I\'m sorry, I currently do not know ",
                RECIPE_NOT_FOUND_WITH_ITEM_NAME: 'the recipe for %s. ',
                RECIPE_NOT_FOUND_WITHOUT_ITEM_NAME: 'that recipe. ',
                RECIPE_NOT_FOUND_REPROMPT: 'What else can I help with?',
            },
        },
        'en-GB': {
            translation: {
                RECIPES: recipes.RECIPE_EN_GB,
                SKILL_NAME: 'British Minecraft Helper',
            },
        },
    };
    
    const handlers = {
        'LaunchRequest': function () {
    	self = this
    
    	var sns = new AWS.SNS();
    
    	sns.publish({
    		Message: 'Test publish to SNS from Lambda',
    		TopicArn: 'arn:aws:sns:eu-west-1:6303xxxxxxxxx:Alarm'
    	}, function(err, data) {});
    
    	this.attributes.speechOutput = this.t('WELCOME_MESSAGE', this.t('SKILL_NAME'));
    	this.attributes.repromptSpeech = this.t('WELCOME_REPROMT');
    	this.emit(':ask', this.attributes.speechOutput, this.attributes.repromptSpeech);
        },
        'AMAZON.HelpIntent': function () {
            this.attributes.speechOutput = this.t('HELP_MESSAGE');
            this.attributes.repromptSpeech = this.t('HELP_REPROMT');
            this.emit(':ask', this.attributes.speechOutput, this.attributes.repromptSpeech);
        },
        'AMAZON.RepeatIntent': function () {
            this.emit(':ask', this.attributes.speechOutput, this.attributes.repromptSpeech);
        },
        'AMAZON.StopIntent': function () {
            this.emit('SessionEndedRequest');
        },
        'AMAZON.CancelIntent': function () {
            this.emit('SessionEndedRequest');
        },
        'SessionEndedRequest': function () {
            this.emit(':tell', this.t('STOP_MESSAGE'));
        },
        'Unhandled': function () {
            this.attributes.speechOutput = this.t('HELP_MESSAGE');
            this.attributes.repromptSpeech = this.t('HELP_REPROMPT');
            this.emit(':ask', this.attributes.speechOutput, this.attributes.repromptSpeech);
        },
    };
    
    exports.handler = function (event, context) {
        const alexa = Alexa.handler(event, context);
        alexa.APP_ID = APP_ID;
        alexa.resources = languageStrings;
        alexa.registerHandlers(handlers);
        alexa.execute();
    };
    


    When tested with the Lambda console, I get…

    {
      "errorMessage": "RequestId: 55088201-6261-11e7-90d2-6941b4326177 Process exited before completing request"
    }
    


    When tested with the Alexa Service Simulator…
    Single Utterance of “Alarm” gives…The remote endpoint could not be called, or the response it returned was invalid.
    Single Utterance of “Alarm Alarm” works, but no SNS.

    Update

    So Alexa was never going to work. The combination of no working examples and poor debugging made it impossible!

    Next I moved to AWS IoT and an IoT Button. The button power the Amazon Dash Button. They are quite cool.

    Again the setup of these buttons is ridiculous. The examples or guides don’t work and the lack of a Decent Error message makes it impossible.

    One thing that works is the Lambda Test, so as expected I test and get a SNS Email a few seconds later.

    But when I push the ASW IoT Button nothing.

    Its fortunate my Reserved Ec2 Instance expires soon, time to evaluate Google.

    If I ever talk about AWS being good please laugh at me

    policy-overview

    So not only do AWS expect you to type this in, when you do it don’t work.

    aws iot list-things --region eu-west-1
    {
        "things": [
            {
                "thingName": "iotbutton_G030PT027106VPAS",
                "version": 1,
                "attributes": {}
            }
        ]
    }

    aws iot list-topic-rules --region eu-west-1
    {
        "rules": [
            {
                "ruleArn": "arn:aws:iot:eu-west-1:{Account-Id}:rule/iotbutton_G030PT027106VPAS",
                "ruleDisabled": false,
                "ruleName": "iotbutton_G030PT027106VPAS",
                "createdAt": 1499677251.0,
                "topicPattern": "iotbutton_G030PT027106VPAS"
            }
        ]
    }

    aws iot get-topic-rule --rule-name iotbutton_G030PT027106VPAS --region eu-west-1
    {
        "rule": {
            "sql": "SELECT * FROM 'iotbutton_G030PT027106VPAS'",
            "ruleName": "iotbutton_G030PT027106VPAS",
            "actions": [
                {
                    "lambda": {
                        "functionArn": "arn:aws:lambda:eu-west-1:{Account-Id}:function:AlarmFunction"
                    }
                }
            ],
            "description": "Event source for your IoT Button to Lambda",
            "awsIotSqlVersion": "2016-03-23",
            "ruleDisabled": false
        },
        "ruleArn": "arn:aws:iot:eu-west-1:{Account-Id}:rule/iotbutton_G030PT027106VPAS"
    }

    aws iot describe-endpoint --region eu-west-1
    {
        "endpointAddress": "a3t1otmrg7j71e.iot.eu-west-1.amazonaws.com"
    }

    aws iot list-certificates --region eu-west-1
    {
        "certificates": [
            {
                "certificateId": "981c38379c24672c4843647cb92cdc12c8b78d94a870376d7fa61aaea3fa2ac7",
                "creationDate": 1499692507.149,
                "status": "ACTIVE",
                "certificateArn": "arn:aws:iot:eu-west-1:{Account-Id}:cert/981c38379c24672c4843647cb92cdc12c8b78d94a870376d7fa61aaea3fa2ac7"
            },
            {
                "certificateId": "7c5dc7fd1b45e1c85c82352d2bd82d7ea04fd59aabff22d40e0a40680ab397ac",
                "creationDate": 1499605333.323,
                "status": "ACTIVE",
                "certificateArn": "arn:aws:iot:eu-west-1:{Account-Id}:cert/7c5dc7fd1b45e1c85c82352d2bd82d7ea04fd59aabff22d40e0a40680ab397ac"
            }
        ]
    }

    aws iot list-policies --region eu-west-1
    {
        "policies": [
            {
                "policyName": "iotbutton_G030PT027106VPAS",
                "policyArn": "arn:aws:iot:eu-west-1:832404184041:policy/iotbutton_G030PT027106VPAS"
            }
        ]
    }

    aws iot get-policy --policy-name iotbutton_G030PT027106VPAS --region eu-west-1
    {
        "policyArn": "arn:aws:iot:eu-west-1:832404184041:policy/iotbutton_G030PT027106VPAS",
        "policyName": "iotbutton_G030PT027106VPAS",
        "policyDocument": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": \"iot:*\",\n      \"Resource\": \"*\"\n    }\n  ]\n}",
        "defaultVersionId": "4"
    }

    openssl s_client -connect a3t1otmrg7j71e.iot.us-east-1.amazonaws.com:8443 -CAfile VeriSign-Class\ 3-Public-Primary-Certification-Authority-G5.pem -cert 981c38379c-certificate.pem.crt -key 981c38379c-private.pem.key 
    CONNECTED(00000003)
    depth=2 C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = "(c) 2006 VeriSign, Inc. - For authorized use only", CN = VeriSign Class 3 Public Primary Certification Authority - G5
    verify return:1
    depth=1 C = US, O = Symantec Corporation, OU = Symantec Trust Network, CN = Symantec Class 3 Secure Server CA - G4
    verify return:1
    depth=0 C = US, ST = Washington, L = Seattle, O = "Amazon.com, Inc.", CN = *.iot.us-east-1.amazonaws.com
    verify return:1
    139936071315160:error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown:s3_pkt.c:1487:SSL alert number 46
    139936071315160:error:140790E5:SSL routines:ssl23_write:ssl handshake failure:s23_lib.c:177:
    ---
    Certificate chain
     0 s:/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=*.iot.us-east-1.amazonaws.com
       i:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 Secure Server CA - G4
     1 s:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 Secure Server CA - G4
       i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
    ---
    Server certificate
    -----BEGIN CERTIFICATE-----
    {CERT}
    -----END CERTIFICATE-----
    subject=/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=*.iot.us-east-1.amazonaws.com
    issuer=/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 Secure Server CA - G4
    ---
    No client certificate CA names sent
    Client Certificate Types: RSA sign, DSA sign, ECDSA sign
    Requested Signature Algorithms: ECDSA+SHA512:RSA+SHA512:ECDSA+SHA384:RSA+SHA384:ECDSA+SHA256:RSA+SHA256:DSA+SHA256:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:ECDSA+SHA1:RSA+SHA1:DSA+SHA1
    Shared Requested Signature Algorithms: ECDSA+SHA512:RSA+SHA512:ECDSA+SHA384:RSA+SHA384:ECDSA+SHA256:RSA+SHA256:DSA+SHA256:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:ECDSA+SHA1:RSA+SHA1:DSA+SHA1
    Peer signing digest: SHA512
    Server Temp Key: ECDH, P-256, 256 bits
    ---
    SSL handshake has read 3386 bytes and written 1271 bytes
    ---
    New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
    Server public key is 2048 bit
    Secure Renegotiation IS supported
    Compression: NONE
    Expansion: NONE
    No ALPN negotiated
    SSL-Session:
        Protocol  : TLSv1.2
        Cipher    : ECDHE-RSA-AES256-GCM-SHA384
        Session-ID: 5963987114C94B9EC5D31F4625464699926CF6EBCF893D15CB46D994F7AE478D
        Session-ID-ctx: 
        Master-Key: 8CF18BAE922E621F5F4781C8584A8C13401D4E0A4F1013A24926CE846DBB419AD1932396B580D049EB05406A1EC725C8
        Key-Arg   : None
        PSK identity: None
        PSK identity hint: None
        SRP username: None
        Start Time: 1499699313
        Timeout   : 300 (sec)
        Verify return code: 0 (ok)
    ---

    AWS IoT Console





    No Rules executed

    Published by

    Daniel McMorrow

    34 Year old disabled geek,

    // //