8000 Add Rituals Perfume Genie sensor platform by milanmeu · Pull Request #48270 · home-assistant/core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add Rituals Perfume Genie sensor platform #48270

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

Merged
merged 12 commits into from
Apr 11, 2021
2 changes: 2 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,8 @@ omit =
homeassistant/components/rest/switch.py
homeassistant/components/ring/camera.py
homeassistant/components/ripple/sensor.py
homeassistant/components/rituals_perfume_genie/entity.py
homeassistant/components/rituals_perfume_genie/sensor.py
homeassistant/components/rituals_perfume_genie/switch.py
homeassistant/components/rituals_perfume_genie/__init__.py
homeassistant/components/rocketchat/notify.py
Expand Down
47 changes: 37 additions & 10 deletions homeassistant/components/rituals_perfume_genie/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""The Rituals Perfume Genie integration."""
import asyncio
from datetime import timedelta
import logging

from aiohttp.client_exceptions import ClientConnectorError
Expand All @@ -9,19 +10,16 @@
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator

from .const import ACCOUNT_HASH, DOMAIN
from .const import ACCOUNT_HASH, COORDINATORS, DEVICES, DOMAIN, HUB, HUBLOT

_LOGGER = logging.getLogger(__name__)
PLATFORMS = ["switch", "sensor"]

EMPTY_CREDENTIALS = ""

PLATFORMS = ["switch"]


async def async_setup(hass: HomeAssistant, config: dict):
"""Set up the Rituals Perfume Genie component."""
return True
_LOGGER = logging.getLogger(__name__)
UPDATE_INTERVAL = timedelta(seconds=30)


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
Expand All @@ -31,11 +29,40 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
account.data = {ACCOUNT_HASH: entry.data.get(ACCOUNT_HASH)}

try:
await account.get_devices()
account_devices = await account.get_devices()
except ClientConnectorError as ex:
raise ConfigEntryNotReady from ex

hass.data.setdefault(DOMAIN, {})[entry.entry_id] = account
hublots = []
devices = {}
for device in account_devices:
hublot = device.data[HUB][HUBLOT]
hublots.append(hublot)
devices[hublot] = device

hass.data.setdefault(DOMAIN, {})[entry.entry_id] = {
COORDINATORS: {},
DEVICES: devices,
}

for hublot in hublots:
device = hass.data[DOMAIN][entry.entry_id][DEVICES][hublot]

async def async_update_data():
await device.update_data()
return device.data

coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
name=f"{DOMAIN}-{hublot}",
update_method=async_update_data,
update_interval=UPDATE_INTERVAL,
)

await coordinator.async_refresh()

hass.data[DOMAIN][entry.entry_id][COORDINATORS][hublot] = coordinator

for platform in PLATFORMS:
hass.async_create_task(
Expand Down
7 changes: 6 additions & 1 deletion homeassistant/components/rituals_perfume_genie/const.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
"""Constants for the Rituals Perfume Genie integration."""

DOMAIN = "rituals_perfume_genie"

COORDINATORS = "coordinators"
DEVICES = "devices"

ACCOUNT_HASH = "account_hash"
ATTRIBUTES = "attributes"
HUB = "hub"
HUBLOT = "hublot"
44 changes: 44 additions & 0 deletions homeassistant/components/rituals_perfume_genie/entity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Base class for Rituals Perfume Genie diffuser entity."""
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import ATTRIBUTES, DOMAIN, HUB, HUBLOT

MANUFACTURER = "Rituals Cosmetics"
MODEL = "Diffuser"

SENSORS = "sensors"
ROOMNAME = "roomnamec"
VERSION = "versionc"


class DiffuserEntity(CoordinatorEntity):
"""Representation of a diffuser entity."""

def __init__(self, diffuser, coordinator, entity_suffix):
"""Init from config, hookup diffuser and coordinator."""
super().__init__(coordinator)
self._diffuser = diffuser
self._entity_suffix = entity_suffix
self._hublot = self.coordinator.data[HUB][HUBLOT]
self._hubname = self.coordinator.data[HUB][ATTRIBUTES][ROOMNAME]

@property
def unique_id(self):
"""Return the unique ID of the entity."""
return f"{self._hublot}{self._entity_suffix}"

@property
def name(self):
"""Return the name of the entity."""
return f"{self._hubname}{self._entity_suffix}"

@property
def device_info(self):
"""Return information about the device."""
return {
"name": self._hubname,
"identifiers": {(DOMAIN, self._hublot)},
"manufacturer": MANUFACTURER,
"model": MODEL,
"sw_version": self.coordinator.data[HUB][SENSORS][VERSION],
}
168 changes: 168 additions & 0 deletions homeassistant/components/rituals_perfume_genie/sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
"""Support for Rituals Perfume Genie sensors."""
from homeassistant.const import (
ATTR_BATTERY_CHARGING,
ATTR_BATTERY_LEVEL,
DEVICE_CLASS_BATTERY,
DEVICE_CLASS_SIGNAL_STRENGTH,
PERCENTAGE,
)

from .const import COORDINATORS, DEVICES, DOMAIN, HUB
from .entity import SENSORS, DiffuserEntity

ID = "id"
TITLE = "title"
ICON = "icon"
WIFI = "wific"
BATTERY = "battc"
PERFUME = "rfidc"
FILL = "fillc"

BATTERY_CHARGING_ID = 21
PERFUME_NO_CARTRIDGE_ID = 19
FILL_NO_CARTRIDGE_ID = 12

BATTERY_SUFFIX = " Battery"
PERFUME_SUFFIX = " Perfume"
FILL_SUFFIX = " Fill"
WIFI_SUFFIX = " Wifi"

ATTR_SIGNAL_STRENGTH = "signal_strength"


async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the diffuser sensors."""
diffusers = hass.data[DOMAIN][config_entry.entry_id][DEVICES]
coordinators = hass.data[DOMAIN][config_entry.entry_id][COORDINATORS]
entities = []
for hublot, diffuser in diffusers.items():
coordinator = coordinators[hublot]
entities.append(DiffuserPerfumeSensor(diffuser, coordinator))
entities.append(DiffuserFillSensor(diffuser, coordinator))
entities.append(DiffuserWifiSensor(diffuser, coordinator))
if BATTERY in diffuser.data[HUB][SENSORS]:
entities.append(DiffuserBatterySensor(diffuser, coordinator))

async_add_entities(entities)


class DiffuserPerfumeSensor(DiffuserEntity):
"""Representation of a diffuser perfume sensor."""

def __init__(self, diffuser, coordinator):
"""Initialize the perfume sensor."""
super().__init__(diffuser, coordinator, PERFUME_SUFFIX)

@property
def icon(self):
"""Return the perfume sensor icon."""
if self.coordinator.data[HUB][SENSORS][PERFUME][ID] == PERFUME_NO_CARTRIDGE_ID:
return "mdi:tag-remove"
return "mdi:tag-text"

@property
def state(self):
"""Return the state of the perfume sensor."""
return self.coordinator.data[HUB][SENSORS][PERFUME][TITLE]


class DiffuserFillSensor(DiffuserEntity):
"""Representation of a diffuser fill sensor."""

def __init__(self, diffuser, coordinator):
"""Initialize the fill sensor."""
super().__init__(diffuser, coordinator, FILL_SUFFIX)

@property
def icon(self):
"""Return the fill sensor icon."""
if self.coordinator.data[HUB][SENSORS][FILL][ID] == FILL_NO_CARTRIDGE_ID:
return "mdi:beaker-question"
return "mdi:beaker"

@property
def state(self):
"""Return the state of the fill sensor."""
return self.coordinator.data[HUB][SENSORS][FILL][TITLE]


class DiffuserBatterySensor(DiffuserEntity):
"""Representation of a diffuser battery sensor."""

def __init__(self, diffuser, coordinator):
"""Initialize the battery sensor."""
super().__init__(diffuser, coordinator, BATTERY_SUFFIX)

@property
def state(self):
"""Return the state of the battery sensor."""
# Use ICON because TITLE may change in the future.
# ICON filename does not match the image.
return {
"battery-charge.png": 100,
"battery-full.png": 100,
"battery-75.png": 50,
"battery-50.png": 25,
"battery-low.png": 10,
}[self.coordinator.data[HUB][SENSORS][BATTERY][ICON]]

@property
def _charging(self):
"""Return battery charging state."""
return bool(
self.coordinator.data[HUB][SENSORS][BATTERY][ID] == BATTERY_CHARGING_ID
)

@property
def device_class(self):
"""Return the class of the battery sensor."""
return DEVICE_CLASS_BATTERY

@property
def extra_state_attributes(self):
"""Return the battery state attributes."""
return {
ATTR_BATTERY_LEVEL: self.coordinator.data[HUB][SENSORS][BATTERY][TITLE],
ATTR_BATTERY_CHARGING: self._charging,
}

@property
def unit_of_measurement(self):
"""Return the battery unit of measurement."""
return PERCENTAGE


class DiffuserWifiSensor(DiffuserEntity):
"""Representation of a diffuser wifi sensor."""

def __init__(self, diffuser, coordinator):
"""Initialize the wifi sensor."""
super().__init__(diffuser, coordinator, WIFI_SUFFIX)

@property
def state(self):
"""Return the state of the wifi sensor."""
# Use ICON because TITLE may change in the future.
return {
"icon-signal.png": 100,
"icon-signal-75.png": 70,
"icon-signal-low.png": 25,
"icon-signal-0.png": 0,
}[self.coordinator.data[HUB][SENSORS][WIFI][ICON]]

@property
def device_class(self):
"""Return the class of the wifi sensor."""
return DEVICE_CLASS_SIGNAL_STRENGTH

@property
def extra_state_attributes(self):
"""Return the wifi state attributes."""
return {
ATTR_SIGNAL_STRENGTH: self.coordinator.data[HUB][SENSORS][WIFI][TITLE],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What measurement is this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the battery. The description of the state as shown in the app: low, medium, ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove it completely or make it a separate sensor entity.

}

@property
def unit_of_measurement(self):
"""Return the wifi unit of measurement."""
return PERCENTAGE
Loading
0