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

Wink sensors #21

Closed
wants to merge 9 commits into from
Closed
2 changes: 1 addition & 1 deletion homeassistant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
DOMAIN = "homeassistant"

# How often time_changed event should fire
TIMER_INTERVAL = 10 # seconds
TIMER_INTERVAL = 3 # seconds
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this one is dangerous, there are a bunch of components that listen to each time changed events to update their state. I'll make sure I'll update them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is basically hinged on the shitty Wink API. I can't find a way to get pushed, and I want to trigger lights on door entry. Chicken? Egg?

If we could get push from wink it would be easy, but waiting 10s to go to the bathroom at 2am sucks.


# How long we wait for the result of a service call
SERVICE_CALL_LIMIT = 10 # seconds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
case "thermostat":
return "homeassistant:thermostat";

case "sensor":
return "visibility";

default:
return "bookmark-outline";
}
Expand Down
89 changes: 89 additions & 0 deletions homeassistant/components/sensor/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
homeassistant.components.sensor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component to interface with various sensors that can be monitored.
"""
import logging
from datetime import timedelta

from homeassistant.loader import get_component
import homeassistant.util as util
from homeassistant.const import (
STATE_OPEN)
from homeassistant.helpers import (
platform_devices_from_config)
from homeassistant.components import group, discovery, wink

DOMAIN = 'sensor'
DEPENDENCIES = []

GROUP_NAME_ALL_SENSORS = 'all_sensors'
ENTITY_ID_ALL_SENSORS = group.ENTITY_ID_FORMAT.format(
GROUP_NAME_ALL_SENSORS)

ENTITY_ID_FORMAT = DOMAIN + '.{}'

MIN_TIME_BETWEEN_SCANS = timedelta(seconds=1)

# Maps discovered services to their platforms
DISCOVERY_PLATFORMS = {
wink.DISCOVER_SENSORS: 'wink',
}

_LOGGER = logging.getLogger(__name__)


def is_on(hass, entity_id=None):
""" Returns if the sensor is open based on the statemachine. """
entity_id = entity_id or ENTITY_ID_ALL_SENSORS

return hass.states.is_state(entity_id, STATE_OPEN)


def setup(hass, config):
""" Track states and offer events for sensors. """
logger = logging.getLogger(__name__)

sensors = platform_devices_from_config(
config, DOMAIN, hass, ENTITY_ID_FORMAT, logger)

# pylint: disable=unused-argument
@util.Throttle(MIN_TIME_BETWEEN_SCANS)
def update_sensor_states(now):
""" Update states of all sensors. """
if sensors:
logger.info("Updating sensor states")

for sensor in sensors.values():
sensor.update_ha_state(hass, True)

update_sensor_states(None)

# Track all sensors in a group
sensor_group = group.Group(
hass, GROUP_NAME_ALL_SENSORS, sensors.keys(), False)

def sensor_discovered(service, info):
""" Called when a sensor is discovered. """
platform = get_component("{}.{}".format(
DOMAIN, DISCOVERY_PLATFORMS[service]))

discovered = platform.devices_discovered(hass, config, info)

for sensor in discovered:
if sensor is not None and sensor not in sensors.values():
sensor.entity_id = util.ensure_unique_string(
ENTITY_ID_FORMAT.format(util.slugify(sensor.name)),
sensors.keys())

sensors[sensor.entity_id] = sensor

sensor.update_ha_state(hass)

sensor_group.update_tracked_entity_ids(sensors.keys())

discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), sensor_discovered)

hass.track_time_change(update_sensor_states)

return True
35 changes: 35 additions & 0 deletions homeassistant/components/sensor/wink.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
""" Support for Wink sensors. """
import logging

# pylint: disable=no-name-in-module, import-error
import homeassistant.external.wink.pywink as pywink

from homeassistant.components.wink import WinkSensorDevice
from homeassistant.const import CONF_ACCESS_TOKEN


# pylint: disable=unused-argument
def get_devices(hass, config):
""" Find and return Wink sensors. """
token = config.get(CONF_ACCESS_TOKEN)

if token is None:
logging.getLogger(__name__).error(
"Missing wink access_token - "
"get one at https://winkbearertoken.appspot.com/")
return []

pywink.set_bearer_token(token)

return get_sensors()


# pylint: disable=unused-argument
def devices_discovered(hass, config, info):
""" Called when a device is discovered. """
return get_sensors()


def get_sensors():
""" Returns the Wink sensors. """
return [WinkSensorDevice(sensor) for sensor in pywink.get_sensors()]
45 changes: 43 additions & 2 deletions homeassistant/components/wink.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@

from homeassistant import bootstrap
from homeassistant.loader import get_component
from homeassistant.helpers import validate_config, ToggleDevice
from homeassistant.helpers import validate_config, ToggleDevice, Device
from homeassistant.const import (
EVENT_PLATFORM_DISCOVERED, CONF_ACCESS_TOKEN,
STATE_OPEN, STATE_CLOSED,
ATTR_SERVICE, ATTR_DISCOVERED, ATTR_FRIENDLY_NAME)

DOMAIN = "wink"
DEPENDENCIES = []

DISCOVER_LIGHTS = "wink.lights"
DISCOVER_SWITCHES = "wink.switches"
DISCOVER_SENSORS = "wink.sensors"


def setup(hass, config):
Expand All @@ -32,7 +34,8 @@ def setup(hass, config):
# Load components for the devices in the Wink that we support
for component_name, func_exists, discovery_type in (
('light', pywink.get_bulbs, DISCOVER_LIGHTS),
('switch', pywink.get_switches, DISCOVER_SWITCHES)):
('switch', pywink.get_switches, DISCOVER_SWITCHES),
('sensor', pywink.get_sensors, DISCOVER_SENSORS)):

if func_exists():
component = get_component(component_name)
Expand All @@ -50,6 +53,44 @@ def setup(hass, config):
return True


class WinkSensorDevice(Device):
""" represents a wink sensor within home assistant. """

def __init__(self, wink):
self.wink = wink

@property
def state(self):
""" Returns the state. """
return STATE_OPEN if self.is_open else STATE_CLOSED

@property
def unique_id(self):
""" Returns the id of this wink switch """
return "{}.{}".format(self.__class__, self.wink.deviceId())

@property
def name(self):
""" Returns the name of the sensor if any. """
return self.wink.name()

@property
def state_attributes(self):
""" Returns optional state attributes. """
return {
ATTR_FRIENDLY_NAME: self.wink.name()
}

def update(self):
""" Update state of the sensor. """
self.wink.updateState()

@property
def is_open(self):
""" True if door is open. """
return self.wink.state()


class WinkToggleDevice(ToggleDevice):
""" represents a WeMo switch within home assistant. """

Expand Down
2 changes: 2 additions & 0 deletions homeassistant/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
STATE_HOME = 'home'
STATE_NOT_HOME = 'not_home'
STATE_UNKNOWN = "unknown"
STATE_OPEN = 'open'
STATE_CLOSED = 'closed'

# #### STATE AND EVENT ATTRIBUTES ####
# Contains current time for a TIME_CHANGED event
Expand Down
Loading