mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Merge pull request #1308 from kk7ds/binary-sensor-class
Add binary sensor class
This commit is contained in:
commit
233a2a2878
@ -17,6 +17,17 @@ DOMAIN = 'binary_sensor'
|
||||
SCAN_INTERVAL = 30
|
||||
|
||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||
SENSOR_CLASSES = [
|
||||
None, # Generic on/off
|
||||
'opening', # Door, window, etc
|
||||
'motion', # Motion sensor
|
||||
'gas', # CO, CO2, etc
|
||||
'smoke', # Smoke detector
|
||||
'moisture', # Specifically a wetness sensor
|
||||
'light', # Lightness threshold
|
||||
'power', # Power, over-current, etc
|
||||
'safety', # Generic on=unsafe, off=safe
|
||||
]
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
@ -47,3 +58,14 @@ class BinarySensorDevice(Entity):
|
||||
def friendly_state(self):
|
||||
""" Returns the friendly state of the binary sensor. """
|
||||
return None
|
||||
|
||||
@property
|
||||
def sensor_class(self):
|
||||
""" Returns the class of this sensor, from SENSOR_CASSES. """
|
||||
return None
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
return {
|
||||
'sensor_class': self.sensor_class,
|
||||
}
|
||||
|
@ -9,17 +9,23 @@ from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the Demo binary sensors. """
|
||||
add_devices([
|
||||
DemoBinarySensor('Basement Floor Wet', False),
|
||||
DemoBinarySensor('Movement Backyard', True),
|
||||
DemoBinarySensor('Basement Floor Wet', False, 'moisture'),
|
||||
DemoBinarySensor('Movement Backyard', True, 'motion'),
|
||||
])
|
||||
|
||||
|
||||
class DemoBinarySensor(BinarySensorDevice):
|
||||
""" A Demo binary sensor. """
|
||||
|
||||
def __init__(self, name, state):
|
||||
def __init__(self, name, state, sensor_class):
|
||||
self._name = name
|
||||
self._state = state
|
||||
self._sensor_type = sensor_class
|
||||
|
||||
@property
|
||||
def sensor_class(self):
|
||||
""" Return our class. """
|
||||
return self._sensor_type
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
|
@ -12,7 +12,8 @@ import time
|
||||
|
||||
import requests
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||
from homeassistant.components.binary_sensor import (BinarySensorDevice,
|
||||
SENSOR_CLASSES)
|
||||
|
||||
REQUIREMENTS = ['pynx584==0.2']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -24,11 +25,17 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
|
||||
host = config.get('host', 'localhost:5007')
|
||||
exclude = config.get('exclude_zones', [])
|
||||
zone_types = config.get('zone_types', {})
|
||||
|
||||
if not all(isinstance(zone, int) for zone in exclude):
|
||||
_LOGGER.error('Invalid excluded zone specified (use zone number)')
|
||||
return False
|
||||
|
||||
if not all(isinstance(zone, int) and ztype in SENSOR_CLASSES
|
||||
for zone, ztype in zone_types.items()):
|
||||
_LOGGER.error('Invalid zone_types entry')
|
||||
return False
|
||||
|
||||
try:
|
||||
client = nx584_client.Client('http://%s' % host)
|
||||
zones = client.list_zones()
|
||||
@ -42,7 +49,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
return False
|
||||
|
||||
zone_sensors = {
|
||||
zone['number']: NX584ZoneSensor(zone)
|
||||
zone['number']: NX584ZoneSensor(
|
||||
zone,
|
||||
zone_types.get(zone['number'], 'opening'))
|
||||
for zone in zones
|
||||
if zone['number'] not in exclude}
|
||||
if zone_sensors:
|
||||
@ -58,8 +67,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
class NX584ZoneSensor(BinarySensorDevice):
|
||||
"""Represents a NX584 zone as a sensor."""
|
||||
|
||||
def __init__(self, zone):
|
||||
def __init__(self, zone, zone_type):
|
||||
self._zone = zone
|
||||
self._zone_type = zone_type
|
||||
|
||||
@property
|
||||
def sensor_class(self):
|
||||
return self._zone_type
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
|
36
tests/components/binary_sensor/test_binary_sensor.py
Normal file
36
tests/components/binary_sensor/test_binary_sensor.py
Normal file
@ -0,0 +1,36 @@
|
||||
"""
|
||||
tests.components.binary_sensor.test_binary_sensor
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Test the binary_sensor base class
|
||||
"""
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
from homeassistant.components import binary_sensor
|
||||
from homeassistant.const import STATE_ON, STATE_OFF
|
||||
|
||||
|
||||
class TestBinarySensor(unittest.TestCase):
|
||||
def test_state(self):
|
||||
sensor = binary_sensor.BinarySensorDevice()
|
||||
self.assertEqual(STATE_OFF, sensor.state)
|
||||
with mock.patch('homeassistant.components.binary_sensor.'
|
||||
'BinarySensorDevice.is_on',
|
||||
new=False):
|
||||
self.assertEqual(STATE_OFF,
|
||||
binary_sensor.BinarySensorDevice().state)
|
||||
with mock.patch('homeassistant.components.binary_sensor.'
|
||||
'BinarySensorDevice.is_on',
|
||||
new=True):
|
||||
self.assertEqual(STATE_ON,
|
||||
binary_sensor.BinarySensorDevice().state)
|
||||
|
||||
def test_attributes(self):
|
||||
sensor = binary_sensor.BinarySensorDevice()
|
||||
self.assertEqual({'sensor_class': None},
|
||||
sensor.device_state_attributes)
|
||||
with mock.patch('homeassistant.components.binary_sensor.'
|
||||
'BinarySensorDevice.sensor_class',
|
||||
new='motion'):
|
||||
self.assertEqual({'sensor_class': 'motion'},
|
||||
sensor.device_state_attributes)
|
@ -41,7 +41,7 @@ class TestNX584SensorSetup(unittest.TestCase):
|
||||
hass = mock.MagicMock()
|
||||
self.assertTrue(nx584.setup_platform(hass, {}, add_devices))
|
||||
mock_nx.assert_has_calls([
|
||||
mock.call(zone)
|
||||
mock.call(zone, 'opening')
|
||||
for zone in self.fake_zones])
|
||||
self.assertTrue(add_devices.called)
|
||||
nx584_client.Client.assert_called_once_with('http://localhost:5007')
|
||||
@ -58,8 +58,8 @@ class TestNX584SensorSetup(unittest.TestCase):
|
||||
hass = mock.MagicMock()
|
||||
self.assertTrue(nx584.setup_platform(hass, config, add_devices))
|
||||
mock_nx.assert_has_calls([
|
||||
mock.call(self.fake_zones[0]),
|
||||
mock.call(self.fake_zones[2]),
|
||||
mock.call(self.fake_zones[0], 'opening'),
|
||||
mock.call(self.fake_zones[2], 'motion'),
|
||||
])
|
||||
self.assertTrue(add_devices.called)
|
||||
nx584_client.Client.assert_called_once_with('http://foo:123')
|
||||
@ -74,6 +74,9 @@ class TestNX584SensorSetup(unittest.TestCase):
|
||||
def test_setup_bad_config(self):
|
||||
bad_configs = [
|
||||
{'exclude_zones': ['a']},
|
||||
{'zone_types': {'a': 'b'}},
|
||||
{'zone_types': {1: 'notatype'}},
|
||||
{'zone_types': {'notazone': 'motion'}},
|
||||
]
|
||||
for config in bad_configs:
|
||||
self._test_assert_graceful_fail(config)
|
||||
@ -98,7 +101,7 @@ class TestNX584SensorSetup(unittest.TestCase):
|
||||
class TestNX584ZoneSensor(unittest.TestCase):
|
||||
def test_sensor_normal(self):
|
||||
zone = {'number': 1, 'name': 'foo', 'state': True}
|
||||
sensor = nx584.NX584ZoneSensor(zone)
|
||||
sensor = nx584.NX584ZoneSensor(zone, 'motion')
|
||||
self.assertEqual('foo', sensor.name)
|
||||
self.assertFalse(sensor.should_poll)
|
||||
self.assertTrue(sensor.is_on)
|
||||
@ -113,8 +116,8 @@ class TestNX584Watcher(unittest.TestCase):
|
||||
zone1 = {'number': 1, 'name': 'foo', 'state': True}
|
||||
zone2 = {'number': 2, 'name': 'bar', 'state': True}
|
||||
zones = {
|
||||
1: nx584.NX584ZoneSensor(zone1),
|
||||
2: nx584.NX584ZoneSensor(zone2),
|
||||
1: nx584.NX584ZoneSensor(zone1, 'motion'),
|
||||
2: nx584.NX584ZoneSensor(zone2, 'motion'),
|
||||
}
|
||||
watcher = nx584.NX584Watcher(None, zones)
|
||||
watcher._process_zone_event({'zone': 1, 'zone_state': False})
|
||||
|
Loading…
x
Reference in New Issue
Block a user