Skip to content

Commit

Permalink
Code Quality improvements for Aussie Broadband (#65408)
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
  • Loading branch information
Bre77 and MartinHjelmare committed Feb 16, 2022
1 parent be0ef5a commit bccface
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 229 deletions.
15 changes: 2 additions & 13 deletions homeassistant/components/aussie_broadband/__init__.py
Expand Up @@ -15,7 +15,7 @@
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import CONF_SERVICES, DEFAULT_UPDATE_INTERVAL, DOMAIN, SERVICE_ID
from .const import DEFAULT_UPDATE_INTERVAL, DOMAIN, SERVICE_ID

_LOGGER = logging.getLogger(__name__)
PLATFORMS = [Platform.SENSOR]
Expand All @@ -31,17 +31,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
)
try:
await client.login()
all_services = await client.get_services()
services = await client.get_services()
except AuthenticationException as exc:
raise ConfigEntryAuthFailed() from exc
except ClientError as exc:
raise ConfigEntryNotReady() from exc

# Filter the service list to those that are enabled in options
services = [
s for s in all_services if str(s["service_id"]) in entry.options[CONF_SERVICES]
]

# Create an appropriate refresh function
def update_data_factory(service_id):
async def async_update_data():
Expand Down Expand Up @@ -71,16 +66,10 @@ async def async_update_data():
"services": services,
}
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
entry.async_on_unload(entry.add_update_listener(update_listener))

return True


async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Reload to update options."""
await hass.config_entries.async_reload(entry.entry_id)


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload the config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
Expand Down
99 changes: 16 additions & 83 deletions homeassistant/components/aussie_broadband/config_flow.py
Expand Up @@ -9,12 +9,10 @@

from homeassistant import config_entries
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv

from .const import CONF_SERVICES, DOMAIN, SERVICE_ID
from .const import CONF_SERVICES, DOMAIN


class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
Expand All @@ -39,11 +37,11 @@ async def async_auth(self, user_input: dict[str, str]) -> dict[str, str] | None:
)
try:
await self.client.login()
return None
except AuthenticationException:
return {"base": "invalid_auth"}
except ClientError:
return {"base": "cannot_connect"}
return None

async def async_step_user(
self, user_input: dict[str, Any] | None = None
Expand All @@ -61,15 +59,10 @@ async def async_step_user(
if not self.services:
return self.async_abort(reason="no_services_found")

if len(self.services) == 1:
return self.async_create_entry(
title=self.data[CONF_USERNAME],
data=self.data,
options={CONF_SERVICES: [str(self.services[0][SERVICE_ID])]},
)

# Account has more than one service, select service to add
return await self.async_step_service()
return self.async_create_entry(
title=self.data[CONF_USERNAME],
data=self.data,
)

return self.async_show_form(
step_id="user",
Expand All @@ -82,37 +75,20 @@ async def async_step_user(
errors=errors,
)

async def async_step_service(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle the optional service selection step."""
if user_input is not None:
return self.async_create_entry(
title=self.data[CONF_USERNAME], data=self.data, options=user_input
)
async def async_step_reauth(self, user_input: dict[str, str]) -> FlowResult:
"""Handle reauth on credential failure."""
self._reauth_username = user_input[CONF_USERNAME]

service_options = {str(s[SERVICE_ID]): s["description"] for s in self.services}
return self.async_show_form(
step_id="service",
data_schema=vol.Schema(
{
vol.Required(
CONF_SERVICES, default=list(service_options.keys())
): cv.multi_select(service_options)
}
),
errors=None,
)
return await self.async_step_reauth_confirm()

async def async_step_reauth(
self, user_input: dict[str, Any] | None = None
async def async_step_reauth_confirm(
self, user_input: dict[str, str] | None = None
) -> FlowResult:
"""Handle reauth."""
"""Handle users reauth credentials."""

errors: dict[str, str] | None = None
if user_input and user_input.get(CONF_USERNAME):
self._reauth_username = user_input[CONF_USERNAME]

elif self._reauth_username and user_input and user_input.get(CONF_PASSWORD):
if user_input and self._reauth_username:
data = {
CONF_USERNAME: self._reauth_username,
CONF_PASSWORD: user_input[CONF_PASSWORD],
Expand All @@ -130,7 +106,7 @@ async def async_step_reauth(
return self.async_create_entry(title=self._reauth_username, data=data)

return self.async_show_form(
step_id="reauth",
step_id="reauth_confirm",
description_placeholders={"username": self._reauth_username},
data_schema=vol.Schema(
{
Expand All @@ -139,46 +115,3 @@ async def async_step_reauth(
),
errors=errors,
)

@staticmethod
@callback
def async_get_options_flow(
config_entry: config_entries.ConfigEntry,
) -> config_entries.OptionsFlow:
"""Get the options flow for this handler."""
return OptionsFlowHandler(config_entry)


class OptionsFlowHandler(config_entries.OptionsFlow):
"""Options flow for picking services."""

def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
"""Initialize options flow."""
self.config_entry = config_entry

async def async_step_init(self, user_input=None):
"""Manage the options."""
if user_input is not None:
return self.async_create_entry(title="", data=user_input)

if self.config_entry.state != config_entries.ConfigEntryState.LOADED:
return self.async_abort(reason="unknown")
data = self.hass.data[DOMAIN][self.config_entry.entry_id]
try:
services = await data["client"].get_services()
except AuthenticationException:
return self.async_abort(reason="invalid_auth")
except ClientError:
return self.async_abort(reason="cannot_connect")
service_options = {str(s[SERVICE_ID]): s["description"] for s in services}
return self.async_show_form(
step_id="init",
data_schema=vol.Schema(
{
vol.Required(
CONF_SERVICES,
default=self.config_entry.options.get(CONF_SERVICES),
): cv.multi_select(service_options),
}
),
)
58 changes: 36 additions & 22 deletions homeassistant/components/aussie_broadband/sensor.py
@@ -1,7 +1,9 @@
"""Support for Aussie Broadband metric sensors."""
from __future__ import annotations

from typing import Any
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any, cast

from homeassistant.components.sensor import (
SensorEntity,
Expand All @@ -14,88 +16,101 @@
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN, SERVICE_ID

SENSOR_DESCRIPTIONS: tuple[SensorEntityDescription, ...] = (

@dataclass
class SensorValueEntityDescription(SensorEntityDescription):
"""Class describing Aussie Broadband sensor entities."""

value: Callable = lambda x: x


SENSOR_DESCRIPTIONS: tuple[SensorValueEntityDescription, ...] = (
# Internet Services sensors
SensorEntityDescription(
SensorValueEntityDescription(
key="usedMb",
name="Data Used",
state_class=SensorStateClass.TOTAL_INCREASING,
native_unit_of_measurement=DATA_MEGABYTES,
icon="mdi:network",
),
SensorEntityDescription(
SensorValueEntityDescription(
key="downloadedMb",
name="Downloaded",
state_class=SensorStateClass.TOTAL_INCREASING,
native_unit_of_measurement=DATA_MEGABYTES,
icon="mdi:download-network",
),
SensorEntityDescription(
SensorValueEntityDescription(
key="uploadedMb",
name="Uploaded",
state_class=SensorStateClass.TOTAL_INCREASING,
native_unit_of_measurement=DATA_MEGABYTES,
icon="mdi:upload-network",
),
# Mobile Phone Services sensors
SensorEntityDescription(
SensorValueEntityDescription(
key="national",
name="National Calls",
state_class=SensorStateClass.TOTAL_INCREASING,
icon="mdi:phone",
value=lambda x: x.get("calls"),
),
SensorEntityDescription(
SensorValueEntityDescription(
key="mobile",
name="Mobile Calls",
state_class=SensorStateClass.TOTAL_INCREASING,
icon="mdi:phone",
value=lambda x: x.get("calls"),
),
SensorEntityDescription(
SensorValueEntityDescription(
key="international",
name="International Calls",
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
icon="mdi:phone-plus",
),
SensorEntityDescription(
SensorValueEntityDescription(
key="sms",
name="SMS Sent",
state_class=SensorStateClass.TOTAL_INCREASING,
icon="mdi:message-processing",
value=lambda x: x.get("calls"),
),
SensorEntityDescription(
SensorValueEntityDescription(
key="internet",
name="Data Used",
state_class=SensorStateClass.TOTAL_INCREASING,
native_unit_of_measurement=DATA_KILOBYTES,
icon="mdi:network",
value=lambda x: x.get("kbytes"),
),
SensorEntityDescription(
SensorValueEntityDescription(
key="voicemail",
name="Voicemail Calls",
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
icon="mdi:phone",
),
SensorEntityDescription(
SensorValueEntityDescription(
key="other",
name="Other Calls",
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
icon="mdi:phone",
),
# Generic sensors
SensorEntityDescription(
SensorValueEntityDescription(
key="daysTotal",
name="Billing Cycle Length",
native_unit_of_measurement=TIME_DAYS,
icon="mdi:calendar-range",
),
SensorEntityDescription(
SensorValueEntityDescription(
key="daysRemaining",
name="Billing Cycle Remaining",
native_unit_of_measurement=TIME_DAYS,
Expand All @@ -122,8 +137,10 @@ async def async_setup_entry(
class AussieBroadandSensorEntity(CoordinatorEntity, SensorEntity):
"""Base class for Aussie Broadband metric sensors."""

entity_description: SensorValueEntityDescription

def __init__(
self, service: dict[str, Any], description: SensorEntityDescription
self, service: dict[str, Any], description: SensorValueEntityDescription
) -> None:
"""Initialize the sensor."""
super().__init__(service["coordinator"])
Expand All @@ -134,16 +151,13 @@ def __init__(
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, service[SERVICE_ID])},
manufacturer="Aussie Broadband",
configuration_url=f"https://my.aussiebroadband.com.au/#/{service['name']}/{service[SERVICE_ID]}/",
configuration_url=f"https://my.aussiebroadband.com.au/#/{service['name'].lower()}/{service[SERVICE_ID]}/",
name=service["description"],
model=service["name"],
)

@property
def native_value(self):
def native_value(self) -> StateType:
"""Return the state of the sensor."""
if self.entity_description.key == "internet":
return self.coordinator.data[self.entity_description.key].get("kbytes")
if self.entity_description.key in ("national", "mobile", "sms"):
return self.coordinator.data[self.entity_description.key].get("calls")
return self.coordinator.data[self.entity_description.key]
parent = self.coordinator.data[self.entity_description.key]
return cast(StateType, self.entity_description.value(parent))
2 changes: 1 addition & 1 deletion homeassistant/components/aussie_broadband/strings.json
Expand Up @@ -13,7 +13,7 @@
"services": "Services"
}
},
"reauth": {
"reauth_confirm": {
"title": "[%key:common::config_flow::title::reauth%]",
"description": "Update password for {username}",
"data": {
Expand Down
Expand Up @@ -11,7 +11,7 @@
"unknown": "Unexpected error"
},
"step": {
"reauth": {
"reauth_confirm": {
"data": {
"password": "Password"
},
Expand Down

0 comments on commit bccface

Please sign in to comment.