Wink AC and addidtional sensor support (#5670)

* Added door bell sensors

* Initial support for AC units.

* Added new device service

* Quirky Aros AC unit support

* Use super() everywhere and error checking for token request.

* Ignore camera sensors during setup of alarms.

* Added manufacturer/device attributes to all wink devices.

* Fixed style errors

* Fixed remaining lint errors.
This commit is contained in:
William Scanlon 2017-02-02 01:43:12 -05:00 committed by Paulus Schoutsen
parent b5f285a789
commit 80a794e587
11 changed files with 361 additions and 88 deletions

View file

@ -11,7 +11,7 @@ from homeassistant.const import (STATE_UNKNOWN,
STATE_ALARM_DISARMED, STATE_ALARM_DISARMED,
STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_AWAY) STATE_ALARM_ARMED_AWAY)
from homeassistant.components.wink import WinkDevice from homeassistant.components.wink import WinkDevice, DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -24,6 +24,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
import pywink import pywink
for camera in pywink.get_cameras(): for camera in pywink.get_cameras():
# get_cameras returns multiple device types.
# Only add those that aren't sensors.
try:
camera.capability()
except AttributeError:
_id = camera.object_id() + camera.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkCameraDevice(camera, hass)]) add_devices([WinkCameraDevice(camera, hass)])
@ -32,7 +39,7 @@ class WinkCameraDevice(WinkDevice, alarm.AlarmControlPanel):
def __init__(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the Wink alarm.""" """Initialize the Wink alarm."""
WinkDevice.__init__(self, wink, hass) super().__init__(wink, hass)
@property @property
def state(self): def state(self):

View file

@ -4,11 +4,14 @@ 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 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.wink import WinkDevice, DOMAIN
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['wink'] DEPENDENCIES = ['wink']
# These are the available sensors mapped to binary_sensor class # These are the available sensors mapped to binary_sensor class
@ -17,11 +20,14 @@ SENSOR_TYPES = {
"brightness": "light", "brightness": "light",
"vibration": "vibration", "vibration": "vibration",
"loudness": "sound", "loudness": "sound",
"noise": "sound",
"capturing_audio": "sound",
"liquid_detected": "moisture", "liquid_detected": "moisture",
"motion": "motion", "motion": "motion",
"presence": "occupancy", "presence": "occupancy",
"co_detected": "gas", "co_detected": "gas",
"smoke_detected": "smoke" "smoke_detected": "smoke",
"capturing_video": None
} }
@ -30,27 +36,55 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
import pywink import pywink
for sensor in pywink.get_sensors(): for sensor in pywink.get_sensors():
_id = sensor.object_id() + sensor.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
if sensor.capability() in SENSOR_TYPES: if sensor.capability() in SENSOR_TYPES:
add_devices([WinkBinarySensorDevice(sensor, hass)]) add_devices([WinkBinarySensorDevice(sensor, hass)])
for key in pywink.get_keys(): for key in pywink.get_keys():
_id = key.object_id() + key.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkBinarySensorDevice(key, hass)]) 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, hass)]) _id = sensor.object_id() + sensor.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkSmokeDetector(sensor, hass)])
for hub in pywink.get_hubs(): for hub in pywink.get_hubs():
_id = hub.object_id() + hub.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkHub(hub, hass)]) add_devices([WinkHub(hub, hass)])
for remote in pywink.get_remotes(): for remote in pywink.get_remotes():
_id = remote.object_id() + remote.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkRemote(remote, hass)]) add_devices([WinkRemote(remote, hass)])
for button in pywink.get_buttons(): for button in pywink.get_buttons():
_id = button.object_id() + button.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkButton(button, hass)]) add_devices([WinkButton(button, hass)])
for gang in pywink.get_gangs(): for gang in pywink.get_gangs():
_id = gang.object_id() + gang.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkGang(gang, hass)]) add_devices([WinkGang(gang, hass)])
for door_bell_sensor in pywink.get_door_bells():
_id = door_bell_sensor.object_id() + door_bell_sensor.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkBinarySensorDevice(door_bell_sensor, hass)])
for camera_sensor in pywink.get_cameras():
_id = camera_sensor.object_id() + camera_sensor.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
try:
if camera_sensor.capability() in SENSOR_TYPES:
add_devices([WinkBinarySensorDevice(camera_sensor, hass)])
except AttributeError:
_LOGGER.info("Device isn't a sensor, skipping.")
class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity): class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity):
"""Representation of a Wink binary sensor.""" """Representation of a Wink binary sensor."""
@ -58,8 +92,14 @@ class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity):
def __init__(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the Wink binary sensor.""" """Initialize the Wink binary sensor."""
super().__init__(wink, hass) super().__init__(wink, hass)
try:
self._unit_of_measurement = self.wink.unit() self._unit_of_measurement = self.wink.unit()
except AttributeError:
self._unit_of_measurement = None
try:
self.capability = self.wink.capability() self.capability = self.wink.capability()
except AttributeError:
self.capability = None
@property @property
def is_on(self): def is_on(self):
@ -72,17 +112,27 @@ class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity):
return SENSOR_TYPES.get(self.capability) return SENSOR_TYPES.get(self.capability)
class WinkHub(WinkDevice, BinarySensorDevice, Entity): class WinkSmokeDetector(WinkBinarySensorDevice):
"""Representation of a Wink Hub.""" """Representation of a Wink Smoke detector."""
def __init(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the hub sensor.""" """Initialize the Wink binary sensor."""
WinkDevice.__init__(self, wink, hass) super().__init__(wink, hass)
@property @property
def is_on(self): def device_state_attributes(self):
"""Return true if the binary sensor is on.""" """Return the state attributes."""
return self.wink.state() return {
'test_activated': self.wink.test_activated()
}
class WinkHub(WinkBinarySensorDevice):
"""Representation of a Wink Hub."""
def __init__(self, wink, hass):
"""Initialize the Wink binary sensor."""
super().__init__(wink, hass)
@property @property
def device_state_attributes(self): def device_state_attributes(self):
@ -93,17 +143,12 @@ class WinkHub(WinkDevice, BinarySensorDevice, Entity):
} }
class WinkRemote(WinkDevice, BinarySensorDevice, Entity): class WinkRemote(WinkBinarySensorDevice):
"""Representation of a Wink Lutron Connected bulb remote.""" """Representation of a Wink Lutron Connected bulb remote."""
def __init(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the hub sensor.""" """Initialize the Wink binary sensor."""
WinkDevice.__init__(self, wink, hass) super().__init__(wink, hass)
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self.wink.state()
@property @property
def device_state_attributes(self): def device_state_attributes(self):
@ -115,18 +160,18 @@ class WinkRemote(WinkDevice, BinarySensorDevice, Entity):
'button_down_pressed': self.wink.button_down_pressed() 'button_down_pressed': self.wink.button_down_pressed()
} }
@property
def sensor_class(self):
"""Return the class of this sensor, from SENSOR_CLASSES."""
return None
class WinkButton(WinkDevice, BinarySensorDevice, Entity):
class WinkButton(WinkBinarySensorDevice):
"""Representation of a Wink Relay button.""" """Representation of a Wink Relay button."""
def __init(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the hub sensor.""" """Initialize the Wink binary sensor."""
WinkDevice.__init__(self, wink, hass) super().__init__(wink, hass)
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self.wink.state()
@property @property
def device_state_attributes(self): def device_state_attributes(self):
@ -137,12 +182,12 @@ class WinkButton(WinkDevice, BinarySensorDevice, Entity):
} }
class WinkGang(WinkDevice, BinarySensorDevice, Entity): class WinkGang(WinkBinarySensorDevice):
"""Representation of a Wink Relay gang.""" """Representation of a Wink Relay gang."""
def __init(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the gang sensor.""" """Initialize the Wink binary sensor."""
WinkDevice.__init__(self, wink, hass) super().__init__(wink, hass)
@property @property
def is_on(self): def is_on(self):

View file

@ -4,7 +4,7 @@ Support for Wink thermostats.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/climate.wink/ https://home-assistant.io/components/climate.wink/
""" """
from homeassistant.components.wink import WinkDevice from homeassistant.components.wink import WinkDevice, DOMAIN
from homeassistant.components.climate import ( from homeassistant.components.climate import (
STATE_AUTO, STATE_COOL, STATE_HEAT, ClimateDevice, STATE_AUTO, STATE_COOL, STATE_HEAT, ClimateDevice,
ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW,
@ -13,12 +13,16 @@ from homeassistant.components.climate import (
from homeassistant.const import ( from homeassistant.const import (
TEMP_CELSIUS, STATE_ON, TEMP_CELSIUS, STATE_ON,
STATE_OFF, STATE_UNKNOWN) STATE_OFF, STATE_UNKNOWN)
from homeassistant.loader import get_component
DEPENDENCIES = ['wink'] DEPENDENCIES = ['wink']
STATE_AUX = 'aux' STATE_AUX = 'aux'
STATE_ECO = 'eco' STATE_ECO = 'eco'
STATE_FAN = 'fan'
SPEED_LOWEST = 'lowest'
SPEED_LOW = 'low'
SPEED_MEDIUM = 'medium'
SPEED_HIGH = 'high'
ATTR_EXTERNAL_TEMPERATURE = "external_temperature" ATTR_EXTERNAL_TEMPERATURE = "external_temperature"
ATTR_SMART_TEMPERATURE = "smart_temperature" ATTR_SMART_TEMPERATURE = "smart_temperature"
@ -30,8 +34,14 @@ 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, hass, temp_unit) for climate in pywink.get_thermostats():
for thermostat in pywink.get_thermostats()) _id = climate.object_id() + climate.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkThermostat(climate, hass, temp_unit)])
for climate in pywink.get_air_conditioners():
_id = climate.object_id() + climate.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkAC(climate, hass, temp_unit)])
# pylint: disable=abstract-method,too-many-public-methods, too-many-branches # pylint: disable=abstract-method,too-many-public-methods, too-many-branches
@ -41,7 +51,6 @@ class WinkThermostat(WinkDevice, ClimateDevice):
def __init__(self, wink, hass, temp_unit): def __init__(self, wink, hass, temp_unit):
"""Initialize the Wink device.""" """Initialize the Wink device."""
super().__init__(wink, hass) super().__init__(wink, hass)
wink = get_component('wink')
self._config_temp_unit = temp_unit self._config_temp_unit = temp_unit
@property @property
@ -329,3 +338,131 @@ class WinkThermostat(WinkDevice, ClimateDevice):
else: else:
return_value = maximum return_value = maximum
return return_value return return_value
class WinkAC(WinkDevice, ClimateDevice):
"""Representation of a Wink air conditioner."""
def __init__(self, wink, hass, temp_unit):
"""Initialize the Wink device."""
super().__init__(wink, hass)
self._config_temp_unit = temp_unit
@property
def temperature_unit(self):
"""Return the unit of measurement."""
# The Wink API always returns temp in Celsius
return TEMP_CELSIUS
@property
def device_state_attributes(self):
"""Return the optional state attributes."""
data = {}
target_temp_high = self.target_temperature_high
target_temp_low = self.target_temperature_low
if target_temp_high is not None:
data[ATTR_TARGET_TEMP_HIGH] = self._convert_for_display(
self.target_temperature_high)
if target_temp_low is not None:
data[ATTR_TARGET_TEMP_LOW] = self._convert_for_display(
self.target_temperature_low)
data["total_consumption"] = self.wink.toatl_consumption()
data["schedule_enabled"] = self.wink.toatl_consumption()
return data
@property
def current_temperature(self):
"""Return the current temperature."""
return self.wink.current_temperature()
@property
def current_operation(self):
"""Return current operation ie. heat, cool, idle."""
if not self.wink.is_on():
current_op = STATE_OFF
elif self.wink.current_mode() == 'cool_only':
current_op = STATE_COOL
elif self.wink.current_mode() == 'auto_eco':
current_op = STATE_ECO
elif self.wink.current_mode() == 'fan_only':
current_op = STATE_FAN
else:
current_op = STATE_UNKNOWN
return current_op
@property
def operation_list(self):
"""List of available operation modes."""
op_list = ['off']
modes = self.wink.modes()
if 'cool_only' in modes:
op_list.append(STATE_COOL)
if 'auto_eco' in modes:
op_list.append(STATE_ECO)
if 'fan_eco' in modes:
op_list.append(STATE_FAN)
return op_list
def set_temperature(self, **kwargs):
"""Set new target temperature."""
target_temp = kwargs.get(ATTR_TEMPERATURE)
self.wink.set_temperature(target_temp)
def set_operation_mode(self, operation_mode):
"""Set operation mode."""
if operation_mode == STATE_COOL:
self.wink.set_operation_mode('cool_only')
elif operation_mode == STATE_ECO:
self.wink.set_operation_mode('auto_eco')
elif operation_mode == STATE_OFF:
self.wink.set_operation_mode('off')
elif operation_mode == STATE_FAN:
self.wink.set_operation_mode('fan_only')
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self.wink.current_max_set_point()
@property
def target_temperature_low(self):
"""Only supports cool."""
return None
@property
def target_temperature_high(self):
"""Only supports cool."""
return None
@property
def current_fan_mode(self):
"""Return the current fan mode."""
speed = self.wink.current_fan_speed()
if speed <= 0.3 and speed >= 0.0:
return SPEED_LOWEST
elif speed <= 0.5 and speed > 0.3:
return SPEED_LOW
elif speed <= 0.8 and speed > 0.5:
return SPEED_MEDIUM
elif speed <= 1.0 and speed > 0.8:
return SPEED_HIGH
else:
return STATE_UNKNOWN
@property
def fan_list(self):
"""List of available fan modes."""
return [SPEED_LOWEST, SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH]
def set_fan_mode(self, mode):
"""Set fan speed."""
if mode == SPEED_LOWEST:
speed = 0.3
elif mode == SPEED_LOW:
speed = 0.5
elif mode == SPEED_MEDIUM:
speed = 0.8
elif mode == SPEED_HIGH:
speed = 1.0
self.wink.set_ac_fan_speed(speed)

View file

@ -6,7 +6,7 @@ https://home-assistant.io/components/cover.wink/
""" """
from homeassistant.components.cover import CoverDevice from homeassistant.components.cover import CoverDevice
from homeassistant.components.wink import WinkDevice from homeassistant.components.wink import WinkDevice, DOMAIN
DEPENDENCIES = ['wink'] DEPENDENCIES = ['wink']
@ -15,10 +15,14 @@ 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, hass) for shade in for shade in pywink.get_shades():
pywink.get_shades()) _id = shade.object_id() + shade.name()
add_devices(WinkCoverDevice(door, hass) for door in if _id not in hass.data[DOMAIN]['unique_ids']:
pywink.get_garage_doors()) add_devices([WinkCoverDevice(shade, hass)])
for door in pywink.get_garage_doors():
_id = door.object_id() + door.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkCoverDevice(door, hass)])
class WinkCoverDevice(WinkDevice, CoverDevice): class WinkCoverDevice(WinkDevice, CoverDevice):
@ -26,7 +30,7 @@ class WinkCoverDevice(WinkDevice, CoverDevice):
def __init__(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the cover.""" """Initialize the cover."""
WinkDevice.__init__(self, wink, hass) super().__init__(wink, hass)
def close_cover(self): def close_cover(self):
"""Close the shade.""" """Close the shade."""

View file

@ -10,7 +10,7 @@ from homeassistant.components.fan import (FanEntity, SPEED_HIGH,
SPEED_LOW, SPEED_MEDIUM, SPEED_LOW, SPEED_MEDIUM,
STATE_UNKNOWN) STATE_UNKNOWN)
from homeassistant.helpers.entity import ToggleEntity from homeassistant.helpers.entity import ToggleEntity
from homeassistant.components.wink import WinkDevice from homeassistant.components.wink import WinkDevice, DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -22,7 +22,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink platform.""" """Setup the Wink platform."""
import pywink import pywink
add_devices(WinkFanDevice(fan, hass) for fan in pywink.get_fans()) for fan in pywink.get_fans():
if fan.object_id() + fan.name() not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkFanDevice(fan, hass)])
class WinkFanDevice(WinkDevice, FanEntity): class WinkFanDevice(WinkDevice, FanEntity):
@ -30,7 +32,7 @@ class WinkFanDevice(WinkDevice, FanEntity):
def __init__(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the fan.""" """Initialize the fan."""
WinkDevice.__init__(self, wink, hass) super().__init__(wink, hass)
def set_direction(self: ToggleEntity, direction: str) -> None: def set_direction(self: ToggleEntity, direction: str) -> None:
"""Set the direction of the fan.""" """Set the direction of the fan."""

View file

@ -9,7 +9,7 @@ import colorsys
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS,
SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light) SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light)
from homeassistant.components.wink import WinkDevice from homeassistant.components.wink import WinkDevice, DOMAIN
from homeassistant.util import color as color_util from homeassistant.util import color as color_util
from homeassistant.util.color import \ from homeassistant.util.color import \
color_temperature_mired_to_kelvin as mired_to_kelvin color_temperature_mired_to_kelvin as mired_to_kelvin
@ -23,7 +23,10 @@ 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, hass) for light in pywink.get_light_bulbs()) for light in pywink.get_light_bulbs():
_id = light.object_id() + light.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkLight(light, hass)])
class WinkLight(WinkDevice, Light): class WinkLight(WinkDevice, Light):
@ -31,7 +34,7 @@ class WinkLight(WinkDevice, Light):
def __init__(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the Wink device.""" """Initialize the Wink device."""
WinkDevice.__init__(self, wink, hass) super().__init__(wink, hass)
@property @property
def is_on(self): def is_on(self):

View file

@ -6,7 +6,7 @@ https://home-assistant.io/components/lock.wink/
""" """
from homeassistant.components.lock import LockDevice from homeassistant.components.lock import LockDevice
from homeassistant.components.wink import WinkDevice from homeassistant.components.wink import WinkDevice, DOMAIN
DEPENDENCIES = ['wink'] DEPENDENCIES = ['wink']
@ -15,7 +15,10 @@ 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, hass) for lock in pywink.get_locks()) for lock in pywink.get_locks():
_id = lock.object_id + lock.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkLockDevice(lock, hass)])
class WinkLockDevice(WinkDevice, LockDevice): class WinkLockDevice(WinkDevice, LockDevice):
@ -23,7 +26,7 @@ class WinkLockDevice(WinkDevice, LockDevice):
def __init__(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the lock.""" """Initialize the lock."""
WinkDevice.__init__(self, wink, hass) super().__init__(wink, hass)
@property @property
def is_locked(self): def is_locked(self):

View file

@ -8,10 +8,10 @@ import logging
from homeassistant.const import TEMP_CELSIUS from homeassistant.const import TEMP_CELSIUS
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.components.wink import WinkDevice from homeassistant.components.wink import WinkDevice, DOMAIN
from homeassistant.loader import get_component
DEPENDENCIES = ['wink'] DEPENDENCIES = ['wink']
_LOGGER = logging.getLogger(__name__)
SENSOR_TYPES = ['temperature', 'humidity', 'balance', 'proximity'] SENSOR_TYPES = ['temperature', 'humidity', 'balance', 'proximity']
@ -21,18 +21,29 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
import pywink import pywink
for sensor in pywink.get_sensors(): for sensor in pywink.get_sensors():
_id = sensor.object_id() + sensor.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
if sensor.capability() in SENSOR_TYPES: if sensor.capability() in SENSOR_TYPES:
add_devices([WinkSensorDevice(sensor, hass)]) add_devices([WinkSensorDevice(sensor, hass)])
for eggtray in pywink.get_eggtrays(): for eggtray in pywink.get_eggtrays():
_id = eggtray.object_id() + eggtray.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkSensorDevice(eggtray, hass)]) add_devices([WinkSensorDevice(eggtray, hass)])
for tank in pywink.get_propane_tanks():
_id = tank.object_id() + tank.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkSensorDevice(tank, hass)])
for piggy_bank in pywink.get_piggy_banks(): for piggy_bank in pywink.get_piggy_banks():
_id = piggy_bank.object_id() + piggy_bank.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
try: try:
if piggy_bank.capability() in SENSOR_TYPES: if piggy_bank.capability() in SENSOR_TYPES:
add_devices([WinkSensorDevice(piggy_bank, hass)]) add_devices([WinkSensorDevice(piggy_bank, hass)])
except AttributeError: except AttributeError:
logging.getLogger(__name__).info("Device is not a sensor") _LOGGER.info("Device is not a sensor")
class WinkSensorDevice(WinkDevice, Entity): class WinkSensorDevice(WinkDevice, Entity):
@ -41,7 +52,6 @@ class WinkSensorDevice(WinkDevice, Entity):
def __init__(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the Wink device.""" """Initialize the Wink device."""
super().__init__(wink, hass) super().__init__(wink, hass)
wink = get_component('wink')
self.capability = self.wink.capability() self.capability = self.wink.capability()
if self.wink.unit() == '°': if self.wink.unit() == '°':
self._unit_of_measurement = TEMP_CELSIUS self._unit_of_measurement = TEMP_CELSIUS

View file

@ -5,7 +5,7 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/switch.wink/ https://home-assistant.io/components/switch.wink/
""" """
from homeassistant.components.wink import WinkDevice from homeassistant.components.wink import WinkDevice, DOMAIN
from homeassistant.helpers.entity import ToggleEntity from homeassistant.helpers.entity import ToggleEntity
DEPENDENCIES = ['wink'] DEPENDENCIES = ['wink']
@ -16,12 +16,20 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
import pywink import pywink
for switch in pywink.get_switches(): for switch in pywink.get_switches():
_id = switch.object_id() + switch.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkToggleDevice(switch, hass)]) add_devices([WinkToggleDevice(switch, hass)])
for switch in pywink.get_powerstrips(): for switch in pywink.get_powerstrips():
_id = switch.object_id() + switch.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkToggleDevice(switch, hass)]) add_devices([WinkToggleDevice(switch, hass)])
for switch in pywink.get_sirens(): for switch in pywink.get_sirens():
_id = switch.object_id() + switch.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkToggleDevice(switch, hass)]) add_devices([WinkToggleDevice(switch, hass)])
for sprinkler in pywink.get_sprinklers(): for sprinkler in pywink.get_sprinklers():
_id = sprinkler.object_id() + sprinkler.name()
if _id not in hass.data[DOMAIN]['unique_ids']:
add_devices([WinkToggleDevice(sprinkler, hass)]) add_devices([WinkToggleDevice(sprinkler, hass)])
@ -30,7 +38,7 @@ class WinkToggleDevice(WinkDevice, ToggleEntity):
def __init__(self, wink, hass): def __init__(self, wink, hass):
"""Initialize the Wink device.""" """Initialize the Wink device."""
WinkDevice.__init__(self, wink, hass) super().__init__(wink, hass)
@property @property
def is_on(self): def is_on(self):
@ -44,3 +52,14 @@ class WinkToggleDevice(WinkDevice, ToggleEntity):
def turn_off(self): def turn_off(self):
"""Turn the device off.""" """Turn the device off."""
self.wink.set_state(False) self.wink.set_state(False)
@property
def device_state_attributes(self):
"""Return the state attributes."""
try:
event = self.wink.last_event()
except AttributeError:
event = None
return {
'last_event': event
}

View file

@ -15,7 +15,7 @@ from homeassistant.const import (
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==1.0.0', 'pubnubsub-handler==1.0.0'] REQUIREMENTS = ['python-wink==1.1.0', 'pubnubsub-handler==1.0.0']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -87,11 +87,16 @@ def setup(hass, config):
password = config[DOMAIN][CONF_PASSWORD] password = config[DOMAIN][CONF_PASSWORD]
payload = {'username': email, 'password': password} payload = {'username': email, 'password': password}
token_response = requests.post(CONF_TOKEN_URL, data=payload) token_response = requests.post(CONF_TOKEN_URL, data=payload)
try:
token = token_response.text.split(':')[1].split()[0].rstrip('<br') token = token_response.text.split(':')[1].split()[0].rstrip('<br')
except IndexError:
_LOGGER.error("Error getting token. Please check email/password.")
return False
pywink.set_bearer_token(token) pywink.set_bearer_token(token)
hass.data[DOMAIN] = {} hass.data[DOMAIN] = {}
hass.data[DOMAIN]['entities'] = [] hass.data[DOMAIN]['entities'] = []
hass.data[DOMAIN]['unique_ids'] = []
hass.data[DOMAIN]['pubnub'] = PubNubSubscriptionHandler( hass.data[DOMAIN]['pubnub'] = PubNubSubscriptionHandler(
pywink.get_subscription_key(), pywink.get_subscription_key(),
pywink.wink_api_fetch) pywink.wink_api_fetch)
@ -113,6 +118,13 @@ def setup(hass, config):
entity.update_ha_state(True) entity.update_ha_state(True)
hass.services.register(DOMAIN, 'Refresh state from Wink', force_update) hass.services.register(DOMAIN, 'Refresh state from Wink', force_update)
def pull_new_devices(call):
"""Pull new devices added to users Wink account since startup."""
_LOGGER.info("Getting new devices from Wink API.")
for component in WINK_COMPONENTS:
discovery.load_platform(hass, component, DOMAIN, {}, config)
hass.services.register(DOMAIN, 'Add new devices', pull_new_devices)
# 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)
@ -131,6 +143,8 @@ class WinkDevice(Entity):
hass.data[DOMAIN]['pubnub'].add_subscription( hass.data[DOMAIN]['pubnub'].add_subscription(
self.wink.pubnub_channel, self._pubnub_update) self.wink.pubnub_channel, self._pubnub_update)
hass.data[DOMAIN]['entities'].append(self) hass.data[DOMAIN]['entities'].append(self)
hass.data[DOMAIN]['unique_ids'].append(self.wink.object_id() +
self.wink.name())
def _pubnub_update(self, message): def _pubnub_update(self, message):
try: try:
@ -168,13 +182,42 @@ class WinkDevice(Entity):
@property @property
def device_state_attributes(self): def device_state_attributes(self):
"""Return the state attributes.""" """Return the state attributes."""
attributes = {}
if self._battery: if self._battery:
return { attributes[ATTR_BATTERY_LEVEL] = self._battery_level
ATTR_BATTERY_LEVEL: self._battery_level, if self._manufacturer_device_model:
} _model = self._manufacturer_device_model
attributes["manufacturer_device_model"] = _model
if self._manufacturer_device_id:
attributes["manufacturer_device_id"] = self._manufacturer_device_id
if self._device_manufacturer:
attributes["device_manufacturer"] = self._device_manufacturer
if self._model_name:
attributes["model_name"] = self._model_name
return attributes
@property @property
def _battery_level(self): def _battery_level(self):
"""Return the battery level.""" """Return the battery level."""
if self.wink.battery_level() is not None: if self.wink.battery_level() is not None:
return self.wink.battery_level() * 100 return self.wink.battery_level() * 100
@property
def _manufacturer_device_model(self):
"""Return the manufacturer device model."""
return self.wink.manufacturer_device_model()
@property
def _manufacturer_device_id(self):
"""Return the manufacturer device id."""
return self.wink.manufacturer_device_id()
@property
def _device_manufacturer(self):
"""Return the device manufacturer."""
return self.wink.device_manufacturer()
@property
def _model_name(self):
"""Return the model name."""
return self.wink.model_name()

View file

@ -534,7 +534,7 @@ python-twitch==1.3.0
python-vlc==1.1.2 python-vlc==1.1.2
# homeassistant.components.wink # homeassistant.components.wink
python-wink==1.0.0 python-wink==1.1.0
# homeassistant.components.device_tracker.trackr # homeassistant.components.device_tracker.trackr
pytrackr==0.0.5 pytrackr==0.0.5