#!/usr/bin/env python3 import re import datetime import os # Paths TSF_MON_PATH = "/sys/kernel/debug/ieee80211/phy0/netdev:mesh0/tsf_mon" NODE_ADDRESSES_SCRIPT = "/opt/scripts/mesh/node_addresses.sh" # Load MAC-to-node mapping def load_node_addresses(script_path): mac_to_node = {} if not os.path.exists(script_path): print(f"Error: node_addresses.sh not found at {script_path}") return mac_to_node current_section = None with open(script_path, "r") as f: for line in f: line = line.strip() # Detect which array we are in if line.startswith("declare -A"): if "eth0MAC" in line: current_section = "eth0MAC" elif "phy0MAC" in line: current_section = "phy0MAC" elif "phy1MAC" in line: current_section = "phy1MAC" else: current_section = None continue # Match MAC entry inside an array match = re.match(r'\["([^"]+)"\]="([^"]+)"', line) if match and current_section: node_name, mac = match.groups() mac = mac.lower() mac_to_node[mac] = node_name return mac_to_node # Parse TSF monitor output def parse_tsf_mon(tsf_path, mac_mapping): if not os.path.exists(tsf_path): print(f"Error: tsf_mon file not found at {tsf_path}") return tsf_entry_re = re.compile(r"Peer MAC: ([\da-fA-F:]+) \| Peer TSF: (\d+) \| Time: (\d+) ns \| Offset: ([+-]?\d+) us") with open(tsf_path, "r") as f: for line in f: match = tsf_entry_re.search(line) if match: mac, peer_tsf, timestamp_ns, offset_us = match.groups() mac = mac.lower() node_name = mac_mapping.get(mac, mac) # fallback to MAC if unknown # Convert timestamp timestamp_sec = int(timestamp_ns) / 1_000_000_000 timestamp_dt = datetime.datetime.utcfromtimestamp(timestamp_sec) print(f"Node: {node_name} | Peer TSF: {peer_tsf} | Time: {timestamp_dt.isoformat()} UTC | Offset: {offset_us} us") # --- Main --- if __name__ == "__main__": mac_mapping = load_node_addresses(NODE_ADDRESSES_SCRIPT) parse_tsf_mon(TSF_MON_PATH, mac_mapping)