diff --git a/.coveragerc b/.coveragerc index 727e57149ba..f8423c089bd 100644 --- a/.coveragerc +++ b/.coveragerc @@ -371,6 +371,9 @@ omit = homeassistant/components/*/webostv.py + homeassistant/components/w800rf32.py + homeassistant/components/*/w800rf32.py + homeassistant/components/wemo.py homeassistant/components/*/wemo.py diff --git a/homeassistant/components/binary_sensor/w800rf32.py b/homeassistant/components/binary_sensor/w800rf32.py new file mode 100644 index 00000000000..48ac6f41a12 --- /dev/null +++ b/homeassistant/components/binary_sensor/w800rf32.py @@ -0,0 +1,132 @@ +""" +Support for w800rf32 binary sensors. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/binary_sensor.w800rf32/ + +""" +import logging + +import voluptuous as vol + +from homeassistant.components.binary_sensor import ( + DEVICE_CLASSES_SCHEMA, PLATFORM_SCHEMA, BinarySensorDevice) +from homeassistant.components.w800rf32 import (W800RF32_DEVICE) +from homeassistant.const import (CONF_DEVICE_CLASS, CONF_NAME, CONF_DEVICES) +from homeassistant.core import callback +from homeassistant.helpers import config_validation as cv +from homeassistant.helpers import event as evt +from homeassistant.util import dt as dt_util +from homeassistant.helpers.dispatcher import (async_dispatcher_connect) + +_LOGGER = logging.getLogger(__name__) + +DEPENDENCIES = ['w800rf32'] +CONF_OFF_DELAY = 'off_delay' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DEVICES): { + cv.string: vol.Schema({ + vol.Optional(CONF_NAME): cv.string, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_OFF_DELAY): + vol.All(cv.time_period, cv.positive_timedelta) + }) + }, +}, extra=vol.ALLOW_EXTRA) + + +async def async_setup_platform(hass, config, + add_entities, discovery_info=None): + """Set up the Binary Sensor platform to w800rf32.""" + binary_sensors = [] + # device_id --> "c1 or a3" X10 device. entity (type dictionary) + # --> name, device_class etc + for device_id, entity in config[CONF_DEVICES].items(): + + _LOGGER.debug("Add %s w800rf32.binary_sensor (class %s)", + entity[CONF_NAME], entity.get(CONF_DEVICE_CLASS)) + + device = W800rf32BinarySensor( + device_id, entity.get(CONF_NAME), entity.get(CONF_DEVICE_CLASS), + entity.get(CONF_OFF_DELAY)) + + binary_sensors.append(device) + + add_entities(binary_sensors) + + +class W800rf32BinarySensor(BinarySensorDevice): + """A representation of a w800rf32 binary sensor.""" + + def __init__(self, device_id, name, device_class=None, off_delay=None): + """Initialize the w800rf32 sensor.""" + self._signal = W800RF32_DEVICE.format(device_id) + self._name = name + self._device_class = device_class + self._off_delay = off_delay + self._state = False + self._delay_listener = None + + @callback + def _off_delay_listener(self, now): + """Switch device off after a delay.""" + self._delay_listener = None + self.update_state(False) + + @property + def name(self): + """Return the device name.""" + return self._name + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def device_class(self): + """Return the sensor class.""" + return self._device_class + + @property + def is_on(self): + """Return true if the sensor state is True.""" + return self._state + + @callback + def binary_sensor_update(self, event): + """Call for control updates from the w800rf32 gateway.""" + import W800rf32 as w800rf32mod + + if not isinstance(event, w800rf32mod.W800rf32Event): + return + + dev_id = event.device + command = event.command + + _LOGGER.debug( + "BinarySensor update (Device ID: %s Command %s ...)", + dev_id, command) + + # Update the w800rf32 device state + if command in ('On', 'Off'): + is_on = command == 'On' + self.update_state(is_on) + + if (self.is_on and self._off_delay is not None and + self._delay_listener is None): + + self._delay_listener = evt.async_track_point_in_time( + self.hass, self._off_delay_listener, + dt_util.utcnow() + self._off_delay) + + def update_state(self, state): + """Update the state of the device.""" + self._state = state + self.async_schedule_update_ha_state() + + async def async_added_to_hass(self): + """Register update callback.""" + async_dispatcher_connect(self.hass, self._signal, + self.binary_sensor_update) diff --git a/homeassistant/components/w800rf32.py b/homeassistant/components/w800rf32.py new file mode 100644 index 00000000000..4b237272546 --- /dev/null +++ b/homeassistant/components/w800rf32.py @@ -0,0 +1,67 @@ +""" +Support for w800rf32 components. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/w800rf32/ + +""" +import logging + +import voluptuous as vol + +from homeassistant.const import (CONF_DEVICE, + EVENT_HOMEASSISTANT_START, + EVENT_HOMEASSISTANT_STOP) + +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.dispatcher import (dispatcher_send) + +REQUIREMENTS = ['pyW800rf32==0.1'] + +DOMAIN = 'w800rf32' +DATA_W800RF32 = 'data_w800rf32' +W800RF32_DEVICE = 'w800rf32_{}' + +_LOGGER = logging.getLogger(__name__) + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_DEVICE): cv.string + }), +}, extra=vol.ALLOW_EXTRA) + + +def setup(hass, config): + """Set up the w800rf32 component.""" + # Try to load the W800rf32 module. + import W800rf32 as w800 + + # Declare the Handle event + def handle_receive(event): + """Handle received messages from w800rf32 gateway.""" + # Log event + if not event.device: + return + _LOGGER.debug("Receive W800rf32 event in handle_receive") + + # Get device_type from device_id in hass.data + device_id = event.device.lower() + signal = W800RF32_DEVICE.format(device_id) + dispatcher_send(hass, signal, event) + + # device --> /dev/ttyUSB0 + device = config[DOMAIN][CONF_DEVICE] + w800_object = w800.Connect(device, None) + + def _start_w800rf32(event): + w800_object.event_callback = handle_receive + hass.bus.listen_once(EVENT_HOMEASSISTANT_START, _start_w800rf32) + + def _shutdown_w800rf32(event): + """Close connection with w800rf32.""" + w800_object.close_connection() + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown_w800rf32) + + hass.data[DATA_W800RF32] = w800_object + + return True diff --git a/requirements_all.txt b/requirements_all.txt index e23e6e7ff77..e54612b7d40 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -817,6 +817,9 @@ pyTibber==0.7.4 # homeassistant.components.switch.dlink pyW215==0.6.0 +# homeassistant.components.w800rf32 +pyW800rf32==0.1 + # homeassistant.components.sensor.noaa_tides # py_noaa==0.3.0