diff --git a/homeassistant/components/wled/const.py b/homeassistant/components/wled/const.py index 4844f37a126..6c5cd9eaad4 100644 --- a/homeassistant/components/wled/const.py +++ b/homeassistant/components/wled/const.py @@ -25,3 +25,4 @@ ATTR_UDP_PORT = "udp_port" # Units of measurement CURRENT_MA = "mA" +SIGNAL_DBM = "dBm" diff --git a/homeassistant/components/wled/sensor.py b/homeassistant/components/wled/sensor.py index e0d92aecd56..b684bdc0977 100644 --- a/homeassistant/components/wled/sensor.py +++ b/homeassistant/components/wled/sensor.py @@ -4,13 +4,18 @@ import logging from typing import Any, Callable, Dict, List, Optional, Union from homeassistant.config_entries import ConfigEntry -from homeassistant.const import DATA_BYTES, DEVICE_CLASS_TIMESTAMP +from homeassistant.const import ( + DATA_BYTES, + DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_TIMESTAMP, + UNIT_PERCENTAGE, +) from homeassistant.helpers.entity import Entity from homeassistant.helpers.typing import HomeAssistantType from homeassistant.util.dt import utcnow from . import WLEDDataUpdateCoordinator, WLEDDeviceEntity -from .const import ATTR_LED_COUNT, ATTR_MAX_POWER, CURRENT_MA, DOMAIN +from .const import ATTR_LED_COUNT, ATTR_MAX_POWER, CURRENT_MA, DOMAIN, SIGNAL_DBM _LOGGER = logging.getLogger(__name__) @@ -27,6 +32,10 @@ async def async_setup_entry( WLEDEstimatedCurrentSensor(entry.entry_id, coordinator), WLEDUptimeSensor(entry.entry_id, coordinator), WLEDFreeHeapSensor(entry.entry_id, coordinator), + WLEDWifiBSSIDSensor(entry.entry_id, coordinator), + WLEDWifiChannelSensor(entry.entry_id, coordinator), + WLEDWifiRSSISensor(entry.entry_id, coordinator), + WLEDWifiSignalSensor(entry.entry_id, coordinator), ] async_add_entities(sensors, True) @@ -142,3 +151,90 @@ class WLEDFreeHeapSensor(WLEDSensor): def state(self) -> Union[None, str, int, float]: """Return the state of the sensor.""" return self.coordinator.data.info.free_heap + + +class WLEDWifiSignalSensor(WLEDSensor): + """Defines a WLED Wi-Fi signal sensor.""" + + def __init__(self, entry_id: str, coordinator: WLEDDataUpdateCoordinator) -> None: + """Initialize WLED Wi-Fi signal sensor.""" + super().__init__( + coordinator=coordinator, + enabled_default=False, + entry_id=entry_id, + icon="mdi:wifi", + key="wifi_signal", + name=f"{coordinator.data.info.name} Wi-Fi Signal", + unit_of_measurement=UNIT_PERCENTAGE, + ) + + @property + def state(self) -> Union[None, str, int, float]: + """Return the state of the sensor.""" + return self.coordinator.data.info.wifi.signal + + +class WLEDWifiRSSISensor(WLEDSensor): + """Defines a WLED Wi-Fi RSSI sensor.""" + + def __init__(self, entry_id: str, coordinator: WLEDDataUpdateCoordinator) -> None: + """Initialize WLED Wi-Fi RSSI sensor.""" + super().__init__( + coordinator=coordinator, + enabled_default=False, + entry_id=entry_id, + icon="mdi:wifi", + key="wifi_rssi", + name=f"{coordinator.data.info.name} Wi-Fi RSSI", + unit_of_measurement=SIGNAL_DBM, + ) + + @property + def state(self) -> Union[None, str, int, float]: + """Return the state of the sensor.""" + return self.coordinator.data.info.wifi.rssi + + @property + def device_class(self) -> Optional[str]: + """Return the class of this sensor.""" + return DEVICE_CLASS_SIGNAL_STRENGTH + + +class WLEDWifiChannelSensor(WLEDSensor): + """Defines a WLED Wi-Fi Channel sensor.""" + + def __init__(self, entry_id: str, coordinator: WLEDDataUpdateCoordinator) -> None: + """Initialize WLED Wi-Fi Channel sensor.""" + super().__init__( + coordinator=coordinator, + enabled_default=False, + entry_id=entry_id, + icon="mdi:wifi", + key="wifi_channel", + name=f"{coordinator.data.info.name} Wi-Fi Channel", + ) + + @property + def state(self) -> Union[None, str, int, float]: + """Return the state of the sensor.""" + return self.coordinator.data.info.wifi.channel + + +class WLEDWifiBSSIDSensor(WLEDSensor): + """Defines a WLED Wi-Fi BSSID sensor.""" + + def __init__(self, entry_id: str, coordinator: WLEDDataUpdateCoordinator) -> None: + """Initialize WLED Wi-Fi BSSID sensor.""" + super().__init__( + coordinator=coordinator, + enabled_default=False, + entry_id=entry_id, + icon="mdi:wifi", + key="wifi_bssid", + name=f"{coordinator.data.info.name} Wi-Fi BSSID", + ) + + @property + def state(self) -> Union[None, str, int, float]: + """Return the state of the sensor.""" + return self.coordinator.data.info.wifi.bssid diff --git a/tests/components/wled/test_sensor.py b/tests/components/wled/test_sensor.py index 894968f5db4..d77bd99b97c 100644 --- a/tests/components/wled/test_sensor.py +++ b/tests/components/wled/test_sensor.py @@ -2,6 +2,7 @@ from datetime import datetime from asynctest import patch +import pytest from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN from homeassistant.components.wled.const import ( @@ -9,8 +10,14 @@ from homeassistant.components.wled.const import ( ATTR_MAX_POWER, CURRENT_MA, DOMAIN, + SIGNAL_DBM, +) +from homeassistant.const import ( + ATTR_ICON, + ATTR_UNIT_OF_MEASUREMENT, + DATA_BYTES, + UNIT_PERCENTAGE, ) -from homeassistant.const import ATTR_ICON, ATTR_UNIT_OF_MEASUREMENT, DATA_BYTES from homeassistant.core import HomeAssistant from homeassistant.util import dt as dt_util @@ -43,6 +50,38 @@ async def test_sensors( disabled_by=None, ) + registry.async_get_or_create( + SENSOR_DOMAIN, + DOMAIN, + "aabbccddeeff_wifi_signal", + suggested_object_id="wled_rgb_light_wifi_signal", + disabled_by=None, + ) + + registry.async_get_or_create( + SENSOR_DOMAIN, + DOMAIN, + "aabbccddeeff_wifi_rssi", + suggested_object_id="wled_rgb_light_wifi_rssi", + disabled_by=None, + ) + + registry.async_get_or_create( + SENSOR_DOMAIN, + DOMAIN, + "aabbccddeeff_wifi_channel", + suggested_object_id="wled_rgb_light_wifi_channel", + disabled_by=None, + ) + + registry.async_get_or_create( + SENSOR_DOMAIN, + DOMAIN, + "aabbccddeeff_wifi_bssid", + suggested_object_id="wled_rgb_light_wifi_bssid", + disabled_by=None, + ) + # Setup test_time = datetime(2019, 11, 11, 9, 10, 32, tzinfo=dt_util.UTC) with patch("homeassistant.components.wled.sensor.utcnow", return_value=test_time): @@ -81,26 +120,70 @@ async def test_sensors( assert entry assert entry.unique_id == "aabbccddeeff_free_heap" + state = hass.states.get("sensor.wled_rgb_light_wifi_signal") + assert state + assert state.attributes.get(ATTR_ICON) == "mdi:wifi" + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UNIT_PERCENTAGE + assert state.state == "76" + entry = registry.async_get("sensor.wled_rgb_light_wifi_signal") + assert entry + assert entry.unique_id == "aabbccddeeff_wifi_signal" + + state = hass.states.get("sensor.wled_rgb_light_wifi_rssi") + assert state + assert state.attributes.get(ATTR_ICON) == "mdi:wifi" + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == SIGNAL_DBM + assert state.state == "-62" + + entry = registry.async_get("sensor.wled_rgb_light_wifi_rssi") + assert entry + assert entry.unique_id == "aabbccddeeff_wifi_rssi" + + state = hass.states.get("sensor.wled_rgb_light_wifi_channel") + assert state + assert state.attributes.get(ATTR_ICON) == "mdi:wifi" + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None + assert state.state == "11" + + entry = registry.async_get("sensor.wled_rgb_light_wifi_channel") + assert entry + assert entry.unique_id == "aabbccddeeff_wifi_channel" + + state = hass.states.get("sensor.wled_rgb_light_wifi_bssid") + assert state + assert state.attributes.get(ATTR_ICON) == "mdi:wifi" + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None + assert state.state == "AA:AA:AA:AA:AA:BB" + + entry = registry.async_get("sensor.wled_rgb_light_wifi_bssid") + assert entry + assert entry.unique_id == "aabbccddeeff_wifi_bssid" + + +@pytest.mark.parametrize( + "entity_id", + ( + "sensor.wled_rgb_light_uptime", + "sensor.wled_rgb_light_free_memory", + "sensor.wled_rgb_light_wi_fi_signal", + "sensor.wled_rgb_light_wi_fi_rssi", + "sensor.wled_rgb_light_wi_fi_channel", + "sensor.wled_rgb_light_wi_fi_bssid", + ), +) async def test_disabled_by_default_sensors( - hass: HomeAssistant, aioclient_mock: AiohttpClientMocker + hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, entity_id: str ) -> None: """Test the disabled by default WLED sensors.""" await init_integration(hass, aioclient_mock) registry = await hass.helpers.entity_registry.async_get_registry() + print(registry.entities) - state = hass.states.get("sensor.wled_rgb_light_uptime") + state = hass.states.get(entity_id) assert state is None - entry = registry.async_get("sensor.wled_rgb_light_uptime") - assert entry - assert entry.disabled - assert entry.disabled_by == "integration" - - state = hass.states.get("sensor.wled_rgb_light_free_memory") - assert state is None - - entry = registry.async_get("sensor.wled_rgb_light_free_memory") + entry = registry.async_get(entity_id) assert entry assert entry.disabled assert entry.disabled_by == "integration" diff --git a/tests/fixtures/wled/rgb.json b/tests/fixtures/wled/rgb.json index 70a54f06644..41d2c69d63c 100644 --- a/tests/fixtures/wled/rgb.json +++ b/tests/fixtures/wled/rgb.json @@ -62,6 +62,12 @@ "live": false, "fxcount": 81, "palcount": 50, + "wifi": { + "bssid": "AA:AA:AA:AA:AA:BB", + "rssi": -62, + "signal": 76, + "channel": 11 + }, "arch": "esp8266", "core": "2_4_2", "freeheap": 14600, diff --git a/tests/fixtures/wled/rgbw.json b/tests/fixtures/wled/rgbw.json index 0d51dfedd2d..ce7033c5888 100644 --- a/tests/fixtures/wled/rgbw.json +++ b/tests/fixtures/wled/rgbw.json @@ -48,6 +48,12 @@ "live": false, "fxcount": 83, "palcount": 50, + "wifi": { + "bssid": "AA:AA:AA:AA:AA:BB", + "rssi": -62, + "signal": 76, + "channel": 11 + }, "arch": "esp8266", "core": "2_5_2", "freeheap": 20136,