""" | |
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('HomeAssistant-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' | |
base_url = base_url.strip("/") | |
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') | |
if token is None and _debug: | |
token = os.environ.get('LONG_LIVED_ACCESS_TOKEN') # only for debug purpose | |
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', | |
'{}/api/alexa/smart_home'.format(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"), | |
} | |
} | |
} | |
_logger.debug('Response: %s', response.data.decode("utf-8")) | |
return json.loads(response.data.decode('utf-8')) |
To actually understand what is happening, I am missing debug output for the response, I added the following line just before the last line:
_logger.debug('Response: %s', response.data.decode("utf-8"))
What is missing from the documentation is that when you delete the LONG_LIVED_ACCESS_TOKEN
you can't test anymore via AWS Lambda test feature because it relies on that token.
@DennisGaida Thanks, I've added the debug line to the code.
After changing my Home Assistant server port to 443 instead of 8123, I'm now also experiencing the
We were unable to link Home Assistant at this time
problem after disabling the Alexa skill and trying to re-link accounts.I'm able to hit the Home Assistant login page when clicking the 'Enable' button, but after entering credentials I get the 'unable to link' error. I don't see any errors with the alexa component logging level set to debug.
Edit: I just ended up having to re-create the Alexa skill, despite updating URLS in the console.
I'm experiencing the same. I just tried several ways and I noticed either via direct to HA or via LWA and in both cases the skill is enabled ONLY if the "Send Alexa messaging" in the Permissions tab is NEVER enabled. Whenever you enable that the linking of the skills FAILS. I guess has to be something regarding the OAuth 2.0 protocol I googled a lot but I m not familiar with this kind of programming and debugging and I m still jammed.
I m using HA Core on docker and ssl support via Caddy and noip.com (for DDDNS) . I m not sure if Caddy support to OAuth2 could be the key .........anyone has any idea ?
PLEASE HELP
Otherwise I've to switch to activate routines via Alex Media Player...............
EDIT: The same behaviour either with original haaska script or matt2005/lambda_function.py . That's something before the use of the lambda functions strictly depending by account linking process............is my understanding
Hi Guys, i have a little Problem.
I have a DS-Lite Connection at home so i'm using AAAA Records to remote-Access my Home-Assistant via IPV6.
But unfortunately this Code doesn't work for me for some reasons... I can normally access my HomeAssistant and i even get a "405" when entering https://YOUR-HA-URL:YOUR-PORT/api/alexa/smart_home , wherever i am. But why can't the Lambda function conntect to my HA... error message as follows:
I hope someone can help me... don't know what to do.. or is the Lambda Function just unable to do ipv6 connections?
Thanks in advance!
Logger: homeassistant.components.http.ban
Source: components/http/ban.py:82
Integration: HTTP (documentation, issues)
First occurred: ١٢:٣٨:٣٩ (1 occurrences)
Last logged: ١٢:٣٨:٣٩
Login attempt or request with invalid authentication from 45.242.228.202 (45.242.228.202). Requested URL: '/auth/login_flow'. (Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/17.0 Chrome/96.0.4664.104 Safari/537.36)
win mack add Alexa skill to work to home assistant
@GamingMaker It seems your firewall problem.
or network path blocked in somewhere.
Check your network path from your mobile 4G/5G wireless network to your HA address not by WiFi.
@matt2005 If you don't mind, can you consider a line to add at the beginning of the lambda_handler or somewhere?
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
Refer the step by step to implement Alexa skil bridge
at
https://alexa_skill_bridge_lambda
The Checklist for your guys in the past and the future for the record.
(If you don't pass thru below checklist any of bit, you cannot get the own Alexa skill link.)
[pre-requisition]
-
Check HA address that your own domain or dynamic DNS(DDNS) or even IP
-
Prepare sure SSL certification that the free Let'sencrypt or free self-signed or commercial SSL cert if you would like.
-
Set the SSL cert on your server for HTTPS. And make sure SSL properly applied.
-
Set Alexa configuration in configuration.xml. Start simple and fill up later after link. Make problem simple for linkage.
-
Create AWS account
-
Choose the AWS Lambda region that N.Virginia or Oregon or EU that related to your Alexa language locale. AWS Alexa service will automatically find your Lambda region geologically by judging your Alexa locale.
I prefer make three identically same lambda in each Regions that Virginia, Oregon, EU if you need it.
-
Just copy & paste the source code into the Lambda(s) from Matt2005 at https://gist.github.com/matt2005/744b5ef548cc13d88d0569eea65f5e5b (thanks)
-
Create AWS Alexa Developer Account
-
Create AWS Alexa Skill for your own HA linkage as the materials
-
Put the endpoint address into the Alexa skill setting(as only default if you only have one, or set multiply each by check the checkbox.)
-
Setup the Lambdas's trigger as Alexa
-
READ carefully ALL the MATERIALS regards above to complete the section for 'Lambda' and 'Skill' both.(above are only simple summary)
-
Stop/cut and logout the home asisstant's(by nabucase.net) cloud annual payment service from the HA settings if you have.
[To get account link(important part)]
- Check the AWS Lambda region that N.Virginia or Oregon or EU that related to your Alexa locale
- Make sure your home assistant's exposed port is 443 not 8123 which Alexa OAuth standard requirement.
so need to change your nginx's exernal open port into 443. Giveaway the 443 to HA if another your own service holding it.
- Make sure your network firewall that possible to reach to Home assistant by LTE or from any outside not your home Wi-Fi self.
by test POST https://your_ha-domain_name/api/alexa/smart_home from lambda source code that any of response working. If you can see 40x on web browser, you will be fine.
Make sure below paths are accessible without any blocker(do not care about server errors if you can reach it.)
- GET https://your_ha-domain_name/auth/authorize (OAuth standard api interface)
- GET https://your_ha-domain_name/auth/providers (OAuth standard api interface)
- GET https://your_ha-domain_name/manifest.json (OAuth standard api interface)
- POST https://your_ha-domain_name/auth/login_flow (OAuth standard api interface)
- POST https://your_ha-domain_name/api/alexa/smart_home (Alexa standard interface)
which means that allow every URL paths in your firewall and NginX for HA.
- Make sure your NginX really bypassing to your HA the outside traffic.
Especially, https://your_ha-domain_name/api/alexa/smart_home paht possible to bypass all traffic.
-
Get your final external address, and set into all BASE_URL of environment variables & every in AWS Alexa console, AWS Lambeda, NginX, etc that port 443 without ':xxxx' part for your HA address.
-
If your SSL cert is free one, make sure your skill as in 'DEV' mode on the Alexa console where listed. If you have commercial no matter what dev or production mode.
-
Go to Alexa app or web > go to skill list > find your skill in DEV or peroper tab > click the skill you made > 'Enable' > Now login into HA(doesn't matter MFA or not) > TADA! you can see beautiful green 'successfully linked' message.
(if you cannot, it might firewall or any network path issue that blocked to reach to HA. So go back and recheck again.)
[Wait discovery(which Automatic drive)]
- AFTER, account link as above, the Alexa app gose to discovery mode.
IF you already have discovered devices list in the Alexa app by another Alexa link service,
the app will tell you 'NO NEW device discovered' that nothing wrong since there are NO MORE NEW devices to discover.
or
if you are very new to link-up with Alexa, after discovery while, you can see all the devices on your Alexa app.
Walla!. All your from now.
[Addition]
- Do not spend your money for same services. Since this is exactly same service you have now.
[Summary]
- Exposed 443 HA port.
- Any SSL cert.
- Get the external HA Address.
- Alexa config in HA confiuration.xml
- Lambda at right region for locale
- Set the address into everywhere correctly like BASE_URL, Alexa console, etc.
- Non-blocked network path to HA reside in your room.
- Wait discovery and use.
[Q & A]
- Is there will be extra charges/bill from AWS Lambda or Alexa Console?
Mostly zero. Since the Lambda(a bridge between Alexa system and HA) only used when you are in log-in via Alexa skill
and discovery and some only few.
By the discovered infomation(which rarely occur), Alexa communicate with HA directly in your local home network.
In common sense, monthly 5000 calls of small Lambda only make about 0.02 USD per month. That cheap enough.
it only make sevral hundres of calls. Do not worry unless your system hacked by bad guys.
- Is there any addtional technical modification while do all above?
No and Yes.
For Alexa console and AWS Lambda code, no extra effort needed. Just copy & paste all the things and do as the materials exaclty guide you. Do no addtional thing unless you are exaxtly understand what you are doing additionally.
For your local home network(like nginx and firewalls, etc), yes. you need to do adjust your own network configuration. But you can find everythings from web. Just do google.
Hi Guys, i have a little Problem. I have a DS-Lite Connection at home so i'm using AAAA Records to remote-Access my Home-Assistant via IPV6. But unfortunately this Code doesn't work for me for some reasons... I can normally access my HomeAssistant and i even get a "405" when entering https://YOUR-HA-URL:YOUR-PORT/api/alexa/smart_home , wherever i am. But why can't the Lambda function conntect to my HA... error message as follows:
I hope someone can help me... don't know what to do.. or is the Lambda Function just unable to do ipv6 connections? Thanks in advance!
Did you find any solution?
after following the instructions to a letter, my issue was in cloudflare (its always dns isnt it?). i had "bot fight mode" (Security->Bots) turned on. and it was blocking any attempt at connecting the app, as well as the lambda test. as a work around under WAF -> Tools, i added
AS16509 (make sure to hit enter after you type it in) as a ip access rule to allow access. seems to work, but be kinda hacky.
help
I followed Lewis's video which was fantastic, I got as far as testing the link to my Home Assistant instance with worked showing my equipment. Unfortunately my SD card crashed and its took me 11days to resurrect my Home Assistant instance, anyway I tried to recover the AWS, Alexa and Home Assistant links. Anyway I get all the way through until I test the setup and then I get an error relating to config START RequestId: 5e47a47a-1306-4dbc-9656-7672bc89a22b Version: $LATEST
[ERROR] AssertionError: Only support payloadVersion == 3
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 36, in lambda_handler
'Only support payloadVersion == 3'
END RequestId: 5e47a47a-1306-4dbc-9656-7672bc89a22b
REPORT RequestId: 5e47a47a-1306-4dbc-9656-7672bc89a22b Duration: 20.64 ms Billed Duration: 21 ms Memory Size: 128 MB Max Memory Used: 38 MB Init Duration: 145.78 ms
I am completely lost as to what to do, I tried deleting all from AWS Function and Role redoing from scratch, this made no difference I got the same error.
Bazza
hmmm .. when adding default endpoint in alexa developer console getting following, any ideas please? ..... Please make sure that "Alexa Smart Home" is selected for the event source type, for provided arn [Invalid value] : arn:aws:lambda:eu-west-1:xxxxxxxxxxxxxx:function:HomeAssistant
thanks
Make sure your using the region Ireland, there’s only a few of the available options work.
Sorry I’m not the right person to help you, I’m also completely stuck, the region is one area I went astray on!
I'm also stuck on this same point. None of the suggested regions appear to have the "smart home" skill. Everything else works and the lambda code can interact with home assistant when I run a test. I just can't get the Alexa skill to integrate with the lambda code. Has anybody figured this out?
I'm also stuck on this same point. None of the suggested regions appear to have the "smart home" skill. Everything else works and the lambda code can interact with home assistant when I run a test. I just can't get the Alexa skill to integrate with the lambda code. Has anybody figured this out?
Make sure you use the Ireland region!
I'm also stuck on this same point. None of the suggested regions appear to have the "smart home" skill. Everything else works and the lambda code can interact with home assistant when I run a test. I just can't get the Alexa skill to integrate with the lambda code. Has anybody figured this out?
Make sure you use the Ireland region!
Thanks for your reply. I have tried all suggested regions. I've attached a screenshot of the Ireland region as an example. The only available trigger is the "Alexa" trigger. Neither the "Alexa Smart Home" or "Alexa Skill Kit" options appear. It is like this for all suggested regions.
What would it cost to get one of you to remote build me a virtualbox for this? I can’t use HA cloud
I'm also stuck on this same point. None of the suggested regions appear to have the "smart home" skill. Everything else works and the lambda code can interact with home assistant when I run a test. I just can't get the Alexa skill to integrate with the lambda code. Has anybody figured this out?
Make sure you use the Ireland region!
Thanks for your reply. I have tried all suggested regions. I've attached a screenshot of the Ireland region as an example. The only available trigger is the "Alexa" trigger. Neither the "Alexa Smart Home" or "Alexa Skill Kit" options appear. It is like this for all suggested regions.
I don't know why it was not doing this when I first posted, but selecting the Alexa iot skill in a supported region now gives me additional options. After selecting the skill, I can select between Alexa Smart Home or Alexa Skill Kit. Selecting Alexa Smart Home seems to do the trick.
I'm at a loss. This has worked - and not worked - and worked - etc - according to the results of the Lambda tests. I have fiddled with so many things and it seems completely random when it works and not. I rarely get two successful tests in a row (but I did a couple times). When it doesn't work, I typically get "Task timed out after 3.01 seconds". When it does work, I've been able to see the devices/entities I expose in the configuration.yaml
file in the logging details, so I know it's communicating w/ my HA. Yet, no matter the situation, Alexa never discovers these exposed entities.
I'm using CloudFlare's Free Tunnel and have allowed WAF (Web Application Firewall) rules that allow unfettered communication between about a dozen Amazon ASNs as well as any traffic originating from HA.
I've also setup my HA using cloudflare. This integration was working very well for me for a while but has recently stopped working, complaining about an SSL error.
The lambda test result now gives me this:
"errorMessage": "HTTPSConnectionPool(host='MY.HA.URL', port=443): Max retries exceeded with url: /api/alexa/smart_home (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1091)')))",
For those who are using Cloudflare's free tier behind your IP and are having difficulty getting it to work, try disabling Bot Fight Mode. I know it's not ideal, but it's the only way I could get it to work for my setup. Maybe anyone have any suggestions?
I found I had to do this a few months back when I changed ISP providers and I was messing with CloudFlare settings at the same time. Think this could be many peoples problem but maybe that setting is off as default and I turned it on myself!?
For those who are using Cloudflare's free tier behind your IP and are having difficulty getting it to work, try disabling Bot Fight Mode. I know it's not ideal, but it's the only way I could get it to work for my setup. Maybe anyone have any suggestions?
I found I had to do this a few months back when I changed ISP providers and I was messing with CloudFlare settings at the same time. Think this could be many peoples problem but maybe that setting is off as default and I turned it on myself!?
Thanks for the hint. Same problem here.
But instead of "Bot Fight Mode" I had enabled a "WAF" (Web Application Firewall).
I had blocked all connections instead of Germany.
But since the Alexa requests are coming from Ireland they were always blocked.
Now after adding Irland to my white list it’s working again 😃.
i am trying to add a user agent in the post request. For that i have added this below.
Unfortunately it is not working as expected.
User_Agent = "python-urllib3/1.26.9"
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',
'{}/api/alexa/smart_home'.format(base_url),
headers={
'Authorization': 'Bearer {}'.format(token),
'Content-Type': 'application/json',
'User-Agent': User_Agent
},
body=json.dumps(event).encode('utf-8'),
)
I've been fighting this for what seems like two days now. Lots of good comments here, that pointed me in the right direction. Figured I would document what worked for me, in hopes that it helps someone save some time.
Specifically, I'm running a Docker instance on Synology, and my only public IP is IP6. Amazon servers will only resolve IP4, so I need a IP4->IP6 proxy. This is pretty simple (festeip.de, MyOnlinePortal.net) both work, but they provide a port that is NOT 443 for the proxy address. Everything worked until account linking, which always failed after logging in to HASS. As noted above, the connections for Alexa account linking have to be made over SSL AND over port 443.
I finally got the Alexa account to link by:
- setup a cloudflare tunnel (gives me the public IP4 addr) that
- tunnels to a CNAME entry maintained by DDNS (Synology's built-in service supports IP6)
- CNAME IP resolves to my NAS IP directly (router forwards port 443 is to NAS)
- A reverse proxy (Synology Login Portal) translates the incoming address (https://my-cloudflare-domain:443) to http://localhost:8123.
From my understanding, the only way to use any skills with HA aside from TTS is to use routines triggered by binary sensors with the type door, window, garage door, and opening. I haven't had any success using this method, but others claim they have.
I'm not really adept at this sort of thing and I only followed a tutorial on Youtube, so I'm sure there is someone here with a better undertsanding that can give you a better answer.