-
-
Save awarecan/630510a9742f5f8901b5ab284c25e912 to your computer and use it in GitHub Desktop.
""" | |
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' | |
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 payload.scope for Discovery directive | |
scope = directive.get('payload', {}).get('scope') | |
if scope is None: | |
# token is in payload.grantee for AcceptGrant directive | |
scope = directive.get('payload', {}).get('grantee') | |
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"), | |
} | |
} | |
} | |
return json.loads(response.data.decode('utf-8')) |
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,
Tried this several times with different combinations of credentials.
My Log from HA.
And my output from Lambda