Add available to LiteJet (#86506)

* Set available attribute as needed.

* Log disconnect reason.

* Change the exception that is raised.

* Bump version.
This commit is contained in:
Jon Caruana 2023-01-24 05:22:16 -08:00 committed by GitHub
parent d703a83412
commit c9499f6574
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 49 deletions

View File

@ -2,7 +2,6 @@
import logging import logging
import pylitejet import pylitejet
from serial import SerialException
import voluptuous as vol import voluptuous as vol
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
@ -53,9 +52,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
try: try:
system = await pylitejet.open(port) system = await pylitejet.open(port)
except SerialException as ex: except pylitejet.LiteJetError as exc:
_LOGGER.error("Error connecting to the LiteJet MCP at %s", port, exc_info=ex) raise ConfigEntryNotReady from exc
raise ConfigEntryNotReady from ex
def handle_connected_changed(connected: bool, reason: str) -> None:
if connected:
_LOGGER.info("Connected")
else:
_LOGGER.warning("Disconnected %s", reason)
system.on_connected_changed(handle_connected_changed)
async def handle_stop(event) -> None: async def handle_stop(event) -> None:
await system.close() await system.close()

View File

@ -1,10 +1,9 @@
"""Support for LiteJet lights.""" """Support for LiteJet lights."""
from __future__ import annotations from __future__ import annotations
import logging
from typing import Any from typing import Any
from pylitejet import LiteJet from pylitejet import LiteJet, LiteJetError
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_BRIGHTNESS,
@ -15,12 +14,11 @@ from homeassistant.components.light import (
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import CONF_DEFAULT_TRANSITION, DOMAIN from .const import CONF_DEFAULT_TRANSITION, DOMAIN
_LOGGER = logging.getLogger(__name__)
ATTR_NUMBER = "number" ATTR_NUMBER = "number"
@ -66,14 +64,19 @@ class LiteJetLight(LightEntity):
"""Run when this Entity has been added to HA.""" """Run when this Entity has been added to HA."""
self._lj.on_load_activated(self._index, self._on_load_changed) self._lj.on_load_activated(self._index, self._on_load_changed)
self._lj.on_load_deactivated(self._index, self._on_load_changed) self._lj.on_load_deactivated(self._index, self._on_load_changed)
self._lj.on_connected_changed(self._on_connected_changed)
async def async_will_remove_from_hass(self) -> None: async def async_will_remove_from_hass(self) -> None:
"""Entity being removed from hass.""" """Entity being removed from hass."""
self._lj.unsubscribe(self._on_load_changed) self._lj.unsubscribe(self._on_load_changed)
self._lj.unsubscribe(self._on_connected_changed)
def _on_load_changed(self, level) -> None: def _on_load_changed(self, level) -> None:
"""Handle state changes.""" """Handle state changes."""
_LOGGER.debug("Updating due to notification for %s", self.name) self.schedule_update_ha_state(True)
def _on_connected_changed(self, connected: bool, reason: str) -> None:
"""Handle connected changes."""
self.schedule_update_ha_state(True) self.schedule_update_ha_state(True)
async def async_turn_on(self, **kwargs: Any) -> None: async def async_turn_on(self, **kwargs: Any) -> None:
@ -83,7 +86,10 @@ class LiteJetLight(LightEntity):
# LiteJet API will use the per-light default brightness and # LiteJet API will use the per-light default brightness and
# transition values programmed in the LiteJet system. # transition values programmed in the LiteJet system.
if ATTR_BRIGHTNESS not in kwargs and ATTR_TRANSITION not in kwargs: if ATTR_BRIGHTNESS not in kwargs and ATTR_TRANSITION not in kwargs:
try:
await self._lj.activate_load(self._index) await self._lj.activate_load(self._index)
except LiteJetError as exc:
raise HomeAssistantError() from exc
return return
# If either attribute is specified then Home Assistant must # If either attribute is specified then Home Assistant must
@ -92,21 +98,35 @@ class LiteJetLight(LightEntity):
transition = kwargs.get(ATTR_TRANSITION, default_transition) transition = kwargs.get(ATTR_TRANSITION, default_transition)
brightness = int(kwargs.get(ATTR_BRIGHTNESS, 255) / 255 * 99) brightness = int(kwargs.get(ATTR_BRIGHTNESS, 255) / 255 * 99)
try:
await self._lj.activate_load_at(self._index, brightness, int(transition)) await self._lj.activate_load_at(self._index, brightness, int(transition))
except LiteJetError as exc:
raise HomeAssistantError() from exc
async def async_turn_off(self, **kwargs: Any) -> None: async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off the light.""" """Turn off the light."""
if ATTR_TRANSITION in kwargs: if ATTR_TRANSITION in kwargs:
try:
await self._lj.activate_load_at(self._index, 0, kwargs[ATTR_TRANSITION]) await self._lj.activate_load_at(self._index, 0, kwargs[ATTR_TRANSITION])
except LiteJetError as exc:
raise HomeAssistantError() from exc
return return
# If transition attribute is not specified then the simple # If transition attribute is not specified then the simple
# deactivate load LiteJet API will use the per-light default # deactivate load LiteJet API will use the per-light default
# transition value programmed in the LiteJet system. # transition value programmed in the LiteJet system.
try:
await self._lj.deactivate_load(self._index) await self._lj.deactivate_load(self._index)
except LiteJetError as exc:
raise HomeAssistantError() from exc
async def async_update(self) -> None: async def async_update(self) -> None:
"""Retrieve the light's brightness from the LiteJet system.""" """Retrieve the light's brightness from the LiteJet system."""
self._attr_available = self._lj.connected
if not self.available:
return
self._attr_brightness = int( self._attr_brightness = int(
await self._lj.get_load_level(self._index) / 99 * 255 await self._lj.get_load_level(self._index) / 99 * 255
) )

View File

@ -2,7 +2,7 @@
"domain": "litejet", "domain": "litejet",
"name": "LiteJet", "name": "LiteJet",
"documentation": "https://www.home-assistant.io/integrations/litejet", "documentation": "https://www.home-assistant.io/integrations/litejet",
"requirements": ["pylitejet==0.4.6"], "requirements": ["pylitejet==0.5.0"],
"codeowners": ["@joncar"], "codeowners": ["@joncar"],
"config_flow": true, "config_flow": true,
"iot_class": "local_push", "iot_class": "local_push",

View File

@ -1,15 +1,19 @@
"""Support for LiteJet scenes.""" """Support for LiteJet scenes."""
import logging
from typing import Any from typing import Any
from pylitejet import LiteJet from pylitejet import LiteJet, LiteJetError
from homeassistant.components.scene import Scene from homeassistant.components.scene import Scene
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
ATTR_NUMBER = "number" ATTR_NUMBER = "number"
@ -35,20 +39,22 @@ class LiteJetScene(Scene):
def __init__(self, entry_id, lj: LiteJet, i, name): # pylint: disable=invalid-name def __init__(self, entry_id, lj: LiteJet, i, name): # pylint: disable=invalid-name
"""Initialize the scene.""" """Initialize the scene."""
self._entry_id = entry_id
self._lj = lj self._lj = lj
self._index = i self._index = i
self._name = name self._attr_unique_id = f"{entry_id}_{i}"
self._attr_name = name
@property async def async_added_to_hass(self) -> None:
def name(self): """Run when this Entity has been added to HA."""
"""Return the name of the scene.""" self._lj.on_connected_changed(self._on_connected_changed)
return self._name
@property async def async_will_remove_from_hass(self) -> None:
def unique_id(self): """Entity being removed from hass."""
"""Return a unique identifier for this scene.""" self._lj.unsubscribe(self._on_connected_changed)
return f"{self._entry_id}_{self._index}"
def _on_connected_changed(self, connected: bool, reason: str) -> None:
self._attr_available = connected
self.schedule_update_ha_state()
@property @property
def extra_state_attributes(self): def extra_state_attributes(self):
@ -57,7 +63,10 @@ class LiteJetScene(Scene):
async def async_activate(self, **kwargs: Any) -> None: async def async_activate(self, **kwargs: Any) -> None:
"""Activate the scene.""" """Activate the scene."""
try:
await self._lj.activate_scene(self._index) await self._lj.activate_scene(self._index)
except LiteJetError as exc:
raise HomeAssistantError() from exc
@property @property
def entity_registry_enabled_default(self) -> bool: def entity_registry_enabled_default(self) -> bool:

View File

@ -1,20 +1,18 @@
"""Support for LiteJet switch.""" """Support for LiteJet switch."""
import logging
from typing import Any from typing import Any
from pylitejet import LiteJet from pylitejet import LiteJet, LiteJetError
from homeassistant.components.switch import SwitchEntity from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from .const import DOMAIN
ATTR_NUMBER = "number" ATTR_NUMBER = "number"
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
@ -43,44 +41,38 @@ class LiteJetSwitch(SwitchEntity):
self._entry_id = entry_id self._entry_id = entry_id
self._lj = lj self._lj = lj
self._index = i self._index = i
self._state = False self._attr_is_on = False
self._name = name self._attr_name = name
async def async_added_to_hass(self) -> None: async def async_added_to_hass(self) -> None:
"""Run when this Entity has been added to HA.""" """Run when this Entity has been added to HA."""
self._lj.on_switch_pressed(self._index, self._on_switch_pressed) self._lj.on_switch_pressed(self._index, self._on_switch_pressed)
self._lj.on_switch_released(self._index, self._on_switch_released) self._lj.on_switch_released(self._index, self._on_switch_released)
self._lj.on_connected_changed(self._on_connected_changed)
async def async_will_remove_from_hass(self) -> None: async def async_will_remove_from_hass(self) -> None:
"""Entity being removed from hass.""" """Entity being removed from hass."""
self._lj.unsubscribe(self._on_switch_pressed) self._lj.unsubscribe(self._on_switch_pressed)
self._lj.unsubscribe(self._on_switch_released) self._lj.unsubscribe(self._on_switch_released)
self._lj.unsubscribe(self._on_connected_changed)
def _on_switch_pressed(self): def _on_switch_pressed(self):
_LOGGER.debug("Updating pressed for %s", self._name) self._attr_is_on = True
self._state = True
self.schedule_update_ha_state() self.schedule_update_ha_state()
def _on_switch_released(self): def _on_switch_released(self):
_LOGGER.debug("Updating released for %s", self._name) self._attr_is_on = False
self._state = False
self.schedule_update_ha_state() self.schedule_update_ha_state()
@property def _on_connected_changed(self, connected: bool, reason: str) -> None:
def name(self): self._attr_available = connected
"""Return the name of the switch.""" self.schedule_update_ha_state()
return self._name
@property @property
def unique_id(self): def unique_id(self):
"""Return a unique identifier for this switch.""" """Return a unique identifier for this switch."""
return f"{self._entry_id}_{self._index}" return f"{self._entry_id}_{self._index}"
@property
def is_on(self):
"""Return if the switch is pressed."""
return self._state
@property @property
def extra_state_attributes(self): def extra_state_attributes(self):
"""Return the device-specific state attributes.""" """Return the device-specific state attributes."""
@ -88,11 +80,17 @@ class LiteJetSwitch(SwitchEntity):
async def async_turn_on(self, **kwargs: Any) -> None: async def async_turn_on(self, **kwargs: Any) -> None:
"""Press the switch.""" """Press the switch."""
try:
await self._lj.press_switch(self._index) await self._lj.press_switch(self._index)
except LiteJetError as exc:
raise HomeAssistantError() from exc
async def async_turn_off(self, **kwargs: Any) -> None: async def async_turn_off(self, **kwargs: Any) -> None:
"""Release the switch.""" """Release the switch."""
try:
await self._lj.release_switch(self._index) await self._lj.release_switch(self._index)
except LiteJetError as exc:
raise HomeAssistantError() from exc
@property @property
def entity_registry_enabled_default(self) -> bool: def entity_registry_enabled_default(self) -> bool:

View File

@ -1744,7 +1744,7 @@ pylgnetcast==0.3.7
pylibrespot-java==0.1.1 pylibrespot-java==0.1.1
# homeassistant.components.litejet # homeassistant.components.litejet
pylitejet==0.4.6 pylitejet==0.5.0
# homeassistant.components.litterrobot # homeassistant.components.litterrobot
pylitterbot==2023.1.1 pylitterbot==2023.1.1

View File

@ -1251,7 +1251,7 @@ pylaunches==1.3.0
pylibrespot-java==0.1.1 pylibrespot-java==0.1.1
# homeassistant.components.litejet # homeassistant.components.litejet
pylitejet==0.4.6 pylitejet==0.5.0
# homeassistant.components.litterrobot # homeassistant.components.litterrobot
pylitterbot==2023.1.1 pylitterbot==2023.1.1