From 3bf4c56254873760673fb94a13ba7cf1d3865da2 Mon Sep 17 00:00:00 2001 From: tomaae <23486452+tomaae@users.noreply.github.com> Date: Mon, 12 Apr 2021 14:28:39 +0200 Subject: [PATCH] Added SFP support #94 --- .../mikrotik_router/binary_sensor.py | 28 ++++++++++ .../mikrotik_router/mikrotik_controller.py | 39 +++++++------ .../mikrotik_router/mikrotikapi.py | 55 +++++++++++++++++++ custom_components/mikrotik_router/switch.py | 39 +++++++++++++ 4 files changed, 144 insertions(+), 17 deletions(-) diff --git a/custom_components/mikrotik_router/binary_sensor.py b/custom_components/mikrotik_router/binary_sensor.py index cb361b4..5cb9748 100644 --- a/custom_components/mikrotik_router/binary_sensor.py +++ b/custom_components/mikrotik_router/binary_sensor.py @@ -58,6 +58,29 @@ DEVICE_ATTRIBUTES_IFACE = [ "poe-out", ] +DEVICE_ATTRIBUTES_IFACE_SFP = [ + "status", + "auto-negotiation", + "advertising", + "link-partner-advertising", + "sfp-temperature", + "sfp-supply-voltage", + "sfp-module-present", + "sfp-tx-bias-current", + "sfp-tx-power", + "sfp-rx-power", + "sfp-rx-loss", + "sfp-tx-fault", + "sfp-type", + "sfp-connector-type", + "sfp-vendor-name", + "sfp-vendor-part-number", + "sfp-vendor-revision", + "sfp-vendor-serial", + "sfp-manufacturing-date", + "eeprom-checksum", +] + DEVICE_ATTRIBUTES_PPP_SECRET = [ "connected", "service", @@ -430,6 +453,11 @@ class MikrotikControllerPortBinarySensor(MikrotikControllerBinarySensor): if variable in self._data: attributes[format_attribute(variable)] = self._data[variable] + if "sfp-shutdown-temperature" in self._data: + for variable in DEVICE_ATTRIBUTES_IFACE_SFP: + if variable in self._data: + attributes[format_attribute(variable)] = self._data[variable] + return attributes @property diff --git a/custom_components/mikrotik_router/mikrotik_controller.py b/custom_components/mikrotik_router/mikrotik_controller.py index d568c83..c81496d 100644 --- a/custom_components/mikrotik_router/mikrotik_controller.py +++ b/custom_components/mikrotik_router/mikrotik_controller.py @@ -683,26 +683,31 @@ class MikrotikControllerData: "sfp-shutdown-temperature" in vals and vals["sfp-shutdown-temperature"] != "" ): - # _LOGGER.warning("!!!!!!!SFP Port %s", uid) self.data["interface"] = parse_api( data=self.data["interface"], - source=self.api.path("/interface/ethernet"), - key="default-name", - key_secondary="name", + source=self.api.get_sfp(uid), + key_search="name", vals=[ - {"name": "default-name"}, - {"name": "name", "default_val": "default-name"}, - {"name": "poe-out", "default": "N/A"}, - {"name": "sfp-shutdown-temperature", "default": ""}, - ], - skip=[ - {"name": "type", "value": "bridge"}, - {"name": "type", "value": "ppp-in"}, - {"name": "type", "value": "pptp-in"}, - {"name": "type", "value": "sstp-in"}, - {"name": "type", "value": "l2tp-in"}, - {"name": "type", "value": "pppoe-in"}, - {"name": "type", "value": "ovpn-in"}, + {"name": "status", "default": "unknown"}, + {"name": "auto-negotiation", "default": "unknown"}, + {"name": "advertising", "default": "unknown"}, + {"name": "link-partner-advertising", "default": "unknown"}, + {"name": "sfp-temperature", "default": "unknown"}, + {"name": "sfp-supply-voltage", "default": "unknown"}, + {"name": "sfp-module-present", "default": "unknown"}, + {"name": "sfp-tx-bias-current", "default": "unknown"}, + {"name": "sfp-tx-power", "default": "unknown"}, + {"name": "sfp-rx-power", "default": "unknown"}, + {"name": "sfp-rx-loss", "default": "unknown"}, + {"name": "sfp-tx-fault", "default": "unknown"}, + {"name": "sfp-type", "default": "unknown"}, + {"name": "sfp-connector-type", "default": "unknown"}, + {"name": "sfp-vendor-name", "default": "unknown"}, + {"name": "sfp-vendor-part-number", "default": "unknown"}, + {"name": "sfp-vendor-revision", "default": "unknown"}, + {"name": "sfp-vendor-serial", "default": "unknown"}, + {"name": "sfp-manufacturing-date", "default": "unknown"}, + {"name": "eeprom-checksum", "default": "unknown"}, ], ) diff --git a/custom_components/mikrotik_router/mikrotikapi.py b/custom_components/mikrotik_router/mikrotikapi.py index c32a8cb..9da31f6 100644 --- a/custom_components/mikrotik_router/mikrotikapi.py +++ b/custom_components/mikrotik_router/mikrotikapi.py @@ -489,6 +489,61 @@ class MikrotikAPI: self.lock.release() return traffic if traffic else None + # --------------------------- + # get_sfp + # --------------------------- + def get_sfp(self, interfaces) -> Optional(list): + """Get sfp info""" + if not self.connection_check(): + return None + + response = self.path("/interface/ethernet", return_list=False) + if response is None: + return None + + args = {".id": interfaces, "once": True} + self.lock.acquire() + try: + _LOGGER.debug("API query: %s %s", "/interface/ethernet/monitor", interfaces) + sfpinfo = response("monitor", **args) + except librouteros.exceptions.ConnectionClosed: + self.disconnect() + self.lock.release() + return None + except ( + librouteros.exceptions.TrapError, + librouteros.exceptions.MultiTrapError, + librouteros.exceptions.ProtocolError, + librouteros.exceptions.FatalError, + ssl.SSLError, + socket_timeout, + socket_error, + BrokenPipeError, + OSError, + ValueError, + ) as api_error: + self.disconnect("get_sfp", api_error) + self.lock.release() + return None + except: + self.disconnect("get_sfp") + self.lock.release() + return None + + try: + sfpinfo = list(sfpinfo) + except librouteros.exceptions.ConnectionClosed as api_error: + self.disconnect("get_sfp", api_error) + self.lock.release() + return None + except: + self.disconnect("get_sfp") + self.lock.release() + return None + + self.lock.release() + return sfpinfo if sfpinfo else None + # --------------------------- # arp_ping # --------------------------- diff --git a/custom_components/mikrotik_router/switch.py b/custom_components/mikrotik_router/switch.py index 396b5fc..00b8c88 100644 --- a/custom_components/mikrotik_router/switch.py +++ b/custom_components/mikrotik_router/switch.py @@ -31,6 +31,29 @@ DEVICE_ATTRIBUTES_IFACE = [ "poe-out", ] +DEVICE_ATTRIBUTES_IFACE_SFP = [ + "status", + "auto-negotiation", + "advertising", + "link-partner-advertising", + "sfp-temperature", + "sfp-supply-voltage", + "sfp-module-present", + "sfp-tx-bias-current", + "sfp-tx-power", + "sfp-rx-power", + "sfp-rx-loss", + "sfp-tx-fault", + "sfp-type", + "sfp-connector-type", + "sfp-vendor-name", + "sfp-vendor-part-number", + "sfp-vendor-revision", + "sfp-vendor-serial", + "sfp-manufacturing-date", + "eeprom-checksum", +] + DEVICE_ATTRIBUTES_NAT = [ "protocol", "dst-port", @@ -320,6 +343,22 @@ class MikrotikControllerPortSwitch(MikrotikControllerSwitch): """Return a unique id for this entity.""" return f"{self._inst.lower()}-enable_switch-{self._data['port-mac-address']}_{self._data['default-name']}" + @property + def device_state_attributes(self) -> Dict[str, Any]: + """Return the state attributes.""" + attributes = self._attrs + + for variable in self._sid_data["sid_attr"]: + if variable in self._data: + attributes[format_attribute(variable)] = self._data[variable] + + if "sfp-shutdown-temperature" in self._data: + for variable in DEVICE_ATTRIBUTES_IFACE_SFP: + if variable in self._data: + attributes[format_attribute(variable)] = self._data[variable] + + return attributes + @property def icon(self) -> str: """Return the icon."""