text: """The tests for the UniFi Network device tracker platform."""
  
  from datetime import timedelta
  from unittest.mock import patch
  
  from aiounifi.controller import (
      MESSAGE_CLIENT,
      MESSAGE_CLIENT_REMOVED,
      MESSAGE_DEVICE,
      MESSAGE_EVENT,
  )
  from aiounifi.websocket import STATE_DISCONNECTED, STATE_RUNNING
  
  from homeassistant import config_entries
  from homeassistant.components.device_tracker import DOMAIN as TRACKER_DOMAIN
  from homeassistant.components.unifi.const import (
      CONF_BLOCK_CLIENT,
      CONF_IGNORE_WIRED_BUG,
      CONF_SSID_FILTER,
      CONF_TRACK_CLIENTS,
      CONF_TRACK_DEVICES,
      CONF_TRACK_WIRED_CLIENTS,
      DOMAIN as UNIFI_DOMAIN,
  )
  from homeassistant.const import STATE_HOME, STATE_NOT_HOME, STATE_UNAVAILABLE
  from homeassistant.helpers import device_registry as dr, entity_registry as er
  import homeassistant.util.dt as dt_util
  
  from .test_controller import ENTRY_CONFIG, setup_unifi_integration
  
  from tests.common import async_fire_time_changed
  
  
  async def test_no_entities(hass, aioclient_mock):
      """Test the update_clients function when no clients are found."""
      await setup_unifi_integration(hass, aioclient_mock)
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 0
  
  
  async def test_tracked_wireless_clients(hass, aioclient_mock, mock_unifi_websocket):
      """Verify tracking of wireless clients."""
      client = {
          "ap_mac": "00:00:00:00:02:01",
          "essid": "ssid",
          "hostname": "client",
          "ip": "10.0.0.1",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      config_entry = await setup_unifi_integration(
          hass, aioclient_mock, clients_response=[client]
      )
      controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id]
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1
      assert hass.states.get("device_tracker.client").state == STATE_NOT_HOME
  
      # State change signalling works without events
  
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      await hass.async_block_till_done()
  
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_HOME
      assert client_state.attributes["ip"] == "10.0.0.1"
      assert client_state.attributes["mac"] == "00:00:00:00:00:01"
      assert client_state.attributes["hostname"] == "client"
      assert client_state.attributes["host_name"] == "client"
  
      # State change signalling works with events
  
      # Disconnected event
  
      event = {
          "user": client["mac"],
          "ssid": client["essid"],
          "hostname": client["hostname"],
          "ap": client["ap_mac"],
          "duration": 467,
          "bytes": 459039,
          "key": "EVT_WU_Disconnected",
          "subsystem": "wlan",
          "site_id": "name",
          "time": 1587752927000,
          "datetime": "2020-04-24T18:28:47Z",
          "msg": f'User{[client["mac"]]} disconnected from "{client["essid"]}" (7m 47s connected, 448.28K bytes, last AP[{client["ap_mac"]}])',
          "_id": "5ea32ff730c49e00f90dca1a",
      }
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_EVENT},
              "data": [event],
          }
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_HOME
  
      # Change time to mark client as away
  
      new_time = dt_util.utcnow() + controller.option_detection_time
      with patch("homeassistant.util.dt.utcnow", return_value=new_time):
          async_fire_time_changed(hass, new_time)
          await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_NOT_HOME
  
      # To limit false positives in client tracker
      # data sources other than events are only used to update state
      # until the first event has been received.
      # This control will be reset if controller connection has been lost.
  
      # New data doesn't change state
  
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_NOT_HOME
  
      # Connected event
  
      event = {
          "user": client["mac"],
          "ssid": client["essid"],
          "ap": client["ap_mac"],
          "radio": "na",
          "channel": "44",
          "hostname": client["hostname"],
          "key": "EVT_WU_Connected",
          "subsystem": "wlan",
          "site_id": "name",
          "time": 1587753456179,
          "datetime": "2020-04-24T18:37:36Z",
          "msg": f'User{[client["mac"]]} has connected to AP[{client["ap_mac"]}] with SSID "{client["essid"]}" on "channel 44(na)"',
          "_id": "5ea331fa30c49e00f90ddc1a",
      }
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_EVENT},
              "data": [event],
          }
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_HOME
  
  
  async def test_tracked_clients(hass, aioclient_mock, mock_unifi_websocket):
      """Test the update_items function with some clients."""
      client_1 = {
          "ap_mac": "00:00:00:00:02:01",
          "essid": "ssid",
          "hostname": "client_1",
          "ip": "10.0.0.1",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      client_2 = {
          "ip": "10.0.0.2",
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:02",
          "name": "Client 2",
      }
      client_3 = {
          "essid": "ssid2",
          "hostname": "client_3",
          "ip": "10.0.0.3",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:03",
      }
      client_4 = {
          "essid": "ssid",
          "hostname": "client_4",
          "ip": "10.0.0.4",
          "is_wired": True,
          "last_seen": dt_util.as_timestamp(dt_util.utcnow()),
          "mac": "00:00:00:00:00:04",
      }
      client_5 = {
          "essid": "ssid",
          "hostname": "client_5",
          "ip": "10.0.0.5",
          "is_wired": True,
          "last_seen": None,
          "mac": "00:00:00:00:00:05",
      }
  
      await setup_unifi_integration(
          hass,
          aioclient_mock,
          options={CONF_SSID_FILTER: ["ssid"]},
          clients_response=[client_1, client_2, client_3, client_4, client_5],
          known_wireless_clients=(client_4["mac"],),
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 4
      assert hass.states.get("device_tracker.client_1").state == STATE_NOT_HOME
      assert hass.states.get("device_tracker.client_2").state == STATE_NOT_HOME
  
      # Client on SSID not in SSID filter
      assert not hass.states.get("device_tracker.client_3")
  
      # Wireless client with wired bug, if bug active on restart mark device away
      assert hass.states.get("device_tracker.client_4").state == STATE_NOT_HOME
  
      # A client that has never been seen should be marked away.
      assert hass.states.get("device_tracker.client_5").state == STATE_NOT_HOME
  
      # State change signalling works
  
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client_1],
          }
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client_1").state == STATE_HOME
  
  
  async def test_tracked_devices(hass, aioclient_mock, mock_unifi_websocket):
      """Test the update_items function with some devices."""
      device_1 = {
          "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 1",
          "next_interval": 20,
          "overheating": True,
          "state": 1,
          "type": "usw",
          "upgradable": True,
          "version": "4.0.42.10433",
      }
      device_2 = {
          "board_rev": 3,
          "device_id": "mock-id",
          "has_fan": True,
          "ip": "10.0.1.2",
          "mac": "00:00:00:00:01:02",
          "model": "US16P150",
          "name": "Device 2",
          "next_interval": 20,
          "state": 0,
          "type": "usw",
          "version": "4.0.42.10433",
      }
      await setup_unifi_integration(
          hass,
          aioclient_mock,
          devices_response=[device_1, device_2],
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 2
      assert hass.states.get("device_tracker.device_1").state == STATE_HOME
      assert hass.states.get("device_tracker.device_2").state == STATE_NOT_HOME
  
      # State change signalling work
  
      device_1["next_interval"] = 20
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_DEVICE},
              "data": [device_1],
          }
      )
      device_2["next_interval"] = 50
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_DEVICE},
              "data": [device_2],
          }
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.device_1").state == STATE_HOME
      assert hass.states.get("device_tracker.device_2").state == STATE_HOME
  
      # Change of time can mark device not_home outside of expected reporting interval
  
      new_time = dt_util.utcnow() + timedelta(seconds=90)
      with patch("homeassistant.util.dt.utcnow", return_value=new_time):
          async_fire_time_changed(hass, new_time)
          await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.device_1").state == STATE_NOT_HOME
      assert hass.states.get("device_tracker.device_2").state == STATE_HOME
  
      # Disabled device is unavailable
  
      device_1["disabled"] = True
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_DEVICE},
              "data": [device_1],
          }
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.device_1").state == STATE_UNAVAILABLE
      assert hass.states.get("device_tracker.device_2").state == STATE_HOME
  
      # Update device registry when device is upgraded
  
      event = {
          "_id": "5eae7fe02ab79c00f9d38960",
          "datetime": "2020-05-09T20:06:37Z",
          "key": "EVT_SW_Upgraded",
          "msg": f'Switch[{device_2["mac"]}] was upgraded from "{device_2["version"]}" to "4.3.13.11253"',
          "subsystem": "lan",
          "sw": device_2["mac"],
          "sw_name": device_2["name"],
          "time": 1589054797635,
          "version_from": {device_2["version"]},
          "version_to": "4.3.13.11253",
      }
  
      device_2["version"] = event["version_to"]
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_DEVICE},
              "data": [device_2],
          }
      )
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_EVENT},
              "data": [event],
          }
      )
      await hass.async_block_till_done()
  
      # Verify device registry has been updated
      entity_registry = er.async_get(hass)
      entry = entity_registry.async_get("device_tracker.device_2")
      device_registry = dr.async_get(hass)
      device = device_registry.async_get(entry.device_id)
      assert device.sw_version == event["version_to"]
  
  
  async def test_remove_clients(hass, aioclient_mock, mock_unifi_websocket):
      """Test the remove_items function with some clients."""
      client_1 = {
          "essid": "ssid",
          "hostname": "client_1",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      client_2 = {
          "hostname": "client_2",
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:02",
      }
      await setup_unifi_integration(
          hass, aioclient_mock, clients_response=[client_1, client_2]
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 2
      assert hass.states.get("device_tracker.client_1")
      assert hass.states.get("device_tracker.client_2")
  
      # Remove client
  
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT_REMOVED},
              "data": [client_1],
          }
      )
      await hass.async_block_till_done()
      await hass.async_block_till_done()
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1
      assert not hass.states.get("device_tracker.client_1")
      assert hass.states.get("device_tracker.client_2")
  
  
  async def test_remove_client_but_keep_device_entry(
      hass, aioclient_mock, mock_unifi_websocket
  ):
      """Test that unifi entity base remove config entry id from a multi integration device registry entry."""
      client_1 = {
          "essid": "ssid",
          "hostname": "client_1",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      await setup_unifi_integration(hass, aioclient_mock, clients_response=[client_1])
  
      device_registry = dr.async_get(hass)
      device_entry = device_registry.async_get_or_create(
          config_entry_id="other",
          connections={("mac", "00:00:00:00:00:01")},
      )
  
      entity_registry = er.async_get(hass)
      other_entity = entity_registry.async_get_or_create(
          TRACKER_DOMAIN,
          "other",
          "unique_id",
          device_id=device_entry.id,
      )
      assert len(device_entry.config_entries) == 2
  
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT_REMOVED},
              "data": [client_1],
          }
      )
      await hass.async_block_till_done()
      await hass.async_block_till_done()
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 0
  
      device_entry = device_registry.async_get(other_entity.device_id)
      assert len(device_entry.config_entries) == 1
  
  
  async def test_controller_state_change(hass, aioclient_mock, mock_unifi_websocket):
      """Verify entities state reflect on controller becoming unavailable."""
      client = {
          "essid": "ssid",
          "hostname": "client",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      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,
          "version": "4.0.42.10433",
      }
  
      await setup_unifi_integration(
          hass,
          aioclient_mock,
          clients_response=[client],
          devices_response=[device],
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 2
      assert hass.states.get("device_tracker.client").state == STATE_NOT_HOME
      assert hass.states.get("device_tracker.device").state == STATE_HOME
  
      # Controller unavailable
      mock_unifi_websocket(state=STATE_DISCONNECTED)
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_UNAVAILABLE
      assert hass.states.get("device_tracker.device").state == STATE_UNAVAILABLE
  
      # Controller available
      mock_unifi_websocket(state=STATE_RUNNING)
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_NOT_HOME
      assert hass.states.get("device_tracker.device").state == STATE_HOME
  
  
  async def test_controller_state_change_client_to_listen_on_all_state_changes(
      hass, aioclient_mock, mock_unifi_websocket
  ):
      """Verify entities state reflect on controller becoming unavailable."""
      client = {
          "ap_mac": "00:00:00:00:02:01",
          "essid": "ssid",
          "hostname": "client",
          "ip": "10.0.0.1",
          "is_wired": False,
          "last_seen": dt_util.as_timestamp(dt_util.utcnow()),
          "mac": "00:00:00:00:00:01",
      }
      config_entry = await setup_unifi_integration(
          hass, aioclient_mock, clients_response=[client]
      )
      controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id]
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1
      assert hass.states.get("device_tracker.client").state == STATE_HOME
  
      # Disconnected event
  
      event = {
          "user": client["mac"],
          "ssid": client["essid"],
          "hostname": client["hostname"],
          "ap": client["ap_mac"],
          "duration": 467,
          "bytes": 459039,
          "key": "EVT_WU_Disconnected",
          "subsystem": "wlan",
          "site_id": "name",
          "time": 1587752927000,
          "datetime": "2020-04-24T18:28:47Z",
          "msg": f'User{[client["mac"]]} disconnected from "{client["essid"]}" (7m 47s connected, 448.28K bytes, last AP[{client["ap_mac"]}])',
          "_id": "5ea32ff730c49e00f90dca1a",
      }
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_EVENT},
              "data": [event],
          }
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_HOME
  
      # Change time to mark client as away
  
      new_time = dt_util.utcnow() + controller.option_detection_time
      with patch("homeassistant.util.dt.utcnow", return_value=new_time):
          async_fire_time_changed(hass, new_time)
          await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_NOT_HOME
  
      # Controller unavailable
      mock_unifi_websocket(state=STATE_DISCONNECTED)
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_UNAVAILABLE
  
      # Controller available
      mock_unifi_websocket(state=STATE_RUNNING)
      await hass.async_block_till_done()
  
      # To limit false positives in client tracker
      # data sources other than events are only used to update state
      # until the first event has been received.
      # This control will be reset if controller connection has been lost.
  
      # New data can change state
  
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_HOME
  
  
  async def test_option_track_clients(hass, aioclient_mock):
      """Test the tracking of clients can be turned off."""
      wireless_client = {
          "essid": "ssid",
          "hostname": "wireless_client",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      wired_client = {
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:02",
          "name": "Wired Client",
      }
      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,
          "version": "4.0.42.10433",
      }
  
      config_entry = await setup_unifi_integration(
          hass,
          aioclient_mock,
          clients_response=[wireless_client, wired_client],
          devices_response=[device],
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 3
      assert hass.states.get("device_tracker.wireless_client")
      assert hass.states.get("device_tracker.wired_client")
      assert hass.states.get("device_tracker.device")
  
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_TRACK_CLIENTS: False},
      )
      await hass.async_block_till_done()
  
      assert not hass.states.get("device_tracker.wireless_client")
      assert not hass.states.get("device_tracker.wired_client")
      assert hass.states.get("device_tracker.device")
  
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_TRACK_CLIENTS: True},
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.wireless_client")
      assert hass.states.get("device_tracker.wired_client")
      assert hass.states.get("device_tracker.device")
  
  
  async def test_option_track_wired_clients(hass, aioclient_mock):
      """Test the tracking of wired clients can be turned off."""
      wireless_client = {
          "essid": "ssid",
          "hostname": "wireless_client",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      wired_client = {
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:02",
          "name": "Wired Client",
      }
      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,
          "version": "4.0.42.10433",
      }
  
      config_entry = await setup_unifi_integration(
          hass,
          aioclient_mock,
          clients_response=[wireless_client, wired_client],
          devices_response=[device],
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 3
      assert hass.states.get("device_tracker.wireless_client")
      assert hass.states.get("device_tracker.wired_client")
      assert hass.states.get("device_tracker.device")
  
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_TRACK_WIRED_CLIENTS: False},
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.wireless_client")
      assert not hass.states.get("device_tracker.wired_client")
      assert hass.states.get("device_tracker.device")
  
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_TRACK_WIRED_CLIENTS: True},
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.wireless_client")
      assert hass.states.get("device_tracker.wired_client")
      assert hass.states.get("device_tracker.device")
  
  
  async def test_option_track_devices(hass, aioclient_mock):
      """Test the tracking of devices can be turned off."""
      client = {
          "hostname": "client",
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      device = {
          "board_rev": 3,
          "device_id": "mock-id",
          "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,
          "version": "4.0.42.10433",
      }
  
      config_entry = await setup_unifi_integration(
          hass,
          aioclient_mock,
          clients_response=[client],
          devices_response=[device],
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 2
      assert hass.states.get("device_tracker.client")
      assert hass.states.get("device_tracker.device")
  
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_TRACK_DEVICES: False},
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client")
      assert not hass.states.get("device_tracker.device")
  
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_TRACK_DEVICES: True},
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client")
      assert hass.states.get("device_tracker.device")
  
  
  async def test_option_ssid_filter(hass, aioclient_mock, mock_unifi_websocket):
      """Test the SSID filter works.
  
      Client will travel from a supported SSID to an unsupported ssid.
      Client on SSID2 will be removed on change of options.
      """
      client = {
          "essid": "ssid",
          "hostname": "client",
          "is_wired": False,
          "last_seen": dt_util.as_timestamp(dt_util.utcnow()),
          "mac": "00:00:00:00:00:01",
      }
      client_on_ssid2 = {
          "essid": "ssid2",
          "hostname": "client_on_ssid2",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:02",
      }
  
      config_entry = await setup_unifi_integration(
          hass, aioclient_mock, clients_response=[client, client_on_ssid2]
      )
      controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id]
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 2
  
      assert hass.states.get("device_tracker.client").state == STATE_HOME
      assert hass.states.get("device_tracker.client_on_ssid2").state == STATE_NOT_HOME
  
      # Setting SSID filter will remove clients outside of filter
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_SSID_FILTER: ["ssid"]},
      )
      await hass.async_block_till_done()
  
      # Not affected by SSID filter
      assert hass.states.get("device_tracker.client").state == STATE_HOME
  
      # Removed due to SSID filter
      assert not hass.states.get("device_tracker.client_on_ssid2")
  
      # Roams to SSID outside of filter
      client["essid"] = "other_ssid"
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      # Data update while SSID filter is in effect shouldn't create the client
      client_on_ssid2["last_seen"] = dt_util.as_timestamp(dt_util.utcnow())
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client_on_ssid2],
          }
      )
      await hass.async_block_till_done()
  
      # SSID filter marks client as away
      assert hass.states.get("device_tracker.client").state == STATE_NOT_HOME
  
      # SSID still outside of filter
      assert not hass.states.get("device_tracker.client_on_ssid2")
  
      # Remove SSID filter
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_SSID_FILTER: []},
      )
      await hass.async_block_till_done()
  
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client_on_ssid2],
          }
      )
      await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_HOME
      assert hass.states.get("device_tracker.client_on_ssid2").state == STATE_HOME
  
      # Time pass to mark client as away
  
      new_time = dt_util.utcnow() + controller.option_detection_time
      with patch("homeassistant.util.dt.utcnow", return_value=new_time):
          async_fire_time_changed(hass, new_time)
          await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client").state == STATE_NOT_HOME
  
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client_on_ssid2],
          }
      )
      await hass.async_block_till_done()
  
      # Client won't go away until after next update
      assert hass.states.get("device_tracker.client_on_ssid2").state == STATE_HOME
  
      # Trigger update to get client marked as away
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client_on_ssid2],
          }
      )
      await hass.async_block_till_done()
  
      new_time = (
          dt_util.utcnow() + controller.option_detection_time + timedelta(seconds=1)
      )
      with patch("homeassistant.util.dt.utcnow", return_value=new_time):
          async_fire_time_changed(hass, new_time)
          await hass.async_block_till_done()
  
      assert hass.states.get("device_tracker.client_on_ssid2").state == STATE_NOT_HOME
  
  
  async def test_wireless_client_go_wired_issue(
      hass, aioclient_mock, mock_unifi_websocket
  ):
      """Test the solution to catch wireless device go wired UniFi issue.
  
      UniFi Network has a known issue that when a wireless device goes away it sometimes gets marked as wired.
      """
      client = {
          "essid": "ssid",
          "hostname": "client",
          "ip": "10.0.0.1",
          "is_wired": False,
          "last_seen": dt_util.as_timestamp(dt_util.utcnow()),
          "mac": "00:00:00:00:00:01",
      }
  
      config_entry = await setup_unifi_integration(
          hass, aioclient_mock, clients_response=[client]
      )
      controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id]
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1
  
      # Client is wireless
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_HOME
      assert client_state.attributes["is_wired"] is False
  
      # Trigger wired bug
      client["is_wired"] = True
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      await hass.async_block_till_done()
  
      # Wired bug fix keeps client marked as wireless
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_HOME
      assert client_state.attributes["is_wired"] is False
  
      # Pass time
      new_time = dt_util.utcnow() + controller.option_detection_time
      with patch("homeassistant.util.dt.utcnow", return_value=new_time):
          async_fire_time_changed(hass, new_time)
          await hass.async_block_till_done()
  
      # Marked as home according to the timer
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_NOT_HOME
      assert client_state.attributes["is_wired"] is False
  
      # Try to mark client as connected
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      await hass.async_block_till_done()
  
      # Make sure it don't go online again until wired bug disappears
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_NOT_HOME
      assert client_state.attributes["is_wired"] is False
  
      # Make client wireless
      client["is_wired"] = False
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      await hass.async_block_till_done()
  
      # Client is no longer affected by wired bug and can be marked online
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_HOME
      assert client_state.attributes["is_wired"] is False
  
  
  async def test_option_ignore_wired_bug(hass, aioclient_mock, mock_unifi_websocket):
      """Test option to ignore wired bug."""
      client = {
          "ap_mac": "00:00:00:00:02:01",
          "essid": "ssid",
          "hostname": "client",
          "ip": "10.0.0.1",
          "is_wired": False,
          "last_seen": dt_util.as_timestamp(dt_util.utcnow()),
          "mac": "00:00:00:00:00:01",
      }
  
      config_entry = await setup_unifi_integration(
          hass,
          aioclient_mock,
          options={CONF_IGNORE_WIRED_BUG: True},
          clients_response=[client],
      )
      controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id]
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1
  
      # Client is wireless
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_HOME
      assert client_state.attributes["is_wired"] is False
  
      # Trigger wired bug
      client["is_wired"] = True
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      await hass.async_block_till_done()
  
      # Wired bug in effect
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_HOME
      assert client_state.attributes["is_wired"] is True
  
      # pass time
      new_time = dt_util.utcnow() + controller.option_detection_time
      with patch("homeassistant.util.dt.utcnow", return_value=new_time):
          async_fire_time_changed(hass, new_time)
          await hass.async_block_till_done()
  
      # Timer marks client as away
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_NOT_HOME
      assert client_state.attributes["is_wired"] is True
  
      # Mark client as connected again
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      await hass.async_block_till_done()
  
      # Ignoring wired bug allows client to go home again even while affected
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_HOME
      assert client_state.attributes["is_wired"] is True
  
      # Make client wireless
      client["is_wired"] = False
      mock_unifi_websocket(
          data={
              "meta": {"message": MESSAGE_CLIENT},
              "data": [client],
          }
      )
      await hass.async_block_till_done()
  
      # Client is wireless and still connected
      client_state = hass.states.get("device_tracker.client")
      assert client_state.state == STATE_HOME
      assert client_state.attributes["is_wired"] is False
  
  
  async def test_restoring_client(hass, aioclient_mock):
      """Verify clients are restored from clients_all if they ever was registered to entity registry."""
      client = {
          "hostname": "client",
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      restored = {
          "hostname": "restored",
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:02",
      }
      not_restored = {
          "hostname": "not_restored",
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:03",
      }
  
      config_entry = config_entries.ConfigEntry(
          version=1,
          domain=UNIFI_DOMAIN,
          title="Mock Title",
          data=ENTRY_CONFIG,
          source="test",
          options={},
          entry_id="1",
      )
  
      registry = er.async_get(hass)
      registry.async_get_or_create(
          TRACKER_DOMAIN,
          UNIFI_DOMAIN,
          f'{restored["mac"]}-site_id',
          suggested_object_id=restored["hostname"],
          config_entry=config_entry,
      )
  
      await setup_unifi_integration(
          hass,
          aioclient_mock,
          options={CONF_BLOCK_CLIENT: True},
          clients_response=[client],
          clients_all_response=[restored, not_restored],
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 2
      assert hass.states.get("device_tracker.client")
      assert hass.states.get("device_tracker.restored")
      assert not hass.states.get("device_tracker.not_restored")
  
  
  async def test_dont_track_clients(hass, aioclient_mock):
      """Test don't track clients config works."""
      wireless_client = {
          "essid": "ssid",
          "hostname": "Wireless client",
          "ip": "10.0.0.1",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      wired_client = {
          "hostname": "Wired client",
          "ip": "10.0.0.2",
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:02",
      }
      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,
          "version": "4.0.42.10433",
      }
  
      config_entry = await setup_unifi_integration(
          hass,
          aioclient_mock,
          options={CONF_TRACK_CLIENTS: False},
          clients_response=[wireless_client, wired_client],
          devices_response=[device],
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1
      assert not hass.states.get("device_tracker.wireless_client")
      assert not hass.states.get("device_tracker.wired_client")
      assert hass.states.get("device_tracker.device")
  
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_TRACK_CLIENTS: True},
      )
      await hass.async_block_till_done()
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 3
      assert hass.states.get("device_tracker.wireless_client")
      assert hass.states.get("device_tracker.wired_client")
      assert hass.states.get("device_tracker.device")
  
  
  async def test_dont_track_devices(hass, aioclient_mock):
      """Test don't track devices config works."""
      client = {
          "hostname": "client",
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      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,
          "version": "4.0.42.10433",
      }
  
      config_entry = await setup_unifi_integration(
          hass,
          aioclient_mock,
          options={CONF_TRACK_DEVICES: False},
          clients_response=[client],
          devices_response=[device],
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1
      assert hass.states.get("device_tracker.client")
      assert not hass.states.get("device_tracker.device")
  
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_TRACK_DEVICES: True},
      )
      await hass.async_block_till_done()
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 2
      assert hass.states.get("device_tracker.client")
      assert hass.states.get("device_tracker.device")
  
  
  async def test_dont_track_wired_clients(hass, aioclient_mock):
      """Test don't track wired clients config works."""
      wireless_client = {
          "essid": "ssid",
          "hostname": "Wireless Client",
          "is_wired": False,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:01",
      }
      wired_client = {
          "is_wired": True,
          "last_seen": 1562600145,
          "mac": "00:00:00:00:00:02",
          "name": "Wired Client",
      }
  
      config_entry = await setup_unifi_integration(
          hass,
          aioclient_mock,
          options={CONF_TRACK_WIRED_CLIENTS: False},
          clients_response=[wireless_client, wired_client],
      )
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1
      assert hass.states.get("device_tracker.wireless_client")
      assert not hass.states.get("device_tracker.wired_client")
  
      hass.config_entries.async_update_entry(
          config_entry,
          options={CONF_TRACK_WIRED_CLIENTS: True},
      )
      await hass.async_block_till_done()
  
      assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 2
      assert hass.states.get("device_tracker.wireless_client")
      assert hass.states.get("device_tracker.wired_client")
  