core/homeassistant/components/alarm_control_panel/egardia.py

218 lines
7.5 KiB
Python

"""
Interfaces with Egardia/Woonveilig alarm control panel.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.egardia/
"""
import logging
import requests
import voluptuous as vol
import homeassistant.components.alarm_control_panel as alarm
import homeassistant.exceptions as exc
import homeassistant.helpers.config_validation as cv
from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.const import (
CONF_PORT, CONF_HOST, CONF_PASSWORD, CONF_USERNAME, STATE_UNKNOWN,
CONF_NAME, STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_TRIGGERED, EVENT_HOMEASSISTANT_STOP)
REQUIREMENTS = ['pythonegardia==1.0.26']
_LOGGER = logging.getLogger(__name__)
CONF_REPORT_SERVER_CODES = 'report_server_codes'
CONF_REPORT_SERVER_ENABLED = 'report_server_enabled'
CONF_REPORT_SERVER_PORT = 'report_server_port'
CONF_REPORT_SERVER_CODES_IGNORE = 'ignore'
CONF_VERSION = 'version'
DEFAULT_NAME = 'Egardia'
DEFAULT_PORT = 80
DEFAULT_REPORT_SERVER_ENABLED = False
DEFAULT_REPORT_SERVER_PORT = 52010
DEFAULT_VERSION = 'GATE-01'
DOMAIN = 'egardia'
D_EGARDIASRV = 'egardiaserver'
NOTIFICATION_ID = 'egardia_notification'
NOTIFICATION_TITLE = 'Egardia'
STATES = {
'ARM': STATE_ALARM_ARMED_AWAY,
'DAY HOME': STATE_ALARM_ARMED_HOME,
'DISARM': STATE_ALARM_DISARMED,
'HOME': STATE_ALARM_ARMED_HOME,
'TRIGGERED': STATE_ALARM_TRIGGERED,
'UNKNOWN': STATE_UNKNOWN,
}
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Optional(CONF_VERSION, default=DEFAULT_VERSION): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_REPORT_SERVER_CODES): vol.All(cv.ensure_list),
vol.Optional(CONF_REPORT_SERVER_ENABLED,
default=DEFAULT_REPORT_SERVER_ENABLED): cv.boolean,
vol.Optional(CONF_REPORT_SERVER_PORT, default=DEFAULT_REPORT_SERVER_PORT):
cv.port,
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Egardia platform."""
from pythonegardia import egardiadevice
from pythonegardia import egardiaserver
name = config.get(CONF_NAME)
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
host = config.get(CONF_HOST)
port = config.get(CONF_PORT)
rs_enabled = config.get(CONF_REPORT_SERVER_ENABLED)
rs_port = config.get(CONF_REPORT_SERVER_PORT)
rs_codes = config.get(CONF_REPORT_SERVER_CODES)
version = config.get(CONF_VERSION)
try:
egardiasystem = egardiadevice.EgardiaDevice(
host, port, username, password, '', version)
except requests.exceptions.RequestException:
raise exc.PlatformNotReady()
except egardiadevice.UnauthorizedError:
_LOGGER.error("Unable to authorize. Wrong password or username")
return
eg_dev = EgardiaAlarm(
name, egardiasystem, rs_enabled, rs_codes)
if rs_enabled:
# Set up the egardia server
_LOGGER.info("Setting up EgardiaServer")
try:
if D_EGARDIASRV not in hass.data:
server = egardiaserver.EgardiaServer('', rs_port)
bound = server.bind()
if not bound:
raise IOError("Binding error occurred while " +
"starting EgardiaServer")
hass.data[D_EGARDIASRV] = server
server.start()
except IOError:
return
hass.data[D_EGARDIASRV].register_callback(eg_dev.handle_status_event)
def handle_stop_event(event):
"""Callback function for HA stop event."""
hass.data[D_EGARDIASRV].stop()
# listen to home assistant stop event
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, handle_stop_event)
# add egardia alarm device
add_devices([eg_dev], True)
class EgardiaAlarm(alarm.AlarmControlPanel):
"""Representation of a Egardia alarm."""
def __init__(self, name, egardiasystem,
rs_enabled=False, rs_codes=None):
"""Initialize object."""
self._name = name
self._egardiasystem = egardiasystem
self._status = None
self._rs_enabled = rs_enabled
if rs_codes is not None:
self._rs_codes = rs_codes[0]
else:
self._rs_codes = rs_codes
@property
def name(self):
"""Return the name of the device."""
return self._name
@property
def state(self):
"""Return the state of the device."""
return self._status
@property
def should_poll(self):
"""Poll if no report server is enabled."""
if not self._rs_enabled:
return True
return False
def handle_status_event(self, event):
"""Handle egardia_system_status_event."""
statuscode = event.get('status')
if statuscode is not None:
status = self.lookupstatusfromcode(statuscode)
self.parsestatus(status)
self.schedule_update_ha_state()
def lookupstatusfromcode(self, statuscode):
"""Look at the rs_codes and returns the status from the code."""
status = 'UNKNOWN'
if self._rs_codes is not None:
statuscode = str(statuscode).strip()
for i in self._rs_codes:
val = str(self._rs_codes[i]).strip()
if ',' in val:
splitted = val.split(',')
for code in splitted:
code = str(code).strip()
if statuscode == code:
status = i.upper()
break
elif statuscode == val:
status = i.upper()
break
return status
def parsestatus(self, status):
"""Parse the status."""
_LOGGER.debug("Parsing status %s", status)
# Ignore the statuscode if it is IGNORE
if status.lower().strip() != CONF_REPORT_SERVER_CODES_IGNORE:
_LOGGER.debug("Not ignoring status")
newstatus = ([v for k, v in STATES.items()
if status.upper() == k][0])
self._status = newstatus
else:
_LOGGER.error("Ignoring status")
def update(self):
"""Update the alarm status."""
status = self._egardiasystem.getstate()
self.parsestatus(status)
def alarm_disarm(self, code=None):
"""Send disarm command."""
try:
self._egardiasystem.alarm_disarm()
except requests.exceptions.RequestException as err:
_LOGGER.error("Egardia device exception occurred when "
"sending disarm command: %s", err)
def alarm_arm_home(self, code=None):
"""Send arm home command."""
try:
self._egardiasystem.alarm_arm_home()
except requests.exceptions.RequestException as err:
_LOGGER.error("Egardia device exception occurred when "
"sending arm home command: %s", err)
def alarm_arm_away(self, code=None):
"""Send arm away command."""
try:
self._egardiasystem.alarm_arm_away()
except requests.exceptions.RequestException as err:
_LOGGER.error("Egardia device exception occurred when "
"sending arm away command: %s", err)