Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion homeassistant/components/unifi/.translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"client_control": {
"data": {
"block_client": "Network access controlled clients",
"new_client": "Add new client for network access control"
"new_client": "Add new client (MAC) for network access control",
"poe_clients": "Allow POE control of clients"
},
"description": "Configure client controls\n\nCreate switches for serial numbers you want to control network access for.",
"title": "UniFi options 2/3"
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/unifi/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
CONF_BLOCK_CLIENT,
CONF_CONTROLLER,
CONF_DETECTION_TIME,
CONF_POE_CLIENTS,
CONF_SITE_ID,
CONF_SSID_FILTER,
CONF_TRACK_CLIENTS,
CONF_TRACK_DEVICES,
CONF_TRACK_WIRED_CLIENTS,
CONTROLLER_ID,
DEFAULT_POE_CLIENTS,
DOMAIN,
LOGGER,
)
Expand Down Expand Up @@ -262,6 +264,10 @@ async def async_step_client_control(self, user_input=None):
step_id="client_control",
data_schema=vol.Schema(
{
vol.Optional(
CONF_POE_CLIENTS,
default=self.options.get(CONF_POE_CLIENTS, DEFAULT_POE_CLIENTS),
): bool,
vol.Optional(
CONF_BLOCK_CLIENT, default=self.options[CONF_BLOCK_CLIENT]
): cv.multi_select(clients_to_block),
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/unifi/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
CONF_ALLOW_BANDWIDTH_SENSORS = "allow_bandwidth_sensors"
CONF_BLOCK_CLIENT = "block_client"
CONF_DETECTION_TIME = "detection_time"
CONF_POE_CLIENTS = "poe_clients"
CONF_TRACK_CLIENTS = "track_clients"
CONF_TRACK_DEVICES = "track_devices"
CONF_TRACK_WIRED_CLIENTS = "track_wired_clients"
CONF_SSID_FILTER = "ssid_filter"

DEFAULT_ALLOW_BANDWIDTH_SENSORS = False
DEFAULT_POE_CLIENTS = True
DEFAULT_TRACK_CLIENTS = True
DEFAULT_TRACK_DEVICES = True
DEFAULT_TRACK_WIRED_CLIENTS = True
Expand Down
7 changes: 7 additions & 0 deletions homeassistant/components/unifi/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
CONF_BLOCK_CLIENT,
CONF_CONTROLLER,
CONF_DETECTION_TIME,
CONF_POE_CLIENTS,
CONF_SITE_ID,
CONF_SSID_FILTER,
CONF_TRACK_CLIENTS,
Expand All @@ -32,6 +33,7 @@
CONTROLLER_ID,
DEFAULT_ALLOW_BANDWIDTH_SENSORS,
DEFAULT_DETECTION_TIME,
DEFAULT_POE_CLIENTS,
DEFAULT_TRACK_CLIENTS,
DEFAULT_TRACK_DEVICES,
DEFAULT_TRACK_WIRED_CLIENTS,
Expand Down Expand Up @@ -98,6 +100,11 @@ def option_block_clients(self):
"""Config entry option with list of clients to control network access."""
return self.config_entry.options.get(CONF_BLOCK_CLIENT, [])

@property
def option_poe_clients(self):
"""Config entry option to control poe clients."""
return self.config_entry.options.get(CONF_POE_CLIENTS, DEFAULT_POE_CLIENTS)

@property
def option_track_clients(self):
"""Config entry option to not track clients."""
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/unifi/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"client_control": {
"data": {
"block_client": "Network access controlled clients",
"new_client": "Add new client for network access control"
"new_client": "Add new client for network access control",
"poe_clients": "Allow POE control of clients"
},
"description": "Configure client controls\n\nCreate switches for serial numbers you want to control network access for.",
"title": "UniFi options 2/3"
Expand Down
97 changes: 54 additions & 43 deletions homeassistant/components/unifi/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
switches_off = []

option_block_clients = controller.option_block_clients
option_poe_clients = controller.option_poe_clients

entity_registry = await hass.helpers.entity_registry.async_get_registry()

Expand Down Expand Up @@ -66,6 +67,7 @@ def update_controller():
def options_updated():
"""Manage entities affected by config entry options."""
nonlocal option_block_clients
nonlocal option_poe_clients

update = set()
remove = set()
Expand All @@ -82,16 +84,26 @@ def options_updated():
else:
remove.add(block_client_id)

for block_client_id in remove:
entity = switches.pop(block_client_id)
if option_poe_clients != controller.option_poe_clients:
option_poe_clients = controller.option_poe_clients

if entity_registry.async_is_registered(entity.entity_id):
entity_registry.async_remove(entity.entity_id)
if option_poe_clients:
update.add("poe_clients_enabled")
else:
for poe_client_id, entity in switches.items():
if isinstance(entity, UniFiPOEClientSwitch):
remove.add(poe_client_id)

hass.async_create_task(entity.async_remove())
for client_id in remove:
entity = switches.pop(client_id)

if len(update) != len(option_block_clients):
update_controller()
if entity_registry.async_is_registered(entity.entity_id):
entity_registry.async_remove(entity.entity_id)

hass.async_create_task(entity.async_remove())

if len(update) != len(option_block_clients):
update_controller()

controller.listeners.append(
async_dispatcher_connect(
Expand All @@ -109,7 +121,6 @@ def add_entities(controller, async_add_entities, switches, switches_off):
new_switches = []
devices = controller.api.devices

# block client
for client_id in controller.option_block_clients:

client = None
Expand All @@ -130,49 +141,49 @@ def add_entities(controller, async_add_entities, switches, switches_off):
switches[block_client_id] = UniFiBlockClientSwitch(client, controller)
new_switches.append(switches[block_client_id])

# control POE
for client_id in controller.api.clients:
if controller.option_poe_clients:
for client_id in controller.api.clients:

poe_client_id = f"poe-{client_id}"

if poe_client_id in switches:
continue
poe_client_id = f"poe-{client_id}"

client = controller.api.clients[client_id]

if poe_client_id in switches_off:
pass
# Network device with active POE
elif (
client_id in controller.wireless_clients
or client.sw_mac not in devices
or not devices[client.sw_mac].ports[client.sw_port].port_poe
or not devices[client.sw_mac].ports[client.sw_port].poe_enable
or controller.mac == client.mac
):
continue
if poe_client_id in switches:
continue

# Multiple POE-devices on same port means non UniFi POE driven switch
multi_clients_on_port = False
for client2 in controller.api.clients.values():
client = controller.api.clients[client_id]

if poe_client_id in switches_off:
break

if (
client2.is_wired
and client.mac != client2.mac
and client.sw_mac == client2.sw_mac
and client.sw_port == client2.sw_port
pass
# Network device with active POE
elif (
client_id in controller.wireless_clients
or client.sw_mac not in devices
or not devices[client.sw_mac].ports[client.sw_port].port_poe
or not devices[client.sw_mac].ports[client.sw_port].poe_enable
or controller.mac == client.mac
):
multi_clients_on_port = True
break
continue

if multi_clients_on_port:
continue
# Multiple POE-devices on same port means non UniFi POE driven switch
multi_clients_on_port = False
for client2 in controller.api.clients.values():

if poe_client_id in switches_off:
break

if (
client2.is_wired
and client.mac != client2.mac
and client.sw_mac == client2.sw_mac
and client.sw_port == client2.sw_port
):
multi_clients_on_port = True
break

if multi_clients_on_port:
continue

switches[poe_client_id] = UniFiPOEClientSwitch(client, controller)
new_switches.append(switches[poe_client_id])
switches[poe_client_id] = UniFiPOEClientSwitch(client, controller)
new_switches.append(switches[poe_client_id])

if new_switches:
async_add_entities(new_switches)
Expand Down
3 changes: 3 additions & 0 deletions tests/components/unifi/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
CONF_BLOCK_CLIENT,
CONF_CONTROLLER,
CONF_DETECTION_TIME,
CONF_POE_CLIENTS,
CONF_SITE_ID,
CONF_SSID_FILTER,
CONF_TRACK_CLIENTS,
Expand Down Expand Up @@ -287,6 +288,7 @@ async def test_option_flow(hass):
user_input={
CONF_BLOCK_CLIENT: clients_to_block,
CONF_NEW_CLIENT: "00:00:00:00:00:01",
CONF_POE_CLIENTS: False,
},
)

Expand Down Expand Up @@ -327,5 +329,6 @@ async def test_option_flow(hass):
CONF_DETECTION_TIME: 100,
CONF_SSID_FILTER: ["SSID 1"],
CONF_BLOCK_CLIENT: ["00:00:00:00:00:01"],
CONF_POE_CLIENTS: False,
CONF_ALLOW_BANDWIDTH_SENSORS: True,
}