-
-
Save matt2005/744b5ef548cc13d88d0569eea65f5e5b 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' | |
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')) |
For those who use this lambda for quite some time - you might use outdated python runtime in AWS , just got this notification :
We are ending support for Python 3.8 in Lambda on October 14, 2024. This follows Python 3.8 End-Of-Life (EOL) which is scheduled for October, 2024 [1].
As described in the Lambda runtime support policy [2], end of support for language runtimes in Lambda happens in several stages. Starting on October 14, 2024, Lambda will no longer apply security patches and other updates to the Python 3.8 runtime used by Lambda functions, and functions using Python 3.8 will no longer be eligible for technical support. Also, Python 3.8 will no longer be available in the AWS Console, although you can still create and update functions that use Python 3.8 via AWS CloudFormation, the AWS CLI, AWS SAM, or other tools. Starting February 28, 2025, you will no longer be able to create new Lambda functions using the Python 3.8 runtime. Starting March 31, 2025, you will no longer be able to update existing functions using the Python 3.8 runtime.
We recommend that you upgrade your existing Python 3.8 functions to the latest available Python runtime in Lambda before October 14, 2024.
You can change it to Python 3.12 - still works with no issues .
Lambda > Functions > Your lambda name
Go to Code > Runtime settings > Edit
Hi! This code is working very fine to me. I am using the CloudFlare Add-On for Home Assistant.
The only concern is that, in the first call, the skill takes almost 10 seconds to run the command but the subsequent calls takes about 1 to 3 seconds.
Is it possible to keep, at least, one connection established using the urllib3.PoolManager to speed the first call?
I am not quite sure, why this isn't working for my setup.
My domain has a CNAME alias pointing to a DynDNS service. Neither the direct use of the DYNDNS url works, nor the domain.
Log look like this:
"errorMessage": "HTTPSConnectionPool(host='homeassistant.example.com', port=443): Max retries exceeded with url: /api/alexa/smart_home (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f20acbc4040>: Failed to establish a new connection: [Errno -2] Name or service not known'))",
IPV6 ping failed in Cloudshell as network is not reachable... what?
I am not quite sure, why this isn't working for my setup. My domain has a CNAME alias pointing to a DynDNS service. Neither the direct use of the DYNDNS url works, nor the domain. Log look like this:
"errorMessage": "HTTPSConnectionPool(host='homeassistant.example.com', port=443): Max retries exceeded with url: /api/alexa/smart_home (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f20acbc4040>: Failed to establish a new connection: [Errno -2] Name or service not known'))",
IPV6 ping failed in Cloudshell as network is not reachable... what?
It is not possible to use IPv6 inside Amazon Skills. You must use IPv4.
Oh... okay. So I expect, that in my case, I need to set up a separate proxy server for ipv4 requests tunneling everything to my ipv6 address, don't I? My ISP doesn't provide me a public IPV4 due to CG-NAT / Ds lite... It is plausible....
Oh... okay. So I expect, that in my case, I need to set up a separate proxy server for ipv4 requests tunneling everything to my ipv6 address, don't I? My ISP doesn't provide me a public IPV4 due to CG-NAT / Ds lite... It is plausible....
Had the same issue, check my solution a few posts up.
Man, you killed the riddle!
I had the same problem and was having trouble for over 2 weeks. It was Bot Fight and WAF. All I had to do was add the rule in waf tools releasing the Amazon ASN and everything went well. Thank you very much. Everything working perfectly. For those who don't know how to identify the ASN that is trying to connect to the Amazon instance, just go to the CloudFlare panel > Security > Events and check the connection attempts to your instance.
God bless you! :)