Skip to content

Commit

Permalink
Merge pull request #3 from RenierM26/ubersolar_refactor_cleanup
Browse files Browse the repository at this point in the history
Major refactor and cleanup.
  • Loading branch information
RenierM26 authored Jul 15, 2023
2 parents 0a6e7c0 + 2582284 commit 8a0efe9
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 109 deletions.
3 changes: 2 additions & 1 deletion custom_components/ubersolar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import logging

import ubersolar

from homeassistant.components import bluetooth
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ADDRESS, CONF_NAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
import ubersolar

from .const import CONF_RETRY_COUNT, DEFAULT_RETRY_COUNT, DOMAIN
from .coordinator import UbersolarDataUpdateCoordinator
Expand Down
4 changes: 2 additions & 2 deletions custom_components/ubersolar/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging
from typing import Any

from ubersolar import UberSolarAdvertisement
import voluptuous as vol

from homeassistant.components.bluetooth import (
Expand All @@ -14,7 +15,6 @@
from homeassistant.const import CONF_ADDRESS
from homeassistant.core import callback
from homeassistant.data_entry_flow import AbortFlow, FlowResult
from ubersolar import UberSolarAdvertisement

from .const import CONF_RETRY_COUNT, DEFAULT_RETRY_COUNT, DOMAIN

Expand Down Expand Up @@ -45,7 +45,7 @@ def async_get_options_flow(
"""Get the options flow for this handler."""
return UbersolarOptionsFlowHandler(config_entry)

def __init__(self):
def __init__(self) -> None:
"""Initialize the config flow."""
self._discovered_adv: UberSolarAdvertisement | None = None
self._discovered_advs: dict[str, UberSolarAdvertisement] = {}
Expand Down
5 changes: 3 additions & 2 deletions custom_components/ubersolar/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
import logging
from typing import TYPE_CHECKING

from ubersolar import UberSmart

from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
import ubersolar

from .const import DOMAIN

Expand All @@ -25,7 +26,7 @@ def __init__(
hass: HomeAssistant,
logger: logging.Logger,
ble_device: BLEDevice,
device: ubersolar.UberSmart,
device: UberSmart,
base_unique_id: str,
device_name: str,
) -> None:
Expand Down
12 changes: 4 additions & 8 deletions custom_components/ubersolar/datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

from homeassistant.components.datetime import DateTimeEntity, DateTimeEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_platform
from homeassistant.helpers.entity import EntityCategory
from homeassistant.util import dt as dt_util
import ubersolar

from .const import DOMAIN
from .coordinator import UbersolarDataUpdateCoordinator
Expand All @@ -23,7 +22,7 @@
DATETIME_TYPE = DateTimeEntityDescription(
key="lluTime",
name="Device Time",
entity_category=EntityCategory.DIAGNOSTIC,
entity_category=EntityCategory.CONFIG,
)


Expand All @@ -35,15 +34,12 @@ async def async_setup_entry(
"""Set up UberSolar based on a config entry."""
coordinator: UbersolarDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]

async_add_entities(UbersmartDateTime(coordinator))
async_add_entities([UbersmartDateTime(coordinator)])


class UbersmartDateTime(UbersolarEntity, DateTimeEntity):
"""Representation of a UberSolar DateTimeEntity."""

_device: ubersolar.UberSmart
_attr_has_entity_name = True

def __init__(self, coordinator: UbersolarDataUpdateCoordinator) -> None:
"""Initialize the UberSmart device."""
super().__init__(coordinator)
Expand All @@ -53,7 +49,7 @@ def __init__(self, coordinator: UbersolarDataUpdateCoordinator) -> None:
@property
def native_value(self) -> datetime | None:
"""Return the value reported by the datetime."""
return dt_util.parse_datetime(self.data["lluTime"])
return dt_util.parse_datetime(f"{self.data['lluTime']}+02:00")

async def async_set_value(self, value: datetime) -> None:
"""Change the date/time."""
Expand Down
11 changes: 10 additions & 1 deletion custom_components/ubersolar/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
import logging
from typing import Any

from ubersolar import UberSmart

from homeassistant.components import bluetooth
from homeassistant.const import ATTR_CONNECTIONS
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.entity import DeviceInfo, Entity
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from ubersolar import UberSmart

from .const import MANUFACTURER, MODEL
from .coordinator import UbersolarDataUpdateCoordinator
Expand Down Expand Up @@ -50,3 +52,10 @@ def __init__(self, coordinator: UbersolarDataUpdateCoordinator) -> None:
def data(self) -> dict[str, Any]:
"""Return coordinator data for this entity."""
return self.coordinator.device.status_data[self._address]

@property
def available(self) -> bool:
"""Return if entity is available."""
return super().available and bluetooth.async_address_present(
self.hass, self._address, True
)
2 changes: 1 addition & 1 deletion custom_components/ubersolar/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
"issue_tracker": "https://github.com/RenierM26/ha-ubersolar/issues",
"loggers": ["ubersolar"],
"requirements": ["PyUbersolar==0.1.3"],
"version": "0.1.8"
"version": "0.1.9"
}
79 changes: 39 additions & 40 deletions custom_components/ubersolar/select.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"""Support for UberSolar."""
from __future__ import annotations

from dataclasses import dataclass
import logging

from homeassistant.components.select import SelectEntity, SelectEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_platform
from homeassistant.helpers.entity import EntityCategory
import ubersolar

from .const import DOMAIN
from .coordinator import UbersolarDataUpdateCoordinator
Expand All @@ -19,19 +19,28 @@
PARALLEL_UPDATES = 0


SELECT_METHODS_LIST: dict[str, list] = {
"eSolenoidMode": ["set_solinoid_off", "set_solinoid_on", "set_solinoid_auto"],
}
@dataclass
class UbersmartSelectEntityDescriptionMixin:
"""Mixin values for Ubersmart select entities."""

SELECT_TYPES: dict[str, SelectEntityDescription] = {
"eSolenoidMode": SelectEntityDescription(
key="eSolenoidMode",
name="Solenoid Mode",
icon="mdi:electric-switch",
entity_category=EntityCategory.CONFIG,
options=[0, 1, 2],
),
}
method: list


@dataclass
class UbersmartSelectEntityDescription(
SelectEntityDescription, UbersmartSelectEntityDescriptionMixin
):
"""Describe a Ubersmart select entity."""


SELECT_TYPE = UbersmartSelectEntityDescription(
key="eSolenoidMode",
name="Solenoid Mode",
icon="mdi:electric-switch",
entity_category=EntityCategory.CONFIG,
options=["Off", "On", "Auto"],
method=["set_solinoid_off", "set_solinoid_on", "set_solinoid_auto"],
)


async def async_setup_entry(
Expand All @@ -41,47 +50,37 @@ async def async_setup_entry(
) -> None:
"""Set up UberSolar based on a config entry."""
coordinator: UbersolarDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
entities = [
UbersmartSelect(
coordinator,
selector,
)
for selector in coordinator.device.status_data[coordinator.address]
if selector in SELECT_TYPES
]

async_add_entities(entities)
async_add_entities([UbersmartSelect(coordinator)])


class UbersmartSelect(UbersolarEntity, SelectEntity):
"""Representation of a UberSolar Selector."""

_device: ubersolar.UberSmart
_attr_has_entity_name = True

def __init__(
self, coordinator: UbersolarDataUpdateCoordinator, selector: str
) -> None:
def __init__(self, coordinator: UbersolarDataUpdateCoordinator) -> None:
"""Initialize the UberSmart device."""
super().__init__(coordinator)
self._selector = selector
self._attr_unique_id = f"{coordinator.base_unique_id}-{selector}"
self.entity_description = SELECT_TYPES[selector]

@property
def current_option(self) -> str | None:
"""Return the selected entity option to represent the entity state."""
return self.data[self._selector]
self._selector = SELECT_TYPE.key
self._attr_unique_id = f"{coordinator.base_unique_id}-{SELECT_TYPE.key}"
self.entity_description = SELECT_TYPE
self._attr_current_option = SELECT_TYPE.options[self.data[self._selector]]

async def async_select_option(self, option: str) -> None:
"""Change the selected option."""
_LOGGER.info(
_LOGGER.debug(
"Set %s value to %s for device %s", self._selector, option, self._address
)

switch_method = getattr(
self._device, SELECT_METHODS_LIST[self._selector][option]
self._device, SELECT_TYPE.method[SELECT_TYPE.options.index(option)]
)

await switch_method()
self._attr_current_option = option
self.async_write_ha_state()

@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
self._attr_current_option = SELECT_TYPE.options[self.data[self._selector]]
super()._handle_coordinator_update()
15 changes: 1 addition & 14 deletions custom_components/ubersolar/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
from homeassistant.const import (
LIGHT_LUX,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfElectricPotential,
UnitOfTemperature,
UnitOfTime,
UnitOfVolume,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import DOMAIN
Expand All @@ -43,29 +43,25 @@
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=True,
),
"fManifoldTemperature": SensorEntityDescription(
key="fManifoldTemperature",
name="Manifold Temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=True,
),
"fStoredWater": SensorEntityDescription(
key="fStoredWater",
name="Stored Water at 40C",
native_unit_of_measurement=UnitOfVolume.LITERS,
device_class=SensorDeviceClass.VOLUME,
state_class=SensorStateClass.TOTAL,
entity_registry_enabled_default=True,
),
"fSolenoidState": SensorEntityDescription(
key="fSolenoidState",
name="Solenoid State",
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=True,
entity_category=EntityCategory.DIAGNOSTIC,
),
"lluTime": SensorEntityDescription(
Expand All @@ -89,29 +85,25 @@
native_unit_of_measurement=LIGHT_LUX,
device_class=SensorDeviceClass.ILLUMINANCE,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
"fPanelVoltage": SensorEntityDescription(
key="fPanelVoltage",
name="Solar Panel Voltage",
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
"fChipTemp": SensorEntityDescription(
key="fChipTemp",
name="ESP32 Temp",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
"fWaterLevel": SensorEntityDescription(
key="fWaterLevel",
name="Water Level in Manifold",
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
),
"fTankSize": SensorEntityDescription(
Expand All @@ -121,34 +113,29 @@
device_class=SensorDeviceClass.VOLUME,
state_class=SensorStateClass.TOTAL,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=True,
),
"bPanelFaultCode": SensorEntityDescription(
key="bPanelFaultCode",
name="SolarPanel Fault Code",
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
),
"bElementFaultCode": SensorEntityDescription(
key="bElementFaultCode",
name="Element Fault Code",
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
),
"bPumpFultCode": SensorEntityDescription(
key="bPumpFultCode",
name="Pump Fault Code",
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
),
"bSolenoidFaultCode": SensorEntityDescription(
key="bSolenoidFaultCode",
name="Solenoid Fault Code",
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
),
}
Expand Down
12 changes: 1 addition & 11 deletions custom_components/ubersolar/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,11 @@
},
"confirm": {
"description": "Do you want to set up {name}?"
},
"password": {
"description": "The {name} device requires a password",
"data": {
"password": "[%key:common::config_flow::data::password%]"
}
}
},
"error": {},
"abort": {
"already_configured_device": "[%key:common::config_flow::abort::already_configured_device%]",
"no_unconfigured_devices": "No unconfigured devices found.",
"unknown": "[%key:common::config_flow::error::unknown%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"switchbot_unsupported_type": "Unsupported Switchbot Type."
"no_unconfigured_devices": "No unconfigured devices found."
}
},
"options": {
Expand Down
Loading

0 comments on commit 8a0efe9

Please sign in to comment.