Skip to content
This repository has been archived by the owner on Jul 7, 2022. It is now read-only.

Commit

Permalink
new package and in sync with PR
Browse files Browse the repository at this point in the history
  • Loading branch information
eavanvalkenburg committed Apr 12, 2021
1 parent 4bca204 commit ead83a5
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 50 deletions.
12 changes: 9 additions & 3 deletions custom_components/sia/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PORT
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady

from .const import DOMAIN
from .hub import SIAHub
Expand All @@ -24,16 +26,20 @@ async def async_setup(hass: HomeAssistant, config: dict):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Set up sia from a config entry."""
hub = SIAHub(hass, entry.data, entry.entry_id, entry.title)

await hub.async_setup_hub()

hass.data[DOMAIN][entry.entry_id] = hub
try:
await hub.sia_client.start(reuse_port=True)
except OSError:
raise ConfigEntryNotReady(
"SIA Server at port %s could not start.", entry.data[CONF_PORT]
)

for component in PLATFORMS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)

await hub.sia_client.start(reuse_port=True)
return True


Expand Down
23 changes: 15 additions & 8 deletions custom_components/sia/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
DOMAIN,
PING_INTERVAL_MARGIN,
)
from .helpers import GET_ENTITY_AND_NAME, GET_PING_INTERVAL, SIA_EVENT_TO_ATTR
from .utils import get_entity_and_name, get_ping_interval, sia_event_to_attr

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -81,7 +81,7 @@ async def async_setup_entry(
async_add_entities(
[
SIAAlarmControlPanel(
*GET_ENTITY_AND_NAME(
*get_entity_and_name(
entry.data[CONF_PORT], acc[CONF_ACCOUNT], zone, DEVICE_CLASS_ALARM
),
entry.data[CONF_PORT],
Expand Down Expand Up @@ -115,7 +115,7 @@ def __init__(
self._port = port
self._account = account
self._zone = zone
self._ping_interval = GET_PING_INTERVAL(ping_interval)
self._ping_interval = get_ping_interval(ping_interval)
self._event_listener_str = f"{SIA_EVENT}_{port}_{account}"
self._unsub = None

Expand Down Expand Up @@ -159,11 +159,18 @@ async def async_added_to_hass(self):
self.state = state.state
else:
self.state = None
await self._async_track_unavailable()
async_dispatcher_connect(self.hass, DATA_UPDATED, self.async_write_ha_state)
self._unsub = self.hass.bus.async_listen(
self._event_listener_str, self.async_handle_event
)
self.setup_sia_alarm()

def setup_sia_alarm(self):
"""Run the setup of the alarm control panel."""
self.assume_available()
self._unsub = self.hass.bus.async_listen(
self._event_listener_str, self.async_handle_event
)
self.async_on_remove(self._async_sia_on_remove)

@callback
Expand All @@ -186,7 +193,7 @@ async def async_handle_event(self, event: Event):
new_state = CODE_CONSEQUENCES.get(sia_event.code)
if not new_state:
return
self._attr.update(SIA_EVENT_TO_ATTR(sia_event))
self._attr.update(sia_event_to_attr(sia_event))
self.state = new_state
if self.enabled:
self.async_schedule_update_ha_state()
Expand Down Expand Up @@ -238,13 +245,13 @@ def should_poll(self) -> bool:
"""Return False if entity pushes its state to HA."""
return False

async def assume_available(self):
def assume_available(self):
"""Reset unavalability tracker."""
if not self.registry_entry.disabled:
await self._async_track_unavailable()
self._async_track_unavailable()

@callback
async def _async_track_unavailable(self) -> bool:
def _async_track_unavailable(self) -> bool:
"""Reset unavailability."""
if self._remove_unavailability_tracker:
self._remove_unavailability_tracker()
Expand Down
27 changes: 17 additions & 10 deletions custom_components/sia/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
PING_INTERVAL_MARGIN,
SIA_EVENT,
)
from .helpers import GET_ENTITY_AND_NAME, GET_PING_INTERVAL, SIA_EVENT_TO_ATTR
from .utils import get_entity_and_name, get_ping_interval, sia_event_to_attr

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -67,7 +67,7 @@ async def async_setup_entry(

devices = [
SIABinarySensor(
*GET_ENTITY_AND_NAME(
*get_entity_and_name(
entry.data[CONF_PORT], acc[CONF_ACCOUNT], zone, device_class
),
entry.data[CONF_PORT],
Expand All @@ -83,7 +83,7 @@ async def async_setup_entry(
devices.extend(
[
SIABinarySensor(
*GET_ENTITY_AND_NAME(
*get_entity_and_name(
entry.data[CONF_PORT],
acc[CONF_ACCOUNT],
HUB_ZONE,
Expand Down Expand Up @@ -123,7 +123,7 @@ def __init__(
self._port = port
self._account = account
self._zone = zone
self._ping_interval = GET_PING_INTERVAL(ping_interval)
self._ping_interval = get_ping_interval(ping_interval)
self._event_listener_str = f"{SIA_EVENT}_{port}_{account}"
self._unsub = None

Expand Down Expand Up @@ -151,11 +151,18 @@ async def async_added_to_hass(self):
self._is_on = True
elif state.state == STATE_OFF:
self._is_on = False
await self._async_track_unavailable()
async_dispatcher_connect(self.hass, DATA_UPDATED, self.async_write_ha_state)
self._unsub = self.hass.bus.async_listen(
self._event_listener_str, self.async_handle_event
)
self.setup_sia_entity()

def setup_sia_entity(self):
"""Run the setup of the alarm control panel."""
self.assume_available()
self._unsub = self.hass.bus.async_listen(
self._event_listener_str, self.async_handle_event
)
self.async_on_remove(self._async_sia_on_remove)

@callback
Expand All @@ -171,15 +178,15 @@ async def async_handle_event(self, event: Event):
If the port and account combo receives any message it means it is online and can therefore be set to available.
"""
await self.assume_available()
self.assume_available()
sia_event = SIAEvent.from_dict(event.data)
sia_event.message_type = sia_event.message_type.value
if int(sia_event.ri) == self._zone or self._device_class == DEVICE_CLASS_POWER:
device_class, new_state = CODE_CONSEQUENCES.get(
sia_event.code, (None, None)
)
if new_state is not None and device_class == self._device_class:
self._attr.update(SIA_EVENT_TO_ATTR(sia_event))
self._attr.update(sia_event_to_attr(sia_event))
self.state = new_state
if self.enabled:
self.async_schedule_update_ha_state()
Expand Down Expand Up @@ -241,13 +248,13 @@ def state(self, new_on: bool):
"""Set state."""
self._is_on = new_on

async def assume_available(self):
def assume_available(self):
"""Reset unavalability tracker."""
if not self.registry_entry.disabled:
await self._async_track_unavailable()
self._async_track_unavailable()

@callback
async def _async_track_unavailable(self) -> bool:
def _async_track_unavailable(self) -> bool:
"""Track availability."""
if self._remove_unavailability_tracker:
self._remove_unavailability_tracker()
Expand Down
7 changes: 1 addition & 6 deletions custom_components/sia/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,8 @@ async def async_shutdown(self, _: Event = None):

async def async_create_and_fire_event(self, event: SIAEvent):
"""Create a event on HA's bus, with the data from the SIAEvent."""
# Get rid of account, because it might contain encryption key.
event.sia_account = None
# Change the message_type to value because otherwise it is not JSON serializable.
event.message_type = event.message_type.value
# Fire event!
self._hass.bus.async_fire(
event_type=f"{SIA_EVENT}_{self._port}_{event.account}",
event_data=event.to_dict(),
event_data=event.to_dict(encode_json=True),
origin=EventOrigin.remote,
)
4 changes: 2 additions & 2 deletions custom_components/sia/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/sia",
"requirements": [
"pysiaalarm==3.0.0b3"
"pysiaalarm==3.0.0b4"
],
"codeowners": [
"@eavanvalkenburg"
],
"version": "0.5.0b1"
"version": "0.5.0b2"
}
16 changes: 11 additions & 5 deletions custom_components/sia/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
HUB_ZONE,
SIA_EVENT,
)
from .helpers import GET_ENTITY_AND_NAME, GET_PING_INTERVAL, SIA_EVENT_TO_ATTR
from .utils import get_entity_and_name, get_ping_interval

_LOGGER = logging.getLogger(__name__)

Expand All @@ -33,7 +33,7 @@ async def async_setup_entry(
async_add_entities(
[
SIASensor(
*GET_ENTITY_AND_NAME(
*get_entity_and_name(
entry.data[CONF_PORT],
acc[CONF_ACCOUNT],
HUB_ZONE,
Expand Down Expand Up @@ -72,7 +72,7 @@ def __init__(
self._port = port
self._account = account
self._zone = zone
self._ping_interval = GET_PING_INTERVAL(ping_interval)
self._ping_interval = get_ping_interval(ping_interval)
self._event_listener_str = f"{SIA_EVENT}_{port}_{account}"
self._unsub = None

Expand All @@ -94,6 +94,13 @@ async def async_added_to_hass(self) -> None:
self._unsub = self.hass.bus.async_listen(
self._event_listener_str, self.async_handle_event
)
self.setup_sia_entity()

def setup_sia_entity(self):
"""Run the setup of the sensor."""
self._unsub = self.hass.bus.async_listen(
self._event_listener_str, self.async_handle_event
)
self.async_on_remove(self._async_sia_on_remove)

@callback
Expand All @@ -105,8 +112,7 @@ def _async_sia_on_remove(self):
async def async_handle_event(self, event: Event):
"""Listen to events for this port and account and update the state and attributes."""
sia_event = SIAEvent.from_dict(event.data)
sia_event.message_type = sia_event.message_type.value
self._attr.update(sia_event.to_dict())
self._attr.update(event.data)
if sia_event.code == "RP":
self.state = utcnow()
if self.enabled:
Expand Down
30 changes: 14 additions & 16 deletions custom_components/sia/helpers.py → custom_components/sia/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
)


def GET_ENTITY_AND_NAME(
def get_entity_and_name(
port: int, account: str, zone: int = 0, entity_type: str = None
) -> Tuple[str, str]:
"""Give back a entity_id and name according to the variables."""
Expand All @@ -25,23 +25,23 @@ def GET_ENTITY_AND_NAME(
"Last Heartbeat" if entity_type == DEVICE_CLASS_TIMESTAMP else "Power"
)
return (
GET_ENTITY_ID(port, account, zone, entity_type),
get_entity_id(port, account, zone, entity_type),
f"{port} - {account} - {entity_type_name}",
)
if entity_type:
return (
GET_ENTITY_ID(port, account, zone, entity_type),
get_entity_id(port, account, zone, entity_type),
f"{port} - {account} - zone {zone} - {entity_type}",
)
return None


def GET_PING_INTERVAL(ping: int) -> timedelta:
def get_ping_interval(ping: int) -> timedelta:
"""Return the ping interval as timedelta."""
return timedelta(minutes=ping)


def GET_ENTITY_ID(
def get_entity_id(
port: int, account: str, zone: int = 0, entity_type: str = None
) -> str:
"""Give back a entity_id according to the variables, defaults to the hub sensor entity_id."""
Expand All @@ -54,15 +54,13 @@ def GET_ENTITY_ID(
return None


def SIA_EVENT_TO_ATTR(event: SIAEvent) -> dict:
def sia_event_to_attr(event: SIAEvent) -> dict:
"""Create the attributes dict from a SIAEvent."""
return (
{
EVENT_ACCOUNT: event.account,
EVENT_ZONE: event.ri,
EVENT_CODE: event.code,
EVENT_MESSAGE: event.message,
EVENT_ID: event.id,
EVENT_TIMESTAMP: event.timestamp,
}
)
return {
EVENT_ACCOUNT: event.account,
EVENT_ZONE: event.ri,
EVENT_CODE: event.code,
EVENT_MESSAGE: event.message,
EVENT_ID: event.id,
EVENT_TIMESTAMP: event.timestamp,
}

0 comments on commit ead83a5

Please sign in to comment.