Wink PubNub v4 (#4561)
* PubNub v4 * Updated to pubnubsub-handler 0.0.5 * Updated requirements_all.txtpull/4419/merge
parent
406afbb369
commit
4c03d670c1
|
@ -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."""
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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."""
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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."""
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue