Skip to content

Commit

Permalink
Merge pull request #571 from MTrab:Add-select-entities
Browse files Browse the repository at this point in the history
Migrate zone selection to input_select entity
  • Loading branch information
MTrab authored Apr 15, 2024
2 parents aa1a940 + e4e3bbe commit e22038a
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 304 deletions.
4 changes: 3 additions & 1 deletion custom_components/landroid_cloud/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
UPDATE_SIGNAL,
LandroidFeatureSupport,
)
from .utils.logger import LandroidLogger, LoggerType, LogLevel
from .utils.logger import LandroidLogger, LoggerType


class LandroidAPI:
Expand Down Expand Up @@ -51,6 +51,8 @@ def __init__(self, hass: HomeAssistant, device_name: str, entry: ConfigEntry):
self.features = 0
self.features_loaded = False

self.device_name = device_name

self.cloud.update(self.device.serial_number)
self.cloud._decode_data(self.device)

Expand Down
8 changes: 1 addition & 7 deletions custom_components/landroid_cloud/attribute_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@

from __future__ import annotations

from homeassistant.const import ATTR_LOCKED

from .const import ATTR_ACCESSORIES, ATTR_LAWN, ATTR_PARTYMODE, ATTR_TORQUE, ATTR_ZONE
from .const import ATTR_ACCESSORIES, ATTR_LAWN

ATTR_MAP = {
"accessories": ATTR_ACCESSORIES,
"lawn": ATTR_LAWN,
"locked": ATTR_LOCKED,
"partymode_enabled": ATTR_PARTYMODE,
"torque": ATTR_TORQUE,
"zone": ATTR_ZONE,
}
10 changes: 9 additions & 1 deletion custom_components/landroid_cloud/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,15 @@
DEFAULT_NAME = "landroid"
DOMAIN = "landroid_cloud"
PLATFORMS_SECONDARY = []
PLATFORMS_PRIMARY = ["lawn_mower", "sensor", "switch", "binary_sensor", "number", "button"]
PLATFORMS_PRIMARY = [
"lawn_mower",
"sensor",
"switch",
"binary_sensor",
"number",
"button",
"select",
]
UPDATE_SIGNAL = "landroid_cloud_update"
LOGLEVEL = LogLevel.DEBUG
ENTITY_ID_FORMAT = DOMAIN + ".{}"
Expand Down
191 changes: 107 additions & 84 deletions custom_components/landroid_cloud/device_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
ZoneNoProbability,
ZoneNotDefined,
)
from pyworxcloud.utils import DeviceHandler

from .api import LandroidAPI
from .attribute_map import ATTR_MAP
Expand All @@ -54,7 +55,6 @@
ATTR_LONGITUDE,
ATTR_RUNTIME,
ATTR_SERVICE,
ATTR_ZONE,
BUTTONTYPE_TO_SERVICE,
DOMAIN,
ENTITY_ID_FORMAT,
Expand Down Expand Up @@ -424,88 +424,6 @@ async def async_get_state_from_api(self, dt=None) -> None: # type: ignore pylin
)


class LandroidCloudSelectEntity(LandroidCloudBaseEntity, SelectEntity):
"""Define a select entity."""

def __init__(
self,
description: SelectEntityDescription,
hass: HomeAssistant,
api: LandroidAPI,
):
"""Initialize a new Landroid Cloud select entity."""
super().__init__(hass, api)
self._api = api
self.entity_description = description
self._attr_unique_id = (
f"{api.name}_select_{description.key}_{api.device.serial_number}"
)
self._attr_options = []
self._attr_current_option = None
self.entity_id = ENTITY_ID_FORMAT.format(f"{api.name} {description.key}")

@property
def available(self) -> bool:
"""Return if the entity is available."""
return self._api.device.online

@property
def device_class(self) -> str:
"""Return the ID of the capability, to identify the entity for translations."""
return f"{DOMAIN}__select_{self.entity_description.key}"


class LandroidCloudSelectZoneEntity(LandroidCloudSelectEntity):
"""Select zone entity definition."""

@callback
def update_selected_zone(self):
"""Get new data and update state."""
if not isinstance(self._attr_options, type(None)):
if len(self._attr_options) > 1:
self._update_zone()

try:
self._attr_current_option = str(self.api.shared_options["current_zone"])
except: # pylint: disable=bare-except
self._attr_current_option = None

self.schedule_update_ha_state(True)

def _update_zone(self) -> None:
"""Update zone selector options."""
try:
zones = self.api.device.zone["starting_point"]
except: # pylint: disable=bare-except
zones = []

if len(zones) == 4:
options = []
options.append("0")
for idx in range(1, 4):
if zones[idx] != 0:
options.append(str(idx))

self._attr_options = options

@callback
def update_callback(self):
"""Get new data and update state."""
self._update_zone()
self.update_selected_zone()

async def async_select_option(self, option: str) -> None:
"""Set next zone to be mowed."""
data = {ATTR_ZONE: int(option)}
target = {"device_id": self.api.device_id}
await self.hass.services.async_call(
DOMAIN,
SERVICE_SETZONE,
service_data=data,
target=target,
)


class LandroidCloudButtonBase(LandroidCloudBaseEntity, ButtonEntity):
"""Define a Landroid Cloud button class."""

Expand Down Expand Up @@ -911,7 +829,7 @@ class LandroidSensorEntityDescription(
"""Describes a Landroid sensor."""

unit_fn: Callable[[WorxCloud], None] = None
attributes: [] | None = None
attributes: [] | None = None # pylance: disable=reportInvalidTypeForm


@dataclass
Expand Down Expand Up @@ -942,6 +860,111 @@ class LandroidSwitchEntityDescription(
icon_off: str | None = None


@dataclass
class LandroidSelectEntityDescription(SelectEntityDescription):
"""Describes a Landroid select."""

value_fn: Callable[[DeviceHandler], bool | str | int | float | None] = None
command_fn: Callable[[LandroidAPI, str], None] = None


class LandroidSelect(SelectEntity):
"""Representation of a Landroid select entity."""

_attr_has_entity_name = True

def __init__(
self,
hass: HomeAssistant,
description: LandroidSelectEntityDescription,
api: LandroidAPI,
config: ConfigEntry,
) -> None:
"""Initialize a Landroid select."""
super().__init__()

self.entity_description = description
self.hass = hass
self.device = api.device

self._api = api
self._config = config

self._attr_name = self.entity_description.name

_LOGGER.debug(
"(%s, Setup) Added input_select '%s'",
self._api.friendly_name,
self._attr_name,
)

self._attr_unique_id = util_slugify(
f"{self._attr_name}_{self._config.entry_id}_{self._api.device.serial_number}"
)
self._attr_should_poll = False

self._attr_device_info = {
"identifiers": {
(
DOMAIN,
self._api.unique_id,
self._api.entry_id,
self._api.device.serial_number,
)
},
"name": str(f"{self._api.friendly_name}"),
"sw_version": self._api.device.firmware["version"],
"manufacturer": self._api.config["type"].capitalize(),
"model": self._api.device.model,
"serial_number": self._api.device.serial_number,
}

if self.device.mac_address != "__UUID__":
_connections = {(dr.CONNECTION_NETWORK_MAC, self.device.mac_address)}
self._attr_device_info.update({"connections": _connections})

self._value = self.entity_description.value_fn(self._api.device) + 1

async_dispatcher_connect(
self.hass,
util_slugify(f"{UPDATE_SIGNAL}_{self._api.device.name}"),
self.handle_update,
)

async def handle_update(self) -> None:
"""Handle the updates when recieving an update signal."""
try:
self._value = self.entity_description.value_fn(self._api.device) + 1
except AttributeError:
return

_LOGGER.debug(
"(%s, Update signal) Updating select '%s'",
self._api.friendly_name,
self._attr_name,
)
try:
self.async_write_ha_state()
except RuntimeError:
pass

@property
def current_option(self) -> str | None:
"""Return the selected entity option to represent the entity state."""
return str(self._value)

async def async_select_option(self, option: int) -> None:
"""Change the selected option."""
_LOGGER.debug(
"(%s, Set value) Setting selected value for '%s' to %s",
self._api.friendly_name,
self._attr_name,
option,
)

self.entity_description.command_fn(self._api, str(option - 1))


class LandroidButton(ButtonEntity):
"""Representation of a Landroid button."""

Expand Down
36 changes: 0 additions & 36 deletions custom_components/landroid_cloud/devices/ferrex.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
SUPPORT_LANDROID_BASE,
LandroidCloudButtonBase,
LandroidCloudMowerBase,
LandroidCloudSelectEntity,
LandroidCloudSelectZoneEntity,
)
from ..utils.logger import LoggerType

Expand Down Expand Up @@ -82,40 +80,6 @@ def __init__(
)
self.device: WorxCloud = self.api.device


class Select(LandroidCloudSelectEntity):
"""Definition of Aldi Ferrex select entity."""

def __init__(
self,
description: SelectEntityDescription,
hass: HomeAssistant,
api: LandroidAPI,
):
"""Init new Aldi Ferrex Select entity."""
super().__init__(description, hass, api)
self.device: WorxCloud = self.api.device
self.log(
LoggerType.SELECT,
"Adding %s",
description.key,
)


class ZoneSelect(Select, LandroidCloudSelectZoneEntity):
"""Definition of a Aldi Ferrex zone selector."""

def __init__(
self,
description: SelectEntityDescription,
hass: HomeAssistant,
api: LandroidAPI,
):
"""Init new Kress Zone Select entity."""
super().__init__(description, hass, api)
self.device: WorxCloud = self.api.device


class MowerDevice(LandroidCloudMowerBase, LawnMowerEntity):
"""Definition of KreAldi Ferrexss device."""

Expand Down
35 changes: 0 additions & 35 deletions custom_components/landroid_cloud/devices/kress.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
SUPPORT_LANDROID_BASE,
LandroidCloudButtonBase,
LandroidCloudMowerBase,
LandroidCloudSelectEntity,
LandroidCloudSelectZoneEntity,
)
from ..utils.logger import LoggerType

Expand Down Expand Up @@ -83,39 +81,6 @@ def __init__(
)


class Select(LandroidCloudSelectEntity):
"""Definition of Kress select entity."""

def __init__(
self,
description: SelectEntityDescription,
hass: HomeAssistant,
api: LandroidAPI,
):
"""Init new Kress Select entity."""
super().__init__(description, hass, api)
self.device: WorxCloud = self.api.device
self.log(
LoggerType.SELECT,
"Adding %s",
description.key,
)


class ZoneSelect(Select, LandroidCloudSelectZoneEntity):
"""Definition of a Kress zone selector."""

def __init__(
self,
description: SelectEntityDescription,
hass: HomeAssistant,
api: LandroidAPI,
):
"""Init new Kress Zone Select entity."""
super().__init__(description, hass, api)
self.device: WorxCloud = self.api.device


class MowerDevice(LandroidCloudMowerBase, LawnMowerEntity):
"""Definition of Kress device."""

Expand Down
Loading

0 comments on commit e22038a

Please sign in to comment.