mirror of
https://github.com/hassio-addons/addon-lutron-cert.git
synced 2025-05-03 18:51:26 +00:00
✨ Add new Hass.io add-on: Lutron Certificate
This commit is contained in:
commit
2364352ba7
41 changed files with 1885 additions and 0 deletions
19
.editorconfig
Executable file
19
.editorconfig
Executable file
|
@ -0,0 +1,19 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
ident_size = 4
|
||||
|
||||
[*.md]
|
||||
ident_size = 2
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.json]
|
||||
ident_size = 2
|
||||
|
||||
[{.gitignore,.gitkeep,.editorconfig}]
|
||||
ident_size = 2
|
4
.github/CODEOWNERS
vendored
Normal file
4
.github/CODEOWNERS
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Require maintainer's :+1: for changes to the .github/ repo-config files
|
||||
# mainly due to https://github.com/probot/settings privilege escalation
|
||||
.github/* @frenck
|
||||
.gitlab-ci.yml @frenck
|
20
.github/ISSUE_TEMPLATE.md
vendored
Executable file
20
.github/ISSUE_TEMPLATE.md
vendored
Executable file
|
@ -0,0 +1,20 @@
|
|||
# Problem/Motivation
|
||||
|
||||
> (Why the issue was filed)
|
||||
|
||||
## Expected behavior
|
||||
|
||||
> (What you expected to happen)
|
||||
|
||||
## Actual behavior
|
||||
|
||||
> (What actually happened)
|
||||
|
||||
## Steps to reproduce
|
||||
|
||||
> (How can someone else make/see it happen)
|
||||
|
||||
## Proposed changes
|
||||
|
||||
> (If you have a proposed change, workaround or fix,
|
||||
> describe the rationale behind it)
|
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
Executable file
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
Executable file
|
@ -0,0 +1,9 @@
|
|||
# Proposed Changes
|
||||
|
||||
> (Describe the changes and rationale behind them)
|
||||
|
||||
## Related Issues
|
||||
|
||||
> ([Github link][autolink-references] to related issues or pull requests)
|
||||
|
||||
[autolink-references]: https://help.github.com/articles/autolinked-references-and-urls/
|
2
.github/autolabeler.yml
vendored
Normal file
2
.github/autolabeler.yml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
"Type: Documentation": ["*.md", "*.j2"]
|
50
.github/config.yml
vendored
Normal file
50
.github/config.yml
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
# Configuration for request-info - https://github.com/behaviorbot/request-info
|
||||
|
||||
# *OPTIONAL* Comment to reply with
|
||||
# Can be either a string :
|
||||
requestInfoReplyComment:
|
||||
- "We would appreciate it if you could provide us with more info about this issue/pr!"
|
||||
- "Hmmm... That issue/PR is kinda low on text. Could you please provide some more content?"
|
||||
|
||||
# *OPTIONAL* default titles to check against for lack of descriptiveness
|
||||
# MUST BE ALL LOWERCASE
|
||||
requestInfoDefaultTitles: []
|
||||
|
||||
# *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given
|
||||
requestInfoLabelToAdd: "Incomplete"
|
||||
|
||||
# *OPTIONAL* Require Pull Requests to contain more information than what is provided in the PR template
|
||||
# Will fail if the pull request's body is equal to the provided template
|
||||
checkPullRequestTemplate: true
|
||||
|
||||
# *OPTIONAL* Only warn about insufficient information on these events type
|
||||
# Keys must be lowercase. Valid values are 'issue' and 'pullRequest'
|
||||
requestInfoOn:
|
||||
pullRequest: true
|
||||
issue: true
|
||||
|
||||
# *OPTIONAL* Add a list of people whose Issues/PRs will not be commented on
|
||||
# keys must be GitHub usernames
|
||||
requestInfoUserstoExclude: []
|
||||
|
||||
# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
|
||||
|
||||
# Comment to be posted to on first time issues
|
||||
newIssueWelcomeComment: >
|
||||
:wave: Thanks for opening your first issue here!
|
||||
If you're reporting a :bug: bug, please make sure you include steps to reproduce it.
|
||||
Also, logs, error messages and information about your hardware might be usefull.
|
||||
|
||||
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
|
||||
|
||||
# Comment to be posted to on PRs from first time contributors in your repository
|
||||
newPRWelcomeComment: >
|
||||
:sparkling_heart: Thanks for opening this pull request! :sparkling_heart:
|
||||
If your PR gets accepted and merged in, we will invite you to the project :tada:
|
||||
|
||||
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
|
||||
|
||||
# Comment to be posted to on pull requests merged by a first time user
|
||||
firstPRMergeComment: >
|
||||
Congrats on merging your first pull request! :tada::tada::tada:
|
10
.github/invite-contributors.yml
vendored
Normal file
10
.github/invite-contributors.yml
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
# If true, this will add new contributors as outside collaborators
|
||||
# to the repo their PR was merged in. Team name is ignored if this
|
||||
# flag is set to true.
|
||||
isOutside: false
|
||||
|
||||
# Specify team name to add new contributors to a specific team
|
||||
# within your organization.
|
||||
# Use team name or team-name-slug
|
||||
team: Contributors
|
20
.github/lock.yml
vendored
Normal file
20
.github/lock.yml
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
# Configuration for lock-threads - https://github.com/dessant/lock-threads
|
||||
# Number of days of inactivity before a closed issue or pull request is locked
|
||||
daysUntilLock: 30
|
||||
|
||||
# Comment to post before locking. Set to `false` to disable
|
||||
lockComment: >
|
||||
This thread has been automatically locked because it has not had recent
|
||||
activity. Please open a new issue for related bugs and link to relevant
|
||||
comments in this thread.
|
||||
|
||||
# Issues or pull requests with these labels will not be locked
|
||||
# exemptLabels:
|
||||
# - no-locking
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
# only: issues
|
||||
|
||||
# Add a label when locking. Set to `false` to disable
|
||||
lockLabel: false
|
20
.github/move.yml
vendored
Normal file
20
.github/move.yml
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
# Delete the command comment when it contains no other content
|
||||
deleteCommand: true
|
||||
|
||||
# Close the source issue after moving
|
||||
closeSourceIssue: true
|
||||
|
||||
# Lock the source issue after moving
|
||||
lockSourceIssue: true
|
||||
|
||||
# Mention issue and comment authors
|
||||
mentionAuthors: true
|
||||
|
||||
# Preserve mentions in the issue content
|
||||
keepContentMentions: false
|
||||
|
||||
# Set custom aliases for targets
|
||||
# aliases:
|
||||
# r: repo
|
||||
# or: owner/repo
|
13
.github/no-response.yml
vendored
Normal file
13
.github/no-response.yml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
# Configuration for probot-no-response - https://github.com/probot/no-response
|
||||
# Number of days of inactivity before an Issue is closed for lack of response
|
||||
daysUntilClose: 14
|
||||
# Label requiring a response
|
||||
responseRequiredLabel: "Status: Awaiting response"
|
||||
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue has been automatically closed because there has been no response
|
||||
to our request for more information from the original author. With only the
|
||||
information that is currently in the issue, we don't have enough information
|
||||
to take action. Please reach out if you have or find the answers we need so
|
||||
that we can investigate further.
|
14
.github/potential-duplicates.yml
vendored
Normal file
14
.github/potential-duplicates.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
# Label name and color to set, when potential duplicates are detected
|
||||
issueLabel: "Potential duplicate"
|
||||
labelColor: e6e6e6
|
||||
|
||||
# If similarity is higher than this threshold, issue will be marked as duplicate
|
||||
threshold: 0.70
|
||||
|
||||
# Comment to post when potential duplicates are detected
|
||||
referenceComment: >
|
||||
Potential duplicates found:
|
||||
{{#issues}}
|
||||
- [#{{ number }}] {{ title }} ({{ accuracy }}%)
|
||||
{{/issues}}
|
150
.github/settings.yml
vendored
Normal file
150
.github/settings.yml
vendored
Normal file
|
@ -0,0 +1,150 @@
|
|||
---
|
||||
repository:
|
||||
description: "Get Lutron Cert - Community Hass.io Add-on for Home Assistant"
|
||||
homepage: https://addons.community
|
||||
topics: lutron, lutron-caseta, lutron-cert, cert, ssl, hassio-addons, hassio, hass, home-assistant, homeassistant, home-automation
|
||||
private: false
|
||||
has_issues: true
|
||||
has_projects: false
|
||||
has_wiki: false
|
||||
has_downloads: false
|
||||
default_branch: master
|
||||
allow_squash_merge: true
|
||||
allow_merge_commit: false
|
||||
allow_rebase_merge: true
|
||||
labels:
|
||||
# Priority labels
|
||||
- name: "Priority: Critical"
|
||||
color: ee0701
|
||||
description: "This should be dealt with ASAP. Not fixing this issue would be a serious error."
|
||||
- name: "Priority: High"
|
||||
color: b60205
|
||||
description: "After critical issues are fixed, these should be dealt with before any further issues."
|
||||
- name: "Priority: Medium"
|
||||
color: 0e8a16
|
||||
description: "This issue may be useful, and needs some attention."
|
||||
- name: "Priority: Low"
|
||||
color: e4ea8a
|
||||
description: "Nice addition, maybe... someday..."
|
||||
|
||||
# Type labels
|
||||
- name: "Type: Bug"
|
||||
color: ee0701
|
||||
description: "Inconsistencies or issues which will cause a problem for users or implementors."
|
||||
- name: "Type: Documentation"
|
||||
color: 0052cc
|
||||
description: "Solely about the documentation of the project."
|
||||
- name: "Type: Enhancement"
|
||||
color: 1d76db
|
||||
description: "Enhancement of the code, not introducing new features."
|
||||
- name: "Type: Feature"
|
||||
color: 0e8a16
|
||||
description: "New features or options."
|
||||
- name: "Type: Support"
|
||||
color: 5319e7
|
||||
description: "Marks an issue as an support ticket."
|
||||
- name: "Type: Discussion"
|
||||
color: d4c5f9
|
||||
description: "Marks an issue as an generic discussion ticket."
|
||||
- name: "Type: Maintaince"
|
||||
color: 2af79e
|
||||
description: "Generic maintaince tasks, e.g., package updates."
|
||||
|
||||
# Additional markers
|
||||
- name: "Security"
|
||||
color: ee0701
|
||||
description: "Marks an security issues that needs to be resolved asap."
|
||||
- name: "Idea"
|
||||
color: fef2c0
|
||||
description: "Marks an idea, which might be excepted and implemented."
|
||||
- name: "Incomplete"
|
||||
color: fef2c0
|
||||
description: "Marks an PR or issue that is missing information."
|
||||
- name: "Pull request"
|
||||
color: fbca04
|
||||
description: "There is an PR opened for this issue."
|
||||
- name: "Accepted"
|
||||
color: c2e0c6
|
||||
description: "This issue or PR has been accepted."
|
||||
- name: "Declined"
|
||||
color: f9d0c4
|
||||
description: "This issue or PR has been declined."
|
||||
- name: "Potential duplicate"
|
||||
color: e6e6e6
|
||||
description: "This issue has been automatically marked as a potential duplicate."
|
||||
|
||||
# Ongoing Status labels
|
||||
- name: "Status: Triage"
|
||||
color: fbca04
|
||||
description: "This issue needs to be triaged."
|
||||
- name: "Status: On hold"
|
||||
color: cccccc
|
||||
description: "Issue or PR that has been placed on hold for now."
|
||||
- name: "Status: In progress"
|
||||
color: fbca04
|
||||
description: "Issue is currently being resolved by a developer."
|
||||
- name: "Status: Stale"
|
||||
color: fef2c0
|
||||
description: "There has not been activity on this issue or PR for quite some time."
|
||||
- name: "Status: Awaiting response"
|
||||
color: fef2c0
|
||||
description: "Issue or PR awaits response from the creator."
|
||||
- name: "Status: Blocked"
|
||||
color: fef2c0
|
||||
description: "Progress on this issue is currently not possible."
|
||||
|
||||
# Closing status labels
|
||||
- name: "Closed: Known limitation"
|
||||
color: e6e6e6
|
||||
description: "Issue is closed, it is a known limitation."
|
||||
- name: "Closed: Expected behavior"
|
||||
color: e6e6e6
|
||||
description: "Issues is closed, it is expected behavior."
|
||||
- name: "Closed: Duplicate"
|
||||
color: e6e6e6
|
||||
description: "Issue is closed, duplicate of an existing issue."
|
||||
- name: "Closed: Invalid"
|
||||
color: e6e6e6
|
||||
description: "Issue is closed, marked as not a valid issue (e.g., an user error)."
|
||||
- name: "Closed: Wrong repository"
|
||||
color: e6e6e6
|
||||
description: "Issue is closed, was created in the wrong repository."
|
||||
- name: "Closed: Won't Fix"
|
||||
color: e6e6e6
|
||||
description: "Issue is closed, it won't be fixed."
|
||||
- name: "Closed: Done"
|
||||
color: c2e0c6
|
||||
description: "Issue closed, work on this issue has been marked complete."
|
||||
|
||||
# Others
|
||||
- name: "Beginner Friendly"
|
||||
color: 0e8a16
|
||||
description: "Good first issue for people wanting to contribute to the project."
|
||||
- name: "Help wanted"
|
||||
color: 0e8a16
|
||||
description: "We need some extra helping hands or expertise in order to resolve this."
|
||||
- name: "Hacktoberfest"
|
||||
description: "Issues/PRs are participating in the Hacktoberfest"
|
||||
color: fbca04
|
||||
|
||||
branches:
|
||||
- name: master
|
||||
protection:
|
||||
required_pull_request_reviews:
|
||||
# required_approving_review_count: 1
|
||||
dismiss_stale_reviews: true
|
||||
require_code_owner_reviews: true
|
||||
dismissal_restrictions:
|
||||
users: []
|
||||
teams:
|
||||
- Admins
|
||||
- Masters
|
||||
required_status_checks:
|
||||
strict: false
|
||||
contexts: []
|
||||
enforce_admins: false
|
||||
restrictions:
|
||||
users: []
|
||||
teams:
|
||||
- Admins
|
||||
- Masters
|
61
.github/stale.yml
vendored
Normal file
61
.github/stale.yml
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 60
|
||||
|
||||
# Number of days of inactivity before a stale Issue or Pull Request is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 7
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- "Status: On hold"
|
||||
- "Status: In progress"
|
||||
- "Status: Awaiting response"
|
||||
- "Status: Blocked"
|
||||
- "Idea"
|
||||
- "Security"
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: "Status: Stale"
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
|
||||
# Comment to post when removing the stale label.
|
||||
# unmarkComment: >
|
||||
# Your comment here.
|
||||
unmarkComment: false
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
# closeComment: >
|
||||
# Your comment here.
|
||||
closeComment: false
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 30
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
only: issues
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
# pulls:
|
||||
# daysUntilStale: 30
|
||||
# markComment: >
|
||||
# This pull request has been automatically marked as stale because it has not had
|
||||
# recent activity. It will be closed if no further activity occurs. Thank you
|
||||
# for your contributions.
|
||||
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - confirmed
|
22
.github/support.yml
vendored
Normal file
22
.github/support.yml
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
---
|
||||
# Configuration for support-requests - https://github.com/dessant/support-requests
|
||||
|
||||
# Label used to mark issues as support requests
|
||||
supportLabel: "Type: Support"
|
||||
|
||||
# Comment to post on issues marked as support requests. Add a link
|
||||
# to a support page, or set to `false` to disable
|
||||
supportComment: >
|
||||
:wave: We use the issue tracker exclusively for bug reports and feature requests.
|
||||
However, this issue appears to be a support request. Please use our
|
||||
support channels to get help with the project.
|
||||
|
||||
Head over to the [Home Assistant community forum](https://community.home-assistant.io/)
|
||||
or join our [Discord](https://discord.me/hassioaddons) chat.
|
||||
|
||||
# Close issues marked as support requests
|
||||
close: true
|
||||
|
||||
# Lock issues marked as support requests
|
||||
lock: false
|
0
.gitignore
vendored
Normal file
0
.gitignore
vendored
Normal file
428
.gitlab-ci.yml
Normal file
428
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,428 @@
|
|||
---
|
||||
image: docker:latest
|
||||
|
||||
variables:
|
||||
ADDON_GITHUB_REPO: hassio-addons/addon-lutron-cert
|
||||
ADDON_SLUG: lutron-cert
|
||||
ADDON_TARGET: lutron-cert
|
||||
DOCKER_DRIVER: overlay2
|
||||
DOCKER_HUB_ORG: hassioaddons
|
||||
|
||||
stages:
|
||||
- preflight
|
||||
- build
|
||||
- scan
|
||||
- deploy
|
||||
- manifest
|
||||
- publish
|
||||
|
||||
# Generic DIND template
|
||||
.dind: &dind
|
||||
before_script:
|
||||
- docker info
|
||||
services:
|
||||
- name: docker:dind
|
||||
command: ["--experimental"]
|
||||
|
||||
# Generic preflight template
|
||||
.preflight: &preflight
|
||||
stage: preflight
|
||||
tags:
|
||||
- preflight
|
||||
|
||||
# Generic build template
|
||||
.build: &build
|
||||
<<: *dind
|
||||
stage: build
|
||||
before_script:
|
||||
- docker info
|
||||
- |
|
||||
if [ "$(apk --print-arch)" = "amd64" ]; then
|
||||
docker run --rm --privileged hassioaddons/qemu-user-static:latest
|
||||
fi
|
||||
- |
|
||||
echo "${CI_JOB_TOKEN}" | docker login \
|
||||
--username gitlab-ci-token \
|
||||
--password-stdin \
|
||||
registry.gitlab.com
|
||||
- docker pull "registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:cache" || true
|
||||
script:
|
||||
- |
|
||||
docker build \
|
||||
--build-arg "BUILD_FROM=${FROM}" \
|
||||
--build-arg "BUILD_DATE=$(date +"%Y-%m-%dT%H:%M:%SZ")" \
|
||||
--build-arg "BUILD_ARCH=${ADDON_ARCH}" \
|
||||
--build-arg "BUILD_REF=${CI_COMMIT_SHA}" \
|
||||
--build-arg "BUILD_VERSION=${CI_COMMIT_TAG:-${CI_COMMIT_SHA:0:7}}" \
|
||||
--cache-from "registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:cache" \
|
||||
--tag \
|
||||
"registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:${CI_COMMIT_SHA}" \
|
||||
"${ADDON_TARGET}"
|
||||
- |
|
||||
docker push \
|
||||
"registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:${CI_COMMIT_SHA}"
|
||||
# Generic scan template
|
||||
.scan: &scan
|
||||
<<: *dind
|
||||
stage: scan
|
||||
allow_failure: true
|
||||
before_script:
|
||||
- docker info
|
||||
- docker run -d --name db arminc/clair-db:latest
|
||||
- docker run -p 6060:6060 --link db:postgres -d --name clair arminc/clair-local-scan:v2.0.1
|
||||
- apk add -U curl ca-certificates
|
||||
- |
|
||||
curl \
|
||||
--silent \
|
||||
--show-error \
|
||||
--location \
|
||||
--fail \
|
||||
--retry 3 \
|
||||
--output /usr/bin/clair-scanner \
|
||||
https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
|
||||
- chmod +x /usr/bin/clair-scanner
|
||||
- touch clair-whitelist.yml
|
||||
- echo "Waiting for Clair to start"
|
||||
- |
|
||||
while ! nc -z docker 6060; do
|
||||
sleep 1
|
||||
WAIT=$((${WAIT} + 1))
|
||||
if [ "${WAIT}" -gt 30 ]; then
|
||||
echo "Error > Timeout waiting for Clair to start"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
- docker pull "registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:${CI_COMMIT_SHA}"
|
||||
script:
|
||||
- |
|
||||
clair-scanner \
|
||||
-c http://docker:6060 \
|
||||
--ip $(hostname -i) \
|
||||
-w clair-whitelist.yml \
|
||||
"registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:${CI_COMMIT_SHA}"
|
||||
tags:
|
||||
- scan
|
||||
|
||||
# Generic deploy template
|
||||
.deploy: &deploy
|
||||
<<: *dind
|
||||
stage: deploy
|
||||
before_script:
|
||||
- docker info
|
||||
- docker pull "registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:${CI_COMMIT_SHA}"
|
||||
- |
|
||||
echo "${CI_JOB_TOKEN}" | docker login \
|
||||
--username gitlab-ci-token \
|
||||
--password-stdin \
|
||||
registry.gitlab.com
|
||||
- |
|
||||
echo "${DOCKER_PASSWORD}" | docker login \
|
||||
--username "${DOCKER_LOGIN}" \
|
||||
--password-stdin
|
||||
script:
|
||||
- |
|
||||
docker tag \
|
||||
"registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:${CI_COMMIT_SHA}" \
|
||||
"registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:cache"
|
||||
- docker push "registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:cache"
|
||||
- TAG="${CI_COMMIT_TAG#v}"
|
||||
- TAG="${TAG:-${CI_COMMIT_SHA:0:7}}"
|
||||
- |
|
||||
docker tag \
|
||||
"registry.gitlab.com/${CI_PROJECT_PATH}/${ADDON_ARCH}:${CI_COMMIT_SHA}" \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:${ADDON_ARCH}-${TAG}"
|
||||
- |
|
||||
docker push \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:${ADDON_ARCH}-${TAG}"
|
||||
tags:
|
||||
- deploy
|
||||
only:
|
||||
- master
|
||||
- /^v\d+\.\d+\.\d+(?:-(?:beta|rc)(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?)?$/
|
||||
except:
|
||||
- /^(?!master).+@/
|
||||
|
||||
# Generic manifest template
|
||||
.manifest: &manifest
|
||||
<<: *dind
|
||||
stage: manifest
|
||||
before_script:
|
||||
- mkdir -p ~/.docker
|
||||
- echo '{"experimental":"enabled"}' > ~/.docker/config.json
|
||||
- docker info
|
||||
- |
|
||||
echo "${DOCKER_PASSWORD}" | docker login \
|
||||
--username "${DOCKER_LOGIN}" \
|
||||
--password-stdin
|
||||
script:
|
||||
- TAG="${TAG#v}"
|
||||
- TAG="${TAG:-${CI_COMMIT_SHA:0:7}}"
|
||||
- REF="${CI_COMMIT_TAG#v}"
|
||||
- REF="${REF:-${CI_COMMIT_SHA:0:7}}"
|
||||
- |
|
||||
docker manifest create \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:${TAG}" \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:aarch64-${REF}" \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:amd64-${REF}" \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:armhf-${REF}" \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:i386-${REF}"
|
||||
- |
|
||||
docker manifest annotate \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:${TAG}" \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:aarch64-${REF}" \
|
||||
--os=linux \
|
||||
--arch=arm64 \
|
||||
--variant=v8
|
||||
- |
|
||||
docker manifest annotate \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:${TAG}" \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:amd64-${REF}" \
|
||||
--os=linux \
|
||||
--arch=amd64
|
||||
- |
|
||||
docker manifest annotate \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:${TAG}" \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:armhf-${REF}" \
|
||||
--os=linux \
|
||||
--arch=arm \
|
||||
--variant=v6
|
||||
- |
|
||||
docker manifest annotate \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:${TAG}" \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:i386-${REF}" \
|
||||
--os=linux \
|
||||
--arch=386
|
||||
- |
|
||||
docker manifest push \
|
||||
"${DOCKER_HUB_ORG}/${ADDON_SLUG}:${TAG}"
|
||||
tags:
|
||||
- manifest
|
||||
except:
|
||||
- /^(?!master).+@/
|
||||
|
||||
# Generic publish template
|
||||
.publish: &publish
|
||||
stage: publish
|
||||
image:
|
||||
name: hassioaddons/repository-updater:latest
|
||||
entrypoint: [""]
|
||||
script:
|
||||
- |
|
||||
repository-updater \
|
||||
--token "${GITHUB_TOKEN}" \
|
||||
--repository "${REPOSITORY}" \
|
||||
--addon "${ADDON_GITHUB_REPO}"
|
||||
tags:
|
||||
- publish
|
||||
except:
|
||||
- /^(?!master).+@/
|
||||
|
||||
# Preflight jobs
|
||||
hadolint:
|
||||
<<: *preflight
|
||||
image: hadolint/hadolint:latest-debian
|
||||
before_script:
|
||||
- hadolint --version
|
||||
script:
|
||||
- hadolint "${ADDON_TARGET}/Dockerfile"
|
||||
|
||||
shellcheck:
|
||||
<<: *preflight
|
||||
image:
|
||||
name: koalaman/shellcheck-alpine:stable
|
||||
entrypoint: [""]
|
||||
before_script:
|
||||
- shellcheck --version
|
||||
- apk --no-cache add grep
|
||||
- |
|
||||
find . -type f -print0 | \
|
||||
xargs -0 sed -i 's:#!/usr/bin/with-contenv bash:#!/bin/bash:g'
|
||||
script:
|
||||
- |
|
||||
for file in $(grep -IRl "#\!\(/usr/bin/env \|/bin/\)" --exclude-dir ".git" "${ADDON_TARGET}"); do
|
||||
if ! shellcheck $file; then
|
||||
export FAILED=1
|
||||
else
|
||||
echo "$file OK"
|
||||
fi
|
||||
done
|
||||
if [ "${FAILED}" = "1" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
yamllint:
|
||||
<<: *preflight
|
||||
image: sdesbure/yamllint
|
||||
before_script:
|
||||
- yamllint --version
|
||||
script:
|
||||
- yamllint .
|
||||
|
||||
jsonlint:
|
||||
<<: *preflight
|
||||
image: sahsu/docker-jsonlint
|
||||
before_script:
|
||||
- jsonlint --version || true
|
||||
script:
|
||||
- |
|
||||
for file in $(find . -type f -name "*.json"); do
|
||||
if ! jsonlint -q $file; then
|
||||
export FAILED=1
|
||||
else
|
||||
echo "$file OK"
|
||||
fi
|
||||
done
|
||||
if [ "${FAILED}" = "1" ]; then
|
||||
exit 1
|
||||
fi
|
||||
markdownlint:
|
||||
<<: *preflight
|
||||
image:
|
||||
name: ruby:alpine
|
||||
entrypoint: [""]
|
||||
before_script:
|
||||
- gem install mdl
|
||||
- mdl --version
|
||||
script:
|
||||
- mdl --style all --warnings .
|
||||
|
||||
# Build Jobs
|
||||
build:armhf:
|
||||
<<: *build
|
||||
variables:
|
||||
ADDON_ARCH: armhf
|
||||
FROM: hassioaddons/base-armhf:2.3.0
|
||||
tags:
|
||||
- build
|
||||
- armhf
|
||||
|
||||
build:aarch64:
|
||||
<<: *build
|
||||
variables:
|
||||
ADDON_ARCH: aarch64
|
||||
FROM: hassioaddons/base-aarch64:2.3.0
|
||||
tags:
|
||||
- build
|
||||
- aarch64
|
||||
|
||||
build:i386:
|
||||
<<: *build
|
||||
variables:
|
||||
ADDON_ARCH: i386
|
||||
FROM: hassioaddons/base-i386:2.3.0
|
||||
tags:
|
||||
- build
|
||||
- i386
|
||||
|
||||
build:amd64:
|
||||
<<: *build
|
||||
variables:
|
||||
ADDON_ARCH: amd64
|
||||
FROM: hassioaddons/base-amd64:2.3.0
|
||||
tags:
|
||||
- build
|
||||
- amd64
|
||||
|
||||
# Scan jobs
|
||||
clair:armhf:
|
||||
<<: *scan
|
||||
variables:
|
||||
ADDON_ARCH: armhf
|
||||
|
||||
clair:aarch64:
|
||||
<<: *scan
|
||||
variables:
|
||||
ADDON_ARCH: aarch64
|
||||
|
||||
clair:i386:
|
||||
<<: *scan
|
||||
variables:
|
||||
ADDON_ARCH: i386
|
||||
|
||||
clair:amd64:
|
||||
<<: *scan
|
||||
variables:
|
||||
ADDON_ARCH: amd64
|
||||
|
||||
# Deploy jobs
|
||||
deploy:armhf:
|
||||
<<: *deploy
|
||||
variables:
|
||||
ADDON_ARCH: armhf
|
||||
|
||||
deploy:aarch64:
|
||||
<<: *deploy
|
||||
variables:
|
||||
ADDON_ARCH: aarch64
|
||||
|
||||
deploy:i386:
|
||||
<<: *deploy
|
||||
variables:
|
||||
ADDON_ARCH: i386
|
||||
|
||||
deploy:amd64:
|
||||
<<: *deploy
|
||||
variables:
|
||||
ADDON_ARCH: amd64
|
||||
|
||||
# Manifest jobs
|
||||
manifest:sha:
|
||||
<<: *manifest
|
||||
only:
|
||||
- master
|
||||
|
||||
manifest:version:
|
||||
<<: *manifest
|
||||
variables:
|
||||
TAG: "${CI_COMMIT_TAG}"
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(?:-(?:beta|rc)(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?)?$/
|
||||
|
||||
manifest:stable:
|
||||
<<: *manifest
|
||||
variables:
|
||||
TAG: latest
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?$/
|
||||
|
||||
manifest:beta:
|
||||
<<: *manifest
|
||||
variables:
|
||||
TAG: beta
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(?:-(?:beta|rc)(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?)?$/
|
||||
|
||||
manifest:edge:
|
||||
<<: *manifest
|
||||
variables:
|
||||
TAG: edge
|
||||
only:
|
||||
- master
|
||||
|
||||
# Publish jobs
|
||||
publish:stable:
|
||||
<<: *publish
|
||||
variables:
|
||||
REPOSITORY: hassio-addons/repository
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?$/
|
||||
environment:
|
||||
name: stable
|
||||
|
||||
publish:beta:
|
||||
<<: *publish
|
||||
variables:
|
||||
REPOSITORY: hassio-addons/repository-beta
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(?:-(?:beta|rc)(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?)?$/
|
||||
environment:
|
||||
name: beta
|
||||
|
||||
publish:edge:
|
||||
<<: *publish
|
||||
variables:
|
||||
REPOSITORY: hassio-addons/repository-edge
|
||||
only:
|
||||
- master
|
||||
environment:
|
||||
name: edge
|
1
.mdlrc
Normal file
1
.mdlrc
Normal file
|
@ -0,0 +1 @@
|
|||
rules "~MD024"
|
64
.yamllint
Normal file
64
.yamllint
Normal file
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
rules:
|
||||
braces:
|
||||
level: error
|
||||
min-spaces-inside: 0
|
||||
max-spaces-inside: 1
|
||||
min-spaces-inside-empty: -1
|
||||
max-spaces-inside-empty: -1
|
||||
brackets:
|
||||
level: error
|
||||
min-spaces-inside: 0
|
||||
max-spaces-inside: 0
|
||||
min-spaces-inside-empty: -1
|
||||
max-spaces-inside-empty: -1
|
||||
colons:
|
||||
level: error
|
||||
max-spaces-before: 0
|
||||
max-spaces-after: 1
|
||||
commas:
|
||||
level: error
|
||||
max-spaces-before: 0
|
||||
min-spaces-after: 1
|
||||
max-spaces-after: 1
|
||||
comments:
|
||||
level: error
|
||||
require-starting-space: true
|
||||
min-spaces-from-content: 2
|
||||
comments-indentation:
|
||||
level: error
|
||||
document-end:
|
||||
level: error
|
||||
present: false
|
||||
document-start:
|
||||
level: error
|
||||
present: true
|
||||
empty-lines:
|
||||
level: error
|
||||
max: 1
|
||||
max-start: 0
|
||||
max-end: 1
|
||||
hyphens:
|
||||
level: error
|
||||
max-spaces-after: 1
|
||||
indentation:
|
||||
level: error
|
||||
spaces: 2
|
||||
indent-sequences: true
|
||||
check-multi-line-strings: false
|
||||
key-duplicates:
|
||||
level: error
|
||||
line-length:
|
||||
level: warning
|
||||
max: 120
|
||||
allow-non-breakable-words: true
|
||||
allow-non-breakable-inline-mappings: true
|
||||
new-line-at-end-of-file:
|
||||
level: error
|
||||
new-lines:
|
||||
level: error
|
||||
type: unix
|
||||
trailing-spaces:
|
||||
level: error
|
||||
truthy:
|
||||
level: error
|
74
CODE_OF_CONDUCT.md
Normal file
74
CODE_OF_CONDUCT.md
Normal file
|
@ -0,0 +1,74 @@
|
|||
# Code of conduct
|
||||
|
||||
## Our pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention
|
||||
or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or
|
||||
electronic address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate
|
||||
in a professional setting
|
||||
|
||||
## Our responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project lead at frenck@addons.community. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project lead is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
29
CONTRIBUTING.md
Normal file
29
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Contributing
|
||||
|
||||
When contributing to this repository, please first discuss the change you wish
|
||||
to make via issue, email, or any other method with the owners of this repository
|
||||
before making a change.
|
||||
|
||||
Please note we have a code of conduct, please follow it in all your interactions
|
||||
with the project.
|
||||
|
||||
## Issues and feature requests
|
||||
|
||||
You've found a bug in the source code, a mistake in the documentation or maybe
|
||||
you'd like a new feature? You can help us by submitting an issue to our
|
||||
[GitHub Repository][github]. Before you create an issue, make sure you search
|
||||
the archive, maybe your question was already answered.
|
||||
|
||||
Even better: You could submit a pull request with a fix / new feature!
|
||||
|
||||
## Pull request process
|
||||
|
||||
1. Search our repository for open or closed [pull requests][prs] that relates
|
||||
to your submission. You don't want to duplicate effort.
|
||||
|
||||
1. You may merge the pull request in once you have the sign-off of two other
|
||||
developers, or if you do not have permission to do that, you may request
|
||||
the second reviewer to merge it for you.
|
||||
|
||||
[github]: https://github.com/hassio-addons/addon-lutron-cert/issues
|
||||
[prs]: https://github.com/hassio-addons/addon-lutron-cert/pulls
|
21
LICENSE.md
Normal file
21
LICENSE.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
# MIT License
|
||||
|
||||
Copyright (c) 2018 Dale Higgs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
219
README.md
Normal file
219
README.md
Normal file
|
@ -0,0 +1,219 @@
|
|||
# Community Hass.io Add-ons: Lutron Certificate
|
||||
|
||||
[![GitHub Release][releases-shield]][releases]
|
||||
![Project Stage][project-stage-shield]
|
||||
[![License][license-shield]](LICENSE.md)
|
||||
|
||||
[![GitLab CI][gitlabci-shield]][gitlabci]
|
||||
![Project Maintenance][maintenance-shield]
|
||||
[![GitHub Activity][commits-shield]][commits]
|
||||
|
||||
[![Bountysource][bountysource-shield]][bountysource]
|
||||
[![Discord][discord-shield]][discord]
|
||||
[![Community Forum][forum-shield]][forum]
|
||||
|
||||
[![Buy me a coffee][buymeacoffee-shield]][buymeacoffee]
|
||||
|
||||
A simple utility to generate signed certificate files to allow local control of
|
||||
a Lutron Caseta smart bridge.
|
||||
|
||||
## About
|
||||
|
||||
This add-on will guide you through the necessary steps to create signed
|
||||
certificate files necessary to control your Lutron Caseta smart bridge with
|
||||
Home Assistant.
|
||||
|
||||
Three files will be created during successful execution of the wizard:
|
||||
|
||||
- `/ssl/lutron/caseta.key`: the private key file used to generate the
|
||||
certificate.
|
||||
- `/ssl/lutron/caseta.crt`: the signed certificate file used to connect to
|
||||
the Lutron Caseta bridge.
|
||||
- `/ssl/lutron/caseta-bridge.crt`: the certificate authority file that is
|
||||
downloaded from the Lutron Caseta bridge.
|
||||
|
||||
Be sure to add Lutron Caseta to your `configuration.yaml` after starting the
|
||||
add-on:
|
||||
|
||||
```yaml
|
||||
lutron_caseta:
|
||||
host: 192.168.1.100
|
||||
keyfile: /ssl/lutron/caseta.key
|
||||
certfile: /ssl/lutron/caseta.crt
|
||||
ca_certs: /ssl/lutron/caseta-bridge.crt
|
||||
```
|
||||
|
||||
For more information on how to configure Lutron Caseta in Home Assistant see
|
||||
the [Lutron Caseta documentation][lutron-caseta-docs].
|
||||
|
||||
## Installation
|
||||
|
||||
The installation of this add-on is pretty straightforward and not different in
|
||||
comparison to installing any other Hass.io add-on.
|
||||
|
||||
1. [Add our Hass.io add-ons repository][repository] to your Hass.io instance.
|
||||
1. Install the "Lutron Certificate" add-on.
|
||||
1. Start the "Lutron Certificate" add-on.
|
||||
1. Check the logs of the "Lutron Certificate" add-on to see if everything went well.
|
||||
1. Open the web UI for the "Lutron Certificate" add-on and follow the steps.
|
||||
1. Configure [Lutron Caseta][lutron-caseta-docs] in your `configuration.yaml` file.
|
||||
|
||||
**NOTE**: Do not add this repository to Hass.io, please use:
|
||||
`https://github.com/hassio-addons/repository`.
|
||||
|
||||
## Docker status
|
||||
|
||||
![Supports armhf Architecture][armhf-shield]
|
||||
![Supports aarch64 Architecture][aarch64-shield]
|
||||
![Supports amd64 Architecture][amd64-shield]
|
||||
![Supports i386 Architecture][i386-shield]
|
||||
|
||||
[![Docker Version][version-shield]][microbadger]
|
||||
[![Docker Layers][layers-shield]][microbadger]
|
||||
[![Docker Pulls][pulls-shield]][dockerhub]
|
||||
|
||||
## Configuration
|
||||
|
||||
Even though this add-on is just a basic add-on, it does come with some
|
||||
configuration options to play around with.
|
||||
|
||||
**Note**: _Remember to restart the add-on when the configuration is changed._
|
||||
|
||||
Lutron Certificate add-on configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"log_level": "info"
|
||||
}
|
||||
```
|
||||
|
||||
### Option: `log_level`
|
||||
|
||||
The `log_level` option controls the level of log output by the add-on and can
|
||||
be changed to be more or less verbose, which might be useful when you are
|
||||
dealing with an unknown issue. Possible values are:
|
||||
|
||||
- `trace`: Show every detail, like all called internal functions.
|
||||
- `debug`: Shows detailed debug information.
|
||||
- `info`: Normal (usually) interesting events.
|
||||
- `warning`: Exceptional occurrences that are not errors.
|
||||
- `error`: Runtime errors that do not require immediate action.
|
||||
- `fatal`: Something went terribly wrong. Add-on becomes unusable.
|
||||
|
||||
Please note that each level automatically includes log messages from a
|
||||
more severe level, e.g., `debug` also shows `info` messages. By default,
|
||||
the `log_level` is set to `info`, which is the recommended setting unless
|
||||
you are troubleshooting.
|
||||
|
||||
## Changelog & Releases
|
||||
|
||||
This repository keeps a change log using [GitHub's releases][releases]
|
||||
functionality. The format of the log is based on
|
||||
[Keep a Changelog][keepchangelog].
|
||||
|
||||
Releases are based on [Semantic Versioning][semver], and use the format
|
||||
of ``MAJOR.MINOR.PATCH``. In a @xxxxshell, the version will be incremented
|
||||
based on the following:
|
||||
|
||||
- ``MAJOR``: Incompatible or major changes.
|
||||
- ``MINOR``: Backwards-compatible new features and enhancements.
|
||||
- ``PATCH``: Backwards-compatible bugfixes and package updates.
|
||||
|
||||
## Support
|
||||
|
||||
Got questions?
|
||||
|
||||
You have several options to get them answered:
|
||||
|
||||
- The [Community Hass.io Add-ons Discord chat server][discord] for add-on
|
||||
support and feature requests.
|
||||
- The [Home Assistant Discord chat server][discord-ha] for general Home
|
||||
Assistant discussions and questions.
|
||||
- The Home Assistant [Community Forum][forum].
|
||||
- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit]
|
||||
|
||||
You could also [open an issue here][issue] GitHub.
|
||||
|
||||
## Contributing
|
||||
|
||||
This is an active open-source project. We are always open to people who want to
|
||||
use the code or contribute to it.
|
||||
|
||||
We have set up a separate document containing our
|
||||
[contribution guidelines](CONTRIBUTING.md).
|
||||
|
||||
Thank you for being involved! :heart_eyes:
|
||||
|
||||
## Authors & contributors
|
||||
|
||||
The original setup of this repository is by [Dale Higgs][dale3h].
|
||||
|
||||
For a full list of all authors and contributors,
|
||||
check [the contributor's page][contributors].
|
||||
|
||||
## We have got some Hass.io add-ons for you
|
||||
|
||||
Want some more functionality to your Hass.io Home Assistant instance?
|
||||
|
||||
We have created multiple add-ons for Hass.io. For a full list, check out
|
||||
our [GitHub Repository][repository].
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Dale Higgs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
|
||||
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
|
||||
[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
|
||||
[bountysource-shield]: https://img.shields.io/bountysource/team/hassio-addons/activity.svg
|
||||
[bountysource]: https://www.bountysource.com/teams/hassio-addons/issues
|
||||
[buymeacoffee-shield]: https://www.buymeacoffee.com/assets/img/guidelines/download-assets-sm-2.svg
|
||||
[buymeacoffee]: https://www.buymeacoffee.com/dale3h
|
||||
[commits-shield]: https://img.shields.io/github/commit-activity/y/hassio-addons/addon-lutron-cert.svg
|
||||
[commits]: https://github.com/hassio-addons/addon-lutron-cert/commits/master
|
||||
[contributors]: https://github.com/hassio-addons/addon-lutron-cert/graphs/contributors
|
||||
[dale3h]: https://github.com/dale3h
|
||||
[discord-ha]: https://discord.gg/c5DvZ4e
|
||||
[discord-shield]: https://img.shields.io/discord/478094546522079232.svg
|
||||
[discord]: https://discord.me/hassioaddons
|
||||
[dockerhub]: https://hub.docker.com/r/hassioaddons/lutron-cert
|
||||
[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg
|
||||
[forum]: https://community.home-assistant.io/t/community-hass-io-add-on-lutron-certificate/70317
|
||||
[gitlabci-shield]: https://gitlab.com/hassio-addons/addon-lutron-cert/badges/master/pipeline.svg
|
||||
[gitlabci]: https://gitlab.com/hassio-addons/addon-lutron-cert/pipelines
|
||||
[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg
|
||||
[issue]: https://github.com/hassio-addons/addon-lutron-cert/issues
|
||||
[keepchangelog]: https://keepachangelog.com/en/1.0.0/
|
||||
[layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/lutron-cert.svg
|
||||
[license-shield]: https://img.shields.io/github/license/hassio-addons/addon-lutron-cert.svg
|
||||
[lutron-caseta-docs]: https://www.home-assistant.io/components/lutron_caseta/
|
||||
[maintenance-shield]: https://img.shields.io/maintenance/yes/2018.svg
|
||||
[microbadger]: https://microbadger.com/images/hassioaddons/lutron-cert
|
||||
[project-stage-shield]: https://img.shields.io/badge/project%20stage-experimental-yellow.svg
|
||||
[pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/lutron-cert.svg
|
||||
[reddit]: https://reddit.com/r/homeassistant
|
||||
[releases-shield]: https://img.shields.io/github/release/hassio-addons/addon-lutron-cert.svg
|
||||
[releases]: https://github.com/hassio-addons/addon-lutron-cert/releases
|
||||
[repository]: https://github.com/hassio-addons/repository
|
||||
[semver]: https://semver.org/spec/v2.0.0.html
|
||||
[version-shield]: https://images.microbadger.com/badges/version/hassioaddons/lutron-cert.svg
|
94
lutron-cert/.README.j2
Normal file
94
lutron-cert/.README.j2
Normal file
|
@ -0,0 +1,94 @@
|
|||
# Community Hass.io Add-ons: Lutron Certificate
|
||||
|
||||
[![Release][release-shield]][release] ![Project Stage][project-stage-shield] ![Project Maintenance][maintenance-shield]
|
||||
|
||||
[![Discord][discord-shield]][discord] [![Community Forum][forum-shield]][forum]
|
||||
|
||||
[![Buy me a coffee][buymeacoffee-shield]][buymeacoffee]
|
||||
|
||||
A simple utility to generate signed certificate files to allow local control of
|
||||
a Lutron Caseta smart bridge.
|
||||
|
||||
## About
|
||||
|
||||
This add-on will guide you through the necessary steps to create signed
|
||||
certificate files necessary to control your Lutron Caseta smart bridge with
|
||||
Home Assistant.
|
||||
|
||||
Three files will be created during successful execution of the wizard:
|
||||
|
||||
- `/ssl/lutron/caseta.key`: the private key file used to generate the
|
||||
certificate.
|
||||
- `/ssl/lutron/caseta.crt`: the signed certificate file used to connect to
|
||||
the Lutron Caseta bridge.
|
||||
- `/ssl/lutron/caseta-bridge.crt`: the certificate authority file that is
|
||||
downloaded from the Lutron Caseta bridge.
|
||||
|
||||
Be sure to add Lutron Caseta to your `configuration.yaml` after starting the
|
||||
add-on:
|
||||
|
||||
```yaml
|
||||
lutron_caseta:
|
||||
host: 192.168.1.100
|
||||
keyfile: /ssl/lutron/caseta.key
|
||||
certfile: /ssl/lutron/caseta.crt
|
||||
ca_certs: /ssl/lutron/caseta-bridge.crt
|
||||
```
|
||||
|
||||
For more information on how to configure Lutron Caseta in Home Assistant see
|
||||
the [Lutron Caseta documentation][lutron-caseta-docs].
|
||||
|
||||
[Click here for the full documentation][docs]
|
||||
|
||||
{% if channel == "edge" %}
|
||||
## WARNING! THIS IS AN EDGE VERSION!
|
||||
|
||||
This Hass.io Add-ons repository contains edge builds of add-ons. Edge builds
|
||||
add-ons are based upon the latest development version.
|
||||
|
||||
- They may not work at all.
|
||||
- They might stop working at any time.
|
||||
- They could have a negative impact on your system.
|
||||
|
||||
This repository was created for:
|
||||
|
||||
- Anybody willing to test.
|
||||
- Anybody interested in trying out upcoming add-ons or add-on features.
|
||||
- Developers.
|
||||
|
||||
If you are more interested in stable releases of our add-ons:
|
||||
|
||||
<https://github.com/hassio-addons/repository>
|
||||
|
||||
{% endif %}
|
||||
{% if channel == "beta" %}
|
||||
## WARNING! THIS IS A BETA VERSION!
|
||||
|
||||
This Hass.io Add-ons repository contains beta releases of add-ons.
|
||||
|
||||
- They might stop working at any time.
|
||||
- They could have a negative impact on your system.
|
||||
|
||||
This repository was created for:
|
||||
|
||||
- Anybody willing to test.
|
||||
- Anybody interested in trying out upcoming add-ons or add-on features.
|
||||
|
||||
If you are more interested in stable releases of our add-ons:
|
||||
|
||||
<https://github.com/hassio-addons/repository>
|
||||
|
||||
{% endif %}
|
||||
|
||||
[buymeacoffee-shield]: https://www.buymeacoffee.com/assets/img/guidelines/download-assets-sm-2.svg
|
||||
[buymeacoffee]: https://www.buymeacoffee.com/dale3h
|
||||
[discord-shield]: https://img.shields.io/discord/478094546522079232.svg
|
||||
[discord]: https://discord.me/hassioaddons
|
||||
[docs]: {{ repo }}/blob/{{ version }}/README.md
|
||||
[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg
|
||||
[forum]: https://community.home-assistant.io/t/community-hass-io-add-on-lutron-certificate/70317
|
||||
[lutron-caseta-docs]: https://www.home-assistant.io/components/lutron_caseta/
|
||||
[maintenance-shield]: https://img.shields.io/maintenance/yes/2018.svg
|
||||
[project-stage-shield]: https://img.shields.io/badge/project%20stage-experimental-yellow.svg
|
||||
[release-shield]: https://img.shields.io/badge/version-{{ version }}-blue.svg
|
||||
[release]: {{ repo }}/tree/{{ version }}
|
42
lutron-cert/Dockerfile
Normal file
42
lutron-cert/Dockerfile
Normal file
|
@ -0,0 +1,42 @@
|
|||
ARG BUILD_FROM=hassioaddons/base:2.3.0
|
||||
# hadolint ignore=DL3006
|
||||
FROM ${BUILD_FROM}
|
||||
|
||||
# Copy root filesystem
|
||||
COPY rootfs /
|
||||
|
||||
# Setup base
|
||||
RUN \
|
||||
apk add --no-cache \
|
||||
python3=3.6.6-r0 \
|
||||
py3-cryptography=2.1.4-r1 \
|
||||
dbus=1.10.24-r1 \
|
||||
\
|
||||
&& python3 -m ensurepip \
|
||||
&& rm -r /usr/lib/python*/ensurepip \
|
||||
\
|
||||
&& pip3 install "requests==2.19.1" "Flask==1.0.2"
|
||||
|
||||
# Build arugments
|
||||
ARG BUILD_ARCH
|
||||
ARG BUILD_DATE
|
||||
ARG BUILD_REF
|
||||
ARG BUILD_VERSION
|
||||
|
||||
# Labels
|
||||
LABEL \
|
||||
io.hass.name="Lutron Certificate" \
|
||||
io.hass.description="Generate certificate to control Lutron Caseta bridge locally" \
|
||||
io.hass.arch="${BUILD_ARCH}" \
|
||||
io.hass.type="addon" \
|
||||
io.hass.version=${BUILD_VERSION} \
|
||||
maintainer="Dale Higgs <dale3h@addons.community>" \
|
||||
org.label-schema.description="Generate certificate to control Lutron Caseta bridge locally" \
|
||||
org.label-schema.build-date=${BUILD_DATE} \
|
||||
org.label-schema.name="Lutron Certificate" \
|
||||
org.label-schema.schema-version="1.0" \
|
||||
org.label-schema.url="https://community.home-assistant.io/" \
|
||||
org.label-schema.usage="https://github.com/hassio-addons/addon-lutron-cert/tree/master/README.md" \
|
||||
org.label-schema.vcs-ref=${BUILD_REF} \
|
||||
org.label-schema.vcs-url="https://github.com/hassio-addons/addon-lutron-cert" \
|
||||
org.label-schema.vendor="Community Hass.io Addons"
|
10
lutron-cert/build.json
Normal file
10
lutron-cert/build.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"squash": false,
|
||||
"build_from": {
|
||||
"aarch64": "hassioaddons/base-aarch64:2.3.0",
|
||||
"amd64": "hassioaddons/base-amd64:2.3.0",
|
||||
"armhf": "hassioaddons/base-armhf:2.3.0",
|
||||
"i386": "hassioaddons/base-i386:2.3.0"
|
||||
},
|
||||
"args": {}
|
||||
}
|
35
lutron-cert/config.json
Normal file
35
lutron-cert/config.json
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "Lutron Certificate",
|
||||
"version": "dev",
|
||||
"slug": "lutron-cert",
|
||||
"description": "Generate certificate to control Lutron Caseta bridge locally",
|
||||
"url": "https://github.com/hassio-addons/addon-lutron-cert",
|
||||
"startup": "once",
|
||||
"webui": "http://[HOST]:[PORT:5817]",
|
||||
"arch": [
|
||||
"aarch64",
|
||||
"amd64",
|
||||
"armhf",
|
||||
"i386"
|
||||
],
|
||||
"boot": "manual",
|
||||
"hassio_role": "default",
|
||||
"hassio_api": true,
|
||||
"homeassistant_api": true,
|
||||
"ports": {
|
||||
"5817/tcp": 5817
|
||||
},
|
||||
"map": [
|
||||
"ssl:rw",
|
||||
"addons"
|
||||
],
|
||||
"options": {
|
||||
"log_level": "info"
|
||||
},
|
||||
"schema": {
|
||||
"log_level": "match(^(trace|debug|info|notice|warning|error|fatal)$)"
|
||||
},
|
||||
"environment": {
|
||||
"LOG_FORMAT": "{LEVEL}: {MESSAGE}"
|
||||
}
|
||||
}
|
BIN
lutron-cert/icon.png
Normal file
BIN
lutron-cert/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
BIN
lutron-cert/logo.png
Normal file
BIN
lutron-cert/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
288
lutron-cert/rootfs/etc/lutron/cert_server.py
Normal file
288
lutron-cert/rootfs/etc/lutron/cert_server.py
Normal file
|
@ -0,0 +1,288 @@
|
|||
"""
|
||||
Server to get Lutron Caseta certificate.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
import socket
|
||||
import ssl
|
||||
|
||||
from flask import (Flask, flash, redirect, render_template, request, session,
|
||||
url_for)
|
||||
|
||||
from cryptography import x509
|
||||
from cryptography.x509.oid import NameOID
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
||||
|
||||
from urllib.parse import urlencode
|
||||
|
||||
################################################################################
|
||||
|
||||
SSL_PATH = "/ssl/lutron"
|
||||
KEY_FILE = "%s/caseta.key" % SSL_PATH
|
||||
CERT_FILE = "%s/caseta.crt" % SSL_PATH
|
||||
CA_FILE = "%s/caseta-bridge.crt" % SSL_PATH
|
||||
|
||||
################################################################################
|
||||
|
||||
LOGIN_SERVER = "device-login.lutron.com"
|
||||
APP_CLIENT_ID = ("e001a4471eb6152b7b3f35e549905fd8589dfcf57eb680b6fb37f20878c"
|
||||
"28e5a")
|
||||
APP_CLIENT_SECRET = ("b07fee362538d6df3b129dc3026a72d27e1005a3d1e5839eed5ed18"
|
||||
"c63a89b27")
|
||||
APP_OAUTH_REDIRECT_PAGE = "lutron_app_oauth_redirect"
|
||||
CERT_SUBJECT = x509.Name([
|
||||
x509.NameAttribute(NameOID.COUNTRY_NAME, "US"),
|
||||
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Pennsylvania"),
|
||||
x509.NameAttribute(NameOID.LOCALITY_NAME, "Coopersburg"),
|
||||
x509.NameAttribute(NameOID.ORGANIZATION_NAME,
|
||||
"Lutron Electronics Co., Inc."),
|
||||
x509.NameAttribute(NameOID.COMMON_NAME, "Lutron Caseta App")
|
||||
])
|
||||
|
||||
BASE_URL = "https://%s/" % LOGIN_SERVER
|
||||
REDIRECT_URI = "https://%s/%s" % (LOGIN_SERVER, APP_OAUTH_REDIRECT_PAGE)
|
||||
|
||||
AUTHORIZE_URL = ("%soauth/authorize?%s" % (BASE_URL,
|
||||
urlencode({
|
||||
"client_id": APP_CLIENT_ID,
|
||||
"redirect_uri": REDIRECT_URI,
|
||||
"response_type": "code"
|
||||
})))
|
||||
|
||||
################################################################################
|
||||
|
||||
def ensure_path():
|
||||
"""Create SSL path if it does not exist."""
|
||||
if not os.path.isdir(SSL_PATH):
|
||||
os.makedirs(SSL_PATH, exist_ok=True)
|
||||
|
||||
################################################################################
|
||||
|
||||
def get_private_key():
|
||||
"""Get the private key file used to generate the certificate."""
|
||||
try:
|
||||
with open(KEY_FILE, 'rb') as f:
|
||||
private_key = load_pem_private_key(f.read(), None,
|
||||
default_backend())
|
||||
except FileNotFoundError:
|
||||
private_key = rsa.generate_private_key(public_exponent=65537,
|
||||
key_size=2048,
|
||||
backend=default_backend())
|
||||
|
||||
ensure_path()
|
||||
with open(KEY_FILE, 'wb') as f:
|
||||
f.write(private_key.private_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=serialization.NoEncryption()
|
||||
))
|
||||
return private_key
|
||||
|
||||
################################################################################
|
||||
|
||||
def get_certificate(oauth_code):
|
||||
"""Get the certificate file used to generate the CA file."""
|
||||
try:
|
||||
with open(CERT_FILE, 'rb') as f:
|
||||
certificate = x509.load_pem_x509_certificate(f.read(),
|
||||
default_backend())
|
||||
except FileNotFoundError:
|
||||
private_key = get_private_key()
|
||||
|
||||
csr = (x509.CertificateSigningRequestBuilder()
|
||||
.subject_name(CERT_SUBJECT)
|
||||
.sign(private_key, hashes.SHA256(), default_backend()))
|
||||
|
||||
if not oauth_code:
|
||||
raise ValueError("Received invalid OAuth code. Please try again.")
|
||||
|
||||
token = requests.post("%soauth/token" % BASE_URL, data={
|
||||
'code': oauth_code,
|
||||
'client_id': APP_CLIENT_ID,
|
||||
'client_secret': APP_CLIENT_SECRET,
|
||||
'redirect_uri': REDIRECT_URI,
|
||||
'grant_type': 'authorization_code'}).json()
|
||||
|
||||
if 'error' in token:
|
||||
raise ValueError(token['error_description'])
|
||||
|
||||
if token.get('token_type') != 'bearer':
|
||||
raise ValueError("Received invalid token %s. Try generating a "
|
||||
"new code (one time use)." % token)
|
||||
|
||||
access_token = token['access_token']
|
||||
|
||||
pairing_request_content = {
|
||||
'remote_signs_app_certificate_signing_request':
|
||||
csr.public_bytes(serialization.Encoding.PEM).decode('ASCII')
|
||||
}
|
||||
|
||||
pairing_response = requests.post(
|
||||
"%sapi/v1/remotepairing/application/user" % BASE_URL,
|
||||
json=pairing_request_content,
|
||||
headers={
|
||||
'X-DeviceType': 'Caseta,RA2Select',
|
||||
'Authorization': 'Bearer %s' % access_token
|
||||
}
|
||||
).json()
|
||||
|
||||
app_cert = pairing_response['remote_signs_app_certificate']
|
||||
remote_cert = pairing_response['local_signs_remote_certificate']
|
||||
|
||||
ensure_path()
|
||||
with open(CERT_FILE, 'wb') as f:
|
||||
f.write(app_cert.encode('ASCII'))
|
||||
f.write(remote_cert.encode('ASCII'))
|
||||
|
||||
################################################################################
|
||||
|
||||
def get_ca_cert(server_addr):
|
||||
raw_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
ssl_socket = ssl.wrap_socket(raw_socket, keyfile=KEY_FILE,
|
||||
certfile=CERT_FILE,
|
||||
ssl_version=ssl.PROTOCOL_TLSv1_2)
|
||||
|
||||
ssl_socket.connect((server_addr, 8081))
|
||||
|
||||
ca_der = ssl_socket.getpeercert(True)
|
||||
ca_cert = x509.load_der_x509_certificate(ca_der, default_backend())
|
||||
|
||||
ensure_path()
|
||||
with open(CA_FILE, 'wb') as f:
|
||||
f.write(ca_cert.public_bytes(serialization.Encoding.PEM))
|
||||
|
||||
ssl_socket.send(("%s\r\n" % json.dumps({
|
||||
'CommuniqueType': 'ReadRequest',
|
||||
'Header': {'Url': '/server/1/status/ping'}
|
||||
})).encode('UTF-8'))
|
||||
|
||||
while True:
|
||||
buffer = b''
|
||||
while not buffer.endswith(b'\r\n'):
|
||||
buffer += ssl_socket.read()
|
||||
|
||||
leap_response = json.loads(buffer.decode('UTF-8'))
|
||||
if leap_response['CommuniqueType'] == 'ReadResponse':
|
||||
break
|
||||
|
||||
ssl_socket.close()
|
||||
|
||||
return leap_response
|
||||
|
||||
################################################################################
|
||||
|
||||
# Flask webserver
|
||||
app = Flask(__name__)
|
||||
|
||||
# Flask app config
|
||||
with open('/var/lib/dbus/machine-id', 'r') as f:
|
||||
app.secret_key = f.read()
|
||||
|
||||
@app.route('/', methods=['GET', 'POST'])
|
||||
def wizard():
|
||||
"""Show the current step based on progress."""
|
||||
if os.path.isfile(CA_FILE):
|
||||
leap_version = session.get('leap_version')
|
||||
if leap_version is not None:
|
||||
flash("Successfully connected to bridge, running LEAP Server"
|
||||
"version %s" % leap_version, 'success')
|
||||
|
||||
return render_template(
|
||||
'success.html',
|
||||
server_addr=session.get('server_addr', '192.168.1.100'),
|
||||
ssl_path=SSL_PATH,
|
||||
ssl_files={'key_file': KEY_FILE,
|
||||
'cert_file': CERT_FILE,
|
||||
'ca_file': CA_FILE})
|
||||
|
||||
if os.path.isfile(CERT_FILE):
|
||||
return render_template(
|
||||
'bridge.html',
|
||||
server_addr=session.get('server_addr', ''))
|
||||
|
||||
return render_template('login.html', authorize_url=AUTHORIZE_URL)
|
||||
|
||||
@app.route('/reset')
|
||||
def reset():
|
||||
"""Delete certificate files and session data."""
|
||||
try:
|
||||
# Remove certificate files
|
||||
os.remove(KEY_FILE)
|
||||
os.remove(CERT_FILE)
|
||||
os.remove(CA_FILE)
|
||||
|
||||
# Clear session data
|
||||
session.clear()
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
# Alert user that session has been reset
|
||||
flash("The certificate files have been deleted and your session "
|
||||
"has been reset.", 'warning')
|
||||
|
||||
return redirect(url_for('wizard'))
|
||||
|
||||
@app.route('/debug')
|
||||
def debug():
|
||||
"""Output session data for debugging."""
|
||||
values = {k: v for (k, v) in session.items()}
|
||||
values.update({
|
||||
'key_file': (KEY_FILE, os.path.isfile(KEY_FILE)),
|
||||
'cert_file': (CERT_FILE, os.path.isfile(CERT_FILE)),
|
||||
'ca_file': (CA_FILE, os.path.isfile(CA_FILE)),
|
||||
})
|
||||
return app.response_class(response=json.dumps(values),
|
||||
status=200,
|
||||
mimetype='application/json')
|
||||
|
||||
################################################################################
|
||||
|
||||
@app.route('/process_url', methods=['POST'])
|
||||
def process_url():
|
||||
"""Process the redirect URL."""
|
||||
redirected_url = request.form.get('redirected_url')
|
||||
oauth_code = re.sub(r'^(.*?code=){0,1}([0-9a-f]*)\s*$', r'\2',
|
||||
redirected_url)
|
||||
|
||||
try:
|
||||
get_certificate(oauth_code)
|
||||
except ValueError as err:
|
||||
flash(str(err), 'danger')
|
||||
|
||||
return redirect(url_for('wizard'))
|
||||
|
||||
@app.route('/process_addr', methods=['POST'])
|
||||
def process_addr():
|
||||
"""Process the bridge IP address/hostname."""
|
||||
server_addr = request.form.get('server_addr')
|
||||
session['server_addr'] = server_addr
|
||||
|
||||
try:
|
||||
leap_response = get_ca_cert(server_addr)
|
||||
session['leap_version'] = leap_response['Body'] \
|
||||
['PingResponse']['LEAPVersion']
|
||||
except ConnectionRefusedError:
|
||||
flash("A connection to %s could not be established. Please check "
|
||||
"the IP address and try again." % server_addr, 'danger')
|
||||
|
||||
return redirect(url_for('wizard'))
|
||||
|
||||
################################################################################
|
||||
|
||||
def main():
|
||||
"""Main program routine."""
|
||||
# Make sure SSL_PATH exists
|
||||
ensure_path()
|
||||
|
||||
# Start flask server
|
||||
app.run(host='0.0.0.0', port=5817)
|
||||
|
||||
################################################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
6
lutron-cert/rootfs/etc/lutron/static/css/bootstrap.min.css
vendored
Normal file
6
lutron-cert/rootfs/etc/lutron/static/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
2
lutron-cert/rootfs/etc/lutron/static/css/highlight.min.css
vendored
Normal file
2
lutron-cert/rootfs/etc/lutron/static/css/highlight.min.css
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/*! Visual Studio-like style based on original C# coloring by Jason Diamond <jason@diamond.name> */
|
||||
.hljs{display:block;overflow-x:auto;padding:.5em;background:#fff;color:#000}.hljs-comment,.hljs-quote,.hljs-variable{color:green}.hljs-built_in,.hljs-keyword,.hljs-name,.hljs-selector-tag,.hljs-tag{color:#00f}.hljs-addition,.hljs-attribute,.hljs-literal,.hljs-section,.hljs-string,.hljs-template-tag,.hljs-template-variable,.hljs-title,.hljs-type{color:#a31515}.hljs-deletion,.hljs-meta,.hljs-selector-attr,.hljs-selector-pseudo{color:#2b91af}.hljs-doctag{color:gray}.hljs-attr{color:red}.hljs-bullet,.hljs-link,.hljs-symbol{color:#00b0e8}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}
|
6
lutron-cert/rootfs/etc/lutron/static/js/bootstrap.min.js
vendored
Normal file
6
lutron-cert/rootfs/etc/lutron/static/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
lutron-cert/rootfs/etc/lutron/static/js/highlight.min.js
vendored
Normal file
2
lutron-cert/rootfs/etc/lutron/static/js/highlight.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
lutron-cert/rootfs/etc/lutron/static/js/jquery.slim.min.js
vendored
Normal file
2
lutron-cert/rootfs/etc/lutron/static/js/jquery.slim.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
lutron-cert/rootfs/etc/lutron/static/js/popper.min.js
vendored
Normal file
4
lutron-cert/rootfs/etc/lutron/static/js/popper.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
47
lutron-cert/rootfs/etc/lutron/templates/base.html
Normal file
47
lutron-cert/rootfs/etc/lutron/templates/base.html
Normal file
|
@ -0,0 +1,47 @@
|
|||
<!doctype html>
|
||||
<title>{% block title %}{% endblock %} - Lutron Caseta</title>
|
||||
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/highlight.min.css') }}">
|
||||
|
||||
<body class="bg-dark">
|
||||
<section class="wrapper pt-5">
|
||||
<div class="container bg-light p-4 mx-auto text-center" style="max-width: 700px;">
|
||||
<header>
|
||||
{% block header %}{% endblock %}
|
||||
</header>
|
||||
|
||||
{% for category, message in get_flashed_messages(with_categories=True) %}
|
||||
<div class="alert alert-{{ category }}" role="alert">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container text-center">
|
||||
<small class="text-muted">
|
||||
To start over at any time, <a href="{{ url_for('reset') }}" class="reset-link text-danger">click here</a>.
|
||||
</small>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="{{ url_for('static', filename='js/jquery.slim.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/popper.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/highlight.min.js') }}"></script>
|
||||
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
<script>
|
||||
(function() {
|
||||
$('.reset-link').click(function() {
|
||||
return confirm("WARNING: THIS WILL DELETE THE CERTIFICATE FILES.\n" +
|
||||
"**THIS CANNOT BE UNDONE**\n\n" +
|
||||
"Do you wish to continue?");
|
||||
})
|
||||
})(jQuery);
|
||||
</script>
|
||||
</body>
|
21
lutron-cert/rootfs/etc/lutron/templates/bridge.html
Normal file
21
lutron-cert/rootfs/etc/lutron/templates/bridge.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1 class="display-4">{% block title %}Caseta Bridge{% endblock %}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
Enter the IP address (or hostname) of your Caseta bridge device:
|
||||
</div>
|
||||
|
||||
<div class="container mt-3">
|
||||
<form method="post" action="{{ url_for('process_addr') }}">
|
||||
<div class="row form-group justify-content-center">
|
||||
<input class="form-control col-3 justify-content-center" id="server_addr" name="server_addr" value="{{ server_addr }}" area-describedby="addr_help" placeholder="192.168.1.100" required>
|
||||
<small id="addr_help" class="form-text text-muted">The IP address of your Caseta bridge can usually be found in your router's control panel.</small>
|
||||
</div>
|
||||
<input class="btn btn-primary" type="submit" value="Continue">
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
27
lutron-cert/rootfs/etc/lutron/templates/login.html
Normal file
27
lutron-cert/rootfs/etc/lutron/templates/login.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1 class="display-4">{% block title %}Login to Lutron{% endblock %}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="m-2">
|
||||
After logging in to Lutron you will be redirected to an "error" page. Copy
|
||||
the URL of the "error" page to your clipboard, and paste it below.
|
||||
</div>
|
||||
<div class="m-2">
|
||||
<a class="btn btn-primary" href="{{ authorize_url }}" target="_blank">Click here to login to Lutron</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container mt-5">
|
||||
<form method="post" action="{{ url_for('process_url') }}">
|
||||
<div class="form-group">
|
||||
<input class="form-control" id="redirected_url" name="redirected_url" size="60" area-describedby="url_help" placeholder="https://device-login.lutron.com/lutron_app_oauth_redirect?code=..." required>
|
||||
<small id="url_help" class="form-text text-muted">Enter the URL of the "error" page you were redirected to (or the code in the URL).</small>
|
||||
</div>
|
||||
<input class="btn btn-secondary" type="submit" value="Continue">
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
30
lutron-cert/rootfs/etc/lutron/templates/success.html
Normal file
30
lutron-cert/rootfs/etc/lutron/templates/success.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1 class="display-4">{% block title %}Success!{% endblock %}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
The following files were added to the <code>{{ ssl_path }}</code> directory:
|
||||
<ul class="list-group my-3 d-inline-block text-left ssl-files">
|
||||
{% for file in ssl_files %}
|
||||
<li class="list-group-item">
|
||||
<code><span class="hljs-string">{{ ssl_files[file] }}</span></code>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
Add this to the Home Assistant <code>configuration.yaml</code> to enable Lutron Caseta:
|
||||
<div class="config my-3">
|
||||
<pre><code class="d-inline-block text-left rounded border"># Example configuration.yaml entry
|
||||
lutron_caseta:
|
||||
host: {{ server_addr }}
|
||||
keyfile: {{ ssl_files.key_file }}
|
||||
certfile: {{ ssl_files.cert_file }}
|
||||
ca_certs: {{ ssl_files.ca_file }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
9
lutron-cert/rootfs/etc/services.d/cert-server/finish
Normal file
9
lutron-cert/rootfs/etc/services.d/cert-server/finish
Normal file
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/execlineb -S0
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: Lutron Certificate
|
||||
# Take down the S6 supervision tree when cert server fails
|
||||
# ==============================================================================
|
||||
if -n { s6-test $# -ne 0 }
|
||||
if -n { s6-test ${1} -eq 256 }
|
||||
|
||||
s6-svscanctl -t /var/run/s6/services
|
10
lutron-cert/rootfs/etc/services.d/cert-server/run
Normal file
10
lutron-cert/rootfs/etc/services.d/cert-server/run
Normal file
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/with-contenv bash
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: Lutron Certificate
|
||||
# Run the cert server
|
||||
# ==============================================================================
|
||||
# shellcheck disable=SC1091
|
||||
source /usr/lib/hassio-addons/base.sh
|
||||
|
||||
hass.log.info "Starting Lutron certificate server"
|
||||
exec python3 /etc/lutron/cert_server.py
|
Loading…
Add table
Add a link
Reference in a new issue