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

Commit

Permalink
update to latest version of package, improvements in code
Browse files Browse the repository at this point in the history
  • Loading branch information
eavanvalkenburg committed Apr 7, 2021
1 parent 5ed2895 commit 4bca204
Show file tree
Hide file tree
Showing 12 changed files with 170 additions and 202 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ debugpy:
logger:
default: info
logs:
custom_components.sia: debug
custom_components.sia: debug
6 changes: 4 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true
}
"files.trimTrailingWhitespace": true,
"remote.autoForwardPorts": false
},
"forwardPorts": [5678, 8126]
}
7 changes: 3 additions & 4 deletions custom_components/sia/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
"""The sia integration."""
import asyncio

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.components.alarm_control_panel import (
DOMAIN as ALARM_CONTROL_PANEL_DOMAIN,
)
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.core import HomeAssistant

from .const import DOMAIN
from .hub import SIAHub


PLATFORMS = [ALARM_CONTROL_PANEL_DOMAIN, BINARY_SENSOR_DOMAIN, SENSOR_DOMAIN]


Expand All @@ -34,7 +33,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
hass.config_entries.async_forward_entry_setup(entry, component)
)

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


Expand Down
71 changes: 32 additions & 39 deletions custom_components/sia/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import logging
from typing import Callable
from pysiaalarm import SIAEvent

from homeassistant.components.alarm_control_panel import (
ENTITY_ID_FORMAT as ALARM_FORMAT,
Expand All @@ -25,23 +26,22 @@
from homeassistant.util.dt import utcnow

from .const import (
ATTR_LAST_CODE,
ATTR_LAST_MESSAGE,
ATTR_LAST_TIMESTAMP,
CONF_ACCOUNT,
CONF_ACCOUNTS,
CONF_PING_INTERVAL,
CONF_ZONES,
DATA_UPDATED,
EVENT_ACCOUNT,
EVENT_CODE,
EVENT_ID,
EVENT_ZONE,
EVENT_MESSAGE,
EVENT_TIMESTAMP,
SIA_EVENT,
DOMAIN,
PING_INTERVAL_MARGIN,
)
from .helpers import GET_ENTITY_AND_NAME, GET_PING_INTERVAL
from .helpers import GET_ENTITY_AND_NAME, GET_PING_INTERVAL, SIA_EVENT_TO_ATTR

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -75,10 +75,10 @@


async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_devices: Callable[[], None]
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: Callable[[], None]
) -> bool:
"""Set up SIA alarm_control_panel(s) from a config entry."""
async_add_devices(
async_add_entities(
[
SIAAlarmControlPanel(
*GET_ENTITY_AND_NAME(
Expand Down Expand Up @@ -119,7 +119,6 @@ def __init__(
self._event_listener_str = f"{SIA_EVENT}_{port}_{account}"
self._unsub = None

self._should_poll = False
self._is_available = True
self._remove_unavailability_tracker = None
self._state = None
Expand All @@ -128,9 +127,12 @@ def __init__(
CONF_ACCOUNT: self._account,
CONF_PING_INTERVAL: self.ping_interval,
CONF_ZONE: self._zone,
ATTR_LAST_MESSAGE: None,
ATTR_LAST_CODE: None,
ATTR_LAST_TIMESTAMP: None,
EVENT_ACCOUNT: None,
EVENT_CODE: None,
EVENT_ID: None,
EVENT_ZONE: None,
EVENT_MESSAGE: None,
EVENT_TIMESTAMP: None,
}

async def async_added_to_hass(self):
Expand Down Expand Up @@ -158,16 +160,14 @@ async def async_added_to_hass(self):
else:
self.state = None
await self._async_track_unavailable()
async_dispatcher_connect(
self.hass, DATA_UPDATED, self._schedule_immediate_update
)
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.async_on_remove(self._sia_on_remove)
self.async_on_remove(self._async_sia_on_remove)

@callback
def _sia_on_remove(self):
def _async_sia_on_remove(self):
"""Remove the unavailability and event listener."""
if self._unsub:
self._unsub()
Expand All @@ -180,23 +180,16 @@ 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()
if int(event.data[EVENT_ZONE]) == self._zone:
new_state = CODE_CONSEQUENCES.get(event.data[EVENT_CODE])
if new_state:
self._attr.update(
{
ATTR_LAST_MESSAGE: event.data[EVENT_MESSAGE],
ATTR_LAST_CODE: event.data[EVENT_CODE],
ATTR_LAST_TIMESTAMP: event.data[EVENT_TIMESTAMP],
}
)
self.state = new_state
if not self.registry_entry.disabled:
self.async_schedule_update_ha_state()

@callback
def _schedule_immediate_update(self):
self.async_schedule_update_ha_state(True)
sia_event = SIAEvent.from_dict(event.data)
if int(sia_event.ri) != self._zone:
return
new_state = CODE_CONSEQUENCES.get(sia_event.code)
if not new_state:
return
self._attr.update(SIA_EVENT_TO_ATTR(sia_event))
self.state = new_state
if self.enabled:
self.async_schedule_update_ha_state()

@property
def name(self) -> str:
Expand All @@ -213,6 +206,13 @@ def state(self) -> str:
"""Get state."""
return self._state

@state.setter
def state(self, state: str):
"""Set state."""
temp = self._old_state if state == PREVIOUS_STATE else state
self._old_state = self._state
self._state = temp

@property
def account(self) -> str:
"""Return device account."""
Expand All @@ -238,13 +238,6 @@ def should_poll(self) -> bool:
"""Return False if entity pushes its state to HA."""
return False

@state.setter
def state(self, state: str):
"""Set state."""
temp = self._old_state if state == PREVIOUS_STATE else state
self._old_state = self._state
self._state = temp

async def assume_available(self):
"""Reset unavalability tracker."""
if not self.registry_entry.disabled:
Expand Down
66 changes: 28 additions & 38 deletions custom_components/sia/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,41 @@
from typing import Callable

from homeassistant.components.binary_sensor import (
ENTITY_ID_FORMAT as BINARY_SENSOR_FORMAT,
BinarySensorEntity,
DEVICE_CLASS_MOISTURE,
DEVICE_CLASS_POWER,
DEVICE_CLASS_SMOKE,
)
from homeassistant.components.binary_sensor import (
ENTITY_ID_FORMAT as BINARY_SENSOR_FORMAT,
)
from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PORT, CONF_ZONE, STATE_OFF, STATE_ON, STATE_UNKNOWN
from homeassistant.core import HomeAssistant, callback, Event
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.util.dt import utcnow
from pysiaalarm import SIAEvent

from .const import (
ATTR_LAST_CODE,
ATTR_LAST_MESSAGE,
ATTR_LAST_TIMESTAMP,
CONF_ACCOUNT,
CONF_ACCOUNTS,
CONF_PING_INTERVAL,
CONF_ZONES,
DATA_UPDATED,
DOMAIN,
EVENT_ACCOUNT,
EVENT_CODE,
EVENT_ID,
EVENT_ZONE,
EVENT_MESSAGE,
EVENT_TIMESTAMP,
HUB_ZONE,
SIA_EVENT,
DOMAIN,
PING_INTERVAL_MARGIN,
SIA_EVENT,
)
from .helpers import GET_ENTITY_AND_NAME, GET_PING_INTERVAL
from .helpers import GET_ENTITY_AND_NAME, GET_PING_INTERVAL, SIA_EVENT_TO_ATTR

_LOGGER = logging.getLogger(__name__)

Expand All @@ -59,7 +61,7 @@


async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_devices: Callable[[], None]
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: Callable[[], None]
) -> bool:
"""Set up sia_binary_sensor from a config entry."""

Expand Down Expand Up @@ -96,7 +98,7 @@ async def async_setup_entry(
for acc in entry.data[CONF_ACCOUNTS]
]
)
async_add_devices(devices)
async_add_entities(devices)
return True


Expand Down Expand Up @@ -125,17 +127,19 @@ def __init__(
self._event_listener_str = f"{SIA_EVENT}_{port}_{account}"
self._unsub = None

self._should_poll = False
self._is_on = None
self._is_available = True
self._remove_unavailability_tracker = None
self._attr = {
CONF_ACCOUNT: self._account,
CONF_PING_INTERVAL: self.ping_interval,
CONF_ZONE: self._zone,
ATTR_LAST_MESSAGE: None,
ATTR_LAST_CODE: None,
ATTR_LAST_TIMESTAMP: None,
EVENT_ACCOUNT: None,
EVENT_CODE: None,
EVENT_ID: None,
EVENT_ZONE: None,
EVENT_MESSAGE: None,
EVENT_TIMESTAMP: None,
}

async def async_added_to_hass(self):
Expand All @@ -148,50 +152,36 @@ async def async_added_to_hass(self):
elif state.state == STATE_OFF:
self._is_on = False
await self._async_track_unavailable()
async_dispatcher_connect(
self.hass, DATA_UPDATED, self._schedule_immediate_update
)
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.async_on_remove(self._sia_on_remove)
self.async_on_remove(self._async_sia_on_remove)

@callback
def _sia_on_remove(self):
def _async_sia_on_remove(self):
"""Remove the unavailability and event listener."""
if self._unsub:
self._unsub()
if self._remove_unavailability_tracker:
self._remove_unavailability_tracker()

@callback
def _schedule_immediate_update(self):
"""Schedule update."""
self.async_schedule_update_ha_state(True)

async def async_handle_event(self, event: Event):
"""Listen to events for this port and account and update states.
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()
if (
int(event.data[EVENT_ZONE]) == self._zone
or self._device_class == DEVICE_CLASS_POWER
):
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(
event.data[EVENT_CODE], (None, None)
sia_event.code, (None, None)
)
if new_state is not None and device_class == self._device_class:
self._attr.update(
{
ATTR_LAST_MESSAGE: event.data[EVENT_MESSAGE],
ATTR_LAST_CODE: event.data[EVENT_CODE],
ATTR_LAST_TIMESTAMP: event.data[EVENT_TIMESTAMP],
}
)
self._attr.update(SIA_EVENT_TO_ATTR(sia_event))
self.state = new_state
if not self.registry_entry.disabled:
if self.enabled:
self.async_schedule_update_ha_state()

@property
Expand Down
Loading

0 comments on commit 4bca204

Please sign in to comment.