Fix initialization and add "pending" status of Satel integra (#21194)

* Added updating alarm state after start of the HA. Still rough and dirty.

* Fixed initialization of the panel and binary sensor.  Before cleanup.

* Added alarm clearing, linting fixes.

* Removed dead code, added style changes.

* Updated requirements

* Fixed linting errors.

* Fixed linting errors

* Fixed linter errors.

* Fixed hopefully last linter errors.

* Fixes after code review, imports sorted.

* Removed init debugging
This commit is contained in:
c-soft 2019-03-07 04:47:47 +01:00 committed by Paulus Schoutsen
parent 9f06be750f
commit f4a9ad0b2e
4 changed files with 102 additions and 54 deletions

View File

@ -1,19 +1,15 @@
"""Support for Satel Integra devices.""" """Support for Satel Integra devices."""
import asyncio
import logging import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_ALARM_TRIGGERED, EVENT_HOMEASSISTANT_STOP)
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.discovery import async_load_platform from homeassistant.helpers.discovery import async_load_platform
from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.dispatcher import async_dispatcher_send
REQUIREMENTS = ['satel_integra==0.2.0'] REQUIREMENTS = ['satel_integra==0.3.2']
DEFAULT_ALARM_NAME = 'satel_integra' DEFAULT_ALARM_NAME = 'satel_integra'
DEFAULT_PORT = 7094 DEFAULT_PORT = 7094
@ -76,7 +72,7 @@ async def async_setup(hass, config):
port = conf.get(CONF_DEVICE_PORT) port = conf.get(CONF_DEVICE_PORT)
partition = conf.get(CONF_DEVICE_PARTITION) partition = conf.get(CONF_DEVICE_PARTITION)
from satel_integra.satel_integra import AsyncSatel, AlarmState from satel_integra.satel_integra import AsyncSatel
controller = AsyncSatel(host, port, hass.loop, zones, outputs, partition) controller = AsyncSatel(host, port, hass.loop, zones, outputs, partition)
@ -96,41 +92,19 @@ async def async_setup(hass, config):
conf, conf,
conf.get(CONF_ARM_HOME_MODE)) conf.get(CONF_ARM_HOME_MODE))
task_control_panel = hass.async_create_task( hass.async_create_task(
async_load_platform(hass, 'alarm_control_panel', DOMAIN, conf, config)) async_load_platform(hass, 'alarm_control_panel', DOMAIN, conf, config))
task_zones = hass.async_create_task( hass.async_create_task(
async_load_platform(hass, 'binary_sensor', DOMAIN, async_load_platform(hass, 'binary_sensor', DOMAIN,
{CONF_ZONES: zones, CONF_OUTPUTS: outputs}, config) {CONF_ZONES: zones, CONF_OUTPUTS: outputs}, config)
) )
await asyncio.wait([task_control_panel, task_zones], loop=hass.loop)
@callback @callback
def alarm_status_update_callback(status): def alarm_status_update_callback():
"""Send status update received from alarm to home assistant.""" """Send status update received from alarm to home assistant."""
_LOGGER.debug("Alarm status callback, status: %s", status) _LOGGER.debug("Sending request to update panel state")
hass_alarm_status = STATE_ALARM_DISARMED async_dispatcher_send(hass, SIGNAL_PANEL_MESSAGE)
if status == AlarmState.ARMED_MODE0:
hass_alarm_status = STATE_ALARM_ARMED_AWAY
elif status in [
AlarmState.ARMED_MODE0,
AlarmState.ARMED_MODE1,
AlarmState.ARMED_MODE2,
AlarmState.ARMED_MODE3
]:
hass_alarm_status = STATE_ALARM_ARMED_HOME
elif status in [AlarmState.TRIGGERED, AlarmState.TRIGGERED_FIRE]:
hass_alarm_status = STATE_ALARM_TRIGGERED
elif status == AlarmState.DISARMED:
hass_alarm_status = STATE_ALARM_DISARMED
_LOGGER.debug("Sending hass_alarm_status: %s...", hass_alarm_status)
async_dispatcher_send(hass, SIGNAL_PANEL_MESSAGE, hass_alarm_status)
@callback @callback
def zones_update_callback(status): def zones_update_callback(status):

View File

@ -1,12 +1,19 @@
"""Support for Satel Integra alarm, using ETHM module.""" """Support for Satel Integra alarm, using ETHM module."""
import asyncio
import logging import logging
from collections import OrderedDict
import homeassistant.components.alarm_control_panel as alarm import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.satel_integra import ( from homeassistant.const import (
CONF_ARM_HOME_MODE, DATA_SATEL, SIGNAL_PANEL_MESSAGE) STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED)
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from . import (
CONF_ARM_HOME_MODE, CONF_DEVICE_PARTITION, DATA_SATEL,
SIGNAL_PANEL_MESSAGE)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['satel_integra'] DEPENDENCIES = ['satel_integra']
@ -19,32 +26,73 @@ async def async_setup_platform(
return return
device = SatelIntegraAlarmPanel( device = SatelIntegraAlarmPanel(
"Alarm Panel", discovery_info.get(CONF_ARM_HOME_MODE)) "Alarm Panel",
discovery_info.get(CONF_ARM_HOME_MODE),
discovery_info.get(CONF_DEVICE_PARTITION))
async_add_entities([device]) async_add_entities([device])
class SatelIntegraAlarmPanel(alarm.AlarmControlPanel): class SatelIntegraAlarmPanel(alarm.AlarmControlPanel):
"""Representation of an AlarmDecoder-based alarm panel.""" """Representation of an AlarmDecoder-based alarm panel."""
def __init__(self, name, arm_home_mode): def __init__(self, name, arm_home_mode, partition_id):
"""Initialize the alarm panel.""" """Initialize the alarm panel."""
self._name = name self._name = name
self._state = None self._state = None
self._arm_home_mode = arm_home_mode self._arm_home_mode = arm_home_mode
self._partition_id = partition_id
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""Register callbacks.""" """Update alarm status and register callbacks for future updates."""
_LOGGER.debug("Starts listening for panel messages")
self._update_alarm_status()
async_dispatcher_connect( async_dispatcher_connect(
self.hass, SIGNAL_PANEL_MESSAGE, self._message_callback) self.hass, SIGNAL_PANEL_MESSAGE, self._update_alarm_status)
@callback @callback
def _message_callback(self, message): def _update_alarm_status(self):
"""Handle received messages.""" """Handle alarm status update."""
if message != self._state: state = self._read_alarm_state()
self._state = message _LOGGER.debug("Got status update, current status: %s", state)
if state != self._state:
self._state = state
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
else: else:
_LOGGER.warning("Ignoring alarm status message, same state") _LOGGER.debug("Ignoring alarm status message, same state")
def _read_alarm_state(self):
"""Read current status of the alarm and translate it into HA status."""
from satel_integra.satel_integra import AlarmState
# Default - disarmed:
hass_alarm_status = STATE_ALARM_DISARMED
satel_controller = self.hass.data[DATA_SATEL]
if not satel_controller.connected:
return None
state_map = OrderedDict([
(AlarmState.TRIGGERED, STATE_ALARM_TRIGGERED),
(AlarmState.TRIGGERED_FIRE, STATE_ALARM_TRIGGERED),
(AlarmState.ARMED_MODE3, STATE_ALARM_ARMED_HOME),
(AlarmState.ARMED_MODE2, STATE_ALARM_ARMED_HOME),
(AlarmState.ARMED_MODE1, STATE_ALARM_ARMED_HOME),
(AlarmState.ARMED_MODE0, STATE_ALARM_ARMED_AWAY),
(AlarmState.EXIT_COUNTDOWN_OVER_10, STATE_ALARM_PENDING),
(AlarmState.EXIT_COUNTDOWN_UNDER_10, STATE_ALARM_PENDING)
])
_LOGGER.debug("State map of Satel: %s",
satel_controller.partition_states)
for satel_state, ha_state in state_map.items():
if satel_state in satel_controller.partition_states and\
self._partition_id in\
satel_controller.partition_states[satel_state]:
hass_alarm_status = ha_state
break
return hass_alarm_status
@property @property
def name(self): def name(self):
@ -68,16 +116,32 @@ class SatelIntegraAlarmPanel(alarm.AlarmControlPanel):
async def async_alarm_disarm(self, code=None): async def async_alarm_disarm(self, code=None):
"""Send disarm command.""" """Send disarm command."""
if code: if not code:
_LOGGER.debug("Code was empty or None")
return
clear_alarm_necessary = self._state == STATE_ALARM_TRIGGERED
_LOGGER.debug("Disarming, self._state: %s", self._state)
await self.hass.data[DATA_SATEL].disarm(code) await self.hass.data[DATA_SATEL].disarm(code)
if clear_alarm_necessary:
# Wait 1s before clearing the alarm
await asyncio.sleep(1)
await self.hass.data[DATA_SATEL].clear_alarm(code)
async def async_alarm_arm_away(self, code=None): async def async_alarm_arm_away(self, code=None):
"""Send arm away command.""" """Send arm away command."""
_LOGGER.debug("Arming away")
if code: if code:
await self.hass.data[DATA_SATEL].arm(code) await self.hass.data[DATA_SATEL].arm(code)
async def async_alarm_arm_home(self, code=None): async def async_alarm_arm_home(self, code=None):
"""Send arm home command.""" """Send arm home command."""
_LOGGER.debug("Arming home")
if code: if code:
await self.hass.data[DATA_SATEL].arm( await self.hass.data[DATA_SATEL].arm(
code, self._arm_home_mode) code, self._arm_home_mode)

View File

@ -2,15 +2,13 @@
import logging import logging
from homeassistant.components.binary_sensor import BinarySensorDevice from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.satel_integra import (CONF_ZONES,
CONF_OUTPUTS,
CONF_ZONE_NAME,
CONF_ZONE_TYPE,
SIGNAL_ZONES_UPDATED,
SIGNAL_OUTPUTS_UPDATED)
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from . import (
CONF_OUTPUTS, CONF_ZONE_NAME, CONF_ZONE_TYPE, CONF_ZONES, DATA_SATEL,
SIGNAL_OUTPUTS_UPDATED, SIGNAL_ZONES_UPDATED)
DEPENDENCIES = ['satel_integra'] DEPENDENCIES = ['satel_integra']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -58,6 +56,18 @@ class SatelIntegraBinarySensor(BinarySensorDevice):
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""Register callbacks.""" """Register callbacks."""
if self._react_to_signal == SIGNAL_OUTPUTS_UPDATED:
if self._device_number in\
self.hass.data[DATA_SATEL].violated_outputs:
self._state = 1
else:
self._state = 0
else:
if self._device_number in\
self.hass.data[DATA_SATEL].violated_zones:
self._state = 1
else:
self._state = 0
async_dispatcher_connect( async_dispatcher_connect(
self.hass, self._react_to_signal, self._devices_updated) self.hass, self._react_to_signal, self._devices_updated)

View File

@ -1532,7 +1532,7 @@ rxv==0.6.0
samsungctl[websocket]==0.7.1 samsungctl[websocket]==0.7.1
# homeassistant.components.satel_integra # homeassistant.components.satel_integra
satel_integra==0.2.0 satel_integra==0.3.2
# homeassistant.components.sensor.deutsche_bahn # homeassistant.components.sensor.deutsche_bahn
schiene==0.22 schiene==0.22