From 154bfccd3214d85c05d3c5dd93f87a8828591f6b Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Tue, 30 Oct 2018 19:50:04 +0000 Subject: [PATCH 01/25] Added lightwave components for switches and lights. --- homeassistant/components/light/lightwave.py | 121 +++++++++++++++++ homeassistant/components/lightwave.py | 136 +++++++++++++++++++ homeassistant/components/switch/lightwave.py | 99 ++++++++++++++ 3 files changed, 356 insertions(+) create mode 100644 homeassistant/components/light/lightwave.py create mode 100644 homeassistant/components/lightwave.py create mode 100644 homeassistant/components/switch/lightwave.py diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py new file mode 100644 index 00000000000000..974cfbaf83e62b --- /dev/null +++ b/homeassistant/components/light/lightwave.py @@ -0,0 +1,121 @@ +""" +homeassistant.components.light.lightwave +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Implements LightwaveRF lights. + + +My understanding of the LightWave Hub is that devices cannot be discovered so must be +registered manually. This is done in the configuration file: + +switch: + - platform: lightwave + devices: + R1D2: + name: Room one Device two + R2D1: + name: Room two Device one + +Each device requires an id and a name. THe id takes the from R#D# where R# is the room number +and D# is the device number. + +If devices are missing the default is to generate 15 rooms with 8 lights. From this you will +be able to determine the room and device number for each light. + +TODO: +Add a registration button. Until then the following command needs to be sent to the LightwaveRF hub: + echo -ne "100,\!F*p." | nc -u -w1 LW_HUB_IP_ADDRESS 9760 + +When this is sent you have 12 seconds to acknowledge the message on the hub. + +For more details on the api see: https://api.lightwaverf.com/ +""" + +import asyncio +import logging +import voluptuous as vol +from homeassistant.const import CONF_DEVICES, CONF_NAME +from homeassistant.components.light import ( + Light, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, PLATFORM_SCHEMA) +import homeassistant.helpers.config_validation as cv + +DEVICE_SCHEMA = vol.Schema({ + vol.Required(CONF_NAME): cv.string +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA} +}) + +_LOGGER = logging.getLogger(__name__) + +LIGHTWAVE_LINK = 'lightwave_link' +DEPENDENCIES = ['lightwave'] + + +async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): + """ Find and return LightWave lights """ + lights = [] + lwlink = hass.data[LIGHTWAVE_LINK] + + for device_id, device_config in config.get(CONF_DEVICES, {}).items(): + name = device_config[CONF_NAME] + lights.append(LRFLight(name, device_id, lwlink)) + + async_add_entities(lights) + + +class LRFLight(Light): + """ Provides a LightWave light. """ + + def __init__(self, name, device_id, lwlink): + self._name = name + self._device_id = device_id + self._state = None + self._brightness = 255 + self._lwlink = lwlink + + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_BRIGHTNESS + + @property + def should_poll(self): + """ No polling needed for a LightWave light. """ + return False + + @property + def name(self): + """ Returns the name of the LightWave light. """ + return self._name + + @property + def brightness(self): + """ Brightness of this light between 0..255. """ + return self._brightness + + @property + def is_on(self): + """ True if the LightWave light is on. """ + return self._state + + async def async_turn_on(self, **kwargs): + """ Turn the LightWave light on. """ + self._state = True + + if ATTR_BRIGHTNESS in kwargs: + self._brightness = kwargs[ATTR_BRIGHTNESS] + + if not self._brightness == 255: + self._lwlink.turn_on_with_brightness( + self._device_id, self._name, self._brightness) + else: + self._lwlink.turn_on_light(self._device_id, self._name) + + self.async_schedule_update_ha_state() + + async def async_turn_off(self, **kwargs): + """ Turn the LightWave light off. """ + self._state = False + self._lwlink.turn_off(self._device_id, self._name) + self.async_schedule_update_ha_state() diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py new file mode 100644 index 00000000000000..a52266a6529e9d --- /dev/null +++ b/homeassistant/components/lightwave.py @@ -0,0 +1,136 @@ +""" +Support for MQTT message handling. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/mqtt/ +""" + +import asyncio +import queue +import threading +import socket +import time +import logging +import voluptuous as vol + +from homeassistant.const import CONF_HOST +from homeassistant.helpers import config_validation as cv + +_LOGGER = logging.getLogger(__name__) + +LIGHTWAVE_LINK = 'lightwave_link' +DOMAIN = 'lightwave' +LWRF_REGISTRATION = '100,!F*p' +LWRF_DEREGISTRATION = '100,!F*xP' + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_HOST): cv.string, + }) +}, extra=vol.ALLOW_EXTRA) + + +async def async_setup(hass, config): + """Try to start embedded Lightwave broker.""" + host = config[DOMAIN].get(CONF_HOST) + hass.data[LIGHTWAVE_LINK] = LWLink(host) + return True + + +class LWLink(): + SOCKET_TIMEOUT = 2.0 + RX_PORT = 9761 + TX_PORT = 9760 + + the_queue = queue.Queue() + thread = None + link_ip = '' + + # msg = "100,!F*p." + + def __init__(self, link_ip=None): + if link_ip != None: + LWLink.link_ip = link_ip + + # methods + def _send_message(self, msg): + LWLink.the_queue.put_nowait(msg) + if LWLink.thread == None or not self.thread.isAlive(): + LWLink.thread = threading.Thread(target=self._sendQueue) + LWLink.thread.start() + + def turn_on_light(self, device_id, name): + msg = '321,!%sFdP32|Turn On|%s' % (device_id, name) + self._send_message(msg) + + def turn_on_switch(self, device_id, name): + msg = '321,!%sF1|Turn On|%s' % (device_id, name) + self._send_message(msg) + + def turn_on_with_brightness(self, device_id, name, brightness): + """Scale brightness from 0..255 to 1..32""" + brightness_value = round((brightness * 31) / 255) + 1 + # F1 = Light on and F0 = light off. FdP[0..32] is brightness. 32 is + # full. We want that when turning the light on. + msg = '321,!%sFdP%d|Lights %d|%s' % ( + device_id, brightness_value, brightness_value, name) + self._send_message(msg) + + def turn_off(self, device_id, name): + msg = "321,!%sF0|Turn Off|%s" % (device_id, name) + self._send_message(msg) + + def _sendQueue(self): + while not LWLink.the_queue.empty(): + self._send_reliable_message(LWLink.the_queue.get_nowait()) + + def _send_reliable_message(self, msg): + """ Send msg to LightwaveRF hub and only returns after: + an OK is received | timeout | exception | max_retries """ + result = False + max_retries = 15 + try: + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as write_sock, socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as read_sock: + write_sock.setsockopt( + socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + read_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + read_sock.settimeout(LWLink.SOCKET_TIMEOUT) + read_sock.bind(('0.0.0.0', LWLink.RX_PORT)) + while max_retries: + max_retries -= 1 + write_sock.sendto(msg.encode( + 'UTF-8'), (LWLink.link_ip, LWLink.TX_PORT)) + result = False + while True: + response, dummy = read_sock.recvfrom(1024) + response = response.decode('UTF-8') + if "Not yet registered." in response: + _LOGGER.error("Not yet registered") + self._send_message(LWRF_REGISTRATION) + result = True + break + + response.split(',')[1] + if response.startswith('OK'): + result = True + break + if response.startswith('ERR'): + break + + if result: + break + + time.sleep(0.25) + + except socket.timeout: + _LOGGER.error("LW broker timeout!") + return result + + except: + _LOGGER.error("LW broker something went wrong!") + + if result: + _LOGGER.info("LW broker OK!") + else: + _LOGGER.error("LW broker fail!") + return result diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py new file mode 100644 index 00000000000000..dda4b38aada7f0 --- /dev/null +++ b/homeassistant/components/switch/lightwave.py @@ -0,0 +1,99 @@ +""" +homeassistant.components.switch.lightwave +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Implements LightwaveRF switches. + + +My understanding of the LightWave Hub is that devices cannot be discovered +so must be registered manually. This is done in the configuration file + +switch: + - platform: lightwave + devices: + R1D2: + name: Room one Device two + R2D1: + name: Room two Device one + +Each device requires an id and a name. THe id takes the from R#D# where R# is the room number +and D# is the device number. + +If devices are missing the default is to generate 15 rooms with 8 lights. From this you will +be able to determine the room and device number for each light. + +TODO: +Add a registration button. Until then the following command needs to be sent to the LightwaveRF hub: + echo -ne "100,\!F*p." | nc -u -w1 LW_HUB_IP_ADDRESS 9760 + +When this is sent you have 12 seconds to acknowledge the message on the hub. + +For more details on the api see: https://api.lightwaverf.com/ +""" +import asyncio +import logging +import voluptuous as vol +from homeassistant.const import CONF_DEVICES, CONF_NAME +from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) +import homeassistant.helpers.config_validation as cv + +DEVICE_SCHEMA = vol.Schema({ + vol.Required(CONF_NAME): cv.string +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA} +}) + +_LOGGER = logging.getLogger(__name__) + +LIGHTWAVE_LINK = 'lightwave_link' +DEPENDENCIES = ['lightwave'] + + +async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): + """ Find and return LightWave switches """ + switches = [] + lwlink = hass.data[LIGHTWAVE_LINK] + + for device_id, device_config in config.get(CONF_DEVICES, {}).items(): + name = device_config[CONF_NAME] + switches.append(LRFSwitch(name, device_id, lwlink)) + + async_add_entities(switches) + + +class LRFSwitch(SwitchDevice): + """ Provides a LightWave switch. """ + + def __init__(self, name, device_id, lwlink): + self._name = name + self._device_id = device_id + self._state = None + self._lwlink = lwlink + + @property + def should_poll(self): + """ No polling needed for a LightWave light. """ + return False + + @property + def name(self): + """ Returns the name of the LightWave switch. """ + return self._name + + @property + def is_on(self): + """ True if LightWave switch is on. """ + return self._state + + async def async_turn_on(self, **kwargs): + """ Turn the LightWave switch on. """ + self._state = True + self._lwlink.turn_on_switch(self._device_id, self._name) + self.async_schedule_update_ha_state() + + async def async_turn_off(self, **kwargs): + """ Turn the LightWave switch off. """ + self._state = False + self._lwlink.turn_off(self._device_id, self._name) + self.async_schedule_update_ha_state() From 381082041ce3d1ec6d8b61eac59b28c8376a8ed1 Mon Sep 17 00:00:00 2001 From: Geoff Soord Date: Wed, 31 Oct 2018 16:18:51 +0000 Subject: [PATCH 02/25] Address warnings raised by Hound --- homeassistant/components/light/lightwave.py | 18 +++---------- homeassistant/components/lightwave.py | 27 ++++++++++++++------ homeassistant/components/switch/lightwave.py | 20 ++++----------- 3 files changed, 28 insertions(+), 37 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 974cfbaf83e62b..92bd764160fabe 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -4,8 +4,8 @@ Implements LightwaveRF lights. -My understanding of the LightWave Hub is that devices cannot be discovered so must be -registered manually. This is done in the configuration file: +My understanding of the LightWave Hub is that devices cannot be discovered +so must be registered manually. This is done in the configuration file: switch: - platform: lightwave @@ -18,19 +18,8 @@ Each device requires an id and a name. THe id takes the from R#D# where R# is the room number and D# is the device number. -If devices are missing the default is to generate 15 rooms with 8 lights. From this you will -be able to determine the room and device number for each light. - -TODO: -Add a registration button. Until then the following command needs to be sent to the LightwaveRF hub: - echo -ne "100,\!F*p." | nc -u -w1 LW_HUB_IP_ADDRESS 9760 - -When this is sent you have 12 seconds to acknowledge the message on the hub. - For more details on the api see: https://api.lightwaverf.com/ """ - -import asyncio import logging import voluptuous as vol from homeassistant.const import CONF_DEVICES, CONF_NAME @@ -52,7 +41,8 @@ DEPENDENCIES = ['lightwave'] -async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): +async def async_setup_platform(hass, config, async_add_entities, + discovery_info=None): """ Find and return LightWave lights """ lights = [] lwlink = hass.data[LIGHTWAVE_LINK] diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index a52266a6529e9d..c7e14c1a877e30 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -1,11 +1,18 @@ """ -Support for MQTT message handling. +homeassistant.components.lightwave +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Implements communication with LightwaveRF -For more details about this component, please refer to the documentation at -https://home-assistant.io/components/mqtt/ -""" +My understanding of the LightWave Hub is that devices cannot be discovered +so must be registered manually. This is done in the configuration file + +lightwave: + host: ip_address -import asyncio +Where ip_address is the ip address of your LightwaveRF hub + +For more details on the api see: https://api.lightwaverf.com/ +""" import queue import threading import socket @@ -49,7 +56,7 @@ class LWLink(): # msg = "100,!F*p." def __init__(self, link_ip=None): - if link_ip != None: + if link_ip is not None: LWLink.link_ip = link_ip # methods @@ -90,10 +97,13 @@ def _send_reliable_message(self, msg): result = False max_retries = 15 try: - with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as write_sock, socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as read_sock: + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as + write_sock, socket.socket(socket.AF_INET, + socket.SOCK_DGRAM) as read_sock: write_sock.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - read_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + read_sock.setsockopt(socket.SOL_SOCKET, + socket.SO_BROADCAST, 1) read_sock.settimeout(LWLink.SOCKET_TIMEOUT) read_sock.bind(('0.0.0.0', LWLink.RX_PORT)) while max_retries: @@ -128,6 +138,7 @@ def _send_reliable_message(self, msg): except: _LOGGER.error("LW broker something went wrong!") + raise if result: _LOGGER.info("LW broker OK!") diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index dda4b38aada7f0..0d6fe8d63abd49 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -3,8 +3,7 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Implements LightwaveRF switches. - -My understanding of the LightWave Hub is that devices cannot be discovered +My understanding of the LightWave Hub is that devices cannot be discovered so must be registered manually. This is done in the configuration file switch: @@ -15,21 +14,11 @@ R2D1: name: Room two Device one -Each device requires an id and a name. THe id takes the from R#D# where R# is the room number -and D# is the device number. - -If devices are missing the default is to generate 15 rooms with 8 lights. From this you will -be able to determine the room and device number for each light. - -TODO: -Add a registration button. Until then the following command needs to be sent to the LightwaveRF hub: - echo -ne "100,\!F*p." | nc -u -w1 LW_HUB_IP_ADDRESS 9760 - -When this is sent you have 12 seconds to acknowledge the message on the hub. +Each device requires an id and a name. THe id takes the from R#D# +where R# is the room number and D# is the device number. For more details on the api see: https://api.lightwaverf.com/ """ -import asyncio import logging import voluptuous as vol from homeassistant.const import CONF_DEVICES, CONF_NAME @@ -50,7 +39,8 @@ DEPENDENCIES = ['lightwave'] -async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): +async def async_setup_platform(hass, config, async_add_entities, + discovery_info=None): """ Find and return LightWave switches """ switches = [] lwlink = hass.data[LIGHTWAVE_LINK] From 102bf5863c1926112499d6781870684d7fe60848 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Wed, 31 Oct 2018 18:12:48 +0000 Subject: [PATCH 03/25] Correcting lint messages and major typo. This time tested before commit. --- homeassistant/components/light/lightwave.py | 6 ++--- homeassistant/components/lightwave.py | 28 +++++++++++--------- homeassistant/components/switch/lightwave.py | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 92bd764160fabe..bab3e84b01497d 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -15,8 +15,8 @@ R2D1: name: Room two Device one -Each device requires an id and a name. THe id takes the from R#D# where R# is the room number -and D# is the device number. +Each device requires an id and a name. THe id takes the from R#D# +where R# is the room number and D# is the device number. For more details on the api see: https://api.lightwaverf.com/ """ @@ -96,7 +96,7 @@ async def async_turn_on(self, **kwargs): if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] - if not self._brightness == 255: + if self._brightness != 255: self._lwlink.turn_on_with_brightness( self._device_id, self._name, self._brightness) else: diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index c7e14c1a877e30..d97d0aafd60864 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -1,7 +1,7 @@ """ homeassistant.components.lightwave -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Implements communication with LightwaveRF +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Implements communication with LightwaveRF My understanding of the LightWave Hub is that devices cannot be discovered so must be registered manually. This is done in the configuration file @@ -45,6 +45,7 @@ async def async_setup(hass, config): class LWLink(): + ''' LWLink provides a communication link with the LightwaveRF hub ''' SOCKET_TIMEOUT = 2.0 RX_PORT = 9761 TX_PORT = 9760 @@ -53,24 +54,24 @@ class LWLink(): thread = None link_ip = '' - # msg = "100,!F*p." - def __init__(self, link_ip=None): if link_ip is not None: LWLink.link_ip = link_ip - # methods def _send_message(self, msg): + ''' adds message to queue ''' LWLink.the_queue.put_nowait(msg) - if LWLink.thread == None or not self.thread.isAlive(): - LWLink.thread = threading.Thread(target=self._sendQueue) + if LWLink.thread is None or not self.thread.isAlive(): + LWLink.thread = threading.Thread(target=self._send_queue) LWLink.thread.start() def turn_on_light(self, device_id, name): + ''' formats message to turn light on ''' msg = '321,!%sFdP32|Turn On|%s' % (device_id, name) self._send_message(msg) def turn_on_switch(self, device_id, name): + ''' formats message to turn switch on ''' msg = '321,!%sF1|Turn On|%s' % (device_id, name) self._send_message(msg) @@ -84,10 +85,12 @@ def turn_on_with_brightness(self, device_id, name, brightness): self._send_message(msg) def turn_off(self, device_id, name): + ''' formats message to turn light or switch off ''' msg = "321,!%sF0|Turn Off|%s" % (device_id, name) self._send_message(msg) - def _sendQueue(self): + def _send_queue(self): + ''' starts processing the queue ''' while not LWLink.the_queue.empty(): self._send_reliable_message(LWLink.the_queue.get_nowait()) @@ -97,9 +100,10 @@ def _send_reliable_message(self, msg): result = False max_retries = 15 try: - with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as - write_sock, socket.socket(socket.AF_INET, - socket.SOCK_DGRAM) as read_sock: + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) \ + as write_sock, \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) \ + as read_sock: write_sock.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) read_sock.setsockopt(socket.SOL_SOCKET, @@ -120,7 +124,7 @@ def _send_reliable_message(self, msg): result = True break - response.split(',')[1] + response = response.split(',')[1] if response.startswith('OK'): result = True break diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index 0d6fe8d63abd49..30143d2aec7344 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -14,7 +14,7 @@ R2D1: name: Room two Device one -Each device requires an id and a name. THe id takes the from R#D# +Each device requires an id and a name. THe id takes the from R#D# where R# is the room number and D# is the device number. For more details on the api see: https://api.lightwaverf.com/ From c366c5d1c057e290d8b26ae9e7a62f481ba3415e Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Wed, 31 Oct 2018 20:39:41 +0000 Subject: [PATCH 04/25] Trying to fix author --- homeassistant/components/light/lightwave.py | 2 +- homeassistant/components/lightwave.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index bab3e84b01497d..24ef17c8084733 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -96,7 +96,7 @@ async def async_turn_on(self, **kwargs): if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] - if self._brightness != 255: + if not self._brightness == 255: self._lwlink.turn_on_with_brightness( self._device_id, self._name, self._brightness) else: diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index d97d0aafd60864..738ef4d32744f9 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -62,7 +62,7 @@ def _send_message(self, msg): ''' adds message to queue ''' LWLink.the_queue.put_nowait(msg) if LWLink.thread is None or not self.thread.isAlive(): - LWLink.thread = threading.Thread(target=self._send_queue) + LWLink.thread = threading.Thread(target=self._sendQueue) LWLink.thread.start() def turn_on_light(self, device_id, name): @@ -89,7 +89,7 @@ def turn_off(self, device_id, name): msg = "321,!%sF0|Turn Off|%s" % (device_id, name) self._send_message(msg) - def _send_queue(self): + def _sendQueue(self): ''' starts processing the queue ''' while not LWLink.the_queue.empty(): self._send_reliable_message(LWLink.the_queue.get_nowait()) @@ -124,7 +124,7 @@ def _send_reliable_message(self, msg): result = True break - response = response.split(',')[1] + response.split(',')[1] if response.startswith('OK'): result = True break From 451a40f5d85e3da25a2d3bfee80b68b7a8cb59d4 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Wed, 31 Oct 2018 20:45:15 +0000 Subject: [PATCH 05/25] Minor lint changes --- homeassistant/components/light/lightwave.py | 2 +- homeassistant/components/lightwave.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 24ef17c8084733..bab3e84b01497d 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -96,7 +96,7 @@ async def async_turn_on(self, **kwargs): if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] - if not self._brightness == 255: + if self._brightness != 255: self._lwlink.turn_on_with_brightness( self._device_id, self._name, self._brightness) else: diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index 738ef4d32744f9..d97d0aafd60864 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -62,7 +62,7 @@ def _send_message(self, msg): ''' adds message to queue ''' LWLink.the_queue.put_nowait(msg) if LWLink.thread is None or not self.thread.isAlive(): - LWLink.thread = threading.Thread(target=self._sendQueue) + LWLink.thread = threading.Thread(target=self._send_queue) LWLink.thread.start() def turn_on_light(self, device_id, name): @@ -89,7 +89,7 @@ def turn_off(self, device_id, name): msg = "321,!%sF0|Turn Off|%s" % (device_id, name) self._send_message(msg) - def _sendQueue(self): + def _send_queue(self): ''' starts processing the queue ''' while not LWLink.the_queue.empty(): self._send_reliable_message(LWLink.the_queue.get_nowait()) @@ -124,7 +124,7 @@ def _send_reliable_message(self, msg): result = True break - response.split(',')[1] + response = response.split(',')[1] if response.startswith('OK'): result = True break From 6b123360e1ac6c6d1497da38b0d2c3b98402ed37 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Fri, 2 Nov 2018 18:52:41 +0000 Subject: [PATCH 06/25] Attempt to correct other lint error. --- homeassistant/components/light/lightwave.py | 21 ++++++++-------- homeassistant/components/lightwave.py | 25 ++++++++++---------- homeassistant/components/switch/lightwave.py | 19 ++++++++------- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index bab3e84b01497d..f2a94839ae5b7b 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -1,6 +1,6 @@ """ -homeassistant.components.light.lightwave -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +homeassistant.components.light.lightwave. + Implements LightwaveRF lights. @@ -43,7 +43,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): - """ Find and return LightWave lights """ + """Find and return LightWave lights""" lights = [] lwlink = hass.data[LIGHTWAVE_LINK] @@ -55,9 +55,10 @@ async def async_setup_platform(hass, config, async_add_entities, class LRFLight(Light): - """ Provides a LightWave light. """ + """Provides a LightWave light.""" def __init__(self, name, device_id, lwlink): + """Setup the component""" self._name = name self._device_id = device_id self._state = None @@ -71,26 +72,26 @@ def supported_features(self): @property def should_poll(self): - """ No polling needed for a LightWave light. """ + """No polling needed for a LightWave light.""" return False @property def name(self): - """ Returns the name of the LightWave light. """ + """Returns the name of the LightWave light.""" return self._name @property def brightness(self): - """ Brightness of this light between 0..255. """ + """Brightness of this light between 0..255.""" return self._brightness @property def is_on(self): - """ True if the LightWave light is on. """ + """True if the LightWave light is on.""" return self._state async def async_turn_on(self, **kwargs): - """ Turn the LightWave light on. """ + """Turn the LightWave light on.""" self._state = True if ATTR_BRIGHTNESS in kwargs: @@ -105,7 +106,7 @@ async def async_turn_on(self, **kwargs): self.async_schedule_update_ha_state() async def async_turn_off(self, **kwargs): - """ Turn the LightWave light off. """ + """Turn the LightWave light off.""" self._state = False self._lwlink.turn_off(self._device_id, self._name) self.async_schedule_update_ha_state() diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index d97d0aafd60864..c98ea852490a49 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -1,10 +1,10 @@ """ -homeassistant.components.lightwave -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Implements communication with LightwaveRF +homeassistant.components.lightwave. + +Implements communication with LightwaveRF. My understanding of the LightWave Hub is that devices cannot be discovered -so must be registered manually. This is done in the configuration file +so must be registered manually. This is done in the configuration file. lightwave: host: ip_address @@ -45,7 +45,7 @@ async def async_setup(hass, config): class LWLink(): - ''' LWLink provides a communication link with the LightwaveRF hub ''' + """LWLink provides a communication link with the LightwaveRF hub""" SOCKET_TIMEOUT = 2.0 RX_PORT = 9761 TX_PORT = 9760 @@ -55,23 +55,24 @@ class LWLink(): link_ip = '' def __init__(self, link_ip=None): + """Initialise the component""" if link_ip is not None: LWLink.link_ip = link_ip def _send_message(self, msg): - ''' adds message to queue ''' + """Adds message to queue""" LWLink.the_queue.put_nowait(msg) if LWLink.thread is None or not self.thread.isAlive(): LWLink.thread = threading.Thread(target=self._send_queue) LWLink.thread.start() def turn_on_light(self, device_id, name): - ''' formats message to turn light on ''' + """Formats message to turn light on""" msg = '321,!%sFdP32|Turn On|%s' % (device_id, name) self._send_message(msg) def turn_on_switch(self, device_id, name): - ''' formats message to turn switch on ''' + """Formats message to turn switch on""" msg = '321,!%sF1|Turn On|%s' % (device_id, name) self._send_message(msg) @@ -85,18 +86,18 @@ def turn_on_with_brightness(self, device_id, name, brightness): self._send_message(msg) def turn_off(self, device_id, name): - ''' formats message to turn light or switch off ''' + """Formats message to turn light or switch off""" msg = "321,!%sF0|Turn Off|%s" % (device_id, name) self._send_message(msg) def _send_queue(self): - ''' starts processing the queue ''' + """Starts processing the queue""" while not LWLink.the_queue.empty(): self._send_reliable_message(LWLink.the_queue.get_nowait()) def _send_reliable_message(self, msg): - """ Send msg to LightwaveRF hub and only returns after: - an OK is received | timeout | exception | max_retries """ + """Send msg to LightwaveRF hub and only returns after: + an OK is received | timeout | exception | max_retries""" result = False max_retries = 15 try: diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index 30143d2aec7344..f4aed65bca6745 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -1,6 +1,6 @@ """ -homeassistant.components.switch.lightwave -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +homeassistant.components.switch.lightwave. + Implements LightwaveRF switches. My understanding of the LightWave Hub is that devices cannot be discovered @@ -41,7 +41,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): - """ Find and return LightWave switches """ + """Find and return LightWave switches""" switches = [] lwlink = hass.data[LIGHTWAVE_LINK] @@ -53,9 +53,10 @@ async def async_setup_platform(hass, config, async_add_entities, class LRFSwitch(SwitchDevice): - """ Provides a LightWave switch. """ + """Provides a LightWave switch.""" def __init__(self, name, device_id, lwlink): + """Setup the component""" self._name = name self._device_id = device_id self._state = None @@ -63,27 +64,27 @@ def __init__(self, name, device_id, lwlink): @property def should_poll(self): - """ No polling needed for a LightWave light. """ + """No polling needed for a LightWave light.""" return False @property def name(self): - """ Returns the name of the LightWave switch. """ + """Returns the name of the LightWave switch.""" return self._name @property def is_on(self): - """ True if LightWave switch is on. """ + """True if LightWave switch is on.""" return self._state async def async_turn_on(self, **kwargs): - """ Turn the LightWave switch on. """ + """Turn the LightWave switch on.""" self._state = True self._lwlink.turn_on_switch(self._device_id, self._name) self.async_schedule_update_ha_state() async def async_turn_off(self, **kwargs): - """ Turn the LightWave switch off. """ + """Turn the LightWave switch off.""" self._state = False self._lwlink.turn_off(self._device_id, self._name) self.async_schedule_update_ha_state() From bc0a6c350fb5e94ca388ec9d8d092302c998e6b9 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Fri, 2 Nov 2018 19:21:07 +0000 Subject: [PATCH 07/25] Another lint attempt. --- homeassistant/components/light/lightwave.py | 8 ++++---- homeassistant/components/lightwave.py | 20 +++++++++++--------- homeassistant/components/switch/lightwave.py | 8 ++++---- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index f2a94839ae5b7b..038ded901d86ec 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -43,7 +43,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): - """Find and return LightWave lights""" + """Find and return LightWave lights.""" lights = [] lwlink = hass.data[LIGHTWAVE_LINK] @@ -58,7 +58,7 @@ class LRFLight(Light): """Provides a LightWave light.""" def __init__(self, name, device_id, lwlink): - """Setup the component""" + """Initilize the component with the name, device_id and link.""" self._name = name self._device_id = device_id self._state = None @@ -77,7 +77,7 @@ def should_poll(self): @property def name(self): - """Returns the name of the LightWave light.""" + """LightWave light name.""" return self._name @property @@ -87,7 +87,7 @@ def brightness(self): @property def is_on(self): - """True if the LightWave light is on.""" + """LightWave light is on state.""" return self._state async def async_turn_on(self, **kwargs): diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index c98ea852490a49..f6f820621a99d9 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -45,7 +45,8 @@ async def async_setup(hass, config): class LWLink(): - """LWLink provides a communication link with the LightwaveRF hub""" + """LWLink provides a communication link with the LightwaveRF hub.""" + SOCKET_TIMEOUT = 2.0 RX_PORT = 9761 TX_PORT = 9760 @@ -55,29 +56,29 @@ class LWLink(): link_ip = '' def __init__(self, link_ip=None): - """Initialise the component""" + """Initialise the component.""" if link_ip is not None: LWLink.link_ip = link_ip def _send_message(self, msg): - """Adds message to queue""" + """Adds message to queue.""" LWLink.the_queue.put_nowait(msg) if LWLink.thread is None or not self.thread.isAlive(): LWLink.thread = threading.Thread(target=self._send_queue) LWLink.thread.start() def turn_on_light(self, device_id, name): - """Formats message to turn light on""" + """Formats message to turn light on.""" msg = '321,!%sFdP32|Turn On|%s' % (device_id, name) self._send_message(msg) def turn_on_switch(self, device_id, name): - """Formats message to turn switch on""" + """Formats message to turn switch on.""" msg = '321,!%sF1|Turn On|%s' % (device_id, name) self._send_message(msg) def turn_on_with_brightness(self, device_id, name, brightness): - """Scale brightness from 0..255 to 1..32""" + """Scale brightness from 0..255 to 1..32.""" brightness_value = round((brightness * 31) / 255) + 1 # F1 = Light on and F0 = light off. FdP[0..32] is brightness. 32 is # full. We want that when turning the light on. @@ -86,18 +87,19 @@ def turn_on_with_brightness(self, device_id, name, brightness): self._send_message(msg) def turn_off(self, device_id, name): - """Formats message to turn light or switch off""" + """Formats message to turn light or switch off.""" msg = "321,!%sF0|Turn Off|%s" % (device_id, name) self._send_message(msg) def _send_queue(self): - """Starts processing the queue""" + """Starts processing the queue.""" while not LWLink.the_queue.empty(): self._send_reliable_message(LWLink.the_queue.get_nowait()) def _send_reliable_message(self, msg): """Send msg to LightwaveRF hub and only returns after: - an OK is received | timeout | exception | max_retries""" + an OK is received | timeout | exception | max_retries. + """ result = False max_retries = 15 try: diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index f4aed65bca6745..1495d360ac4fe1 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -41,7 +41,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): - """Find and return LightWave switches""" + """Find and return LightWave switches.""" switches = [] lwlink = hass.data[LIGHTWAVE_LINK] @@ -56,7 +56,7 @@ class LRFSwitch(SwitchDevice): """Provides a LightWave switch.""" def __init__(self, name, device_id, lwlink): - """Setup the component""" + """Setup the component.""" self._name = name self._device_id = device_id self._state = None @@ -69,12 +69,12 @@ def should_poll(self): @property def name(self): - """Returns the name of the LightWave switch.""" + """LightWave switch name.""" return self._name @property def is_on(self): - """True if LightWave switch is on.""" + """LightWave switch is on state.""" return self._state async def async_turn_on(self, **kwargs): From a92114745248d549513df61f5aff9b009d158911 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sat, 3 Nov 2018 11:04:24 +0000 Subject: [PATCH 08/25] More lint issues. --- homeassistant/components/light/lightwave.py | 4 ++-- homeassistant/components/lightwave.py | 14 ++++++-------- homeassistant/components/switch/lightwave.py | 6 +++--- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 038ded901d86ec..93c1c78c19566d 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -77,7 +77,7 @@ def should_poll(self): @property def name(self): - """LightWave light name.""" + """Lightwave light name.""" return self._name @property @@ -87,7 +87,7 @@ def brightness(self): @property def is_on(self): - """LightWave light is on state.""" + """Lightwave light is on state.""" return self._state async def async_turn_on(self, **kwargs): diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index f6f820621a99d9..cb1693a1c123c4 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -61,19 +61,19 @@ def __init__(self, link_ip=None): LWLink.link_ip = link_ip def _send_message(self, msg): - """Adds message to queue.""" + """Add message to queue and start processing the queue.""" LWLink.the_queue.put_nowait(msg) if LWLink.thread is None or not self.thread.isAlive(): LWLink.thread = threading.Thread(target=self._send_queue) LWLink.thread.start() def turn_on_light(self, device_id, name): - """Formats message to turn light on.""" + """Create the message to turn light on.""" msg = '321,!%sFdP32|Turn On|%s' % (device_id, name) self._send_message(msg) def turn_on_switch(self, device_id, name): - """Formats message to turn switch on.""" + """Create the message to turn switch on.""" msg = '321,!%sF1|Turn On|%s' % (device_id, name) self._send_message(msg) @@ -87,19 +87,17 @@ def turn_on_with_brightness(self, device_id, name, brightness): self._send_message(msg) def turn_off(self, device_id, name): - """Formats message to turn light or switch off.""" + """Create the message to turn light or switch off.""" msg = "321,!%sF0|Turn Off|%s" % (device_id, name) self._send_message(msg) def _send_queue(self): - """Starts processing the queue.""" + """if the queue is not empty, process the queue.""" while not LWLink.the_queue.empty(): self._send_reliable_message(LWLink.the_queue.get_nowait()) def _send_reliable_message(self, msg): - """Send msg to LightwaveRF hub and only returns after: - an OK is received | timeout | exception | max_retries. - """ + """Send msg to LightwaveRF hub.""" result = False max_retries = 15 try: diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index 1495d360ac4fe1..638337da803f2e 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -56,7 +56,7 @@ class LRFSwitch(SwitchDevice): """Provides a LightWave switch.""" def __init__(self, name, device_id, lwlink): - """Setup the component.""" + """Lightwave switch setup for later use.""" self._name = name self._device_id = device_id self._state = None @@ -69,12 +69,12 @@ def should_poll(self): @property def name(self): - """LightWave switch name.""" + """Lightwave switch name.""" return self._name @property def is_on(self): - """LightWave switch is on state.""" + """Lightwave switch is on state.""" return self._state async def async_turn_on(self, **kwargs): From d93e6cf4625ae1f9dc9bcb4f443cc09fb5a61d71 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sat, 3 Nov 2018 11:21:10 +0000 Subject: [PATCH 09/25] Last two lint errors! Hurrah. --- homeassistant/components/lightwave.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index cb1693a1c123c4..5ce8c7e4f8e043 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -92,7 +92,7 @@ def turn_off(self, device_id, name): self._send_message(msg) def _send_queue(self): - """if the queue is not empty, process the queue.""" + """If the queue is not empty, process the queue.""" while not LWLink.the_queue.empty(): self._send_reliable_message(LWLink.the_queue.get_nowait()) @@ -141,8 +141,9 @@ def _send_reliable_message(self, msg): _LOGGER.error("LW broker timeout!") return result - except: + except Exception as ex: _LOGGER.error("LW broker something went wrong!") + _LOGGER.error(ex) raise if result: From faeef0ea5ea66b5dd0caff4bc3884c5c2b65e129 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Mon, 12 Nov 2018 18:51:04 +0000 Subject: [PATCH 10/25] Changes after review from fabaff. --- homeassistant/components/light/lightwave.py | 27 +++++--------------- homeassistant/components/lightwave.py | 1 - homeassistant/components/switch/lightwave.py | 26 +++++-------------- 3 files changed, 12 insertions(+), 42 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 93c1c78c19566d..44356b0d9a124e 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -1,31 +1,16 @@ """ -homeassistant.components.light.lightwave. - Implements LightwaveRF lights. - -My understanding of the LightWave Hub is that devices cannot be discovered -so must be registered manually. This is done in the configuration file: - -switch: - - platform: lightwave - devices: - R1D2: - name: Room one Device two - R2D1: - name: Room two Device one - -Each device requires an id and a name. THe id takes the from R#D# -where R# is the room number and D# is the device number. - -For more details on the api see: https://api.lightwaverf.com/ +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/light.lightwave/ """ import logging import voluptuous as vol +import homeassistant.helpers.config_validation as cv + from homeassistant.const import CONF_DEVICES, CONF_NAME from homeassistant.components.light import ( Light, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, PLATFORM_SCHEMA) -import homeassistant.helpers.config_validation as cv DEVICE_SCHEMA = vol.Schema({ vol.Required(CONF_NAME): cv.string @@ -55,10 +40,10 @@ async def async_setup_platform(hass, config, async_add_entities, class LRFLight(Light): - """Provides a LightWave light.""" + """Representation of a LightWaveRF light.""" def __init__(self, name, device_id, lwlink): - """Initilize the component with the name, device_id and link.""" + """Initialize LRFLight entity.""" self._name = name self._device_id = device_id self._state = None diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index 5ce8c7e4f8e043..c8c7f50977026e 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -142,7 +142,6 @@ def _send_reliable_message(self, msg): return result except Exception as ex: - _LOGGER.error("LW broker something went wrong!") _LOGGER.error(ex) raise diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index 638337da803f2e..eff9ceb4f06c1d 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -1,29 +1,15 @@ """ -homeassistant.components.switch.lightwave. - Implements LightwaveRF switches. -My understanding of the LightWave Hub is that devices cannot be discovered -so must be registered manually. This is done in the configuration file - -switch: - - platform: lightwave - devices: - R1D2: - name: Room one Device two - R2D1: - name: Room two Device one - -Each device requires an id and a name. THe id takes the from R#D# -where R# is the room number and D# is the device number. - -For more details on the api see: https://api.lightwaverf.com/ +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/switch.lightwave/ """ import logging import voluptuous as vol +import homeassistant.helpers.config_validation as cv + from homeassistant.const import CONF_DEVICES, CONF_NAME from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) -import homeassistant.helpers.config_validation as cv DEVICE_SCHEMA = vol.Schema({ vol.Required(CONF_NAME): cv.string @@ -53,10 +39,10 @@ async def async_setup_platform(hass, config, async_add_entities, class LRFSwitch(SwitchDevice): - """Provides a LightWave switch.""" + """Representation of a LightWaveRF switch.""" def __init__(self, name, device_id, lwlink): - """Lightwave switch setup for later use.""" + """Initialize LRFSwitch entity.""" self._name = name self._device_id = device_id self._state = None From 3bd6f5c78a481657219ed48fb798751469755b55 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sat, 24 Nov 2018 19:39:30 +0000 Subject: [PATCH 11/25] Moved device dependent code to PyPi. --- homeassistant/components/lightwave.py | 119 +------------------------- 1 file changed, 2 insertions(+), 117 deletions(-) diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index c8c7f50977026e..9d7fbf96f10562 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -13,22 +13,15 @@ For more details on the api see: https://api.lightwaverf.com/ """ -import queue -import threading -import socket -import time -import logging import voluptuous as vol +from lightwave.lightwave import LWLink from homeassistant.const import CONF_HOST from homeassistant.helpers import config_validation as cv -_LOGGER = logging.getLogger(__name__) - +DEPENDENCIES = ['lightwave'] LIGHTWAVE_LINK = 'lightwave_link' DOMAIN = 'lightwave' -LWRF_REGISTRATION = '100,!F*p' -LWRF_DEREGISTRATION = '100,!F*xP' CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ @@ -42,111 +35,3 @@ async def async_setup(hass, config): host = config[DOMAIN].get(CONF_HOST) hass.data[LIGHTWAVE_LINK] = LWLink(host) return True - - -class LWLink(): - """LWLink provides a communication link with the LightwaveRF hub.""" - - SOCKET_TIMEOUT = 2.0 - RX_PORT = 9761 - TX_PORT = 9760 - - the_queue = queue.Queue() - thread = None - link_ip = '' - - def __init__(self, link_ip=None): - """Initialise the component.""" - if link_ip is not None: - LWLink.link_ip = link_ip - - def _send_message(self, msg): - """Add message to queue and start processing the queue.""" - LWLink.the_queue.put_nowait(msg) - if LWLink.thread is None or not self.thread.isAlive(): - LWLink.thread = threading.Thread(target=self._send_queue) - LWLink.thread.start() - - def turn_on_light(self, device_id, name): - """Create the message to turn light on.""" - msg = '321,!%sFdP32|Turn On|%s' % (device_id, name) - self._send_message(msg) - - def turn_on_switch(self, device_id, name): - """Create the message to turn switch on.""" - msg = '321,!%sF1|Turn On|%s' % (device_id, name) - self._send_message(msg) - - def turn_on_with_brightness(self, device_id, name, brightness): - """Scale brightness from 0..255 to 1..32.""" - brightness_value = round((brightness * 31) / 255) + 1 - # F1 = Light on and F0 = light off. FdP[0..32] is brightness. 32 is - # full. We want that when turning the light on. - msg = '321,!%sFdP%d|Lights %d|%s' % ( - device_id, brightness_value, brightness_value, name) - self._send_message(msg) - - def turn_off(self, device_id, name): - """Create the message to turn light or switch off.""" - msg = "321,!%sF0|Turn Off|%s" % (device_id, name) - self._send_message(msg) - - def _send_queue(self): - """If the queue is not empty, process the queue.""" - while not LWLink.the_queue.empty(): - self._send_reliable_message(LWLink.the_queue.get_nowait()) - - def _send_reliable_message(self, msg): - """Send msg to LightwaveRF hub.""" - result = False - max_retries = 15 - try: - with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) \ - as write_sock, \ - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) \ - as read_sock: - write_sock.setsockopt( - socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - read_sock.setsockopt(socket.SOL_SOCKET, - socket.SO_BROADCAST, 1) - read_sock.settimeout(LWLink.SOCKET_TIMEOUT) - read_sock.bind(('0.0.0.0', LWLink.RX_PORT)) - while max_retries: - max_retries -= 1 - write_sock.sendto(msg.encode( - 'UTF-8'), (LWLink.link_ip, LWLink.TX_PORT)) - result = False - while True: - response, dummy = read_sock.recvfrom(1024) - response = response.decode('UTF-8') - if "Not yet registered." in response: - _LOGGER.error("Not yet registered") - self._send_message(LWRF_REGISTRATION) - result = True - break - - response = response.split(',')[1] - if response.startswith('OK'): - result = True - break - if response.startswith('ERR'): - break - - if result: - break - - time.sleep(0.25) - - except socket.timeout: - _LOGGER.error("LW broker timeout!") - return result - - except Exception as ex: - _LOGGER.error(ex) - raise - - if result: - _LOGGER.info("LW broker OK!") - else: - _LOGGER.error("LW broker fail!") - return result From 9667ae0ddd28a908ea6a1e8e5e16994af6bacf91 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sun, 25 Nov 2018 09:05:50 +0000 Subject: [PATCH 12/25] Replaced DEPENDENCIES with REQUIREMENTS --- homeassistant/components/lightwave.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index 9d7fbf96f10562..5cc1aa3b27a042 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -19,7 +19,7 @@ from homeassistant.const import CONF_HOST from homeassistant.helpers import config_validation as cv -DEPENDENCIES = ['lightwave'] +REQUIREMENTS = ['lightwave==0.14'] LIGHTWAVE_LINK = 'lightwave_link' DOMAIN = 'lightwave' From ef25b9a6986fb5d955d1b8874157998282b759cb Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sun, 25 Nov 2018 12:44:10 +0000 Subject: [PATCH 13/25] Updated following code review from Martin Hjelmare. --- homeassistant/components/light/lightwave.py | 4 ++-- homeassistant/components/lightwave.py | 20 ++++++-------------- homeassistant/components/switch/lightwave.py | 2 +- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 44356b0d9a124e..67354b39261d1d 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -11,18 +11,18 @@ from homeassistant.const import CONF_DEVICES, CONF_NAME from homeassistant.components.light import ( Light, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, PLATFORM_SCHEMA) +from homeassistant.components.lightwave import LIGHTWAVE_LINK DEVICE_SCHEMA = vol.Schema({ vol.Required(CONF_NAME): cv.string }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA} + vol.Required(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA} }) _LOGGER = logging.getLogger(__name__) -LIGHTWAVE_LINK = 'lightwave_link' DEPENDENCIES = ['lightwave'] diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index 5cc1aa3b27a042..2de261a85e74fb 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -1,21 +1,11 @@ """ -homeassistant.components.lightwave. +Support for device connected via Lightwave WiFi-link hub. -Implements communication with LightwaveRF. - -My understanding of the LightWave Hub is that devices cannot be discovered -so must be registered manually. This is done in the configuration file. - -lightwave: - host: ip_address - -Where ip_address is the ip address of your LightwaveRF hub - -For more details on the api see: https://api.lightwaverf.com/ +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/lightwave/ """ import voluptuous as vol -from lightwave.lightwave import LWLink from homeassistant.const import CONF_HOST from homeassistant.helpers import config_validation as cv @@ -32,6 +22,8 @@ async def async_setup(hass, config): """Try to start embedded Lightwave broker.""" - host = config[DOMAIN].get(CONF_HOST) + from lightwave.lightwave import LWLink + + host = config[DOMAIN][CONF_HOST] hass.data[LIGHTWAVE_LINK] = LWLink(host) return True diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index eff9ceb4f06c1d..37bbd3ccf5291f 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -10,6 +10,7 @@ from homeassistant.const import CONF_DEVICES, CONF_NAME from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) +from homeassistant.components.lightwave import LIGHTWAVE_LINK DEVICE_SCHEMA = vol.Schema({ vol.Required(CONF_NAME): cv.string @@ -21,7 +22,6 @@ _LOGGER = logging.getLogger(__name__) -LIGHTWAVE_LINK = 'lightwave_link' DEPENDENCIES = ['lightwave'] From 369f4100e2501b4483ffee90cdd7983a14eb83eb Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sun, 25 Nov 2018 12:57:42 +0000 Subject: [PATCH 14/25] Added lightwave to requirements_all.txt --- requirements_all.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/requirements_all.txt b/requirements_all.txt index e46fdeb3a6e015..4d75687449b28d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -564,6 +564,9 @@ liffylights==0.9.4 # homeassistant.components.light.osramlightify lightify==1.0.6.1 +# homeassistant.components.lightwave +lightwave==0.14 + # homeassistant.components.light.limitlessled limitlessled==1.1.3 @@ -1605,4 +1608,4 @@ zigpy-xbee==0.1.1 zigpy==0.2.0 # homeassistant.components.zoneminder -zm-py==0.1.0 +zm-py==0.1.0 \ No newline at end of file From 073592bd93d57f099b3a7f81a8c9cb680a5dfec1 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sun, 25 Nov 2018 15:07:27 +0000 Subject: [PATCH 15/25] Omit lightwave from tests. --- .coveragerc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.coveragerc b/.coveragerc index dea02d21f567d5..659f84ec4aabf1 100644 --- a/.coveragerc +++ b/.coveragerc @@ -200,6 +200,9 @@ omit = homeassistant/components/linode.py homeassistant/components/*/linode.py + homeassistant/components/lightwave.py + homeassistant/components/*/lightwave.py + homeassistant/components/logi_circle.py homeassistant/components/*/logi_circle.py From e728ab51d7eb924fe46533436ff867ca1c139119 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Mon, 26 Nov 2018 20:36:10 +0000 Subject: [PATCH 16/25] Updated requirements_all.txt --- requirements_all.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_all.txt b/requirements_all.txt index 4d75687449b28d..c604e60506b348 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1608,4 +1608,4 @@ zigpy-xbee==0.1.1 zigpy==0.2.0 # homeassistant.components.zoneminder -zm-py==0.1.0 \ No newline at end of file +zm-py==0.1.0 From f5c2de6c2abcf305abf99623ac99e14e0bb9235f Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Fri, 30 Nov 2018 18:04:10 +0000 Subject: [PATCH 17/25] Refactored how lightwave lights and switches load. --- homeassistant/components/light/lightwave.py | 22 +++++++------------- homeassistant/components/lightwave.py | 21 ++++++++++++++++++- homeassistant/components/switch/lightwave.py | 14 +++---------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 67354b39261d1d..49f9ec4198ad5d 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -8,23 +8,17 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv -from homeassistant.const import CONF_DEVICES, CONF_NAME +from homeassistant.const import CONF_NAME from homeassistant.components.light import ( - Light, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, PLATFORM_SCHEMA) + Light, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS) from homeassistant.components.lightwave import LIGHTWAVE_LINK -DEVICE_SCHEMA = vol.Schema({ - vol.Required(CONF_NAME): cv.string -}) - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA} -}) - _LOGGER = logging.getLogger(__name__) DEPENDENCIES = ['lightwave'] +MAX_BRIGHTNESS = 255 + async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): @@ -32,7 +26,7 @@ async def async_setup_platform(hass, config, async_add_entities, lights = [] lwlink = hass.data[LIGHTWAVE_LINK] - for device_id, device_config in config.get(CONF_DEVICES, {}).items(): + for device_id, device_config in discovery_info.items(): name = device_config[CONF_NAME] lights.append(LRFLight(name, device_id, lwlink)) @@ -47,7 +41,7 @@ def __init__(self, name, device_id, lwlink): self._name = name self._device_id = device_id self._state = None - self._brightness = 255 + self._brightness = MAX_BRIGHTNESS self._lwlink = lwlink @property @@ -67,7 +61,7 @@ def name(self): @property def brightness(self): - """Brightness of this light between 0..255.""" + """Brightness of this light between 0..MAX_BRIGHTNESS.""" return self._brightness @property @@ -82,7 +76,7 @@ async def async_turn_on(self, **kwargs): if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] - if self._brightness != 255: + if self._brightness != MAX_BRIGHTNESS: self._lwlink.turn_on_with_brightness( self._device_id, self._name, self._brightness) else: diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index 2de261a85e74fb..79aec2a958a6e0 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -6,8 +6,10 @@ """ import voluptuous as vol -from homeassistant.const import CONF_HOST +from homeassistant.const import CONF_HOST, CONF_LIGHTS, CONF_NAME, CONF_SWITCHES from homeassistant.helpers import config_validation as cv +from homeassistant.helpers.discovery import async_load_platform + REQUIREMENTS = ['lightwave==0.14'] LIGHTWAVE_LINK = 'lightwave_link' @@ -16,6 +18,12 @@ CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_LIGHTS, default={}): { + cv.string: vol.Schema({vol.Required(CONF_NAME): cv.string}), + }, + vol.Optional(CONF_SWITCHES, default={}): { + cv.string: vol.Schema({vol.Required(CONF_NAME): cv.string}), + } }) }, extra=vol.ALLOW_EXTRA) @@ -26,4 +34,15 @@ async def async_setup(hass, config): host = config[DOMAIN][CONF_HOST] hass.data[LIGHTWAVE_LINK] = LWLink(host) + + lights = config[DOMAIN][CONF_LIGHTS] + if lights: + hass.async_create_task(async_load_platform( + hass, 'light', DOMAIN, lights, config)) + + switches = config[DOMAIN][CONF_SWITCHES] + if switches: + hass.async_create_task(async_load_platform( + hass, 'switch', DOMAIN, switches, config)) + return True diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index 37bbd3ccf5291f..735d82540652ff 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -8,18 +8,10 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv -from homeassistant.const import CONF_DEVICES, CONF_NAME -from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) +from homeassistant.const import CONF_NAME +from homeassistant.components.switch import SwitchDevice from homeassistant.components.lightwave import LIGHTWAVE_LINK -DEVICE_SCHEMA = vol.Schema({ - vol.Required(CONF_NAME): cv.string -}) - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA} -}) - _LOGGER = logging.getLogger(__name__) DEPENDENCIES = ['lightwave'] @@ -31,7 +23,7 @@ async def async_setup_platform(hass, config, async_add_entities, switches = [] lwlink = hass.data[LIGHTWAVE_LINK] - for device_id, device_config in config.get(CONF_DEVICES, {}).items(): + for device_id, device_config in discovery_info.items(): name = device_config[CONF_NAME] switches.append(LRFSwitch(name, device_id, lwlink)) From 037c6260f7a49555ab634738da8d12637674156a Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Fri, 30 Nov 2018 18:50:04 +0000 Subject: [PATCH 18/25] Removed imports that were no longer required. --- homeassistant/components/light/lightwave.py | 6 ------ homeassistant/components/switch/lightwave.py | 6 ------ 2 files changed, 12 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 49f9ec4198ad5d..1e80e9e85af0bd 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -4,17 +4,11 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/light.lightwave/ """ -import logging -import voluptuous as vol -import homeassistant.helpers.config_validation as cv - from homeassistant.const import CONF_NAME from homeassistant.components.light import ( Light, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS) from homeassistant.components.lightwave import LIGHTWAVE_LINK -_LOGGER = logging.getLogger(__name__) - DEPENDENCIES = ['lightwave'] MAX_BRIGHTNESS = 255 diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index 735d82540652ff..6e794b31d01699 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -4,16 +4,10 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/switch.lightwave/ """ -import logging -import voluptuous as vol -import homeassistant.helpers.config_validation as cv - from homeassistant.const import CONF_NAME from homeassistant.components.switch import SwitchDevice from homeassistant.components.lightwave import LIGHTWAVE_LINK -_LOGGER = logging.getLogger(__name__) - DEPENDENCIES = ['lightwave'] From c9d8ae08a2d492e468c7c44516a2047e18b7c861 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sat, 1 Dec 2018 10:49:51 +0000 Subject: [PATCH 19/25] Add guard for no discovery_info. --- homeassistant/components/light/lightwave.py | 13 +++++++------ homeassistant/components/switch/lightwave.py | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 1e80e9e85af0bd..c7b40f24c286b8 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -17,14 +17,15 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Find and return LightWave lights.""" - lights = [] - lwlink = hass.data[LIGHTWAVE_LINK] + if discovery_info: + lights = [] + lwlink = hass.data[LIGHTWAVE_LINK] - for device_id, device_config in discovery_info.items(): - name = device_config[CONF_NAME] - lights.append(LRFLight(name, device_id, lwlink)) + for device_id, device_config in discovery_info.items(): + name = device_config[CONF_NAME] + lights.append(LRFLight(name, device_id, lwlink)) - async_add_entities(lights) + async_add_entities(lights) class LRFLight(Light): diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index 6e794b31d01699..4d8b0e74671dc6 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -14,14 +14,15 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Find and return LightWave switches.""" - switches = [] - lwlink = hass.data[LIGHTWAVE_LINK] + if discovery_info: + switches = [] + lwlink = hass.data[LIGHTWAVE_LINK] - for device_id, device_config in discovery_info.items(): - name = device_config[CONF_NAME] - switches.append(LRFSwitch(name, device_id, lwlink)) + for device_id, device_config in discovery_info.items(): + name = device_config[CONF_NAME] + switches.append(LRFSwitch(name, device_id, lwlink)) - async_add_entities(switches) + async_add_entities(switches) class LRFSwitch(SwitchDevice): From b08f076f1ec551cb62990a08218a0f6a914098f1 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sat, 1 Dec 2018 12:40:55 +0000 Subject: [PATCH 20/25] Make it a guard clause and save indentation. Rename LRFxxx to LWRFxxx. --- homeassistant/components/light/lightwave.py | 20 +++++++++++--------- homeassistant/components/lightwave.py | 2 +- homeassistant/components/switch/lightwave.py | 20 +++++++++++--------- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index c7b40f24c286b8..9f1607fd0798de 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -17,22 +17,24 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Find and return LightWave lights.""" - if discovery_info: - lights = [] - lwlink = hass.data[LIGHTWAVE_LINK] + if not discovery_info: + return True - for device_id, device_config in discovery_info.items(): - name = device_config[CONF_NAME] - lights.append(LRFLight(name, device_id, lwlink)) + lights = [] + lwlink = hass.data[LIGHTWAVE_LINK] - async_add_entities(lights) + for device_id, device_config in discovery_info.items(): + name = device_config[CONF_NAME] + lights.append(LWRFLight(name, device_id, lwlink)) + async_add_entities(lights) -class LRFLight(Light): + +class LWRFLight(Light): """Representation of a LightWaveRF light.""" def __init__(self, name, device_id, lwlink): - """Initialize LRFLight entity.""" + """Initialize LWRFLight entity.""" self._name = name self._device_id = device_id self._state = None diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index 79aec2a958a6e0..fd7dd73ac0b02d 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -11,7 +11,7 @@ from homeassistant.helpers.discovery import async_load_platform -REQUIREMENTS = ['lightwave==0.14'] +REQUIREMENTS = ['lightwave==0.15'] LIGHTWAVE_LINK = 'lightwave_link' DOMAIN = 'lightwave' diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index 4d8b0e74671dc6..c5e64a9c90073e 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -14,22 +14,24 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Find and return LightWave switches.""" - if discovery_info: - switches = [] - lwlink = hass.data[LIGHTWAVE_LINK] + if not discovery_info: + return True - for device_id, device_config in discovery_info.items(): - name = device_config[CONF_NAME] - switches.append(LRFSwitch(name, device_id, lwlink)) + switches = [] + lwlink = hass.data[LIGHTWAVE_LINK] - async_add_entities(switches) + for device_id, device_config in discovery_info.items(): + name = device_config[CONF_NAME] + switches.append(LWRFSwitch(name, device_id, lwlink)) + async_add_entities(switches) -class LRFSwitch(SwitchDevice): + +class LWRFSwitch(SwitchDevice): """Representation of a LightWaveRF switch.""" def __init__(self, name, device_id, lwlink): - """Initialize LRFSwitch entity.""" + """Initialize LWRFSwitch entity.""" self._name = name self._device_id = device_id self._state = None From 533e1e9d6d9a5b378cd80ca857180357a2b26110 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sat, 1 Dec 2018 12:49:39 +0000 Subject: [PATCH 21/25] Sorted imports to match style guidelines. --- homeassistant/components/light/lightwave.py | 4 ++-- homeassistant/components/lightwave.py | 4 ++-- homeassistant/components/switch/lightwave.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 9f1607fd0798de..8d965deb1cb02f 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -4,10 +4,10 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/light.lightwave/ """ -from homeassistant.const import CONF_NAME from homeassistant.components.light import ( - Light, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS) + ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light) from homeassistant.components.lightwave import LIGHTWAVE_LINK +from homeassistant.const import CONF_NAME DEPENDENCIES = ['lightwave'] diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index fd7dd73ac0b02d..e95e6577ae589a 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -6,11 +6,11 @@ """ import voluptuous as vol -from homeassistant.const import CONF_HOST, CONF_LIGHTS, CONF_NAME, CONF_SWITCHES +from homeassistant.const import ( + CONF_HOST, CONF_LIGHTS, CONF_NAME, CONF_SWITCHES) from homeassistant.helpers import config_validation as cv from homeassistant.helpers.discovery import async_load_platform - REQUIREMENTS = ['lightwave==0.15'] LIGHTWAVE_LINK = 'lightwave_link' DOMAIN = 'lightwave' diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index c5e64a9c90073e..bba6b87d9349cf 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -4,9 +4,9 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/switch.lightwave/ """ -from homeassistant.const import CONF_NAME -from homeassistant.components.switch import SwitchDevice from homeassistant.components.lightwave import LIGHTWAVE_LINK +from homeassistant.components.switch import SwitchDevice +from homeassistant.const import CONF_NAME DEPENDENCIES = ['lightwave'] From 1dee677404edfdbf05b3bce40edbcb38eb7dab0c Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sat, 1 Dec 2018 13:49:05 +0000 Subject: [PATCH 22/25] Correct return value. --- homeassistant/components/light/lightwave.py | 2 +- homeassistant/components/switch/lightwave.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/light/lightwave.py b/homeassistant/components/light/lightwave.py index 8d965deb1cb02f..50c664d90463d8 100644 --- a/homeassistant/components/light/lightwave.py +++ b/homeassistant/components/light/lightwave.py @@ -18,7 +18,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Find and return LightWave lights.""" if not discovery_info: - return True + return lights = [] lwlink = hass.data[LIGHTWAVE_LINK] diff --git a/homeassistant/components/switch/lightwave.py b/homeassistant/components/switch/lightwave.py index bba6b87d9349cf..b612cd8dec74cb 100644 --- a/homeassistant/components/switch/lightwave.py +++ b/homeassistant/components/switch/lightwave.py @@ -15,7 +15,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Find and return LightWave switches.""" if not discovery_info: - return True + return switches = [] lwlink = hass.data[LIGHTWAVE_LINK] From 1b7d3a6a9beeff1c678f3096fea067478dce7c34 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sat, 1 Dec 2018 15:46:01 +0000 Subject: [PATCH 23/25] Update requirements_all.txt --- requirements_all.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_all.txt b/requirements_all.txt index c604e60506b348..4cebe1a25cfe41 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -565,7 +565,7 @@ liffylights==0.9.4 lightify==1.0.6.1 # homeassistant.components.lightwave -lightwave==0.14 +lightwave==0.15 # homeassistant.components.light.limitlessled limitlessled==1.1.3 From 115a929a82d7a8bf57a84768ece37291f914bc03 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sat, 1 Dec 2018 19:44:59 +0000 Subject: [PATCH 24/25] Catch case where we have no lights or switches configured. --- homeassistant/components/lightwave.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index e95e6577ae589a..07dcb36cae4997 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -5,9 +5,8 @@ https://home-assistant.io/components/lightwave/ """ import voluptuous as vol - -from homeassistant.const import ( - CONF_HOST, CONF_LIGHTS, CONF_NAME, CONF_SWITCHES) +from homeassistant.const import (CONF_HOST, CONF_LIGHTS, CONF_NAME, + CONF_SWITCHES) from homeassistant.helpers import config_validation as cv from homeassistant.helpers.discovery import async_load_platform @@ -30,17 +29,21 @@ async def async_setup(hass, config): """Try to start embedded Lightwave broker.""" + lights = config[DOMAIN][CONF_LIGHTS] + switches = config[DOMAIN][CONF_SWITCHES] + + if not lights and not switches: + return True + from lightwave.lightwave import LWLink host = config[DOMAIN][CONF_HOST] hass.data[LIGHTWAVE_LINK] = LWLink(host) - lights = config[DOMAIN][CONF_LIGHTS] if lights: hass.async_create_task(async_load_platform( hass, 'light', DOMAIN, lights, config)) - switches = config[DOMAIN][CONF_SWITCHES] if switches: hass.async_create_task(async_load_platform( hass, 'switch', DOMAIN, switches, config)) From f84a9fa274793e911e8aed4fe2f9d04bbef71ff8 Mon Sep 17 00:00:00 2001 From: GeoffAtHome Date: Sun, 2 Dec 2018 08:51:33 +0000 Subject: [PATCH 25/25] Improve configuration validation. --- homeassistant/components/lightwave.py | 30 +++++++++++++-------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/lightwave.py b/homeassistant/components/lightwave.py index 07dcb36cae4997..e1aa1664eba49c 100644 --- a/homeassistant/components/lightwave.py +++ b/homeassistant/components/lightwave.py @@ -5,45 +5,43 @@ https://home-assistant.io/components/lightwave/ """ import voluptuous as vol +import homeassistant.helpers.config_validation as cv from homeassistant.const import (CONF_HOST, CONF_LIGHTS, CONF_NAME, CONF_SWITCHES) -from homeassistant.helpers import config_validation as cv from homeassistant.helpers.discovery import async_load_platform REQUIREMENTS = ['lightwave==0.15'] LIGHTWAVE_LINK = 'lightwave_link' DOMAIN = 'lightwave' + CONFIG_SCHEMA = vol.Schema({ - DOMAIN: vol.Schema({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_LIGHTS, default={}): { - cv.string: vol.Schema({vol.Required(CONF_NAME): cv.string}), - }, - vol.Optional(CONF_SWITCHES, default={}): { - cv.string: vol.Schema({vol.Required(CONF_NAME): cv.string}), - } - }) + DOMAIN: vol.Schema( + cv.has_at_least_one_key(CONF_LIGHTS, CONF_SWITCHES), { + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_LIGHTS, default={}): { + cv.string: vol.Schema({vol.Required(CONF_NAME): cv.string}), + }, + vol.Optional(CONF_SWITCHES, default={}): { + cv.string: vol.Schema({vol.Required(CONF_NAME): cv.string}), + } + }) }, extra=vol.ALLOW_EXTRA) async def async_setup(hass, config): """Try to start embedded Lightwave broker.""" - lights = config[DOMAIN][CONF_LIGHTS] - switches = config[DOMAIN][CONF_SWITCHES] - - if not lights and not switches: - return True - from lightwave.lightwave import LWLink host = config[DOMAIN][CONF_HOST] hass.data[LIGHTWAVE_LINK] = LWLink(host) + lights = config[DOMAIN][CONF_LIGHTS] if lights: hass.async_create_task(async_load_platform( hass, 'light', DOMAIN, lights, config)) + switches = config[DOMAIN][CONF_SWITCHES] if switches: hass.async_create_task(async_load_platform( hass, 'switch', DOMAIN, switches, config))