灵芯派的系统检查

 

 

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
灵芯派测试程序 - 优化版本
全屏显示,增强各测试项功能,优化界面布局
"""

import os
import sys
import time
import subprocess
import threading
import psutil
import platform
import socket
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
from datetime import datetime
import random

# 尝试导入智能模块
try:
    from smartpi import base_driver
    SMART_MODULE_AVAILABLE = True
except ImportError:
    SMART_MODULE_AVAILABLE = False
    print("警告: 无法导入 smartpi.base_driver 模块")

class SmartPiTesterFullScreen:
    def __init__(self):
        # 创建主窗口
        self.root = tk.Tk()
        self.root.title("灵芯派测试系统")
        
        # 全屏设置
        self.root.attributes('-fullscreen', True)
        self.screen_width = self.root.winfo_screenwidth()
        self.screen_height = self.root.winfo_screenheight()
        
        # 设置ESC键退出全屏
        self.root.bind('<Escape>', self.exit_fullscreen)
        
        # 设置窗口关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
        
        # 颜色定义
        self.colors = {
            "background": "#2c3e50",     # 深蓝背景
            "header": "#3498db",         # 蓝色标题
            "success": "#27ae60",        # 绿色成功
            "error": "#e74c3c",          # 红色错误
            "warning": "#f39c12",        # 橙色警告
            "running": "#2980b9",        # 蓝色运行中
            "pending": "#7f8c8d",        # 灰色待测试
            "text": "#ecf0f1",           # 浅灰文字
            "subtext": "#bdc3c7",        # 深灰副文字
            "card_bg": "#34495e",        # 卡片背景
            "separator": "#2c3e50",      # 分隔线
            "progress": "#27ae60",       # 进度条绿色
            "shutdown": "#9b59b6"        # 关机按钮紫色
        }
        
        # 测试项目
        self.tests = [
            {"id": "system", "name": "系统信息", "func": self.test_system},
            {"id": "cpu", "name": "处理器", "func": self.test_cpu},
            {"id": "memory", "name": "内存", "func": self.test_memory},
            {"id": "storage", "name": "存储", "func": self.test_storage},
            {"id": "wifi", "name": "无线网络", "func": self.test_wifi},
            {"id": "network", "name": "互联网", "func": self.test_network},
            {"id": "display", "name": "显示屏", "func": self.test_display}
        ]
        
        # 测试状态
        self.test_status = {}
        for test in self.tests:
            self.test_status[test["id"]] = {
                "status": "待测试",  # 待测试, 测试中, 通过, 失败, 警告
                "message": "等待测试",
                "value": "",
                "progress": 0
            }
        
        # 测试结果
        self.test_results = {}
        self.current_test = 0
        self.testing_complete = False
        self.start_time = time.time()
        self.is_testing = False
        
        # 初始化UI
        self.setup_ui()
        
        # 启动界面更新
        self.update_ui()
        
    def exit_fullscreen(self, event=None):
        """退出全屏"""
        self.root.attributes('-fullscreen', False)
        
    def setup_ui(self):
        """设置用户界面"""
        # 设置背景色
        self.root.configure(bg=self.colors["background"])
        
        # 创建主框架容器
        self.main_frame = tk.Frame(self.root, bg=self.colors["background"])
        self.main_frame.pack(fill="both", expand=True, padx=10, pady=10)
        
        # 顶部标题区域
        self.create_header()
        
        # 测试卡片区域 - 使用固定高度的容器
        self.create_test_cards_area()
        
        # 日志输出区域
        self.create_log_area()
        
        # 底部控制区域
        self.create_footer()
        
    def create_header(self):
        """创建标题区域"""
        header_frame = tk.Frame(self.main_frame, bg=self.colors["header"])
        header_frame.pack(fill="x", pady=(0, 10))
        
        # 标题
        title_label = tk.Label(header_frame, text="灵芯派测试系统", 
                              font=("Helvetica", 28, "bold"), bg=self.colors["header"], 
                              fg=self.colors["text"])
        title_label.pack(pady=(15, 10))
        
        # 进度条
        self.progress_frame = tk.Frame(header_frame, bg=self.colors["header"])
        self.progress_frame.pack(fill="x", padx=20, pady=(0, 15))
        
        self.progress_label = tk.Label(self.progress_frame, text="进度: 0/7", 
                                      font=("Helvetica", 16), bg=self.colors["header"], 
                                      fg=self.colors["text"])
        self.progress_label.pack(side="left")
        
        # 配置进度条样式
        style = ttk.Style()
        style.theme_use('default')
        style.configure("green.Horizontal.TProgressbar", 
                       background=self.colors["progress"],
                       troughcolor=self.colors["separator"],
                       bordercolor=self.colors["separator"],
                       lightcolor=self.colors["progress"],
                       darkcolor=self.colors["progress"])
        
        self.progress_bar = ttk.Progressbar(self.progress_frame, length=250, 
                                          mode="determinate",
                                          style="green.Horizontal.TProgressbar")
        self.progress_bar.pack(side="right", padx=(10, 0))
        
    def create_test_cards_area(self):
        """创建测试卡片区域 - 使用简单的Frame,确保所有项可见"""
        # 创建一个固定高度的框架来容纳所有测试卡片
        test_area_frame = tk.Frame(self.main_frame, bg=self.colors["background"])
        test_area_frame.pack(fill="both", expand=True, pady=5)
        
        # 创建一个Frame来容纳所有测试卡片,不使用Canvas
        self.test_cards_container = tk.Frame(test_area_frame, bg=self.colors["background"])
        self.test_cards_container.pack(fill="both", expand=True)
        
        # 创建测试卡片
        self.test_card_widgets = {}
        for i, test in enumerate(self.tests):
            self.create_test_card(i, test)
        
    def create_test_card(self, index, test_info):
        """创建测试卡片 - 所有卡片统一大小,右侧只显示状态指示器"""
        card_frame = tk.Frame(self.test_cards_container, bg=self.colors["card_bg"], 
                             relief="flat", bd=1)
        card_frame.pack(fill="x", pady=2, padx=5, ipady=6)  # 调整内边距使大小一致
        
        # 使用网格布局,使左侧、中间、右侧分区更清晰
        card_frame.grid_columnconfigure(1, weight=1)  # 中间列可扩展
        
        # 左侧:编号和名称(合并到一列)
        left_frame = tk.Frame(card_frame, bg=self.colors["card_bg"])
        left_frame.grid(row=0, column=0, sticky="w", padx=12)
        
        # 测试编号和名称在同一行显示
        number_label = tk.Label(left_frame, text=f"{index+1:02d}.", 
                               font=("Helvetica", 14, "bold"), bg=self.colors["card_bg"], 
                               fg=self.colors["text"])
        number_label.pack(side="left", padx=(0, 8))
        
        name_label = tk.Label(left_frame, text=test_info["name"], 
                             font=("Helvetica", 14), bg=self.colors["card_bg"], 
                             fg=self.colors["text"])
        name_label.pack(side="left")
        
        # 中间:测试信息(占用最大空间)
        middle_frame = tk.Frame(card_frame, bg=self.colors["card_bg"])
        middle_frame.grid(row=0, column=1, sticky="ew", padx=10)
        
        # 消息标签(测试详情)
        message_label = tk.Label(middle_frame, text="等待测试", 
                                font=("Helvetica", 12), bg=self.colors["card_bg"], 
                                fg=self.colors["subtext"], anchor="w", justify="left")
        message_label.pack(side="left", fill="x", expand=True)
        
        # 右侧:状态指示器(紧凑显示)
        right_frame = tk.Frame(card_frame, bg=self.colors["card_bg"])
        right_frame.grid(row=0, column=2, sticky="e", padx=12)
        
        # 状态指示器(使用符号和紧凑文本)
        status_indicator = tk.Label(right_frame, text="", 
                                   font=("Helvetica", 20, "bold"), bg=self.colors["card_bg"], 
                                   fg=self.colors["pending"])
        status_indicator.pack(side="right", padx=(5, 0))
        
        # 存储小部件引用
        self.test_card_widgets[test_info["id"]] = {
            "frame": card_frame,
            "status_indicator": status_indicator,
            "message_label": message_label,
            "number_label": number_label,
            "name_label": name_label,
            "left_frame": left_frame,
            "middle_frame": middle_frame,
            "right_frame": right_frame
        }
        
    def create_log_area(self):
        """创建日志输出区域"""
        log_frame = tk.Frame(self.main_frame, bg=self.colors["background"])
        log_frame.pack(fill="both", expand=False, pady=(5, 10), ipady=5)
        
        # 日志标题
        log_title = tk.Label(log_frame, text="测试输出日志", 
                            font=("Helvetica", 16, "bold"), bg=self.colors["background"], 
                            fg=self.colors["text"])
        log_title.pack(anchor="w", pady=(0, 5))
        
        # 创建文本区域和滚动条
        text_frame = tk.Frame(log_frame, bg=self.colors["background"])
        text_frame.pack(fill="both", expand=True)
        
        # 创建文本区域
        self.log_text = tk.Text(
            text_frame,
            height=6,
            width=50,
            font=("Courier", 12),
            bg="#1e272e",
            fg="#ffffff",
            relief="flat",
            wrap=tk.WORD
        )
        
        # 创建滚动条并设置样式
        log_scrollbar = ttk.Scrollbar(text_frame, orient="vertical", 
                                     command=self.log_text.yview)
        
        # 配置日志滚动条样式
        style = ttk.Style()
        style.configure("Log.Vertical.TScrollbar", 
                       gripcount=0,
                       background="#3498db",
                       darkcolor="#3498db",
                       lightcolor="#3498db",
                       troughcolor="#1e272e",
                       bordercolor="#1e272e",
                       arrowcolor="#ecf0f1",
                       width=20)
        
        log_scrollbar.configure(style="Log.Vertical.TScrollbar")
        self.log_text.configure(yscrollcommand=log_scrollbar.set)
        
        # 布局文本区域和滚动条
        self.log_text.pack(side="left", fill="both", expand=True)
        log_scrollbar.pack(side="right", fill="y")
        
        # 禁止用户编辑日志
        self.log_text.config(state="disabled")
        
    def create_footer(self):
        """创建底部区域"""
        footer_frame = tk.Frame(self.main_frame, bg=self.colors["header"])
        footer_frame.pack(fill="x", side="bottom", pady=(0, 5))
        
        # 左侧:运行时间
        self.time_label = tk.Label(footer_frame, text="运行时间: 0秒", 
                                  font=("Helvetica", 16), bg=self.colors["header"], 
                                  fg=self.colors["text"])
        self.time_label.pack(side="left", padx=25, pady=10)
        
        # 右侧:控制按钮区域
        button_frame = tk.Frame(footer_frame, bg=self.colors["header"])
        button_frame.pack(side="right", padx=25, pady=2)
        
        # 主要操作按钮 - 初始为"开始测试",测试结束后变为"关机"
        # 显著增大按钮高度和宽度
        self.action_button = tk.Button(
            button_frame, 
            text="开始测试", 
            command=self.start_testing,
            font=("Helvetica", 18, "bold"),  # 增大字体
            bg=self.colors["success"],
            fg=self.colors["text"],
            relief="raised",
            width=14,  # 增加宽度
            height=2,   # 增加高度(行数)
            cursor="hand2",
            bd=3        # 增加边框宽度
        )
        self.action_button.pack(side="left", padx=15, ipady=2)  # 增加内部和外部间距
        
        # 退出按钮 - 同样显著增大
        self.exit_button = tk.Button(
            button_frame, 
            text="退出程序", 
            command=self.on_closing,
            font=("Helvetica", 22, "bold"),  # 增大字体
            bg=self.colors["error"],
            fg=self.colors["text"],
            relief="raised",
            width=14,  # 增加宽度
            height=2,   # 增加高度(行数)
            cursor="hand2",
            bd=3        # 增加边框宽度
        )
        self.exit_button.pack(side="left", padx=15, ipady=2)  # 增加内部和外部间距
        
    def shutdown_device(self):
        """执行关机操作"""
        if not SMART_MODULE_AVAILABLE:
            self.log_message("错误: 智能模块不可用,无法执行关机操作")
            # 尝试使用系统命令关机
            try:
                self.log_message("尝试使用系统命令关机...")
                result = subprocess.run(["sudo", "shutdown", "-h", "now"], 
                                      capture_output=True, text=True)
                self.log_message(f"关机命令执行结果: {result.returncode}")
            except Exception as e:
                self.log_message(f"关机失败: {e}")
            return
            
        try:
            self.log_message("正在执行关机操作...")
            
            # 显示关机确认对话框
            response = messagebox.askyesno(
                "确认关机",
                "确定要关闭设备吗?\n\n系统将在10秒后关闭。",
                parent=self.root
            )
            
            if response:
                self.log_message("用户确认关机,正在执行关机命令...")
                
                # 禁用关机按钮,防止重复点击
                self.action_button.config(state="disabled", text="关机中...")
                
                # 添加一个延迟,让用户看到日志
                self.root.after(1000, self.execute_shutdown)
            else:
                self.log_message("用户取消关机操作")
                
        except Exception as e:
            self.log_message(f"关机操作失败: {e}")
            self.action_button.config(state="normal", text="关 机")
            
    def execute_shutdown(self):
        """执行实际的关机操作"""
        try:
            # 调用base_driver的shut_down方法
            base_driver.shut_down()
            self.log_message("关机命令已发送")
        except Exception as e:
            self.log_message(f"调用关机函数失败: {e}")
            # 尝试备用方法
            try:
                self.log_message("尝试使用备用关机方法...")
                subprocess.run(["sudo", "shutdown", "-h", "+1"], 
                             capture_output=True, text=True)
                self.log_message("备用关机命令已发送,设备将在1分钟后关闭")
            except Exception as e2:
                self.log_message(f"备用关机也失败: {e2}")
                
    def log_message(self, message):
        """添加日志消息"""
        self.log_text.config(state="normal")
        timestamp = datetime.now().strftime("%H:%M:%S")
        self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
        self.log_text.see(tk.END)  # 滚动到底部
        self.log_text.config(state="disabled")
        
    def update_test_status(self, test_id, status, message="", value=""):
        """更新测试状态"""
        if test_id in self.test_status:
            self.test_status[test_id]["status"] = status
            self.test_status[test_id]["message"] = message
            self.test_status[test_id]["value"] = value
            
            # 更新UI
            self.root.after(0, self.update_test_card_ui, test_id)
            
            # 添加到日志
            test_name = next((t["name"] for t in self.tests if t["id"] == test_id), test_id)
            log_msg = f"{test_name}: {message}"
            if value:
                log_msg += f" ({value})"
            self.log_message(log_msg)
    
    def update_test_card_ui(self, test_id):
        """更新测试卡片UI - 右侧只显示状态,卡片背景色根据测试结果变化"""
        if test_id in self.test_card_widgets and test_id in self.test_status:
            widgets = self.test_card_widgets[test_id]
            status_info = self.test_status[test_id]
            status = status_info["status"]
            
            # 状态颜色和指示器符号配置,包含背景色
            status_config = {
                "通过": {
                    "color": self.colors["success"], 
                    "indicator_text": "",  # 对勾符号
                    "bg_color": "#2ecc71",      # 浅绿色背景
                    "text_color": "#ffffff",    # 白色文字
                    "message_color": "#ffffff",  # 白色消息
                    "sub_text_color": "#d5f4e6"  # 浅绿色副文字
                },
                "失败": {
                    "color": self.colors["error"], 
                    "indicator_text": "",  # 叉号符号
                    "bg_color": "#e74c3c",      # 浅红色背景
                    "text_color": "#ffffff",    # 白色文字
                    "message_color": "#ffffff",  # 白色消息
                    "sub_text_color": "#fadbd8"  # 浅红色副文字
                },
                "警告": {
                    "color": self.colors["warning"], 
                    "indicator_text": "!",  # 感叹号
                    "bg_color": "#f39c12",      # 浅橙色背景
                    "text_color": "#ffffff",    # 白色文字
                    "message_color": "#ffffff",  # 白色消息
                    "sub_text_color": "#fdebd0"  # 浅橙色副文字
                },
                "测试中": {
                    "color": self.colors["running"], 
                    "indicator_text": "",  # 旋转箭头
                    "bg_color": "#3498db",      # 浅蓝色背景
                    "text_color": "#ffffff",    # 白色文字
                    "message_color": "#ffffff",  # 白色消息
                    "sub_text_color": "#d6eaf8"  # 浅蓝色副文字
                },
                "待测试": {
                    "color": self.colors["pending"], 
                    "indicator_text": "",  # 空心圆
                    "bg_color": self.colors["card_bg"],  # 默认卡片背景
                    "text_color": self.colors["text"],   # 默认文字颜色
                    "message_color": self.colors["subtext"],  # 默认消息颜色
                    "sub_text_color": self.colors["subtext"]  # 默认副文字颜色
                }
            }
            
            config = status_config.get(status, status_config["待测试"])
            
            # 更新卡片框架背景色
            widgets["frame"].config(bg=config["bg_color"])
            
            # 更新所有子框架背景色
            widgets["left_frame"].config(bg=config["bg_color"])
            widgets["middle_frame"].config(bg=config["bg_color"])
            widgets["right_frame"].config(bg=config["bg_color"])
            
            # 更新状态指示器
            widgets["status_indicator"].config(
                text=config["indicator_text"],
                fg=config["color"],
                bg=config["bg_color"]
            )
            
            # 更新左侧标签颜色
            widgets["number_label"].config(
                fg=config["text_color"],
                bg=config["bg_color"]
            )
            widgets["name_label"].config(
                fg=config["text_color"],
                bg=config["bg_color"]
            )
            
            # 更新消息显示(中间区域)
            message = status_info["message"]
            if status_info["value"]:
                message = f"{message} | {status_info['value']}"
            
            # 如果消息太长,适当截断
            if len(message) > 60:
                message = message[:57] + "..."
                
            widgets["message_label"].config(
                text=message,
                fg=config["message_color"],
                bg=config["bg_color"]
            )
            
            # 如果是测试中状态,设置卡片背景色轻微闪烁效果
            if status == "测试中":
                current_color = widgets["frame"].cget("bg")
                if current_color == "#3498db":  # 蓝色
                    new_color = "#2980b9"  # 深蓝色
                else:
                    new_color = "#3498db"  # 蓝色
                    
                # 更新所有框架的背景色
                widgets["frame"].config(bg=new_color)
                widgets["left_frame"].config(bg=new_color)
                widgets["middle_frame"].config(bg=new_color)
                widgets["right_frame"].config(bg=new_color)
                
                # 更新所有标签的背景色
                widgets["status_indicator"].config(bg=new_color)
                widgets["number_label"].config(bg=new_color)
                widgets["name_label"].config(bg=new_color)
                widgets["message_label"].config(bg=new_color)
    
    def update_progress(self):
        """更新进度条"""
        completed = sum(1 for t in self.test_status.values() if t["status"] in ["通过", "失败", "警告"])
        total = len(self.tests)
        
        progress_percent = int((completed / total) * 100) if total > 0 else 0
        self.progress_bar["value"] = progress_percent
        self.progress_label.config(text=f"进度: {completed}/{total}")
    
    def update_time(self):
        """更新时间显示"""
        elapsed = int(time.time() - self.start_time)
        minutes = elapsed // 60
        seconds = elapsed % 60
        self.time_label.config(text=f"运行时间: {minutes:02d}:{seconds:02d}")
        
    def update_ui(self):
        """更新UI"""
        self.update_progress()
        self.update_time()
        
        # 检查是否所有测试完成
        if not self.is_testing:
            all_done = all(t["status"] in ["通过", "失败", "警告"] for t in self.test_status.values())
            if all_done and not self.testing_complete:
                self.testing_complete = True
                # 测试完成后将按钮变为"关机"
                self.action_button.config(
                    text="关 机",
                    command=self.shutdown_device,
                    bg=self.colors["shutdown"],
                    state="normal",
                    font=("Helvetica", 22, "bold"),
                    width=14,
                    height=2,
                    bd=3
                )
                self.log_message("测试完成!")
                self.log_message("点击'关机'按钮关闭设备")
        
        # 继续更新
        self.root.after(1000, self.update_ui)
    
    def run_command(self, cmd, timeout=5):
        """执行命令"""
        try:
            result = subprocess.run(
                cmd, shell=True,
                capture_output=True,
                text=True,
                timeout=timeout
            )
            return result.returncode == 0, result.stdout.strip()
        except subprocess.TimeoutExpired:
            return False, "超时"
        except Exception as e:
            return False, str(e)
    
    def test_system(self):
        """增强系统信息测试"""
        test_id = "system"
        self.update_test_status(test_id, "测试中", "获取系统信息")
        
        try:
            uname = platform.uname()
            system_name = uname.system
            machine = uname.machine
            kernel = uname.release
            
            # 获取更多系统信息
            uptime_seconds = psutil.boot_time()
            current_time = time.time()
            uptime = current_time - uptime_seconds
            uptime_str = self.format_time(uptime)
            
            # 获取CPU架构详细信息
            arch_display = "未知"
            if "aarch64" in machine:
                arch_display = "ARM64"
            elif "arm" in machine:
                arch_display = "ARM"
            else:
                arch_display = machine[:10]
            
            # 获取Python版本
            python_version = platform.python_version()
            
            # 获取主机名
            hostname = socket.gethostname()
            
            # 获取发行版信息
            distro_info = "未知"
            try:
                with open('/etc/os-release', 'r') as f:
                    for line in f:
                        if line.startswith('PRETTY_NAME='):
                            distro_info = line.split('=')[1].strip().strip('"')
                            break
            except:
                pass
            
            message = f"{system_name} {kernel}"
            value = f"{arch_display} 运行:{uptime_str}"
            
            self.update_test_status(test_id, "通过", message, value)
            return True
            
        except Exception as e:
            self.update_test_status(test_id, "失败", f"错误: {str(e)[:20]}")
            return False
    
    def format_time(self, seconds):
        """格式化时间显示"""
        days = int(seconds // (24 * 3600))
        seconds = seconds % (24 * 3600)
        hours = int(seconds // 3600)
        seconds %= 3600
        minutes = int(seconds // 60)
        seconds = int(seconds % 60)
        
        if days > 0:
            return f"{days}天{hours}小时"
        elif hours > 0:
            return f"{hours}小时{minutes}分"
        else:
            return f"{minutes}分{seconds}秒"
    
    def test_cpu(self):
        """增强CPU测试"""
        test_id = "cpu"
        self.update_test_status(test_id, "测试中", "测试CPU性能")
        
        try:
            # CPU信息
            cpu_count = os.cpu_count() or 1
            
            # 获取CPU型号和架构详细信息
            cpu_model = "RK3566"
            cpu_arch = "未知"
            cpu_bogo = "未知"
            
            try:
                with open('/proc/cpuinfo', 'r') as f:
                    content = f.read()
                    
                    # 提取CPU型号
                    import re
                    model_match = re.search(r'model name\s*:\s*(.+)', content)
                    if model_match:
                        cpu_model = model_match.group(1).strip()
                    
                    # 提取BogoMIPS
                    bogo_match = re.search(r'BogoMIPS\s*:\s*(.+)', content)
                    if bogo_match:
                        cpu_bogo = bogo_match.group(1).strip()
                    
                    # 提取架构
                    arch_match = re.search(r'CPU architecture\s*:\s*(\d+)', content)
                    if arch_match:
                        cpu_arch = f"ARMv{arch_match.group(1)}"
            except:
                pass
            
            # 多阶段性能测试
            self.update_test_status(test_id, "测试中", "性能测试阶段1")
            
            # 阶段1: 整数运算性能
            start_time = time.time()
            total = 0
            for i in range(1000000):
                total += i * i
            int_time = time.time() - start_time
            
            # 阶段2: 浮点运算性能
            self.update_test_status(test_id, "测试中", "性能测试阶段2")
            start_time = time.time()
            total = 0.0
            for i in range(500000):
                total += i * 1.5
            float_time = time.time() - start_time
            
            # 阶段3: 多线程测试
            self.update_test_status(test_id, "测试中", "性能测试阶段3")
            start_time = time.time()
            
            def compute_chunk(start, end):
                result = 0
                for i in range(start, end):
                    result += i * i
                return result
            
            # 使用线程池
            import concurrent.futures
            chunk_size = 250000
            with concurrent.futures.ThreadPoolExecutor(max_workers=cpu_count) as executor:
                futures = []
                for i in range(cpu_count):
                    start = i * chunk_size
                    end = (i + 1) * chunk_size
                    futures.append(executor.submit(compute_chunk, start, end))
                
                total = sum(f.result() for f in futures)
            
            multi_time = time.time() - start_time
            
            # 计算总分
            total_time = int_time + float_time + multi_time
            
            # 评估性能
            if total_time < 2.0:
                performance = "极佳"
                status = "通过"
            elif total_time < 4.0:
                performance = "良好"
                status = "通过"
            elif total_time < 6.0:
                performance = "一般"
                status = "警告"
            else:
                performance = "较慢"
                status = "警告"
            
            # 获取CPU频率
            cpu_freq = "未知"
            try:
                freq_file = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"
                if os.path.exists(freq_file):
                    with open(freq_file, 'r') as f:
                        freq_khz = int(f.read().strip())
                        cpu_freq = f"{freq_khz/1000:.1f}MHz"
            except:
                pass
            
            message = f"{cpu_count}核心"
            value = f"{performance} {total_time:.1f}s"
            
            self.update_test_status(test_id, status, message, f"{cpu_model} {cpu_freq}")
            return status == "通过"
            
        except Exception as e:
            self.update_test_status(test_id, "失败", "测试失败")
            return False
    
    def test_memory(self):
        """增强内存测试"""
        test_id = "memory"
        self.update_test_status(test_id, "测试中", "测试内存")
        
        try:
            mem = psutil.virtual_memory()
            total_gb = mem.total / (1024**3)
            used_gb = mem.used / (1024**3)
            percent = mem.percent
            
            # 获取交换分区信息
            swap = psutil.swap_memory()
            swap_gb = swap.total / (1024**3) if swap.total > 0 else 0
            
            # 内存速度测试
            self.update_test_status(test_id, "测试中", "内存速度测试")
            
            test_size = 10 * 1024 * 1024  # 10MB
            try:
                # 写入测试
                data = bytearray(test_size)
                start = time.time()
                for i in range(0, test_size, 4096):
                    data[i] = i % 256
                write_time = time.time() - start
                
                # 读取测试
                start = time.time()
                total = 0
                for i in range(0, test_size, 4096):
                    total += data[i]
                read_time = time.time() - start
                
                if write_time > 0 and read_time > 0:
                    write_speed = test_size / write_time / 1024 / 1024
                    read_speed = test_size / read_time / 1024 / 1024
                    avg_speed = (write_speed + read_speed) / 2
                    
                    if avg_speed > 200:
                        speed_rating = "极快"
                    elif avg_speed > 100:
                        speed_rating = "快速"
                    elif avg_speed > 50:
                        speed_rating = "正常"
                    else:
                        speed_rating = "较慢"
                    
                    speed_text = f"{avg_speed:.1f}MB/s"
                else:
                    speed_text = "测速失败"
                    speed_rating = "未知"
            except MemoryError:
                speed_text = "内存不足"
                speed_rating = "未知"
            except:
                speed_text = "测速错误"
                speed_rating = "未知"
            
            # 评估内存状态
            if percent < 70:
                status = "通过"
                health = "良好"
            elif percent < 90:
                status = "警告"
                health = "正常"
            else:
                status = "失败"
                health = "紧张"
            
            message = f"{total_gb:.1f}GB LPDDR4X"
            if swap_gb > 0:
                value = f"使用{percent:.0f}% 交换{swap_gb:.1f}GB {speed_rating}"
            else:
                value = f"使用{percent:.0f}% {speed_rating}"
            
            self.update_test_status(test_id, status, message, value)
            return status == "通过"
            
        except Exception as e:
            self.update_test_status(test_id, "失败", "测试失败")
            return False
    
    def test_storage(self):
        """增强存储测试"""
        test_id = "storage"
        self.update_test_status(test_id, "测试中", "测试存储设备")
        
        try:
            # 获取存储信息
            disk = psutil.disk_usage('/')
            total_gb = disk.total / (1024**3)
            free_gb = disk.free / (1024**3)
            percent = disk.percent
            
            # 获取文件系统信息
            fstype = "未知"
            try:
                fstype_cmd, fstype_output = self.run_command("df -T / | tail -1 | awk '{print $2}'")
                if fstype_cmd:
                    fstype = fstype_output.strip()
            except:
                pass
            
            # 多阶段速度测试
            self.update_test_status(test_id, "测试中", "存储速度测试")
            
            test_file = "/tmp/rk3566_speed_test.tmp"
            test_size = 10 * 1024 * 1024  # 10MB
            
            # 阶段1: 顺序写入测试
            start = time.time()
            try:
                with open(test_file, 'wb') as f:
                    data = os.urandom(test_size)
                    f.write(data)
                write_time = time.time() - start
                
                # 阶段2: 顺序读取测试
                start = time.time()
                with open(test_file, 'rb') as f:
                    _ = f.read()
                read_time = time.time() - start
                
                # 阶段3: 随机读取测试
                start = time.time()
                with open(test_file, 'rb') as f:
                    for _ in range(1000):
                        f.seek(random.randint(0, test_size - 4096))
                        _ = f.read(4096)
                random_read_time = time.time() - start
                
                # 清理
                if os.path.exists(test_file):
                    os.remove(test_file)
                
                # 计算速度
                if write_time > 0 and read_time > 0:
                    write_speed = test_size / write_time / 1024 / 1024
                    read_speed = test_size / read_time / 1024 / 1024
                    random_read_speed = (1000 * 4096) / random_read_time / 1024 / 1024
                    
                    # 综合评分
                    avg_speed = (write_speed + read_speed + random_read_speed) / 3
                    
                    if avg_speed > 50:
                        speed_rating = "极快"
                        status = "通过"
                    elif avg_speed > 30:
                        speed_rating = "快速"
                        status = "通过"
                    elif avg_speed > 15:
                        speed_rating = "正常"
                        status = "通过"
                    elif avg_speed > 5:
                        speed_rating = "较慢"
                        status = "警告"
                    else:
                        speed_rating = "很慢"
                        status = "警告"
                    
                    speed_text = f"写:{write_speed:.1f}/读:{read_speed:.1f}/随机:{random_read_speed:.1f}MB/s"
                else:
                    speed_text = "测速失败"
                    speed_rating = "未知"
                    status = "警告"
                    
            except Exception as e:
                speed_text = "测速错误"
                speed_rating = "未知"
                status = "警告"
            
            message = f"{total_gb:.0f}GB EMMC"
            value = f"剩{free_gb:.0f}GB {fstype} {speed_rating}"
            
            self.update_test_status(test_id, status, message, value)
            return status == "通过"
            
        except Exception as e:
            self.update_test_status(test_id, "失败", "测试失败")
            return False
    
    def test_wifi(self):
        """增强WiFi测试"""
        test_id = "wifi"
        self.update_test_status(test_id, "测试中", "检测WiFi模块")
        
        try:
            # 1. 检查网络接口
            success, ip_output = self.run_command("ip link show | grep -E 'wlan|wl'", timeout=2)
            
            if not success or not ip_output:
                self.update_test_status(test_id, "失败", "未找到WiFi接口")
                return False
            
            # 2. 获取WiFi详细信息
            iw_check, _ = self.run_command("which iw", timeout=2)
            
            if iw_check:
                # 获取连接状态
                iw_link, iw_output = self.run_command("iw dev wlan0 link 2>/dev/null", timeout=3)
                
                if iw_link and iw_output:
                    if "Connected" in iw_output:
                        # 获取SSID
                        ssid = "未知网络"
                        ssid_cmd, ssid_output = self.run_command("iw dev wlan0 info | grep 'ssid' | awk '{print $2}'", timeout=2)
                        if ssid_cmd and ssid_output:
                            ssid = ssid_output.strip()
                        
                        # 获取信号强度
                        signal_strength = ""
                        for line in iw_output.split('\n'):
                            if 'signal:' in line:
                                signal_strength = line.split('signal:')[1].strip()
                                break
                        
                        # 获取连接速度
                        tx_bitrate = ""
                        for line in iw_output.split('\n'):
                            if 'tx bitrate:' in line:
                                tx_bitrate = line.split('tx bitrate:')[1].strip()
                                break
                        
                        # 获取频率
                        freq = ""
                        for line in iw_output.split('\n'):
                            if 'freq:' in line:
                                freq = line.split('freq:')[1].strip()
                                break
                        
                        # 构建显示信息
                        info_parts = []
                        if signal_strength:
                            info_parts.append(f"信号:{signal_strength}")
                        if tx_bitrate:
                            info_parts.append(f"速度:{tx_bitrate}")
                        if freq:
                            freq_mhz = int(freq)
                            if freq_mhz > 5000:
                                info_parts.append("5GHz")
                            else:
                                info_parts.append("2.4GHz")
                        
                        info_text = " ".join(info_parts) if info_parts else "已连接"
                        
                        self.update_test_status(test_id, "通过", f"已连接: {ssid}", info_text)
                        return True
                    else:
                        self.update_test_status(test_id, "警告", "WiFi未连接", "接口就绪")
                        return True
            
            # 3. 如果没有iw命令,尝试使用iwconfig
            else:
                iwconfig_check, _ = self.run_command("which iwconfig", timeout=2)
                if iwconfig_check:
                    success, output = self.run_command("iwconfig wlan0 2>/dev/null | grep -i essid", timeout=2)
                    
                    if success and output:
                        if "off/any" not in output:
                            essid = "未知网络"
                            if '"' in output:
                                essid = output.split('ESSID:"')[1].split('"')[0]
                            
                            # 尝试获取信号强度
                            signal_cmd, signal_output = self.run_command("iwconfig wlan0 | grep -i signal", timeout=2)
                            signal_info = ""
                            if signal_cmd and signal_output:
                                signal_info = signal_output.strip()[:30]
                            
                            if signal_info:
                                self.update_test_status(test_id, "通过", "WiFi已连接", f"{essid[:15]} {signal_info}")
                            else:
                                self.update_test_status(test_id, "通过", "WiFi已连接", essid[:15])
                            return True
                        else:
                            self.update_test_status(test_id, "警告", "WiFi未连接", "接口就绪")
                            return True
            
            # 4. 最后检查IP地址
            try:
                interfaces = psutil.net_if_addrs()
                if 'wlan0' in interfaces:
                    for addr in interfaces['wlan0']:
                        if addr.family == socket.AF_INET:
                            # 检查网络连接质量
                            ping_success, ping_output = self.run_command("ping -c 2 -W 1 8.8.8.8 2>&1 | grep 'time='", timeout=3)
                            if ping_success:
                                # 提取延迟
                                times = []
                                for line in ping_output.split('\n'):
                                    if 'time=' in line:
                                        time_str = line.split('time=')[1].split(' ')[0]
                                        try:
                                            times.append(float(time_str))
                                        except:
                                            pass
                                
                                if times:
                                    avg_latency = sum(times) / len(times)
                                    self.update_test_status(test_id, "通过", "WiFi已连接", f"延迟:{avg_latency:.1f}ms")
                                else:
                                    self.update_test_status(test_id, "通过", "WiFi已连接", "已分配IP")
                            else:
                                self.update_test_status(test_id, "通过", "WiFi已连接", "已分配IP")
                            return True
                    
                    self.update_test_status(test_id, "警告", "WiFi接口存在", "未连接网络")
                    return True
                else:
                    self.update_test_status(test_id, "失败", "WiFi接口不存在")
                    return False
                    
            except Exception as e:
                self.update_test_status(test_id, "警告", "WiFi检测异常", str(e)[:20])
                return True
                
        except Exception as e:
            self.update_test_status(test_id, "失败", f"测试失败: {str(e)}")
            return False
    
    def test_network(self):
        """增强网络连接测试"""
        test_id = "network"
        self.update_test_status(test_id, "测试中", "测试互联网连接")
        
        try:
            # 测试多个网站,包含DNS解析和HTTP连接
            test_hosts = [
                ("www.baidu.com", "百度"),
                ("github.com", "github"),
                ("gitee.com", "gitee")
            ]
            
            reachable = 0
            response_times = []
            detailed_results = []
            
            for host, name in test_hosts:
                try:
                    start = time.time()
                    socket.gethostbyname(host)
                    dns_time = (time.time() - start) * 1000
                    
                    # 尝试HTTP连接
                    try:
                        import urllib.request
                        start = time.time()
                        response = urllib.request.urlopen(f"http://{host}", timeout=3)
                        http_time = (time.time() - start) * 1000
                        if response.status in [200, 204]:
                            reachable += 1
                            response_times.append(dns_time)
                            detailed_results.append(f"{name}:DNS{dns_time:.0f}ms HTTP{http_time:.0f}ms")
                        else:
                            detailed_results.append(f"{name}:DNS正常 HTTP{response.status}")
                    except:
                        # DNS正常但HTTP失败
                        reachable += 0.5  # 部分分数
                        response_times.append(dns_time)
                        detailed_results.append(f"{name}:DNS{dns_time:.0f}ms HTTP失败")
                        
                except socket.gaierror:
                    detailed_results.append(f"{name}:DNS失败")
                except Exception as e:
                    detailed_results.append(f"{name}:错误")
            
            # 评估结果
            if reachable >= 2.5:
                avg_response = sum(response_times) / len(response_times) if response_times else 0
                status = "通过"
                message = "互联网正常"
                value = f"延迟:{avg_response:.0f}ms"
            elif reachable >= 1.5:
                status = "警告"
                message = "连接不稳定"
                value = "部分可达"
            else:
                status = "失败"
                message = "无法连接"
                value = "请检查网络"
            
            # 记录详细结果到日志
            for result in detailed_results:
                self.log_message(f"网络测试: {result}")
            
            self.update_test_status(test_id, status, message, value)
            return status == "通过"
            
        except Exception as e:
            self.update_test_status(test_id, "失败", "测试失败")
            return False
    
    def test_display(self):
        """增强显示测试"""
        test_id = "display"
        self.update_test_status(test_id, "测试中", "测试显示功能")
        
        try:
            # 阶段1: 显示检测
            time.sleep(0.3)
            
            # 阶段2: 颜色测试
            self.update_test_status(test_id, "测试中", "颜色测试")
            time.sleep(0.3)
            
            # 阶段3: 分辨率检测
            resolution = f"{self.screen_width}x{self.screen_height}"
            display_info = f"{resolution} 全屏显示"
            
            # 尝试获取显示设备信息
            try:
                xrandr_cmd, xrandr_output = self.run_command("xrandr 2>/dev/null | grep ' connected'", timeout=2)
                if xrandr_cmd and xrandr_output:
                    display_info = f"{resolution} {xrandr_output.split()[0]}"
            except:
                pass
            
            self.update_test_status(test_id, "通过", "显示屏正常", display_info)
            return True
                
        except Exception as e:
            self.update_test_status(test_id, "失败", "显示测试失败")
            return False
    
    def run_all_tests(self):
        """运行所有测试"""
        # 重置按钮状态
        self.action_button.config(text="测试中...", state="disabled", bg=self.colors["running"])
        
        self.log_message("=" * 60)
        self.log_message("灵芯派测试系统启动")
        self.log_message(f"屏幕分辨率: {self.screen_width}x{self.screen_height}")
        self.log_message("=" * 60)
        
        # 重置测试状态
        for test in self.tests:
            self.test_status[test["id"]] = {
                "status": "待测试",
                "message": "等待测试",
                "value": "",
                "progress": 0
            }
        
        self.testing_complete = False
        self.start_time = time.time()
        
        # 开始测试
        self.is_testing = True
        
        # 在单独的线程中运行所有测试
        threading.Thread(target=self.run_tests_sequence, daemon=True).start()
    
    def run_tests_sequence(self):
        """按顺序运行所有测试"""
        test_functions = {
            "system": self.test_system,
            "cpu": self.test_cpu,
            "memory": self.test_memory,
            "storage": self.test_storage,
            "wifi": self.test_wifi,
            "network": self.test_network,
            "display": self.test_display
        }
        
        # 执行测试
        for test in self.tests:
            test_id = test["id"]
            if test_id in test_functions:
                try:
                    test_functions[test_id]()
                    time.sleep(0.5)  # 测试间隔
                except Exception as e:
                    self.update_test_status(test_id, "失败", "测试异常")
                    time.sleep(0.5)
        
        # 测试完成
        self.is_testing = False
        
        # 输出最终结果到日志
        self.log_message("\n" + "=" * 60)
        self.log_message("测试完成!")
        
        passed = sum(1 for t in self.test_status.values() if t["status"] == "通过")
        failed = sum(1 for t in self.test_status.values() if t["status"] == "失败")
        total = len(self.tests)
        
        self.log_message(f"总测试: {total}项 | 通过: {passed}项 | 失败: {failed}项")
        self.log_message("=" * 60)
    
    def start_testing(self):
        """开始测试按钮回调"""
        if not self.is_testing:
            threading.Thread(target=self.run_all_tests, daemon=True).start()
    
    def on_closing(self):
        """窗口关闭事件"""
        response = messagebox.askyesno(
            "确认退出",
            "确定要退出测试程序吗?",
            parent=self.root
        )
        
        if response:
            self.log_message("程序退出")
            self.root.destroy()
    
    def run(self):
        """运行主程序"""
        self.log_message("灵芯派测试系统启动...")
        
        # 检查智能模块
        if SMART_MODULE_AVAILABLE:
            self.log_message("智能模块已加载")
        else:
            self.log_message("警告: 智能模块不可用,关机功能可能受限")
            
        self.root.mainloop()

def check_dependencies():
    """检查依赖"""
    try:
        import psutil
        print("[OK] psutil模块已安装")
        return True
    except ImportError:
        print("[ERROR] 需要安装psutil模块")
        print("请运行: pip3 install psutil")
        return False

def main():
    """主函数"""
    print("启动灵芯派测试系统 - 优化版本")
    print("按ESC键可以退出全屏模式")
    print()
    
    # 检查依赖
    if not check_dependencies():
        return 1
    
    # 检查运行权限
    if os.geteuid() == 0:
        print("[警告] 不建议使用root权限运行本程序")
        print()
    
    try:
        # 创建并运行测试器
        tester = SmartPiTesterFullScreen()
        tester.run()
        
    except KeyboardInterrupt:
        print()
        print("程序被用户中断")
    except Exception as e:
        print()
        print(f"程序运行错误: {e}")
        import traceback
        traceback.print_exc()
        return 1
    
    return 0

if __name__ == "__main__":
    sys.exit(main())

 

posted @ 2025-12-10 08:47  aiplus  阅读(5)  评论(0)    收藏  举报
悬浮按钮示例