Skip to content

Commit

Permalink
Merge pull request #214 from Snuffy2/Sort-Device-Tracker-Selector
Browse files Browse the repository at this point in the history
Sort Device Tracker Selector
  • Loading branch information
alexdelprete authored Sep 27, 2024
2 parents 71b06a7 + 2035e05 commit 745ea74
Showing 1 changed file with 38 additions and 12 deletions.
50 changes: 38 additions & 12 deletions custom_components/opnsense/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Config flow for OPNsense integration."""

from collections.abc import Mapping
import ipaddress
import logging
from typing import Any
from urllib.parse import quote_plus, urlparse
Expand Down Expand Up @@ -40,6 +41,14 @@
_LOGGER = logging.getLogger(__name__)


def is_ip_address(value) -> bool:
try:
ipaddress.ip_address(value)
return True
except ValueError:
return False


def cleanse_sensitive_data(message, secrets=[]):
for secret in secrets:
if secret is not None:
Expand Down Expand Up @@ -245,9 +254,11 @@ async def async_step_init(self, user_input=None):
async def async_step_device_tracker(self, user_input=None):
"""Handle device tracker list step."""
url = self.config_entry.data[CONF_URL].strip()
username = self.config_entry.data.get(CONF_USERNAME, DEFAULT_USERNAME)
password = self.config_entry.data[CONF_PASSWORD]
verify_ssl = self.config_entry.data.get(CONF_VERIFY_SSL, DEFAULT_VERIFY_SSL)
username: str = self.config_entry.data.get(CONF_USERNAME, DEFAULT_USERNAME)
password: str = self.config_entry.data[CONF_PASSWORD]
verify_ssl: bool = self.config_entry.data.get(
CONF_VERIFY_SSL, DEFAULT_VERIFY_SSL
)
client = OPNsenseClient(
url=url,
username=username,
Expand All @@ -256,32 +267,47 @@ async def async_step_device_tracker(self, user_input=None):
opts={"verify_ssl": verify_ssl},
)
if user_input is None and (arp_table := await client.get_arp_table(True)):
selected_devices = self.config_entry.options.get(CONF_DEVICES, [])
selected_devices: list = self.config_entry.options.get(CONF_DEVICES, [])

# dicts are ordered so put all previously selected items at the top
entries = {}
entries: Mapping[str, Any] = {}
for device in selected_devices:
entries[device] = device

# follow with all arp table entries
for entry in arp_table:
mac: str = entry.get("mac", "").lower()
mac: str = entry.get("mac", "").lower().strip()
if len(mac) < 1:
continue

hostname: str = entry.get("hostname", "").strip("?")
ip: str = entry.get("ip", "")

label: str = f"{mac} - {hostname.strip()} ({ip.strip()})"
hostname: str = entry.get("hostname", "").strip("?").strip()
ip: str = entry.get("ip", "").strip()
label: str = f"{ip} {'('+hostname+') ' if hostname else ''}[{mac}]"
entries[mac] = label

sorted_entries: Mapping[str, Any] = {
key: value
for key, value in sorted(
entries.items(),
key=lambda item: (
(
0 if not is_ip_address(item[1].split()[0]) else 1
), # Sort MAC address only labels first
(
item[1].split()[0]
if not is_ip_address(item[1].split()[0])
else ipaddress.ip_address(item[1].split()[0])
),
),
)
}

return self.async_show_form(
step_id="device_tracker",
data_schema=vol.Schema(
{
vol.Optional(
CONF_DEVICES, default=selected_devices
): cv.multi_select(entries),
): cv.multi_select(sorted_entries),
}
),
)
Expand Down

0 comments on commit 745ea74

Please sign in to comment.