diff --git a/.github/ISSUE_TEMPLATE/issue.md b/.github/ISSUE_TEMPLATE/issue.md index 277703d..bbd0345 100644 --- a/.github/ISSUE_TEMPLATE/issue.md +++ b/.github/ISSUE_TEMPLATE/issue.md @@ -15,21 +15,26 @@ Issues not containing the minimum requirements will be closed: --> ## Version of the custom_component - - -## Describe the bug -A clear and concise description of what the bug is. + -## `custom_updater` configuration +## Configuration ```yaml -# Add configuration here +Add your logs here. ``` +## Describe the bug +A clear and concise description of what the bug is. + + ## Debug log + + ```text Add your logs here. diff --git a/.github/main.workflow b/.github/main.workflow index 2e7cc29..7fbb3c4 100644 --- a/.github/main.workflow +++ b/.github/main.workflow @@ -1,32 +1,8 @@ -workflow "Trigger: Push to master from admin account" { - on = "push" - resolves = ["HA Index"] -} - workflow "Trigger: Push" { on = "push" resolves = ["Black Code Formatter"] } -action "branch-filter" { - uses = "actions/bin/filter@master" - args = "branch master" -} - -action "Access control" { - uses = "ludeeus/action-accesscontrol@master" - env = { - ACTION_LEVEL = "admin" - } - secrets = ["GITHUB_TOKEN"] -} - -action "HA Index" { - uses = "ludeeus/action-haindex@master" - secrets = ["GITHUB_TOKEN"] - needs = ["branch-filter", "Access control"] -} - action "Black Code Formatter" { uses = "lgeiger/black-action@master" args = "$GITHUB_WORKSPACE --check --diff" diff --git a/README.md b/README.md index d08f503..2cad190 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,10 @@ 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 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. + +HAVE FUN! 😎 + ## Why? This is simple, by having custom_components look (README + structure) the same @@ -12,6 +16,29 @@ 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 developers will have use for, please open a PR to add it :) +## What? + +This repository contains multiple files, here is a overview: + +File | Purpose +-- | -- +`.github/ISSUE_TEMPLATE/feature_request.md` | Template for Feature Requests +`.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/stale.yml` | Probot settings for the stale bot. +`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/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/sensor.py` | Sensor platform for the integration. +`custom_components/blueprint/switch.py` | Switch sensor platform for the integration. +`CONTRIBUTING.md` | Guidelines on how to contribute. +`example.png` | Screenshot that demonstrate how it might look in the UI. +`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. +`resources.json` | A special file that ['custom_updater'][customupdater] needs to download all required files. + *** README content if this was a published component: *** @@ -56,6 +83,7 @@ Using your HA configuration directory (folder) as a starting point you should no custom_components/blueprint/__init__.py custom_components/blueprint/binary_sensor.py custom_components/blueprint/const.py +custom_components/blueprint/manifest.json custom_components/blueprint/sensor.py custom_components/blueprint/switch.py ``` @@ -64,6 +92,8 @@ custom_components/blueprint/switch.py ```yaml blueprint: + username: my_username + password: my_password binary_sensor: - enabled: true name: My custom name @@ -79,8 +109,11 @@ blueprint: 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 diff --git a/custom_components/blueprint/__init__.py b/custom_components/blueprint/__init__.py index 6eab07c..6b942d6 100644 --- a/custom_components/blueprint/__init__.py +++ b/custom_components/blueprint/__init__.py @@ -7,26 +7,26 @@ import os from datetime import timedelta import logging -import requests import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.helpers import discovery from homeassistant.util import Throttle from .const import ( + CONF_BINARY_SENSOR, + CONF_ENABLED, + CONF_NAME, + CONF_PASSWORD, + CONF_SENSOR, + CONF_SWITCH, + CONF_USERNAME, + DEFAULT_NAME, DOMAIN_DATA, DOMAIN, ISSUE_URL, PLATFORMS, REQUIRED_FILES, STARTUP, - URL, VERSION, - CONF_BINARY_SENSOR, - CONF_SENSOR, - CONF_SWITCH, - CONF_ENABLED, - CONF_NAME, - DEFAULT_NAME, ) MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30) @@ -58,6 +58,8 @@ { DOMAIN: vol.Schema( { + vol.Optional(CONF_USERNAME): cv.string, + vol.Optional(CONF_PASSWORD): cv.string, vol.Optional(CONF_BINARY_SENSOR): vol.All( cv.ensure_list, [BINARY_SENSOR_SCHEMA] ), @@ -72,6 +74,8 @@ async def async_setup(hass, config): """Set up this component.""" + # Import client from a external python package hosted on PyPi + from sampleclient.client import Client # Print startup message startup = STARTUP.format(name=DOMAIN, version=VERSION, issueurl=ISSUE_URL) @@ -85,6 +89,14 @@ async def async_setup(hass, config): # Create DATA dict hass.data[DOMAIN_DATA] = {} + # Get "global" configuration. + username = config[DOMAIN].get(CONF_USERNAME) + password = config[DOMAIN].get(CONF_PASSWORD) + + # Configure the client. + client = Client(username, password) + hass.data[DOMAIN_DATA]["client"] = BlueprintData(hass, client) + # Load platforms for platform in PLATFORMS: # Get platform specific configuration @@ -110,16 +122,23 @@ async def async_setup(hass, config): return True -@Throttle(MIN_TIME_BETWEEN_UPDATES) -async def update_data(hass): - """Update data.""" - # This is where the main logic to update platform data goes. - try: - request = requests.get(URL) - jsondata = request.json() - hass.data[DOMAIN_DATA] = jsondata - except Exception as error: # pylint: disable=broad-except - _LOGGER.error("Could not update data - %s", error) +class BlueprintData: + """This class handle communication and stores the data.""" + + def __init__(self, hass, client): + """Initialize the class.""" + self.hass = hass + self.client = client + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + async def update_data(self): + """Update data.""" + # This is where the main logic to update platform data goes. + try: + data = self.client.get_data() + self.hass.data[DOMAIN_DATA]["data"] = data + except Exception as error: # pylint: disable=broad-except + _LOGGER.error("Could not update data - %s", error) async def check_files(hass): diff --git a/custom_components/blueprint/binary_sensor.py b/custom_components/blueprint/binary_sensor.py index a6a6130..6466019 100644 --- a/custom_components/blueprint/binary_sensor.py +++ b/custom_components/blueprint/binary_sensor.py @@ -1,7 +1,6 @@ """Binary sensor platform for blueprint.""" from homeassistant.components.binary_sensor import BinarySensorDevice -from . import update_data -from .const import BINARY_SENSOR_DEVICE_CLASS, DOMAIN_DATA +from .const import ATTRIBUTION, BINARY_SENSOR_DEVICE_CLASS, DEFAULT_NAME, DOMAIN_DATA async def async_setup_platform( @@ -18,25 +17,26 @@ def __init__(self, hass, config): self.hass = hass self.attr = {} self._status = False - self._name = config["name"] + self._name = config.get("name", DEFAULT_NAME) async def async_update(self): """Update the binary_sensor.""" # Send update "signal" to the component - await update_data(self.hass) + await self.hass.data[DOMAIN_DATA]["client"].update_data() # Get new data (if any) - updated = self.hass.data[DOMAIN_DATA] + updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {}) # Check the data and update the value. - if updated.get("completed") is None: + if updated.get("bool_on") is None: self._status = self._status else: - self._status = updated.get("completed") + self._status = updated.get("bool_on") # Set/update attributes - self.attr["user_id"] = updated.get("userId") - self.attr["title"] = updated.get("title") + self.attr["attribution"] = ATTRIBUTION + self.attr["time"] = str(updated.get("time")) + self.attr["static"] = updated.get("static") @property def name(self): diff --git a/custom_components/blueprint/const.py b/custom_components/blueprint/const.py index 90c07d8..7e3a620 100644 --- a/custom_components/blueprint/const.py +++ b/custom_components/blueprint/const.py @@ -4,9 +4,15 @@ DOMAIN_DATA = "{}_data".format(DOMAIN) VERSION = "0.0.1" PLATFORMS = ["binary_sensor", "sensor", "switch"] -REQUIRED_FILES = ["binary_sensor.py", "const.py", "sensor.py", "switch.py"] +REQUIRED_FILES = [ + "binary_sensor.py", + "const.py", + "manifest.json", + "sensor.py", + "switch.py", +] ISSUE_URL = "https://github.com/custom-components/blueprint/issues" - +ATTRIBUTION = "Data from this is provided by blueprint." STARTUP = """ ------------------------------------------------------------------- {name} @@ -17,9 +23,6 @@ ------------------------------------------------------------------- """ -# Operational -URL = "https://jsonplaceholder.typicode.com/todos/1" - # Icons ICON = "mdi:format-quote-close" @@ -32,6 +35,8 @@ CONF_SWITCH = "switch" CONF_ENABLED = "enabled" CONF_NAME = "name" +CONF_USERNAME = "username" +CONF_PASSWORD = "password" # Defaults DEFAULT_NAME = DOMAIN diff --git a/custom_components/blueprint/manifest.json b/custom_components/blueprint/manifest.json index fe915a6..05e6909 100644 --- a/custom_components/blueprint/manifest.json +++ b/custom_components/blueprint/manifest.json @@ -1,8 +1,8 @@ { "domain": "blueprint", "name": "Blueprint", - "documentation": "https://github.com/custom-components/blueprint/blob/master/README.md", + "documentation": "https://github.com/custom-components/blueprint", "dependencies": [], "codeowners": ["@ludeeus"], - "requirements": [] + "requirements": ["sampleclient==0.0.1"] } diff --git a/custom_components/blueprint/sensor.py b/custom_components/blueprint/sensor.py index 5b079d0..7864a79 100644 --- a/custom_components/blueprint/sensor.py +++ b/custom_components/blueprint/sensor.py @@ -1,7 +1,6 @@ """Sensor platform for blueprint.""" from homeassistant.helpers.entity import Entity -from . import update_data -from .const import DOMAIN_DATA, ICON +from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON async def async_setup_platform( @@ -18,25 +17,26 @@ def __init__(self, hass, config): self.hass = hass self.attr = {} self._state = None - self._name = config["name"] + self._name = config.get("name", DEFAULT_NAME) async def async_update(self): """Update the sensor.""" # Send update "signal" to the component - await update_data(self.hass) + await self.hass.data[DOMAIN_DATA]["client"].update_data() # Get new data (if any) - updated = self.hass.data[DOMAIN_DATA] + updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {}) # Check the data and update the value. - if updated.get("title") is None: + if updated.get("static") is None: self._state = self._status else: - self._state = updated.get("title") + self._state = updated.get("static") # Set/update attributes - self.attr["user_id"] = updated.get("userId") - self.attr["completed"] = updated.get("completed") + self.attr["attribution"] = ATTRIBUTION + self.attr["time"] = str(updated.get("time")) + self.attr["none"] = updated.get("none") @property def name(self): diff --git a/custom_components/blueprint/switch.py b/custom_components/blueprint/switch.py index c2f4e63..e588db8 100644 --- a/custom_components/blueprint/switch.py +++ b/custom_components/blueprint/switch.py @@ -1,7 +1,6 @@ """Switch platform for blueprint.""" from homeassistant.components.switch import SwitchDevice -from . import update_data -from .const import ICON, DOMAIN_DATA +from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON async def async_setup_platform( @@ -18,33 +17,31 @@ def __init__(self, hass, config): self.hass = hass self.attr = {} self._status = False - self._name = config["name"] + self._name = config.get("name", DEFAULT_NAME) async def async_update(self): """Update the switch.""" # Send update "signal" to the component - await update_data(self.hass) + await self.hass.data[DOMAIN_DATA]["client"].update_data() # Get new data (if any) - updated = self.hass.data[DOMAIN_DATA] + updated = self.hass.data[DOMAIN_DATA]["data"].get("data", {}) # Check the data and update the value. - if updated.get("completed") is None: - self._status = self._status - else: - self._status = updated.get("completed") + self._status = self.hass.data[DOMAIN_DATA]["client"].client.something # Set/update attributes - self.attr["user_id"] = updated.get("userId") - self.attr["title"] = updated.get("title") + self.attr["attribution"] = ATTRIBUTION + self.attr["time"] = str(updated.get("time")) + self.attr["static"] = updated.get("static") async def async_turn_on(self, **kwargs): # pylint: disable=unused-argument """Turn on the switch.""" - self._status = True + await self.hass.data[DOMAIN_DATA]["client"].client.change_something(True) async def async_turn_off(self, **kwargs): # pylint: disable=unused-argument """Turn off the switch.""" - self._status = False + await self.hass.data[DOMAIN_DATA]["client"].client.change_something(False) @property def name(self): diff --git a/package.yaml b/package.yaml deleted file mode 100644 index 071c8e9..0000000 --- a/package.yaml +++ /dev/null @@ -1,19 +0,0 @@ -author: - email: ludeeus@gmail.com - homepage: https://github.com/ludeeus - name: ludeeus -description: Blueprint for custom_component developers. -files: -- custom_components/blueprint/__init__.py -- custom_components/blueprint/binary_sensor.py -- custom_components/blueprint/const.py -- custom_components/blueprint/sensor.py -keywords: -- blueprint -- homeassistant -- home-assistant -- custom-component -- python -license: MIT License -name: blueprint -type: component