Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for the Quirky Nimbus #16520

Merged
merged 3 commits into from
Sep 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions homeassistant/components/climate/wink.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,24 +118,24 @@ def device_state_attributes(self):
self.hass, self.target_temperature_low, self.temperature_unit,
PRECISION_TENTHS)

if self.external_temperature:
if self.external_temperature is not None:
data[ATTR_EXTERNAL_TEMPERATURE] = show_temp(
self.hass, self.external_temperature, self.temperature_unit,
PRECISION_TENTHS)

if self.smart_temperature:
data[ATTR_SMART_TEMPERATURE] = self.smart_temperature

if self.occupied:
if self.occupied is not None:
data[ATTR_OCCUPIED] = self.occupied

if self.eco_target:
if self.eco_target is not None:
data[ATTR_ECO_TARGET] = self.eco_target

if self.heat_on:
if self.heat_on is not None:
data[ATTR_HEAT_ON] = self.heat_on

if self.cool_on:
if self.cool_on is not None:
data[ATTR_COOL_ON] = self.cool_on

current_humidity = self.current_humidity
Expand Down
163 changes: 152 additions & 11 deletions homeassistant/components/wink/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from homeassistant.helpers.event import track_time_interval
from homeassistant.util.json import load_json, save_json

REQUIREMENTS = ['python-wink==1.9.1', 'pubnubsub-handler==1.0.2']
REQUIREMENTS = ['python-wink==1.10.1', 'pubnubsub-handler==1.0.2']

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -73,11 +73,25 @@
SERVICE_SIREN_STROBE_ENABLED = "set_siren_strobe_enabled"
SERVICE_CHIME_STROBE_ENABLED = "set_chime_strobe_enabled"
SERVICE_ENABLE_SIREN = "enable_siren"
SERVICE_SET_DIAL_CONFIG = "set_nimbus_dial_configuration"
SERVICE_SET_DIAL_STATE = "set_nimbus_dial_state"

ATTR_VOLUME = "volume"
ATTR_TONE = "tone"
ATTR_ENABLED = "enabled"
ATTR_AUTO_SHUTOFF = "auto_shutoff"
ATTR_MIN_VALUE = "min_value"
ATTR_MAX_VALUE = "max_value"
ATTR_ROTATION = "rotation"
ATTR_SCALE = "scale"
ATTR_TICKS = "ticks"
ATTR_MIN_POSITION = "min_position"
ATTR_MAX_POSITION = "max_position"
ATTR_VALUE = "value"
ATTR_LABELS = "labels"

SCALES = ["linear", "log"]
ROTATIONS = ["cw", "ccw"]

VOLUMES = ["low", "medium", "high"]
TONES = ["doorbell", "fur_elise", "doorbell_extended", "alert",
Expand Down Expand Up @@ -145,6 +159,23 @@
vol.Required(ATTR_ENABLED): cv.boolean
})

DIAL_CONFIG_SCHEMA = vol.Schema({
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
vol.Optional(ATTR_MIN_VALUE): vol.Coerce(int),
vol.Optional(ATTR_MAX_VALUE): vol.Coerce(int),
vol.Optional(ATTR_MIN_POSITION): cv.positive_int,
vol.Optional(ATTR_MAX_POSITION): cv.positive_int,
vol.Optional(ATTR_ROTATION): vol.In(ROTATIONS),
vol.Optional(ATTR_SCALE): vol.In(SCALES),
vol.Optional(ATTR_TICKS): cv.positive_int
})

DIAL_STATE_SCHEMA = vol.Schema({
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
vol.Required(ATTR_VALUE): vol.Coerce(int),
vol.Optional(ATTR_LABELS): cv.ensure_list(cv.string)
})

WINK_COMPONENTS = [
'binary_sensor', 'sensor', 'light', 'switch', 'lock', 'cover', 'climate',
'fan', 'alarm_control_panel', 'scene'
Expand Down Expand Up @@ -432,8 +463,23 @@ def delete_device(call):
DOMAIN, SERVICE_SET_PAIRING_MODE, set_pairing_mode,
schema=SET_PAIRING_MODE_SCHEMA)

def service_handle(service):
"""Handle services."""
def nimbus_service_handle(service):
"""Handle nimbus services."""
entity_id = service.data.get('entity_id')[0]
_all_dials = []
for sensor in hass.data[DOMAIN]['entities']['sensor']:
if isinstance(sensor, WinkNimbusDialDevice):
_all_dials.append(sensor)
for _dial in _all_dials:
if _dial.entity_id == entity_id:
if service.service == SERVICE_SET_DIAL_CONFIG:
_dial.set_configuration(**service.data)
if service.service == SERVICE_SET_DIAL_STATE:
_dial.wink.set_state(service.data.get("value"),
service.data.get("labels"))

def siren_service_handle(service):
"""Handle siren services."""
entity_ids = service.data.get('entity_id')
all_sirens = []
for switch in hass.data[DOMAIN]['entities']['switch']:
Expand Down Expand Up @@ -495,41 +541,68 @@ def service_handle(service):
if sirens:

hass.services.register(DOMAIN, SERVICE_SET_AUTO_SHUTOFF,
service_handle,
siren_service_handle,
schema=SET_AUTO_SHUTOFF_SCHEMA)

hass.services.register(DOMAIN, SERVICE_ENABLE_SIREN,
service_handle,
siren_service_handle,
schema=ENABLED_SIREN_SCHEMA)

if has_dome_or_wink_siren:

hass.services.register(DOMAIN, SERVICE_SET_SIREN_TONE,
service_handle,
siren_service_handle,
schema=SET_SIREN_TONE_SCHEMA)

hass.services.register(DOMAIN, SERVICE_ENABLE_CHIME,
service_handle,
siren_service_handle,
schema=SET_CHIME_MODE_SCHEMA)

hass.services.register(DOMAIN, SERVICE_SET_SIREN_VOLUME,
service_handle,
siren_service_handle,
schema=SET_VOLUME_SCHEMA)

hass.services.register(DOMAIN, SERVICE_SET_CHIME_VOLUME,
service_handle,
siren_service_handle,
schema=SET_VOLUME_SCHEMA)

hass.services.register(DOMAIN, SERVICE_SIREN_STROBE_ENABLED,
service_handle,
siren_service_handle,
schema=SET_STROBE_ENABLED_SCHEMA)

hass.services.register(DOMAIN, SERVICE_CHIME_STROBE_ENABLED,
service_handle,
siren_service_handle,
schema=SET_STROBE_ENABLED_SCHEMA)

component.add_entities(sirens)

nimbi = []
dials = {}
all_nimbi = pywink.get_cloud_clocks()
all_dials = []
for nimbus in all_nimbi:
if nimbus.object_type() == "cloud_clock":
nimbi.append(nimbus)
dials[nimbus.object_id()] = []
for nimbus in all_nimbi:
if nimbus.object_type() == "dial":
dials[nimbus.parent_id()].append(nimbus)

for nimbus in nimbi:
for dial in dials[nimbus.object_id()]:
all_dials.append(WinkNimbusDialDevice(nimbus, dial, hass))

if nimbi:
hass.services.register(DOMAIN, SERVICE_SET_DIAL_CONFIG,
nimbus_service_handle,
schema=DIAL_CONFIG_SCHEMA)

hass.services.register(DOMAIN, SERVICE_SET_DIAL_STATE,
nimbus_service_handle,
schema=DIAL_STATE_SCHEMA)

component.add_entities(all_dials)

return True


Expand Down Expand Up @@ -596,6 +669,7 @@ def __init__(self, wink, hass):
self.wink.name())

def _pubnub_update(self, message):
_LOGGER.debug(message)
try:
if message is None:
_LOGGER.error("Error on pubnub update for %s "
Expand Down Expand Up @@ -740,3 +814,70 @@ def device_state_attributes(self):
attributes["chime_mode"] = chime_mode

return attributes


class WinkNimbusDialDevice(WinkDevice):
"""Representation of the Quirky Nimbus device."""

def __init__(self, nimbus, dial, hass):
"""Initialize the Nimbus dial."""
super().__init__(dial, hass)
self.parent = nimbus

@asyncio.coroutine
def async_added_to_hass(self):
"""Call when entity is added to hass."""
self.hass.data[DOMAIN]['entities']['sensor'].append(self)

@property
def state(self):
"""Return dials current value."""
return self.wink.state()

@property
def name(self):
"""Return the name of the device."""
return self.parent.name() + " dial " + str(self.wink.index() + 1)

@property
def device_state_attributes(self):
"""Return the device state attributes."""
attributes = super(WinkNimbusDialDevice, self).device_state_attributes
dial_attributes = self.dial_attributes()

return {**attributes, **dial_attributes}

def dial_attributes(self):
"""Return the dial only attributes."""
return {
"labels": self.wink.labels(),
"position": self.wink.position(),
"rotation": self.wink.rotation(),
"max_value": self.wink.max_value(),
"min_value": self.wink.min_value(),
"num_ticks": self.wink.ticks(),
"scale_type": self.wink.scale(),
"max_position": self.wink.max_position(),
"min_position": self.wink.min_position()
}

def set_configuration(self, **kwargs):
"""
Set the dial config.

Anything not sent will default to current setting.
"""
attributes = {**self.dial_attributes(), **kwargs}

min_value = attributes["min_value"]
max_value = attributes["max_value"]
rotation = attributes["rotation"]
ticks = attributes["num_ticks"]
scale = attributes["scale_type"]
min_position = attributes["min_position"]
max_position = attributes["max_position"]

self.wink.set_configuration(min_value, max_value, rotation,
scale=scale, ticks=ticks,
min_position=min_position,
max_position=max_position)
41 changes: 41 additions & 0 deletions homeassistant/components/wink/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,44 @@ set_chime_volume:
volume:
description: Volume level. One of ["low", "medium", "high"]
example: "low"

set_nimbus_dial_configuration:
description: Set the configuration of an individual nimbus dial
fields:
entity_id:
description: Name of the entity to set.
example: 'wink.nimbus_dial_3'
rotation:
description: Direction dial hand should spin ["cw" or "ccw"]
example: 'cw'
ticks:
description: Number of times the hand should move
example: 12
scale:
description: How the dial should move in response to higher values ["log" or "linear"]
example: "linear"
min_value:
description: The minimum value allowed to be set
example: 0
max_value:
description: The maximum value allowd to be set
example: 500
min_position:
description: The minimum position the dial hand can rotate to generally [0-360]
example: 0
max_position:
description: The maximum position the dial hand can rotate to generally [0-360]
example: 360

set_nimbus_dial_state:
description: Set the value and lables of an individual nimbus dial
fields:
entity_id:
description: Name fo the entity to set.
example: 'wink.nimbus_dial_3'
value:
description: The value that should be set (Should be between min_value and max_value)
example: 250
labels:
description: The values shown on the dial labels ["Dial 1", "test"] the first value is what is shown by default the second value is shown when the nimbus is pressed
example: ["example", "test"]
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,7 @@ python-velbus==2.0.19
python-vlc==1.1.2

# homeassistant.components.wink
python-wink==1.9.1
python-wink==1.10.1

# homeassistant.components.sensor.swiss_public_transport
python_opendata_transport==0.1.3
Expand Down