Merge remote-tracking branch 'origin/remove-external' into dev

This commit is contained in:
Paulus Schoutsen 2015-07-24 04:11:31 -07:00
commit c1b6d03d1b
18 changed files with 59 additions and 499 deletions

12
.gitmodules vendored
View File

@ -1,12 +1,3 @@
[submodule "homeassistant/external/pynetgear"]
path = homeassistant/external/pynetgear
url = https://github.com/balloob/pynetgear.git
[submodule "homeassistant/external/pywemo"]
path = homeassistant/external/pywemo
url = https://github.com/balloob/pywemo.git
[submodule "homeassistant/external/netdisco"]
path = homeassistant/external/netdisco
url = https://github.com/balloob/netdisco.git
[submodule "homeassistant/external/noop"]
path = homeassistant/external/noop
url = https://github.com/balloob/noop.git
@ -16,9 +7,6 @@
[submodule "homeassistant/external/nzbclients"]
path = homeassistant/external/nzbclients
url = https://github.com/jamespcole/home-assistant-nzb-clients.git
[submodule "homeassistant/external/pymysensors"]
path = homeassistant/external/pymysensors
url = https://github.com/theolind/pymysensors
[submodule "homeassistant/components/frontend/www_static/home-assistant-polymer"]
path = homeassistant/components/frontend/www_static/home-assistant-polymer
url = https://github.com/balloob/home-assistant-polymer.git

View File

@ -43,6 +43,7 @@ from homeassistant.components.device_tracker import DOMAIN
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['pynetgear>=0.1']
def get_scanner(hass, config):
@ -64,22 +65,10 @@ class NetgearDeviceScanner(object):
""" This class queries a Netgear wireless router using the SOAP-API. """
def __init__(self, host, username, password):
import pynetgear
self.last_results = []
try:
# Pylint does not play nice if not every folders has an __init__.py
# pylint: disable=no-name-in-module, import-error
import homeassistant.external.pynetgear.pynetgear as pynetgear
except ImportError:
_LOGGER.exception(
("Failed to import pynetgear. "
"Did you maybe not run `git submodule init` "
"and `git submodule update`?"))
self.success_init = False
return
self._api = pynetgear.Netgear(host, username, password)
self.lock = threading.Lock()

View File

@ -12,9 +12,6 @@ loaded before the EVENT_PLATFORM_DISCOVERED is fired.
import logging
import threading
# pylint: disable=no-name-in-module, import-error
import homeassistant.external.netdisco.netdisco.const as services
from homeassistant import bootstrap
from homeassistant.const import (
EVENT_HOMEASSISTANT_START, EVENT_PLATFORM_DISCOVERED,
@ -22,14 +19,20 @@ from homeassistant.const import (
DOMAIN = "discovery"
DEPENDENCIES = []
REQUIREMENTS = ['zeroconf>=0.16.0']
REQUIREMENTS = ['netdisco>=0.1']
SCAN_INTERVAL = 300 # seconds
# Next 3 lines for now a mirror from netdisco.const
# Should setup a mapping netdisco.const -> own constants
SERVICE_WEMO = 'belkin_wemo'
SERVICE_HUE = 'philips_hue'
SERVICE_CAST = 'google_cast'
SERVICE_HANDLERS = {
services.BELKIN_WEMO: "switch",
services.GOOGLE_CAST: "media_player",
services.PHILIPS_HUE: "light",
SERVICE_WEMO: "switch",
SERVICE_CAST: "media_player",
SERVICE_HUE: "light",
}
@ -56,14 +59,7 @@ def setup(hass, config):
""" Starts a discovery service. """
logger = logging.getLogger(__name__)
try:
from homeassistant.external.netdisco.netdisco.service import \
DiscoveryService
except ImportError:
logger.exception(
"Unable to import netdisco. "
"Did you install all the zeroconf dependency?")
return False
from netdisco.service import DiscoveryService
# Disable zeroconf logging, it spams
logging.getLogger('zeroconf').setLevel(logging.CRITICAL)

View File

@ -99,7 +99,7 @@ LIGHT_PROFILES_FILE = "light_profiles.csv"
DISCOVERY_PLATFORMS = {
wink.DISCOVER_LIGHTS: 'wink',
isy994.DISCOVER_LIGHTS: 'isy994',
discovery.services.PHILIPS_HUE: 'hue',
discovery.SERVICE_HUE: 'hue',
}
PROP_TO_ATTR = {

View File

@ -1,9 +1,6 @@
""" Support for Hue lights. """
""" Support for Wink lights. """
import logging
# pylint: disable=no-name-in-module, import-error
import homeassistant.external.wink.pywink as pywink
from homeassistant.components.light import ATTR_BRIGHTNESS
from homeassistant.components.wink import WinkToggleDevice
from homeassistant.const import CONF_ACCESS_TOKEN
@ -11,6 +8,8 @@ from homeassistant.const import CONF_ACCESS_TOKEN
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
""" Find and return Wink lights. """
import pywink
token = config.get(CONF_ACCESS_TOKEN)
if not pywink.is_token_set() and token is None:

View File

@ -24,7 +24,7 @@ SCAN_INTERVAL = 30
ENTITY_ID_FORMAT = DOMAIN + '.{}'
DISCOVERY_PLATFORMS = {
discovery.services.GOOGLE_CAST: 'cast',
discovery.SERVICE_CAST: 'cast',
}
SERVICE_YOUTUBE_VIDEO = 'play_youtube_video'

View File

@ -21,9 +21,6 @@ Port of your connection to your MySensors device.
"""
import logging
# pylint: disable=no-name-in-module, import-error
import homeassistant.external.pymysensors.mysensors.mysensors as mysensors
import homeassistant.external.pymysensors.mysensors.const as const
from homeassistant.helpers.entity import Entity
from homeassistant.const import (
@ -39,12 +36,16 @@ ATTR_NODE_ID = "node_id"
ATTR_CHILD_ID = "child_id"
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['pyserial>=2.7']
REQUIREMENTS = ['https://github.com/theolind/pymysensors/archive/master.zip'
'#egg=pymysensors-0.1']
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Setup the mysensors platform. """
import mysensors.mysensors as mysensors
import mysensors.const as const
devices = {} # keep track of devices added to HA
# Just assume celcius means that the user wants metric for now.
# It may make more sense to make this a global config option in the future.
@ -69,7 +70,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
name = '{} {}.{}'.format(sensor.sketch_name, nid, child.id)
node[child_id][value_type] = \
MySensorsNodeValue(
nid, child_id, name, value_type, is_metric)
nid, child_id, name, value_type, is_metric, const)
new_devices.append(node[child_id][value_type])
else:
node[child_id][value_type].update_sensor(
@ -102,8 +103,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class MySensorsNodeValue(Entity):
""" Represents the value of a MySensors child node. """
# pylint: disable=too-many-arguments
def __init__(self, node_id, child_id, name, value_type, metric):
# pylint: disable=too-many-arguments, too-many-instance-attributes
def __init__(self, node_id, child_id, name, value_type, metric, const):
self._name = name
self.node_id = node_id
self.child_id = child_id
@ -111,6 +112,7 @@ class MySensorsNodeValue(Entity):
self.value_type = value_type
self.metric = metric
self._value = ''
self.const = const
@property
def should_poll(self):
@ -130,11 +132,11 @@ class MySensorsNodeValue(Entity):
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity. """
if self.value_type == const.SetReq.V_TEMP:
if self.value_type == self.const.SetReq.V_TEMP:
return TEMP_CELCIUS if self.metric else TEMP_FAHRENHEIT
elif self.value_type == const.SetReq.V_HUM or \
self.value_type == const.SetReq.V_DIMMER or \
self.value_type == const.SetReq.V_LIGHT_LEVEL:
elif self.value_type == self.const.SetReq.V_HUM or \
self.value_type == self.const.SetReq.V_DIMMER or \
self.value_type == self.const.SetReq.V_LIGHT_LEVEL:
return '%'
return None
@ -150,8 +152,8 @@ class MySensorsNodeValue(Entity):
def update_sensor(self, value, battery_level):
""" Update a sensor with the latest value from the controller. """
_LOGGER.info("%s value = %s", self._name, value)
if self.value_type == const.SetReq.V_TRIPPED or \
self.value_type == const.SetReq.V_ARMED:
if self.value_type == self.const.SetReq.V_TRIPPED or \
self.value_type == self.const.SetReq.V_ARMED:
self._value = STATE_ON if int(value) == 1 else STATE_OFF
else:
self._value = value

View File

@ -1,15 +1,14 @@
""" Support for Wink sensors. """
import logging
# pylint: disable=no-name-in-module, import-error
import homeassistant.external.wink.pywink as pywink
from homeassistant.helpers.entity import Entity
from homeassistant.const import CONF_ACCESS_TOKEN, STATE_OPEN, STATE_CLOSED
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Wink platform. """
import pywink
if discovery_info is None:
token = config.get(CONF_ACCESS_TOKEN)

View File

@ -29,7 +29,7 @@ MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
# Maps discovered services to their platforms
DISCOVERY_PLATFORMS = {
discovery.services.BELKIN_WEMO: 'wemo',
discovery.SERVICE_WEMO: 'wemo',
wink.DISCOVER_SWITCHES: 'wink',
isy994.DISCOVER_SWITCHES: 'isy994',
}

View File

@ -12,17 +12,8 @@ from homeassistant.components.switch import SwitchDevice
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
""" Find and return WeMo switches. """
try:
# pylint: disable=no-name-in-module, import-error
import homeassistant.external.pywemo.pywemo as pywemo
import homeassistant.external.pywemo.pywemo.discovery as discovery
except ImportError:
logging.getLogger(__name__).exception((
"Failed to import pywemo. "
"Did you maybe not run `git submodule init` "
"and `git submodule update`?"))
return
import pywemo
import pywemo.discovery as discovery
if discovery_info is not None:
device = discovery.device_from_description(discovery_info)

View File

@ -6,15 +6,14 @@ Support for Wink switches.
"""
import logging
# pylint: disable=no-name-in-module, import-error
import homeassistant.external.wink.pywink as pywink
from homeassistant.components.wink import WinkToggleDevice
from homeassistant.const import CONF_ACCESS_TOKEN
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Wink platform. """
import pywink
if discovery_info is None:
token = config.get(CONF_ACCESS_TOKEN)

View File

@ -6,9 +6,6 @@ Connects to a Wink hub and loads relevant components to control its devices.
"""
import logging
# pylint: disable=no-name-in-module, import-error
import homeassistant.external.wink.pywink as pywink
from homeassistant import bootstrap
from homeassistant.loader import get_component
from homeassistant.helpers import validate_config
@ -19,6 +16,8 @@ from homeassistant.const import (
DOMAIN = "wink"
DEPENDENCIES = []
REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/master.zip'
'#pywink>=0.1']
DISCOVER_LIGHTS = "wink.lights"
DISCOVER_SWITCHES = "wink.switches"
@ -32,6 +31,7 @@ def setup(hass, config):
if not validate_config(config, {DOMAIN: [CONF_ACCESS_TOKEN]}, logger):
return False
import pywink
pywink.set_bearer_token(config[DOMAIN][CONF_ACCESS_TOKEN])
# Load components for the devices in the Wink that we support

@ -1 +0,0 @@
Subproject commit b2cad7c2b959efa8eee9b5ac62d87232bf0b5176

@ -1 +0,0 @@
Subproject commit cd5ef892eeec0ad027727f7e8f757e7f2927da97

@ -1 +0,0 @@
Subproject commit e946ecf7926b9b2adaa1e3127a9738201a1b1fc7

@ -1 +0,0 @@
Subproject commit ca94e41faa48c783f600a2efd550c6b7dae01b0d

View File

@ -1,408 +0,0 @@
__author__ = 'JOHNMCL'
import json
import time
import requests
baseUrl = "https://winkapi.quirky.com"
headers = {}
class wink_sensor_pod(object):
""" represents a wink.py sensor
json_obj holds the json stat at init (and if there is a refresh it's updated
it's the native format for this objects methods
and looks like so:
{
"data": {
"last_event": {
"brightness_occurred_at": None,
"loudness_occurred_at": None,
"vibration_occurred_at": None
},
"model_name": "Tripper",
"capabilities": {
"sensor_types": [
{
"field": "opened",
"type": "boolean"
},
{
"field": "battery",
"type": "percentage"
}
]
},
"manufacturer_device_model": "quirky_ge_tripper",
"location": "",
"radio_type": "zigbee",
"manufacturer_device_id": None,
"gang_id": None,
"sensor_pod_id": "37614",
"subscription": {
},
"units": {
},
"upc_id": "184",
"hidden_at": None,
"last_reading": {
"battery_voltage_threshold_2": 0,
"opened": False,
"battery_alarm_mask": 0,
"opened_updated_at": 1421697092.7347496,
"battery_voltage_min_threshold_updated_at": 1421697092.7347229,
"battery_voltage_min_threshold": 0,
"connection": None,
"battery_voltage": 25,
"battery_voltage_threshold_1": 25,
"connection_updated_at": None,
"battery_voltage_threshold_3": 0,
"battery_voltage_updated_at": 1421697092.7347066,
"battery_voltage_threshold_1_updated_at": 1421697092.7347302,
"battery_voltage_threshold_3_updated_at": 1421697092.7347434,
"battery_voltage_threshold_2_updated_at": 1421697092.7347374,
"battery": 1.0,
"battery_updated_at": 1421697092.7347553,
"battery_alarm_mask_updated_at": 1421697092.734716
},
"triggers": [
],
"name": "MasterBathroom",
"lat_lng": [
37.550773,
-122.279182
],
"uuid": "a2cb868a-dda3-4211-ab73-fc08087aeed7",
"locale": "en_us",
"device_manufacturer": "quirky_ge",
"created_at": 1421523277,
"local_id": "2",
"hub_id": "88264"
},
}
"""
def __init__(self, aJSonObj, objectprefix="sensor_pods"):
self.jsonState = aJSonObj
self.objectprefix = objectprefix
def __str__(self):
return "%s %s %s" % (self.name(), self.deviceId(), self.state())
def __repr__(self):
return "<Wink sensor %s %s %s>" % (self.name(), self.deviceId(), self.state())
@property
def _last_reading(self):
return self.jsonState.get('last_reading') or {}
def name(self):
return self.jsonState.get('name', "Unknown Name")
def state(self):
return self._last_reading.get('opened', False)
def deviceId(self):
return self.jsonState.get('sensor_pod_id', self.name())
def refresh_state_at_hub(self):
"""
Tell hub to query latest status from device and upload to Wink.
PS: Not sure if this even works..
"""
urlString = baseUrl + "/%s/%s/refresh" % (self.objectprefix, self.deviceId())
requests.get(urlString, headers=headers)
def updateState(self):
""" Update state with latest info from Wink API. """
urlString = baseUrl + "/%s/%s" % (self.objectprefix, self.deviceId())
arequest = requests.get(urlString, headers=headers)
self._updateStateFromResponse(arequest.json())
def _updateStateFromResponse(self, response_json):
"""
:param response_json: the json obj returned from query
:return:
"""
self.jsonState = response_json.get('data')
class wink_binary_switch(object):
""" represents a wink.py switch
json_obj holds the json stat at init (and if there is a refresh it's updated
it's the native format for this objects methods
and looks like so:
{
"data": {
"binary_switch_id": "4153",
"name": "Garage door indicator",
"locale": "en_us",
"units": {},
"created_at": 1411614982,
"hidden_at": null,
"capabilities": {},
"subscription": {},
"triggers": [],
"desired_state": {
"powered": false
},
"manufacturer_device_model": "leviton_dzs15",
"manufacturer_device_id": null,
"device_manufacturer": "leviton",
"model_name": "Switch",
"upc_id": "94",
"gang_id": null,
"hub_id": "11780",
"local_id": "9",
"radio_type": "zwave",
"last_reading": {
"powered": false,
"powered_updated_at": 1411614983.6153464,
"powering_mode": null,
"powering_mode_updated_at": null,
"consumption": null,
"consumption_updated_at": null,
"cost": null,
"cost_updated_at": null,
"budget_percentage": null,
"budget_percentage_updated_at": null,
"budget_velocity": null,
"budget_velocity_updated_at": null,
"summation_delivered": null,
"summation_delivered_updated_at": null,
"sum_delivered_multiplier": null,
"sum_delivered_multiplier_updated_at": null,
"sum_delivered_divisor": null,
"sum_delivered_divisor_updated_at": null,
"sum_delivered_formatting": null,
"sum_delivered_formatting_updated_at": null,
"sum_unit_of_measure": null,
"sum_unit_of_measure_updated_at": null,
"desired_powered": false,
"desired_powered_updated_at": 1417893563.7567682,
"desired_powering_mode": null,
"desired_powering_mode_updated_at": null
},
"current_budget": null,
"lat_lng": [
38.429996,
-122.653721
],
"location": "",
"order": 0
},
"errors": [],
"pagination": {}
}
"""
def __init__(self, aJSonObj, objectprefix="binary_switches"):
self.jsonState = aJSonObj
self.objectprefix = objectprefix
# Tuple (desired state, time)
self._last_call = (0, None)
def __str__(self):
return "%s %s %s" % (self.name(), self.deviceId(), self.state())
def __repr__(self):
return "<Wink switch %s %s %s>" % (self.name(), self.deviceId(), self.state())
@property
def _last_reading(self):
return self.jsonState.get('last_reading') or {}
def name(self):
return self.jsonState.get('name', "Unknown Name")
def state(self):
# Optimistic approach to setState:
# Within 15 seconds of a call to setState we assume it worked.
if self._recent_state_set():
return self._last_call[1]
return self._last_reading.get('powered', False)
def deviceId(self):
return self.jsonState.get('binary_switch_id', self.name())
def setState(self, state):
"""
:param state: a boolean of true (on) or false ('off')
:return: nothing
"""
urlString = baseUrl + "/%s/%s" % (self.objectprefix, self.deviceId())
values = {"desired_state": {"powered": state}}
arequest = requests.put(urlString, data=json.dumps(values), headers=headers)
self._updateStateFromResponse(arequest.json())
self._last_call = (time.time(), state)
def refresh_state_at_hub(self):
"""
Tell hub to query latest status from device and upload to Wink.
PS: Not sure if this even works..
"""
urlString = baseUrl + "/%s/%s/refresh" % (self.objectprefix, self.deviceId())
requests.get(urlString, headers=headers)
def updateState(self):
""" Update state with latest info from Wink API. """
urlString = baseUrl + "/%s/%s" % (self.objectprefix, self.deviceId())
arequest = requests.get(urlString, headers=headers)
self._updateStateFromResponse(arequest.json())
def wait_till_desired_reached(self):
""" Wait till desired state reached. Max 10s. """
if self._recent_state_set():
return
# self.refresh_state_at_hub()
tries = 1
while True:
self.updateState()
last_read = self._last_reading
if last_read.get('desired_powered') == last_read.get('powered') \
or tries == 5:
break
time.sleep(2)
tries += 1
self.updateState()
last_read = self._last_reading
def _updateStateFromResponse(self, response_json):
"""
:param response_json: the json obj returned from query
:return:
"""
self.jsonState = response_json.get('data')
def _recent_state_set(self):
return time.time() - self._last_call[0] < 15
class wink_bulb(wink_binary_switch):
""" represents a wink.py bulb
json_obj holds the json stat at init (and if there is a refresh it's updated
it's the native format for this objects methods
and looks like so:
"light_bulb_id": "33990",
"name": "downstaurs lamp",
"locale": "en_us",
"units":{},
"created_at": 1410925804,
"hidden_at": null,
"capabilities":{},
"subscription":{},
"triggers":[],
"desired_state":{"powered": true, "brightness": 1},
"manufacturer_device_model": "lutron_p_pkg1_w_wh_d",
"manufacturer_device_id": null,
"device_manufacturer": "lutron",
"model_name": "Caseta Wireless Dimmer & Pico",
"upc_id": "3",
"hub_id": "11780",
"local_id": "8",
"radio_type": "lutron",
"linked_service_id": null,
"last_reading":{
"brightness": 1,
"brightness_updated_at": 1417823487.490747,
"connection": true,
"connection_updated_at": 1417823487.4907365,
"powered": true,
"powered_updated_at": 1417823487.4907532,
"desired_powered": true,
"desired_powered_updated_at": 1417823485.054675,
"desired_brightness": 1,
"desired_brightness_updated_at": 1417409293.2591703
},
"lat_lng":[38.429962, -122.653715],
"location": "",
"order": 0
"""
jsonState = {}
def __init__(self, ajsonobj):
super().__init__(ajsonobj, "light_bulbs")
def deviceId(self):
return self.jsonState.get('light_bulb_id', self.name())
def brightness(self):
return self._last_reading.get('brightness')
def setState(self, state, brightness=None):
"""
:param state: a boolean of true (on) or false ('off')
:return: nothing
"""
urlString = baseUrl + "/light_bulbs/%s" % self.deviceId()
values = {
"desired_state": {
"powered": state
}
}
if brightness is not None:
values["desired_state"]["brightness"] = brightness
urlString = baseUrl + "/light_bulbs/%s" % self.deviceId()
arequest = requests.put(urlString, data=json.dumps(values), headers=headers)
self._updateStateFromResponse(arequest.json())
self._last_call = (time.time(), state)
def __repr__(self):
return "<Wink Bulb %s %s %s>" % (
self.name(), self.deviceId(), self.state())
def get_devices(filter, constructor):
arequestUrl = baseUrl + "/users/me/wink_devices"
j = requests.get(arequestUrl, headers=headers).json()
items = j.get('data')
devices = []
for item in items:
id = item.get(filter)
if (id is not None and item.get("hidden_at") is None):
devices.append(constructor(item))
return devices
def get_bulbs():
return get_devices('light_bulb_id', wink_bulb)
def get_switches():
return get_devices('binary_switch_id', wink_binary_switch)
def get_sensors():
return get_devices('sensor_pod_id', wink_sensor_pod)
def is_token_set():
""" Returns if an auth token has been set. """
return bool(headers)
def set_bearer_token(token):
global headers
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer {}".format(token)
}
if __name__ == "__main__":
sw = get_bulbs()
lamp = sw[3]
lamp.setState(False)

View File

@ -5,9 +5,6 @@ pytz>=2015.2
# Optional, needed for specific components
# Discovery platform (discovery)
zeroconf>=0.16.0
# Sun (sun)
astral>=0.8.1
@ -77,8 +74,20 @@ python-forecastio>=1.3.3
# Firmata Bindings (*.arduino)
PyMata==2.07a
# Mysensors serial gateway
pyserial>=2.7
#Rfxtrx sensor
https://github.com/Danielhiversen/pyRFXtrx/archive/master.zip
# Mysensors
https://github.com/theolind/pymysensors/archive/master.zip#egg=pymysensors-0.1
# Netgear (device_tracker.netgear)
pynetgear>=0.1
# Netdisco (discovery)
netdisco>=0.1
# Wemo (switch.wemo)
pywemo>=0.1
# Wink (*.wink)
https://github.com/balloob/python-wink/archive/master.zip#pywink>=0.1