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 commite6e1db9cfb
. * Revert "Add a shadow for covers that do not support postion" This reverts commit4f53e2c6c6
. * 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:
parent
c7ab5de07c
commit
c5adcab195
5 changed files with 248 additions and 7 deletions
|
@ -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
|
||||
|
|
142
homeassistant/components/lightwave/climate.py
Normal file
142
homeassistant/components/lightwave/climate.py
Normal 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."""
|
|
@ -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": []
|
||||
}
|
||||
|
|
60
homeassistant/components/lightwave/sensor.py
Normal file
60
homeassistant/components/lightwave/sensor.py
Normal 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
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue