diff --git a/README.md b/README.md index 95dd001..e759779 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,11 @@ Track availability of all network devices. All devices visible to Mikrotik devic ![Host tracker](https://raw.githubusercontent.com/tomaae/homeassistant-mikrotik_router/master/docs/assets/images/ui/host_tracker.png) +## Netwatch Tracking +Track netwatch status. + +![Netwatch](https://raw.githubusercontent.com/tomaae/homeassistant-mikrotik_router/master/docs/assets/images/ui/netwatch_tracker.png) + ## Scripts Execute Mikrotik Router scripts. You can execute scripts by automatically created switches or using services. diff --git a/custom_components/mikrotik_router/binary_sensor.py b/custom_components/mikrotik_router/binary_sensor.py index 595f996..574192f 100644 --- a/custom_components/mikrotik_router/binary_sensor.py +++ b/custom_components/mikrotik_router/binary_sensor.py @@ -16,12 +16,15 @@ from .binary_sensor_types import ( DEVICE_ATTRIBUTES_IFACE_ETHER, DEVICE_ATTRIBUTES_IFACE_SFP, DEVICE_ATTRIBUTES_IFACE_WIRELESS, + DEVICE_ATTRIBUTES_NETWATCH, ) from .const import ( CONF_SENSOR_PPP, DEFAULT_SENSOR_PPP, CONF_SENSOR_PORT_TRACKER, DEFAULT_SENSOR_PORT_TRACKER, + CONF_SENSOR_NETWATCH_TRACKER, + DEFAULT_SENSOR_NETWATCH_TRACKER, ) from .entity import MikrotikEntity, async_add_entities from .helper import format_attribute diff --git a/custom_components/mikrotik_router/binary_sensor_types.py b/custom_components/mikrotik_router/binary_sensor_types.py index 40f69d8..6657907 100644 --- a/custom_components/mikrotik_router/binary_sensor_types.py +++ b/custom_components/mikrotik_router/binary_sensor_types.py @@ -108,6 +108,15 @@ DEVICE_ATTRIBUTES_UPS = [ "hid-self-test", ] +DEVICE_ATTRIBUTES_NETWATCH = [ + "host", + "type", + "interval", + "port", + "http-codes", + "status", + "comment", +] @dataclass class MikrotikBinarySensorEntityDescription(BinarySensorEntityDescription): @@ -177,6 +186,24 @@ SENSOR_TYPES: tuple[BinarySensorEntityDescription, ...] = ( data_attributes_list=DEVICE_ATTRIBUTES_IFACE, func="MikrotikPortBinarySensor", ), + MikrotikBinarySensorEntityDescription( + key="netwatch", + name="Netwatch", + icon_enabled="mdi:lan-connect", + icon_disabled="mdi:lan-pending", + device_class=BinarySensorDeviceClass.CONNECTIVITY, + ha_group="Netwatch", + ha_connection=DOMAIN, + ha_connection_value="Netwatch", + data_path="netwatch", + data_attribute="status", + data_name="host", + data_name_comment=True, + data_uid="host", + data_reference="host", + data_attributes_list=DEVICE_ATTRIBUTES_NETWATCH, + func="MikrotikBinarySensor", + ), ) SENSOR_SERVICES = {} diff --git a/custom_components/mikrotik_router/config_flow.py b/custom_components/mikrotik_router/config_flow.py index 935a39b..83d1f97 100644 --- a/custom_components/mikrotik_router/config_flow.py +++ b/custom_components/mikrotik_router/config_flow.py @@ -59,6 +59,8 @@ from .const import ( DEFAULT_PORT, DEFAULT_DEVICE_NAME, DEFAULT_SSL, + DEFAULT_SENSOR_NETWATCH_TRACKER, + CONF_SENSOR_NETWATCH_TRACKER, ) from .mikrotikapi import MikrotikAPI @@ -280,6 +282,12 @@ class MikrotikControllerOptionsFlowHandler(OptionsFlow): CONF_SENSOR_KIDCONTROL, DEFAULT_SENSOR_KIDCONTROL ), ): bool, + vol.Optional( + CONF_SENSOR_NETWATCH_TRACKER, + default=self.config_entry.options.get( + CONF_SENSOR_NETWATCH_TRACKER, DEFAULT_SENSOR_NETWATCH_TRACKER + ), + ): bool, vol.Optional( CONF_SENSOR_PPP, default=self.config_entry.options.get( diff --git a/custom_components/mikrotik_router/const.py b/custom_components/mikrotik_router/const.py index c2cec52..d7ac4b2 100644 --- a/custom_components/mikrotik_router/const.py +++ b/custom_components/mikrotik_router/const.py @@ -58,6 +58,8 @@ CONF_SENSOR_SCRIPTS = "sensor_scripts" DEFAULT_SENSOR_SCRIPTS = False CONF_SENSOR_ENVIRONMENT = "sensor_environment" DEFAULT_SENSOR_ENVIRONMENT = False +CONF_SENSOR_NETWATCH_TRACKER = "sensor_netwatch_tracker" +DEFAULT_SENSOR_NETWATCH_TRACKER = False TO_REDACT = { "ip-address", diff --git a/custom_components/mikrotik_router/coordinator.py b/custom_components/mikrotik_router/coordinator.py index ed2058d..a072e77 100644 --- a/custom_components/mikrotik_router/coordinator.py +++ b/custom_components/mikrotik_router/coordinator.py @@ -59,7 +59,7 @@ from .const import ( CONF_SENSOR_SCRIPTS, DEFAULT_SENSOR_SCRIPTS, CONF_SENSOR_ENVIRONMENT, - DEFAULT_SENSOR_ENVIRONMENT, + DEFAULT_SENSOR_ENVIRONMENT, CONF_SENSOR_NETWATCH_TRACKER, DEFAULT_SENSOR_NETWATCH_TRACKER, ) from .exceptions import ApiEntryNotFound from .apiparser import parse_api @@ -258,6 +258,7 @@ class MikrotikCoordinator(DataUpdateCoordinator[None]): "environment": {}, "ups": {}, "gps": {}, + "netwatch": {} } self.notified_flags = [] @@ -386,6 +387,14 @@ class MikrotikCoordinator(DataUpdateCoordinator[None]): CONF_SENSOR_KIDCONTROL, DEFAULT_SENSOR_KIDCONTROL ) + # --------------------------- + # option_sensor_netwatch + # --------------------------- + @property + def option_sensor_netwatch(self): + """Config entry option to not track ARP.""" + return self.config_entry.options.get(CONF_SENSOR_NETWATCH_TRACKER, DEFAULT_SENSOR_NETWATCH_TRACKER) + # --------------------------- # option_sensor_ppp # --------------------------- @@ -627,6 +636,9 @@ class MikrotikCoordinator(DataUpdateCoordinator[None]): if self.api.connected() and self.option_sensor_filter: await self.hass.async_add_executor_job(self.get_filter) + if self.api.connected() and self.option_sensor_netwatch: + await self.hass.async_add_executor_job(self.get_netwatch) + if self.api.connected() and self.support_ppp and self.option_sensor_ppp: await self.hass.async_add_executor_job(self.get_ppp) @@ -1310,6 +1322,32 @@ class MikrotikCoordinator(DataUpdateCoordinator[None]): self.ds["ppp_secret"][uid]["address"] = "not connected" self.ds["ppp_secret"][uid]["encoding"] = "not connected" + # --------------------------- + # get_netwatch + # --------------------------- + def get_netwatch(self) -> None: + """Get netwatch data from Mikrotik""" + self.ds["netwatch"] = parse_api( + data=self.ds["netwatch"], + source=self.api.query("/tool/netwatch"), + key="host", + vals=[ + {"name": "host"}, + {"name": "type"}, + {"name": "interval"}, + {"name": "port"}, + {"name": "http-codes"}, + {"name": "status", "type": "bool", "default": "unknown"}, + {"name": "comment"}, + { + "name": "enabled", + "source": "disabled", + "type": "bool", + "reverse": True, + }, + ], + ) + # --------------------------- # get_system_routerboard # --------------------------- diff --git a/custom_components/mikrotik_router/entity.py b/custom_components/mikrotik_router/entity.py index 1f9924a..daf171f 100644 --- a/custom_components/mikrotik_router/entity.py +++ b/custom_components/mikrotik_router/entity.py @@ -26,6 +26,8 @@ from .const import ( DEFAULT_TRACK_HOSTS, CONF_SENSOR_PORT_TRACKER, DEFAULT_SENSOR_PORT_TRACKER, + CONF_SENSOR_NETWATCH_TRACKER, + DEFAULT_SENSOR_NETWATCH_TRACKER, ) from .coordinator import MikrotikCoordinator, MikrotikTrackerCoordinator from .helper import format_attribute @@ -70,6 +72,14 @@ def _skip_sensor(config_entry, entity_description, data, uid) -> bool: ): return True + if ( + entity_description.data_path == "netwatch" + and not config_entry.options.get( + CONF_SENSOR_NETWATCH_TRACKER, DEFAULT_SENSOR_NETWATCH_TRACKER + ) + ): + return True + # Device Tracker if ( # Skip if host tracking is disabled diff --git a/custom_components/mikrotik_router/strings.json b/custom_components/mikrotik_router/strings.json index 828f5c5..1303cf1 100644 --- a/custom_components/mikrotik_router/strings.json +++ b/custom_components/mikrotik_router/strings.json @@ -39,6 +39,7 @@ "data": { "track_network_hosts": "Track network devices", "sensor_port_tracker": "Port tracker sensors", + "sensor_netwatch_tracker": "Netwatch tracker sensors", "sensor_port_traffic": "Port traffic sensors", "sensor_client_traffic": "Client traffic sensors", "sensor_client_captive": "Captive portal data", diff --git a/docs/assets/images/ui/netwatch_tracker.png b/docs/assets/images/ui/netwatch_tracker.png new file mode 100644 index 0000000..a4c7086 Binary files /dev/null and b/docs/assets/images/ui/netwatch_tracker.png differ