Skip to content

Commit

Permalink
Switch to DeviceEntryType instead of entry_type
Browse files Browse the repository at this point in the history
  • Loading branch information
CharlesGillanders committed Aug 31, 2022
1 parent 71e75c5 commit 2a19c0e
Show file tree
Hide file tree
Showing 7 changed files with 287 additions and 216 deletions.
73 changes: 13 additions & 60 deletions custom_components/alphaess/__init__.py
Original file line number Diff line number Diff line change
@@ -1,89 +1,42 @@
"""The Alpha ESS integration."""
"""The AlphaEss integration."""
from __future__ import annotations

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import (
DataUpdateCoordinator,
UpdateFailed,
)

from datetime import timedelta
import logging

import asyncio
from alphaess import alphaess

from .const import (
DOMAIN,
STARTUP_MESSAGE
)


PLATFORMS = ["sensor"]

SCAN_INTERVAL = timedelta(minutes=5)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant

_LOGGER: logging.Logger = logging.getLogger(__package__)
from .const import DOMAIN, PLATFORMS
from .coordinator import AlphaESSDataUpdateCoordinator


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Alpha ESS from a config entry."""

if hass.data.get(DOMAIN) is None:
hass.data.setdefault(DOMAIN, {})
_LOGGER.info(STARTUP_MESSAGE)

client = alphaess.alphaess()
client.username = entry.data.get("username")
client.password = entry.data.get("password")
client.username = entry.data[CONF_USERNAME]
client.password = entry.data[CONF_PASSWORD]

coordinator = AlphaESSDataUpdateCoordinator(hass, client=client)
await coordinator.async_config_entry_first_refresh()

if not coordinator.last_update_success:
raise ConfigEntryNotReady


hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator

hass.config_entries.async_setup_platforms(entry, PLATFORMS)

entry.async_on_unload(entry.add_update_listener(async_update_options))
entry.async_on_unload(entry.add_update_listener(update_listener))

return True

class AlphaESSDataUpdateCoordinator(DataUpdateCoordinator):
"""Class to manage fetching data from the API."""

def __init__(
self, hass: HomeAssistant, client: alphaess.alphaess
) -> None:
"""Initialize."""
self.api = client
self.platforms = ['sensor']
self.update_method = self._async_update_data

super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL)

async def _async_update_data(self):
"""Update data via library."""
try:
_LOGGER.info("Trying to query AlphaESS api data")
return await self.api.getdata()
except Exception as exception:
raise UpdateFailed() from exception

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok:
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
hass.data[DOMAIN].pop(entry.entry_id)

return unload_ok

async def async_update_options(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Update options."""
await hass.config_entries.async_reload(entry.entry_id)
async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Handle options update."""
await hass.config_entries.async_reload(entry.entry_id)
87 changes: 39 additions & 48 deletions custom_components/alphaess/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,43 @@
"""Config flow for Alpha ESS integration."""
"""Config flow for AlphaEss integration."""
from __future__ import annotations

import logging
from typing import Any

import aiohttp
from alphaess import alphaess
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult
from homeassistant.exceptions import HomeAssistantError

from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from alphaess import alphaess

from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)

STEP_USER_DATA_SCHEMA = vol.Schema({vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str})

# class PlaceholderHub:
# """Placeholder class to make tests pass.

# TODO Remove this placeholder class and replace with things from your PyPI package.
# """

# def __init__(self, host: str) -> None:
# """Initialize."""
# self.host = host

# async def authenticate(self, username: str, password: str) -> bool:
# """Test if we can authenticate with the host."""
# return True
STEP_USER_DATA_SCHEMA = vol.Schema(
{vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
)


async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str, Any]:
"""Validate the user input allows us to connect."""
"""Validate the user input allows us to connect."cd ""
client = alphaess.alphaess()

if not await client.authenticate(data["username"],data["password"]):
raise InvalidAuth
return {"AlphaESS": data["username"]}
try:
await client.authenticate(data[CONF_USERNAME], data[CONF_PASSWORD])
except aiohttp.ClientResponseError as e:
if e.status == 401:
raise InvalidAuth
else:
raise e
except aiohttp.client_exceptions.ClientConnectorError:
raise CannotConnect
else:
return {"AlphaESS": data[CONF_USERNAME]}
class AlphaESSConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
Expand All @@ -55,33 +49,30 @@ async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle the initial step."""
if user_input is None:
return self.async_show_form(
step_id="user", data_schema=STEP_USER_DATA_SCHEMA
)
if user_input:
errors = {}

try:
info = await validate_input(self.hass, user_input)
except CannotConnect:
errors["base"] = "cannot_connect"
except InvalidAuth:
errors["base"] = "invalid_auth"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
return self.async_create_entry(title=user_input["username"], data=user_input)
errors = {}
try:
await validate_input(self.hass, user_input)
except CannotConnect:
errors["base"] = "cannot_connect"
except InvalidAuth:
errors["base"] = "invalid_auth"
return self.async_create_entry(
title=user_input["username"], data=user_input
)
return self.async_show_form(
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
)
class CannotConnect(HomeAssistantError):
"""Error to indicate we cannot connect."""


class InvalidAuth(HomeAssistantError):
"""Error to indicate there is invalid auth."""
class CannotConnect(HomeAssistantError):
"""Error to indicate there is a problem connecting."""
13 changes: 8 additions & 5 deletions custom_components/alphaess/const.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
"""Constants for the Alpha ESS integration."""

NAME = "Alpha ESS"
VERSION = "0.0.6"
ISSUE_URL = "https://github.com/CharlesGillanders/homeassistant-alphaESS/issues"
from datetime import timedelta

from homeassistant.const import Platform

DOMAIN = "alphaess"
PLATFORMS = [Platform.SENSOR]
SCAN_INTERVAL = timedelta(minutes=5)

ATTR_ENTRY_TYPE = "entry_type"
ENTRY_TYPE_SERVICE = "service"
NAME = "Alpha ESS"
VERSION = "0.0.6"
ISSUE_URL = "https://github.com/CharlesGillanders/homeassistant-alphaESS/issues"

STARTUP_MESSAGE = f"""
-------------------------------------------------------------------
Expand Down
52 changes: 52 additions & 0 deletions custom_components/alphaess/coordinator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Coordinator for AlphaEss integration."""
import datetime
import json
import logging

import aiohttp
from alphaess import alphaess

from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import DOMAIN, SCAN_INTERVAL

_LOGGER: logging.Logger = logging.getLogger(__package__)


class AlphaESSDataUpdateCoordinator(DataUpdateCoordinator):
"""Class to manage fetching data from the API."""

def __init__(self, hass: HomeAssistant, client: alphaess.alphaess) -> None:
"""Initialize."""
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL)
self.api = client
self.update_method = self._async_update_data
self.data: dict[str, dict[str, float]] = {}

async def _async_update_data(self):
"""Update data via library."""
try:
jsondata: json = await self.api.getdata()
for invertor in jsondata:
index = int(datetime.date.today().strftime("%d")) - 1
inverterdata: dict[str, any] = {}
inverterdata.update({"Model": invertor["minv"]})
inverterdata.update({"Solar Production": invertor["statistics"]["EpvT"]})
inverterdata.update({"Solar to Battery": invertor["statistics"]["Epvcharge"]})
inverterdata.update({"Solar to Grid": invertor["statistics"]["Eout"]})
inverterdata.update({"Solar to Load": invertor["statistics"]["Epv2load"]})
inverterdata.update({"Total Load": invertor["statistics"]["EHomeLoad"]})
inverterdata.update({"Grid to Load": invertor["statistics"]["EGrid2Load"]})
inverterdata.update({"Grid to Battery": invertor["statistics"]["EGridCharge"]})
inverterdata.update({"State of Charge": invertor["statistics"]["Soc"]})
inverterdata.update({"Charge": invertor["system_statistics"]["ECharge"][index]})
inverterdata.update({"Discharge": invertor["system_statistics"]["EDischarge"][index]})
inverterdata.update({"EV Charger": invertor["statistics"]["EChargingPile"]})
self.data.update({invertor["sys_sn"]: inverterdata})
return self.data
except (
aiohttp.client_exceptions.ClientConnectorError,
aiohttp.ClientResponseError,
) as error:
raise UpdateFailed(error) from error
16 changes: 16 additions & 0 deletions custom_components/alphaess/entity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Parent class for AlphaESS devices."""
from __future__ import annotations

from collections.abc import Callable
from dataclasses import dataclass

from homeassistant.components.sensor import SensorEntityDescription


@dataclass
class AlphaESSSensorDescription(SensorEntityDescription):
"""Class to describe an AlphaESS sensor."""

native_value: Callable[
[str | int | float], str | int | float
] | None = lambda val: val
19 changes: 19 additions & 0 deletions custom_components/alphaess/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Parent class for AlphaESSNames enum."""
from enum import Enum, unique


@unique
class AlphaESSNames(str, Enum):
"""Device names used by AlphaESS."""

SolarProduction = "Solar Production"
SolarToBattery = "Solar to Battery"
SolarToGrid = "Solar to Grid"
SolarToLoad = "Solar to Load"
TotalLoad = "Total Load"
GridToLoad = "Grid to Load"
GridToBattery = "Grid to Battery"
StateOfCharge = "State of Charge"
Charge = "Charge"
Discharge = "Discharge"
EVCharger = "EV Charger"
Loading

0 comments on commit 2a19c0e

Please sign in to comment.