Add Lightwave TRV (#31665)

* Add a shadow for covers that do not support postion

* Rename shadow as optimistic

* Add TRV support

* Revert "Rename shadow as optimistic"

This reverts commit e6e1db9cfb.

* Revert "Add a shadow for covers that do not support postion"

This reverts commit 4f53e2c6c6.

* fix logic error

* Modified configuration

* Modified configuration (2)

* ATTR_BATTERY_LEVEL

* move socket code to library 2

* requirements_all.txt

* Update homeassistant/components/lightwave/sensor.py

Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com>

* Style changes requested by @sprintstan

* Update homeassistant/components/lightwave/__init__.py

Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com>

* Update homeassistant/components/lightwave/__init__.py

Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com>

* Update homeassistant/components/lightwave/__init__.py

Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com>

* Black

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com>

* Remove device_attr

* remove redundant proxy parameters, left over from previous change

* remove device id - not used

* add comment on inhibit flag

* pylint

* fix config logic error

* revert suggested change: need different behaviour with None & 0

* touch

* backoff error in rebase change

* Requesed code changes from @springstan

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/sensor.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/sensor.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/climate.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/sensor.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/sensor.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/lightwave/sensor.py

Co-Authored-By: Martin Hjelmare <marhje52@gmail.com>

* Changes requested by @MartinHjelmare

* Clean temp step constant

Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com>

Co-authored-by: springstan <46536646+springstan@users.noreply.github.com>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Colin Robbins 2020-04-13 03:35:47 +01:00 committed by GitHub
parent c7ab5de07c
commit c5adcab195
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 248 additions and 7 deletions

View File

@ -2,20 +2,30 @@
from lightwave.lightwave import LWLink
import voluptuous as vol
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import CONF_HOST, CONF_LIGHTS, CONF_NAME, CONF_SWITCHES
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.discovery import async_load_platform
LIGHTWAVE_LINK = "lightwave_link"
CONF_SERIAL = "serial"
CONF_PROXY_IP = "proxy_ip"
CONF_PROXY_PORT = "proxy_port"
CONF_TRV = "trv"
CONF_TRVS = "trvs"
DEFAULT_PROXY_PORT = 7878
DEFAULT_PROXY_IP = "127.0.0.1"
DOMAIN = "lightwave"
LIGHTWAVE_LINK = f"{DOMAIN}_link"
LIGHTWAVE_TRV_PROXY = f"{DOMAIN}_proxy"
LIGHTWAVE_TRV_PROXY_PORT = f"{DOMAIN}_proxy_port"
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
vol.All(
cv.has_at_least_one_key(CONF_LIGHTS, CONF_SWITCHES),
cv.has_at_least_one_key(CONF_LIGHTS, CONF_SWITCHES, CONF_TRV),
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_LIGHTS, default={}): {
@ -24,6 +34,22 @@ CONFIG_SCHEMA = vol.Schema(
vol.Optional(CONF_SWITCHES, default={}): {
cv.string: vol.Schema({vol.Required(CONF_NAME): cv.string})
},
vol.Optional(CONF_TRV, default={}): {
vol.Optional(
CONF_PROXY_PORT, default=DEFAULT_PROXY_PORT
): cv.port,
vol.Optional(
CONF_PROXY_IP, default=DEFAULT_PROXY_IP
): cv.string,
vol.Required(CONF_TRVS, default={}): {
cv.string: vol.Schema(
{
vol.Required(CONF_NAME): cv.string,
vol.Required(CONF_SERIAL): cv.string,
}
)
},
},
},
)
)
@ -34,9 +60,9 @@ CONFIG_SCHEMA = vol.Schema(
async def async_setup(hass, config):
"""Try to start embedded Lightwave broker."""
host = config[DOMAIN][CONF_HOST]
hass.data[LIGHTWAVE_LINK] = LWLink(host)
lwlink = LWLink(host)
hass.data[LIGHTWAVE_LINK] = lwlink
lights = config[DOMAIN][CONF_LIGHTS]
if lights:
@ -50,4 +76,17 @@ async def async_setup(hass, config):
async_load_platform(hass, "switch", DOMAIN, switches, config)
)
trv = config[DOMAIN][CONF_TRV]
if trv:
trvs = trv[CONF_TRVS]
proxy_ip = trv[CONF_PROXY_IP]
proxy_port = trv[CONF_PROXY_PORT]
lwlink.set_trv_proxy(proxy_ip, proxy_port)
platforms = [CLIMATE_DOMAIN, SENSOR_DOMAIN]
for platform in platforms:
hass.async_create_task(
async_load_platform(hass, platform, DOMAIN, trvs, config)
)
return True

View File

@ -0,0 +1,142 @@
"""Support for LightwaveRF TRVs."""
from homeassistant.components.climate import (
DEFAULT_MAX_TEMP,
DEFAULT_MIN_TEMP,
HVAC_MODE_HEAT,
HVAC_MODE_OFF,
SUPPORT_TARGET_TEMPERATURE,
ClimateDevice,
)
from homeassistant.components.climate.const import CURRENT_HVAC_HEAT, CURRENT_HVAC_OFF
from homeassistant.const import ATTR_TEMPERATURE, CONF_NAME, TEMP_CELSIUS
from . import CONF_SERIAL, LIGHTWAVE_LINK
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Find and return LightWave lights."""
if discovery_info is None:
return
entities = []
lwlink = hass.data[LIGHTWAVE_LINK]
for device_id, device_config in discovery_info.items():
name = device_config[CONF_NAME]
serial = device_config[CONF_SERIAL]
entities.append(LightwaveTrv(name, device_id, lwlink, serial))
async_add_entities(entities)
class LightwaveTrv(ClimateDevice):
"""Representation of a LightWaveRF TRV."""
def __init__(self, name, device_id, lwlink, serial):
"""Initialize LightwaveTrv entity."""
self._name = name
self._device_id = device_id
self._state = None
self._current_temperature = None
self._target_temperature = None
self._hvac_action = None
self._lwlink = lwlink
self._serial = serial
# inhibit is used to prevent race condition on update. If non zero, skip next update cycle.
self._inhibit = 0
@property
def supported_features(self):
"""Flag supported features."""
return SUPPORT_TARGET_TEMPERATURE
def update(self):
"""Communicate with a Lightwave RTF Proxy to get state."""
(temp, targ, _, trv_output) = self._lwlink.read_trv_status(self._serial)
if temp is not None:
self._current_temperature = temp
if targ is not None:
if self._inhibit == 0:
self._target_temperature = targ
if targ == 0:
# TRV off
self._target_temperature = None
if targ >= 40:
# Call for heat mode, or TRV in a fixed position
self._target_temperature = None
else:
# Done the job - use proxy next iteration
self._inhibit = 0
if trv_output is not None:
if trv_output > 0:
self._hvac_action = CURRENT_HVAC_HEAT
else:
self._hvac_action = CURRENT_HVAC_OFF
@property
def name(self):
"""Lightwave trv name."""
return self._name
@property
def current_temperature(self):
"""Property giving the current room temperature."""
return self._current_temperature
@property
def target_temperature(self):
"""Target room temperature."""
if self._inhibit > 0:
# If we get an update before the new temp has
# propagated, the target temp is set back to the
# old target on the next poll, showing a false
# reading temporarily.
self._target_temperature = self._inhibit
return self._target_temperature
@property
def hvac_modes(self):
"""HVAC modes."""
return [HVAC_MODE_HEAT, HVAC_MODE_OFF]
@property
def hvac_mode(self):
"""HVAC mode."""
return HVAC_MODE_HEAT
@property
def hvac_action(self):
"""HVAC action."""
return self._hvac_action
@property
def min_temp(self):
"""Min Temp."""
return DEFAULT_MIN_TEMP
@property
def max_temp(self):
"""Max Temp."""
return DEFAULT_MAX_TEMP
@property
def temperature_unit(self):
"""Set temperature unit."""
return TEMP_CELSIUS
@property
def target_temperature_step(self):
"""Set temperature step."""
return 0.5
def set_temperature(self, **kwargs):
"""Set TRV target temperature."""
if ATTR_TEMPERATURE in kwargs:
self._target_temperature = kwargs[ATTR_TEMPERATURE]
self._inhibit = self._target_temperature
self._lwlink.set_temperature(
self._device_id, self._target_temperature, self._name
)
async def async_set_hvac_mode(self, hvac_mode):
"""Set HVAC Mode for TRV."""

View File

@ -2,6 +2,6 @@
"domain": "lightwave",
"name": "Lightwave",
"documentation": "https://www.home-assistant.io/integrations/lightwave",
"requirements": ["lightwave==0.17"],
"requirements": ["lightwave==0.18"],
"codeowners": []
}

View File

@ -0,0 +1,60 @@
"""Support for LightwaveRF TRV - Associated Battery."""
from homeassistant.const import CONF_NAME, DEVICE_CLASS_BATTERY, UNIT_PERCENTAGE
from homeassistant.helpers.entity import Entity
from . import CONF_SERIAL, LIGHTWAVE_LINK
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Find and return battery."""
if discovery_info is None:
return
batteries = []
lwlink = hass.data[LIGHTWAVE_LINK]
for device_config in discovery_info.values():
name = device_config[CONF_NAME]
serial = device_config[CONF_SERIAL]
batteries.append(LightwaveBattery(name, lwlink, serial))
async_add_entities(batteries)
class LightwaveBattery(Entity):
"""Lightwave TRV Battery."""
def __init__(self, name, lwlink, serial):
"""Initialize the Lightwave Trv battery sensor."""
self._name = name
self._state = None
self._lwlink = lwlink
self._serial = serial
@property
def device_class(self):
"""Return the device class of the sensor."""
return DEVICE_CLASS_BATTERY
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def state(self):
"""Return the state of the sensor."""
return self._state
@property
def unit_of_measurement(self):
"""Return the state of the sensor."""
return UNIT_PERCENTAGE
def update(self):
"""Communicate with a Lightwave RTF Proxy to get state."""
(dummy_temp, dummy_targ, battery, dummy_output) = self._lwlink.read_trv_status(
self._serial
)
self._state = battery

View File

@ -818,7 +818,7 @@ liffylights==0.9.4
lightify==1.0.7.2
# homeassistant.components.lightwave
lightwave==0.17
lightwave==0.18
# homeassistant.components.limitlessled
limitlessled==1.1.3