import tkinter as tk
from tkinter import ttk
import socket
import threading
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.font_manager import FontProperties
import subprocess
# 指定黑体字体文件路径,需要根据实际情况修改
font_path = '/home/nvidia/test/simhei.ttf'
font_prop = FontProperties(fname=font_path)
plt.rcParams['font.family'] = font_prop.get_name()
# 解决负号显示问题
plt.rcParams['axes.unicode_minus'] = False
class DeviceManager(tk.Tk):
def __init__(self):
super().__init__()
self.title("设备管理器")
self.geometry("1100x900")
self.resizable(False, False)
self.configure(bg="#f9f9f9")
self.devices = {
"设备1": {
"ip": "192.168.31.50",
"status": "离线",
"temperature": 0,
"power": 0,
"memory": 0,
"bandwidth": 0,
"send_count": 0,
"mlu_avg_usage": 0,
"cpu_avg_usage": 0,
"mlu_core_usage": [1, 1, 1, 1],
"cpu_core_usage": [1, 1, 1, 1]
}
}
self.current_device = "设备1"
self.current_page = 1
self.create_sidebar()
self.create_pages()
self.start_udp_receive()
self.has_received_data = False
self.frame_count = 0
# 用于标记页面2、页面3和页面4的折线图是否已初始化
self.page2_plots_initialized = False
self.page3_plots_initialized = False
self.page4_plots_initialized = False
def create_sidebar(self):
# 增大侧边栏宽度
self.sidebar = tk.Frame(self, bg="#e0e0e0", width=300)
self.sidebar.pack(side="left", fill="y")
# 增大按钮尺寸并增加与左侧边界的间距
button_style = ttk.Style()
button_style.configure('TButton', font=('Arial', 16))
self.page1_button = ttk.Button(self.sidebar, text="主页面", command=lambda: self.show_page(1), style='TButton')
self.page1_button.pack(pady=20, padx=30, fill=tk.X)
self.page2_button = ttk.Button(self.sidebar, text="MLU", command=lambda: self.show_page(2),
style='TButton')
self.page2_button.pack(pady=20, padx=30, fill=tk.X)
self.page3_button = ttk.Button(self.sidebar, text="CPU", command=lambda: self.show_page(3),
style='TButton')
self.page3_button.pack(pady=20, padx=30, fill=tk.X)
self.page4_button = ttk.Button(self.sidebar, text="内存", command=lambda: self.show_page(4),
style='TButton')
self.page4_button.pack(pady=20, padx=30, fill=tk.X)
def create_pages(self):
self.pages = []
for i in range(4):
page = tk.Frame(self, bg="#f9f9f9")
page.pack(side="right", fill="both", expand=True, padx=20, pady=20)
self.pages.append(page)
self.create_page1()
self.create_page2()
self.create_page3()
self.create_page4()
self.show_page(1)
def create_page1(self):
self.info_frame = self.pages[0]
self.ip_frame = tk.Frame(self.info_frame, bg="#f9f9f9")
self.ip_frame.pack(pady=20, anchor="w")
self.create_info_widget("IP 地址:", self.ip_frame, "ip")
self.status_frame = tk.Frame(self.info_frame, bg="#f9f9f9")
self.status_frame.pack(pady=20, anchor="w")
self.create_info_widget("状态:", self.status_frame, "status")
self.temp_frame = tk.Frame(self.info_frame, bg="#f9f9f9")
self.temp_frame.pack(pady=20, anchor="w")
self.create_info_widget("温度:", self.temp_frame, "temperature", "°C")
self.power_frame = tk.Frame(self.info_frame, bg="#f9f9f9")
self.power_frame.pack(pady=20, anchor="w")
self.create_info_widget("功率:", self.power_frame, "power", "W")
self.bandwidth_frame = tk.Frame(self.info_frame, bg="#f9f9f9")
self.bandwidth_frame.pack(pady=20, anchor="w")
self.create_info_widget("带宽:", self.bandwidth_frame, "bandwidth", "GB/s")
# self.send_count_frame = tk.Frame(self.info_frame, bg="#f9f9f9")
# self.send_count_frame.pack(pady=20)
# self.create_info_widget("发送次数:", self.send_count_frame, "send_count")
self.mlu_avg_frame = tk.Frame(self.info_frame, bg="#f9f9f9")
self.mlu_avg_frame.pack(pady=20, anchor="w")
self.create_info_widget("MLU 平均占用率:", self.mlu_avg_frame, "mlu_avg_usage", "%")
self.cpu_avg_frame = tk.Frame(self.info_frame, bg="#f9f9f9")
self.cpu_avg_frame.pack(pady=20, anchor="w")
self.create_info_widget("CPU 平均占用率:", self.cpu_avg_frame, "cpu_avg_usage", "%")
def create_info_widget(self, label_text, parent_frame, data_key, unit=""):
label = ttk.Label(parent_frame, text=f"{label_text}",
font=("Arial", 14, "bold"),
background="#f9f9f9")
label.pack(side="left", padx=5)
value = ttk.Label(parent_frame, text="",
font=("Arial", 14),
background="#f9f9f9")
value.pack(side="left", padx=5)
setattr(self, f"{data_key}_value", value)
if unit:
setattr(self, f"{data_key}_unit", unit)
def create_page2(self):
self.mlu_figs = []
self.mlu_axs = []
self.mlu_xs = [[] for _ in range(4)]
self.mlu_ys = [[] for _ in range(4)]
self.mlu_lines = []
for i in range(4):
fig = plt.Figure(figsize=(5, 5), dpi=80)
ax = fig.add_subplot(111)
line, = ax.plot([], [], lw=2)
ax.set_xlabel('')
ax.set_ylabel('占用率 (%)')
ax.set_title(f'MLU 核 {i + 1} 占用率')
ax.set_xlim(0, 20)
ax.set_ylim(0, 100)
# 手动设置横轴刻度
ax.set_xticks(range(0, 21, 5))
canvas = FigureCanvasTkAgg(fig, master=self.pages[1])
if i < 2:
canvas.get_tk_widget().grid(row=0, column=i, padx=10, pady=10)
else:
canvas.get_tk_widget().grid(row=1, column=i - 2, padx=10, pady=10)
self.mlu_figs.append(fig)
self.mlu_axs.append(ax)
self.mlu_lines.append(line)
def create_page3(self):
self.cpu_figs = []
self.cpu_axs = []
self.cpu_xs = [[] for _ in range(4)]
self.cpu_ys = [[] for _ in range(4)]
self.cpu_lines = []
for i in range(4):
fig = plt.Figure(figsize=(5, 5), dpi=80)
ax = fig.add_subplot(111)
line, = ax.plot([], [], lw=2)
ax.set_xlabel('')
ax.set_ylabel('占用率 (%)')
ax.set_title(f'CPU 核 {i + 1} 占用率')
ax.set_xlim(0, 20)
ax.set_ylim(0, 100)
# 手动设置横轴刻度
ax.set_xticks(range(0, 21, 5))
canvas = FigureCanvasTkAgg(fig, master=self.pages[2])
if i < 2:
canvas.get_tk_widget().grid(row=0, column=i, padx=10, pady=10)
else:
canvas.get_tk_widget().grid(row=1, column=i - 2, padx=10, pady=10)
self.cpu_figs.append(fig)
self.cpu_axs.append(ax)
self.cpu_lines.append(line)
def create_page4(self):
self.memory_fig = plt.Figure(figsize=(10, 8), dpi=80)
self.memory_ax = self.memory_fig.add_subplot(111)
self.memory_line, = self.memory_ax.plot([], [], lw=2)
self.memory_ax.set_xlabel('')
self.memory_ax.set_ylabel('占用率 (%)')
self.memory_ax.set_title('内存占用率')
self.memory_ax.set_xlim(0, 20)
self.memory_ax.set_ylim(0, 100)
# 手动设置横轴刻度
self.memory_ax.set_xticks(range(0, 21, 5))
canvas = FigureCanvasTkAgg(self.memory_fig, master=self.pages[3])
canvas.get_tk_widget().pack(padx=10, pady=10)
self.memory_xs = []
self.memory_ys = []
def show_page(self, page_num):
for i, page in enumerate(self.pages):
if i == page_num - 1:
page.pack(side="right", fill="both", expand=True, padx=20, pady=20)
self.current_page = page_num
else:
page.pack_forget()
def update_device_info(self, info_str):
info = self.parse_info(info_str)
device = self.devices[self.current_device]
device.update(info)
self.update_display()
if not self.has_received_data:
self.has_received_data = True
self.initialize_plots()
def parse_info(self, info_str):
info = {}
sections = info_str.split("---------------END---------------")[0].split("\n\n")
for section in sections:
lines = [line.strip() for line in section.splitlines() if line.strip()]
if not lines:
continue
key = lines[0].split(":")[0].strip()
if key == "温度信息":
info.update(self.parse_temperature(lines[1:]))
elif key == "功率信息":
info.update(self.parse_power(lines[1:]))
elif key == "内存信息":
info.update(self.parse_memory(lines))
elif key == "带宽信息":
info.update(self.parse_bandwidth(lines[1:]))
elif key == "发送次数":
info.update(self.parse_send_count(lines))
elif key == "MLU信息":
info.update(self.parse_mlu_avg_usage(lines))
info.update(self.parse_mlu_core_usage(lines))
elif key == "CPU信息":
info.update(self.parse_cpu_avg_usage(lines))
info.update(self.parse_cpu_core_usage(lines))
return info
def parse_temperature(self, lines):
temp = 0
for line in lines:
if "C" in line:
try:
temp = max(temp, float(line.split(":")[1].strip().replace(" C", "")))
except (IndexError, ValueError):
continue
return {"temperature": temp}
def parse_power(self, lines):
power = 0
for line in lines:
if "W" in line:
try:
power = float(line.split(":")[1].strip().replace(" W", ""))
except (IndexError, ValueError):
continue
return {"power": power}
def parse_memory(self, lines):
total = 0
used = 0
physical_memory_section = False
for line in lines:
if "Physical Memory Usage" in line:
physical_memory_section = True
elif physical_memory_section:
if "Total" in line:
total = self.parse_memory_value(line)
elif "Used" in line:
used = self.parse_memory_value(line)
return {"memory": round(used / total * 100, 1) if total != 0 else 0}
def parse_memory_value(self, line):
try:
value = line.split(":")[1].strip()
num = float(value.split()[0])
unit = value.split()[1]
if unit == "MiB":
return num * 1024 * 1024
return num
except (IndexError, ValueError):
return 0
def parse_bandwidth(self, lines):
bandwidth = 0
for line in lines:
if "GB/s" in line:
try:
bandwidth = float(line.split(":")[1].strip().replace(" GB/s", ""))
except (IndexError, ValueError):
continue
return {"bandwidth": bandwidth}
def parse_send_count(self, lines):
send_count = 0
for line in lines:
if "次" in line:
try:
value_part = line.split(":")[-1].strip()
send_count = float(value_part.replace("次", ""))
except (IndexError, ValueError):
continue
return {"send_count": int(send_count)}
def parse_mlu_avg_usage(self, lines):
for line in lines:
if "MLU Average" in line:
try:
parts = line.split(':')
if len(parts) > 1:
mlu_avg_usage = float(parts[1].strip().replace("%", ""))
return {"mlu_avg_usage": mlu_avg_usage}
except (IndexError, ValueError):
continue
return {"mlu_avg_usage": 0}
def parse_cpu_avg_usage(self, lines):
for line in lines:
if "Device CPU Chip" in line:
try:
parts = line.split(':')
if len(parts) > 1:
cpu_avg_usage = float(parts[1].strip().replace("%", ""))
return {"cpu_avg_usage": cpu_avg_usage}
except (IndexError, ValueError):
continue
return {"cpu_avg_usage": 0}
def parse_mlu_core_usage(self, lines):
mlu_core_usage = [1, 1, 1, 1]
for line in lines:
if "MLU " in line and "%" in line:
try:
parts = line.split(':')
core_num = int(parts[0].split('MLU ')[1])
usage = float(parts[1].strip().replace("%", ""))
mlu_core_usage[core_num] = usage
except (IndexError, ValueError) as e:
pass
return {"mlu_core_usage": mlu_core_usage}
def parse_cpu_core_usage(self, lines):
cpu_core_usage = [1, 1, 1, 1]
for line in lines:
if "Device CPU Core" in line and "%" in line:
try:
parts = line.split(':')
core_num = int(parts[0].split('Device CPU Core ')[1])
usage = float(parts[1].strip().replace("%", ""))
cpu_core_usage[core_num] = usage
except (IndexError, ValueError) as e:
pass
return {"cpu_core_usage": cpu_core_usage}
def update_display(self):
device = self.devices[self.current_device]
# 新增ping检测逻辑
ip = device["ip"]
try:
result = subprocess.run(['ping', '-c', '1', '-W', '1', ip], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode == 0:
device["status"] = "在线"
else:
device["status"] = "离线"
except Exception as e:
print(f"Ping 检测出错: {e}")
device["status"] = "离线"
if self.current_page == 1:
self.ip_value.config(text=device["ip"])
self.status_value.config(text=device["status"],
foreground="green" if device["status"] == "在线" else "red")
self.temperature_value.config(text=f"{device['temperature']:.1f}°C")
self.power_value.config(text=f"{device['power']:.2f} W")
self.bandwidth_value.config(text=f"{device['bandwidth']:.1f} GB/s")
# self.send_count_value.config(text=device["send_count"])
self.mlu_avg_usage_value.config(text=f"{device['mlu_avg_usage']:.1f}%")
self.cpu_avg_usage_value.config(text=f"{device['cpu_avg_usage']:.1f}%")
self.update_page2_plots()
self.update_page3_plots()
self.update_page4_plots()
self.frame_count += 1
def start_udp_receive(self):
def read_config():
config = {}
try:
with open('config.txt', 'r') as config_file:
for line in config_file:
if '=' in line:
key, value = line.strip().split('=', 1)
config[key] = value
print("Read config success.")
except FileNotFoundError:
print("Unable to open config file!")
return None
return config
config = read_config()
if config is None:
return
server_ip = config.get('SERVER_IP')
server_port = int(config.get('SERVER_PORT'))
client_ip = config.get('CLIENT_IP')
client_port = int(config.get('CLIENT_PORT'))
print("ServerIP: {}".format(server_ip))
print("ServerPort: {}".format(server_port))
print("ClientIP: {}".format(client_ip))
print("ClientPort: {}".format(client_port))
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print("Set socket ok.")
try:
sock.bind((client_ip, client_port))
print("Bind success.")
except OSError:
print("Bind error!")
return
def receive_data():
print("Start receive data.")
try:
while True:
data, addr = sock.recvfrom(4096)
try:
info_str = data.decode('utf-8')
self.update_device_info(info_str)
except UnicodeDecodeError:
print("解码数据时出错,请检查数据编码。")
except OSError:
print("Receive data error!")
except KeyboardInterrupt:
print("Program interrupted by user.")
finally:
sock.close()
receive_thread = threading.Thread(target=receive_data)
receive_thread.daemon = True
receive_thread.start()
def initialize_plots(self):
if not self.page2_plots_initialized:
self.page2_plots_initialized = True
if not self.page3_plots_initialized:
self.page3_plots_initialized = True
if not self.page4_plots_initialized:
self.page4_plots_initialized = True
def update_page2_plots(self):
device = self.devices[self.current_device]
for i in range(4):
try:
usage = device["mlu_core_usage"][i]
if not isinstance(usage, (int, float)):
usage = 1
except (IndexError, KeyError):
usage = 1
# 确保只添加新的时间点
if not self.mlu_xs[i] or self.mlu_xs[i][-1] < self.frame_count:
self.mlu_xs[i].append(self.frame_count)
self.mlu_ys[i].append(usage)
else:
# 如果当前时间点已存在,更新该时间点的值
self.mlu_ys[i][-1] = usage
# 保证数据列表长度不超过20
if len(self.mlu_xs[i]) > 20:
self.mlu_xs[i] = self.mlu_xs[i][-20:]
self.mlu_ys[i] = self.mlu_ys[i][-20:]
# 调整横轴范围
start = max(self.mlu_xs[i][0], self.frame_count - 19)
end = start + 19
self.mlu_axs[i].set_xlim(start, end)
# 确保刻度是 5 的倍数
tick_start = (start // 5) * 5
tick_end = (end // 5) * 5
ticks = [tick for tick in range(tick_start, tick_end + 1, 5) if start <= tick <= end]
self.mlu_axs[i].set_xticks(ticks)
self.mlu_lines[i].set_data(self.mlu_xs[i], self.mlu_ys[i])
self.mlu_figs[i].canvas.draw()
def update_page3_plots(self):
device = self.devices[self.current_device]
for i in range(4):
try:
usage = device["cpu_core_usage"][i]
if not isinstance(usage, (int, float)):
usage = 1
except (IndexError, KeyError):
usage = 1
# 确保只添加新的时间点
if not self.cpu_xs[i] or self.cpu_xs[i][-1] < self.frame_count:
self.cpu_xs[i].append(self.frame_count)
self.cpu_ys[i].append(usage)
else:
# 如果当前时间点已存在,更新该时间点的值
self.cpu_ys[i][-1] = usage
# 保证数据列表长度不超过20
if len(self.cpu_xs[i]) > 20:
self.cpu_xs[i] = self.cpu_xs[i][-20:]
self.cpu_ys[i] = self.cpu_ys[i][-20:]
# 调整横轴范围
start = max(self.cpu_xs[i][0], self.frame_count - 19)
end = start + 19
self.cpu_axs[i].set_xlim(start, end)
# 确保刻度是 5 的倍数
tick_start = (start // 5) * 5
tick_end = (end // 5) * 5
ticks = [tick for tick in range(tick_start, tick_end + 1, 5) if start <= tick <= end]
self.cpu_axs[i].set_xticks(ticks)
self.cpu_lines[i].set_data(self.cpu_xs[i], self.cpu_ys[i])
self.cpu_figs[i].canvas.draw()
def update_page4_plots(self):
device = self.devices[self.current_device]
memory_usage = device["memory"]
# 确保只添加新的时间点
if not self.memory_xs or self.memory_xs[-1] < self.frame_count:
self.memory_xs.append(self.frame_count)
self.memory_ys.append(memory_usage)
else:
# 如果当前时间点已存在,更新该时间点的值
self.memory_ys[-1] = memory_usage
# 保证数据列表长度不超过20
if len(self.memory_xs) > 20:
self.memory_xs = self.memory_xs[-20:]
self.memory_ys = self.memory_ys[-20:]
# 调整横轴范围
start = max(self.memory_xs[0], self.frame_count - 19)
end = start + 19
self.memory_ax.set_xlim(start, end)
# 确保刻度是 5 的倍数
tick_start = (start // 5) * 5
tick_end = (end // 5) * 5
ticks = [tick for tick in range(tick_start, tick_end + 1, 5) if start <= tick <= end]
self.memory_ax.set_xticks(ticks)
self.memory_line.set_data(self.memory_xs, self.memory_ys)
self.memory_fig.canvas.draw()
if __name__ == "__main__":
app = DeviceManager()
app.mainloop()
该代码是如何处理服务端文本数据的
最新发布