import os import csv import tkinter as tk from tkinter import ttk from tkinter import messagebox from datetime import datetime import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg LOGS_DIR = "logs" class GraphViewer(tk.Toplevel): def __init__(self, master=None): super().__init__(master) self.title("Valve Graph Viewer") self.geometry("1000x600") self._create_widgets() self._populate_dates() def _create_widgets(self): self.date_label = ttk.Label(self, text="Select Date:") self.date_label.pack() self.date_cb = ttk.Combobox(self, state="readonly") self.date_cb.pack() self.node_label = ttk.Label(self, text="Select Node:") self.node_label.pack() self.node_cb = ttk.Combobox(self, state="readonly", values=[f"Node{nid:02}" for nid in range(5, 25)]) self.node_cb.pack() self.plot_btn = ttk.Button(self, text="Plot Graph", command=self._plot_graph) self.plot_btn.pack(pady=10) self.canvas_frame = ttk.Frame(self) self.canvas_frame.pack(fill="both", expand=True) def _populate_dates(self): if not os.path.exists(LOGS_DIR): return dates = [d for d in os.listdir(LOGS_DIR) if os.path.isdir(os.path.join(LOGS_DIR, d))] self.date_cb['values'] = sorted(dates) if dates: self.date_cb.current(0) self.node_cb.current(0) def _plot_graph(self): date = self.date_cb.get() node = self.node_cb.get() filepath = os.path.join(LOGS_DIR, date, f"{node}.csv") if not os.path.exists(filepath): messagebox.showerror("File Not Found", f"No data for {node} on {date}.") return timestamps = [] setpoints = [] feedbacks = [] flows = [] pressures = [] with open(filepath, newline='') as csvfile: reader = csv.DictReader(csvfile) for row in reader: try: timestamps.append(datetime.strptime(row["Timestamp"], "%Y-%m-%d %H:%M:%S")) setpoints.append(float(row["Setpoint"])) feedbacks.append(float(row["Feedback"])) flows.append(float(row["Flow (L/h)"])) pressures.append(float(row["Pressure (bar)"])) except Exception as e: print(f"[PARSE ERROR] {e}") self._draw_plot(timestamps, setpoints, feedbacks, flows, pressures) def _draw_plot(self, t, sp, fb, fl, pr): for widget in self.canvas_frame.winfo_children(): widget.destroy() fig, ax = plt.subplots(figsize=(10, 5)) ax.plot(t, sp, label="Setpoint") ax.plot(t, fb, label="Feedback") ax.plot(t, fl, label="Flow (L/h)") ax.plot(t, pr, label="Pressure (bar)") ax.set_title("Valve Performance") ax.set_xlabel("Time") ax.set_ylabel("Values") ax.legend() ax.grid(True) canvas = FigureCanvasTkAgg(fig, master=self.canvas_frame) canvas.draw() canvas.get_tk_widget().pack(fill="both", expand=True) # Usage: # from graph_viewer import GraphViewer # btn.config(command=lambda: GraphViewer(root))