From eaff8b05c20b19c59e32e2646ca17d7bc75250aa Mon Sep 17 00:00:00 2001 From: jwansek Date: Sun, 18 May 2025 22:41:07 +0100 Subject: Added fetching mikrotik POE usage to InfluxDB too --- switch-snmp/snmpOmada.py | 96 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 switch-snmp/snmpOmada.py (limited to 'switch-snmp/snmpOmada.py') diff --git a/switch-snmp/snmpOmada.py b/switch-snmp/snmpOmada.py new file mode 100644 index 0000000..f1546a7 --- /dev/null +++ b/switch-snmp/snmpOmada.py @@ -0,0 +1,96 @@ +# wget https://static.tp-link.com/upload/software/2022/202209/20220915/privateMibs(20220831).zip +# cp -v *.mib /home/eden/.snmp/mibs +# sudo apt install snmp +# sudo apt-get install snmp-mibs-downloader + +import subprocess +from dataclasses import dataclass +import dotenv +import os +import pandas +import configparser + +from influxdb_client import InfluxDBClient, Point, WritePrecision +from influxdb_client.client.write_api import SYNCHRONOUS + +DIVIDE_BY_10_ENDPOINTS = ["tpPoePower", "tpPoeVoltage"] + +@dataclass +class SNMPReading: + endpoint: str + port: int + reading: float + + @classmethod + def from_string(cls, str_): + s = str_.split() + if len(s) != 4: + raise Exception("Couldn't parse") + endpoint_and_port, _, type_, reading = s + endpoint, port = endpoint_and_port.split(".") + + if reading.isdigit(): + reading = int(reading) + if endpoint in DIVIDE_BY_10_ENDPOINTS: + reading = reading / 10 + + return cls(endpoint, int(port), reading) + +def get_alternate_name(port, host): + port_names = configparser.ConfigParser() + port_names.read(os.path.join(os.path.dirname(__file__), "omada-switches.conf")) + port_names = {int(k): v for k, v in port_names[host].items()} + + try: + return port_names[port] + except KeyError: + return port + +def snmp_walk(host): + proc = subprocess.Popen( + ["snmpwalk", "-Os", "-c", "tplink", "-v", "2c", "-m", "TPLINK-POWER-OVER-ETHERNET-MIB", host, "tplinkPowerOverEthernetMIB"], + stdout = subprocess.PIPE + ) + out = [] + while True: + line = proc.stdout.readline() + if not line: + break + try: + out.append(SNMPReading.from_string(line.rstrip().decode())) + except Exception: + pass + + return out + +def readings_to_points(readings, switch_host): + points = [] + df = pandas.DataFrame(readings) + df["port_name"] = df["port"].apply(get_alternate_name, args = (switch_host, )) + for p, group_df in df.groupby(["port", "port_name"]): + port, port_name = p + fields = dict(zip(group_df['endpoint'], group_df['reading'])) + + points.append({ + "measurement": "switch_status", + "tags": {"port": port, "port_name": port_name, "switch_host": switch_host, "type": "Omada"}, + "fields": fields + }) + + return points + +def get_points(): + if not os.path.exists(os.path.join(os.path.dirname(__file__), "omada-switches.conf")): + raise FileNotFoundError("Couldn't find config file") + switches = configparser.ConfigParser() + switches.read(os.path.join(os.path.dirname(__file__), "omada-switches.conf")) + points = [] + for switch_host in switches.sections(): + points += readings_to_points(snmp_walk(switch_host), switch_host) + return points + +if __name__ == "__main__": + import mikrotik + points = get_points() + print(points) + mikrotik.append(points) \ No newline at end of file -- cgit v1.2.3