Summer update 😎
This commit is contained in:
parent
45617d8515
commit
8457aefc77
17
.devcontainer/Dockerfile
Normal file
17
.devcontainer/Dockerfile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
FROM python:3.7
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
git \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN python -m pip install --upgrade colorlog black
|
||||||
|
RUN python -m pip install --upgrade git+git://github.com/home-assistant/home-assistant.git@dev
|
||||||
|
RUN cd && mkdir -p /config/custom_components
|
||||||
|
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
|
||||||
|
# Set the default shell to bash instead of sh
|
||||||
|
ENV SHELL /bin/bash
|
53
.devcontainer/README.md
Normal file
53
.devcontainer/README.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Devcontainer
|
||||||
|
|
||||||
|
_The easiest way to contribute to and/or test this repository._
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
|
||||||
|
- [docker](https://docs.docker.com/install/)
|
||||||
|
- [VS Code](https://code.visualstudio.com/)
|
||||||
|
- [Remote - Containers (VSC Extention)](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
|
||||||
|
|
||||||
|
[More info about requirements and devcontainer in general](https://code.visualstudio.com/docs/remote/containers#_getting-started)
|
||||||
|
|
||||||
|
## How to use Devcontainer for development/test
|
||||||
|
|
||||||
|
1. Make sure your computer meets the requirements.
|
||||||
|
1. Fork this repository.
|
||||||
|
1. Clone the repository to your computer.
|
||||||
|
1. Open the repository using VS Code.
|
||||||
|
|
||||||
|
When you open this repository with VSCode and your computer meets the requirements you are asked to "Reopen in Container", do that.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
If you don't see this notification, open the command pallet (ctrl+shift+p) and select `Remote-Containers: Reopen Folder in Container`.
|
||||||
|
|
||||||
|
_It will now build the devcontainer._
|
||||||
|
|
||||||
|
The container have some "tasks" to help you testing your changes.
|
||||||
|
|
||||||
|
## Custom Tasks in this repository
|
||||||
|
|
||||||
|
_Start "tasks" by opening the the command pallet (ctrl+shift+p) and select `Tasks: Run Task`_
|
||||||
|
|
||||||
|
Running tasks like `Start Home Assistant on port 8124` can be restarted by opening the the command pallet (ctrl+shift+p) and select `Tasks: Restart Running Task`, then select the task you want to restart.
|
||||||
|
|
||||||
|
### Start Home Assistant on port 8124
|
||||||
|
|
||||||
|
This will copy the configuration and the integration files to the expected location in the container.
|
||||||
|
|
||||||
|
And start up Home Assistant on [port 8124.](http://localhost:8124)
|
||||||
|
|
||||||
|
### Upgrade Home Assistant to latest dev
|
||||||
|
|
||||||
|
This will upgrade Home Assistant to the latest dev version.
|
||||||
|
|
||||||
|
### Set Home Assistant Version
|
||||||
|
|
||||||
|
This allows you to specify a version of Home Assistant to install inside the devcontainer.
|
||||||
|
|
||||||
|
### Home Assistant Config Check
|
||||||
|
|
||||||
|
This runs a config check to make sure your config is valid.
|
@ -1,12 +1,20 @@
|
|||||||
blueprint:
|
default_config:
|
||||||
username: my_username
|
logger:
|
||||||
password: my_password
|
default: error
|
||||||
binary_sensor:
|
logs:
|
||||||
- enabled: true
|
custom_components.blueprint: debug
|
||||||
name: My custom name
|
|
||||||
sensor:
|
|
||||||
- enabled: true
|
|
||||||
name: My custom name
|
blueprint:
|
||||||
switch:
|
username: my_username
|
||||||
- enabled: true
|
password: my_password
|
||||||
name: My custom name
|
binary_sensor:
|
||||||
|
- enabled: true
|
||||||
|
name: My custom name
|
||||||
|
sensor:
|
||||||
|
- enabled: true
|
||||||
|
name: My custom name
|
||||||
|
switch:
|
||||||
|
- enabled: true
|
||||||
|
name: My custom name
|
26
.devcontainer/custom_component_helper
Normal file
26
.devcontainer/custom_component_helper
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
function StartHomeAssistant {
|
||||||
|
echo "Copy configuration.yaml"
|
||||||
|
cp -f .devcontainer/configuration.yaml /config || echo ".devcontainer/configuration.yaml are missing!" exit 1
|
||||||
|
|
||||||
|
echo "Copy the custom component"
|
||||||
|
rm -R /config/custom_components/ || echo ""
|
||||||
|
cp -r custom_components /config/custom_components/ || echo "Could not copy the custom_component" exit 1
|
||||||
|
|
||||||
|
echo "Start Home Assistant"
|
||||||
|
hass -c /config
|
||||||
|
}
|
||||||
|
|
||||||
|
function UpdgradeHomeAssistantDev {
|
||||||
|
python -m pip install --upgrade git+git://github.com/home-assistant/home-assistant.git@dev
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetHomeAssistantVersion {
|
||||||
|
read -p 'Version: ' version
|
||||||
|
python -m pip install --upgrade homeassistant==$version
|
||||||
|
}
|
||||||
|
|
||||||
|
function HomeAssistantConfigCheck {
|
||||||
|
hass -c /config --script check_config
|
||||||
|
}
|
23
.devcontainer/devcontainer.json
Normal file
23
.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
|
||||||
|
{
|
||||||
|
"context": "..",
|
||||||
|
"dockerFile": "Dockerfile",
|
||||||
|
"appPort": "8124:8123",
|
||||||
|
"runArgs": [
|
||||||
|
"-e",
|
||||||
|
"GIT_EDTIOR='code --wait'"
|
||||||
|
],
|
||||||
|
"extensions": [
|
||||||
|
"ms-python.python"
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"python.pythonPath": "/usr/local/bin/python",
|
||||||
|
"python.linting.pylintEnabled": true,
|
||||||
|
"python.linting.enabled": true,
|
||||||
|
"python.formatting.provider": "black",
|
||||||
|
"editor.formatOnPaste": false,
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.formatOnType": true,
|
||||||
|
"files.trimTrailingWhitespace": true
|
||||||
|
}
|
||||||
|
}
|
BIN
.devcontainer/images/reopen.png
Normal file
BIN
.devcontainer/images/reopen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
32
.github/ISSUE_TEMPLATE/feature_request.md
vendored
32
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,17 +1,17 @@
|
|||||||
---
|
---
|
||||||
name: Feature request
|
name: Feature request
|
||||||
about: Suggest an idea for this project
|
about: Suggest an idea for this project
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
**Is your feature request related to a problem? Please describe.**
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
**Describe the solution you'd like**
|
||||||
A clear and concise description of what you want to happen.
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
**Describe alternatives you've considered**
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
82
.github/ISSUE_TEMPLATE/issue.md
vendored
82
.github/ISSUE_TEMPLATE/issue.md
vendored
@ -1,42 +1,42 @@
|
|||||||
---
|
---
|
||||||
name: Issue
|
name: Issue
|
||||||
about: Create a report to help us improve
|
about: Create a report to help us improve
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Before you open a new issue, search through the existing issues to see if others have had the same problem.
|
<!-- Before you open a new issue, search through the existing issues to see if others have had the same problem.
|
||||||
|
|
||||||
Issues not containing the minimum requirements will be closed:
|
Issues not containing the minimum requirements will be closed:
|
||||||
|
|
||||||
- Issues without a description (using the header is not good enough) will be closed.
|
- Issues without a description (using the header is not good enough) will be closed.
|
||||||
- Issues without debug logging will be closed.
|
- Issues without debug logging will be closed.
|
||||||
- Issues without configuration will be closed
|
- Issues without configuration will be closed
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Version of the custom_component
|
## Version of the custom_component
|
||||||
<!-- If you are not using the newest version, download and try that before opening an issue
|
<!-- If you are not using the newest version, download and try that before opening an issue
|
||||||
If you are unsure about the version check the const.py file.
|
If you are unsure about the version check the const.py file.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|
||||||
Add your logs here.
|
Add your logs here.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Describe the bug
|
## Describe the bug
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
|
||||||
## Debug log
|
## Debug log
|
||||||
|
|
||||||
<!-- To enable debug logs check this https://www.home-assistant.io/components/logger/ -->
|
<!-- To enable debug logs check this https://www.home-assistant.io/components/logger/ -->
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
|
||||||
Add your logs here.
|
Add your logs here.
|
||||||
|
|
||||||
```
|
```
|
9
.github/main.workflow
vendored
9
.github/main.workflow
vendored
@ -1,9 +0,0 @@
|
|||||||
workflow "Trigger: Push" {
|
|
||||||
on = "push"
|
|
||||||
resolves = ["Black Code Formatter"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "Black Code Formatter" {
|
|
||||||
uses = "lgeiger/black-action@master"
|
|
||||||
args = "$GITHUB_WORKSPACE --check --diff"
|
|
||||||
}
|
|
44
.github/settings.yml
vendored
44
.github/settings.yml
vendored
@ -1,23 +1,23 @@
|
|||||||
repository:
|
repository:
|
||||||
private: false
|
private: false
|
||||||
has_issues: true
|
has_issues: true
|
||||||
has_projects: false
|
has_projects: false
|
||||||
has_wiki: false
|
has_wiki: false
|
||||||
has_downloads: false
|
has_downloads: false
|
||||||
default_branch: master
|
default_branch: master
|
||||||
allow_squash_merge: true
|
allow_squash_merge: true
|
||||||
allow_merge_commit: false
|
allow_merge_commit: false
|
||||||
allow_rebase_merge: false
|
allow_rebase_merge: false
|
||||||
labels:
|
labels:
|
||||||
- name: "Feature Request"
|
- name: "Feature Request"
|
||||||
color: "fbca04"
|
color: "fbca04"
|
||||||
- name: "Bug"
|
- name: "Bug"
|
||||||
color: "b60205"
|
color: "b60205"
|
||||||
- name: "Wont Fix"
|
- name: "Wont Fix"
|
||||||
color: "ffffff"
|
color: "ffffff"
|
||||||
- name: "Enhancement"
|
- name: "Enhancement"
|
||||||
color: a2eeef
|
color: a2eeef
|
||||||
- name: "Documentation"
|
- name: "Documentation"
|
||||||
color: "008672"
|
color: "008672"
|
||||||
- name: "Stale"
|
- name: "Stale"
|
||||||
color: "930191"
|
color: "930191"
|
30
.github/stale.yml
vendored
30
.github/stale.yml
vendored
@ -1,16 +1,16 @@
|
|||||||
# Number of days of inactivity before an issue becomes stale
|
# Number of days of inactivity before an issue becomes stale
|
||||||
daysUntilStale: 14
|
daysUntilStale: 14
|
||||||
# Number of days of inactivity before a stale issue is closed
|
# Number of days of inactivity before a stale issue is closed
|
||||||
daysUntilClose: 7
|
daysUntilClose: 7
|
||||||
# Issues with these labels will never be considered stale
|
# Issues with these labels will never be considered stale
|
||||||
#exemptLabels:
|
#exemptLabels:
|
||||||
# - pinned
|
# - pinned
|
||||||
# - security
|
# - security
|
||||||
# Label to use when marking an issue as stale
|
# Label to use when marking an issue as stale
|
||||||
staleLabel: Stale
|
staleLabel: Stale
|
||||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||||
markComment: >
|
markComment: >
|
||||||
This issue has been automatically marked as stale because it has not had
|
This issue has been automatically marked as stale because it has not had
|
||||||
recent activity. It will be closed if no further activity occurs.
|
recent activity. It will be closed if no further activity occurs.
|
||||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||||
closeComment: false
|
closeComment: false
|
61
.vscode/tasks.json
vendored
Normal file
61
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Start Home Assistant on port 8124",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "source .devcontainer/custom_component_helper && StartHomeAssistant",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true,
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "new"
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Upgrade Home Assistant to latest dev",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "source .devcontainer/custom_component_helper && UpdgradeHomeAssistantDev",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true,
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "new"
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Set Home Assistant Version",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "source .devcontainer/custom_component_helper && SetHomeAssistantVersion",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true,
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "new"
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Home Assistant Config Check",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "source .devcontainer/custom_component_helper && HomeAssistantConfigCheck",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true,
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "new"
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
100
CONTRIBUTING.md
100
CONTRIBUTING.md
@ -1,50 +1,50 @@
|
|||||||
# Contribution guidelines
|
# Contribution guidelines
|
||||||
|
|
||||||
Contributing to this project should be as easy and transparent as possible, whether it's:
|
Contributing to this project should be as easy and transparent as possible, whether it's:
|
||||||
|
|
||||||
- Reporting a bug
|
- Reporting a bug
|
||||||
- Discussing the current state of the code
|
- Discussing the current state of the code
|
||||||
- Submitting a fix
|
- Submitting a fix
|
||||||
- Proposing new features
|
- Proposing new features
|
||||||
|
|
||||||
## Github is used for everything
|
## Github is used for everything
|
||||||
|
|
||||||
Github is used to host code, to track issues and feature requests, as well as accept pull requests.
|
Github is used to host code, to track issues and feature requests, as well as accept pull requests.
|
||||||
|
|
||||||
Pull requests are the best way to propose changes to the codebase.
|
Pull requests are the best way to propose changes to the codebase.
|
||||||
|
|
||||||
1. Fork the repo and create your branch from `master`.
|
1. Fork the repo and create your branch from `master`.
|
||||||
2. If you've changed something, update the documentation.
|
2. If you've changed something, update the documentation.
|
||||||
3. Make sure your code lints (using black).
|
3. Make sure your code lints (using black).
|
||||||
4. Issue that pull request!
|
4. Issue that pull request!
|
||||||
|
|
||||||
## Any contributions you make will be under the MIT Software License
|
## Any contributions you make will be under the MIT Software License
|
||||||
|
|
||||||
In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern.
|
In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern.
|
||||||
|
|
||||||
## Report bugs using Github's [issues](../../issues)
|
## Report bugs using Github's [issues](../../issues)
|
||||||
|
|
||||||
GitHub issues are used to track public bugs.
|
GitHub issues are used to track public bugs.
|
||||||
Report a bug by [opening a new issue](../../issues/new/choose); it's that easy!
|
Report a bug by [opening a new issue](../../issues/new/choose); it's that easy!
|
||||||
|
|
||||||
## Write bug reports with detail, background, and sample code
|
## Write bug reports with detail, background, and sample code
|
||||||
|
|
||||||
**Great Bug Reports** tend to have:
|
**Great Bug Reports** tend to have:
|
||||||
|
|
||||||
- A quick summary and/or background
|
- A quick summary and/or background
|
||||||
- Steps to reproduce
|
- Steps to reproduce
|
||||||
- Be specific!
|
- Be specific!
|
||||||
- Give sample code if you can.
|
- Give sample code if you can.
|
||||||
- What you expected would happen
|
- What you expected would happen
|
||||||
- What actually happens
|
- What actually happens
|
||||||
- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
|
- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
|
||||||
|
|
||||||
People *love* thorough bug reports. I'm not even kidding.
|
People *love* thorough bug reports. I'm not even kidding.
|
||||||
|
|
||||||
## Use a Consistent Coding Style
|
## Use a Consistent Coding Style
|
||||||
|
|
||||||
Use [black](https://github.com/ambv/black) to make sure the code follows the style.
|
Use [black](https://github.com/ambv/black) to make sure the code follows the style.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
By contributing, you agree that your contributions will be licensed under its MIT License.
|
By contributing, you agree that your contributions will be licensed under its MIT License.
|
||||||
|
40
LICENSE
40
LICENSE
@ -1,21 +1,21 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2019 Joakim Sørensen @ludeeus
|
Copyright (c) 2019 Joakim Sørensen @ludeeus
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
319
README.md
319
README.md
@ -1,160 +1,159 @@
|
|||||||
# Notice
|
# Notice
|
||||||
|
|
||||||
The component and platforms in this repository are not meant to be used by a
|
The component and platforms in this repository are not meant to be used by a
|
||||||
user, but as a "blueprint" that custom component developers can build
|
user, but as a "blueprint" that custom component developers can build
|
||||||
upon, to make more awesome stuff.
|
upon, to make more awesome stuff.
|
||||||
|
|
||||||
This blueprint uses ['sampleclient'](https://github.com/ludeeus/sampleclient) to simulate what you actually might use in your integration.
|
This blueprint uses ['sampleclient'](https://github.com/ludeeus/sampleclient) to simulate what you actually might use in your integration.
|
||||||
|
|
||||||
HAVE FUN! 😎
|
HAVE FUN! 😎
|
||||||
|
|
||||||
## Why?
|
## Why?
|
||||||
|
|
||||||
This is simple, by having custom_components look (README + structure) the same
|
This is simple, by having custom_components look (README + structure) the same
|
||||||
it is easier for developers to help each other and for users to start using them.
|
it is easier for developers to help each other and for users to start using them.
|
||||||
|
|
||||||
If you are a developer and you want to add things to this "blueprint" that you think more
|
If you are a developer and you want to add things to this "blueprint" that you think more
|
||||||
developers will have use for, please open a PR to add it :)
|
developers will have use for, please open a PR to add it :)
|
||||||
|
|
||||||
## What?
|
## What?
|
||||||
|
|
||||||
This repository contains multiple files, here is a overview:
|
This repository contains multiple files, here is a overview:
|
||||||
|
|
||||||
File | Purpose
|
File | Purpose
|
||||||
-- | --
|
-- | --
|
||||||
`.github/ISSUE_TEMPLATE/feature_request.md` | Template for Feature Requests
|
`.github/ISSUE_TEMPLATE/feature_request.md` | Template for Feature Requests
|
||||||
`.github/ISSUE_TEMPLATE/issue.md` | Template for issues
|
`.github/ISSUE_TEMPLATE/issue.md` | Template for issues
|
||||||
`.github/main.workflow` | Workflow file for GitHub Actions
|
`.github/settings.yml` | Probot settings to control the repository settings.
|
||||||
`.github/settings.yml` | Probot settings to control the repository settings.
|
`custom_components/blueprint/__init__.py` | The component file for the integration.
|
||||||
`custom_components/blueprint/__init__.py` | The component file for the integration.
|
`custom_components/blueprint/binary_sensor.py` | Binary sensor platform for the integration.
|
||||||
`custom_components/blueprint/binary_sensor.py` | Binary sensor platform for the integration.
|
`custom_components/blueprint/const.py` | A file to hold shared variables/constants for the entire integration.
|
||||||
`custom_components/blueprint/const.py` | A file to hold shared variables/constants for the entire integration.
|
`custom_components/blueprint/manifest.json` | A [manifest file](https://developers.home-assistant.io/docs/en/creating_integration_manifest.html) for Home Assistant.
|
||||||
`custom_components/blueprint/manifest.json` | A [manifest file](https://developers.home-assistant.io/docs/en/creating_integration_manifest.html) for Home Assistant.
|
`custom_components/blueprint/sensor.py` | Sensor platform for the integration.
|
||||||
`custom_components/blueprint/sensor.py` | Sensor platform for the integration.
|
`custom_components/blueprint/switch.py` | Switch sensor platform for the integration.
|
||||||
`custom_components/blueprint/switch.py` | Switch sensor platform for the integration.
|
`CONTRIBUTING.md` | Guidelines on how to contribute.
|
||||||
`CONTRIBUTING.md` | Guidelines on how to contribute.
|
`example.png` | Screenshot that demonstrate how it might look in the UI.
|
||||||
`example.png` | Screenshot that demonstrate how it might look in the UI.
|
`info.md` | An example on a info file (used by [hacs][hacs]).
|
||||||
`example.yaml` | An example on how it might look in the users configuration.yaml file.
|
`LICENSE` | The license file for the project.
|
||||||
`LICENSE` | The license file for the project.
|
`README.md` | The file you are reading now, should contain info about the integration, installation and configuration instructions.
|
||||||
`README.md` | The file you are reading now, should contain info about the integration, installation and configuration instructions.
|
|
||||||
|
***
|
||||||
***
|
README content if this was a published component:
|
||||||
README content if this was a published component:
|
***
|
||||||
***
|
|
||||||
|
# blueprint
|
||||||
# blueprint
|
|
||||||
|
[![GitHub Release][releases-shield]][releases]
|
||||||
[![GitHub Release][releases-shield]][releases]
|
[![GitHub Activity][commits-shield]][commits]
|
||||||
[![GitHub Activity][commits-shield]][commits]
|
[![License][license-shield]](LICENSE.md)
|
||||||
[![custom_updater][customupdaterbadge]][customupdater]
|
|
||||||
[![License][license-shield]](LICENSE.md)
|
[![hacs][hacsbadge]](hacs)
|
||||||
|
![Project Maintenance][maintenance-shield]
|
||||||
![Project Maintenance][maintenance-shield]
|
[![BuyMeCoffee][buymecoffeebadge]][buymecoffee]
|
||||||
[![BuyMeCoffee][buymecoffeebadge]][buymecoffee]
|
|
||||||
|
[![Discord][discord-shield]][discord]
|
||||||
[![Discord][discord-shield]][discord]
|
[![Community Forum][forum-shield]][forum]
|
||||||
[![Community Forum][forum-shield]][forum]
|
|
||||||
|
_Component to integrate with [blueprint][blueprint]._
|
||||||
_Component to integrate with [blueprint][blueprint]._
|
|
||||||
|
**This component will set up the following platforms.**
|
||||||
**This component will set up the following platforms.**
|
|
||||||
|
Platform | Description
|
||||||
Platform | Description
|
-- | --
|
||||||
-- | --
|
`binary_sensor` | Show something `True` or `False`.
|
||||||
`binary_sensor` | Show something `True` or `False`.
|
`sensor` | Show info from blueprint API.
|
||||||
`sensor` | Show info from blueprint API.
|
`switch` | Switch something `True` or `False`.
|
||||||
`switch` | Switch something `True` or `False`.
|
|
||||||
|
![example][exampleimg]
|
||||||
![example][exampleimg]
|
|
||||||
|
## Installation
|
||||||
## Installation
|
|
||||||
|
1. Using the tool of choice open the directory (folder) for your HA configuration (where you find `configuration.yaml`).
|
||||||
1. Using the tool of choice open the directory (folder) for your HA configuration (where you find `configuration.yaml`).
|
2. If you do not have a `custom_components` directory (folder) there, you need to create it.
|
||||||
2. If you do not have a `custom_components` directory (folder) there, you need to create it.
|
3. In the `custom_components` directory (folder) create a new folder called `blueprint`.
|
||||||
3. In the `custom_components` directory (folder) create a new folder called `blueprint`.
|
4. Download _all_ the files from the `custom_components/blueprint/` directory (folder) in this repository.
|
||||||
4. Download _all_ the files from the `custom_components/blueprint/` directory (folder) in this repository.
|
5. Place the files you downloaded in the new directory (folder) you created.
|
||||||
5. Place the files you downloaded in the new directory (folder) you created.
|
6. Add `blueprint:` to your HA configuration.
|
||||||
6. Add `blueprint:` to your HA configuration.
|
|
||||||
|
Using your HA configuration directory (folder) as a starting point you should now also have this:
|
||||||
Using your HA configuration directory (folder) as a starting point you should now also have this:
|
|
||||||
|
```text
|
||||||
```text
|
custom_components/blueprint/__init__.py
|
||||||
custom_components/blueprint/__init__.py
|
custom_components/blueprint/binary_sensor.py
|
||||||
custom_components/blueprint/binary_sensor.py
|
custom_components/blueprint/const.py
|
||||||
custom_components/blueprint/const.py
|
custom_components/blueprint/manifest.json
|
||||||
custom_components/blueprint/manifest.json
|
custom_components/blueprint/sensor.py
|
||||||
custom_components/blueprint/sensor.py
|
custom_components/blueprint/switch.py
|
||||||
custom_components/blueprint/switch.py
|
```
|
||||||
```
|
|
||||||
|
## Example configuration.yaml
|
||||||
## Example configuration.yaml
|
|
||||||
|
```yaml
|
||||||
```yaml
|
blueprint:
|
||||||
blueprint:
|
username: my_username
|
||||||
username: my_username
|
password: my_password
|
||||||
password: my_password
|
binary_sensor:
|
||||||
binary_sensor:
|
- enabled: true
|
||||||
- enabled: true
|
name: My custom name
|
||||||
name: My custom name
|
sensor:
|
||||||
sensor:
|
- enabled: true
|
||||||
- enabled: true
|
name: My custom name
|
||||||
name: My custom name
|
switch:
|
||||||
switch:
|
- enabled: true
|
||||||
- enabled: true
|
name: My custom name
|
||||||
name: My custom name
|
```
|
||||||
```
|
|
||||||
|
## Configuration options
|
||||||
## Configuration options
|
|
||||||
|
Key | Type | Required | Description
|
||||||
Key | Type | Required | Description
|
-- | -- | -- | --
|
||||||
-- | -- | -- | --
|
`username` | `string` | `False` | Username for the client.
|
||||||
`username` | `string` | `False` | Username for the client.
|
`password` | `string` | `False` | Password for the client.
|
||||||
`password` | `string` | `False` | Password for the client.
|
`binary_sensor` | `list` | `False` | Configuration for the `binary_sensor` platform.
|
||||||
`binary_sensor` | `list` | `False` | Configuration for the `binary_sensor` platform.
|
`sensor` | `list` | `False` | Configuration for the `sensor` platform.
|
||||||
`sensor` | `list` | `False` | Configuration for the `sensor` platform.
|
`switch` | `list` | `False` | Configuration for the `switch` platform.
|
||||||
`switch` | `list` | `False` | Configuration for the `switch` platform.
|
|
||||||
|
### Configuration options for `binary_sensor` list
|
||||||
### Configuration options for `binary_sensor` list
|
|
||||||
|
Key | Type | Required | Default | Description
|
||||||
Key | Type | Required | Default | Description
|
-- | -- | -- | -- | --
|
||||||
-- | -- | -- | -- | --
|
`enabled` | `boolean` | `False` | `True` | Boolean to enable/disable the platform.
|
||||||
`enabled` | `boolean` | `False` | `True` | Boolean to enable/disable the platform.
|
`name` | `string` | `False` | `blueprint` | Custom name for the entity.
|
||||||
`name` | `string` | `False` | `blueprint` | Custom name for the entity.
|
|
||||||
|
### Configuration options for `sensor` list
|
||||||
### Configuration options for `sensor` list
|
|
||||||
|
Key | Type | Required | Default | Description
|
||||||
Key | Type | Required | Default | Description
|
-- | -- | -- | -- | --
|
||||||
-- | -- | -- | -- | --
|
`enabled` | `boolean` | `False` | `True` | Boolean to enable/disable the platform.
|
||||||
`enabled` | `boolean` | `False` | `True` | Boolean to enable/disable the platform.
|
`name` | `string` | `False` | `blueprint` | Custom name for the entity.
|
||||||
`name` | `string` | `False` | `blueprint` | Custom name for the entity.
|
|
||||||
|
|
||||||
|
### Configuration options for `switch` list
|
||||||
### Configuration options for `switch` list
|
|
||||||
|
Key | Type | Required | Default | Description
|
||||||
Key | Type | Required | Default | Description
|
-- | -- | -- | -- | --
|
||||||
-- | -- | -- | -- | --
|
`enabled` | `boolean` | `False` | `True` | Boolean to enable/disable the platform.
|
||||||
`enabled` | `boolean` | `False` | `True` | Boolean to enable/disable the platform.
|
`name` | `string` | `False` | `blueprint` | Custom name for the entity.
|
||||||
`name` | `string` | `False` | `blueprint` | Custom name for the entity.
|
|
||||||
|
## Contributions are welcome!
|
||||||
## Contributions are welcome!
|
|
||||||
|
If you want to contribute to this please read the [Contribution guidelines](CONTRIBUTING.md)
|
||||||
If you want to contribute to this please read the [Contribution guidelines](CONTRIBUTING.md)
|
|
||||||
|
***
|
||||||
***
|
|
||||||
|
[blueprint]: https://github.com/custom-components/blueprint
|
||||||
[blueprint]: https://github.com/custom-components/blueprint
|
[buymecoffee]: https://www.buymeacoffee.com/ludeeus
|
||||||
[buymecoffee]: https://www.buymeacoffee.com/ludeeus
|
[buymecoffeebadge]: https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg?style=for-the-badge
|
||||||
[buymecoffeebadge]: https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg?style=for-the-badge
|
[commits-shield]: https://img.shields.io/github/commit-activity/y/custom-components/blueprint.svg?style=for-the-badge
|
||||||
[commits-shield]: https://img.shields.io/github/commit-activity/y/custom-components/blueprint.svg?style=for-the-badge
|
[commits]: https://github.com/custom-components/blueprint/commits/master
|
||||||
[commits]: https://github.com/custom-components/blueprint/commits/master
|
[hacs]: https://github.com/custom-components/hacs
|
||||||
[customupdater]: https://github.com/custom-components/custom_updater
|
[hacsbadge]: https://img.shields.io/badge/HACS-Custom-orange.svg?style=for-the-badge
|
||||||
[customupdaterbadge]: https://img.shields.io/badge/custom__updater-true-success.svg?style=for-the-badge
|
[discord]: https://discord.gg/Qa5fW2R
|
||||||
[discord]: https://discord.gg/Qa5fW2R
|
[discord-shield]: https://img.shields.io/discord/330944238910963714.svg?style=for-the-badge
|
||||||
[discord-shield]: https://img.shields.io/discord/330944238910963714.svg?style=for-the-badge
|
[exampleimg]: example.png
|
||||||
[exampleimg]: example.png
|
[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg?style=for-the-badge
|
||||||
[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg?style=for-the-badge
|
[forum]: https://community.home-assistant.io/
|
||||||
[forum]: https://community.home-assistant.io/
|
[license-shield]: https://img.shields.io/github/license/custom-components/blueprint.svg?style=for-the-badge
|
||||||
[license-shield]: https://img.shields.io/github/license/custom-components/blueprint.svg?style=for-the-badge
|
[maintenance-shield]: https://img.shields.io/badge/maintainer-Joakim%20Sørensen%20%40ludeeus-blue.svg?style=for-the-badge
|
||||||
[maintenance-shield]: https://img.shields.io/badge/maintainer-Joakim%20Sørensen%20%40ludeeus-blue.svg?style=for-the-badge
|
[releases-shield]: https://img.shields.io/github/release/custom-components/blueprint.svg?style=for-the-badge
|
||||||
[releases-shield]: https://img.shields.io/github/release/custom-components/blueprint.svg?style=for-the-badge
|
[releases]: https://github.com/custom-components/blueprint/releases
|
||||||
[releases]: https://github.com/custom-components/blueprint/releases
|
|
||||||
|
@ -1,160 +1,159 @@
|
|||||||
"""
|
"""
|
||||||
Component to integrate with blueprint.
|
Component to integrate with blueprint.
|
||||||
|
|
||||||
For more details about this component, please refer to
|
For more details about this component, please refer to
|
||||||
https://github.com/custom-components/blueprint
|
https://github.com/custom-components/blueprint
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers import discovery
|
from homeassistant.helpers import discovery
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_BINARY_SENSOR,
|
CONF_BINARY_SENSOR,
|
||||||
CONF_ENABLED,
|
CONF_ENABLED,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_SENSOR,
|
CONF_SENSOR,
|
||||||
CONF_SWITCH,
|
CONF_SWITCH,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
DEFAULT_NAME,
|
DEFAULT_NAME,
|
||||||
DOMAIN_DATA,
|
DOMAIN_DATA,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
ISSUE_URL,
|
ISSUE_URL,
|
||||||
PLATFORMS,
|
PLATFORMS,
|
||||||
REQUIRED_FILES,
|
REQUIRED_FILES,
|
||||||
STARTUP,
|
STARTUP,
|
||||||
VERSION,
|
VERSION,
|
||||||
)
|
)
|
||||||
|
|
||||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
|
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
BINARY_SENSOR_SCHEMA = vol.Schema(
|
BINARY_SENSOR_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_ENABLED, default=True): cv.boolean,
|
vol.Optional(CONF_ENABLED, default=True): cv.boolean,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
SENSOR_SCHEMA = vol.Schema(
|
SENSOR_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_ENABLED, default=True): cv.boolean,
|
vol.Optional(CONF_ENABLED, default=True): cv.boolean,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
SWITCH_SCHEMA = vol.Schema(
|
SWITCH_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_ENABLED, default=True): cv.boolean,
|
vol.Optional(CONF_ENABLED, default=True): cv.boolean,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
CONFIG_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
DOMAIN: vol.Schema(
|
DOMAIN: vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_USERNAME): cv.string,
|
vol.Optional(CONF_USERNAME): cv.string,
|
||||||
vol.Optional(CONF_PASSWORD): cv.string,
|
vol.Optional(CONF_PASSWORD): cv.string,
|
||||||
vol.Optional(CONF_BINARY_SENSOR): vol.All(
|
vol.Optional(CONF_BINARY_SENSOR): vol.All(
|
||||||
cv.ensure_list, [BINARY_SENSOR_SCHEMA]
|
cv.ensure_list, [BINARY_SENSOR_SCHEMA]
|
||||||
),
|
),
|
||||||
vol.Optional(CONF_SENSOR): vol.All(cv.ensure_list, [SENSOR_SCHEMA]),
|
vol.Optional(CONF_SENSOR): vol.All(cv.ensure_list, [SENSOR_SCHEMA]),
|
||||||
vol.Optional(CONF_SWITCH): vol.All(cv.ensure_list, [SWITCH_SCHEMA]),
|
vol.Optional(CONF_SWITCH): vol.All(cv.ensure_list, [SWITCH_SCHEMA]),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
extra=vol.ALLOW_EXTRA,
|
extra=vol.ALLOW_EXTRA,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass, config):
|
async def async_setup(hass, config):
|
||||||
"""Set up this component."""
|
"""Set up this component."""
|
||||||
# Import client from a external python package hosted on PyPi
|
# Import client from a external python package hosted on PyPi
|
||||||
from sampleclient.client import Client
|
from sampleclient.client import Client
|
||||||
|
|
||||||
# Print startup message
|
# Print startup message
|
||||||
startup = STARTUP.format(name=DOMAIN, version=VERSION, issueurl=ISSUE_URL)
|
startup = STARTUP.format(name=DOMAIN, version=VERSION, issueurl=ISSUE_URL)
|
||||||
_LOGGER.info(startup)
|
_LOGGER.info(startup)
|
||||||
|
|
||||||
# Check that all required files are present
|
# Check that all required files are present
|
||||||
file_check = await check_files(hass)
|
file_check = await check_files(hass)
|
||||||
if not file_check:
|
if not file_check:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Create DATA dict
|
# Create DATA dict
|
||||||
hass.data[DOMAIN_DATA] = {}
|
hass.data[DOMAIN_DATA] = {}
|
||||||
|
|
||||||
# Get "global" configuration.
|
# Get "global" configuration.
|
||||||
username = config[DOMAIN].get(CONF_USERNAME)
|
username = config[DOMAIN].get(CONF_USERNAME)
|
||||||
password = config[DOMAIN].get(CONF_PASSWORD)
|
password = config[DOMAIN].get(CONF_PASSWORD)
|
||||||
|
|
||||||
# Configure the client.
|
# Configure the client.
|
||||||
client = Client(username, password)
|
client = Client(username, password)
|
||||||
hass.data[DOMAIN_DATA]["client"] = BlueprintData(hass, client)
|
hass.data[DOMAIN_DATA]["client"] = BlueprintData(hass, client)
|
||||||
|
|
||||||
# Load platforms
|
# Load platforms
|
||||||
for platform in PLATFORMS:
|
for platform in PLATFORMS:
|
||||||
# Get platform specific configuration
|
# Get platform specific configuration
|
||||||
platform_config = config[DOMAIN].get(platform, {})
|
platform_config = config[DOMAIN].get(platform, {})
|
||||||
|
|
||||||
# If platform is not enabled, skip.
|
# If platform is not enabled, skip.
|
||||||
if not platform_config:
|
if not platform_config:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for entry in platform_config:
|
for entry in platform_config:
|
||||||
entry_config = entry
|
entry_config = entry
|
||||||
_LOGGER.critical(entry_config)
|
|
||||||
|
# If entry is not enabled, skip.
|
||||||
# If entry is not enabled, skip.
|
if not entry_config[CONF_ENABLED]:
|
||||||
if not entry_config[CONF_ENABLED]:
|
continue
|
||||||
continue
|
|
||||||
|
hass.async_create_task(
|
||||||
hass.async_create_task(
|
discovery.async_load_platform(
|
||||||
discovery.async_load_platform(
|
hass, platform, DOMAIN, entry_config, config
|
||||||
hass, platform, DOMAIN, entry_config, config
|
)
|
||||||
)
|
)
|
||||||
)
|
return True
|
||||||
return True
|
|
||||||
|
|
||||||
|
class BlueprintData:
|
||||||
class BlueprintData:
|
"""This class handle communication and stores the data."""
|
||||||
"""This class handle communication and stores the data."""
|
|
||||||
|
def __init__(self, hass, client):
|
||||||
def __init__(self, hass, client):
|
"""Initialize the class."""
|
||||||
"""Initialize the class."""
|
self.hass = hass
|
||||||
self.hass = hass
|
self.client = client
|
||||||
self.client = client
|
|
||||||
|
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
async def update_data(self):
|
||||||
async def update_data(self):
|
"""Update data."""
|
||||||
"""Update data."""
|
# This is where the main logic to update platform data goes.
|
||||||
# This is where the main logic to update platform data goes.
|
try:
|
||||||
try:
|
data = self.client.get_data()
|
||||||
data = self.client.get_data()
|
self.hass.data[DOMAIN_DATA]["data"] = data
|
||||||
self.hass.data[DOMAIN_DATA]["data"] = data
|
except Exception as error: # pylint: disable=broad-except
|
||||||
except Exception as error: # pylint: disable=broad-except
|
_LOGGER.error("Could not update data - %s", error)
|
||||||
_LOGGER.error("Could not update data - %s", error)
|
|
||||||
|
|
||||||
|
async def check_files(hass):
|
||||||
async def check_files(hass):
|
"""Return bool that indicates if all files are present."""
|
||||||
"""Return bool that indicates if all files are present."""
|
# Verify that the user downloaded all files.
|
||||||
# Verify that the user downloaded all files.
|
base = "{}/custom_components/{}/".format(hass.config.path(), DOMAIN)
|
||||||
base = "{}/custom_components/{}/".format(hass.config.path(), DOMAIN)
|
missing = []
|
||||||
missing = []
|
for file in REQUIRED_FILES:
|
||||||
for file in REQUIRED_FILES:
|
fullpath = "{}{}".format(base, file)
|
||||||
fullpath = "{}{}".format(base, file)
|
if not os.path.exists(fullpath):
|
||||||
if not os.path.exists(fullpath):
|
missing.append(file)
|
||||||
missing.append(file)
|
|
||||||
|
if missing:
|
||||||
if missing:
|
_LOGGER.critical("The following files are missing: %s", str(missing))
|
||||||
_LOGGER.critical("The following files are missing: %s", str(missing))
|
returnvalue = False
|
||||||
returnvalue = False
|
else:
|
||||||
else:
|
returnvalue = True
|
||||||
returnvalue = True
|
|
||||||
|
return returnvalue
|
||||||
return returnvalue
|
|
||||||
|
@ -1,59 +1,59 @@
|
|||||||
"""Binary sensor platform for blueprint."""
|
"""Binary sensor platform for blueprint."""
|
||||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||||
from .const import ATTRIBUTION, BINARY_SENSOR_DEVICE_CLASS, DEFAULT_NAME, DOMAIN_DATA
|
from .const import ATTRIBUTION, BINARY_SENSOR_DEVICE_CLASS, DEFAULT_NAME, DOMAIN_DATA
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass, config, async_add_entities, discovery_info=None
|
hass, config, async_add_entities, discovery_info=None
|
||||||
): # pylint: disable=unused-argument
|
): # pylint: disable=unused-argument
|
||||||
"""Setup binary_sensor platform."""
|
"""Setup binary_sensor platform."""
|
||||||
async_add_entities([BlueprintBinarySensor(hass, discovery_info)], True)
|
async_add_entities([BlueprintBinarySensor(hass, discovery_info)], True)
|
||||||
|
|
||||||
|
|
||||||
class BlueprintBinarySensor(BinarySensorDevice):
|
class BlueprintBinarySensor(BinarySensorDevice):
|
||||||
"""blueprint binary_sensor class."""
|
"""blueprint binary_sensor class."""
|
||||||
|
|
||||||
def __init__(self, hass, config):
|
def __init__(self, hass, config):
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.attr = {}
|
self.attr = {}
|
||||||
self._status = False
|
self._status = False
|
||||||
self._name = config.get("name", DEFAULT_NAME)
|
self._name = config.get("name", DEFAULT_NAME)
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
"""Update the binary_sensor."""
|
"""Update the binary_sensor."""
|
||||||
# Send update "signal" to the component
|
# Send update "signal" to the component
|
||||||
await self.hass.data[DOMAIN_DATA]["client"].update_data()
|
await self.hass.data[DOMAIN_DATA]["client"].update_data()
|
||||||
|
|
||||||
# Get new data (if any)
|
# Get new data (if any)
|
||||||
updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {})
|
updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {})
|
||||||
|
|
||||||
# Check the data and update the value.
|
# Check the data and update the value.
|
||||||
if updated.get("bool_on") is None:
|
if updated.get("bool_on") is None:
|
||||||
self._status = self._status
|
self._status = self._status
|
||||||
else:
|
else:
|
||||||
self._status = updated.get("bool_on")
|
self._status = updated.get("bool_on")
|
||||||
|
|
||||||
# Set/update attributes
|
# Set/update attributes
|
||||||
self.attr["attribution"] = ATTRIBUTION
|
self.attr["attribution"] = ATTRIBUTION
|
||||||
self.attr["time"] = str(updated.get("time"))
|
self.attr["time"] = str(updated.get("time"))
|
||||||
self.attr["static"] = updated.get("static")
|
self.attr["static"] = updated.get("static")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the binary_sensor."""
|
"""Return the name of the binary_sensor."""
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_class(self):
|
def device_class(self):
|
||||||
"""Return the class of this binary_sensor."""
|
"""Return the class of this binary_sensor."""
|
||||||
return BINARY_SENSOR_DEVICE_CLASS
|
return BINARY_SENSOR_DEVICE_CLASS
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self):
|
||||||
"""Return true if the binary_sensor is on."""
|
"""Return true if the binary_sensor is on."""
|
||||||
return self._status
|
return self._status
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the state attributes."""
|
"""Return the state attributes."""
|
||||||
return self.attr
|
return self.attr
|
||||||
|
@ -1,42 +1,42 @@
|
|||||||
"""Constants for blueprint."""
|
"""Constants for blueprint."""
|
||||||
# Base component constants
|
# Base component constants
|
||||||
DOMAIN = "blueprint"
|
DOMAIN = "blueprint"
|
||||||
DOMAIN_DATA = "{}_data".format(DOMAIN)
|
DOMAIN_DATA = "{}_data".format(DOMAIN)
|
||||||
VERSION = "0.0.1"
|
VERSION = "0.0.1"
|
||||||
PLATFORMS = ["binary_sensor", "sensor", "switch"]
|
PLATFORMS = ["binary_sensor", "sensor", "switch"]
|
||||||
REQUIRED_FILES = [
|
REQUIRED_FILES = [
|
||||||
"binary_sensor.py",
|
"binary_sensor.py",
|
||||||
"const.py",
|
"const.py",
|
||||||
"manifest.json",
|
"manifest.json",
|
||||||
"sensor.py",
|
"sensor.py",
|
||||||
"switch.py",
|
"switch.py",
|
||||||
]
|
]
|
||||||
ISSUE_URL = "https://github.com/custom-components/blueprint/issues"
|
ISSUE_URL = "https://github.com/custom-components/blueprint/issues"
|
||||||
ATTRIBUTION = "Data from this is provided by blueprint."
|
ATTRIBUTION = "Data from this is provided by blueprint."
|
||||||
STARTUP = """
|
STARTUP = """
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
{name}
|
{name}
|
||||||
Version: {version}
|
Version: {version}
|
||||||
This is a custom component
|
This is a custom component
|
||||||
If you have any issues with this you need to open an issue here:
|
If you have any issues with this you need to open an issue here:
|
||||||
{issueurl}
|
{issueurl}
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Icons
|
# Icons
|
||||||
ICON = "mdi:format-quote-close"
|
ICON = "mdi:format-quote-close"
|
||||||
|
|
||||||
# Device classes
|
# Device classes
|
||||||
BINARY_SENSOR_DEVICE_CLASS = "connectivity"
|
BINARY_SENSOR_DEVICE_CLASS = "connectivity"
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
CONF_BINARY_SENSOR = "binary_sensor"
|
CONF_BINARY_SENSOR = "binary_sensor"
|
||||||
CONF_SENSOR = "sensor"
|
CONF_SENSOR = "sensor"
|
||||||
CONF_SWITCH = "switch"
|
CONF_SWITCH = "switch"
|
||||||
CONF_ENABLED = "enabled"
|
CONF_ENABLED = "enabled"
|
||||||
CONF_NAME = "name"
|
CONF_NAME = "name"
|
||||||
CONF_USERNAME = "username"
|
CONF_USERNAME = "username"
|
||||||
CONF_PASSWORD = "password"
|
CONF_PASSWORD = "password"
|
||||||
|
|
||||||
# Defaults
|
# Defaults
|
||||||
DEFAULT_NAME = DOMAIN
|
DEFAULT_NAME = DOMAIN
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"domain": "blueprint",
|
"domain": "blueprint",
|
||||||
"name": "Blueprint",
|
"name": "Blueprint",
|
||||||
"documentation": "https://github.com/custom-components/blueprint",
|
"documentation": "https://github.com/custom-components/blueprint",
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": ["@ludeeus"],
|
"codeowners": ["@ludeeus"],
|
||||||
"requirements": ["sampleclient==0.0.1"]
|
"requirements": ["sampleclient==0.0.1"]
|
||||||
}
|
}
|
||||||
|
@ -1,59 +1,59 @@
|
|||||||
"""Sensor platform for blueprint."""
|
"""Sensor platform for blueprint."""
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON
|
from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass, config, async_add_entities, discovery_info=None
|
hass, config, async_add_entities, discovery_info=None
|
||||||
): # pylint: disable=unused-argument
|
): # pylint: disable=unused-argument
|
||||||
"""Setup sensor platform."""
|
"""Setup sensor platform."""
|
||||||
async_add_entities([BlueprintSensor(hass, discovery_info)], True)
|
async_add_entities([BlueprintSensor(hass, discovery_info)], True)
|
||||||
|
|
||||||
|
|
||||||
class BlueprintSensor(Entity):
|
class BlueprintSensor(Entity):
|
||||||
"""blueprint Sensor class."""
|
"""blueprint Sensor class."""
|
||||||
|
|
||||||
def __init__(self, hass, config):
|
def __init__(self, hass, config):
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.attr = {}
|
self.attr = {}
|
||||||
self._state = None
|
self._state = None
|
||||||
self._name = config.get("name", DEFAULT_NAME)
|
self._name = config.get("name", DEFAULT_NAME)
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
"""Update the sensor."""
|
"""Update the sensor."""
|
||||||
# Send update "signal" to the component
|
# Send update "signal" to the component
|
||||||
await self.hass.data[DOMAIN_DATA]["client"].update_data()
|
await self.hass.data[DOMAIN_DATA]["client"].update_data()
|
||||||
|
|
||||||
# Get new data (if any)
|
# Get new data (if any)
|
||||||
updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {})
|
updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {})
|
||||||
|
|
||||||
# Check the data and update the value.
|
# Check the data and update the value.
|
||||||
if updated.get("static") is None:
|
if updated.get("static") is None:
|
||||||
self._state = self._status
|
self._state = self._status
|
||||||
else:
|
else:
|
||||||
self._state = updated.get("static")
|
self._state = updated.get("static")
|
||||||
|
|
||||||
# Set/update attributes
|
# Set/update attributes
|
||||||
self.attr["attribution"] = ATTRIBUTION
|
self.attr["attribution"] = ATTRIBUTION
|
||||||
self.attr["time"] = str(updated.get("time"))
|
self.attr["time"] = str(updated.get("time"))
|
||||||
self.attr["none"] = updated.get("none")
|
self.attr["none"] = updated.get("none")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the sensor."""
|
"""Return the name of the sensor."""
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon(self):
|
def icon(self):
|
||||||
"""Return the icon of the sensor."""
|
"""Return the icon of the sensor."""
|
||||||
return ICON
|
return ICON
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the state attributes."""
|
"""Return the state attributes."""
|
||||||
return self.attr
|
return self.attr
|
||||||
|
@ -1,64 +1,64 @@
|
|||||||
"""Switch platform for blueprint."""
|
"""Switch platform for blueprint."""
|
||||||
from homeassistant.components.switch import SwitchDevice
|
from homeassistant.components.switch import SwitchDevice
|
||||||
from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON
|
from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass, config, async_add_entities, discovery_info=None
|
hass, config, async_add_entities, discovery_info=None
|
||||||
): # pylint: disable=unused-argument
|
): # pylint: disable=unused-argument
|
||||||
"""Setup switch platform."""
|
"""Setup switch platform."""
|
||||||
async_add_entities([BlueprintBinarySwitch(hass, discovery_info)], True)
|
async_add_entities([BlueprintBinarySwitch(hass, discovery_info)], True)
|
||||||
|
|
||||||
|
|
||||||
class BlueprintBinarySwitch(SwitchDevice):
|
class BlueprintBinarySwitch(SwitchDevice):
|
||||||
"""blueprint switch class."""
|
"""blueprint switch class."""
|
||||||
|
|
||||||
def __init__(self, hass, config):
|
def __init__(self, hass, config):
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.attr = {}
|
self.attr = {}
|
||||||
self._status = False
|
self._status = False
|
||||||
self._name = config.get("name", DEFAULT_NAME)
|
self._name = config.get("name", DEFAULT_NAME)
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
"""Update the switch."""
|
"""Update the switch."""
|
||||||
# Send update "signal" to the component
|
# Send update "signal" to the component
|
||||||
await self.hass.data[DOMAIN_DATA]["client"].update_data()
|
await self.hass.data[DOMAIN_DATA]["client"].update_data()
|
||||||
|
|
||||||
# Get new data (if any)
|
# Get new data (if any)
|
||||||
updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {})
|
updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {})
|
||||||
|
|
||||||
# Check the data and update the value.
|
# Check the data and update the value.
|
||||||
self._status = self.hass.data[DOMAIN_DATA]["client"].client.something
|
self._status = self.hass.data[DOMAIN_DATA]["client"].client.something
|
||||||
|
|
||||||
# Set/update attributes
|
# Set/update attributes
|
||||||
self.attr["attribution"] = ATTRIBUTION
|
self.attr["attribution"] = ATTRIBUTION
|
||||||
self.attr["time"] = str(updated.get("time"))
|
self.attr["time"] = str(updated.get("time"))
|
||||||
self.attr["static"] = updated.get("static")
|
self.attr["static"] = updated.get("static")
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs): # pylint: disable=unused-argument
|
async def async_turn_on(self, **kwargs): # pylint: disable=unused-argument
|
||||||
"""Turn on the switch."""
|
"""Turn on the switch."""
|
||||||
await self.hass.data[DOMAIN_DATA]["client"].client.change_something(True)
|
await self.hass.data[DOMAIN_DATA]["client"].client.change_something(True)
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs): # pylint: disable=unused-argument
|
async def async_turn_off(self, **kwargs): # pylint: disable=unused-argument
|
||||||
"""Turn off the switch."""
|
"""Turn off the switch."""
|
||||||
await self.hass.data[DOMAIN_DATA]["client"].client.change_something(False)
|
await self.hass.data[DOMAIN_DATA]["client"].client.change_something(False)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the switch."""
|
"""Return the name of the switch."""
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon(self):
|
def icon(self):
|
||||||
"""Return the icon of this switch."""
|
"""Return the icon of this switch."""
|
||||||
return ICON
|
return ICON
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self):
|
||||||
"""Return true if the switch is on."""
|
"""Return true if the switch is on."""
|
||||||
return self._status
|
return self._status
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the state attributes."""
|
"""Return the state attributes."""
|
||||||
return self.attr
|
return self.attr
|
||||||
|
98
info.md
Normal file
98
info.md
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
[![GitHub Release][releases-shield]][releases]
|
||||||
|
[![GitHub Activity][commits-shield]][commits]
|
||||||
|
[![License][license-shield]](LICENSE.md)
|
||||||
|
|
||||||
|
[![hacs][hacsbadge]](hacs)
|
||||||
|
![Project Maintenance][maintenance-shield]
|
||||||
|
[![BuyMeCoffee][buymecoffeebadge]][buymecoffee]
|
||||||
|
|
||||||
|
[![Discord][discord-shield]][discord]
|
||||||
|
[![Community Forum][forum-shield]][forum]
|
||||||
|
|
||||||
|
_Component to integrate with [blueprint][blueprint]._
|
||||||
|
|
||||||
|
**This component will set up the following platforms.**
|
||||||
|
|
||||||
|
Platform | Description
|
||||||
|
-- | --
|
||||||
|
`binary_sensor` | Show something `True` or `False`.
|
||||||
|
`sensor` | Show info from blueprint API.
|
||||||
|
`switch` | Switch something `True` or `False`.
|
||||||
|
|
||||||
|
![example][exampleimg]
|
||||||
|
|
||||||
|
{% if not installed %}
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Click install.
|
||||||
|
1. Add `blueprint:` to your HA configuration.
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
## Example configuration.yaml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
blueprint:
|
||||||
|
username: my_username
|
||||||
|
password: my_password
|
||||||
|
binary_sensor:
|
||||||
|
- enabled: true
|
||||||
|
name: My custom name
|
||||||
|
sensor:
|
||||||
|
- enabled: true
|
||||||
|
name: My custom name
|
||||||
|
switch:
|
||||||
|
- enabled: true
|
||||||
|
name: My custom name
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration options
|
||||||
|
|
||||||
|
Key | Type | Required | Description
|
||||||
|
-- | -- | -- | --
|
||||||
|
`username` | `string` | `False` | Username for the client.
|
||||||
|
`password` | `string` | `False` | Password for the client.
|
||||||
|
`binary_sensor` | `list` | `False` | Configuration for the `binary_sensor` platform.
|
||||||
|
`sensor` | `list` | `False` | Configuration for the `sensor` platform.
|
||||||
|
`switch` | `list` | `False` | Configuration for the `switch` platform.
|
||||||
|
|
||||||
|
### Configuration options for `binary_sensor` list
|
||||||
|
|
||||||
|
Key | Type | Required | Default | Description
|
||||||
|
-- | -- | -- | -- | --
|
||||||
|
`enabled` | `boolean` | `False` | `True` | Boolean to enable/disable the platform.
|
||||||
|
`name` | `string` | `False` | `blueprint` | Custom name for the entity.
|
||||||
|
|
||||||
|
### Configuration options for `sensor` list
|
||||||
|
|
||||||
|
Key | Type | Required | Default | Description
|
||||||
|
-- | -- | -- | -- | --
|
||||||
|
`enabled` | `boolean` | `False` | `True` | Boolean to enable/disable the platform.
|
||||||
|
`name` | `string` | `False` | `blueprint` | Custom name for the entity.
|
||||||
|
|
||||||
|
|
||||||
|
### Configuration options for `switch` list
|
||||||
|
|
||||||
|
Key | Type | Required | Default | Description
|
||||||
|
-- | -- | -- | -- | --
|
||||||
|
`enabled` | `boolean` | `False` | `True` | Boolean to enable/disable the platform.
|
||||||
|
`name` | `string` | `False` | `blueprint` | Custom name for the entity.
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
[blueprint]: https://github.com/custom-components/blueprint
|
||||||
|
[buymecoffee]: https://www.buymeacoffee.com/ludeeus
|
||||||
|
[buymecoffeebadge]: https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg?style=for-the-badge
|
||||||
|
[commits-shield]: https://img.shields.io/github/commit-activity/y/custom-components/blueprint.svg?style=for-the-badge
|
||||||
|
[commits]: https://github.com/custom-components/blueprint/commits/master
|
||||||
|
[hacs]: https://github.com/custom-components/hacs
|
||||||
|
[hacsbadge]: https://img.shields.io/badge/HACS-Custom-orange.svg?style=for-the-badge
|
||||||
|
[discord]: https://discord.gg/Qa5fW2R
|
||||||
|
[discord-shield]: https://img.shields.io/discord/330944238910963714.svg?style=for-the-badge
|
||||||
|
[exampleimg]: example.png
|
||||||
|
[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg?style=for-the-badge
|
||||||
|
[forum]: https://community.home-assistant.io/
|
||||||
|
[license-shield]: https://img.shields.io/github/license/custom-components/blueprint.svg?style=for-the-badge
|
||||||
|
[maintenance-shield]: https://img.shields.io/badge/maintainer-Joakim%20Sørensen%20%40ludeeus-blue.svg?style=for-the-badge
|
||||||
|
[releases-shield]: https://img.shields.io/github/release/custom-components/blueprint.svg?style=for-the-badge
|
||||||
|
[releases]: https://github.com/custom-components/blueprint/releases
|
Loading…
x
Reference in New Issue
Block a user