diff --git a/custom_components/mikrotik_router/config_flow.py b/custom_components/mikrotik_router/config_flow.py index 97302be..3aaead2 100644 --- a/custom_components/mikrotik_router/config_flow.py +++ b/custom_components/mikrotik_router/config_flow.py @@ -35,6 +35,8 @@ from .const import ( DEFAULT_SENSOR_PORT_TRAFFIC, CONF_SENSOR_CLIENT_TRAFFIC, DEFAULT_SENSOR_CLIENT_TRAFFIC, + CONF_SENSOR_CLIENT_CAPTIVE, + DEFAULT_SENSOR_CLIENT_CAPTIVE, CONF_SENSOR_SIMPLE_QUEUES, DEFAULT_SENSOR_SIMPLE_QUEUES, CONF_SENSOR_NAT, @@ -250,6 +252,12 @@ class MikrotikControllerOptionsFlowHandler(OptionsFlow): CONF_SENSOR_CLIENT_TRAFFIC, DEFAULT_SENSOR_CLIENT_TRAFFIC ), ): bool, + vol.Optional( + CONF_SENSOR_CLIENT_CAPTIVE, + default=self.config_entry.options.get( + CONF_SENSOR_CLIENT_CAPTIVE, DEFAULT_SENSOR_CLIENT_CAPTIVE + ), + ): bool, vol.Optional( CONF_SENSOR_SIMPLE_QUEUES, default=self.config_entry.options.get( diff --git a/custom_components/mikrotik_router/const.py b/custom_components/mikrotik_router/const.py index 4bbbfdf..54367c7 100644 --- a/custom_components/mikrotik_router/const.py +++ b/custom_components/mikrotik_router/const.py @@ -41,6 +41,8 @@ CONF_SENSOR_PORT_TRAFFIC = "sensor_port_traffic" DEFAULT_SENSOR_PORT_TRAFFIC = False CONF_SENSOR_CLIENT_TRAFFIC = "sensor_client_traffic" DEFAULT_SENSOR_CLIENT_TRAFFIC = False +CONF_SENSOR_CLIENT_CAPTIVE = "sensor_client_captive" +DEFAULT_SENSOR_CLIENT_CAPTIVE = False CONF_SENSOR_SIMPLE_QUEUES = "sensor_simple_queues" DEFAULT_SENSOR_SIMPLE_QUEUES = False CONF_SENSOR_NAT = "sensor_nat" diff --git a/custom_components/mikrotik_router/device_tracker_types.py b/custom_components/mikrotik_router/device_tracker_types.py index b2ddd1c..7b4408b 100644 --- a/custom_components/mikrotik_router/device_tracker_types.py +++ b/custom_components/mikrotik_router/device_tracker_types.py @@ -9,6 +9,8 @@ from homeassistant.components.switch import ( DEVICE_ATTRIBUTES_HOST = [ "interface", "source", + "authorized", + "bypassed", "last-seen", ] diff --git a/custom_components/mikrotik_router/mikrotik_controller.py b/custom_components/mikrotik_router/mikrotik_controller.py index 8e2bd37..19d5aa2 100644 --- a/custom_components/mikrotik_router/mikrotik_controller.py +++ b/custom_components/mikrotik_router/mikrotik_controller.py @@ -41,6 +41,8 @@ from .const import ( DEFAULT_SENSOR_PORT_TRAFFIC, CONF_SENSOR_CLIENT_TRAFFIC, DEFAULT_SENSOR_CLIENT_TRAFFIC, + CONF_SENSOR_CLIENT_CAPTIVE, + DEFAULT_SENSOR_CLIENT_CAPTIVE, CONF_SENSOR_SIMPLE_QUEUES, DEFAULT_SENSOR_SIMPLE_QUEUES, CONF_SENSOR_NAT, @@ -130,6 +132,7 @@ class MikrotikControllerData: "wireless_hosts": {}, "host": {}, "host_hass": {}, + "hostspot_host": {}, "client_traffic": {}, "environment": {}, } @@ -231,6 +234,16 @@ class MikrotikControllerData: CONF_SENSOR_CLIENT_TRAFFIC, DEFAULT_SENSOR_CLIENT_TRAFFIC ) + # --------------------------- + # option_sensor_client_captive + # --------------------------- + @property + def option_sensor_client_captive(self): + """Config entry option to not track ARP.""" + return self.config_entry.options.get( + CONF_SENSOR_CLIENT_CAPTIVE, DEFAULT_SENSOR_CLIENT_CAPTIVE + ) + # --------------------------- # option_sensor_simple_queues # --------------------------- @@ -637,6 +650,9 @@ class MikrotikControllerData: elif 0 < self.major_fw_version >= 7: await self.hass.async_add_executor_job(self.process_kid_control_devices) + if self.api.connected() and self.option_sensor_client_captive: + await self.hass.async_add_executor_job(self.get_captive) + if self.api.connected() and self.option_sensor_simple_queues: await self.hass.async_add_executor_job(self.get_queue) @@ -1501,6 +1517,32 @@ class MikrotikControllerData: ], ) + # --------------------------- + # get_captive + # --------------------------- + def get_captive(self): + """Get list of all environment variables from Mikrotik""" + self.data["hostspot_host"] = parse_api( + data={}, + source=self.api.path("/ip/hotspot/host"), + key="mac-address", + vals=[ + {"name": "mac-address"}, + { + "name": "authorized", + "source": "disabled", + "type": "bool", + "reverse": True, + }, + { + "name": "bypassed", + "source": "disabled", + "type": "bool", + "reverse": True, + }, + ], + ) + # --------------------------- # get_queue # --------------------------- @@ -1877,6 +1919,20 @@ class MikrotikControllerData: self.data["resource"]["clients_wired"] = 0 self.data["resource"]["clients_wireless"] = 0 for uid, vals in self.data["host"].items(): + # Captive portal data + if self.option_sensor_client_captive: + if uid in self.data["hostspot_host"]: + self.data["host"][uid]["authorized"] = self.data["hostspot_host"][ + "authorized" + ] + self.data["host"][uid]["bypassed"] = self.data["hostspot_host"][ + "bypassed" + ] + else: + if "authorized" in self.data["host"][uid]: + del self.data["host"][uid]["authorized"] + del self.data["host"][uid]["bypassed"] + # CAPS-MAN availability if vals["source"] == "capsman" and uid not in capsman_detected: self.data["host"][uid]["available"] = False diff --git a/custom_components/mikrotik_router/sensor_types.py b/custom_components/mikrotik_router/sensor_types.py index a4b2a59..61d144d 100644 --- a/custom_components/mikrotik_router/sensor_types.py +++ b/custom_components/mikrotik_router/sensor_types.py @@ -63,7 +63,13 @@ DEVICE_ATTRIBUTES_IFACE_SFP = [ "eeprom-checksum", ] -DEVICE_ATTRIBUTES_CLIENT_TRAFFIC = ["address", "mac-address", "host-name"] +DEVICE_ATTRIBUTES_CLIENT_TRAFFIC = [ + "address", + "mac-address", + "host-name", + "authorized", + "bypassed", +] @dataclass diff --git a/custom_components/mikrotik_router/strings.json b/custom_components/mikrotik_router/strings.json index 7eecb86..828f5c5 100644 --- a/custom_components/mikrotik_router/strings.json +++ b/custom_components/mikrotik_router/strings.json @@ -41,6 +41,7 @@ "sensor_port_tracker": "Port tracker sensors", "sensor_port_traffic": "Port traffic sensors", "sensor_client_traffic": "Client traffic sensors", + "sensor_client_captive": "Captive portal data", "sensor_simple_queues": "Simple queues switches", "sensor_nat": "NAT switches", "sensor_scripts": "Script switches",