UniFi - Make POE control switches configurable (#32781)
* Allow control whether POE switches are to be created or not * Fix options flow and test
This commit is contained in:
parent
23e091696e
commit
314bc07cee
7 changed files with 76 additions and 45 deletions
|
@ -32,7 +32,8 @@
|
||||||
"client_control": {
|
"client_control": {
|
||||||
"data": {
|
"data": {
|
||||||
"block_client": "Network access controlled clients",
|
"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.",
|
"description": "Configure client controls\n\nCreate switches for serial numbers you want to control network access for.",
|
||||||
"title": "UniFi options 2/3"
|
"title": "UniFi options 2/3"
|
||||||
|
|
|
@ -19,12 +19,14 @@ from .const import (
|
||||||
CONF_BLOCK_CLIENT,
|
CONF_BLOCK_CLIENT,
|
||||||
CONF_CONTROLLER,
|
CONF_CONTROLLER,
|
||||||
CONF_DETECTION_TIME,
|
CONF_DETECTION_TIME,
|
||||||
|
CONF_POE_CLIENTS,
|
||||||
CONF_SITE_ID,
|
CONF_SITE_ID,
|
||||||
CONF_SSID_FILTER,
|
CONF_SSID_FILTER,
|
||||||
CONF_TRACK_CLIENTS,
|
CONF_TRACK_CLIENTS,
|
||||||
CONF_TRACK_DEVICES,
|
CONF_TRACK_DEVICES,
|
||||||
CONF_TRACK_WIRED_CLIENTS,
|
CONF_TRACK_WIRED_CLIENTS,
|
||||||
CONTROLLER_ID,
|
CONTROLLER_ID,
|
||||||
|
DEFAULT_POE_CLIENTS,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
LOGGER,
|
LOGGER,
|
||||||
)
|
)
|
||||||
|
@ -262,6 +264,10 @@ class UnifiOptionsFlowHandler(config_entries.OptionsFlow):
|
||||||
step_id="client_control",
|
step_id="client_control",
|
||||||
data_schema=vol.Schema(
|
data_schema=vol.Schema(
|
||||||
{
|
{
|
||||||
|
vol.Optional(
|
||||||
|
CONF_POE_CLIENTS,
|
||||||
|
default=self.options.get(CONF_POE_CLIENTS, DEFAULT_POE_CLIENTS),
|
||||||
|
): bool,
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_BLOCK_CLIENT, default=self.options[CONF_BLOCK_CLIENT]
|
CONF_BLOCK_CLIENT, default=self.options[CONF_BLOCK_CLIENT]
|
||||||
): cv.multi_select(clients_to_block),
|
): cv.multi_select(clients_to_block),
|
||||||
|
|
|
@ -14,12 +14,14 @@ UNIFI_WIRELESS_CLIENTS = "unifi_wireless_clients"
|
||||||
CONF_ALLOW_BANDWIDTH_SENSORS = "allow_bandwidth_sensors"
|
CONF_ALLOW_BANDWIDTH_SENSORS = "allow_bandwidth_sensors"
|
||||||
CONF_BLOCK_CLIENT = "block_client"
|
CONF_BLOCK_CLIENT = "block_client"
|
||||||
CONF_DETECTION_TIME = "detection_time"
|
CONF_DETECTION_TIME = "detection_time"
|
||||||
|
CONF_POE_CLIENTS = "poe_clients"
|
||||||
CONF_TRACK_CLIENTS = "track_clients"
|
CONF_TRACK_CLIENTS = "track_clients"
|
||||||
CONF_TRACK_DEVICES = "track_devices"
|
CONF_TRACK_DEVICES = "track_devices"
|
||||||
CONF_TRACK_WIRED_CLIENTS = "track_wired_clients"
|
CONF_TRACK_WIRED_CLIENTS = "track_wired_clients"
|
||||||
CONF_SSID_FILTER = "ssid_filter"
|
CONF_SSID_FILTER = "ssid_filter"
|
||||||
|
|
||||||
DEFAULT_ALLOW_BANDWIDTH_SENSORS = False
|
DEFAULT_ALLOW_BANDWIDTH_SENSORS = False
|
||||||
|
DEFAULT_POE_CLIENTS = True
|
||||||
DEFAULT_TRACK_CLIENTS = True
|
DEFAULT_TRACK_CLIENTS = True
|
||||||
DEFAULT_TRACK_DEVICES = True
|
DEFAULT_TRACK_DEVICES = True
|
||||||
DEFAULT_TRACK_WIRED_CLIENTS = True
|
DEFAULT_TRACK_WIRED_CLIENTS = True
|
||||||
|
|
|
@ -24,6 +24,7 @@ from .const import (
|
||||||
CONF_BLOCK_CLIENT,
|
CONF_BLOCK_CLIENT,
|
||||||
CONF_CONTROLLER,
|
CONF_CONTROLLER,
|
||||||
CONF_DETECTION_TIME,
|
CONF_DETECTION_TIME,
|
||||||
|
CONF_POE_CLIENTS,
|
||||||
CONF_SITE_ID,
|
CONF_SITE_ID,
|
||||||
CONF_SSID_FILTER,
|
CONF_SSID_FILTER,
|
||||||
CONF_TRACK_CLIENTS,
|
CONF_TRACK_CLIENTS,
|
||||||
|
@ -32,6 +33,7 @@ from .const import (
|
||||||
CONTROLLER_ID,
|
CONTROLLER_ID,
|
||||||
DEFAULT_ALLOW_BANDWIDTH_SENSORS,
|
DEFAULT_ALLOW_BANDWIDTH_SENSORS,
|
||||||
DEFAULT_DETECTION_TIME,
|
DEFAULT_DETECTION_TIME,
|
||||||
|
DEFAULT_POE_CLIENTS,
|
||||||
DEFAULT_TRACK_CLIENTS,
|
DEFAULT_TRACK_CLIENTS,
|
||||||
DEFAULT_TRACK_DEVICES,
|
DEFAULT_TRACK_DEVICES,
|
||||||
DEFAULT_TRACK_WIRED_CLIENTS,
|
DEFAULT_TRACK_WIRED_CLIENTS,
|
||||||
|
@ -98,6 +100,11 @@ class UniFiController:
|
||||||
"""Config entry option with list of clients to control network access."""
|
"""Config entry option with list of clients to control network access."""
|
||||||
return self.config_entry.options.get(CONF_BLOCK_CLIENT, [])
|
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
|
@property
|
||||||
def option_track_clients(self):
|
def option_track_clients(self):
|
||||||
"""Config entry option to not track clients."""
|
"""Config entry option to not track clients."""
|
||||||
|
|
|
@ -43,7 +43,8 @@
|
||||||
"client_control": {
|
"client_control": {
|
||||||
"data": {
|
"data": {
|
||||||
"block_client": "Network access controlled clients",
|
"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.",
|
"description": "Configure client controls\n\nCreate switches for serial numbers you want to control network access for.",
|
||||||
"title": "UniFi options 2/3"
|
"title": "UniFi options 2/3"
|
||||||
|
|
|
@ -30,6 +30,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
switches_off = []
|
switches_off = []
|
||||||
|
|
||||||
option_block_clients = controller.option_block_clients
|
option_block_clients = controller.option_block_clients
|
||||||
|
option_poe_clients = controller.option_poe_clients
|
||||||
|
|
||||||
entity_registry = await hass.helpers.entity_registry.async_get_registry()
|
entity_registry = await hass.helpers.entity_registry.async_get_registry()
|
||||||
|
|
||||||
|
@ -66,6 +67,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
def options_updated():
|
def options_updated():
|
||||||
"""Manage entities affected by config entry options."""
|
"""Manage entities affected by config entry options."""
|
||||||
nonlocal option_block_clients
|
nonlocal option_block_clients
|
||||||
|
nonlocal option_poe_clients
|
||||||
|
|
||||||
update = set()
|
update = set()
|
||||||
remove = set()
|
remove = set()
|
||||||
|
@ -82,16 +84,26 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
else:
|
else:
|
||||||
remove.add(block_client_id)
|
remove.add(block_client_id)
|
||||||
|
|
||||||
for block_client_id in remove:
|
if option_poe_clients != controller.option_poe_clients:
|
||||||
entity = switches.pop(block_client_id)
|
option_poe_clients = controller.option_poe_clients
|
||||||
|
|
||||||
if entity_registry.async_is_registered(entity.entity_id):
|
if option_poe_clients:
|
||||||
entity_registry.async_remove(entity.entity_id)
|
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):
|
if entity_registry.async_is_registered(entity.entity_id):
|
||||||
update_controller()
|
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(
|
controller.listeners.append(
|
||||||
async_dispatcher_connect(
|
async_dispatcher_connect(
|
||||||
|
@ -109,7 +121,6 @@ def add_entities(controller, async_add_entities, switches, switches_off):
|
||||||
new_switches = []
|
new_switches = []
|
||||||
devices = controller.api.devices
|
devices = controller.api.devices
|
||||||
|
|
||||||
# block client
|
|
||||||
for client_id in controller.option_block_clients:
|
for client_id in controller.option_block_clients:
|
||||||
|
|
||||||
client = None
|
client = None
|
||||||
|
@ -130,49 +141,49 @@ def add_entities(controller, async_add_entities, switches, switches_off):
|
||||||
switches[block_client_id] = UniFiBlockClientSwitch(client, controller)
|
switches[block_client_id] = UniFiBlockClientSwitch(client, controller)
|
||||||
new_switches.append(switches[block_client_id])
|
new_switches.append(switches[block_client_id])
|
||||||
|
|
||||||
# control POE
|
if controller.option_poe_clients:
|
||||||
for client_id in controller.api.clients:
|
for client_id in controller.api.clients:
|
||||||
|
|
||||||
poe_client_id = f"poe-{client_id}"
|
poe_client_id = f"poe-{client_id}"
|
||||||
|
|
||||||
if poe_client_id in switches:
|
if poe_client_id in switches:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
client = controller.api.clients[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
|
|
||||||
|
|
||||||
# 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:
|
if poe_client_id in switches_off:
|
||||||
break
|
pass
|
||||||
|
# Network device with active POE
|
||||||
if (
|
elif (
|
||||||
client2.is_wired
|
client_id in controller.wireless_clients
|
||||||
and client.mac != client2.mac
|
or client.sw_mac not in devices
|
||||||
and client.sw_mac == client2.sw_mac
|
or not devices[client.sw_mac].ports[client.sw_port].port_poe
|
||||||
and client.sw_port == client2.sw_port
|
or not devices[client.sw_mac].ports[client.sw_port].poe_enable
|
||||||
|
or controller.mac == client.mac
|
||||||
):
|
):
|
||||||
multi_clients_on_port = True
|
continue
|
||||||
break
|
|
||||||
|
|
||||||
if multi_clients_on_port:
|
# Multiple POE-devices on same port means non UniFi POE driven switch
|
||||||
continue
|
multi_clients_on_port = False
|
||||||
|
for client2 in controller.api.clients.values():
|
||||||
|
|
||||||
switches[poe_client_id] = UniFiPOEClientSwitch(client, controller)
|
if poe_client_id in switches_off:
|
||||||
new_switches.append(switches[poe_client_id])
|
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])
|
||||||
|
|
||||||
if new_switches:
|
if new_switches:
|
||||||
async_add_entities(new_switches)
|
async_add_entities(new_switches)
|
||||||
|
|
|
@ -11,6 +11,7 @@ from homeassistant.components.unifi.const import (
|
||||||
CONF_BLOCK_CLIENT,
|
CONF_BLOCK_CLIENT,
|
||||||
CONF_CONTROLLER,
|
CONF_CONTROLLER,
|
||||||
CONF_DETECTION_TIME,
|
CONF_DETECTION_TIME,
|
||||||
|
CONF_POE_CLIENTS,
|
||||||
CONF_SITE_ID,
|
CONF_SITE_ID,
|
||||||
CONF_SSID_FILTER,
|
CONF_SSID_FILTER,
|
||||||
CONF_TRACK_CLIENTS,
|
CONF_TRACK_CLIENTS,
|
||||||
|
@ -287,6 +288,7 @@ async def test_option_flow(hass):
|
||||||
user_input={
|
user_input={
|
||||||
CONF_BLOCK_CLIENT: clients_to_block,
|
CONF_BLOCK_CLIENT: clients_to_block,
|
||||||
CONF_NEW_CLIENT: "00:00:00:00:00:01",
|
CONF_NEW_CLIENT: "00:00:00:00:00:01",
|
||||||
|
CONF_POE_CLIENTS: False,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -327,5 +329,6 @@ async def test_option_flow(hass):
|
||||||
CONF_DETECTION_TIME: 100,
|
CONF_DETECTION_TIME: 100,
|
||||||
CONF_SSID_FILTER: ["SSID 1"],
|
CONF_SSID_FILTER: ["SSID 1"],
|
||||||
CONF_BLOCK_CLIENT: ["00:00:00:00:00:01"],
|
CONF_BLOCK_CLIENT: ["00:00:00:00:00:01"],
|
||||||
|
CONF_POE_CLIENTS: False,
|
||||||
CONF_ALLOW_BANDWIDTH_SENSORS: True,
|
CONF_ALLOW_BANDWIDTH_SENSORS: True,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue