From d69e48989b396802022c24ab2de5e9c9f2cf67bd Mon Sep 17 00:00:00 2001 From: marvint24 Date: Mon, 12 Aug 2024 21:42:10 +0000 Subject: [PATCH 1/4] Add a method to run this addon as container --- .gitignore | 1 + ha_skill/CHANGELOG.md | 3 +++ ha_skill/Dockerfile | 4 ++-- ha_skill/README.md | 10 +++++++++- ha_skill/compose.yaml | 6 ++++++ ha_skill/example-options.json | 10 ++++++++++ ha_skill/run.py | 12 +++++++++--- 7 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 .gitignore create mode 100644 ha_skill/compose.yaml create mode 100644 ha_skill/example-options.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fb8c7c9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +options.json \ No newline at end of file diff --git a/ha_skill/CHANGELOG.md b/ha_skill/CHANGELOG.md index 73417bf..d91e89d 100644 --- a/ha_skill/CHANGELOG.md +++ b/ha_skill/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +## [1.0.8] +- Add a method to run this addon as standalone docker container + ## [1.0.7] - Handle large responses by splitting the response across messages diff --git a/ha_skill/Dockerfile b/ha_skill/Dockerfile index e2b36c6..fc13f6f 100644 --- a/ha_skill/Dockerfile +++ b/ha_skill/Dockerfile @@ -1,5 +1,4 @@ -ARG BUILD_FROM -FROM ${BUILD_FROM} +FROM alpine:3.20.2 # Install requirements for add-on RUN apk add --no-cache python3 py3-pip py3-requests py3-boto3 @@ -7,6 +6,7 @@ RUN apk add --no-cache python3 py3-pip py3-requests py3-boto3 # Copy data for add-on COPY run.py / COPY cloudformation.yaml / +COPY options.json /data/options.json ENTRYPOINT [ "python3" ] CMD [ "/run.py" ] diff --git a/ha_skill/README.md b/ha_skill/README.md index c0c2f28..25e0694 100644 --- a/ha_skill/README.md +++ b/ha_skill/README.md @@ -10,4 +10,12 @@ AWS CloudFormation. Manual setup is still required to create a custom Alexa Skill and to create an AWS account and create bootstrap IAM credentials. All AWS usage will fit in the [always free tier](https://aws.amazon.com/free/?awsf.Free%20Tier%20Types=tier%23always-free). -See DOCS.md for setup instructions. \ No newline at end of file +See DOCS.md for setup instructions. + +## Docker standalone mode +If you want to use this addon, but you are running HomeAssistant as a Docker container, you can do the following steps: +1. Create a Long Lived Access Token in HomeAssistant +1. Clone this repo +1. `cd ha_addons/ha_skill/` +1. Rename the `example-options.json` file to `options.json` and paste in your informations +1. You can start the container with: `docker compose up -d` diff --git a/ha_skill/compose.yaml b/ha_skill/compose.yaml new file mode 100644 index 0000000..99336dd --- /dev/null +++ b/ha_skill/compose.yaml @@ -0,0 +1,6 @@ +services: + ha-alexa-skill: + image: ha-alexa-skill + build: + context: . + restart: unless-stopped \ No newline at end of file diff --git a/ha_skill/example-options.json b/ha_skill/example-options.json new file mode 100644 index 0000000..be1a882 --- /dev/null +++ b/ha_skill/example-options.json @@ -0,0 +1,10 @@ +{ + "AWS Access Key": "ASDADFADSF32897438342", + "AWS Secret Key": "fjdfsljkasdfjklsafdkjlasfdkljjsfdklsj", + "AWS Region":"eu-west-1", + "Alexa Skill Id": "amzn1.asl.skill.6546564545-4544-4455-4554-4514545a1c", + "CloudFormation Stack Name": "HASkill", + "Debug": true, + "HA Base URL":"https://myha.mydomain.com", + "HA Token":"dsdsakjdwkljakjjajhgJHhas2jdhFIDKJNHDSKFDSJHKhjkajshdHJDFJHHD34SFJKGDSHKSALJKAHS32h3jhawpsdasa" +} diff --git a/ha_skill/run.py b/ha_skill/run.py index 8d30299..7fab583 100644 --- a/ha_skill/run.py +++ b/ha_skill/run.py @@ -73,7 +73,7 @@ def handle_cloudformation_stack(session, stack_name, stack_params={}): log.info(f'Stack has outputs\n{json.dumps(outputs, indent=2)}') -def poll_for_work(session): +def poll_for_work(session,options): sqs = session.resource('sqs') request_queue = sqs.get_queue_by_name(QueueName=QUEUE_NAME) @@ -82,8 +82,15 @@ def poll_for_work(session): ) token = os.environ.get('SUPERVISOR_TOKEN') + if options['HA Token']: + token=options['HA Token'] assert token is not None + request_url = 'http://supervisor/core/api/alexa/smart_home' + if options['HA Base URL']: + request_url=os.path.join(options['HA Base URL'],'api/alexa/smart_home') + log.debug(f'request_url: "{request_url}"') + log.info(f'Polling for work from {QUEUE_NAME}...') while True: try: @@ -106,7 +113,6 @@ def poll_for_work(session): response_queue = sqs.Queue(payload['response_queue']) group_id = m.attributes['MessageGroupId'] - request_url = 'http://supervisor/core/api/alexa/smart_home' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json', @@ -178,4 +184,4 @@ def split_string_for_sqs(s): 'Debug': str(options.get('Debug', False)) } handle_cloudformation_stack(session, options['CloudFormation Stack Name'], stack_params=stack_params) - poll_for_work(session) \ No newline at end of file + poll_for_work(session,options) \ No newline at end of file From 18fef4cf4184fe98e1c5e5733b8628487a5a4da4 Mon Sep 17 00:00:00 2001 From: marvint24 Date: Mon, 12 Aug 2024 22:05:46 +0000 Subject: [PATCH 2/4] remove secrets from image --- ha_skill/Dockerfile | 4 +++- ha_skill/compose.yaml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ha_skill/Dockerfile b/ha_skill/Dockerfile index fc13f6f..0a31a1c 100644 --- a/ha_skill/Dockerfile +++ b/ha_skill/Dockerfile @@ -6,7 +6,9 @@ RUN apk add --no-cache python3 py3-pip py3-requests py3-boto3 # Copy data for add-on COPY run.py / COPY cloudformation.yaml / -COPY options.json /data/options.json + +RUN mkdir /data +RUN touch /data/options.json ENTRYPOINT [ "python3" ] CMD [ "/run.py" ] diff --git a/ha_skill/compose.yaml b/ha_skill/compose.yaml index 99336dd..be3b122 100644 --- a/ha_skill/compose.yaml +++ b/ha_skill/compose.yaml @@ -3,4 +3,6 @@ services: image: ha-alexa-skill build: context: . - restart: unless-stopped \ No newline at end of file + restart: unless-stopped + volumes: + - ./options.json:/data/options.json From bb5de481acbc322869594465a63112c2b49ed7f9 Mon Sep 17 00:00:00 2001 From: marvint24 Date: Tue, 13 Aug 2024 06:38:44 +0000 Subject: [PATCH 3/4] restore old Dockerfile --- ha_skill/Dockerfile | 6 ++---- ha_skill/Dockerfile_standalone | 14 ++++++++++++++ ha_skill/compose.yaml | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 ha_skill/Dockerfile_standalone diff --git a/ha_skill/Dockerfile b/ha_skill/Dockerfile index 0a31a1c..e2b36c6 100644 --- a/ha_skill/Dockerfile +++ b/ha_skill/Dockerfile @@ -1,4 +1,5 @@ -FROM alpine:3.20.2 +ARG BUILD_FROM +FROM ${BUILD_FROM} # Install requirements for add-on RUN apk add --no-cache python3 py3-pip py3-requests py3-boto3 @@ -7,8 +8,5 @@ RUN apk add --no-cache python3 py3-pip py3-requests py3-boto3 COPY run.py / COPY cloudformation.yaml / -RUN mkdir /data -RUN touch /data/options.json - ENTRYPOINT [ "python3" ] CMD [ "/run.py" ] diff --git a/ha_skill/Dockerfile_standalone b/ha_skill/Dockerfile_standalone new file mode 100644 index 0000000..0a31a1c --- /dev/null +++ b/ha_skill/Dockerfile_standalone @@ -0,0 +1,14 @@ +FROM alpine:3.20.2 + +# Install requirements for add-on +RUN apk add --no-cache python3 py3-pip py3-requests py3-boto3 + +# Copy data for add-on +COPY run.py / +COPY cloudformation.yaml / + +RUN mkdir /data +RUN touch /data/options.json + +ENTRYPOINT [ "python3" ] +CMD [ "/run.py" ] diff --git a/ha_skill/compose.yaml b/ha_skill/compose.yaml index be3b122..117463a 100644 --- a/ha_skill/compose.yaml +++ b/ha_skill/compose.yaml @@ -3,6 +3,7 @@ services: image: ha-alexa-skill build: context: . + dockerfile: Dockerfile_standalone restart: unless-stopped volumes: - ./options.json:/data/options.json From b78ebebffcdfe7d38ced734d0762a9174baeb1bc Mon Sep 17 00:00:00 2001 From: marvint24 Date: Tue, 13 Aug 2024 06:43:04 +0000 Subject: [PATCH 4/4] fix check if key exists --- ha_skill/run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ha_skill/run.py b/ha_skill/run.py index 7fab583..51f07ed 100644 --- a/ha_skill/run.py +++ b/ha_skill/run.py @@ -82,12 +82,12 @@ def poll_for_work(session,options): ) token = os.environ.get('SUPERVISOR_TOKEN') - if options['HA Token']: + if 'HA Token' in options: token=options['HA Token'] assert token is not None request_url = 'http://supervisor/core/api/alexa/smart_home' - if options['HA Base URL']: + if 'HA Base URL' in options: request_url=os.path.join(options['HA Base URL'],'api/alexa/smart_home') log.debug(f'request_url: "{request_url}"')