mirror of
https://github.com/home-assistant/core.git
synced 2025-12-19 18:38:58 +00:00
Add strict typing, shared constants, and fix OPNsense name casing (#151599)
This commit is contained in:
@@ -383,6 +383,7 @@ homeassistant.components.openai_conversation.*
|
||||
homeassistant.components.openexchangerates.*
|
||||
homeassistant.components.opensky.*
|
||||
homeassistant.components.openuv.*
|
||||
homeassistant.components.opnsense.*
|
||||
homeassistant.components.opower.*
|
||||
homeassistant.components.oralb.*
|
||||
homeassistant.components.otbr.*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Support for OPNSense Routers."""
|
||||
"""Support for OPNsense Routers."""
|
||||
|
||||
import logging
|
||||
|
||||
@@ -12,15 +12,16 @@ from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.discovery import load_platform
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import (
|
||||
CONF_API_SECRET,
|
||||
CONF_INTERFACE_CLIENT,
|
||||
CONF_TRACKER_INTERFACES,
|
||||
DOMAIN,
|
||||
OPNSENSE_DATA,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_API_SECRET = "api_secret"
|
||||
CONF_TRACKER_INTERFACE = "tracker_interfaces"
|
||||
|
||||
DOMAIN = "opnsense"
|
||||
|
||||
OPNSENSE_DATA = DOMAIN
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
@@ -29,7 +30,7 @@ CONFIG_SCHEMA = vol.Schema(
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Required(CONF_API_SECRET): cv.string,
|
||||
vol.Optional(CONF_VERIFY_SSL, default=False): cv.boolean,
|
||||
vol.Optional(CONF_TRACKER_INTERFACE, default=[]): vol.All(
|
||||
vol.Optional(CONF_TRACKER_INTERFACES, default=[]): vol.All(
|
||||
cv.ensure_list, [cv.string]
|
||||
),
|
||||
}
|
||||
@@ -47,7 +48,7 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
api_key = conf[CONF_API_KEY]
|
||||
api_secret = conf[CONF_API_SECRET]
|
||||
verify_ssl = conf[CONF_VERIFY_SSL]
|
||||
tracker_interfaces = conf[CONF_TRACKER_INTERFACE]
|
||||
tracker_interfaces = conf[CONF_TRACKER_INTERFACES]
|
||||
|
||||
interfaces_client = diagnostics.InterfaceClient(
|
||||
api_key, api_secret, url, verify_ssl, timeout=20
|
||||
@@ -72,8 +73,8 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
return False
|
||||
|
||||
hass.data[OPNSENSE_DATA] = {
|
||||
"interfaces": interfaces_client,
|
||||
CONF_TRACKER_INTERFACE: tracker_interfaces,
|
||||
CONF_INTERFACE_CLIENT: interfaces_client,
|
||||
CONF_TRACKER_INTERFACES: tracker_interfaces,
|
||||
}
|
||||
|
||||
load_platform(hass, Platform.DEVICE_TRACKER, DOMAIN, tracker_interfaces, config)
|
||||
|
||||
8
homeassistant/components/opnsense/const.py
Normal file
8
homeassistant/components/opnsense/const.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""Constants for OPNsense component."""
|
||||
|
||||
DOMAIN = "opnsense"
|
||||
OPNSENSE_DATA = DOMAIN
|
||||
|
||||
CONF_API_SECRET = "api_secret"
|
||||
CONF_INTERFACE_CLIENT = "interface_client"
|
||||
CONF_TRACKER_INTERFACES = "tracker_interfaces"
|
||||
@@ -1,34 +1,41 @@
|
||||
"""Device tracker support for OPNSense routers."""
|
||||
"""Device tracker support for OPNsense routers."""
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import Any, NewType
|
||||
|
||||
from pyopnsense import diagnostics
|
||||
|
||||
from homeassistant.components.device_tracker import DeviceScanner
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from . import CONF_TRACKER_INTERFACE, OPNSENSE_DATA
|
||||
from .const import CONF_INTERFACE_CLIENT, CONF_TRACKER_INTERFACES, OPNSENSE_DATA
|
||||
|
||||
DeviceDetails = NewType("DeviceDetails", dict[str, Any])
|
||||
DeviceDetailsByMAC = NewType("DeviceDetailsByMAC", dict[str, DeviceDetails])
|
||||
|
||||
|
||||
async def async_get_scanner(
|
||||
hass: HomeAssistant, config: ConfigType
|
||||
) -> OPNSenseDeviceScanner:
|
||||
"""Configure the OPNSense device_tracker."""
|
||||
interface_client = hass.data[OPNSENSE_DATA]["interfaces"]
|
||||
return OPNSenseDeviceScanner(
|
||||
interface_client, hass.data[OPNSENSE_DATA][CONF_TRACKER_INTERFACE]
|
||||
) -> DeviceScanner | None:
|
||||
"""Configure the OPNsense device_tracker."""
|
||||
return OPNsenseDeviceScanner(
|
||||
hass.data[OPNSENSE_DATA][CONF_INTERFACE_CLIENT],
|
||||
hass.data[OPNSENSE_DATA][CONF_TRACKER_INTERFACES],
|
||||
)
|
||||
|
||||
|
||||
class OPNSenseDeviceScanner(DeviceScanner):
|
||||
"""Class which queries a router running OPNsense."""
|
||||
class OPNsenseDeviceScanner(DeviceScanner):
|
||||
"""This class queries a router running OPNsense."""
|
||||
|
||||
def __init__(self, client, interfaces):
|
||||
def __init__(
|
||||
self, client: diagnostics.InterfaceClient, interfaces: list[str]
|
||||
) -> None:
|
||||
"""Initialize the scanner."""
|
||||
self.last_results = {}
|
||||
self.last_results: dict[str, Any] = {}
|
||||
self.client = client
|
||||
self.interfaces = interfaces
|
||||
|
||||
def _get_mac_addrs(self, devices):
|
||||
def _get_mac_addrs(self, devices: list[DeviceDetails]) -> DeviceDetailsByMAC | dict:
|
||||
"""Create dict with mac address keys from list of devices."""
|
||||
out_devices = {}
|
||||
for device in devices:
|
||||
@@ -36,30 +43,31 @@ class OPNSenseDeviceScanner(DeviceScanner):
|
||||
out_devices[device["mac"]] = device
|
||||
return out_devices
|
||||
|
||||
def scan_devices(self):
|
||||
def scan_devices(self) -> list[str]:
|
||||
"""Scan for new devices and return a list with found device IDs."""
|
||||
self.update_info()
|
||||
return list(self.last_results)
|
||||
|
||||
def get_device_name(self, device):
|
||||
def get_device_name(self, device: str) -> str | None:
|
||||
"""Return the name of the given device or None if we don't know."""
|
||||
if device not in self.last_results:
|
||||
return None
|
||||
return self.last_results[device].get("hostname") or None
|
||||
|
||||
def update_info(self):
|
||||
"""Ensure the information from the OPNSense router is up to date.
|
||||
def update_info(self) -> bool:
|
||||
"""Ensure the information from the OPNsense router is up to date.
|
||||
|
||||
Return boolean if scanning successful.
|
||||
"""
|
||||
|
||||
devices = self.client.get_arp()
|
||||
self.last_results = self._get_mac_addrs(devices)
|
||||
return True
|
||||
|
||||
def get_extra_attributes(self, device):
|
||||
def get_extra_attributes(self, device: str) -> dict[Any, Any]:
|
||||
"""Return the extra attrs of the given device."""
|
||||
if device not in self.last_results:
|
||||
return None
|
||||
if not (mfg := self.last_results[device].get("manufacturer")):
|
||||
return {}
|
||||
mfg = self.last_results[device].get("manufacturer")
|
||||
if not mfg:
|
||||
return {}
|
||||
return {"manufacturer": mfg}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"domain": "opnsense",
|
||||
"name": "OPNSense",
|
||||
"name": "OPNsense",
|
||||
"codeowners": ["@mtreinish"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/opnsense",
|
||||
"iot_class": "local_polling",
|
||||
|
||||
@@ -4736,7 +4736,7 @@
|
||||
}
|
||||
},
|
||||
"opnsense": {
|
||||
"name": "OPNSense",
|
||||
"name": "OPNsense",
|
||||
"integration_type": "hub",
|
||||
"config_flow": false,
|
||||
"iot_class": "local_polling"
|
||||
|
||||
10
mypy.ini
generated
10
mypy.ini
generated
@@ -3586,6 +3586,16 @@ disallow_untyped_defs = true
|
||||
warn_return_any = true
|
||||
warn_unreachable = true
|
||||
|
||||
[mypy-homeassistant.components.opnsense.*]
|
||||
check_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
disallow_subclassing_any = true
|
||||
disallow_untyped_calls = true
|
||||
disallow_untyped_decorators = true
|
||||
disallow_untyped_defs = true
|
||||
warn_return_any = true
|
||||
warn_unreachable = true
|
||||
|
||||
[mypy-homeassistant.components.opower.*]
|
||||
check_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
|
||||
Reference in New Issue
Block a user