mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 17:57:11 +00:00
Support for the Quirky Nimbus (#16520)
* Support for quriky nimbu * Fixed lint * fixed some typos
This commit is contained in:
parent
aec134c47a
commit
f43d9ba680
@ -118,7 +118,7 @@ class WinkThermostat(WinkDevice, ClimateDevice):
|
|||||||
self.hass, self.target_temperature_low, self.temperature_unit,
|
self.hass, self.target_temperature_low, self.temperature_unit,
|
||||||
PRECISION_TENTHS)
|
PRECISION_TENTHS)
|
||||||
|
|
||||||
if self.external_temperature:
|
if self.external_temperature is not None:
|
||||||
data[ATTR_EXTERNAL_TEMPERATURE] = show_temp(
|
data[ATTR_EXTERNAL_TEMPERATURE] = show_temp(
|
||||||
self.hass, self.external_temperature, self.temperature_unit,
|
self.hass, self.external_temperature, self.temperature_unit,
|
||||||
PRECISION_TENTHS)
|
PRECISION_TENTHS)
|
||||||
@ -126,16 +126,16 @@ class WinkThermostat(WinkDevice, ClimateDevice):
|
|||||||
if self.smart_temperature:
|
if self.smart_temperature:
|
||||||
data[ATTR_SMART_TEMPERATURE] = self.smart_temperature
|
data[ATTR_SMART_TEMPERATURE] = self.smart_temperature
|
||||||
|
|
||||||
if self.occupied:
|
if self.occupied is not None:
|
||||||
data[ATTR_OCCUPIED] = self.occupied
|
data[ATTR_OCCUPIED] = self.occupied
|
||||||
|
|
||||||
if self.eco_target:
|
if self.eco_target is not None:
|
||||||
data[ATTR_ECO_TARGET] = self.eco_target
|
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
|
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
|
data[ATTR_COOL_ON] = self.cool_on
|
||||||
|
|
||||||
current_humidity = self.current_humidity
|
current_humidity = self.current_humidity
|
||||||
|
@ -26,7 +26,7 @@ from homeassistant.helpers.entity_component import EntityComponent
|
|||||||
from homeassistant.helpers.event import track_time_interval
|
from homeassistant.helpers.event import track_time_interval
|
||||||
from homeassistant.util.json import load_json, save_json
|
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__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -73,11 +73,25 @@ SERVICE_SET_AUTO_SHUTOFF = "siren_set_auto_shutoff"
|
|||||||
SERVICE_SIREN_STROBE_ENABLED = "set_siren_strobe_enabled"
|
SERVICE_SIREN_STROBE_ENABLED = "set_siren_strobe_enabled"
|
||||||
SERVICE_CHIME_STROBE_ENABLED = "set_chime_strobe_enabled"
|
SERVICE_CHIME_STROBE_ENABLED = "set_chime_strobe_enabled"
|
||||||
SERVICE_ENABLE_SIREN = "enable_siren"
|
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_VOLUME = "volume"
|
||||||
ATTR_TONE = "tone"
|
ATTR_TONE = "tone"
|
||||||
ATTR_ENABLED = "enabled"
|
ATTR_ENABLED = "enabled"
|
||||||
ATTR_AUTO_SHUTOFF = "auto_shutoff"
|
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"]
|
VOLUMES = ["low", "medium", "high"]
|
||||||
TONES = ["doorbell", "fur_elise", "doorbell_extended", "alert",
|
TONES = ["doorbell", "fur_elise", "doorbell_extended", "alert",
|
||||||
@ -145,6 +159,23 @@ ENABLED_SIREN_SCHEMA = vol.Schema({
|
|||||||
vol.Required(ATTR_ENABLED): cv.boolean
|
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 = [
|
WINK_COMPONENTS = [
|
||||||
'binary_sensor', 'sensor', 'light', 'switch', 'lock', 'cover', 'climate',
|
'binary_sensor', 'sensor', 'light', 'switch', 'lock', 'cover', 'climate',
|
||||||
'fan', 'alarm_control_panel', 'scene'
|
'fan', 'alarm_control_panel', 'scene'
|
||||||
@ -432,8 +463,23 @@ def setup(hass, config):
|
|||||||
DOMAIN, SERVICE_SET_PAIRING_MODE, set_pairing_mode,
|
DOMAIN, SERVICE_SET_PAIRING_MODE, set_pairing_mode,
|
||||||
schema=SET_PAIRING_MODE_SCHEMA)
|
schema=SET_PAIRING_MODE_SCHEMA)
|
||||||
|
|
||||||
def service_handle(service):
|
def nimbus_service_handle(service):
|
||||||
"""Handle services."""
|
"""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')
|
entity_ids = service.data.get('entity_id')
|
||||||
all_sirens = []
|
all_sirens = []
|
||||||
for switch in hass.data[DOMAIN]['entities']['switch']:
|
for switch in hass.data[DOMAIN]['entities']['switch']:
|
||||||
@ -495,41 +541,68 @@ def setup(hass, config):
|
|||||||
if sirens:
|
if sirens:
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_SET_AUTO_SHUTOFF,
|
hass.services.register(DOMAIN, SERVICE_SET_AUTO_SHUTOFF,
|
||||||
service_handle,
|
siren_service_handle,
|
||||||
schema=SET_AUTO_SHUTOFF_SCHEMA)
|
schema=SET_AUTO_SHUTOFF_SCHEMA)
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_ENABLE_SIREN,
|
hass.services.register(DOMAIN, SERVICE_ENABLE_SIREN,
|
||||||
service_handle,
|
siren_service_handle,
|
||||||
schema=ENABLED_SIREN_SCHEMA)
|
schema=ENABLED_SIREN_SCHEMA)
|
||||||
|
|
||||||
if has_dome_or_wink_siren:
|
if has_dome_or_wink_siren:
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_SET_SIREN_TONE,
|
hass.services.register(DOMAIN, SERVICE_SET_SIREN_TONE,
|
||||||
service_handle,
|
siren_service_handle,
|
||||||
schema=SET_SIREN_TONE_SCHEMA)
|
schema=SET_SIREN_TONE_SCHEMA)
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_ENABLE_CHIME,
|
hass.services.register(DOMAIN, SERVICE_ENABLE_CHIME,
|
||||||
service_handle,
|
siren_service_handle,
|
||||||
schema=SET_CHIME_MODE_SCHEMA)
|
schema=SET_CHIME_MODE_SCHEMA)
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_SET_SIREN_VOLUME,
|
hass.services.register(DOMAIN, SERVICE_SET_SIREN_VOLUME,
|
||||||
service_handle,
|
siren_service_handle,
|
||||||
schema=SET_VOLUME_SCHEMA)
|
schema=SET_VOLUME_SCHEMA)
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_SET_CHIME_VOLUME,
|
hass.services.register(DOMAIN, SERVICE_SET_CHIME_VOLUME,
|
||||||
service_handle,
|
siren_service_handle,
|
||||||
schema=SET_VOLUME_SCHEMA)
|
schema=SET_VOLUME_SCHEMA)
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_SIREN_STROBE_ENABLED,
|
hass.services.register(DOMAIN, SERVICE_SIREN_STROBE_ENABLED,
|
||||||
service_handle,
|
siren_service_handle,
|
||||||
schema=SET_STROBE_ENABLED_SCHEMA)
|
schema=SET_STROBE_ENABLED_SCHEMA)
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_CHIME_STROBE_ENABLED,
|
hass.services.register(DOMAIN, SERVICE_CHIME_STROBE_ENABLED,
|
||||||
service_handle,
|
siren_service_handle,
|
||||||
schema=SET_STROBE_ENABLED_SCHEMA)
|
schema=SET_STROBE_ENABLED_SCHEMA)
|
||||||
|
|
||||||
component.add_entities(sirens)
|
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
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -596,6 +669,7 @@ class WinkDevice(Entity):
|
|||||||
self.wink.name())
|
self.wink.name())
|
||||||
|
|
||||||
def _pubnub_update(self, message):
|
def _pubnub_update(self, message):
|
||||||
|
_LOGGER.debug(message)
|
||||||
try:
|
try:
|
||||||
if message is None:
|
if message is None:
|
||||||
_LOGGER.error("Error on pubnub update for %s "
|
_LOGGER.error("Error on pubnub update for %s "
|
||||||
@ -740,3 +814,70 @@ class WinkSirenDevice(WinkDevice):
|
|||||||
attributes["chime_mode"] = chime_mode
|
attributes["chime_mode"] = chime_mode
|
||||||
|
|
||||||
return attributes
|
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)
|
||||||
|
@ -111,3 +111,44 @@ set_chime_volume:
|
|||||||
volume:
|
volume:
|
||||||
description: Volume level. One of ["low", "medium", "high"]
|
description: Volume level. One of ["low", "medium", "high"]
|
||||||
example: "low"
|
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"]
|
@ -1160,7 +1160,7 @@ python-velbus==2.0.19
|
|||||||
python-vlc==1.1.2
|
python-vlc==1.1.2
|
||||||
|
|
||||||
# homeassistant.components.wink
|
# homeassistant.components.wink
|
||||||
python-wink==1.9.1
|
python-wink==1.10.1
|
||||||
|
|
||||||
# homeassistant.components.sensor.swiss_public_transport
|
# homeassistant.components.sensor.swiss_public_transport
|
||||||
python_opendata_transport==0.1.3
|
python_opendata_transport==0.1.3
|
||||||
|
Loading…
x
Reference in New Issue
Block a user