-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Michael Arthur
committed
Mar 10, 2023
1 parent
291a0a2
commit 765a439
Showing
11 changed files
with
635 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,129 +1,136 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
/config | ||
config2/* | ||
|
||
tests/testing_config/deps | ||
tests/testing_config/home-assistant.log* | ||
|
||
# hass-release | ||
data/ | ||
.token | ||
|
||
# Translations | ||
custom_components/*/translations | ||
|
||
# Hide sublime text stuff | ||
*.sublime-project | ||
*.sublime-workspace | ||
|
||
# Hide some OS X stuff | ||
.DS_Store | ||
.AppleDouble | ||
.LSOverride | ||
Icon | ||
|
||
# Thumbnails | ||
._* | ||
|
||
# IntelliJ IDEA | ||
.idea | ||
*.iml | ||
|
||
# pytest | ||
.pytest_cache | ||
.cache | ||
|
||
# GITHUB Proposed Python stuff: | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
pip-wheel-metadata/ | ||
share/python-wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
# Packages | ||
*.egg | ||
MANIFEST | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
*.egg-info | ||
dist | ||
build | ||
eggs | ||
.eggs | ||
parts | ||
bin | ||
var | ||
sdist | ||
develop-eggs | ||
.installed.cfg | ||
lib | ||
lib64 | ||
pip-wheel-metadata | ||
|
||
# Installer logs | ||
# Logs | ||
*.log | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.nox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
*.py,cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
nosetests.xml | ||
htmlcov/ | ||
test-reports/ | ||
test-results.xml | ||
test-output.xml | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
db.sqlite3-journal | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# IPython | ||
profile_default/ | ||
ipython_config.py | ||
# Mr Developer | ||
.mr.developer.cfg | ||
.project | ||
.pydevproject | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# pipenv | ||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | ||
# However, in case of collaboration, if having platform-specific dependencies or dependencies | ||
# having no cross-platform support, pipenv may install dependencies that don't work, or not | ||
# install all needed dependencies. | ||
#Pipfile.lock | ||
# emacs auto backups | ||
*~ | ||
*# | ||
*.orig | ||
|
||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow | ||
__pypackages__/ | ||
|
||
# Celery stuff | ||
celerybeat-schedule | ||
celerybeat.pid | ||
# venv stuff | ||
pyvenv.cfg | ||
pip-selfcheck.json | ||
venv | ||
.venv | ||
Pipfile* | ||
share/* | ||
/Scripts/ | ||
|
||
# vimmy stuff | ||
*.swp | ||
*.swo | ||
tags | ||
ctags.tmp | ||
|
||
# vagrant stuff | ||
virtualization/vagrant/setup_done | ||
virtualization/vagrant/.vagrant | ||
virtualization/vagrant/config | ||
|
||
# Visual Studio Code | ||
.vscode/* | ||
!.vscode/cSpell.json | ||
!.vscode/extensions.json | ||
!.vscode/tasks.json | ||
.env | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
# Built docs | ||
docs/build | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
# Windows Explorer | ||
desktop.ini | ||
/home-assistant.pyproj | ||
/home-assistant.sln | ||
/.vs/* | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
# mypy | ||
/.mypy_cache/* | ||
/.dmypy.json | ||
|
||
# Rope project settings | ||
.ropeproject | ||
# Secrets | ||
.lokalise_token | ||
|
||
# mkdocs documentation | ||
/site | ||
# monkeytype | ||
monkeytype.sqlite3 | ||
|
||
# mypy | ||
.mypy_cache/ | ||
.dmypy.json | ||
dmypy.json | ||
# This is left behind by Azure Restore Cache | ||
tmp_cache | ||
|
||
# Pyre type checker | ||
.pyre/ | ||
# python-language-server / Rope | ||
.ropeproject |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,10 @@ | ||
# ha-electric-kiwi | ||
HACS compatible version of the electric kiwi integration | ||
|
||
[](https://github.com/hacs/integration) | ||
|
||
|
||
Requires a valid Electric Kiwi account | ||
credentials have been given to Nabu Casa so nothing needs to be obtained, just install and use it. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
"""The Electric Kiwi integration.""" | ||
from __future__ import annotations | ||
|
||
import aiohttp | ||
from electrickiwi_api import ElectricKiwiApi | ||
from electrickiwi_api.exceptions import AuthException | ||
|
||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.const import Platform | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady | ||
from homeassistant.helpers import aiohttp_client, config_entry_oauth2_flow | ||
|
||
from . import api | ||
from .const import DOMAIN | ||
|
||
PLATFORMS: list[Platform] = [Platform.SENSOR] | ||
|
||
|
||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Set up Electric Kiwi from a config entry.""" | ||
implementation = ( | ||
await config_entry_oauth2_flow.async_get_config_entry_implementation( | ||
hass, entry | ||
) | ||
) | ||
|
||
session = config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation) | ||
|
||
try: | ||
await session.async_ensure_token_valid() | ||
except aiohttp.ClientResponseError as err: | ||
if 400 <= err.status < 500: | ||
raise ConfigEntryAuthFailed(err) from err | ||
raise ConfigEntryNotReady from err | ||
except aiohttp.ClientError as err: | ||
raise ConfigEntryNotReady from err | ||
|
||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = ElectricKiwiApi( | ||
api.AsyncConfigEntryAuth(aiohttp_client.async_get_clientsession(hass), session) | ||
) | ||
|
||
# we need to set the client number and connection id | ||
try: | ||
await hass.data[DOMAIN][entry.entry_id].set_active_session() | ||
except AuthException as err: | ||
raise ConfigEntryAuthFailed(err) from err | ||
|
||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) | ||
|
||
return True | ||
|
||
|
||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Unload a config entry.""" | ||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): | ||
hass.data[DOMAIN].pop(entry.entry_id) | ||
|
||
return unload_ok |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
"""API for Electric Kiwi bound to Home Assistant OAuth.""" | ||
|
||
from aiohttp import ClientSession | ||
from electrickiwi_api import AbstractAuth | ||
|
||
from homeassistant.helpers import config_entry_oauth2_flow | ||
|
||
from .const import API_BASE_URL | ||
|
||
|
||
class AsyncConfigEntryAuth(AbstractAuth): | ||
"""Provide Electric Kiwi authentication tied to an OAuth2 based config entry.""" | ||
|
||
def __init__( | ||
self, | ||
websession: ClientSession, | ||
oauth_session: config_entry_oauth2_flow.OAuth2Session, | ||
) -> None: | ||
"""Initialize Electric Kiwi auth.""" | ||
# add host when ready for production "https://api.electrickiwi.co.nz" defaults to dev | ||
super().__init__(websession, API_BASE_URL) | ||
self._oauth_session = oauth_session | ||
|
||
async def async_get_access_token(self) -> str: | ||
"""Return a valid access token.""" | ||
if not self._oauth_session.valid_token: | ||
await self._oauth_session.async_ensure_token_valid() | ||
|
||
return self._oauth_session.token["access_token"] |
38 changes: 38 additions & 0 deletions
38
custom_components/electric_kiwi/application_credentials.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
"""application_credentials platform the Electric Kiwi integration.""" | ||
|
||
from homeassistant.components.application_credentials import ( | ||
AuthorizationServer, | ||
ClientCredential, | ||
) | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers import config_entry_oauth2_flow | ||
|
||
from .const import OAUTH2_AUTHORIZE, OAUTH2_TOKEN | ||
from .oauth2 import ElectricKiwiLocalOAuth2Implementation | ||
|
||
|
||
async def async_get_auth_implementation( | ||
hass: HomeAssistant, auth_domain: str, credential: ClientCredential | ||
) -> config_entry_oauth2_flow.AbstractOAuth2Implementation: | ||
"""Return auth implementation.""" | ||
return ElectricKiwiLocalOAuth2Implementation( | ||
hass, | ||
auth_domain, | ||
credential, | ||
authorization_server=await async_get_authorization_server(hass), | ||
) | ||
|
||
|
||
async def async_get_authorization_server(hass: HomeAssistant) -> AuthorizationServer: | ||
"""Return authorization server.""" | ||
return AuthorizationServer( | ||
authorize_url=OAUTH2_AUTHORIZE, | ||
token_url=OAUTH2_TOKEN, | ||
) | ||
|
||
|
||
async def async_get_description_placeholders(hass: HomeAssistant) -> dict[str, str]: | ||
"""Return description placeholders for the credentials dialog.""" | ||
return { | ||
"more_info_url": "https://www.home-assistant.io/integrations/electric_kiwi/" | ||
} |
Oops, something went wrong.