core/tests/components/unifi/test_sensor.py

1000 lines
32 KiB
Python
Raw Normal View History

"""UniFi Network sensor platform tests."""
from copy import deepcopy
from datetime import datetime, timedelta
from unittest.mock import patch
from aiounifi.models.device import DeviceState
from aiounifi.models.message import MessageKey
from freezegun.api import FrozenDateTimeFactory, freeze_time
import pytest
from homeassistant.components.sensor import (
ATTR_STATE_CLASS,
DOMAIN as SENSOR_DOMAIN,
SCAN_INTERVAL,
SensorDeviceClass,
SensorStateClass,
)
from homeassistant.components.unifi.const import (
CONF_ALLOW_BANDWIDTH_SENSORS,
Add UniFi Uptime sensor (#40058) * Added UniFi Uptime sensor Added the UniFi uptime data as a sensor. Untested. * Update sensor.py Updated code as a result of the tests. * Changed timestamp format and device class Converted state to iso timestamp and changed device class to DEVICE_CLASS_TIMESTAMP. * Updated unit of measurement to None * Added import * Update homeassistant/components/unifi/sensor.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Removed whitespace * Added the uptime sensors option to the config flow * All the unit tests should be there now * Whoops * Fixed translation * Properly formatted the code * Flake8 really has angel eyes * Black should also be satisfied now * Should have satisfied all static code analysis tools * Fixed add uptime sensor function * Fixed overintendation * Fixed unit tests * Made a spelling mistake during editing of unit tests * Test verifies if utc time is correct * Converted to iso format * Converted unit test to iso format * Unit test sensor json had the wrong uptime name * Added options_updated handler * Fixed remove sensors unit test * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update test_device_tracker.py Removed uptime from the devices * Fixed black formatting issue * I think the code coverage should be good now * Trying to add the sensors again * Using signals to hopefully trigger the controller to add them again * Forgot import * Sorted components * fixed isort comments * Removed CLASS and DEVICE_CLASS * Added TYPE again * Removed double underscores Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>
2020-09-18 17:33:37 +00:00
CONF_ALLOW_UPTIME_SENSORS,
CONF_DETECTION_TIME,
CONF_TRACK_CLIENTS,
CONF_TRACK_DEVICES,
DEFAULT_DETECTION_TIME,
DEVICE_STATES,
)
from homeassistant.config_entries import RELOAD_AFTER_UPDATE_DELAY
from homeassistant.const import ATTR_DEVICE_CLASS, STATE_UNAVAILABLE, EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_registry import RegistryEntryDisabler
import homeassistant.util.dt as dt_util
from .test_hub import setup_unifi_integration
from tests.common import async_fire_time_changed
from tests.test_util.aiohttp import AiohttpClientMocker
DEVICE_1 = {
"board_rev": 2,
"device_id": "mock-id",
"ip": "10.0.1.1",
"mac": "10:00:00:00:01:01",
"last_seen": 1562600145,
"model": "US16P150",
"name": "mock-name",
"port_overrides": [],
"port_table": [
{
"media": "GE",
"name": "Port 1",
"port_idx": 1,
"poe_class": "Class 4",
"poe_enable": True,
"poe_mode": "auto",
"poe_power": "2.56",
"poe_voltage": "53.40",
"portconf_id": "1a1",
"port_poe": True,
"up": True,
},
{
"media": "GE",
"name": "Port 2",
"port_idx": 2,
"poe_class": "Class 4",
"poe_enable": True,
"poe_mode": "auto",
"poe_power": "2.56",
"poe_voltage": "53.40",
"portconf_id": "1a2",
"port_poe": True,
"up": True,
},
{
"media": "GE",
"name": "Port 3",
"port_idx": 3,
"poe_class": "Unknown",
"poe_enable": False,
"poe_mode": "off",
"poe_power": "0.00",
"poe_voltage": "0.00",
"portconf_id": "1a3",
"port_poe": False,
"up": True,
},
{
"media": "GE",
"name": "Port 4",
"port_idx": 4,
"poe_class": "Unknown",
"poe_enable": False,
"poe_mode": "auto",
"poe_power": "0.00",
"poe_voltage": "0.00",
"portconf_id": "1a4",
"port_poe": True,
"up": True,
},
],
"state": 1,
"type": "usw",
"version": "4.0.42.10433",
}
WLAN = {
"_id": "012345678910111213141516",
"bc_filter_enabled": False,
"bc_filter_list": [],
"dtim_mode": "default",
"dtim_na": 1,
"dtim_ng": 1,
"enabled": True,
"group_rekey": 3600,
"mac_filter_enabled": False,
"mac_filter_list": [],
"mac_filter_policy": "allow",
"minrate_na_advertising_rates": False,
"minrate_na_beacon_rate_kbps": 6000,
"minrate_na_data_rate_kbps": 6000,
"minrate_na_enabled": False,
"minrate_na_mgmt_rate_kbps": 6000,
"minrate_ng_advertising_rates": False,
"minrate_ng_beacon_rate_kbps": 1000,
"minrate_ng_data_rate_kbps": 1000,
"minrate_ng_enabled": False,
"minrate_ng_mgmt_rate_kbps": 1000,
"name": "SSID 1",
"no2ghz_oui": False,
"schedule": [],
"security": "wpapsk",
"site_id": "5a32aa4ee4b0412345678910",
"usergroup_id": "012345678910111213141518",
"wep_idx": 1,
"wlangroup_id": "012345678910111213141519",
"wpa_enc": "ccmp",
"wpa_mode": "wpa2",
"x_iapp_key": "01234567891011121314151617181920",
"x_passphrase": "password",
}
PDU_DEVICE_1 = {
"_id": "123456654321abcdef012345",
"required_version": "5.28.0",
"port_table": [],
"license_state": "registered",
"lcm_brightness_override": False,
"type": "usw",
"board_rev": 4,
"hw_caps": 136,
"reboot_duration": 70,
"snmp_contact": "",
"config_network": {"type": "dhcp", "bonding_enabled": False},
"outlet_table": [
{
"index": 1,
"relay_state": True,
"cycle_enabled": False,
"name": "USB Outlet 1",
"outlet_caps": 1,
},
{
"index": 2,
"relay_state": True,
"cycle_enabled": False,
"name": "Outlet 2",
"outlet_caps": 3,
"outlet_voltage": "119.644",
"outlet_current": "0.935",
"outlet_power": "73.827",
"outlet_power_factor": "0.659",
},
],
"model": "USPPDUP",
"manufacturer_id": 4,
"ip": "192.168.1.76",
"fw2_caps": 0,
"jumboframe_enabled": False,
"version": "6.5.59.14777",
"unsupported_reason": 0,
"adoption_completed": True,
"outlet_enabled": True,
"stp_version": "rstp",
"name": "Dummy USP-PDU-Pro",
"fw_caps": 1732968229,
"lcm_brightness": 80,
"internet": True,
"mgmt_network_id": "123456654321abcdef012347",
"gateway_mac": "01:02:03:04:05:06",
"stp_priority": "32768",
"lcm_night_mode_begins": "22:00",
"two_phase_adopt": False,
"connected_at": 1690626493,
"inform_ip": "192.168.1.1",
"cfgversion": "ba8f30a5a17aad64",
"mac": "01:02:03:04:05:ff",
"provisioned_at": 1690989511,
"inform_url": "http://192.168.1.1:8080/inform",
"upgrade_duration": 100,
"ethernet_table": [{"num_port": 1, "name": "eth0", "mac": "01:02:03:04:05:a1"}],
"flowctrl_enabled": False,
"unsupported": False,
"ble_caps": 0,
"sys_error_caps": 0,
"dot1x_portctrl_enabled": False,
"last_uplink": {},
"disconnected_at": 1690626452,
"architecture": "mips",
"x_aes_gcm": True,
"has_fan": False,
"outlet_overrides": [
{
"cycle_enabled": False,
"name": "USB Outlet 1",
"relay_state": True,
"index": 1,
},
{"cycle_enabled": False, "name": "Outlet 2", "relay_state": True, "index": 2},
],
"model_incompatible": False,
"satisfaction": 100,
"model_in_eol": False,
"anomalies": -1,
"has_temperature": False,
"switch_caps": {},
"adopted_by_client": "web",
"snmp_location": "",
"model_in_lts": False,
"kernel_version": "4.14.115",
"serial": "abc123",
"power_source_ctrl_enabled": False,
"lcm_night_mode_ends": "08:00",
"adopted": True,
"hash_id": "abcdef123456",
"device_id": "mock-pdu",
"uplink": {},
"state": 1,
"start_disconnected_millis": 1690626383386,
"credential_caps": 0,
"default": False,
"discovered_via": "l2",
"adopt_ip": "10.0.10.4",
"adopt_url": "http://192.168.1.1:8080/inform",
"last_seen": 1691518814,
"min_inform_interval_seconds": 10,
"upgradable": False,
"adoptable_when_upgraded": False,
"rollupgrade": False,
"known_cfgversion": "abcfde03929",
"uptime": 1193042,
"_uptime": 1193042,
"locating": False,
"start_connected_millis": 1690626493324,
"prev_non_busy_state": 5,
"next_interval": 47,
"sys_stats": {},
"system-stats": {"cpu": "1.4", "mem": "28.9", "uptime": "1193042"},
"ssh_session_table": [],
"lldp_table": [],
"displayable_version": "6.5.59",
"connection_network_id": "123456654321abcdef012349",
"connection_network_name": "Default",
"startup_timestamp": 1690325774,
"is_access_point": False,
"safe_for_autoupgrade": True,
"overheating": False,
"power_source": "0",
"total_max_power": 0,
"outlet_ac_power_budget": "1875.000",
"outlet_ac_power_consumption": "201.683",
"downlink_table": [],
"uplink_depth": 1,
"downlink_lldp_macs": [],
"dhcp_server_table": [],
"connect_request_ip": "10.0.10.4",
"connect_request_port": "57951",
"ipv4_lease_expiration_timestamp_seconds": 1691576686,
"stat": {},
"tx_bytes": 1426780,
"rx_bytes": 1435064,
"bytes": 2861844,
"num_sta": 0,
"user-num_sta": 0,
"guest-num_sta": 0,
"x_has_ssh_hostkey": True,
}
PDU_OUTLETS_UPDATE_DATA = [
{
"index": 1,
"relay_state": True,
"cycle_enabled": False,
"name": "USB Outlet 1",
"outlet_caps": 1,
},
{
"index": 2,
"relay_state": True,
"cycle_enabled": False,
"name": "Outlet 2",
"outlet_caps": 3,
"outlet_voltage": "119.644",
"outlet_current": "0.935",
"outlet_power": "123.45",
"outlet_power_factor": "0.659",
},
]
async def test_no_clients(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test the update_clients function when no clients are found."""
2021-02-05 15:31:47 +00:00
await setup_unifi_integration(
2020-08-27 11:56:20 +00:00
hass,
2021-02-05 15:31:47 +00:00
aioclient_mock,
Add UniFi Uptime sensor (#40058) * Added UniFi Uptime sensor Added the UniFi uptime data as a sensor. Untested. * Update sensor.py Updated code as a result of the tests. * Changed timestamp format and device class Converted state to iso timestamp and changed device class to DEVICE_CLASS_TIMESTAMP. * Updated unit of measurement to None * Added import * Update homeassistant/components/unifi/sensor.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Removed whitespace * Added the uptime sensors option to the config flow * All the unit tests should be there now * Whoops * Fixed translation * Properly formatted the code * Flake8 really has angel eyes * Black should also be satisfied now * Should have satisfied all static code analysis tools * Fixed add uptime sensor function * Fixed overintendation * Fixed unit tests * Made a spelling mistake during editing of unit tests * Test verifies if utc time is correct * Converted to iso format * Converted unit test to iso format * Unit test sensor json had the wrong uptime name * Added options_updated handler * Fixed remove sensors unit test * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update test_device_tracker.py Removed uptime from the devices * Fixed black formatting issue * I think the code coverage should be good now * Trying to add the sensors again * Using signals to hopefully trigger the controller to add them again * Forgot import * Sorted components * fixed isort comments * Removed CLASS and DEVICE_CLASS * Added TYPE again * Removed double underscores Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>
2020-09-18 17:33:37 +00:00
options={
CONF_ALLOW_BANDWIDTH_SENSORS: True,
CONF_ALLOW_UPTIME_SENSORS: True,
},
)
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 0
async def test_bandwidth_sensors(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, mock_unifi_websocket
) -> None:
"""Verify that bandwidth sensors are working as expected."""
wired_client = {
"hostname": "Wired client",
"is_wired": True,
"mac": "00:00:00:00:00:01",
"oui": "Producer",
"wired-rx_bytes-r": 1234000000,
"wired-tx_bytes-r": 5678000000,
}
wireless_client = {
"is_wired": False,
"mac": "00:00:00:00:00:02",
"name": "Wireless client",
"oui": "Producer",
"rx_bytes-r": 2345000000.0,
"tx_bytes-r": 6789000000.0,
}
options = {
CONF_ALLOW_BANDWIDTH_SENSORS: True,
CONF_ALLOW_UPTIME_SENSORS: False,
CONF_TRACK_CLIENTS: False,
CONF_TRACK_DEVICES: False,
}
2021-02-05 15:31:47 +00:00
config_entry = await setup_unifi_integration(
hass,
2021-02-05 15:31:47 +00:00
aioclient_mock,
options=options,
clients_response=[wired_client, wireless_client],
)
assert len(hass.states.async_all()) == 5
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 4
# Verify sensor attributes and state
wrx_sensor = hass.states.get("sensor.wired_client_rx")
assert wrx_sensor.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.DATA_RATE
assert wrx_sensor.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.MEASUREMENT
assert wrx_sensor.state == "1234.0"
wtx_sensor = hass.states.get("sensor.wired_client_tx")
assert wtx_sensor.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.DATA_RATE
assert wtx_sensor.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.MEASUREMENT
assert wtx_sensor.state == "5678.0"
wlrx_sensor = hass.states.get("sensor.wireless_client_rx")
assert wlrx_sensor.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.DATA_RATE
assert wlrx_sensor.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.MEASUREMENT
assert wlrx_sensor.state == "2345.0"
wltx_sensor = hass.states.get("sensor.wireless_client_tx")
assert wltx_sensor.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.DATA_RATE
assert wltx_sensor.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.MEASUREMENT
assert wltx_sensor.state == "6789.0"
# Verify state update
Add UniFi Uptime sensor (#40058) * Added UniFi Uptime sensor Added the UniFi uptime data as a sensor. Untested. * Update sensor.py Updated code as a result of the tests. * Changed timestamp format and device class Converted state to iso timestamp and changed device class to DEVICE_CLASS_TIMESTAMP. * Updated unit of measurement to None * Added import * Update homeassistant/components/unifi/sensor.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Removed whitespace * Added the uptime sensors option to the config flow * All the unit tests should be there now * Whoops * Fixed translation * Properly formatted the code * Flake8 really has angel eyes * Black should also be satisfied now * Should have satisfied all static code analysis tools * Fixed add uptime sensor function * Fixed overintendation * Fixed unit tests * Made a spelling mistake during editing of unit tests * Test verifies if utc time is correct * Converted to iso format * Converted unit test to iso format * Unit test sensor json had the wrong uptime name * Added options_updated handler * Fixed remove sensors unit test * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update test_device_tracker.py Removed uptime from the devices * Fixed black formatting issue * I think the code coverage should be good now * Trying to add the sensors again * Using signals to hopefully trigger the controller to add them again * Forgot import * Sorted components * fixed isort comments * Removed CLASS and DEVICE_CLASS * Added TYPE again * Removed double underscores Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>
2020-09-18 17:33:37 +00:00
wireless_client["rx_bytes-r"] = 3456000000
wireless_client["tx_bytes-r"] = 7891000000
mock_unifi_websocket(message=MessageKey.CLIENT, data=wireless_client)
await hass.async_block_till_done()
assert hass.states.get("sensor.wireless_client_rx").state == "3456.0"
assert hass.states.get("sensor.wireless_client_tx").state == "7891.0"
# Verify reset sensor after heartbeat expires
new_time = dt_util.utcnow()
wireless_client["last_seen"] = dt_util.as_timestamp(new_time)
mock_unifi_websocket(message=MessageKey.CLIENT, data=wireless_client)
await hass.async_block_till_done()
with freeze_time(new_time):
async_fire_time_changed(hass, new_time)
await hass.async_block_till_done()
assert hass.states.get("sensor.wireless_client_rx").state == "3456.0"
assert hass.states.get("sensor.wireless_client_tx").state == "7891.0"
new_time += timedelta(
seconds=(
config_entry.options.get(CONF_DETECTION_TIME, DEFAULT_DETECTION_TIME) + 1
)
)
with freeze_time(new_time):
async_fire_time_changed(hass, new_time)
await hass.async_block_till_done()
assert hass.states.get("sensor.wireless_client_rx").state == STATE_UNAVAILABLE
assert hass.states.get("sensor.wireless_client_tx").state == STATE_UNAVAILABLE
# Disable option
options[CONF_ALLOW_BANDWIDTH_SENSORS] = False
hass.config_entries.async_update_entry(config_entry, options=options.copy())
await hass.async_block_till_done()
Add UniFi Uptime sensor (#40058) * Added UniFi Uptime sensor Added the UniFi uptime data as a sensor. Untested. * Update sensor.py Updated code as a result of the tests. * Changed timestamp format and device class Converted state to iso timestamp and changed device class to DEVICE_CLASS_TIMESTAMP. * Updated unit of measurement to None * Added import * Update homeassistant/components/unifi/sensor.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Removed whitespace * Added the uptime sensors option to the config flow * All the unit tests should be there now * Whoops * Fixed translation * Properly formatted the code * Flake8 really has angel eyes * Black should also be satisfied now * Should have satisfied all static code analysis tools * Fixed add uptime sensor function * Fixed overintendation * Fixed unit tests * Made a spelling mistake during editing of unit tests * Test verifies if utc time is correct * Converted to iso format * Converted unit test to iso format * Unit test sensor json had the wrong uptime name * Added options_updated handler * Fixed remove sensors unit test * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update test_device_tracker.py Removed uptime from the devices * Fixed black formatting issue * I think the code coverage should be good now * Trying to add the sensors again * Using signals to hopefully trigger the controller to add them again * Forgot import * Sorted components * fixed isort comments * Removed CLASS and DEVICE_CLASS * Added TYPE again * Removed double underscores Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>
2020-09-18 17:33:37 +00:00
assert len(hass.states.async_all()) == 1
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 0
assert hass.states.get("sensor.wireless_client_rx") is None
assert hass.states.get("sensor.wireless_client_tx") is None
assert hass.states.get("sensor.wired_client_rx") is None
assert hass.states.get("sensor.wired_client_tx") is None
# Enable option
options[CONF_ALLOW_BANDWIDTH_SENSORS] = True
hass.config_entries.async_update_entry(config_entry, options=options.copy())
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 5
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 4
assert hass.states.get("sensor.wireless_client_rx")
assert hass.states.get("sensor.wireless_client_tx")
assert hass.states.get("sensor.wired_client_rx")
assert hass.states.get("sensor.wired_client_tx")
@pytest.mark.parametrize(
("initial_uptime", "event_uptime", "new_uptime"),
[
# Uptime listed in epoch time should never change
(1609462800, 1609462800, 1612141200),
# Uptime counted in seconds increases with every event
(60, 64, 60),
],
)
async def test_uptime_sensors(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
aioclient_mock: AiohttpClientMocker,
freezer: FrozenDateTimeFactory,
mock_unifi_websocket,
entity_registry_enabled_by_default: None,
initial_uptime,
event_uptime,
new_uptime,
) -> None:
"""Verify that uptime sensors are working as expected."""
uptime_client = {
"mac": "00:00:00:00:00:01",
"name": "client1",
"oui": "Producer",
"uptime": initial_uptime,
}
options = {
CONF_ALLOW_BANDWIDTH_SENSORS: False,
CONF_ALLOW_UPTIME_SENSORS: True,
CONF_TRACK_CLIENTS: False,
CONF_TRACK_DEVICES: False,
}
now = datetime(2021, 1, 1, 1, 1, 0, tzinfo=dt_util.UTC)
freezer.move_to(now)
config_entry = await setup_unifi_integration(
hass,
aioclient_mock,
options=options,
clients_response=[uptime_client],
)
assert len(hass.states.async_all()) == 2
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 1
assert hass.states.get("sensor.client1_uptime").state == "2021-01-01T01:00:00+00:00"
assert (
entity_registry.async_get("sensor.client1_uptime").entity_category
2021-12-17 10:12:43 +00:00
is EntityCategory.DIAGNOSTIC
)
# Verify normal new event doesn't change uptime
# 4 seconds has passed
uptime_client["uptime"] = event_uptime
now = datetime(2021, 1, 1, 1, 1, 4, tzinfo=dt_util.UTC)
with patch("homeassistant.util.dt.now", return_value=now):
mock_unifi_websocket(message=MessageKey.CLIENT, data=uptime_client)
await hass.async_block_till_done()
assert hass.states.get("sensor.client1_uptime").state == "2021-01-01T01:00:00+00:00"
# Verify new event change uptime
# 1 month has passed
uptime_client["uptime"] = new_uptime
now = datetime(2021, 2, 1, 1, 1, 0, tzinfo=dt_util.UTC)
with patch("homeassistant.util.dt.now", return_value=now):
mock_unifi_websocket(message=MessageKey.CLIENT, data=uptime_client)
await hass.async_block_till_done()
assert hass.states.get("sensor.client1_uptime").state == "2021-02-01T01:00:00+00:00"
# Disable option
options[CONF_ALLOW_UPTIME_SENSORS] = False
hass.config_entries.async_update_entry(config_entry, options=options.copy())
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 1
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 0
assert hass.states.get("sensor.client1_uptime") is None
# Enable option
options[CONF_ALLOW_UPTIME_SENSORS] = True
with patch("homeassistant.util.dt.now", return_value=now):
hass.config_entries.async_update_entry(config_entry, options=options.copy())
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 2
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 1
assert hass.states.get("sensor.client1_uptime")
async def test_remove_sensors(
hass: HomeAssistant,
aioclient_mock: AiohttpClientMocker,
mock_unifi_websocket,
entity_registry_enabled_by_default: None,
) -> None:
"""Verify removing of clients work as expected."""
wired_client = {
"hostname": "Wired client",
"is_wired": True,
"mac": "00:00:00:00:00:01",
"oui": "Producer",
"wired-rx_bytes": 1234000000,
"wired-tx_bytes": 5678000000,
"uptime": 1600094505,
}
wireless_client = {
"is_wired": False,
"mac": "00:00:00:00:00:02",
"name": "Wireless client",
"oui": "Producer",
"rx_bytes": 2345000000,
"tx_bytes": 6789000000,
"uptime": 60,
}
await setup_unifi_integration(
2020-08-27 11:56:20 +00:00
hass,
2021-02-05 15:31:47 +00:00
aioclient_mock,
Add UniFi Uptime sensor (#40058) * Added UniFi Uptime sensor Added the UniFi uptime data as a sensor. Untested. * Update sensor.py Updated code as a result of the tests. * Changed timestamp format and device class Converted state to iso timestamp and changed device class to DEVICE_CLASS_TIMESTAMP. * Updated unit of measurement to None * Added import * Update homeassistant/components/unifi/sensor.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Removed whitespace * Added the uptime sensors option to the config flow * All the unit tests should be there now * Whoops * Fixed translation * Properly formatted the code * Flake8 really has angel eyes * Black should also be satisfied now * Should have satisfied all static code analysis tools * Fixed add uptime sensor function * Fixed overintendation * Fixed unit tests * Made a spelling mistake during editing of unit tests * Test verifies if utc time is correct * Converted to iso format * Converted unit test to iso format * Unit test sensor json had the wrong uptime name * Added options_updated handler * Fixed remove sensors unit test * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update test_device_tracker.py Removed uptime from the devices * Fixed black formatting issue * I think the code coverage should be good now * Trying to add the sensors again * Using signals to hopefully trigger the controller to add them again * Forgot import * Sorted components * fixed isort comments * Removed CLASS and DEVICE_CLASS * Added TYPE again * Removed double underscores Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>
2020-09-18 17:33:37 +00:00
options={
CONF_ALLOW_BANDWIDTH_SENSORS: True,
CONF_ALLOW_UPTIME_SENSORS: True,
},
clients_response=[wired_client, wireless_client],
)
Add UniFi Uptime sensor (#40058) * Added UniFi Uptime sensor Added the UniFi uptime data as a sensor. Untested. * Update sensor.py Updated code as a result of the tests. * Changed timestamp format and device class Converted state to iso timestamp and changed device class to DEVICE_CLASS_TIMESTAMP. * Updated unit of measurement to None * Added import * Update homeassistant/components/unifi/sensor.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Removed whitespace * Added the uptime sensors option to the config flow * All the unit tests should be there now * Whoops * Fixed translation * Properly formatted the code * Flake8 really has angel eyes * Black should also be satisfied now * Should have satisfied all static code analysis tools * Fixed add uptime sensor function * Fixed overintendation * Fixed unit tests * Made a spelling mistake during editing of unit tests * Test verifies if utc time is correct * Converted to iso format * Converted unit test to iso format * Unit test sensor json had the wrong uptime name * Added options_updated handler * Fixed remove sensors unit test * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update test_device_tracker.py Removed uptime from the devices * Fixed black formatting issue * I think the code coverage should be good now * Trying to add the sensors again * Using signals to hopefully trigger the controller to add them again * Forgot import * Sorted components * fixed isort comments * Removed CLASS and DEVICE_CLASS * Added TYPE again * Removed double underscores Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>
2020-09-18 17:33:37 +00:00
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 6
assert hass.states.get("sensor.wired_client_rx")
assert hass.states.get("sensor.wired_client_tx")
assert hass.states.get("sensor.wired_client_uptime")
assert hass.states.get("sensor.wireless_client_rx")
assert hass.states.get("sensor.wireless_client_tx")
assert hass.states.get("sensor.wireless_client_uptime")
# Remove wired client
Add UniFi Uptime sensor (#40058) * Added UniFi Uptime sensor Added the UniFi uptime data as a sensor. Untested. * Update sensor.py Updated code as a result of the tests. * Changed timestamp format and device class Converted state to iso timestamp and changed device class to DEVICE_CLASS_TIMESTAMP. * Updated unit of measurement to None * Added import * Update homeassistant/components/unifi/sensor.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Removed whitespace * Added the uptime sensors option to the config flow * All the unit tests should be there now * Whoops * Fixed translation * Properly formatted the code * Flake8 really has angel eyes * Black should also be satisfied now * Should have satisfied all static code analysis tools * Fixed add uptime sensor function * Fixed overintendation * Fixed unit tests * Made a spelling mistake during editing of unit tests * Test verifies if utc time is correct * Converted to iso format * Converted unit test to iso format * Unit test sensor json had the wrong uptime name * Added options_updated handler * Fixed remove sensors unit test * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update test_device_tracker.py Removed uptime from the devices * Fixed black formatting issue * I think the code coverage should be good now * Trying to add the sensors again * Using signals to hopefully trigger the controller to add them again * Forgot import * Sorted components * fixed isort comments * Removed CLASS and DEVICE_CLASS * Added TYPE again * Removed double underscores Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>
2020-09-18 17:33:37 +00:00
mock_unifi_websocket(message=MessageKey.CLIENT_REMOVED, data=wired_client)
await hass.async_block_till_done()
Add UniFi Uptime sensor (#40058) * Added UniFi Uptime sensor Added the UniFi uptime data as a sensor. Untested. * Update sensor.py Updated code as a result of the tests. * Changed timestamp format and device class Converted state to iso timestamp and changed device class to DEVICE_CLASS_TIMESTAMP. * Updated unit of measurement to None * Added import * Update homeassistant/components/unifi/sensor.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Removed whitespace * Added the uptime sensors option to the config flow * All the unit tests should be there now * Whoops * Fixed translation * Properly formatted the code * Flake8 really has angel eyes * Black should also be satisfied now * Should have satisfied all static code analysis tools * Fixed add uptime sensor function * Fixed overintendation * Fixed unit tests * Made a spelling mistake during editing of unit tests * Test verifies if utc time is correct * Converted to iso format * Converted unit test to iso format * Unit test sensor json had the wrong uptime name * Added options_updated handler * Fixed remove sensors unit test * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update homeassistant/components/unifi/sensor.py Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com> * Update test_device_tracker.py Removed uptime from the devices * Fixed black formatting issue * I think the code coverage should be good now * Trying to add the sensors again * Using signals to hopefully trigger the controller to add them again * Forgot import * Sorted components * fixed isort comments * Removed CLASS and DEVICE_CLASS * Added TYPE again * Removed double underscores Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>
2020-09-18 17:33:37 +00:00
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 3
assert hass.states.get("sensor.wired_client_rx") is None
assert hass.states.get("sensor.wired_client_tx") is None
assert hass.states.get("sensor.wired_client_uptime") is None
assert hass.states.get("sensor.wireless_client_rx")
assert hass.states.get("sensor.wireless_client_tx")
assert hass.states.get("sensor.wireless_client_uptime")
async def test_poe_port_switches(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
aioclient_mock: AiohttpClientMocker,
mock_unifi_websocket,
websocket_mock,
) -> None:
"""Test the update_items function with some clients."""
await setup_unifi_integration(hass, aioclient_mock, devices_response=[DEVICE_1])
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 2
ent_reg_entry = entity_registry.async_get("sensor.mock_name_port_1_poe_power")
assert ent_reg_entry.disabled_by == RegistryEntryDisabler.INTEGRATION
assert ent_reg_entry.entity_category is EntityCategory.DIAGNOSTIC
# Enable entity
entity_registry.async_update_entity(
entity_id="sensor.mock_name_port_1_poe_power", disabled_by=None
)
await hass.async_block_till_done()
async_fire_time_changed(
hass,
dt_util.utcnow() + timedelta(seconds=RELOAD_AFTER_UPDATE_DELAY + 1),
)
await hass.async_block_till_done()
# Validate state object
poe_sensor = hass.states.get("sensor.mock_name_port_1_poe_power")
assert poe_sensor.state == "2.56"
assert poe_sensor.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.POWER
# Update state object
device_1 = deepcopy(DEVICE_1)
device_1["port_table"][0]["poe_power"] = "5.12"
mock_unifi_websocket(message=MessageKey.DEVICE, data=device_1)
await hass.async_block_till_done()
assert hass.states.get("sensor.mock_name_port_1_poe_power").state == "5.12"
# PoE is disabled
device_1 = deepcopy(DEVICE_1)
device_1["port_table"][0]["poe_mode"] = "off"
mock_unifi_websocket(message=MessageKey.DEVICE, data=device_1)
await hass.async_block_till_done()
assert hass.states.get("sensor.mock_name_port_1_poe_power").state == "0"
# Availability signalling
# Controller disconnects
await websocket_mock.disconnect()
assert (
hass.states.get("sensor.mock_name_port_1_poe_power").state == STATE_UNAVAILABLE
)
# Controller reconnects
await websocket_mock.reconnect()
assert (
hass.states.get("sensor.mock_name_port_1_poe_power").state != STATE_UNAVAILABLE
)
# Device gets disabled
device_1["disabled"] = True
mock_unifi_websocket(message=MessageKey.DEVICE, data=device_1)
await hass.async_block_till_done()
assert (
hass.states.get("sensor.mock_name_port_1_poe_power").state == STATE_UNAVAILABLE
)
# Device gets re-enabled
device_1["disabled"] = False
mock_unifi_websocket(message=MessageKey.DEVICE, data=device_1)
await hass.async_block_till_done()
assert hass.states.get("sensor.mock_name_port_1_poe_power")
async def test_wlan_client_sensors(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
aioclient_mock: AiohttpClientMocker,
mock_unifi_websocket,
websocket_mock,
) -> None:
"""Verify that WLAN client sensors are working as expected."""
wireless_client_1 = {
"essid": "SSID 1",
"is_wired": False,
"last_seen": dt_util.as_timestamp(dt_util.utcnow()),
"mac": "00:00:00:00:00:01",
"name": "Wireless client",
"oui": "Producer",
"rx_bytes-r": 2345000000,
"tx_bytes-r": 6789000000,
}
wireless_client_2 = {
"essid": "SSID 2",
"is_wired": False,
"last_seen": dt_util.as_timestamp(dt_util.utcnow()),
"mac": "00:00:00:00:00:02",
"name": "Wireless client2",
"oui": "Producer2",
"rx_bytes-r": 2345000000,
"tx_bytes-r": 6789000000,
}
await setup_unifi_integration(
hass,
aioclient_mock,
clients_response=[wireless_client_1, wireless_client_2],
wlans_response=[WLAN],
)
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 1
ent_reg_entry = entity_registry.async_get("sensor.ssid_1")
assert ent_reg_entry.unique_id == "wlan_clients-012345678910111213141516"
assert ent_reg_entry.entity_category is EntityCategory.DIAGNOSTIC
# Validate state object
ssid_1 = hass.states.get("sensor.ssid_1")
assert ssid_1 is not None
assert ssid_1.state == "1"
# Verify state update - increasing number
wireless_client_1["essid"] = "SSID 1"
wireless_client_2["essid"] = "SSID 1"
mock_unifi_websocket(message=MessageKey.CLIENT, data=wireless_client_1)
mock_unifi_websocket(message=MessageKey.CLIENT, data=wireless_client_2)
await hass.async_block_till_done()
ssid_1 = hass.states.get("sensor.ssid_1")
assert ssid_1.state == "1"
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
await hass.async_block_till_done()
ssid_1 = hass.states.get("sensor.ssid_1")
assert ssid_1.state == "2"
# Verify state update - decreasing number
wireless_client_1["essid"] = "SSID"
mock_unifi_websocket(message=MessageKey.CLIENT, data=wireless_client_1)
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
await hass.async_block_till_done()
ssid_1 = hass.states.get("sensor.ssid_1")
assert ssid_1.state == "1"
# Verify state update - decreasing number
wireless_client_2["last_seen"] = 0
mock_unifi_websocket(message=MessageKey.CLIENT, data=wireless_client_2)
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
await hass.async_block_till_done()
ssid_1 = hass.states.get("sensor.ssid_1")
assert ssid_1.state == "0"
# Availability signalling
# Controller disconnects
await websocket_mock.disconnect()
assert hass.states.get("sensor.ssid_1").state == STATE_UNAVAILABLE
# Controller reconnects
await websocket_mock.reconnect()
assert hass.states.get("sensor.ssid_1").state == "0"
# WLAN gets disabled
wlan_1 = deepcopy(WLAN)
wlan_1["enabled"] = False
mock_unifi_websocket(message=MessageKey.WLAN_CONF_UPDATED, data=wlan_1)
await hass.async_block_till_done()
assert hass.states.get("sensor.ssid_1").state == STATE_UNAVAILABLE
# WLAN gets re-enabled
wlan_1["enabled"] = True
mock_unifi_websocket(message=MessageKey.WLAN_CONF_UPDATED, data=wlan_1)
await hass.async_block_till_done()
assert hass.states.get("sensor.ssid_1").state == "0"
@pytest.mark.parametrize(
(
"entity_id",
"expected_unique_id",
"expected_value",
"changed_data",
"expected_update_value",
),
[
(
"dummy_usp_pdu_pro_outlet_2_outlet_power",
"outlet_power-01:02:03:04:05:ff_2",
"73.827",
{"outlet_table": PDU_OUTLETS_UPDATE_DATA},
"123.45",
),
(
"dummy_usp_pdu_pro_ac_power_budget",
"ac_power_budget-01:02:03:04:05:ff",
"1875.000",
None,
None,
),
(
"dummy_usp_pdu_pro_ac_power_consumption",
"ac_power_conumption-01:02:03:04:05:ff",
"201.683",
{"outlet_ac_power_consumption": "456.78"},
"456.78",
),
],
)
async def test_outlet_power_readings(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
aioclient_mock: AiohttpClientMocker,
mock_unifi_websocket,
entity_id: str,
expected_unique_id: str,
expected_value: any,
changed_data: dict | None,
expected_update_value: any,
) -> None:
"""Test the outlet power reporting on PDU devices."""
await setup_unifi_integration(hass, aioclient_mock, devices_response=[PDU_DEVICE_1])
assert len(hass.states.async_all()) == 11
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 5
ent_reg_entry = entity_registry.async_get(f"sensor.{entity_id}")
assert ent_reg_entry.unique_id == expected_unique_id
assert ent_reg_entry.entity_category is EntityCategory.DIAGNOSTIC
sensor_data = hass.states.get(f"sensor.{entity_id}")
assert sensor_data.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.POWER
assert sensor_data.state == expected_value
if changed_data is not None:
updated_device_data = deepcopy(PDU_DEVICE_1)
updated_device_data.update(changed_data)
mock_unifi_websocket(message=MessageKey.DEVICE, data=updated_device_data)
await hass.async_block_till_done()
sensor_data = hass.states.get(f"sensor.{entity_id}")
assert sensor_data.state == expected_update_value
async def test_device_uptime(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
aioclient_mock: AiohttpClientMocker,
mock_unifi_websocket,
) -> None:
"""Verify that uptime sensors are working as expected."""
device = {
"board_rev": 3,
"device_id": "mock-id",
"has_fan": True,
"fan_level": 0,
"ip": "10.0.1.1",
"last_seen": 1562600145,
"mac": "00:00:00:00:01:01",
"model": "US16P150",
"name": "Device",
"next_interval": 20,
"overheating": True,
"state": 1,
"type": "usw",
"upgradable": True,
"uptime": 60,
"version": "4.0.42.10433",
}
now = datetime(2021, 1, 1, 1, 1, 0, tzinfo=dt_util.UTC)
with patch("homeassistant.util.dt.now", return_value=now):
await setup_unifi_integration(hass, aioclient_mock, devices_response=[device])
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 2
assert hass.states.get("sensor.device_uptime").state == "2021-01-01T01:00:00+00:00"
assert (
entity_registry.async_get("sensor.device_uptime").entity_category
is EntityCategory.DIAGNOSTIC
)
# Verify normal new event doesn't change uptime
# 4 seconds has passed
device["uptime"] = 64
now = datetime(2021, 1, 1, 1, 1, 4, tzinfo=dt_util.UTC)
with patch("homeassistant.util.dt.now", return_value=now):
mock_unifi_websocket(message=MessageKey.DEVICE, data=device)
assert hass.states.get("sensor.device_uptime").state == "2021-01-01T01:00:00+00:00"
# Verify new event change uptime
# 1 month has passed
device["uptime"] = 60
now = datetime(2021, 2, 1, 1, 1, 0, tzinfo=dt_util.UTC)
with patch("homeassistant.util.dt.now", return_value=now):
mock_unifi_websocket(message=MessageKey.DEVICE, data=device)
assert hass.states.get("sensor.device_uptime").state == "2021-02-01T01:00:00+00:00"
async def test_device_temperature(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
aioclient_mock: AiohttpClientMocker,
mock_unifi_websocket,
) -> None:
"""Verify that temperature sensors are working as expected."""
device = {
"board_rev": 3,
"device_id": "mock-id",
"general_temperature": 30,
"has_fan": True,
"has_temperature": True,
"fan_level": 0,
"ip": "10.0.1.1",
"last_seen": 1562600145,
"mac": "00:00:00:00:01:01",
"model": "US16P150",
"name": "Device",
"next_interval": 20,
"overheating": True,
"state": 1,
"type": "usw",
"upgradable": True,
"uptime": 60,
"version": "4.0.42.10433",
}
await setup_unifi_integration(hass, aioclient_mock, devices_response=[device])
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 3
assert hass.states.get("sensor.device_temperature").state == "30"
assert (
entity_registry.async_get("sensor.device_temperature").entity_category
is EntityCategory.DIAGNOSTIC
)
# Verify new event change temperature
device["general_temperature"] = 60
mock_unifi_websocket(message=MessageKey.DEVICE, data=device)
assert hass.states.get("sensor.device_temperature").state == "60"
async def test_device_state(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
aioclient_mock: AiohttpClientMocker,
mock_unifi_websocket,
) -> None:
"""Verify that state sensors are working as expected."""
device = {
"board_rev": 3,
"device_id": "mock-id",
"general_temperature": 30,
"has_fan": True,
"has_temperature": True,
"fan_level": 0,
"ip": "10.0.1.1",
"last_seen": 1562600145,
"mac": "00:00:00:00:01:01",
"model": "US16P150",
"name": "Device",
"next_interval": 20,
"overheating": True,
"state": 1,
"type": "usw",
"upgradable": True,
"uptime": 60,
"version": "4.0.42.10433",
}
await setup_unifi_integration(hass, aioclient_mock, devices_response=[device])
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 3
assert (
entity_registry.async_get("sensor.device_state").entity_category
is EntityCategory.DIAGNOSTIC
)
for i in list(map(int, DeviceState)):
device["state"] = i
mock_unifi_websocket(message=MessageKey.DEVICE, data=device)
assert hass.states.get("sensor.device_state").state == DEVICE_STATES[i]