Update PTPLogger/PTPLogger_Graphing.py
This commit is contained in:
@@ -8,9 +8,6 @@ import tkinter as tk
|
|||||||
from tkinter import filedialog, messagebox, scrolledtext
|
from tkinter import filedialog, messagebox, scrolledtext
|
||||||
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# PARSE LOG
|
|
||||||
# ===========================
|
|
||||||
def parse_log(file_path):
|
def parse_log(file_path):
|
||||||
t, rms, freq = [], [], []
|
t, rms, freq = [], [], []
|
||||||
state_events = []
|
state_events = []
|
||||||
@@ -21,7 +18,6 @@ def parse_log(file_path):
|
|||||||
with open(file_path, encoding='utf-8', errors='ignore') as f:
|
with open(file_path, encoding='utf-8', errors='ignore') as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
|
|
||||||
# --- Try syslog timestamp ---
|
|
||||||
ts_match = re.match(r'^(\w+ \d+ \d+:\d+:\d+)', line)
|
ts_match = re.match(r'^(\w+ \d+ \d+:\d+:\d+)', line)
|
||||||
if ts_match:
|
if ts_match:
|
||||||
try:
|
try:
|
||||||
@@ -30,34 +26,31 @@ def parse_log(file_path):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
timestamp = last_timestamp # fallback for ptp4l lines
|
timestamp = last_timestamp
|
||||||
|
|
||||||
|
if not timestamp:
|
||||||
|
continue
|
||||||
|
|
||||||
# --- RMS/FREQ ---
|
|
||||||
m = re.search(r'rms\s+(\d+).*freq\s+([+-]?\d+)', line)
|
m = re.search(r'rms\s+(\d+).*freq\s+([+-]?\d+)', line)
|
||||||
if m and timestamp:
|
if m:
|
||||||
t.append(timestamp)
|
t.append(timestamp)
|
||||||
rms.append(int(m.group(1)))
|
rms.append(int(m.group(1)))
|
||||||
freq.append(int(m.group(2)))
|
freq.append(int(m.group(2)))
|
||||||
|
|
||||||
# --- STATE CHANGE ---
|
|
||||||
m = re.search(r'port \d+: (\w+) to (\w+)', line)
|
m = re.search(r'port \d+: (\w+) to (\w+)', line)
|
||||||
if m and timestamp:
|
if m:
|
||||||
state_events.append((timestamp, f"{m.group(1)}→{m.group(2)}"))
|
state_events.append((timestamp, f"{m.group(1)}→{m.group(2)}"))
|
||||||
|
|
||||||
# --- MASTER CHANGE ---
|
|
||||||
m = re.search(
|
m = re.search(
|
||||||
r'(selected best master clock|new foreign master)\s+([0-9a-fA-F\.:]+)',
|
r'(selected best master clock|new foreign master)\s+([0-9a-fA-F\.:]+)',
|
||||||
line
|
line
|
||||||
)
|
)
|
||||||
if m and timestamp:
|
if m:
|
||||||
master_events.append((timestamp, m.group(2)))
|
master_events.append((timestamp, m.group(2)))
|
||||||
|
|
||||||
return t, rms, freq, state_events, master_events
|
return t, rms, freq, state_events, master_events
|
||||||
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# PLOT
|
|
||||||
# ===========================
|
|
||||||
def plot_data(t, rms, freq, state_events, master_events, detail):
|
def plot_data(t, rms, freq, state_events, master_events, detail):
|
||||||
|
|
||||||
if not t:
|
if not t:
|
||||||
@@ -75,7 +68,7 @@ def plot_data(t, rms, freq, state_events, master_events, detail):
|
|||||||
ax2.set_xlabel("Time")
|
ax2.set_xlabel("Time")
|
||||||
ax2.grid()
|
ax2.grid()
|
||||||
|
|
||||||
# --- EVENTS ---
|
# event lines
|
||||||
for ts, _ in state_events:
|
for ts, _ in state_events:
|
||||||
ax1.axvline(ts, color='blue', linestyle='--', alpha=0.7)
|
ax1.axvline(ts, color='blue', linestyle='--', alpha=0.7)
|
||||||
ax2.axvline(ts, color='blue', linestyle='--', alpha=0.7)
|
ax2.axvline(ts, color='blue', linestyle='--', alpha=0.7)
|
||||||
@@ -84,7 +77,6 @@ def plot_data(t, rms, freq, state_events, master_events, detail):
|
|||||||
ax1.axvline(ts, color='red', linestyle='--', alpha=0.7)
|
ax1.axvline(ts, color='red', linestyle='--', alpha=0.7)
|
||||||
ax2.axvline(ts, color='red', linestyle='--', alpha=0.7)
|
ax2.axvline(ts, color='red', linestyle='--', alpha=0.7)
|
||||||
|
|
||||||
# --- LEGEND ---
|
|
||||||
legend = [
|
legend = [
|
||||||
Line2D([0], [0], color='black', label='RMS/Freq'),
|
Line2D([0], [0], color='black', label='RMS/Freq'),
|
||||||
Line2D([0], [0], color='blue', linestyle='--', label='State'),
|
Line2D([0], [0], color='blue', linestyle='--', label='State'),
|
||||||
@@ -92,11 +84,7 @@ def plot_data(t, rms, freq, state_events, master_events, detail):
|
|||||||
]
|
]
|
||||||
ax1.legend(handles=legend)
|
ax1.legend(handles=legend)
|
||||||
|
|
||||||
# --- SAFE DATE FORMAT ---
|
multi_day = any(d.date() != t[0].date() for d in t)
|
||||||
if len(t) > 0:
|
|
||||||
multi_day = any(d.date() != t[0].date() for d in t)
|
|
||||||
else:
|
|
||||||
multi_day = False
|
|
||||||
|
|
||||||
if multi_day:
|
if multi_day:
|
||||||
formatter = mdates.DateFormatter('%d %H:%M')
|
formatter = mdates.DateFormatter('%d %H:%M')
|
||||||
@@ -121,12 +109,9 @@ def plot_data(t, rms, freq, state_events, master_events, detail):
|
|||||||
|
|
||||||
plt.xticks(rotation=45)
|
plt.xticks(rotation=45)
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.show(block=False)
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# LOAD FILE
|
|
||||||
# ===========================
|
|
||||||
def open_file():
|
def open_file():
|
||||||
file_path = filedialog.askopenfilename(
|
file_path = filedialog.askopenfilename(
|
||||||
title="Select log",
|
title="Select log",
|
||||||
@@ -142,7 +127,6 @@ def open_file():
|
|||||||
|
|
||||||
plot_data(t, rms, freq, state_events, master_events, detail)
|
plot_data(t, rms, freq, state_events, master_events, detail)
|
||||||
|
|
||||||
# --- EVENT LIST ---
|
|
||||||
event_box.delete(1.0, tk.END)
|
event_box.delete(1.0, tk.END)
|
||||||
|
|
||||||
events = []
|
events = []
|
||||||
@@ -162,9 +146,7 @@ def open_file():
|
|||||||
event_box.insert(tk.END, "No events found.\n")
|
event_box.insert(tk.END, "No events found.\n")
|
||||||
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# GUI
|
# GUI
|
||||||
# ===========================
|
|
||||||
root = tk.Tk()
|
root = tk.Tk()
|
||||||
root.title("PTP Log Viewer")
|
root.title("PTP Log Viewer")
|
||||||
root.geometry("750x550")
|
root.geometry("750x550")
|
||||||
|
|||||||
Reference in New Issue
Block a user