"""AsusRouter constants module.""" from __future__ import annotations from collections.abc import Callable from typing import Any from asusrouter.modules.openvpn import AsusOVPNClient, AsusOVPNServer from asusrouter.modules.parental_control import ( AsusBlockAll, AsusParentalControl, ) from asusrouter.modules.port_forwarding import AsusPortForwarding from asusrouter.modules.system import AsusSystem from asusrouter.modules.wireguard import ( AsusWireGuardClient, AsusWireGuardServer, ) from asusrouter.modules.wlan import AsusWLAN, Wlan from asusrouter.tools import converters from homeassistant.components.binary_sensor import BinarySensorDeviceClass from homeassistant.components.button import ButtonDeviceClass from homeassistant.components.sensor import SensorDeviceClass, SensorStateClass from homeassistant.components.update import UpdateDeviceClass from homeassistant.const import ( ATTR_CONNECTIONS, ATTR_IDENTIFIERS, CONF_DEVICES, CONF_PORT, CONF_SCAN_INTERVAL, CONF_UNIQUE_ID, CONF_USERNAME, CONF_VERIFY_SSL, PERCENTAGE, EntityCategory, Platform, UnitOfDataRate, UnitOfInformation, UnitOfTemperature, UnitOfTime, ) from .dataclass import ( ARBinarySensorDescription, ARButtonDescription, AREntityDescription, ARLightDescription, ARSensorDescription, ARSwitchDescription, ARUpdateDescription, ) # INTEGRATION DATA --> ASUSROUTER = "asusrouter" DOMAIN = ASUSROUTER MANUFACTURER = "ASUSTek" PLATFORMS = [ Platform.BINARY_SENSOR, Platform.BUTTON, Platform.DEVICE_TRACKER, Platform.LIGHT, Platform.SENSOR, Platform.SWITCH, Platform.UPDATE, ] # <-- INTEGRATION DATA # NUMERIC --> NUMERIC_CORES = range(1, 9) # maximum of 8 cores from 1 to 8 NUMERIC_GWLAN = range(1, 4) # maximum of 4 guest WLANs from 1 to 3 NUMERIC_LAN = range(1, 9) # maximum of 8 LAN ports from 1 to 8 NUMERIC_OVPN_SERVER = range(1, 3) # maximum of 2 OVPN servers from 1 to 2 NUMERIC_WAN = range(4) # maximum of 4 WAN ports from 0 to 3 NUMERIC_WLAN = range(4) # maximum of 4 WLANs from 0 to 3 # <-- NUMERIC # GENERAL DATA --> ACCESS_POINT = "access_point" ACTION = "action" ACTION_MODE = "action_mode" AIMESH = "aimesh" ALIAS = "alias" ALL_CLIENTS = "all_clients" API_ID = "api_id" API_TYPE = "api_type" APPLY = "apply" AURA = "aura" BITS_PER_SECOND = "bits/s" BOOTTIME = "boottime" BRIDGE = "bridge" BYTES = "bytes" CONFIG = "config" CONNECTION = "connection" COORDINATOR = "coordinator" CORE = "core" CPU = "cpu" DDNS = "ddns" DEVICES = "devices" DNS = "dns" DSL = "dsl" FIRMWARE = "firmware" FREE = "free" GWLAN = "gwlan" HTTP = "http" HTTPS = "https" IP = "ip" IP_EXTERNAL = "ip_external" IPS = "ips" ISO = "iso" LACP = "lacp" LAN = "lan" LED = "led" LEVEL = "level" LIGHT = "light" LIST = "list" LOAD_AVG = "load_avg" MAC = "mac" MEDIA_BRIDGE = "media_bridge" METHOD = "method" MISC = "misc" MODEL = "model" NAME = "name" NETWORK = "network" NETWORK_STAT = "network_stat" NEXT = "next" NODE = "node" NO_SSL = "no_ssl" NUMBER = "number" PARENT = "parent" PARENTAL_CONTROL = "parental_control" PASSWORD = "password" # noqa: S105 PORT = "port" PORT_EXTERNAL = "port_external" PORT_FORWARDING = "port_forwarding" PORTS = "ports" PRODUCT_ID = "product_id" PROTOCOL = "protocol" RAM = "ram" ROUTER = "router" RX = "rx" RX_SPEED = "rx_speed" SENSORS = "sensors" SSID = "ssid" SSL = "ssl" STATE = "state" STATUS = "status" SYSINFO = "sysinfo" TEMPERATURE = "temperature" TIMESTAMP = "timestamp" TOTAL = "total" TX = "tx" TX_SPEED = "tx_speed" TYPE = "type" UNIQUE_ID = "unique_id" UNKNOWN = "unknown" USAGE = "usage" USB = "usb" USED = "used" VPN = "vpn" WAN = "wan" WIRED = "wired" WLAN = "wlan" WLAN_2GHZ = "2ghz" WLAN_5GHZ = "5ghz" WLAN_5GHZ2 = "5ghz2" WLAN_6GHZ = "6ghz" # <-- GENERAL DATA LIST_PORTS = [ LAN, USB, WAN, ] MAP_WLAN = { WLAN_2GHZ: 0, WLAN_5GHZ: 1, WLAN_5GHZ2: 2, WLAN_6GHZ: 3, } # MIGRATION TEMP --> MAP_NETWORK_TEMP = { BRIDGE.upper(): BRIDGE, USB.upper(): USB, WAN.upper(): WAN, WIRED.upper(): WIRED, "WLAN0": WLAN_2GHZ, "WLAN1": WLAN_5GHZ, "WLAN2": WLAN_5GHZ2, "WLAN3": WLAN_6GHZ, } # <-- MIGRATION TEMP # GENERAL STATES --> CONNECTED = "connected" # <-- GENERAL STATES # LABELS --> CONNECTION_2G = "2.4 GHz" CONNECTION_5G = "5 GHz" CONNECTION_5G2 = "5 GHz-2" CONNECTION_6G = "6 GHz" CONNECTION_LIST = [ CONNECTION_2G, CONNECTION_5G, CONNECTION_5G2, CONNECTION_6G, ] CONNECTION_WIRED = "Wired" LABEL_LOAD_AVG = "Load Average" LABEL_RX = "Download" LABEL_SPEED = "Speed" LABEL_TEMPERATURE = "Temperature" LABEL_TX = "Upload" LABEL_WLAN = "Wireless" LABEL_WLAN_2GHZ = "2.4 GHz" LABEL_WLAN_5GHZ = "5 GHz" LABEL_WLAN_5GHZ2 = "5 GHz-2" LABEL_WLAN_6GHZ = "6 GHz" LABELS_LOAD_AVG = { sensor: f"{LABEL_LOAD_AVG} ({sensor} min)" for sensor in ("1", "5", "15") } LABELS_TEMPERATURE = { "cpu": "Temperature CPU", Wlan.FREQ_2G: "Temperature 2.4 GHz", Wlan.FREQ_5G: "Temperature 5 GHz", Wlan.FREQ_5G2: "Temperature 5 GHz-2", Wlan.FREQ_6G: "Temperature 6 GHz", } LABELS_WLAN = { WLAN_2GHZ: LABEL_WLAN_2GHZ, WLAN_5GHZ: LABEL_WLAN_5GHZ, WLAN_5GHZ2: LABEL_WLAN_5GHZ2, WLAN_6GHZ: LABEL_WLAN_6GHZ, } # <-- LABELS # MODES --> # AiMesh Node MODE_NODE = [ BOOTTIME, CPU, FIRMWARE, LED, NETWORK, PORTS, RAM, SYSINFO, TEMPERATURE, ] # Access Point MODE_ACCESS_POINT = MODE_NODE.copy() MODE_ACCESS_POINT.extend([WLAN, AURA]) # Media Bridge MODE_MEDIA_BRIDGE = MODE_ACCESS_POINT.copy() # Router MODE_ROUTER = MODE_ACCESS_POINT.copy() MODE_ROUTER.extend( [ DDNS, DSL, GWLAN, "ovpn_client", "ovpn_server", PARENTAL_CONTROL, PORT_FORWARDING, VPN, "wan", "wireguard_client", "wireguard_server", ] ) MODE_SENSORS = { ACCESS_POINT: MODE_ACCESS_POINT, MEDIA_BRIDGE: MODE_MEDIA_BRIDGE, NODE: MODE_NODE, ROUTER: MODE_ROUTER, } # <-- MODES # SENSORS LIST --> SENSORS_AIMESH = [NUMBER, LIST] SENSORS_BOOTTIME = ["datetime", "uptime"] SENSORS_CHANGE = ["change"] SENSORS_CONNECTED_DEVICES = [ NUMBER, DEVICES, "latest", "latest_time", "gn_number", ] SENSORS_CPU = [TOTAL, USED, USAGE] SENSORS_FIRMWARE = [STATE, "state_beta"] SENSORS_GWLAN = { "sync_node": "aimesh_sync", "auth_mode_x": "auth_method", "bw_enabled": "bw_limit", "bw_dl": "bw_limit_download", "bw_ul": "bw_limit_upload", "expire": "expire", "expire_tmp": "expire_in", "closed": "hidden", "lanaccess": "lan_access", "maclist": "maclist", "macmode": "macmode", "wpa_psk": PASSWORD, SSID: SSID, "crypto": "wpa_encryption", } SENSORS_LED = [STATE] SENSORS_MISC = [BOOTTIME] SENSORS_NETWORK = [RX, RX_SPEED, TX, TX_SPEED] SENSORS_OVPN_CLIENT = { "active": "active", "auth_read": "auth_read", "datetime": "update_time", "errno": "error", "error": "error", IP: "local_ip", "login": "login", "name": "name", "password": "password", "post_compress": "post_compress_bytes", "post_decompress": "post_decompress_bytes", "pre_compress": "pre_compress_bytes", "pre_decompress": "pre_decompress_bytes", "rip": "public_ip", "remote_auth": "server_auth", "remote_ip": "server_ip", "remote_port": "server_port", STATUS: STATUS, "tcp_udp_read": "tcp_udp_read_bytes", "tcp_udp_write": "tcp_udp_write_bytes", "tun_tap_read": "tun_tap_read_bytes", "tun_tap_write": "tun_tap_write_bytes", "vpnc_id": "vpnc_id", "vpnc_unit": "vpnc_unit", } SENSORS_OVPN_SERVER = { "address": "address", "advertise_dns": "advertise_dns", "allow_lan": "allow_lan", "allow_specific_clients": "allow_specific_clients", "allow_wan": "allow_wan", "auth_mode": "auth_mode", "cipher": "cipher", "client_list": "clients", "client_specific_config": "client_specific_config", "client_to_client": "client_to_client", "clients": "clients", "compression": "compression", "dhcp": "dhcp", "digest": "digest", "hmac": "hmac", "interface": "interface", "netmask": "netmask", "password_only": "password_only", "port": "port", "protocol": "protocol", "remote_address": "remote_address", "response_to_dns": "response_to_dns", "routing_table": "routing_table", "server_r1": "server_r1", "server_r2": "server_r2", "subnet": "subnet", "tls_keysize": "tls_keysize", "tls_reneg": "tls_reneg", "unit": "unit", } SENSORS_PARENTAL_CONTROL = ["block_all", STATE] SENSORS_PORT_FORWARDING = [STATE] SENSORS_PORTS = [LAN, WAN] SENSORS_RAM = [FREE, TOTAL, USAGE, USED] SENSORS_SYSINFO = [f"{LOAD_AVG}_{sensor}" for sensor in LABELS_LOAD_AVG] SENSORS_WAN = { "dns": "dns", "expires": "expires", "gateway": "gateway", "ip_address": "ip_address", "lease": "lease", "mask": "mask", } SENSORS_WIREGUARD_CLIENT = { "active": "active", "address": "address", "allowed_ips": "allowed_ips", "endpoint_address": "endpoint_address", "endpoint_port": "endpoint_port", "error": "error", "keep_alive": "keep_alive", "login": "login", "name": "name", "nat": "nat", "password": "password", "private_key": "private_key", "psk": "psk", "public_key": "public_key", "vpnc_id": "vpnc_id", "vpnc_unit": "vpnc_unit", } SENSORS_WIREGUARD_SERVER = { "address": "address", "dns": "dns", "keep_alive": "keep_alive", "lan_access": "lan_access", "nat6": "nat6", "port": "port", "private_key": "private_key", "psk": "psk_state", "public_key": "public_key", "clients": "clients", } SENSORS_WLAN = { "auth_mode_x": "auth_method", "channel": "channel", "bw": "channel_bandwidth", "chanspec": "chanspec", "country_code": "country_code", "gmode_check": "gmode_check", "wpa_gtk_rekey": "group_key_rotation", "closed": "hidden", "maclist_x": "maclist_x", "macmode": "macmode", "mbo_enable": "mbo_enable", "mfp": "mfp", "nmode_x": "mode", "wpa_psk": PASSWORD, "radius_ipaddr": "radius_ipaddr", "radius_key": "radius_key", "radius_port": "radius_port", SSID: SSID, "crypto": "wpa_encryption", "optimizexbox_ckb": "xbox_optimized", } # Defaults DEFAULT_SENSORS: dict[str, list[str]] = {CPU: [TOTAL]} # <-- SENSORS # CONFIGURATION CONSTANTS & DEFAULTS --> # Keys CONF_CACHE_TIME = "cache_time" CONF_CERT_PATH = "cert_path" CONF_CLIENT_DEVICE = "client_device" CONF_CLIENT_FILTER = "client_filter" CONF_CLIENT_FILTER_LIST = "client_filter_list" CONF_CLIENTS_IN_ATTR = "clients_in_attr" CONF_CONFIRM = "confirm" CONF_CONSIDER_HOME = "consider_home" CONF_CREATE_DEVICES = "create_devices" CONF_ENABLE_CONTROL = "enable_control" CONF_EVENT_DEVICE_CONNECTED = "device_connected" CONF_EVENT_DEVICE_DISCONNECTED = "device_disconnected" CONF_EVENT_DEVICE_RECONNECTED = "device_reconnected" CONF_EVENT_NODE_CONNECTED = "node_connected" CONF_EVENT_NODE_DISCONNECTED = "node_disconnected" CONF_EVENT_NODE_RECONNECTED = "node_reconnected" CONF_HIDE_PASSWORDS = "hide_passwords" CONF_INTERFACES = "interfaces" CONF_INTERVAL = "interval_" CONF_INTERVAL_DEVICES = CONF_INTERVAL + DEVICES CONF_INTERVALS = [ CONF_INTERVAL + CPU, CONF_INTERVAL + FIRMWARE, CONF_INTERVAL + GWLAN, CONF_INTERVAL + LIGHT, CONF_INTERVAL + MISC, CONF_INTERVAL + NETWORK, CONF_INTERVAL + PARENTAL_CONTROL, CONF_INTERVAL + PORTS, CONF_INTERVAL + RAM, CONF_INTERVAL + SYSINFO, CONF_INTERVAL + TEMPERATURE, CONF_INTERVAL + VPN, CONF_INTERVAL + WAN, CONF_INTERVAL + WLAN, ] CONF_LATEST_CONNECTED = "latest_connected" CONF_MODE = "mode" CONF_SPLIT_INTERVALS = "split_intervals" CONF_TRACK_DEVICES = "track_devices" CONF_UNITS = "units" CONF_UNITS_SPEED = "units_speed" CONF_UNITS_TRAFFIC = "units_traffic" # Defaults CONF_DEFAULT_CACHE_TIME = 5 CONF_DEFAULT_CLIENT_DEVICE = False CONF_DEFAULT_CLIENT_FILTER = "no_filter" CONF_DEFAULT_CLIENTS_IN_ATTR = True CONF_DEFAULT_CONSIDER_HOME = 45 CONF_DEFAULT_CREATE_DEVICES = False CONF_DEFAULT_ENABLE_CONTROL = False CONF_DEFAULT_EVENT: dict[str, bool] = { CONF_EVENT_DEVICE_CONNECTED: True, CONF_EVENT_DEVICE_DISCONNECTED: False, CONF_EVENT_DEVICE_RECONNECTED: False, CONF_EVENT_NODE_CONNECTED: True, CONF_EVENT_NODE_DISCONNECTED: True, CONF_EVENT_NODE_RECONNECTED: True, } CONF_DEFAULT_HIDE_PASSWORDS = False CONF_DEFAULT_INTERFACES = [WAN.upper()] CONF_DEFAULT_INTERVALS = {CONF_INTERVAL + FIRMWARE: 600} CONF_DEFAULT_LATEST_CONNECTED = 5 CONF_DEFAULT_MODE = ROUTER CONF_DEFAULT_PORT = 0 CONF_DEFAULT_PORTS = {NO_SSL: 80, SSL: 8443} CONF_DEFAULT_SCAN_INTERVAL = 30 CONF_DEFAULT_SPLIT_INTERVALS = False CONF_DEFAULT_SSL = True CONF_DEFAULT_TRACK_DEVICES = True CONF_DEFAULT_UNITS_SPEED = UnitOfDataRate.MEGABITS_PER_SECOND CONF_DEFAULT_UNITS_TRAFFIC = UnitOfInformation.GIGABYTES CONF_DEFAULT_USERNAME = "admin" # Labels CONF_LABELS_CLIENT_FILTER = { "no_filter": "No filter / All clients", "include": "Include only", "exclude": "Exclude devices", } CONF_LABELS_INTERFACES = { BRIDGE: "Bridge", f"{LACP}1": "LACP1", f"{LACP}2": "LACP2", USB: USB.upper(), WAN: WAN.upper(), WIRED: CONNECTION_WIRED, WLAN_2GHZ: CONNECTION_2G, WLAN_5GHZ: CONNECTION_5G, WLAN_5GHZ2: CONNECTION_5G2, WLAN_6GHZ: CONNECTION_6G, } CONF_LABELS_MODE = { ROUTER: "Router", NODE: "AiMesh node", ACCESS_POINT: "Access Point", MEDIA_BRIDGE: "Media bridge", } # Options that require restarting the integration CONF_REQ_RELOAD = [ CONF_CACHE_TIME, CONF_CERT_PATH, CONF_CLIENT_DEVICE, CONF_CLIENT_FILTER, CONF_CLIENT_FILTER_LIST, CONF_CLIENTS_IN_ATTR, CONF_CONFIRM, CONF_CONSIDER_HOME, CONF_CREATE_DEVICES, CONF_ENABLE_CONTROL, CONF_EVENT_DEVICE_CONNECTED, CONF_EVENT_DEVICE_DISCONNECTED, CONF_EVENT_DEVICE_RECONNECTED, CONF_EVENT_NODE_CONNECTED, CONF_EVENT_NODE_DISCONNECTED, CONF_EVENT_NODE_RECONNECTED, CONF_HIDE_PASSWORDS, CONF_INTERFACES, CONF_INTERVAL_DEVICES, CONF_LATEST_CONNECTED, CONF_MODE, CONF_SPLIT_INTERVALS, CONF_SCAN_INTERVAL, CONF_TRACK_DEVICES, ] CONF_REQ_RELOAD.extend(CONF_INTERVALS) # Input values CONF_VALUES_DATA = [ UnitOfInformation.BITS, UnitOfInformation.KILOBITS, UnitOfInformation.MEGABITS, UnitOfInformation.GIGABITS, UnitOfInformation.BYTES, UnitOfInformation.KILOBYTES, UnitOfInformation.MEGABYTES, UnitOfInformation.GIGABYTES, ] CONF_VALUES_DATARATE = [ UnitOfDataRate.BITS_PER_SECOND, UnitOfDataRate.KILOBITS_PER_SECOND, UnitOfDataRate.MEGABITS_PER_SECOND, UnitOfDataRate.GIGABITS_PER_SECOND, UnitOfDataRate.BYTES_PER_SECOND, UnitOfDataRate.KILOBYTES_PER_SECOND, UnitOfDataRate.MEGABYTES_PER_SECOND, UnitOfDataRate.GIGABYTES_PER_SECOND, ] CONF_VALUES_MODE = [ ROUTER, NODE, ACCESS_POINT, MEDIA_BRIDGE, ] # Defaults DEFAULT_DEVICE_NAME = "Unknown device" DEFAULT_HTTP = {NO_SSL: HTTP, SSL: HTTPS} DEFAULT_VERIFY_SSL = True # Simplified setup SIMPLE_SETUP_PARAMETERS = { SSL: { CONF_PORT: CONF_DEFAULT_PORTS[SSL], CONF_VERIFY_SSL: DEFAULT_VERIFY_SSL, CONF_CERT_PATH: "", }, NO_SSL: { CONF_PORT: CONF_DEFAULT_PORTS[NO_SSL], CONF_VERIFY_SSL: DEFAULT_VERIFY_SSL, CONF_CERT_PATH: "", }, } # Types of steps STEP_TYPE_COMPLETE = "complete" STEP_TYPE_SIMPLE = "simplified" # Types of results on actions RESULT_CONNECTION_REFUSED = "connection_refused" RESULT_ERROR = "error" RESULT_LOGIN_BLOCKED = "login_blocked" RESULT_SUCCESS = "success" RESULT_UNKNOWN = "unknown" RESULT_WRONG_CREDENTIALS = "wrong_credentials" # <-- CONFIGURATION # CONSTANTS & CONVERTERS --> CONVERT_SPEED = { UnitOfDataRate.BITS_PER_SECOND: 1, UnitOfDataRate.KILOBITS_PER_SECOND: 1024, UnitOfDataRate.MEGABITS_PER_SECOND: 1048576, UnitOfDataRate.GIGABITS_PER_SECOND: 1073741824, UnitOfDataRate.BYTES_PER_SECOND: 8, UnitOfDataRate.KILOBYTES_PER_SECOND: 8192, UnitOfDataRate.MEGABYTES_PER_SECOND: 8388608, UnitOfDataRate.GIGABYTES_PER_SECOND: 8589934592, } CONVERT_TRAFFIC = { UnitOfInformation.BITS: 0.125, UnitOfInformation.KILOBITS: 128, UnitOfInformation.MEGABITS: 131072, UnitOfInformation.GIGABITS: 134217728, UnitOfInformation.BYTES: 1, UnitOfInformation.KILOBYTES: 1024, UnitOfInformation.MEGABYTES: 1048576, UnitOfInformation.GIGABYTES: 1073741824, } # <-- CONSTANTS & CONVERTERS # MISC --> # Connection state CONNECTION_BLOCKED = "blocked" CONNECTION_CONNECTED = "connected" CONNECTION_DISCONNECTED = "disconnected" # Connection type CONNECTION_TYPE_2G = CONNECTION_2G CONNECTION_TYPE_5G = CONNECTION_5G CONNECTION_TYPE_5G2 = CONNECTION_5G2 CONNECTION_TYPE_6G = CONNECTION_6G CONNECTION_TYPE_WIRED = CONNECTION_WIRED CONNECTION_TYPE_UNKNOWN = UNKNOWN # Device attributes DEVICE_ATTRIBUTE_CONNECTION_TIME = "connection_time" DEVICE_ATTRIBUTE_CONNECTION_TYPE = "connection_type" DEVICE_ATTRIBUTE_GUEST = "guest" DEVICE_ATTRIBUTE_GUEST_ID = "guest_id" DEVICE_ATTRIBUTE_INTERNET = "internet" DEVICE_ATTRIBUTE_INTERNET_MODE = "internet_mode" DEVICE_ATTRIBUTE_IP_TYPE = "ip_type" DEVICE_ATTRIBUTE_LAST_ACTIVITY = "last_activity" DEVICE_ATTRIBUTE_RSSI = "rssi" DEVICE_ATTRIBUTE_RX_SPEED = RX_SPEED DEVICE_ATTRIBUTE_TX_SPEED = TX_SPEED DEVICE_ATTRIBUTES: list[str] = [ DEVICE_ATTRIBUTE_CONNECTION_TIME, DEVICE_ATTRIBUTE_CONNECTION_TYPE, DEVICE_ATTRIBUTE_GUEST, DEVICE_ATTRIBUTE_INTERNET, DEVICE_ATTRIBUTE_INTERNET_MODE, DEVICE_ATTRIBUTE_IP_TYPE, DEVICE_ATTRIBUTE_RSSI, DEVICE_ATTRIBUTE_RX_SPEED, DEVICE_ATTRIBUTE_TX_SPEED, ] # Generate wireless networks NAME_GWLAN = {} NAME_WLAN = {} for i in NUMERIC_WLAN: # WLAN NAME_WLAN[i] = f"Wireless {CONNECTION_LIST[i]}" # Guest WLAN for j in NUMERIC_GWLAN: NAME_GWLAN[f"{i}.{j}"] = f"Guest {CONNECTION_LIST[i]} {j}" SENSORS_PARAM: dict[str, dict[str, Any]] = { "key": {}, "key_group": {}, NAME: {}, "icon": {}, "state_class": {}, "native_unit_of_measurement": {}, "factor": {}, "entity_registry_enabled_default": {}, "extra_state_attributes": {}, } SENSORS_PARAM_NETWORK: dict[str, dict[str, Any]] = { RX: { NAME: f"{LABEL_RX}", "icon": "mdi:download-outline", "state_class": SensorStateClass.TOTAL_INCREASING, "device_class": SensorDeviceClass.DATA_SIZE, "native_unit_of_measurement": UnitOfInformation.BYTES, "suggested_unit_of_measurement": UnitOfInformation.GIGABYTES, "suggested_display_precision": 3, "entity_registry_enabled_default": True, }, RX_SPEED: { NAME: f"{LABEL_RX} {LABEL_SPEED}", "icon": "mdi:download-network-outline", "state_class": SensorStateClass.MEASUREMENT, "device_class": SensorDeviceClass.DATA_RATE, "native_unit_of_measurement": UnitOfDataRate.BITS_PER_SECOND, "suggested_unit_of_measurement": UnitOfDataRate.MEGABITS_PER_SECOND, "suggested_display_precision": 3, "entity_registry_enabled_default": True, }, TX: { NAME: f"{LABEL_TX}", "icon": "mdi:upload-outline", "state_class": SensorStateClass.TOTAL_INCREASING, "device_class": SensorDeviceClass.DATA_SIZE, "native_unit_of_measurement": UnitOfInformation.BYTES, "suggested_unit_of_measurement": UnitOfInformation.GIGABYTES, "suggested_display_precision": 3, "entity_registry_enabled_default": True, }, TX_SPEED: { NAME: f"{LABEL_TX} {LABEL_SPEED}", "icon": "mdi:upload-network-outline", "state_class": SensorStateClass.MEASUREMENT, "device_class": SensorDeviceClass.DATA_RATE, "native_unit_of_measurement": UnitOfDataRate.BITS_PER_SECOND, "suggested_unit_of_measurement": UnitOfDataRate.MEGABITS_PER_SECOND, "suggested_display_precision": 3, "entity_registry_enabled_default": True, }, } # <-- MISC # DIAGNOSTICS --> TO_REDACT: list[str] = [PASSWORD, CONF_UNIQUE_ID, CONF_USERNAME] TO_REDACT_DEV: list[str] = [ATTR_CONNECTIONS, ATTR_IDENTIFIERS] TO_REDACT_STATE: list[str] = ["WAN IP"] TO_REDACT_ATTRS: list[str] = [ CONF_DEVICES, PASSWORD, IP, SSID, LIST, "private_key", "psk", ] # <-- DIAGNOSTICS # SERVICES --> SERVICE_ALLOWED_ADJUST_GWLAN: dict[str, Callable | None] = { "sync_node": converters.safe_int, "bw_enabled": converters.safe_int, "bw_dl": None, "bw_ul": None, "expire": None, "closed": converters.safe_int, "lanaccess": converters.safe_int, SSID: None, } SERVICE_ALLOWED_ADJUST_WLAN: dict[str, Callable | None] = { "closed": converters.safe_int, SSID: None, } SERVICE_ALLOWED_DEVICE_INTERNET_ACCCESS: list[str] = [ "block", "disable", ] SERVICE_ALLOWED_PORT_FORWARDING_ACTION: list[str] = [ "remove_ip", "remove", "set", ] SERVICE_ALLOWED_PORT_FORWARDING_PROTOCOL: list[str] = [ "TCP", "UDP", "BOTH", ] # <-- SERVICES # ICONS --> ICON_CPU = "mdi:cpu-32-bit" ICON_DDNS = "mdi:dns-outline" ICON_DEVICES = "mdi:devices" ICON_DUALWAN = "mdi:call-split" ICON_ETHERNET_ON = "mdi:ethernet-cable" ICON_ETHERNET_OFF = "mdi:ethernet-cable-off" ICON_INTERNET_ACCESS_OFF = "mdi:lock-outline" ICON_INTERNET_ACCESS_ON = "mdi:lock-open-variant-outline" ICON_IP = "mdi:ip" ICON_LIGHT_OFF = "mdi:led-off" ICON_LIGHT_ON = "mdi:led-on" ICON_PARENTAL_CONTROL_OFF = "mdi:magnify" ICON_PARENTAL_CONTROL_ON = "mdi:magnify-expand" ICON_PORT_FORWARDING_OFF = "mdi:lan-disconnect" ICON_PORT_FORWARDING_ON = "mdi:lan-connect" ICON_RAM = "mdi:memory" ICON_RESTART = "mdi:restart" ICON_ROUTER = "mdi:router-network" ICON_TEMPERATURE = "mdi:thermometer" ICON_UPDATE = "mdi:update" ICON_USB = "mdi:usb-port" ICON_VPN_OFF = "mdi:close-network-outline" ICON_VPN_ON = "mdi:check-network-outline" ICON_WAN_AGGREGATION = "mdi:call-merge" ICON_WLAN_OFF = "mdi:wifi-off" ICON_WLAN_ON = "mdi:wifi" # <-- ICONS # SENSORS --> STATIC_BINARY_SENSORS: list[AREntityDescription] = [ # DDNS ARBinarySensorDescription( key="state", key_group="ddns", name="DDNS", icon=ICON_DDNS, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, extra_state_attributes={ "enabled": "enabled", "hostname": "hostname", "ip_address": "ip_address", "old_name": "old_name", "replace_status": "replace_status", "return_code": "return_code", "server": "server", "status": "status", "status_hint": "status_hint", "updated": "updated", }, ), # Dual WAN ARBinarySensorDescription( key="dualwan_state", key_group="wan", name="Dual WAN", icon=ICON_DUALWAN, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, extra_state_attributes={ "dualwan_mode": "mode", "dualwan_priority": "priority", }, ), # Port status / LAN ARBinarySensorDescription( key="lan", key_group="ports", name="Port Status (LAN)", icon_on=ICON_ETHERNET_ON, icon_off=ICON_ETHERNET_OFF, entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.CONNECTIVITY, entity_registry_enabled_default=False, extra_state_attributes={ "lan_list": "list", }, ), # Port status / USB ARBinarySensorDescription( key="usb", key_group="ports", name="Port Status (USB)", icon=ICON_USB, entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.CONNECTIVITY, entity_registry_enabled_default=False, extra_state_attributes={ "usb_list": "list", }, ), # Port status / WAN ARBinarySensorDescription( key="wan", key_group="ports", name="Port Status (WAN)", icon_on=ICON_ETHERNET_ON, icon_off=ICON_ETHERNET_OFF, entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.CONNECTIVITY, entity_registry_enabled_default=False, extra_state_attributes={ "wan_list": "list", }, ), # Internet state ARBinarySensorDescription( key="internet_link", key_group="wan", name="Internet", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.CONNECTIVITY, entity_registry_enabled_default=True, extra_state_attributes={ "internet_ip_address": "ip_address", "internet_unit": "wan_unit", }, ), # WAN Aggregation ARBinarySensorDescription( key="aggregation_state", key_group="wan", name="WAN Aggregation", icon=ICON_WAN_AGGREGATION, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, extra_state_attributes={ "aggregation_ports": "ports", }, ), ] STATIC_BINARY_SENSORS.extend( [ # WAN state ARBinarySensorDescription( key=f"{num}_state", key_group="wan", name=f"WAN{label}", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.CONNECTIVITY, entity_registry_enabled_default=False, extra_state_attributes={ f"{num}_link": "link", f"{num}_primary": "primary", }, ) for num, label in zip((0, 1), ("", " (Secondary)")) ] ) STATIC_BUTTONS: list[ARButtonDescription] = [ ARButtonDescription( key="check_update", name="Check for updates", icon=ICON_UPDATE, state=AsusSystem.FIRMWARE_CHECK, entity_registry_enabled_default=True, ), ARButtonDescription( key="reboot", name="Reboot", icon=ICON_RESTART, state=AsusSystem.REBOOT, device_class=ButtonDeviceClass.RESTART, entity_registry_enabled_default=True, ), ARButtonDescription( key="restart_httpd", name="Restart HTTP daemon", icon=ICON_RESTART, state=AsusSystem.RESTART_HTTPD, entity_registry_enabled_default=False, ), ARButtonDescription( key="restart_wired", name="Restart wired", icon=ICON_ETHERNET_ON, state=AsusSystem.RESTART_NET, ), ARButtonDescription( key="restart_wireless", name="Restart wireless", icon=ICON_RESTART, state=AsusSystem.RESTART_WIRELESS, entity_registry_enabled_default=False, ), ] STATIC_BUTTONS_OPTIONAL: list[ARButtonDescription] = [ ARButtonDescription( key="reboot_aimesh", name="Reboot AiMesh", icon=ICON_RESTART, state=AsusSystem.AIMESH_REBOOT, device_class=ButtonDeviceClass.RESTART, entity_registry_enabled_default=True, ), ARButtonDescription( key="rebuild_aimesh", name="Rebuild AiMesh", icon=ICON_DEVICES, state=AsusSystem.AIMESH_REBUILD, device_class=ButtonDeviceClass.RESTART, entity_registry_enabled_default=True, ), ARButtonDescription( key="restart_firewall", name="Restart firewall", icon=ICON_RESTART, state=AsusSystem.RESTART_FIREWALL, entity_registry_enabled_default=False, ), ARButtonDescription( key="refresh_clients", name="Refresh clients", icon=ICON_DEVICES, state=AsusSystem.UPDATE_CLIENTS, entity_registry_enabled_default=True, ), ] STATIC_LIGHTS: list[AREntityDescription] = [ ARLightDescription( key="state", key_group="led", name="LED", icon_on=ICON_LIGHT_ON, icon_off=ICON_LIGHT_OFF, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=True, ), ] STATIC_AURA: list[AREntityDescription] = [ ARLightDescription( key="state", key_group="aura", name="AURA", icon_on=ICON_LIGHT_ON, icon_off=ICON_LIGHT_OFF, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=True, extra_state_attributes={ "brightness": "brightness", "rgb_color": "rgb_color", "zones": "zones", }, ), ] STATIC_SENSORS: list[AREntityDescription] = [ # AiMesh ARSensorDescription( key="number", key_group="aimesh", name="AiMesh", icon=ICON_DEVICES, state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=True, extra_state_attributes={ "list": "list", }, ), # Boottime ARSensorDescription( key="datetime", key_group="boottime", name="Boot Time", icon=ICON_RESTART, device_class=SensorDeviceClass.TIMESTAMP, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, ), ARSensorDescription( key="uptime", key_group="boottime", name="Uptime", icon=ICON_RESTART, state_class=SensorStateClass.TOTAL, device_class=SensorDeviceClass.DURATION, native_unit_of_measurement=UnitOfTime.SECONDS, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, ), # Connected devices ARSensorDescription( key="number", key_group="devices", name="Connected Devices", icon=ICON_ROUTER, state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=True, extra_state_attributes={ "devices": "devices", }, ), # Connected GuestNetwork devices ARSensorDescription( key="gn_number", key_group="devices", name="Connected GuestNetwork Devices", icon=ICON_ROUTER, state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=True, extra_state_attributes={}, ), # CPU ARSensorDescription( key="total_usage", key_group="cpu", name="CPU", icon=ICON_CPU, state_class=SensorStateClass.MEASUREMENT, native_unit_of_measurement=PERCENTAGE, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, extra_state_attributes={ f"{num}_usage": f"core_{num}" for num in NUMERIC_CORES }, ), # DSL ARSensorDescription( key="datarate_up", key_group=DSL, name="DSL Datarate Up", icon="mdi:upload-network-outline", state_class=SensorStateClass.MEASUREMENT, device_class=SensorDeviceClass.DATA_RATE, native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND, suggested_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND, suggested_display_precision=0, entity_registry_enabled_default=True, ), ARSensorDescription( key="datarate_down", key_group=DSL, name="DSL Datarate Down", icon="mdi:download-network-outline", state_class=SensorStateClass.MEASUREMENT, device_class=SensorDeviceClass.DATA_RATE, native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND, suggested_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND, suggested_display_precision=0, entity_registry_enabled_default=True, ), # Latest connected ARSensorDescription( key="latest_time", key_group="devices", name="Latest Connected", icon=ICON_DEVICES, device_class=SensorDeviceClass.TIMESTAMP, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, extra_state_attributes={ "latest": "list", }, ), # RAM ARSensorDescription( key="usage", key_group="ram", name="RAM", icon=ICON_RAM, state_class=SensorStateClass.MEASUREMENT, native_unit_of_measurement=PERCENTAGE, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, extra_state_attributes={ "free": "free", "total": "total", "used": "used", }, ), # WAN IP ARSensorDescription( key="ip_address", key_group="wan", name="WAN IP", icon=ICON_IP, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, extra_state_attributes={ "dns": "dns", "gateway": "gateway", "ip_type": "ip_type", "mask": "mask", "private_subnet": "private_subnet", "xdns": "xdns", "xgateway": "xgateway", "xip": "xip", "xtype": "xip_type", "xmask": "xmask", }, ), ] # Temperature sensors STATIC_SENSORS.extend( [ ARSensorDescription( key=sensor, key_group="temperature", name=label, icon=ICON_TEMPERATURE, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, native_unit_of_measurement=UnitOfTemperature.CELSIUS, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, ) for sensor, label in LABELS_TEMPERATURE.items() ] ) # Load avg sensors STATIC_SENSORS.extend( [ ARSensorDescription( key=f"load_avg_{sensor}", key_group="sysinfo", name=label, icon=ICON_CPU, state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, ) for sensor, label in LABELS_LOAD_AVG.items() ] ) # WAN IPs STATIC_SENSORS.extend( [ ARSensorDescription( key=f"{num}_{extra_key}_ip_address", key_group="wan", name=f"WAN IP{label}{extra_label}", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.CONNECTIVITY, entity_registry_enabled_default=False, extra_state_attributes={ f"{num}_{extra_key}_{key}": attribute for key, attribute in SENSORS_WAN.items() }, ) for extra_key, extra_label in zip(("main", "extra"), ("", " (Extra)")) for num, label in zip((0, 1), ("", " (Secondary)")) ] ) STATIC_SWITCHES: list[AREntityDescription] = [ # Block Internet ARSwitchDescription( key="block_all", key_group="parental_control", name="Block Internet", icon_on=ICON_INTERNET_ACCESS_OFF, state_on=AsusBlockAll.ON, icon_off=ICON_INTERNET_ACCESS_ON, state_off=AsusBlockAll.OFF, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=True, ), # Parental control ARSwitchDescription( key="state", key_group="parental_control", name="Parental control", icon_on=ICON_PARENTAL_CONTROL_ON, state_on=AsusParentalControl.ON, icon_off=ICON_PARENTAL_CONTROL_OFF, state_off=AsusParentalControl.OFF, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=False, extra_state_attributes={ "list": "list", }, ), ] STATIC_SWITCHES.extend( [ # OpenVPN clients ARSwitchDescription( key=f"{num}_state", key_group="ovpn_client", name=f"OpenVPN Client {num}", icon_on=ICON_VPN_ON, state_on=AsusOVPNClient.ON, state_on_args={"id": num}, icon_off=ICON_VPN_OFF, state_off=AsusOVPNClient.OFF, state_off_args={"id": num}, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=False, extra_state_attributes={ f"{num}_{key}": value for key, value in SENSORS_OVPN_CLIENT.items() }, ) for num in range(1, 6) ] ) STATIC_SWITCHES.extend( [ # OpenVPN servers ARSwitchDescription( key=f"{num}_{STATE}", key_group="ovpn_server", name=f"OpenVPN Server {num}", icon_on=ICON_VPN_ON, state_on=AsusOVPNServer.ON, state_on_args={"id": num}, icon_off=ICON_VPN_OFF, state_off=AsusOVPNServer.OFF, state_off_args={"id": num}, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=False, extra_state_attributes={ f"{num}_{key}": value for key, value in SENSORS_OVPN_SERVER.items() }, ) for num in NUMERIC_OVPN_SERVER ] ) STATIC_SWITCHES.extend( [ # WireGuard clients ARSwitchDescription( key=f"{num}_state", key_group="wireguard_client", name=f"WireGuard Client {num}", icon_on=ICON_VPN_ON, state_on=AsusWireGuardClient.ON, state_on_args={"id": num}, icon_off=ICON_VPN_OFF, state_off=AsusWireGuardClient.OFF, state_off_args={"id": num}, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=False, extra_state_attributes={ f"{num}_{key}": value for key, value in SENSORS_WIREGUARD_CLIENT.items() }, ) for num in range(1, 6) ] ) STATIC_SWITCHES.extend( [ # WireGuard Server ARSwitchDescription( key=f"{num}_state", key_group="wireguard_server", name=f"WireGuard Server {num}", icon_on=ICON_VPN_ON, state_on=AsusWireGuardServer.ON, state_on_args={"id": num}, icon_off=ICON_VPN_OFF, state_off=AsusWireGuardServer.OFF, state_off_args={"id": num}, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=False, extra_state_attributes={ f"{num}_{key}": value for key, value in SENSORS_WIREGUARD_SERVER.items() }, ) for num in range(1, 2) ] ) STATIC_SWITCHES.extend( [ # WLANs ARSwitchDescription( key=f"{wlan}_radio", key_group="wlan", name=f"Wireless {LABELS_WLAN[wlan]}", icon_on=ICON_WLAN_ON, state_on=AsusWLAN.ON, state_on_args={ API_ID: wlan_id, API_TYPE: "wlan", }, icon_off=ICON_WLAN_OFF, state_off=AsusWLAN.OFF, state_off_args={ API_ID: wlan_id, API_TYPE: "wlan", }, state_expect_modify=True, device_class="wlan", capabilities={ API_TYPE: "wlan", API_ID: wlan_id, }, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=True, extra_state_attributes={ f"{wlan}_{key}": value for key, value in SENSORS_WLAN.items() }, ) for wlan, wlan_id in MAP_WLAN.items() ] ) STATIC_SWITCHES.extend( [ # Guest WLANs ARSwitchDescription( key=f"{wlan}_{gwlan}_bss_enabled", key_group="gwlan", name=f"Guest {LABELS_WLAN[wlan]} {gwlan}", icon_on=ICON_WLAN_ON, state_on=AsusWLAN.ON, state_on_args={ API_ID: f"{wlan_id}.{gwlan}", API_TYPE: "gwlan", }, icon_off=ICON_WLAN_OFF, state_off=AsusWLAN.OFF, state_off_args={ API_ID: f"{wlan_id}.{gwlan}", API_TYPE: "gwlan", }, state_expect_modify=True, device_class="wlan", capabilities={ API_TYPE: "gwlan", API_ID: f"{wlan_id}.{gwlan}", }, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=False, extra_state_attributes={ f"{wlan}_{gwlan}_{key}": value for key, value in SENSORS_GWLAN.items() }, ) for gwlan in NUMERIC_GWLAN for wlan, wlan_id in MAP_WLAN.items() ] ) STATIC_SWITCHES.extend( [ # Port forwarding ARSwitchDescription( key="state", key_group="port_forwarding", name="Port forwarding", icon_on=ICON_PORT_FORWARDING_ON, state_on=AsusPortForwarding.ON, icon_off=ICON_PORT_FORWARDING_OFF, state_off=AsusPortForwarding.OFF, entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=False, extra_state_attributes={ "list": "list", }, ) ] ) STATIC_UPDATES: list[AREntityDescription] = [ ARUpdateDescription( key="state", key_group="firmware", name="Firmware update", icon=ICON_UPDATE, device_class=UpdateDeviceClass.FIRMWARE, entity_registry_enabled_default=True, extra_state_attributes={ "current": "current", "latest": "latest", "release_note": "release_note", }, ), ARUpdateDescription( key="state_beta", key_group="firmware", name="Firmware update (Beta)", icon=ICON_UPDATE, device_class=UpdateDeviceClass.FIRMWARE, entity_registry_enabled_default=False, extra_state_attributes={ "current": "current", "latest_beta": "latest", "release_note": "release_note", }, ), ] # <-- SENSORS # CONSTANTS BY MODULE --> # __init__ constants STOP_LISTENER = "stop_listener" # Configuration flow BASE = "base" CONFIGS = "configs" ERRORS = "errors" INTERFACES = "interfaces" RESULT_ACCESS_ERROR = "access_error" RESULT_CANNOT_RESOLVE = "cannot_resolve" RESULT_CONNECTION_ERROR = "connection_error" RESULT_CONNECTION_REFUSED = "connection_refused" RESULT_ERROR = "error" RESULT_LOGIN_BLOCKED = "login_blocked" RESULT_SUCCESS = "success" RESULT_TIMEOUT = "timeout" RESULT_UNKNOWN = "unknown" RESULT_WRONG_CREDENTIALS = "wrong_credentials" STEP_CONNECTED_DEVICES = "connected_devices" STEP_CREDENTIALS = "credentials" STEP_EVENTS = "events" STEP_FIND = "find" STEP_FINISH = "finish" STEP_INTERFACES = "interfaces" STEP_INTERVALS = "intervals" STEP_NAME = "name" STEP_OPERATION = "operation" STEP_OPTIONS = "options" STEP_SECURITY = "security"