1
0
mirror of https://github.com/home-assistant/core.git synced 2026-07-02 12:17:30 +01:00
Files
core/homeassistant/components/opnsense/device_tracker.py
T
Kevin McCormack e02ea041b7 Add config flow for OPNsense (#151121)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
Co-authored-by: Philippe Lafoucrière <12752+gravis@users.noreply.github.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: Robert Resch <robert@resch.dev>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ariel Ebersberger <ariel@ebersberger.io>
2026-05-27 10:15:16 +02:00

118 lines
3.8 KiB
Python

"""Device tracker support for OPNsense routers."""
from typing import Any
from homeassistant.components.device_tracker import ScannerEntity
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .coordinator import OPNsenseDeviceTrackerCoordinator
from .types import DeviceDetails, OPNsenseConfigEntry
async def async_setup_entry(
hass: HomeAssistant,
entry: OPNsenseConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up device tracker for OPNsense component."""
client = entry.runtime_data.client
interfaces = entry.runtime_data.tracker_interfaces
coordinator = OPNsenseDeviceTrackerCoordinator(hass, entry, client, interfaces)
def _async_add_new_entities() -> None:
"""Add entities for newly discovered devices."""
if not coordinator.data:
return
entities = []
for mac_address in coordinator.data:
if mac_address in coordinator.tracked_devices:
continue
entity = OPNsenseDeviceTrackerEntity(coordinator, mac_address)
coordinator.tracked_devices.add(mac_address)
entities.append(entity)
if entities:
async_add_entities(entities)
entry.async_on_unload(coordinator.async_add_listener(_async_add_new_entities))
# Initial data fetch
await coordinator.async_config_entry_first_refresh()
_async_add_new_entities()
class OPNsenseDeviceTrackerEntity(
CoordinatorEntity[OPNsenseDeviceTrackerCoordinator], ScannerEntity
):
"""Representation of a tracked device."""
def __init__(
self,
coordinator: OPNsenseDeviceTrackerCoordinator,
mac_address: str,
) -> None:
"""Initialize the device tracker entity."""
super().__init__(coordinator)
self._attr_mac_address = mac_address
@property
def device_data(self) -> DeviceDetails | None:
"""Return device data for current device."""
if self.coordinator.data and self.mac_address in self.coordinator.data:
return self.coordinator.data[self.mac_address]
return None
@property
def is_connected(self) -> bool:
"""Return true if the device is connected to the network."""
return (
self.coordinator.data is not None
and self.mac_address in self.coordinator.data
)
@property
def name(self) -> str:
"""Return device name."""
device_data = self.device_data
if device_data and device_data.get("hostname"):
return str(device_data["hostname"])
return f"OPNsense {self.mac_address}"
@property
def ip_address(self) -> str | None:
"""Return the primary IP address of the device."""
device_data = self.device_data
if device_data:
return device_data.get("ip")
return None
@property
def hostname(self) -> str | None:
"""Return hostname of the device."""
device_data = self.device_data
if device_data:
hostname = device_data.get("hostname")
return hostname or None
return None
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes."""
device_data = self.device_data
if not device_data:
return {}
attrs = {}
if manufacturer := device_data.get("manufacturer"):
attrs["manufacturer"] = manufacturer
if interface := device_data.get("intf_description"):
attrs["interface"] = interface
if expires := device_data.get("expires"):
attrs["expires"] = expires
return attrs