Maintenance zoneminder (#4102)

* Add timeout to requests, fix typos, and defaults

* Clean-up
This commit is contained in:
Fabian Affolter 2016-10-29 22:10:42 +02:00 committed by Paulus Schoutsen
parent 9ea1101aba
commit 942d630762
3 changed files with 43 additions and 45 deletions

View File

@ -1,13 +1,14 @@
""" """
Support for Zoneminder Sensors. Support for ZoneMinder Sensors.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.zoneminder/ https://home-assistant.io/components/sensor.zoneminder/
""" """
import logging import logging
import homeassistant.components.zoneminder as zoneminder from homeassistant.const import STATE_UNKNOWN
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
import homeassistant.components.zoneminder as zoneminder
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -15,7 +16,7 @@ DEPENDENCIES = ['zoneminder']
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup Zoneminder platform.""" """Set up the ZoneMinder sensor platform."""
sensors = [] sensors = []
monitors = zoneminder.get_state('api/monitors.json') monitors = zoneminder.get_state('api/monitors.json')
@ -31,7 +32,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class ZMSensorMonitors(Entity): class ZMSensorMonitors(Entity):
"""Get the status of each monitor.""" """Get the status of each ZoneMinder monitor."""
def __init__(self, monitor_id, monitor_name): def __init__(self, monitor_id, monitor_name):
"""Initiate monitor sensor.""" """Initiate monitor sensor."""
@ -42,7 +43,7 @@ class ZMSensorMonitors(Entity):
@property @property
def name(self): def name(self):
"""Return the name of the sensor.""" """Return the name of the sensor."""
return "%s Status" % self._monitor_name return '{} Status'.format(self._monitor_name)
@property @property
def state(self): def state(self):
@ -55,7 +56,7 @@ class ZMSensorMonitors(Entity):
'api/monitors/%i.json' % self._monitor_id 'api/monitors/%i.json' % self._monitor_id
) )
if monitor['monitor']['Monitor']['Function'] is None: if monitor['monitor']['Monitor']['Function'] is None:
self._state = "None" self._state = STATE_UNKNOWN
else: else:
self._state = monitor['monitor']['Monitor']['Function'] self._state = monitor['monitor']['Monitor']['Function']
@ -72,7 +73,7 @@ class ZMSensorEvents(Entity):
@property @property
def name(self): def name(self):
"""Return the name of the sensor.""" """Return the name of the sensor."""
return "%s Events" % self._monitor_name return '{} Events'.format(self._monitor_name)
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):

View File

@ -1,5 +1,5 @@
""" """
Support for Zoneminder switches. Support for ZoneMinder switches.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/switch.zoneminder/ https://home-assistant.io/components/switch.zoneminder/
@ -10,23 +10,21 @@ import voluptuous as vol
from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA)
from homeassistant.const import (CONF_COMMAND_ON, CONF_COMMAND_OFF) from homeassistant.const import (CONF_COMMAND_ON, CONF_COMMAND_OFF)
import homeassistant.components.zoneminder as zoneminder
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.components.zoneminder as zoneminder _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['zoneminder']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_COMMAND_ON): cv.string, vol.Required(CONF_COMMAND_ON): cv.string,
vol.Required(CONF_COMMAND_OFF): cv.string, vol.Required(CONF_COMMAND_OFF): cv.string,
}) })
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['zoneminder']
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Zoneminder switch.""" """Set up the ZoneMinder switch platform."""
on_state = config.get(CONF_COMMAND_ON) on_state = config.get(CONF_COMMAND_ON)
off_state = config.get(CONF_COMMAND_OFF) off_state = config.get(CONF_COMMAND_OFF)
@ -47,7 +45,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class ZMSwitchMonitors(SwitchDevice): class ZMSwitchMonitors(SwitchDevice):
"""Representation of an zoneminder switch.""" """Representation of a ZoneMinder switch."""
icon = 'mdi:record-rec' icon = 'mdi:record-rec'

View File

@ -1,10 +1,9 @@
""" """
Support for Zoneminder. Support for ZoneMinder.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/zoneminder/ https://home-assistant.io/components/zoneminder/
""" """
import logging import logging
import json import json
from urllib.parse import urljoin from urllib.parse import urljoin
@ -12,43 +11,44 @@ from urllib.parse import urljoin
import requests import requests
import voluptuous as vol import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.const import ( from homeassistant.const import (
CONF_PATH, CONF_HOST, CONF_SSL, CONF_PASSWORD, CONF_USERNAME) CONF_PATH, CONF_HOST, CONF_SSL, CONF_PASSWORD, CONF_USERNAME)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
REQUIREMENTS = [] DEFAULT_PATH = '/zm/'
DEFAULT_SSL = False
DEFAULT_TIMEOUT = 10
DOMAIN = 'zoneminder' DOMAIN = 'zoneminder'
LOGIN_RETRIES = 2
ZM = {}
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({ DOMAIN: vol.Schema({
vol.Required(CONF_HOST): cv.string, vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_SSL, default=False): cv.boolean, vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
vol.Optional(CONF_PATH, default="/zm/"): cv.string, vol.Optional(CONF_PATH, default=DEFAULT_PATH): cv.string,
vol.Optional(CONF_USERNAME): cv.string, vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_PASSWORD): cv.string vol.Optional(CONF_PASSWORD): cv.string
}) })
}, extra=vol.ALLOW_EXTRA) }, extra=vol.ALLOW_EXTRA)
LOGIN_RETRIES = 2
ZM = {}
def setup(hass, config): def setup(hass, config):
"""Setup the zonminder platform.""" """Set up the ZoneMinder component."""
global ZM global ZM
ZM = {} ZM = {}
conf = config[DOMAIN] conf = config[DOMAIN]
if conf[CONF_SSL]: if conf[CONF_SSL]:
schema = "https" schema = 'https'
else: else:
schema = "http" schema = 'http'
url = urljoin(schema + "://" + conf[CONF_HOST], conf[CONF_PATH]) url = urljoin('{}://{}'.format(schema, conf[CONF_HOST]), conf[CONF_PATH])
username = conf.get(CONF_USERNAME, None) username = conf.get(CONF_USERNAME, None)
password = conf.get(CONF_PASSWORD, None) password = conf.get(CONF_PASSWORD, None)
@ -61,8 +61,8 @@ def setup(hass, config):
# pylint: disable=no-member # pylint: disable=no-member
def login(): def login():
"""Login to the zoneminder api.""" """Login to the ZoneMinder API."""
_LOGGER.debug("Attempting to login to zoneminder") _LOGGER.debug("Attempting to login to ZoneMinder")
login_post = {'view': 'console', 'action': 'login'} login_post = {'view': 'console', 'action': 'login'}
if ZM['username']: if ZM['username']:
@ -73,12 +73,11 @@ def login():
req = requests.post(ZM['url'] + '/index.php', data=login_post) req = requests.post(ZM['url'] + '/index.php', data=login_post)
ZM['cookies'] = req.cookies ZM['cookies'] = req.cookies
# Login calls returns a 200 repsonse on both failure and success.. # Login calls returns a 200 response on both failure and success.
# The only way to tell if you logged in correctly is to issue an api call. # The only way to tell if you logged in correctly is to issue an api call.
req = requests.get( req = requests.get(
ZM['url'] + 'api/host/getVersion.json', ZM['url'] + 'api/host/getVersion.json', cookies=ZM['cookies'],
cookies=ZM['cookies'] timeout=DEFAULT_TIMEOUT)
)
if req.status_code != requests.codes.ok: if req.status_code != requests.codes.ok:
_LOGGER.error("Connection error logging into ZoneMinder") _LOGGER.error("Connection error logging into ZoneMinder")
@ -89,18 +88,19 @@ def login():
# pylint: disable=no-member # pylint: disable=no-member
def get_state(api_url): def get_state(api_url):
"""Get a state from the zoneminder API service.""" """Get a state from the ZoneMinder API service."""
# Since the API uses sessions that expire, sometimes we need # Since the API uses sessions that expire, sometimes we need to re-auth
# to re-auth if the call fails. # if the call fails.
for _ in range(LOGIN_RETRIES): for _ in range(LOGIN_RETRIES):
req = requests.get(urljoin(ZM['url'], api_url), cookies=ZM['cookies']) req = requests.get(urljoin(ZM['url'], api_url), cookies=ZM['cookies'],
timeout=DEFAULT_TIMEOUT)
if req.status_code != requests.codes.ok: if req.status_code != requests.codes.ok:
login() login()
else: else:
break break
else: else:
_LOGGER.exception("Unable to get API response") _LOGGER.exception("Unable to get API response from ZoneMinder")
return json.loads(req.text) return json.loads(req.text)
@ -110,9 +110,8 @@ def change_state(api_url, post_data):
"""Update a state using the Zoneminder API.""" """Update a state using the Zoneminder API."""
for _ in range(LOGIN_RETRIES): for _ in range(LOGIN_RETRIES):
req = requests.post( req = requests.post(
urljoin(ZM['url'], api_url), urljoin(ZM['url'], api_url), data=post_data, cookies=ZM['cookies'],
data=post_data, timeout=DEFAULT_TIMEOUT)
cookies=ZM['cookies'])
if req.status_code != requests.codes.ok: if req.status_code != requests.codes.ok:
login() login()
@ -120,6 +119,6 @@ def change_state(api_url, post_data):
break break
else: else:
_LOGGER.exception("Unable to get API response") _LOGGER.exception("Unable to get API response from ZoneMinder")
return json.loads(req.text) return json.loads(req.text)