Skip to content

Commit

Permalink
wifi_rssi sensor
Browse files Browse the repository at this point in the history
  • Loading branch information
PeteRager committed Jan 13, 2024
1 parent dcf1b6f commit 3f9c9f0
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 1 deletion.
1 change: 1 addition & 0 deletions custom_components/lennoxs30/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
UNIQUE_ID_SUFFIX_BLE: Final = "_BLE"
UNIQUE_ID_SUFFIX_BLE_COMMSTATUS: Final = "_BLE_COMMSTATUS"
UNIQUE_ID_SUFFIX_VENTILATION_SELECT: Final = "_VENT_SELECT"
UNIQUE_ID_SUFFIX_WIFI_RSSI: Final = "_WIFI_RSSI"

VENTILATION_EQUIPMENT_ID = -900

Expand Down
5 changes: 4 additions & 1 deletion custom_components/lennoxs30/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
from .ble_device_21p02 import lennox_21p02_sensors, lennox_iaq_sensors
from .sensor_ble import S40BleSensor
from .sensor_iaq import S40IAQSensor
from .sensor_wifi import WifiRSSISensor
from .sensor_wt_env import lennox_wt_env_sensors, WTEnvSensor, lennox_wt_env_sensors_metric, lennox_wt_env_sensors_us


_LOGGER = logging.getLogger(__name__)

DOMAIN = "lennoxs30"
Expand Down Expand Up @@ -175,6 +175,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_e
ble_device.controlModelNumber,
)

if manager.api.isLANConnection:
sensor_list.append(WifiRSSISensor(hass, manager, system))

if len(sensor_list) != 0:
async_add_entities(sensor_list, True)
return True
Expand Down
93 changes: 93 additions & 0 deletions custom_components/lennoxs30/sensor_wifi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""Support for Lennoxs30 outdoor temperature sensor"""
# pylint: disable=global-statement
# pylint: disable=broad-except
# pylint: disable=unused-argument
# pylint: disable=line-too-long
# pylint: disable=invalid-name
import logging
from typing import Any

from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.components.sensor import SensorEntity
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.const import SIGNAL_STRENGTH_DECIBELS_MILLIWATT
from homeassistant.helpers.entity import EntityCategory

from lennoxs30api import lennox_system

from . import Manager
from .base_entity import S30BaseEntityMixin
from .const import LENNOX_DOMAIN, UNIQUE_ID_SUFFIX_WIFI_RSSI
from .helpers import helper_create_system_unique_id

_LOGGER = logging.getLogger(__name__)

class WifiRSSISensor(S30BaseEntityMixin, SensorEntity):
"""Class for Lennox S40 WTEnvSensor Sensors."""

def __init__(self, hass: HomeAssistant, manager: Manager, system: lennox_system):
super().__init__(manager, system)
self._hass = hass
self._myname = self._system.name + "_wifi_rssi"

async def async_added_to_hass(self) -> None:
"""Run when entity about to be added to hass."""
_LOGGER.debug("async_added_to_hass WifiRSSISensor myname [%s]", self._myname)
self._system.registerOnUpdateCallback(
self.update_callback,
["wifi_rssi", "wifi_macAddr", "wifi_ssid", "wifi_ip", "wifi_router","wifi_dns","wifi_dns2","wifi_subnetMask","wifi_bitRate"],
)
await super().async_added_to_hass()

def update_callback(self):
"""Callback to execute on data change"""
_LOGGER.debug("update_callback WifiRSSISensor myname [%s]", self._myname)
self.schedule_update_ha_state()

@property
def unique_id(self) -> str:
return (self._system.unique_id + UNIQUE_ID_SUFFIX_WIFI_RSSI).replace("-", "")

@property
def extra_state_attributes(self):
"""Return the state attributes."""
attrs: dict[str, Any] = {}
attrs["macAddr"] = self._system.wifi_macAddr
attrs["ssid"] = self._system.wifi_ssid
attrs["ip"] = self._system.wifi_ip
attrs["router"] = self._system.wifi_router
attrs["dns"] = self._system.wifi_dns
attrs["dns2"] = self._system.wifi_dns2
attrs["subnetMask"] = self._system.wifi_subnetMask
attrs["bitRate"] = self._system.wifi_bitRate
return attrs
@property
def name(self):
return self._myname

@property
def native_value(self):
return self._system.wifi_rssi

@property
def native_unit_of_measurement(self):
return SIGNAL_STRENGTH_DECIBELS_MILLIWATT

@property
def device_class(self):
return SensorDeviceClass.SIGNAL_STRENGTH

@property
def state_class(self):
return SensorStateClass.MEASUREMENT

@property
def device_info(self) -> DeviceInfo:
return {
"identifiers": {(LENNOX_DOMAIN, self._system.unique_id)},
}

@property
def entity_category(self):
return EntityCategory.DIAGNOSTIC
48 changes: 48 additions & 0 deletions tests/messages/wifi_interface_status.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"MessageId": 0,
"SenderID": "**redacted**",
"TargetID": "homeassistant",
"MessageType": "PropertyChange",
"Data": {
"interfaces": [
{
"publisher": {
"publisherName": "lcc"
},
"Info": {
"status": {
"macAddr": "60:a4:4c:6b:d2:4c",
"ssid": "wifi_home",
"ip": "10.0.0.10",
"router": "10.0.0.1",
"networkStatus": "enabled",
"channel": 0,
"dns": "8.8.8.8",
"dns2": "4.4.4.4",
"subnetMask": "255.255.0.0",
"bitRate": 72200000,
"speed": " 72.2 MBit per second",
"rssi": -68
},
"APDetails": {
"rssi": -68,
"security": "WPA-Personal",
"password": "**redacted**",
"ssid": "**redacted**",
"bssid": "60:a4:4c:6b:d2:4c"
},
"diagnostics": {
"ssid": "**redacted**",
"bssid": "60:a4:4c:6b:d2:4c",
"txByteCount": 75453148,
"rxByteCount": 0,
"ip4addr": "**redacted**",
"txPacketCount": 157356,
"rxPacketCount": 0
}
},
"id": 0
}
]
}
}
11 changes: 11 additions & 0 deletions tests/test_sensor_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
)
from custom_components.lennoxs30.sensor_ble import S40BleSensor
from custom_components.lennoxs30.sensor_iaq import S40IAQSensor
from custom_components.lennoxs30.sensor_wifi import WifiRSSISensor
from custom_components.lennoxs30.sensor_wt_env import WTEnvSensor

from tests.conftest import loadfile
Expand All @@ -46,10 +47,20 @@ async def test_async_setup_entry(hass, manager: Manager, caplog):
manager.create_sensors = False
manager.create_diagnostic_sensors = False
manager.create_alert_sensors = False
manager.api.isLANConnection = False
async_add_entities = Mock()
await async_setup_entry(hass, entry, async_add_entities)
assert async_add_entities.called == 0

manager.api.isLANConnection = True
async_add_entities = Mock()
await async_setup_entry(hass, entry, async_add_entities)
assert async_add_entities.called == 1
sensor_list = async_add_entities.call_args[0][0]
assert len(sensor_list) == 1
assert isinstance(sensor_list[0], WifiRSSISensor)
manager.api.isLANConnection = False

# Outdoor Temperature Sensor
system.outdoorTemperatureStatus = LENNOX_STATUS_GOOD
manager.create_inverter_power = False
Expand Down
133 changes: 133 additions & 0 deletions tests/test_sensor_wifi_rssi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# pylint: disable=too-many-lines
# pylint: disable=missing-module-docstring
# pylint: disable=missing-function-docstring
# pylint: disable=invalid-name
# pylint: disable=protected-access
# pylint: disable=line-too-long

import logging
from unittest.mock import patch
import pytest

from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT, SensorDeviceClass
from homeassistant.const import UnitOfTemperature,SIGNAL_STRENGTH_DECIBELS_MILLIWATT

from lennoxs30api.s30api_async import lennox_system

from custom_components.lennoxs30 import Manager
from custom_components.lennoxs30.const import LENNOX_DOMAIN
from custom_components.lennoxs30.sensor_wifi import WifiRSSISensor

from tests.conftest import conftest_base_entity_availability, loadfile


@pytest.mark.asyncio
async def test_wifi_rssi_sensor(hass, manager: Manager, caplog):
manager.is_metric = False
system: lennox_system = manager.api.system_list[0]
message = loadfile("wifi_interface_status.json", system.sysId)
system.processMessage(message)

s = WifiRSSISensor(hass, manager, system)

assert s.unique_id == (system.unique_id + "_WIFI_RSSI").replace("-", "")
assert s.available is True
assert s.should_poll is False
assert s.update() is True
assert s.name == system.name + "_wifi_rssi"
assert len(s.extra_state_attributes) == 8
attrs = s.extra_state_attributes
assert attrs["macAddr"] == "60:a4:4c:6b:d2:4c"
assert attrs["ssid"] == "wifi_home"
assert attrs["ip"] == "10.0.0.10"
assert attrs["router"] == "10.0.0.1"
assert attrs["dns"] == "8.8.8.8"
assert attrs["dns2"] == "4.4.4.4"
assert attrs["subnetMask"] == "255.255.0.0"
assert attrs["bitRate"] == 72200000
assert s.native_value == -68
assert s.native_unit_of_measurement == SIGNAL_STRENGTH_DECIBELS_MILLIWATT

assert s.device_class == SensorDeviceClass.SIGNAL_STRENGTH
assert s.state_class == STATE_CLASS_MEASUREMENT

identifiers = s.device_info["identifiers"]
for x in identifiers:
assert x[0] == LENNOX_DOMAIN
assert x[1] == system.unique_id



@pytest.mark.asyncio
async def test_wifi_rssi_sensor_subscription(hass, manager: Manager):
manager.is_metric = False
system: lennox_system = manager.api.system_list[0]
message = loadfile("wifi_interface_status.json", system.sysId)
system.processMessage(message)
s = WifiRSSISensor(hass, manager, system)
await s.async_added_to_hass()

with patch.object(s, "schedule_update_ha_state") as update_callback:
update_set = {"wifi_rssi": system.wifi_rssi + 1}
system.attr_updater(update_set, "wifi_rssi")
system.executeOnUpdateCallbacks()
assert update_callback.call_count == 1
assert s.native_value == -67

with patch.object(s, "schedule_update_ha_state") as update_callback:
update_set = {"wifi_macAddr": "newMac"}
system.attr_updater(update_set, "wifi_macAddr")
system.executeOnUpdateCallbacks()
assert update_callback.call_count == 1
assert s.extra_state_attributes["macAddr"] == "newMac"

with patch.object(s, "schedule_update_ha_state") as update_callback:
update_set = {"wifi_ssid": "newSSID"}
system.attr_updater(update_set, "wifi_ssid")
system.executeOnUpdateCallbacks()
assert update_callback.call_count == 1
assert s.extra_state_attributes["ssid"] == "newSSID"

with patch.object(s, "schedule_update_ha_state") as update_callback:
update_set = {"wifi_ip": "1.1.1.1"}
system.attr_updater(update_set, "wifi_ip")
system.executeOnUpdateCallbacks()
assert update_callback.call_count == 1
assert s.extra_state_attributes["ip"] == "1.1.1.1"

with patch.object(s, "schedule_update_ha_state") as update_callback:
update_set = {"wifi_router": "2.2.2.2"}
system.attr_updater(update_set, "wifi_router")
system.executeOnUpdateCallbacks()
assert update_callback.call_count == 1
assert s.extra_state_attributes["router"] == "2.2.2.2"

with patch.object(s, "schedule_update_ha_state") as update_callback:
update_set = {"wifi_dns": "3.3.3.3"}
system.attr_updater(update_set, "wifi_dns")
system.executeOnUpdateCallbacks()
assert update_callback.call_count == 1
assert s.extra_state_attributes["dns"] == "3.3.3.3"

with patch.object(s, "schedule_update_ha_state") as update_callback:
update_set = {"wifi_dns2": "5.5.5.5"}
system.attr_updater(update_set, "wifi_dns2")
system.executeOnUpdateCallbacks()
assert update_callback.call_count == 1
assert s.extra_state_attributes["dns2"] == "5.5.5.5"

with patch.object(s, "schedule_update_ha_state") as update_callback:
update_set = {"wifi_subnetMask": "255.255.255.0"}
system.attr_updater(update_set, "wifi_subnetMask")
system.executeOnUpdateCallbacks()
assert update_callback.call_count == 1
assert s.extra_state_attributes["subnetMask"] == "255.255.255.0"

with patch.object(s, "schedule_update_ha_state") as update_callback:
update_set = {"wifi_bitRate": 10 }
system.attr_updater(update_set, "wifi_bitRate")
system.executeOnUpdateCallbacks()
assert update_callback.call_count == 1
assert s.extra_state_attributes["bitRate"] == 10

conftest_base_entity_availability(manager, system, s)

0 comments on commit 3f9c9f0

Please sign in to comment.