Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework goalzero for EntityDescription #54786

Merged
merged 5 commits into from Aug 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 11 additions & 10 deletions homeassistant/components/goalzero/__init__.py
Expand Up @@ -43,7 +43,7 @@
PLATFORMS = [DOMAIN_BINARY_SENSOR, DOMAIN_SENSOR, DOMAIN_SWITCH]


async def async_setup_entry(hass, entry):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Goal Zero Yeti from a config entry."""
name = entry.data[CONF_NAME]
host = entry.data[CONF_HOST]
Expand Down Expand Up @@ -81,7 +81,7 @@ async def async_update_data():
return True


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
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:
Expand All @@ -94,7 +94,13 @@ class YetiEntity(CoordinatorEntity):

_attr_extra_state_attributes = {ATTR_ATTRIBUTION: ATTRIBUTION}

def __init__(self, api, coordinator, name, server_unique_id):
def __init__(
self,
api: Yeti,
coordinator: DataUpdateCoordinator,
name: str,
server_unique_id: str,
) -> None:
"""Initialize a Goal Zero Yeti entity."""
super().__init__(coordinator)
self.api = api
Expand All @@ -104,15 +110,10 @@ def __init__(self, api, coordinator, name, server_unique_id):
@property
def device_info(self) -> DeviceInfo:
"""Return the device information of the entity."""
model = sw_version = None
if self.api.sysdata:
model = self.api.sysdata[ATTR_MODEL]
if self.api.data:
sw_version = self.api.data["firmwareVersion"]
return {
ATTR_IDENTIFIERS: {(DOMAIN, self._server_unique_id)},
ATTR_MANUFACTURER: "Goal Zero",
ATTR_NAME: self._name,
ATTR_MODEL: str(model),
ATTR_SW_VERSION: str(sw_version),
ATTR_MODEL: self.api.sysdata.get(ATTR_MODEL),
ATTR_SW_VERSION: self.api.data.get("firmwareVersion"),
}
78 changes: 54 additions & 24 deletions homeassistant/components/goalzero/binary_sensor.py
@@ -1,14 +1,51 @@
"""Support for Goal Zero Yeti Sensors."""
from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.const import ATTR_DEVICE_CLASS, ATTR_ICON, ATTR_NAME, CONF_NAME
from __future__ import annotations

from . import YetiEntity
from .const import BINARY_SENSOR_DICT, DATA_KEY_API, DATA_KEY_COORDINATOR, DOMAIN
from homeassistant.components.binary_sensor import (
DEVICE_CLASS_BATTERY_CHARGING,
DEVICE_CLASS_CONNECTIVITY,
DEVICE_CLASS_POWER,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator

from . import Yeti, YetiEntity
from .const import DATA_KEY_API, DATA_KEY_COORDINATOR, DOMAIN

PARALLEL_UPDATES = 0

BINARY_SENSOR_TYPES: tuple[BinarySensorEntityDescription, ...] = (
tkdrob marked this conversation as resolved.
Show resolved Hide resolved
BinarySensorEntityDescription(
key="backlight",
name="Backlight",
icon="mdi:clock-digital",
),
BinarySensorEntityDescription(
key="app_online",
name="App Online",
device_class=DEVICE_CLASS_CONNECTIVITY,
),
BinarySensorEntityDescription(
key="isCharging",
name="Charging",
device_class=DEVICE_CLASS_BATTERY_CHARGING,
),
BinarySensorEntityDescription(
key="inputDetected",
name="Input Detected",
device_class=DEVICE_CLASS_POWER,
),
)


async def async_setup_entry(hass, entry, async_add_entities):
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the Goal Zero Yeti sensor."""
name = entry.data[CONF_NAME]
goalzero_data = hass.data[DOMAIN][entry.entry_id]
Expand All @@ -17,10 +54,10 @@ async def async_setup_entry(hass, entry, async_add_entities):
goalzero_data[DATA_KEY_API],
goalzero_data[DATA_KEY_COORDINATOR],
name,
sensor_name,
description,
entry.entry_id,
)
for sensor_name in BINARY_SENSOR_DICT
for description in BINARY_SENSOR_TYPES
)


Expand All @@ -29,26 +66,19 @@ class YetiBinarySensor(YetiEntity, BinarySensorEntity):

def __init__(
self,
api,
coordinator,
name,
sensor_name,
server_unique_id,
):
api: Yeti,
coordinator: DataUpdateCoordinator,
name: str,
description: BinarySensorEntityDescription,
server_unique_id: str,
) -> None:
"""Initialize a Goal Zero Yeti sensor."""
super().__init__(api, coordinator, name, server_unique_id)

self._condition = sensor_name
self._attr_device_class = BINARY_SENSOR_DICT[sensor_name].get(ATTR_DEVICE_CLASS)
self._attr_icon = BINARY_SENSOR_DICT[sensor_name].get(ATTR_ICON)
self._attr_name = f"{name} {BINARY_SENSOR_DICT[sensor_name].get(ATTR_NAME)}"
self._attr_unique_id = (
f"{server_unique_id}/{BINARY_SENSOR_DICT[sensor_name].get(ATTR_NAME)}"
)
self.entity_description = description
self._attr_name = f"{name} {description.name}"
self._attr_unique_id = f"{server_unique_id}/{description.key}"

@property
def is_on(self) -> bool:
"""Return if the service is on."""
if self.api.data:
return self.api.data[self._condition] == 1
return False
return self.api.data.get(self.entity_description.key) == 1
15 changes: 9 additions & 6 deletions homeassistant/components/goalzero/config_flow.py
Expand Up @@ -13,6 +13,7 @@
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.typing import DiscoveryInfoType

from .const import DEFAULT_NAME, DOMAIN

Expand All @@ -24,19 +25,19 @@ class GoalZeroFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):

VERSION = 1

def __init__(self):
def __init__(self) -> None:
"""Initialize a Goal Zero Yeti flow."""
self.ip_address = None

async def async_step_dhcp(self, discovery_info):
async def async_step_dhcp(self, discovery_info: DiscoveryInfoType) -> FlowResult:
"""Handle dhcp discovery."""
self.ip_address = discovery_info[IP_ADDRESS]

await self.async_set_unique_id(discovery_info[MAC_ADDRESS])
self._abort_if_unique_id_configured(updates={CONF_HOST: self.ip_address})
self._async_abort_entries_match({CONF_HOST: self.ip_address})

_, error = await self._async_try_connect(self.ip_address)
_, error = await self._async_try_connect(str(self.ip_address))
if error is None:
return await self.async_step_confirm_discovery()
return self.async_abort(reason=error)
Expand All @@ -63,7 +64,9 @@ async def async_step_confirm_discovery(
},
)

async def async_step_user(self, user_input=None) -> FlowResult:
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle a flow initiated by the user."""
errors = {}
if user_input is not None:
Expand All @@ -74,7 +77,7 @@ async def async_step_user(self, user_input=None) -> FlowResult:

mac_address, error = await self._async_try_connect(host)
if error is None:
await self.async_set_unique_id(format_mac(mac_address))
await self.async_set_unique_id(format_mac(str(mac_address)))
self._abort_if_unique_id_configured(updates={CONF_HOST: host})
return self.async_create_entry(
title=name,
Expand All @@ -98,7 +101,7 @@ async def async_step_user(self, user_input=None) -> FlowResult:
errors=errors,
)

async def _async_try_connect(self, host) -> tuple:
async def _async_try_connect(self, host: str) -> tuple[str | None, str | None]:
"""Try connecting to Goal Zero Yeti."""
try:
session = async_get_clientsession(self.hass)
Expand Down
141 changes: 0 additions & 141 deletions homeassistant/components/goalzero/const.py
@@ -1,37 +1,6 @@
"""Constants for the Goal Zero Yeti integration."""
from datetime import timedelta

from homeassistant.components.binary_sensor import (
DEVICE_CLASS_BATTERY_CHARGING,
DEVICE_CLASS_CONNECTIVITY,
DEVICE_CLASS_POWER,
)
from homeassistant.components.sensor import (
ATTR_STATE_CLASS,
DEVICE_CLASS_BATTERY,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_SIGNAL_STRENGTH,
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_VOLTAGE,
STATE_CLASS_MEASUREMENT,
)
from homeassistant.const import (
ATTR_DEVICE_CLASS,
ATTR_ICON,
ATTR_NAME,
ATTR_UNIT_OF_MEASUREMENT,
ELECTRIC_CURRENT_AMPERE,
ELECTRIC_POTENTIAL_VOLT,
ENERGY_WATT_HOUR,
PERCENTAGE,
POWER_WATT,
SIGNAL_STRENGTH_DECIBELS,
TEMP_CELSIUS,
TIME_MINUTES,
TIME_SECONDS,
)

ATTRIBUTION = "Data provided by Goal Zero"
ATTR_DEFAULT_ENABLED = "default_enabled"

Expand All @@ -41,113 +10,3 @@
DATA_KEY_API = "api"

MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)

BINARY_SENSOR_DICT = {
"backlight": {ATTR_NAME: "Backlight", ATTR_ICON: "mdi:clock-digital"},
"app_online": {
ATTR_NAME: "App Online",
ATTR_DEVICE_CLASS: DEVICE_CLASS_CONNECTIVITY,
},
"isCharging": {
ATTR_NAME: "Charging",
ATTR_DEVICE_CLASS: DEVICE_CLASS_BATTERY_CHARGING,
},
"inputDetected": {
ATTR_NAME: "Input Detected",
ATTR_DEVICE_CLASS: DEVICE_CLASS_POWER,
},
}

SENSOR_DICT = {
"wattsIn": {
ATTR_NAME: "Watts In",
ATTR_DEVICE_CLASS: DEVICE_CLASS_POWER,
ATTR_UNIT_OF_MEASUREMENT: POWER_WATT,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
ATTR_DEFAULT_ENABLED: True,
},
"ampsIn": {
ATTR_NAME: "Amps In",
ATTR_DEVICE_CLASS: DEVICE_CLASS_CURRENT,
ATTR_UNIT_OF_MEASUREMENT: ELECTRIC_CURRENT_AMPERE,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
ATTR_DEFAULT_ENABLED: False,
},
"wattsOut": {
ATTR_NAME: "Watts Out",
ATTR_DEVICE_CLASS: DEVICE_CLASS_POWER,
ATTR_UNIT_OF_MEASUREMENT: POWER_WATT,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
ATTR_DEFAULT_ENABLED: True,
},
"ampsOut": {
ATTR_NAME: "Amps Out",
ATTR_DEVICE_CLASS: DEVICE_CLASS_CURRENT,
ATTR_UNIT_OF_MEASUREMENT: ELECTRIC_CURRENT_AMPERE,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
ATTR_DEFAULT_ENABLED: False,
},
"whOut": {
ATTR_NAME: "WH Out",
ATTR_DEVICE_CLASS: DEVICE_CLASS_ENERGY,
ATTR_UNIT_OF_MEASUREMENT: ENERGY_WATT_HOUR,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
ATTR_DEFAULT_ENABLED: False,
},
"whStored": {
ATTR_NAME: "WH Stored",
ATTR_DEVICE_CLASS: DEVICE_CLASS_ENERGY,
ATTR_UNIT_OF_MEASUREMENT: ENERGY_WATT_HOUR,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
ATTR_DEFAULT_ENABLED: True,
},
"volts": {
ATTR_NAME: "Volts",
ATTR_DEVICE_CLASS: DEVICE_CLASS_VOLTAGE,
ATTR_UNIT_OF_MEASUREMENT: ELECTRIC_POTENTIAL_VOLT,
ATTR_DEFAULT_ENABLED: False,
},
"socPercent": {
ATTR_NAME: "State of Charge Percent",
ATTR_DEVICE_CLASS: DEVICE_CLASS_BATTERY,
ATTR_UNIT_OF_MEASUREMENT: PERCENTAGE,
ATTR_DEFAULT_ENABLED: True,
},
"timeToEmptyFull": {
ATTR_NAME: "Time to Empty/Full",
ATTR_DEVICE_CLASS: TIME_MINUTES,
ATTR_UNIT_OF_MEASUREMENT: TIME_MINUTES,
ATTR_DEFAULT_ENABLED: True,
},
"temperature": {
ATTR_NAME: "Temperature",
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
ATTR_DEFAULT_ENABLED: True,
},
"wifiStrength": {
ATTR_NAME: "Wifi Strength",
ATTR_DEVICE_CLASS: DEVICE_CLASS_SIGNAL_STRENGTH,
ATTR_UNIT_OF_MEASUREMENT: SIGNAL_STRENGTH_DECIBELS,
ATTR_DEFAULT_ENABLED: True,
},
"timestamp": {
ATTR_NAME: "Total Run Time",
ATTR_UNIT_OF_MEASUREMENT: TIME_SECONDS,
ATTR_DEFAULT_ENABLED: False,
},
"ssid": {
ATTR_NAME: "Wi-Fi SSID",
ATTR_DEFAULT_ENABLED: False,
},
"ipAddr": {
ATTR_NAME: "IP Address",
ATTR_DEFAULT_ENABLED: False,
},
}

SWITCH_DICT = {
"v12PortStatus": "12V Port Status",
"usbPortStatus": "USB Port Status",
"acPortStatus": "AC Port Status",
}