Wink PubNub v4 (#4561)

* PubNub v4

* Updated to pubnubsub-handler 0.0.5

* Updated requirements_all.txt
pull/4419/merge
William Scanlon 2016-11-30 16:12:26 -05:00 committed by Paulus Schoutsen
parent 406afbb369
commit 4c03d670c1
9 changed files with 82 additions and 80 deletions

View File

@ -4,8 +4,6 @@ Support for Wink binary 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
at https://home-assistant.io/components/binary_sensor.wink/ at https://home-assistant.io/components/binary_sensor.wink/
""" """
import json
import logging
from homeassistant.components.binary_sensor import BinarySensorDevice from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.sensor.wink import WinkDevice from homeassistant.components.sensor.wink import WinkDevice
@ -34,38 +32,25 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
for sensor in pywink.get_sensors(): for sensor in pywink.get_sensors():
if sensor.capability() in SENSOR_TYPES: if sensor.capability() in SENSOR_TYPES:
add_devices([WinkBinarySensorDevice(sensor)]) add_devices([WinkBinarySensorDevice(sensor, hass)])
for key in pywink.get_keys(): for key in pywink.get_keys():
add_devices([WinkBinarySensorDevice(key)]) add_devices([WinkBinarySensorDevice(key, hass)])
for sensor in pywink.get_smoke_and_co_detectors(): for sensor in pywink.get_smoke_and_co_detectors():
add_devices([WinkBinarySensorDevice(sensor)]) add_devices([WinkBinarySensorDevice(sensor, hass)])
class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity): class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity):
"""Representation of a Wink binary sensor.""" """Representation of a Wink binary sensor."""
def __init__(self, wink): def __init__(self, wink, hass):
"""Initialize the Wink binary sensor.""" """Initialize the Wink binary sensor."""
super().__init__(wink) super().__init__(wink, hass)
wink = get_component('wink') wink = get_component('wink')
self._unit_of_measurement = self.wink.UNIT self._unit_of_measurement = self.wink.UNIT
self.capability = self.wink.capability() self.capability = self.wink.capability()
def _pubnub_update(self, message, channel):
try:
if 'data' in message:
json_data = json.dumps(message.get('data'))
else:
json_data = message
self.wink.pubnub_update(json.loads(json_data))
self.update_ha_state()
except (AttributeError, KeyError):
error = "Pubnub returned invalid json for " + self.name
logging.getLogger(__name__).error(error)
self.update_ha_state(True)
@property @property
def is_on(self): def is_on(self):
"""Return true if the binary sensor is on.""" """Return true if the binary sensor is on."""

View File

@ -30,7 +30,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink thermostat.""" """Setup the Wink thermostat."""
import pywink import pywink
temp_unit = hass.config.units.temperature_unit temp_unit = hass.config.units.temperature_unit
add_devices(WinkThermostat(thermostat, temp_unit) add_devices(WinkThermostat(thermostat, hass, temp_unit)
for thermostat in pywink.get_thermostats()) for thermostat in pywink.get_thermostats())
@ -38,9 +38,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class WinkThermostat(WinkDevice, ClimateDevice): class WinkThermostat(WinkDevice, ClimateDevice):
"""Representation of a Wink thermostat.""" """Representation of a Wink thermostat."""
def __init__(self, wink, temp_unit): def __init__(self, wink, hass, temp_unit):
"""Initialize the Wink device.""" """Initialize the Wink device."""
super().__init__(wink) super().__init__(wink, hass)
wink = get_component('wink') wink = get_component('wink')
self._config_temp_unit = temp_unit self._config_temp_unit = temp_unit

View File

@ -15,18 +15,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink cover platform.""" """Setup the Wink cover platform."""
import pywink import pywink
add_devices(WinkCoverDevice(shade) for shade in add_devices(WinkCoverDevice(shade, hass) for shade in
pywink.get_shades()) pywink.get_shades())
add_devices(WinkCoverDevice(door) for door in add_devices(WinkCoverDevice(door, hass) for door in
pywink.get_garage_doors()) pywink.get_garage_doors())
class WinkCoverDevice(WinkDevice, CoverDevice): class WinkCoverDevice(WinkDevice, CoverDevice):
"""Representation of a Wink cover device.""" """Representation of a Wink cover device."""
def __init__(self, wink): def __init__(self, wink, hass):
"""Initialize the cover.""" """Initialize the cover."""
WinkDevice.__init__(self, wink) WinkDevice.__init__(self, wink, hass)
def close_cover(self): def close_cover(self):
"""Close the shade.""" """Close the shade."""

View File

@ -23,15 +23,15 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink lights.""" """Setup the Wink lights."""
import pywink import pywink
add_devices(WinkLight(light) for light in pywink.get_bulbs()) add_devices(WinkLight(light, hass) for light in pywink.get_bulbs())
class WinkLight(WinkDevice, Light): class WinkLight(WinkDevice, Light):
"""Representation of a Wink light.""" """Representation of a Wink light."""
def __init__(self, wink): def __init__(self, wink, hass):
"""Initialize the Wink device.""" """Initialize the Wink device."""
WinkDevice.__init__(self, wink) WinkDevice.__init__(self, wink, hass)
@property @property
def is_on(self): def is_on(self):

View File

@ -15,15 +15,15 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink platform.""" """Setup the Wink platform."""
import pywink import pywink
add_devices(WinkLockDevice(lock) for lock in pywink.get_locks()) add_devices(WinkLockDevice(lock, hass) for lock in pywink.get_locks())
class WinkLockDevice(WinkDevice, LockDevice): class WinkLockDevice(WinkDevice, LockDevice):
"""Representation of a Wink lock.""" """Representation of a Wink lock."""
def __init__(self, wink): def __init__(self, wink, hass):
"""Initialize the lock.""" """Initialize the lock."""
WinkDevice.__init__(self, wink) WinkDevice.__init__(self, wink, hass)
@property @property
def is_locked(self): def is_locked(self):

View File

@ -22,24 +22,25 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
for sensor in pywink.get_sensors(): for sensor in pywink.get_sensors():
if sensor.capability() in SENSOR_TYPES: if sensor.capability() in SENSOR_TYPES:
add_devices([WinkSensorDevice(sensor)]) add_devices([WinkSensorDevice(sensor, hass)])
add_devices(WinkEggMinder(eggtray) for eggtray in pywink.get_eggtrays()) for eggtray in pywink.get_eggtrays():
add_devices([WinkEggMinder(eggtray, hass)])
for piggy_bank in pywink.get_piggy_banks(): for piggy_bank in pywink.get_piggy_banks():
try: try:
if piggy_bank.capability() in SENSOR_TYPES: if piggy_bank.capability() in SENSOR_TYPES:
add_devices([WinkSensorDevice(piggy_bank)]) add_devices([WinkSensorDevice(piggy_bank, hass)])
except AttributeError: except AttributeError:
logging.getLogger(__name__).error("Device is not a sensor") logging.getLogger(__name__).info("Device is not a sensor")
class WinkSensorDevice(WinkDevice, Entity): class WinkSensorDevice(WinkDevice, Entity):
"""Representation of a Wink sensor.""" """Representation of a Wink sensor."""
def __init__(self, wink): def __init__(self, wink, hass):
"""Initialize the Wink device.""" """Initialize the Wink device."""
super().__init__(wink) super().__init__(wink, hass)
wink = get_component('wink') wink = get_component('wink')
self.capability = self.wink.capability() self.capability = self.wink.capability()
if self.wink.UNIT == '°': if self.wink.UNIT == '°':
@ -84,9 +85,9 @@ class WinkSensorDevice(WinkDevice, Entity):
class WinkEggMinder(WinkDevice, Entity): class WinkEggMinder(WinkDevice, Entity):
"""Representation of a Wink Egg Minder.""" """Representation of a Wink Egg Minder."""
def __init__(self, wink): def __init__(self, wink, hass):
"""Initialize the sensor.""" """Initialize the sensor."""
WinkDevice.__init__(self, wink) WinkDevice.__init__(self, wink, hass)
@property @property
def state(self): def state(self):

View File

@ -15,18 +15,20 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink platform.""" """Setup the Wink platform."""
import pywink import pywink
add_devices(WinkToggleDevice(switch) for switch in pywink.get_switches()) for switch in pywink.get_switches():
add_devices(WinkToggleDevice(switch) for switch in add_devices([WinkToggleDevice(switch, hass)])
pywink.get_powerstrip_outlets()) for switch in pywink.get_powerstrip_outlets():
add_devices(WinkToggleDevice(switch) for switch in pywink.get_sirens()) add_devices([WinkToggleDevice(switch, hass)])
for switch in pywink.get_sirens():
add_devices([WinkToggleDevice(switch, hass)])
class WinkToggleDevice(WinkDevice, ToggleEntity): class WinkToggleDevice(WinkDevice, ToggleEntity):
"""Representation of a Wink toggle device.""" """Representation of a Wink toggle device."""
def __init__(self, wink): def __init__(self, wink, hass):
"""Initialize the Wink device.""" """Initialize the Wink device."""
WinkDevice.__init__(self, wink) WinkDevice.__init__(self, wink, hass)
@property @property
def is_on(self): def is_on(self):

View File

@ -5,17 +5,18 @@ For more details about this component, please refer to the documentation at
https://home-assistant.io/components/wink/ https://home-assistant.io/components/wink/
""" """
import logging import logging
import json
import voluptuous as vol import voluptuous as vol
from homeassistant.helpers import discovery from homeassistant.helpers import discovery
from homeassistant.const import CONF_ACCESS_TOKEN, ATTR_BATTERY_LEVEL, \ from homeassistant.const import CONF_ACCESS_TOKEN, ATTR_BATTERY_LEVEL, \
CONF_EMAIL, CONF_PASSWORD CONF_EMAIL, CONF_PASSWORD, \
EVENT_HOMEASSISTANT_START, \
EVENT_HOMEASSISTANT_STOP
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['python-wink==0.10.0', 'pubnub==3.8.2'] REQUIREMENTS = ['python-wink==0.10.1', 'pubnubsub-handler==0.0.5']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -57,13 +58,13 @@ WINK_COMPONENTS = [
def setup(hass, config): def setup(hass, config):
"""Setup the Wink component.""" """Setup the Wink component."""
import pywink import pywink
from pubnubsubhandler import PubNubSubscriptionHandler
user_agent = config[DOMAIN][CONF_USER_AGENT] user_agent = config[DOMAIN].get(CONF_USER_AGENT)
if user_agent: if user_agent:
pywink.set_user_agent(user_agent) pywink.set_user_agent(user_agent)
from pubnub import Pubnub
access_token = config[DOMAIN].get(CONF_ACCESS_TOKEN) access_token = config[DOMAIN].get(CONF_ACCESS_TOKEN)
if access_token: if access_token:
@ -76,49 +77,62 @@ def setup(hass, config):
pywink.set_wink_credentials(email, password, client_id, pywink.set_wink_credentials(email, password, client_id,
client_secret) client_secret)
global SUBSCRIPTION_HANDLER hass.data[DOMAIN] = {}
SUBSCRIPTION_HANDLER = Pubnub( hass.data[DOMAIN]['entities'] = []
'N/A', pywink.get_subscription_key(), ssl_on=True) hass.data[DOMAIN]['pubnub'] = PubNubSubscriptionHandler(
SUBSCRIPTION_HANDLER.set_heartbeat(120) pywink.get_subscription_key(),
pywink.wink_api_fetch)
def start_subscription(event):
"""Start the pubnub subscription."""
hass.data[DOMAIN]['pubnub'].subscribe()
hass.bus.listen(EVENT_HOMEASSISTANT_START, start_subscription)
def stop_subscription(event):
"""Stop the pubnub subscription."""
hass.data[DOMAIN]['pubnub'].unsubscribe()
hass.bus.listen(EVENT_HOMEASSISTANT_STOP, stop_subscription)
def force_update(call):
"""Force all devices to poll the Wink API."""
_LOGGER.info("Refreshing Wink states from API.")
for entity in hass.data[DOMAIN]['entities']:
entity.update_ha_state(True)
hass.services.register(DOMAIN, 'Refresh state from Wink', force_update)
# Load components for the devices in Wink that we support # Load components for the devices in Wink that we support
for component in WINK_COMPONENTS: for component in WINK_COMPONENTS:
discovery.load_platform(hass, component, DOMAIN, {}, config) discovery.load_platform(hass, component, DOMAIN, {}, config)
return True return True
class WinkDevice(Entity): class WinkDevice(Entity):
"""Representation a base Wink device.""" """Representation a base Wink device."""
def __init__(self, wink): def __init__(self, wink, hass):
"""Initialize the Wink device.""" """Initialize the Wink device."""
from pubnub import Pubnub
self.wink = wink self.wink = wink
self._battery = self.wink.battery_level self._battery = self.wink.battery_level
if self.wink.pubnub_channel in CHANNELS: hass.data[DOMAIN]['pubnub'].add_subscription(
pubnub = Pubnub('N/A', self.wink.pubnub_key, ssl_on=True) self.wink.pubnub_channel,
pubnub.set_heartbeat(120) self._pubnub_update)
pubnub.subscribe(self.wink.pubnub_channel, hass.data[DOMAIN]['entities'].append(self)
self._pubnub_update,
error=self._pubnub_error)
else:
CHANNELS.append(self.wink.pubnub_channel)
SUBSCRIPTION_HANDLER.subscribe(self.wink.pubnub_channel,
self._pubnub_update,
error=self._pubnub_error)
def _pubnub_update(self, message, channel): def _pubnub_update(self, message):
try: try:
self.wink.pubnub_update(json.loads(message)) if message is None:
self.update_ha_state() _LOGGER.error("Error on pubnub update for " + self.name +
except (AttributeError, KeyError): " pollin API for current state")
error = "Pubnub returned invalid json for " + self.name self.update_ha_state(True)
logging.getLogger(__name__).error(error) else:
self.wink.pubnub_update(message)
self.update_ha_state()
except (ValueError, KeyError, AttributeError):
_LOGGER.error("Error in pubnub JSON for " + self.name +
" pollin API for current state")
self.update_ha_state(True) self.update_ha_state(True)
def _pubnub_error(self, message):
_LOGGER.error("Error on pubnub update for " + self.wink.name())
@property @property
def unique_id(self): def unique_id(self):
"""Return the ID of this Wink device.""" """Return the ID of this Wink device."""

View File

@ -340,7 +340,7 @@ proliphix==0.4.1
psutil==5.0.0 psutil==5.0.0
# homeassistant.components.wink # homeassistant.components.wink
pubnub==3.8.2 pubnubsub-handler==0.0.5
# homeassistant.components.notify.pushbullet # homeassistant.components.notify.pushbullet
pushbullet.py==0.10.0 pushbullet.py==0.10.0
@ -465,7 +465,7 @@ python-telegram-bot==5.2.0
python-twitch==1.3.0 python-twitch==1.3.0
# homeassistant.components.wink # homeassistant.components.wink
python-wink==0.10.0 python-wink==0.10.1
# homeassistant.components.keyboard # homeassistant.components.keyboard
# pyuserinput==0.1.11 # pyuserinput==0.1.11