Skip to content

Commit

Permalink
Merge pull request #268 from PeteRager/2023_10_0
Browse files Browse the repository at this point in the history
2023 10 0
  • Loading branch information
PeteRager committed Oct 6, 2023
2 parents 25ce86f + 46f5754 commit 6f5f46c
Show file tree
Hide file tree
Showing 21 changed files with 1,595 additions and 369 deletions.
11 changes: 9 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
{
"python.testing.pytestArgs": ["tests"],
"python.testing.pytestArgs": ["tests", "--asyncio-mode=auto"],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"cSpell.words": [
"ASHRAE",
"automations",
"desp",
"dewpoint",
"HACS",
"heatpump",
"homeassistant",
"husp",
"HVAC",
"Lennox",
"lennoxicomfort",
"lennoxs",
"rssi",
"Setpoint",
"setpoints",
"sysuptime"
],
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--line-length", "120"],
"cSpell.enabled": false,
"cSpell.enabled": true,
"python.linting.flake8Enabled": false,
"python.linting.enabled": true,
"python.linting.flake8Args": ["--config=setup.cfg", "--doctests"],
Expand Down
136 changes: 84 additions & 52 deletions README.MD

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions custom_components/lennoxs30/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
UNIQUE_ID_SUFFIX_RESET_SMART_HUB: Final = "_RESET_SMART_HUB"
UNIQUE_ID_SUFFIX_BLE: Final = "_BLE"
UNIQUE_ID_SUFFIX_BLE_COMMSTATUS: Final = "_BLE_COMMSTATUS"
UNIQUE_ID_SUFFIX_VENTILATION_SELECT: Final = "_VENT_SELECT"

VENTILATION_EQUIPMENT_ID = -900

Expand Down
52 changes: 52 additions & 0 deletions custom_components/lennoxs30/diagnostics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Diagnostics support for Nest."""
# pylint: disable=line-too-long
from __future__ import annotations
from typing import Any

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD

from . import MANAGER, Manager
from .const import LENNOX_DOMAIN


async def async_get_config_entry_diagnostics(hass: HomeAssistant, config_entry: ConfigEntry) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
manager: Manager = hass.data[LENNOX_DOMAIN][config_entry.unique_id][MANAGER]
data: dict[str, Any] = {}

data["config"] = {}
for key, val in config_entry.data.items():
data["config"][key] = val
if CONF_PASSWORD in data["config"]:
data["config"][CONF_PASSWORD] = "**redacted**"
if CONF_EMAIL in data["config"]:
data["config"][CONF_EMAIL] = "**redacted**"
data["system"] = {}
for system in manager.api.system_list:
system_data: dict[str, any] = {
"relayServer": system.relayServerConnected,
"internet": system.internetStatus,
"diagLevel": system.diagLevel,
"cloud_status": system.cloud_status,
"productType": system.productType,
"sibling_identifier": system.sibling_identifier,
"sibling_ip": system.sibling_ipAddress,
"softwareVersion": system.softwareVersion,
"sysUpTime": system.sysUpTime,
}

system_data["equipment"] = {}
for eq_id, equipment in system.equipment.items():
element = {
"name": equipment.equipment_name,
"eqType": equipment.equipType,
"eqTypeName": equipment.equipment_type_name,
"model": equipment.unit_model_number,
}
system_data["equipment"][eq_id] = element
data["system"][system.sysId] = system_data

data["comm_metrics"] = manager.getMetricsList()
return data
4 changes: 2 additions & 2 deletions custom_components/lennoxs30/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"iot_class": "local_push",
"issue_tracker" : "https://github.com/PeteRager/lennoxs30/issues",
"quality_scale": "platinum",
"requirements": ["lennoxs30api==0.2.8"],
"version": "2023.6.1"
"requirements": ["lennoxs30api==0.2.10"],
"version": "2023.10.0"
}
5 changes: 2 additions & 3 deletions custom_components/lennoxs30/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
lennox_system,
LENNOX_CIRCULATE_TIME_MAX,
LENNOX_CIRCULATE_TIME_MIN,
LENNOX_VENTILATION_CONTROL_MODE_TIMED,
)

from lennoxs30api.lennox_equipment import (
Expand Down Expand Up @@ -98,7 +97,7 @@ async def async_setup_entry(
number = CirculateTime(hass, manager, system)
number_list.append(number)

if system.supports_ventilation() and system.ventilationControlMode == LENNOX_VENTILATION_CONTROL_MODE_TIMED:
if system.supports_ventilation():
number = TimedVentilationNumber(hass, manager, system)
number_list.append(number)

Expand Down Expand Up @@ -368,7 +367,7 @@ class TimedVentilationNumber(S30BaseEntityMixin, NumberEntity):
def __init__(self, hass: HomeAssistant, manager: Manager, system: lennox_system):
super().__init__(manager, system)
self._hass = hass
self._myname = self._system.name + "_timed_ventilation"
self._myname = self._system.name + "_ventilate_now"
_LOGGER.debug("Create TimedVentilationNumber myname [%s]", self._myname)

async def async_added_to_hass(self) -> None:
Expand Down
99 changes: 98 additions & 1 deletion custom_components/lennoxs30/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
LENNOX_DEHUMIDIFICATION_MODE_HIGH,
LENNOX_DEHUMIDIFICATION_MODE_MEDIUM,
LENNOX_DEHUMIDIFICATION_MODE_AUTO,
LENNOX_VENTILATION_MODES,
LENNOX_VENTILATION_MODE_INSTALLER,
LENNOX_VENTILATION_MODE_ON,
LENNOX_VENTILATION_MODE_OFF,
lennox_system,
lennox_zone,
)
Expand All @@ -39,7 +43,12 @@
)

from .base_entity import S30BaseEntityMixin
from .const import LOG_INFO_SELECT_ASYNC_SELECT_OPTION, MANAGER, UNIQUE_ID_SUFFIX_EQ_PARAM_SELECT
from .const import (
LOG_INFO_SELECT_ASYNC_SELECT_OPTION,
MANAGER,
UNIQUE_ID_SUFFIX_EQ_PARAM_SELECT,
UNIQUE_ID_SUFFIX_VENTILATION_SELECT,
)
from . import DOMAIN, Manager


Expand All @@ -61,6 +70,11 @@ async def async_setup_entry(
_LOGGER.debug("Create DehumidificationModeSelect system [%s]", system.sysId)
sel = DehumidificationModeSelect(hass, manager, system)
select_list.append(sel)

if system.supports_ventilation():
_LOGGER.info("Create S30 ventilation select system [%s]", system.sysId)
select_list.append(VentilationModeSelect(hass, manager, system))

for zone in system.zone_list:
if zone.is_zone_active():
if zone.dehumidificationOption or zone.humidificationOption:
Expand Down Expand Up @@ -362,3 +376,86 @@ def entity_category(self):
@property
def extra_state_attributes(self) -> dict[str, Any]:
return helper_get_parameter_extra_attributes(self.equipment, self.parameter)


class VentilationModeSelect(S30BaseEntityMixin, SelectEntity):
"""Set the ventilation mode"""

def __init__(
self,
hass: HomeAssistant,
manager: Manager,
system: lennox_system,
):
super().__init__(manager, system)
self.hass: HomeAssistant = hass
self._myname = self._system.name + "_ventilation_mode"
_LOGGER.debug("Create VentilationModeSelect myname [%s]", self._myname)

async def async_added_to_hass(self) -> None:
"""Run when entity about to be added to hass."""
_LOGGER.debug("async_added_to_hass VentilationModeSelect myname [%s]", self._myname)
self._system.registerOnUpdateCallback(
self.system_update_callback,
[
"ventilationMode",
"ventilationControlMode",
],
)
await super().async_added_to_hass()

def system_update_callback(self):
"""Callback for system updates"""
if _LOGGER.isEnabledFor(logging.DEBUG):
_LOGGER.debug(
"system_update_callback VentilationModeSelect myname [%s] system ventilation mode [%s]",
self._myname,
self._system.ventilationMode,
)
self.schedule_update_ha_state()

@property
def unique_id(self) -> str:
# HA fails with dashes in IDs
return self._system.unique_id + UNIQUE_ID_SUFFIX_VENTILATION_SELECT

@property
def name(self):
return self._myname

@property
def current_option(self) -> str:
return self._system.ventilationMode

@property
def options(self) -> list:
return LENNOX_VENTILATION_MODES

async def async_select_option(self, option: str) -> None:
_LOGGER.info(LOG_INFO_SELECT_ASYNC_SELECT_OPTION, self.__class__.__name__, self._myname, option)
try:
if option == LENNOX_VENTILATION_MODE_ON:
await self._system.ventilation_on()
elif option == LENNOX_VENTILATION_MODE_OFF:
await self._system.ventilation_off()
elif option == LENNOX_VENTILATION_MODE_INSTALLER:
await self._system.ventilation_installer()
else:
raise HomeAssistantError(f"select_option [{self._myname}] invalid mode [{option}]")
except Exception as ex:
raise HomeAssistantError(f"select_option unexpected exception, [{self._myname}] exception [{ex}]") from ex

@property
def device_info(self) -> DeviceInfo:
"""Return device info."""
result = {
"identifiers": {(DOMAIN, self._system.unique_id)},
}
return result

@property
def extra_state_attributes(self):
"""Return the state attributes."""
attrs: dict[str, Any] = {}
attrs["installer_settings"] = self._system.ventilationControlMode
return attrs
25 changes: 23 additions & 2 deletions custom_components/lennoxs30/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
UnitOfFrequency,
UnitOfElectricCurrent,
UnitOfElectricPotential,
REVOLUTIONS_PER_MINUTE,
)
from homeassistant.core import HomeAssistant
from homeassistant.config_entries import ConfigEntry
Expand Down Expand Up @@ -47,6 +48,7 @@
from .ble_device_21p02 import lennox_21p02_sensors, lennox_iaq_sensors
from .sensor_ble import S40BleSensor
from .sensor_iaq import S40IAQSensor
from .sensor_wt_env import lennox_wt_env_sensors, WTEnvSensor, lennox_wt_env_sensors_metric, lennox_wt_env_sensors_us


_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -105,6 +107,19 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_e
diagsensor = S30DiagSensor(hass, manager, system, equip, diagnostic)
sensor_list.append(diagsensor)

if system.is_s40:
for env in lennox_wt_env_sensors:
wt_sensor = WTEnvSensor(hass, manager, system, env)
sensor_list.append(wt_sensor)
if manager.is_metric:
for env in lennox_wt_env_sensors_metric:
wt_sensor = WTEnvSensor(hass, manager, system, env)
sensor_list.append(wt_sensor)
else:
for env in lennox_wt_env_sensors_us:
wt_sensor = WTEnvSensor(hass, manager, system, env)
sensor_list.append(wt_sensor)

if manager.create_sensors:
for zone in system.zone_list:
if zone.is_zone_active():
Expand Down Expand Up @@ -182,7 +197,13 @@ def __init__(
self._equipment: lennox_equipment = equipment
self._diagnostic: lennox_equipment_diagnostic = diagnostic

if diagnostic.unit.strip() == "":
self.uom = diagnostic.unit.strip()
if self.uom == "":
# Lennox does not provide a unit for RPM
if self._diagnostic.name.endswith("RPM"):
self.uom = REVOLUTIONS_PER_MINUTE

if self.uom == "":
self._state_class = None
else:
self._state_class = SensorStateClass.MEASUREMENT
Expand Down Expand Up @@ -255,7 +276,7 @@ def name(self):

@property
def native_unit_of_measurement(self):
return lennox_uom_to_ha_uom(self._diagnostic.unit)
return lennox_uom_to_ha_uom(self.uom)

@property
def device_class(self):
Expand Down
Loading

0 comments on commit 6f5f46c

Please sign in to comment.