Skip to content

Commit

Permalink
Remove fragrance name from select entity and add an active fragrance …
Browse files Browse the repository at this point in the history
…sensor
  • Loading branch information
natekspencer committed Nov 11, 2023
1 parent 4134ca1 commit b6d48bb
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 21 deletions.
2 changes: 0 additions & 2 deletions custom_components/pura/entity.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"""Pura entities."""
from __future__ import annotations

from typing import Any

from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.device_registry import (
CONNECTION_BLUETOOTH,
Expand Down
26 changes: 11 additions & 15 deletions custom_components/pura/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from datetime import timedelta
import functools

from pypura import PuraApiException, fragrance_name
from pypura import PuraApiException
import voluptuous as vol

from homeassistant.components.select import SelectEntity, SelectEntityDescription
Expand All @@ -21,7 +21,9 @@
from .entity import PuraEntity, has_fragrance
from .helpers import get_device_id

SELECT_DESCRIPTION = SelectEntityDescription(key="fragrance", name="Fragrance")
SELECT_DESCRIPTION = SelectEntityDescription(
key="fragrance", translation_key="fragrance"
)

SERVICE_START_TIMER = "start_timer"
SERVICE_TIMER_SCHEMA = vol.All(
Expand Down Expand Up @@ -77,36 +79,30 @@ def current_option(self) -> str:
"""Return the selected entity option to represent the entity state."""
device = self.get_device()
if device["bay1"]["activeAt"]:
return self.options[1]
return "slot_1"
if device["bay2"]["activeAt"]:
return self.options[2 if has_fragrance(device, 1) else 1]
return "Off"
return "slot_2"
return "off"

@property
def options(self) -> list[str]:
"""Return a set of selectable options."""
device = self.get_device()
opts = [
f"Slot {i}: {fragrance_name(device[f'bay{i}']['code'])}"
for i in (1, 2)
if has_fragrance(device, i)
]
return ["Off"] + opts
return ["off"] + [f"slot_{i}" for i in (1, 2) if has_fragrance(device, i)]

@property
def icon(self) -> str:
"""Return the icon to use in the frontend."""
return f"mdi:scent{'-off' if self.current_option=='Off' else ''}"
return f"mdi:scent{'-off' if self.current_option=='off' else ''}"

async def async_select_option(self, option: str) -> None:
"""Change the selected option."""
if option == "Off":
if option == "off":
job = functools.partial(self.coordinator.api.stop_all, self._device_id)
elif self.get_device()["controller"] == "away":
raise PuraApiException(ERROR_AWAY_MODE)
else:
device = self.get_device()
bay = self.options.index(option) + (0 if has_fragrance(device, 1) else 1)
bay = int(option.replace("slot_", ""))
job = functools.partial(
self.coordinator.api.set_always_on, self._device_id, bay=bay
)
Expand Down
25 changes: 21 additions & 4 deletions custom_components/pura/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from .const import DOMAIN
from .coordinator import PuraDataUpdateCoordinator
from .entity import PuraEntity, has_fragrance
from .helpers import first_key_value, get_device_id
from .helpers import get_device_id


@dataclass
Expand Down Expand Up @@ -53,21 +53,24 @@ class PuraSensorEntityDescription(SensorEntityDescription, RequiredKeysMixin):
PuraSensorEntityDescription(
key="fragrance",
name="Fragrance",
entity_category=EntityCategory.DIAGNOSTIC,
icon="mdi:scent",
available_fn=lambda data: has_fragrance(data, 1),
value_fn=lambda data: data["bay_1"]["name"],
),
PuraSensorEntityDescription(
key="intensity",
name="Fan intensity",
entity_category=EntityCategory.DIAGNOSTIC,
icon="mdi:fan",
available_fn=lambda data: has_fragrance(data, 1),
value_fn=lambda data: data["bay_1"]["fan_intensity"],
),
PuraSensorEntityDescription(
key="last_active",
device_class=SensorDeviceClass.TIMESTAMP,
name="Last active",
device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC,
available_fn=lambda data: has_fragrance(data, 1),
value_fn=lambda data: datetime.fromtimestamp(
data["bay_1"]["active_at"] / 1000, UTC
Expand All @@ -77,16 +80,26 @@ class PuraSensorEntityDescription(SensorEntityDescription, RequiredKeysMixin):
key="runtime_remaining",
name="Runtime remaining",
device_class=SensorDeviceClass.DURATION,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfTime.HOURS,
state_class=SensorStateClass.MEASUREMENT,
available_fn=lambda data: has_fragrance(data, 1),
value_fn=lambda data: data["bay_1"]["wearing_time"],
),
),
("wall"): (
PuraSensorEntityDescription(
key="active_fragrance",
translation_key="active_fragrance",
icon="mdi:scent",
value_fn=lambda data: fragrance_name(data[f"bay{bay}"]["code"])
if (bay := data["deviceActiveState"]["activeBay"])
else "none",
),
PuraSensorEntityDescription(
key="bay_1",
name="Slot 1 fragrance",
entity_category=EntityCategory.DIAGNOSTIC,
icon="mdi:scent",
available_fn=lambda data: has_fragrance(data, 1),
value_fn=lambda data: fragrance_name(data["bay1"]["code"]),
Expand All @@ -95,6 +108,7 @@ class PuraSensorEntityDescription(SensorEntityDescription, RequiredKeysMixin):
key="bay_1_runtime",
name="Slot 1 runtime",
device_class=SensorDeviceClass.DURATION,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfTime.SECONDS,
state_class=SensorStateClass.TOTAL_INCREASING,
available_fn=lambda data: has_fragrance(data, 1),
Expand All @@ -104,13 +118,15 @@ class PuraSensorEntityDescription(SensorEntityDescription, RequiredKeysMixin):
key="bay_1_installed",
name="Slot 1 installed",
device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
available_fn=lambda data: has_fragrance(data, 1),
value_fn=lambda data: datetime.fromtimestamp(data["bay1"]["id"], UTC),
),
PuraSensorEntityDescription(
key="bay_2",
name="Slot 2 fragrance",
entity_category=EntityCategory.DIAGNOSTIC,
icon="mdi:scent",
available_fn=lambda data: has_fragrance(data, 2),
value_fn=lambda data: fragrance_name(data["bay2"]["code"]),
Expand All @@ -119,6 +135,7 @@ class PuraSensorEntityDescription(SensorEntityDescription, RequiredKeysMixin):
key="bay_2_runtime",
name="Slot 2 runtime",
device_class=SensorDeviceClass.DURATION,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfTime.SECONDS,
state_class=SensorStateClass.TOTAL_INCREASING,
available_fn=lambda data: has_fragrance(data, 2),
Expand All @@ -128,13 +145,14 @@ class PuraSensorEntityDescription(SensorEntityDescription, RequiredKeysMixin):
key="bay_2_installed",
name="Slot 2 installed",
device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
available_fn=lambda data: has_fragrance(data, 2),
value_fn=lambda data: datetime.fromtimestamp(data["bay2"]["id"], UTC),
),
PuraSensorEntityDescription(
key="controller",
name="Controller",
entity_category=EntityCategory.DIAGNOSTIC,
translation_key="controller",
value_fn=lambda data: data["controller"],
icon_fn=CONTROLLER_ICON.get,
Expand Down Expand Up @@ -176,7 +194,6 @@ class PuraSensorEntity(PuraEntity, SensorEntity):
"""Pura sensor entity."""

entity_description: PuraSensorEntityDescription
_attr_entity_category = EntityCategory.DIAGNOSTIC

@property
def available(self) -> bool:
Expand Down
17 changes: 17 additions & 0 deletions custom_components/pura/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,25 @@
}
},
"entity": {
"select": {
"fragrance": {
"name": "Fragrance",
"state": {
"off": "[%key:common::state::off%]",
"slot_1": "Slot 1",
"slot_2": "Slot 2"
}
}
},
"sensor": {
"active_fragrance": {
"name": "Active fragrance",
"state": {
"none": "None"
}
},
"controller": {
"name": "Controller",
"state": {
"away": "Away",
"default": "Default",
Expand Down
17 changes: 17 additions & 0 deletions custom_components/pura/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,25 @@
}
},
"entity": {
"select": {
"fragrance": {
"name": "Fragrance",
"state": {
"off": "Off",
"slot_1": "Slot 1",
"slot_2": "Slot 2"
}
}
},
"sensor": {
"active_fragrance": {
"name": "Active fragrance",
"state": {
"none": "None"
}
},
"controller": {
"name": "Controller",
"state": {
"away": "Away",
"default": "Default",
Expand Down

0 comments on commit b6d48bb

Please sign in to comment.