Coder Social home page Coder Social logo

ckhmer1 / node-red-contrib-alexa-virtual-smarthome Goto Github PK

View Code? Open in Web Editor NEW
10.0 3.0 4.0 1.57 MB

Alexa Smart Home Node Red module to control your smart home devices via Alexa

License: GNU General Public License v3.0

HTML 41.38% JavaScript 58.28% Python 0.35%

node-red-contrib-alexa-virtual-smarthome's Introduction

Alexa Smart Home Node Red module

WARNING: beta code, use at your own risk

Table of Contents


Introduction

A collection of Node-RED nodes to control your smart home devices via Amazon Alexa or the Alexa App.

This module does NOT directly interface with devices made by Amazon.


Prerequisites

  1. A host reachable from Amazon Alexa with a fixed IP address or a domain name with a fixed IP address or a domain name with the dynamic DNS server (refers to this in instructions as YOUR_DOMAIN) e.g. your_domain.it.
  2. A 'real' SSL certificate for the host e.g. from Let’s Encrypt.
  3. A reverse proxy, like nginx, forwarding the Amazon request to the Node-RED server.
  4. Forward TCP traffic coming in from the Internet to your reverse proxy server.
  5. Node-RED installed using an updated NodeJS version.
  6. An Amazon Developer account (use the same username used in the Amazon Alexa App or Alexa devices).
  7. An Amazon Web Service (AWS) account (use the same username used in the Amazon Alexa App or Alexa devices).

Setup Instructions

You are going to create a Smart Home Skill, a Lambda Function linked to the Node-RED server. See Understand the Smart Home Skill API for mode info.

Create a Security Profile (Used also for the login with Amazon feature)

To create the Security Profile, use the following steps (Register for Login with Amazon for more info):

  • Sign in to your Login with Amazon Console
  • Click on the "Create a New Security Profile" button.
  • Fill in the "Security Profile Name", e.g.: "Smart Home".
  • Fill in the "Security Profile Description", e.g.: "Smart Home Node-RED".
  • Fill in the "Consent Privacy Notice URL", e.g.: "https://YOUR_DOMAIN/alexa/oauth?policy".
  • Fill in the "Consent Logo Image", if You wish.
  • Click on the "Save" button.
Add your Website to your Security Profile
  • Click on the "Gears wheels" and select "Web Settings".
  • Click on the "Edit" button.
  • Fill in the "Allowed Origins" field, e.g.: "https://YOUR_DOMAIN".
  • Fill in the "Allowed Return URLs" field, e.g.: "https://YOUR_DOMAIN/alexa/oauth".
  • Click on the "Save" button.
  • Click on the "Show Secret" button, and copy the "Client ID" (1) and "Client Secret" (2). You will need it later in the Node-RED configuration.

Create a smart home skill

To create a smart home skill, use the following steps (Steps to Build a Smart Home Skill for more info):

  • Sign in to your Alexa developer account
  • Click on the "Create Skill" button.
  • Enter the "Skill name", e.g. "Smart Home".
  • Select the "Default language".
  • Under "Choose a model to add to your skill" page, select "Smart Home", and then click the "Create skill" button.
  • Under Payload Version, select "v3".
  • Copy Your Skill ID (3) to the clipboard, clicking the "Copy to clipboard" button.

Create a Lambda Function

To create a lambda function for the skill, use the following steps (Host a Custom Skill as an AWS Lambda Function and Steps to Build a Smart Home Skill: Add a Lambda Function for more info):

Create an IAM Role for Lambda
  • Sign in to your IAM console
  • From the upper-right menù, select the correct region for your region and skill language. For discovery of smart home devices to succeed, you must choose the region where the devices are located. Select only a region for the lambda server that supports the Alexa Smart Home trigger. See see Deploy Your Lambda Function to Multiple Regions for more info.
  • Choose "Roles" and click "Create role".
  • Select "AWS service" under "Select type of trusted entity".
  • Select "AWS Lambda" under "AWS Service Role".
  • Click the "Next: Permissions" button.
  • Type "basic" in the filter box and choose the "AWSLambdaBasicExecutionRole", check it, and click on the "Next: Tags" button.
  • Click on the "Next: Review" button.
  • Enter a name that identifies this role and click Create role, e.g.: "lambda_basic_execution".
  • Click on the "Create Role" button.
Create a Lambda function and add code
  • On the AWS Console
  • From the upper-right menù, select the correct region for your region and skill language. Select the same region selected previously for the "IAM Role". See see Deploy Your Lambda Function to Multiple Regions for more info.
  • Expand "Services", under "Compute", select "Lambda"
  • Click on the "Create Function" button.
  • Select "Author from scratch".
  • Enter the "Function name, e.g.: "SmartHome".
  • Select "Python 3.9" as "Runtime".
  • Expand the "Change default execution role".
  • Select "Use an existing role".
  • Select the role created before, "lambda_basic_execution".
  • Click the "Create Function" button.
  • In the "Function overview", click the "Add trigger" button.
  • Select the "Alexa Smart Home" trigger.
  • In the "Configure triggers" section, add the Skill ID (3) from the developer console in the box specified.
  • Leave "Enable trigger" checked.
  • Click the "Add" button.
  • Select the "Code" tab.
  • Double-Click on the "lambda_function.py".
  • Paste the lambda function, completely replacing the existing code. Use the following lambda function, modified for the Node-RED server.
"""
Copyright 2019 Jason Hu <awaregit at gmail.com>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import os
import json
import logging
import urllib3

_debug = bool(os.environ.get('DEBUG'))

_logger = logging.getLogger('NODE-Red-SmartHome')
_logger.setLevel(logging.DEBUG if _debug else logging.INFO)


def lambda_handler(event, context):
    """Handle incoming Alexa directive."""

    _logger.debug('Event: %s', event)

    base_url = os.environ.get('BASE_URL')
    assert base_url is not None, 'Please set BASE_URL environment variable'

    directive = event.get('directive')
    assert directive is not None, 'Malformatted request - missing directive'
    assert directive.get('header', {}).get('payloadVersion') == '3', \
        'Only support payloadVersion == 3'

    scope = directive.get('endpoint', {}).get('scope')
    if scope is None:
        # token is in grantee for Linking directive 
        scope = directive.get('payload', {}).get('grantee')
    if scope is None:
        # token is in payload for Discovery directive 
        scope = directive.get('payload', {}).get('scope')
    assert scope is not None, 'Malformatted request - missing endpoint.scope'
    assert scope.get('type') == 'BearerToken', 'Only support BearerToken'

    token = scope.get('token')

    verify_ssl = not bool(os.environ.get('NOT_VERIFY_SSL'))

    http = urllib3.PoolManager(
        cert_reqs='CERT_REQUIRED' if verify_ssl else 'CERT_NONE',
        timeout=urllib3.Timeout(connect=2.0, read=10.0)
    )

    response = http.request(
        'POST',
        base_url,
        headers={
            'Authorization': 'Bearer {}'.format(token),
            'Content-Type': 'application/json',
        },
        body=json.dumps(event).encode('utf-8'),
    )
    if response.status >= 400:
        return {
            'event': {
                'payload': {
                    'type': 'INVALID_AUTHORIZATION_CREDENTIAL'
                    if response.status in (401, 403) else 'INTERNAL_ERROR',
                    'message': response.data.decode("utf-8"),
                }
            }
        }
    return json.loads(response.data.decode('utf-8'))

  • Click on the "Deploy" button.
  • Click on the "Configuration" tab.
  • Select the "Environment variables" section.
  • Click on the "Edit" button.
  • Click on the "Add environment variable" button.
  • Enter "BASE_URL" as the "Key".
  • Enter "https://YOUR_DOMAIN/alexa/smarthome" as the Value.
  • Click on the "Add environment variable" button.
  • Enter "DEBUG" as the "Key".
  • Enter "True" as the Value.
  • Click on the "Add environment variable" button.
  • Enter "NOT_VERIFY_SSL" as the "Key".
  • Enter "True" as the Value.
  • Click on the "Save" button.
  • Click on the "Copy ARN" (4) button.
Configure the service endpoint
  • Navigate back to your skill in the developer console.
  • Under "Smart Home service endpoint", in the "Default endpoint" box, provide the ARN number (4) from the Lambda function you created and click Save.
  • If your skill only supports one language/region, provide the same ARN for the default ARN and the selected regional ARN.
  • Click on the "Save" button.
  • Click on the "Setup Account Linking" button.
  • Enter the "Your Web Authorization URI" field as "https://YOUR_DOMAIN/alexa/oauth".
  • Enter the "Access Token URI" field as "https://YOUR_DOMAIN/alexa/token".
  • Enter the "Your Client ID" field with a Client ID of your choice (5). You need it in the Node-RED configuration.
  • Enter the "Your Secret" field with a password of your choice (6). You need it in the Node-RED configuration.
  • Select "Credential in the request body" as "Your Authentication Scheme".
  • Click the "Add scope" button, and fill it with "smart_home" (7).
  • Enter 3600 for the "Default Access Token Expiration Time" field.
  • Click the "Save" button.
  • Copy the "Alexa Redirect URLs" (8), You will need them later.
  • Click on the "Permission" left menù entry.
  • Enable the "Send Alexa Events".
  • Click the "Show" button.
  • Copy the "Alexa Client Id" (9) and "Alexa Client Secret" (10) values, You need them in the Node-RED configuration.
  • Open the "Security Profile" tab.
  • Click the "Edit" button.
  • Copy the three "Alexa Redirect URLs" (8) from the "Account linking" in the "Allowed Return URLs" field.
  • Click the "Save" button.

Add an Alexa Device node on the Node-RED server

You need to add an Alexa Device node in Node-RED to Link your account with your Smart Home skill.

Configure a reverse proxy for forwarding the Amazon request to the Node-RED server

You need to configure your reverse proxy (nginx, Apache HTTP) to forwart the /alexa/oauth, /alexa/token and /alexa/smarthome to the Node-RED Alexa node. Update the /alexa path in according with "HTTP Path" configuration.

See Nginx reverse proxy configuration for an example of the nginx configuration.

Link your account with your Smart Home skill

  • Add and configure a node in Your Node-RED server.
  • Go to the Alexa site
  • Click on Skills
  • Click on Your Skill
  • Click on Skill for developers
  • Click on your SmartHome skill
  • Click on the link to start the process

The Config node

Fill the config node in the following way (You need exactly one config node):

  • "Name": a name, e.g.: "Alexa".
  • "Login with Amazon", checked.
  • "Client id": the value copied in (1).
  • "Secret": the value copied in (2).
  • "Allowed emails": add the email used to login with Amazon.
  • "Alexa skill client id": the value copied in (9).
  • "Alexa skill secret": the value copied in (10).
  • "Your client id": the value copied in (5).
  • "Your secret": the value copied in (6).
  • "Scope": the value copied in (7)., e.g.: "smart_home".
  • "Event endpoint": enter the endpoint for your region. See Send Events to the Correct URL.
  • "HTTP Port": You can leave it empty for using the same Node-RED port, or fill it with a port number. You need to redirect the "/alexa/" HTTPS traffic on this port.
  • "HTTP Path": enter "alexa". If You change it, You need to adapt all the uri in the Amazon configuration.
  • "Verbose log": enable it only for troubleshooting.

The Device node

This is the "real" device node, configure the following info:

  • "Alexa": the alexa config node.
  • "Name": the device name.
  • "Out topic": the topic used when a voice command is received.
  • "Display categories": the display categories. See Display categories for more info.
  • "Interfaces": the interfaces supported by the device. See Interfaces for more info.

Example flow: See the flow used for the tests here

Troubleshooting

This is a checklist for the config:

Check the forward rule for /alexa/oauth

  • Open your browser at "https://YOUR_DOMAIN/alexa/oauth"
  • You should get the message "Wrong client id". If not, check your port forwarding the reverse proxy or reverse proxy config.

Check the forward rule for /alexa/token

  • Enable the debug log in the Node-Red Alexa node configuration.
  • Open your browser at "https://YOUR_DOMAIN/alexa/token"
  • You should get the message "https://YOUR_DOMAIN/alexa/token". If not, check your port forwarding to the reverse proxy or reverse proxy config.

Check the forward rule for /alexa/smarthome

  • Enable the debug log in the Node-Red Alexa node configuration.
  • Open your browser at "https://YOUR_DOMAIN/alexa/smarthome"
  • You should get the following message:
Alexa SmartHome test page

Url: https://YOUR_DOMAIN/alexa/smarthome
Post: {"ok":"ok"}

If not, check your port forwarding to the reverse proxy or reverse proxy config.

Check the lambda function

  • Enable the debug log in the Node-Red Alexa node configuration.
  • Open your browser at AWS lambda
  • Click on the "SmartHome" function
  • Click on the "Execute Test" tab
  • Paste the following message on the editor:
{
  "directive": {
    "header": {
      "namespace": "Test",
      "name": "Test",
      "messageId": "<message id>",
      "payloadVersion": "3"
    },
    "payload": {
      "grant": {
        "type": "OAuth2.AuthorizationCode",
        "code": "Test"
      },
      "grantee": {
        "type": "BearerToken",
        "token": "Test"
      }
    }
  }
}
  • Click on "Execute test" button
  • Click on detail, You should see the following response:
{
  "ok": "ok"
}

Check the Alexa account linking

node: Alexa
msg : string[15]
"oauth_get login"
node: Alexa
msg : string[17]
"oauth_get profile"
node: Alexa
msg : string[37]
"Username [email protected] authorized"
node: Alexa
msg : string[29]
"token_post authorization_code"
node: Alexa
msg : string[37]
"smarthome_post: oauth_get AcceptGrant"

Nginx reverse proxy configuration

Following is a sample forwarding config for Nginx

        location ~ ^/alexa/(oauth|token|smarthome) {
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_pass http://192.168.0.3:3001;
        }

Credits

Parts of this README and large parts of the code comes from Amazon guide.

Copyright and license

Copyright 2021 Claudio Chimera under the GNU General Public License version 3.

node-red-contrib-alexa-virtual-smarthome's People

Contributors

ckhmer1 avatar claudiochimera avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

node-red-contrib-alexa-virtual-smarthome's Issues

Continueing issue 5 becuase it closed

Just opening up a new one because the old one was closed.

I am not getting the granted success. I am getting the access and refresh tokens though

#5

(907e9b1f-45de-4ce1-8da8-a1c97dce05db) Method response body after transformations: 
{
    "access_token": "Atza|B4oLmAn5xWoBFS3CBtHEchhLgkj4Ejg7e7SGxt3aUfjW",
    "token_type": "bearer",
    "expires_in": 3600,
    "refresh_token": "Atzr|BMUKqxYJtEyrNRz6zETTZfs8fmD68qZTHHQku8Fey6EU"
}

Contact Sensor

hello many thanks for the great job works very well
except for the contact sensor. we generated and appears in the alexa app but does not work alex app shows the message "a problem has occurred"
sorry for my bad english, i use google to translate

brightness command when lamp is off

Hi there,
I'm back :)
I updated to version 0.0.28
I have the problem with the light controller with brightness and powerstate
when I turn on the lamp then give the brightness command everything works ...
but when the lamp is off and i directly give the command set lamp to xx brightness, on Nodered I get the brightness value but with powerstate off but in the alexa app the power button is changed to on

Unathorized client sercet

When I go to perform the LWA with my account, I get this error:

Unauthorized client_secret

Now, I triple checked the values that I was placing in. I checked to make sure that I placed in the correct "Your Client ID" and "Your Secret" values in the correct boxes in the config and in the endpoint. But when I do the LWA, the result in unable to link Smart Home

Do you know what might also be causing this error?

Discovering Devices

Hello
As I am testing my back end and learning some new things, I deleted the device from my Alexa profile.

To add it back in, do I need to ask Alexa to "Discover new devices?" I did that and it was unable to find the node red device

Authication server

Hello,
Very good tutorial. Although there are some parts that need to be updated since Amazon changed a few things.

One quick question, there is no guide or pre-req stating that you need an authentication server for the Oauth or how to setup the directories on the Node red installation.

Would you be able to tell me how to set these up?

For the authenticating, I have been using this guide:
https://coderedirect.com/questions/512574/whats-an-easy-way-to-setup-oauth-for-an-amazon-alexa-connected-home-skill

But, if I use this method, there is an issue with the Lambda function script where the BASE_URL does not point to the node red. Is there a way to make the script compatible with the above link and without having the authentication server on the node red installation (Just fyi, I am running this on the Pi)

Get device name

I am using a virtual device node as a BLIND to set the Alexa device volume as a percentage in combination with node-red-contrib-alexa-remote2 node.

Here is the output of the Virtual Device node
percentage: 12
source: "alexa"
mode: "Position.Down"
directive: "SetRangeValue"
name: "hautparleur"
type: "BLINDS"

The problem is that the Virtual Device node is not providing the device name I am speaking to. Is there a way to get it?

Communicating with Alexa node device

OK, so I have the devices and now I am authenticated. Now my biggest thing that I am attempting to do is to communicate with the virtual device.

Here is what i am wanting to do. I want to create a custom command that will get the voltage of a device from Node Red

  1. Say "Alexa, get the voltage of the battery"
  2. This information is sent to the lambda server
  3. Lambda server processes the command and sends something to the Node red server virtual device called battery (most likely a json object with what is being asked but can be anything)
  4. Through a series of nodes, node red grabs the voltage reading and sends it back to the lambda server.
  5. Lambda server processes the data and sends it back to the Alexa service
  6. Alexa says "The voltage of the battery is 12 V"

I am getting hung up on steps 3 and 5. How do I send data (be it json object or request or something else) from the Lambda server to the Virtual device? Is there some sort of API that I can use? Or do I need to send a HTTPS request?

Config error (red triangle) on new nodes

Hi. I have the PRO subscription. Lately, when I add a node, it shows up with a red triangle (see below). I have tried updating the Amazon account but no help. Originally, I think it was due to duplicate names but that has been eliminated. Thanks.
Capture
Capture2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.