From b5214af762b7e0fa142271f8e9c5841dba42473f Mon Sep 17 00:00:00 2001 From: David Grant Date: Mon, 30 Oct 2017 03:40:14 -0400 Subject: [PATCH] Add gc100 platforms and component (#10159) * Initial commit of gc100 platforms and component * Fixed removed temporary code to set import path * Fixed removed unused import * Implementing changes requested by @fabaff * Fixed linter errors * Remove reference to binary sensor * Move const * Add const * Fix pylint --- .coveragerc | 3 + .../components/binary_sensor/gc100.py | 69 +++++++++++++++++ homeassistant/components/gc100.py | 74 +++++++++++++++++++ homeassistant/components/switch/gc100.py | 74 +++++++++++++++++++ requirements_all.txt | 3 + 5 files changed, 223 insertions(+) create mode 100644 homeassistant/components/binary_sensor/gc100.py create mode 100644 homeassistant/components/gc100.py create mode 100644 homeassistant/components/switch/gc100.py diff --git a/.coveragerc b/.coveragerc index 0cadbe492ab..d706f09ae90 100644 --- a/.coveragerc +++ b/.coveragerc @@ -71,6 +71,9 @@ omit = homeassistant/components/envisalink.py homeassistant/components/*/envisalink.py + homeassistant/components/gc100.py + homeassistant/components/*/gc100.py + homeassistant/components/google.py homeassistant/components/*/google.py diff --git a/homeassistant/components/binary_sensor/gc100.py b/homeassistant/components/binary_sensor/gc100.py new file mode 100644 index 00000000000..c17e6b50911 --- /dev/null +++ b/homeassistant/components/binary_sensor/gc100.py @@ -0,0 +1,69 @@ +""" +Support for binary sensor using GC100. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/binary_sensor.gc100/ +""" +import voluptuous as vol + +from homeassistant.components.gc100 import DATA_GC100, CONF_PORTS +from homeassistant.components.binary_sensor import ( + BinarySensorDevice, PLATFORM_SCHEMA) +from homeassistant.const import DEVICE_DEFAULT_NAME +import homeassistant.helpers.config_validation as cv + +DEPENDENCIES = ['gc100'] + +_SENSORS_SCHEMA = vol.Schema({ + cv.string: cv.string, +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_PORTS): vol.All(cv.ensure_list, [_SENSORS_SCHEMA]) +}) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the GC100 devices.""" + binary_sensors = [] + ports = config.get(CONF_PORTS) + for port in ports: + for port_addr, port_name in port.items(): + binary_sensors.append(GC100BinarySensor( + port_name, port_addr, hass.data[DATA_GC100])) + add_devices(binary_sensors, True) + + +class GC100BinarySensor(BinarySensorDevice): + """Representation of a binary sensor from GC100.""" + + def __init__(self, name, port_addr, gc100): + """Initialize the GC100 binary sensor.""" + # pylint: disable=no-member + self._name = name or DEVICE_DEFAULT_NAME + self._port_addr = port_addr + self._gc100 = gc100 + self._state = None + + # Subscribe to be notified about state changes (PUSH) + self._gc100.subscribe(self._port_addr, self.set_state) + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def is_on(self): + """Return the state of the entity.""" + return self._state + + def update(self): + """Update the sensor state.""" + self._gc100.read_sensor(self._port_addr, self.set_state) + + def set_state(self, state): + """Set the current state.""" + self._state = state == 1 + self.schedule_update_ha_state() diff --git a/homeassistant/components/gc100.py b/homeassistant/components/gc100.py new file mode 100644 index 00000000000..7c772e345ae --- /dev/null +++ b/homeassistant/components/gc100.py @@ -0,0 +1,74 @@ +""" +Support for controlling Global Cache gc100. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/gc100/ +""" +import logging + +import voluptuous as vol + +from homeassistant.const import ( + EVENT_HOMEASSISTANT_STOP, CONF_HOST, CONF_PORT) +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['python-gc100==1.0.1a'] + +_LOGGER = logging.getLogger(__name__) + +CONF_PORTS = 'ports' + +DEFAULT_PORT = 4998 +DOMAIN = 'gc100' + +DATA_GC100 = 'gc100' + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + }), +}, extra=vol.ALLOW_EXTRA) + + +# pylint: disable=no-member, import-self +def setup(hass, base_config): + """Set up the gc100 component.""" + import gc100 + + config = base_config[DOMAIN] + host = config[CONF_HOST] + port = config[CONF_PORT] + + gc_device = gc100.GC100SocketClient(host, port) + + def cleanup_gc100(): + """Stuff to do before stopping.""" + gc_device.quit() + + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, cleanup_gc100) + + hass.data[DATA_GC100] = GC100Device(hass, gc_device) + + return True + + +class GC100Device(object): + """The GC100 component.""" + + def __init__(self, hass, gc_device): + """Init a gc100 device.""" + self.hass = hass + self.gc_device = gc_device + + def read_sensor(self, port_addr, callback): + """Read a value from a digital input.""" + self.gc_device.read_sensor(port_addr, callback) + + def write_switch(self, port_addr, state, callback): + """Write a value to a relay.""" + self.gc_device.write_switch(port_addr, state, callback) + + def subscribe(self, port_addr, callback): + """Add detection for RISING and FALLING events.""" + self.gc_device.subscribe_notify(port_addr, callback) diff --git a/homeassistant/components/switch/gc100.py b/homeassistant/components/switch/gc100.py new file mode 100644 index 00000000000..ed50c3f63f6 --- /dev/null +++ b/homeassistant/components/switch/gc100.py @@ -0,0 +1,74 @@ +""" +Support for switches using GC100. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/switch.gc100/ +""" +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.components.gc100 import DATA_GC100, CONF_PORTS +from homeassistant.components.switch import (PLATFORM_SCHEMA) +from homeassistant.helpers.entity import ToggleEntity +from homeassistant.const import DEVICE_DEFAULT_NAME + +DEPENDENCIES = ['gc100'] + +_SWITCH_SCHEMA = vol.Schema({ + cv.string: cv.string, +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_PORTS): vol.All(cv.ensure_list, [_SWITCH_SCHEMA]) +}) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the GC100 devices.""" + switches = [] + ports = config.get(CONF_PORTS) + for port in ports: + for port_addr, port_name in port.items(): + switches.append(GC100Switch( + port_name, port_addr, hass.data[DATA_GC100])) + add_devices(switches, True) + + +class GC100Switch(ToggleEntity): + """Represent a switch/relay from GC100.""" + + def __init__(self, name, port_addr, gc100): + """Initialize the GC100 switch.""" + # pylint: disable=no-member + self._name = name or DEVICE_DEFAULT_NAME + self._port_addr = port_addr + self._gc100 = gc100 + self._state = None + + @property + def name(self): + """Return the name of the switch.""" + return self._name + + @property + def is_on(self): + """Return the state of the entity.""" + return self._state + + def turn_on(self): + """Turn the device on.""" + self._gc100.write_switch(self._port_addr, 1, self.set_state) + + def turn_off(self): + """Turn the device off.""" + self._gc100.write_switch(self._port_addr, 0, self.set_state) + + def update(self): + """Update the sensor state.""" + self._gc100.read_sensor(self._port_addr, self.set_state) + + def set_state(self, state): + """Set the current state.""" + self._state = state == 1 + self.schedule_update_ha_state() diff --git a/requirements_all.txt b/requirements_all.txt index ddf56b179c8..03997632013 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -806,6 +806,9 @@ python-etherscan-api==0.0.1 # homeassistant.components.sensor.darksky python-forecastio==1.3.5 +# homeassistant.components.gc100 +python-gc100==1.0.1a + # homeassistant.components.sensor.hp_ilo python-hpilo==3.9