Update for v2.0rc5

This commit is contained in:
James Deng 2024-09-02 15:34:14 +08:00
parent 6840e3ee3c
commit bf0e94711a
11 changed files with 758 additions and 243 deletions

View file

@ -1,7 +1,9 @@
from typing import Union from typing import Union
import os import os
import json import json
from cricket.singleton import SingletonMeta, singleton
@singleton
class SimpleLang(object): class SimpleLang(object):
def __init__(self, file = None): def __init__(self, file = None):
file = file if file else 'languages.json' file = file if file else 'languages.json'

View file

@ -37,7 +37,9 @@
"wifi": "WiFi", "wifi": "WiFi",
"wifi_mac": "WiFi Mac", "wifi_mac": "WiFi Mac",
"cpu_temp": "CPU温度" "cpu_temp": "CPU温度",
"wifi_signal_init":"正在检测WiFi信号强度",
"peripheral_test":"外设性能测试"
}, },
"en": { "en": {
"title": "Factory Test", "title": "Factory Test",
@ -77,6 +79,8 @@
"wifi": "WiFi", "wifi": "WiFi",
"wifi_mac": "WiFi Mac", "wifi_mac": "WiFi Mac",
"cpu_temp": "CPU_Temp" "cpu_temp": "CPU_Temp",
"wifi_signal_init":"Checking WiFi signal strength",
"peripheral_test":"Peripheral performance testing"
} }
} }

View file

@ -0,0 +1,32 @@
import logging
import os
import inspect
import logging.handlers
import sys
class LoggerManager:
def __init__(self, name='LoggerManager', console_level=logging.INFO):
self.logger = logging.getLogger(name)
self.logger.setLevel(logging.DEBUG) # Set the root log level to DEBUG to capture all logs
# Create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s [%(filename)s:%(lineno)d]')
# Create and configure the console processor
self.console_handler = logging.StreamHandler(sys.stdout)
self.console_handler.setLevel(console_level)
self.console_handler.setFormatter(formatter)
# Add a processor to the logger
self.logger.addHandler(self.console_handler)
# Creating a file processor
self.file_handler = logging.FileHandler("/root/factorytest.log")
self.file_handler.setLevel(logging.INFO)
self.file_handler.setFormatter(formatter)
self.logger.addHandler(self.file_handler)
def get_logger(self):
return self.logger

58
cricket/cricket/macro.py Normal file
View file

@ -0,0 +1,58 @@
from cricket.model import TestMethod, TestCase, TestModule
PASS_COLOR = '#28C025'
FAIL_COLOR = '#E32C2E'
PASSSTR = "PASS"
FAILSTR = "FAIL"
INITSTR = "NA"
READ_ERROR = 'read error'
# Display constants for test status
STATUS = {
TestMethod.STATUS_PASS: {
'description': u'通过',
'symbol': u'\u25cf',
'tag': 'pass',
'color': PASS_COLOR
},
TestMethod.STATUS_SKIP: {
'description': u'Skipped',
'symbol': u'S',
'tag': 'skip',
'color': '#259EBF'
},
TestMethod.STATUS_FAIL: {
'description': u'失败',
'symbol': u'F',
'tag': 'fail',
'color': FAIL_COLOR
},
TestMethod.STATUS_EXPECTED_FAIL: {
'description': u'Expected\n failure',
'symbol': u'X',
'tag': 'expected',
'color': '#3C25BF'
},
TestMethod.STATUS_UNEXPECTED_SUCCESS: {
'description': u'Unexpected\n success',
'symbol': u'U',
'tag': 'unexpected',
'color': '#C82788'
},
TestMethod.STATUS_ERROR: {
'description': 'Error',
'symbol': u'E',
'tag': 'error',
'color': '#E4742C'
},
}
STATUS_DEFAULT = {
'description': 'Not\nexecuted',
'symbol': u'',
'tag': None,
'color': '#BFBFBF',
}

View file

@ -0,0 +1,271 @@
from PyQt5.QtCore import Qt, QTimer, QUrl, QObject, QThread, pyqtSignal
from PyQt5.QtGui import QColor, QPixmap, QImage, QPalette
from PyQt5.QtWidgets import (QWidget, QDialog, QFrame, QHBoxLayout, QVBoxLayout, QLabel,
QPushButton,QLineEdit, QCheckBox,QComboBox, QSizePolicy, QSpacerItem, QTextEdit)
import subprocess
import re
import os
from typing import Tuple, List
from cricket.lang import SimpleLang
from cricket.loggermanager import LoggerManager
from cricket.macro import *
import time
class PeripheralTestWindow(QDialog):
def __init__(self, parent):
super().__init__(parent)
self._parent = parent
self.sl = SimpleLang()
self.info_msg_index = 0
self.log_manager = LoggerManager(name='PeripheralLogger')
self.custom_logger = self.log_manager.get_logger()
self.name_dict = {'EMMC':"EMMC", "SSD":"SSD", 'TF':'TF Card', 'FlashDrive':'U盘'}
self.th_dict = {'EMMC':50.0*0.25, 'SSD':380*0.25, 'TF':40.0*0.20, 'FlashDrive':50.0*0.25} # key corresponds to name
self.size_dict = {'EMMC':'1GB'}
self.test_sequence = []
self.current_test_index = 0
self.initUI()
self.test_sequence.append({"type":"storage", "name": "EMMC", "control":self.emmc_control, "output_file":'/dev/mmcblk2', "seek":0})
self.test_sequence.append({"type":"storage", "name": "SSD", "control":self.ssd_control, "output_file":'/dev/nvme0n1', "seek":0})
self.test_sequence.append({"type":"storage", "name": "TF", "control":self.tf_card_control, "output_file":'/dev/mmcblk0', "seek":10240})
self.test_sequence.append({"type":"storage", "name": "FlashDrive", "control":self.flash_drive_control, "output_file":'/dev/sda', "seek":0})
def initUI(self):
font_size = 32
self.setGeometry(200,200, 800, 800)
self.setStyleSheet(f"font-size: {font_size}px;")
self.setWindowTitle('Peripheral Test')
layout = QVBoxLayout()
self.setLayout(layout)
# frame, [check_box, commbox, speed_show, result_show]
# EMMC
emmc_frame, self.emmc_control = self.gen_storage_device_testing_ui(self.name_dict['EMMC'], font_size=font_size)
layout.addWidget(emmc_frame)
# SSD
ssd_frame, self.ssd_control = self.gen_storage_device_testing_ui(self.name_dict['SSD'], font_size=font_size)
layout.addWidget(ssd_frame)
# TF Card
tf_card_frame, self.tf_card_control = self.gen_storage_device_testing_ui(self.name_dict['TF'], font_size=font_size)
layout.addWidget(tf_card_frame)
# U盘
flash_drive_frame, self.flash_drive_control = self.gen_storage_device_testing_ui(self.name_dict['FlashDrive'], font_size=font_size)
layout.addWidget(flash_drive_frame)
# Create a text edit box that displays the run information
self.text_edit = QTextEdit(self)
self.text_edit.setReadOnly(True)
self.text_edit.setFixedHeight(100)
self.text_edit.setStyleSheet("font-size: 18px;")
layout.addWidget(self.text_edit)
# call button
self.test_button = QPushButton('一键测试', self)
self.test_button.setStyleSheet(f"font-size: {font_size}px;")
self.test_button.clicked.connect(self.test_all)
layout.addWidget(self.test_button)
def gen_storage_device_testing_ui(self, storage_name, font_size=32) -> Tuple[QFrame, List[QWidget]]:
storage_frame = QFrame(self)
# storage_frame.setAutoFillBackground(True)
storage_frame.setPalette(QPalette(QColor('darkgray')))
storage_layout = QHBoxLayout(storage_frame)
spacer = QSpacerItem(40, 20, QSizePolicy.Fixed, QSizePolicy.Minimum)
storage_layout.addSpacerItem(spacer)
# check
check_box_frame = QWidget(storage_frame)
check_box_layout = QHBoxLayout(check_box_frame)
storage_check_box = QCheckBox(storage_frame)
storage_check_box.setStyleSheet("""
QCheckBox::indicator {
width: 32px;
height: 32px;
}
""")
storage_check_box.setChecked(True)
check_box_layout.addWidget(storage_check_box)
storage_name_label = QLabel(storage_name, check_box_frame)
storage_name_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
check_box_layout.addWidget(storage_name_label)
storage_layout.addWidget(check_box_frame)
spacer = QSpacerItem(60, 20, QSizePolicy.Fixed, QSizePolicy.Minimum)
storage_layout.addSpacerItem(spacer)
# write size
write_size_frame = QWidget(storage_frame)
write_size_frame_layout = QHBoxLayout(write_size_frame)
write_text_label = QLabel('写入大小:', write_size_frame)
write_text_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
write_text_label.setStyleSheet(f"font-size: {font_size}px;")
write_size_frame_layout.addWidget(write_text_label)
storage_comm_box = QComboBox(write_size_frame)
storage_comm_box.addItems(['1GB', '2GB', '3GB', '4GB'])
storage_comm_box.setStyleSheet(f"font-size: {font_size}px;")
storage_comm_box.currentText()
write_size_frame_layout.addWidget(storage_comm_box)
storage_layout.addWidget(write_size_frame)
spacer = QSpacerItem(60, 20, QSizePolicy.Fixed, QSizePolicy.Minimum)
storage_layout.addSpacerItem(spacer)
# speed result
speed_frame = QWidget(storage_frame)
speed_frame_layout = QHBoxLayout(speed_frame)
speed_text_label = QLabel('速度:', speed_frame)
speed_text_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
speed_text_label.setStyleSheet(f"font-size: {font_size}px;")
speed_frame_layout.addWidget(speed_text_label)
storage_speed_show = QLabel(' ', speed_frame)
storage_speed_show.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
storage_speed_show.setStyleSheet(f"font-size: {font_size}px;")
speed_frame_layout.addWidget(storage_speed_show)
storage_layout.addWidget(speed_frame)
spacer = QSpacerItem(32, 20, QSizePolicy.Fixed, QSizePolicy.Minimum)
storage_layout.addSpacerItem(spacer)
# speed result judgment
judgment_frame = QWidget(storage_frame)
judgment_frame_layout = QHBoxLayout(judgment_frame)
judgment_text_label = QLabel('结果:', judgment_frame)
judgment_text_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
judgment_text_label.setStyleSheet(f"font-size: {font_size}px;")
judgment_frame_layout.addWidget(judgment_text_label)
judgment_show = QLabel('未测', judgment_frame)
judgment_show.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
judgment_show.setStyleSheet(f"font-size: {font_size}px;")
judgment_frame_layout.addWidget(judgment_show)
storage_layout.addWidget(judgment_frame)
return storage_frame, [storage_check_box, storage_comm_box, storage_speed_show, judgment_show]
def test_all(self):
self.test_button.setEnabled(False)
self.text_edit.append(f"{self.info_msg_index} : 开始测试所有被勾选项目................")
self.info_msg_index += 1
self.run_next_test()
def run_next_test(self):
if self.current_test_index < len(self.test_sequence):
test_info = self.test_sequence[self.current_test_index]
if test_info["type"] == "storage":
of = test_info["output_file"]
if test_info["name"] == "FlashDrive":
of = self.find_sda_to_sdf_devices()
self.test_storage_wrapper(test_info["control"], test_info["name"], output_file=of, seek=test_info["seek"])
elif test_info["type"] == "network":
pass
else:
self.test_button.setEnabled(True)
self.text_edit.append(f"{self.info_msg_index} : 所有测试项目已完成")
self.info_msg_index += 1
self.current_test_index = 0
# storage function
def test_storage_wrapper(self, storage_control, test_name, output_file='/dev/mmcblk2', seek=0):
if storage_control[0].isChecked():
self.text_edit.append(f"{self.info_msg_index} : 开始测试{self.name_dict[test_name]}写入速度................")
self.info_msg_index += 1
size = storage_control[1].currentText()
size = int(size[0]) * 1024
self.thread_storage = StorageTestThread(output_file=output_file, size=size, seek=seek)
self.thread_storage.task_finished.connect(
lambda msg, storage_control=storage_control, test_name=test_name:self.test_storage_postprocessing(msg, storage_control, test_name))
self.thread_storage.start()
else:
self.current_test_index += 1
self.run_next_test()
def test_storage_postprocessing(self, msg, storage_control, test_name):
ret = msg[0]
speed = msg[1]
time_cst = msg[2]
if type(ret) == str:
storage_control[2].setText(ret)
else:
storage_control[2].setText(f"{speed} MB/S")
th = self.th_dict[test_name]
if speed>=th:
storage_control[3].setText(f"通过")
storage_control[3].setStyleSheet(f"color: {PASS_COLOR};")
else:
storage_control[3].setText(f"失败")
storage_control[3].setStyleSheet(f"color: {FAIL_COLOR};")
self.text_edit.append(f"{self.info_msg_index} : {self.name_dict[test_name]}写入速度测试完成, 耗时为{time_cst}s, 返回:{ret}")
self.info_msg_index += 1
test_info = self.test_sequence[self.current_test_index]
if test_info["type"] == "storage":
self.thread_storage.quit()
self.thread_storage.wait()
del self.thread_storage
elif test_info["type"] == "network":
pass
# Move to the next test item
self.current_test_index += 1
self.run_next_test()
def find_sda_to_sdf_devices(self):
try:
file_list = ['/dev/'+sub for sub in ['sda', 'sdb', 'sdc', 'sdd', 'sde', 'sdf']]
for device in file_list:
if os.path.exists(device):
return device
return '/dev/noexist'
except Exception as e:
return '/dev/noexist'
class StorageTestThread(QThread):
# Defines a signal that notifies the main thread when a thread task has completed
task_finished = pyqtSignal(list)
def __init__(self, output_file='', size='', seek=''):
super().__init__()
self.output_file = output_file
self.size = size
self.seek = seek
self.speed = None
self.ret = None
def run(self):
t_start = time.time()
self.ret = self.test_storage_write_speed(output_file=self.output_file, count=self.size, seek=self.seek)
t_period = time.time() - t_start
speed = float(self.size)/t_period
self.speed = round(speed, 1)
self.task_finished.emit([self.ret, self.speed, round(t_period, 1)])
def test_storage_write_speed(self, output_file, bs="1M", count=1024, seek=0):
try:
if not os.path.exists(output_file):
return "设备不存在"
command = ["dd", f"if=/dev/zero", f"of={output_file}", f"bs={bs}", f"count={count}", "oflag=direct", f"seek={seek}"]
result = subprocess.run(command, stderr=subprocess.PIPE, text=True)
return 0
except Exception as e:
return f"dd命令执行异常{e}"

View file

@ -40,76 +40,30 @@ from importlib import import_module
from cricket.model import TestMethod, TestCase, TestModule from cricket.model import TestMethod, TestCase, TestModule
from cricket.executor import Executor from cricket.executor import Executor
from cricket.lang import SimpleLang from cricket.lang import SimpleLang
from cricket.macro import *
PASS_COLOR = '#28C025' from cricket.statusview import StatusView
FAIL_COLOR = '#E32C2E' from cricket.peripheraltestview import PeripheralTestWindow
from cricket.wifimacview import WifiMacView
# Display constants for test status
STATUS = {
TestMethod.STATUS_PASS: {
'description': u'通过',
'symbol': u'\u25cf',
'tag': 'pass',
'color': '#28C025',
},
TestMethod.STATUS_SKIP: {
'description': u'Skipped',
'symbol': u'S',
'tag': 'skip',
'color': '#259EBF'
},
TestMethod.STATUS_FAIL: {
'description': u'失败',
'symbol': u'F',
'tag': 'fail',
'color': '#E32C2E'
},
TestMethod.STATUS_EXPECTED_FAIL: {
'description': u'Expected\n failure',
'symbol': u'X',
'tag': 'expected',
'color': '#3C25BF'
},
TestMethod.STATUS_UNEXPECTED_SUCCESS: {
'description': u'Unexpected\n success',
'symbol': u'U',
'tag': 'unexpected',
'color': '#C82788'
},
TestMethod.STATUS_ERROR: {
'description': 'Error',
'symbol': u'E',
'tag': 'error',
'color': '#E4742C'
},
}
STATUS_DEFAULT = {
'description': 'Not\nexecuted',
'symbol': u'',
'tag': None,
'color': '#BFBFBF',
}
class MainWindow(QMainWindow, SimpleLang): class MainWindow(QMainWindow):
def __init__(self, root): def __init__(self, root):
super().__init__() super().__init__()
self.sl = SimpleLang()
self._project = None self._project = None
self.test_table = {} self.test_table = {}
self.test_list = {} self.test_list = {}
self.run_status = {} self.run_status = {}
self.executor = {} self.executor = {}
self.usb_list = [] self.usb_list = []
self.set_brightness() self.set_brightness()
self.wifi_mac_Ok = False self.wifi_mac_Ok = False
self.root = root self.root = root
self.setWindowTitle(self.get_text('title')) self.setWindowTitle(self.sl.get_text('title'))
# self.showFullScreen() # self.showFullScreen()
self.font_size = 14 self.font_size = 14
@ -117,6 +71,8 @@ class MainWindow(QMainWindow, SimpleLang):
# Set up the main content for the window. # Set up the main content for the window.
self._setup_main_content() self._setup_main_content()
self.peripheral_test_view = PeripheralTestWindow(self)
# Set up listeners for runner events. # Set up listeners for runner events.
Executor.bind('test_status_update', self.on_executorStatusUpdate) Executor.bind('test_status_update', self.on_executorStatusUpdate)
Executor.bind('test_start', self.on_executorTestStart) Executor.bind('test_start', self.on_executorTestStart)
@ -127,7 +83,7 @@ class MainWindow(QMainWindow, SimpleLang):
###################################################### ######################################################
# Internal GUI layout methods. # Internal GUI layout methods.
###################################################### ######################################################
def _setup_main_content(self): def _setup_main_content(self):
''' '''
The button toolbar runs as a horizontal area at the top of the GUI. The button toolbar runs as a horizontal area at the top of the GUI.
@ -146,30 +102,30 @@ class MainWindow(QMainWindow, SimpleLang):
toolbar = QFrame(self.content) toolbar = QFrame(self.content)
layout = QGridLayout(toolbar) layout = QGridLayout(toolbar)
self.run_all_button = QPushButton(self.get_text('run_all_button'), toolbar) self.run_all_button = QPushButton(self.sl.get_text('run_all_button'), toolbar)
self.run_all_button.clicked.connect(self.cmd_run_all) self.run_all_button.clicked.connect(self.cmd_run_all)
self.run_all_button.setFocus() self.run_all_button.setFocus()
layout.addWidget(self.run_all_button, 0, 0) layout.addWidget(self.run_all_button, 0, 0)
self.run_selected_button = QPushButton(self.get_text('run_selected_button'), self.run_selected_button = QPushButton(self.sl.get_text('run_selected_button'),
toolbar) toolbar)
self.run_selected_button.setDisabled(True) self.run_selected_button.setDisabled(True)
self.run_selected_button.clicked.connect(self.cmd_run_selected) self.run_selected_button.clicked.connect(self.cmd_run_selected)
layout.addWidget(self.run_selected_button, 0, 1) layout.addWidget(self.run_selected_button, 0, 1)
self.stop_button = QPushButton(self.get_text('stop_button'), toolbar) self.stop_button = QPushButton(self.sl.get_text('stop_button'), toolbar)
self.stop_button.setDisabled(True) self.stop_button.setDisabled(True)
self.stop_button.clicked.connect(self.cmd_stop) self.stop_button.clicked.connect(self.cmd_stop)
layout.addWidget(self.stop_button, 0 , 2) layout.addWidget(self.stop_button, 0 , 2)
self.reboot_button = QPushButton(self.get_text('reboot_button'), toolbar) self.reboot_button = QPushButton(self.sl.get_text('reboot_button'), toolbar)
self.reboot_button.clicked.connect(self.cmd_reboot) self.reboot_button.clicked.connect(self.cmd_reboot)
layout.addWidget(self.reboot_button, 0, 3) layout.addWidget(self.reboot_button, 0, 3)
self.poweroff_button = QPushButton(self.get_text('poweroff_button'), toolbar) self.poweroff_button = QPushButton(self.sl.get_text('poweroff_button'), toolbar)
self.poweroff_button.clicked.connect(self.cmd_poweroff) self.poweroff_button.clicked.connect(self.cmd_poweroff)
layout.addWidget(self.poweroff_button, 0, 4) layout.addWidget(self.poweroff_button, 0, 4)
self.content_layout.addWidget(toolbar) self.content_layout.addWidget(toolbar)
# tests # tests
@ -188,7 +144,7 @@ class MainWindow(QMainWindow, SimpleLang):
self._setup_usb_frame(5, 0, 1, 1) self._setup_usb_frame(5, 0, 1, 1)
self._setup_test_table('manual', 6, 0, 4, 1) self._setup_test_table('manual', 6, 0, 4, 1)
camera_box = QGroupBox(self.get_text('camera'), self.tests) camera_box = QGroupBox(self.sl.get_text('camera'), self.tests)
camera_box_layout = QVBoxLayout(camera_box) camera_box_layout = QVBoxLayout(camera_box)
video_widget = QVideoWidget(camera_box) video_widget = QVideoWidget(camera_box)
self.media_player = QMediaPlayer() self.media_player = QMediaPlayer()
@ -220,39 +176,39 @@ class MainWindow(QMainWindow, SimpleLang):
# set main content to window # set main content to window
self.setCentralWidget(self.content) self.setCentralWidget(self.content)
def _setup_info(self): def _setup_info(self):
info = QFrame(self.content) info = QFrame(self.content)
info_layout = QGridLayout(info) info_layout = QGridLayout(info)
cpu_model = QLabel(f'{self.get_text("cpu_model")}: {self._get_CPU_model()}', info) cpu_model = QLabel(f'{self.sl.get_text("cpu_model")}: {self._get_CPU_model()}', info)
info_layout.addWidget(cpu_model, 0, 0) info_layout.addWidget(cpu_model, 0, 0)
cpu_freq = QLabel(f'{self.get_text("cpu_freq")}: {self._get_CPU_freq()} GHz', info) cpu_freq = QLabel(f'{self.sl.get_text("cpu_freq")}: {self._get_CPU_freq()} GHz', info)
info_layout.addWidget(cpu_freq, 0, 1) info_layout.addWidget(cpu_freq, 0, 1)
self.cpu_temp = QLabel(f'{self.get_text("cpu_temp")}: {self._get_CPU_Temp()} °C', info) self.cpu_temp = QLabel(f'{self.sl.get_text("cpu_temp")}: {self._get_CPU_Temp()} °C', info)
self._cpu_temp_timer = QTimer(self) self._cpu_temp_timer = QTimer(self)
self._cpu_temp_timer.timeout.connect(self.on_cpuTempUpdate) self._cpu_temp_timer.timeout.connect(self.on_cpuTempUpdate)
self._cpu_temp_timer.start(1000) self._cpu_temp_timer.start(1000)
info_layout.addWidget(self.cpu_temp, 0, 2) info_layout.addWidget(self.cpu_temp, 0, 2)
ddr_size = QLabel(f'{self.get_text("ddr_size")}: {self._get_DDR_size()} GB', info) ddr_size = QLabel(f'{self.sl.get_text("ddr_size")}: {self._get_DDR_size()} GB', info)
info_layout.addWidget(ddr_size, 0, 3) info_layout.addWidget(ddr_size, 0, 3)
emmc_size = QLabel(f'{self.get_text("emmc_size")}: {self._get_eMMC_size()} GB', info) emmc_size = QLabel(f'{self.sl.get_text("emmc_size")}: {self._get_eMMC_size()} GB', info)
info_layout.addWidget(emmc_size, 0, 4) info_layout.addWidget(emmc_size, 0, 4)
ssd_size = QLabel(f'{self.get_text("ssd_size")}: {self._get_SSD_size()} GB', info) ssd_size = QLabel(f'{self.sl.get_text("ssd_size")}: {self._get_SSD_size()} GB', info)
info_layout.addWidget(ssd_size, 0, 5) info_layout.addWidget(ssd_size, 0, 5)
self.hdmi_model = QLabel(f'{self.get_text("hdmi_model")}: None', info) self.hdmi_model = QLabel(f'{self.sl.get_text("hdmi_model")}: None', info)
info_layout.addWidget(self.hdmi_model, 0, 6) info_layout.addWidget(self.hdmi_model, 0, 6)
product_name = QLabel(f'{self.get_text("product_name")}: {self._get_product_name()}', info) product_name = QLabel(f'{self.sl.get_text("product_name")}: {self._get_product_name()}', info)
info_layout.addWidget(product_name, 0, 7) info_layout.addWidget(product_name, 0, 7)
fw_version = QLabel(f'{self.get_text("fw_version")}: {self._get_fw_version()}', info) fw_version = QLabel(f'{self.sl.get_text("fw_version")}: {self._get_fw_version()}', info)
info_layout.addWidget(fw_version, 0, 8) info_layout.addWidget(fw_version, 0, 8)
self.content_layout.addWidget(info) self.content_layout.addWidget(info)
@ -260,11 +216,11 @@ class MainWindow(QMainWindow, SimpleLang):
def _setup_test_table(self, name, row, column, row_span, column_span): def _setup_test_table(self, name, row, column, row_span, column_span):
module = import_module(name) module = import_module(name)
box = QGroupBox(module.MODULE_NAME[self.current_lang], self.tests) box = QGroupBox(module.MODULE_NAME[self.sl.current_lang], self.tests)
box.setStyleSheet("QGroupBox::title { font-weight: bold; }") box.setStyleSheet("QGroupBox::title { font-weight: bold; }")
layout = QVBoxLayout(box) layout = QVBoxLayout(box)
columns = self.get_text('test_table_head') columns = self.sl.get_text('test_table_head')
table = QTableWidget(box) table = QTableWidget(box)
table.setStyleSheet('QTableWidget { background-color: black; color: white; }') table.setStyleSheet('QTableWidget { background-color: black; color: white; }')
@ -287,14 +243,14 @@ class MainWindow(QMainWindow, SimpleLang):
self.tests_layout.addWidget(box, row, column, row_span, column_span) self.tests_layout.addWidget(box, row, column, row_span, column_span)
def _setup_others(self): def _setup_others(self):
self.others_box = QGroupBox(self.get_text('others'), self.tests) self.others_box = QGroupBox(self.sl.get_text('others'), self.tests)
self.others_box_layout = QVBoxLayout(self.others_box) self.others_box_layout = QVBoxLayout(self.others_box)
# Comment the code below if you don't need it # Comment the code below if you don't need it
# item # item
self._setup_others_item() self._setup_others_item()
# status # status
self._setup_others_status() self._setup_others_status()
@ -304,8 +260,9 @@ class MainWindow(QMainWindow, SimpleLang):
self.others_box_layout.addWidget(self.others_item) self.others_box_layout.addWidget(self.others_item)
self._setup_others_test() self._setup_others_test()
self._setup_wifi_mac() self.wifi_mac_view = WifiMacView(self.others_item)
self.others_item_layout.addWidget(self.wifi_mac_view)
sn = self._get_sn() sn = self._get_sn()
if sn: if sn:
@ -320,38 +277,49 @@ class MainWindow(QMainWindow, SimpleLang):
lcd_frame.setAutoFillBackground(True) lcd_frame.setAutoFillBackground(True)
lcd_frame.setPalette(QPalette(QColor('darkgray'))) lcd_frame.setPalette(QPalette(QColor('darkgray')))
lcd_layout = QHBoxLayout(lcd_frame) lcd_layout = QHBoxLayout(lcd_frame)
# lcd_button = QPushButton(self.get_text('lcd'), lcd_frame) # lcd_button = QPushButton(self.get_text('lcd'), lcd_frame)
# lcd_button.clicked.connect(self.cmd_lcd) # lcd_button.clicked.connect(self.cmd_lcd)
# lcd_layout.addWidget(lcd_button) # lcd_layout.addWidget(lcd_button)
# lcd backlight # lcd backlight
backlight_label = QLabel(self.get_text('lcd_backlight')+" :", lcd_frame) backlight_label = QLabel(self.sl.get_text('lcd_backlight')+" :", lcd_frame)
backlight_label.setAlignment( Qt.AlignVCenter) backlight_label.setAlignment( Qt.AlignVCenter)
lcd_layout.addWidget(backlight_label) lcd_layout.addWidget(backlight_label)
# Create a slider # Create a slider
lcd_slider = QSlider(Qt.Horizontal, lcd_frame) lcd_slider = QSlider(Qt.Horizontal, lcd_frame)
lcd_slider.setRange(0, 255) lcd_slider.setRange(0, 255)
lcd_slider.setValue(128) lcd_slider.setValue(128)
lcd_slider.valueChanged.connect(self.set_brightness) lcd_slider.valueChanged.connect(self.set_brightness)
lcd_layout.addWidget(lcd_slider) lcd_layout.addWidget(lcd_slider)
label_brightness = QLabel("128", lcd_frame) label_brightness = QLabel("128", lcd_frame)
label_brightness.setAlignment(Qt.AlignRight | Qt.AlignVCenter) label_brightness.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
label_brightness.setFixedWidth(24) label_brightness.setFixedWidth(24)
lcd_slider.valueChanged.connect(lambda value: label_brightness.setText(str(value))) lcd_slider.valueChanged.connect(lambda value: label_brightness.setText(str(value)))
lcd_layout.addWidget(label_brightness) lcd_layout.addWidget(label_brightness)
others_test_layout.addWidget(lcd_frame) others_test_layout.addWidget(lcd_frame)
# peripheral test
peripheral_frame = QFrame(others_test)
peripheral_frame.setAutoFillBackground(True)
peripheral_frame.setPalette(QPalette(QColor('darkgray')))
peripheral_layout = QHBoxLayout(peripheral_frame)
self.peripheral_test_button = QPushButton(self.sl.get_text('peripheral_test'), peripheral_frame)
self.peripheral_test_button.setAutoFillBackground(True)
self.peripheral_test_button.clicked.connect(self.cmd_peripheral_test)
peripheral_layout.addWidget(self.peripheral_test_button)
others_test_layout.addWidget(peripheral_frame)
# aging test # aging test
aging_test = QFrame(others_test) aging_test = QFrame(others_test)
aging_test.setAutoFillBackground(True) aging_test.setAutoFillBackground(True)
aging_test.setPalette(QPalette(QColor('darkgray'))) aging_test.setPalette(QPalette(QColor('darkgray')))
aging_test_layout = QVBoxLayout(aging_test) aging_test_layout = QVBoxLayout(aging_test)
self.aging_button = QPushButton(self.get_text('aging_test'), aging_test) self.aging_button = QPushButton(self.sl.get_text('aging_test'), aging_test)
self.aging_button.setAutoFillBackground(True) self.aging_button.setAutoFillBackground(True)
self.aging_button.clicked.connect(self.cmd_aging) self.aging_button.clicked.connect(self.cmd_aging)
aging_test_layout.addWidget(self.aging_button) aging_test_layout.addWidget(self.aging_button)
@ -374,7 +342,7 @@ class MainWindow(QMainWindow, SimpleLang):
aging_duration = QFrame(aging_test) aging_duration = QFrame(aging_test)
aging_duration_layout = QHBoxLayout(aging_duration) aging_duration_layout = QHBoxLayout(aging_duration)
aging_duration_label = QLabel(f'{self.get_text("aging_duration")}: ', aging_duration) aging_duration_label = QLabel(f'{self.sl.get_text("aging_duration")}: ', aging_duration)
aging_duration_layout.addWidget(aging_duration_label) aging_duration_layout.addWidget(aging_duration_label)
self.aging_duration_choice = QComboBox(aging_test) self.aging_duration_choice = QComboBox(aging_test)
self.aging_duration_choice.addItems(['4', '8', '12', '24']) self.aging_duration_choice.addItems(['4', '8', '12', '24'])
@ -383,40 +351,16 @@ class MainWindow(QMainWindow, SimpleLang):
aging_test_layout.addWidget(aging_duration) aging_test_layout.addWidget(aging_duration)
others_test_layout.addWidget(aging_test) others_test_layout.addWidget(aging_test)
self.others_item_layout.addWidget(others_test) self.others_item_layout.addWidget(others_test)
def _setup_wifi_mac(self):
mac = self._get_wifi_mac() # wifi signal part
if mac:
self._setup_wifi_mac_qrcode(mac)
else:
QTimer.singleShot(2000, self._setup_wifi_mac)
# wifi signal part
def _setup_others_status(self): def _setup_others_status(self):
self.others_status = QFrame(self.others_box)
self.others_status_layout = QHBoxLayout(self.others_status)
self.others_box_layout.addWidget(self.others_status)
self._setup_wifi_view()
def _setup_wifi_view(self): self.others_status_view = StatusView(self.others_box)
wifi = QFrame(self.others_status) self.others_box_layout.addWidget(self.others_status_view)
wifi_layout = QGridLayout(wifi)
self.others_status_layout.addWidget(wifi)
wifi_label = QLabel(f'{self.get_text("wifi")}: ', wifi)
wifi_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
wifi_layout.addWidget(wifi_label, 0, 0)
self.wifi_signal_level = QProgressBar(wifi)
self.wifi_signal_level.setAlignment(Qt.AlignLeft)
self.wifi_signal_level.setMaximum(5)
wifi_layout.addWidget(self.wifi_signal_level, 0, 1)
QTimer.singleShot(3000, lambda: self.on_wifiStatusUpdate())
# [start] Check the usb to see if the device is inserted # [start] Check the usb to see if the device is inserted
def usb_loop(self, label, usb_path): def usb_loop(self, label, usb_path):
while True: while True:
@ -441,17 +385,17 @@ class MainWindow(QMainWindow, SimpleLang):
def _setup_usb_frame(self, row, column, row_span, column_span): def _setup_usb_frame(self, row, column, row_span, column_span):
self.usb_frame = QFrame(self.tests) self.usb_frame = QFrame(self.tests)
self.usb_frame_layout = QGridLayout(self.usb_frame) self.usb_frame_layout = QGridLayout(self.usb_frame)
self._add_usb_test('USB A口 (左上) 2.0', 0, 0, self._add_usb_test('USB A口 (左上) 2.0', 0, 0,
'/sys/bus/usb/devices/usb2/2-1/2-1.1/product') '/sys/bus/usb/devices/usb2/2-1/2-1.1/product')
self._add_usb_test('USB A口 (左上) 3.0', 1, 0, self._add_usb_test('USB A口 (左上) 3.0', 1, 0,
'/sys/bus/usb/devices/usb3/3-1/3-1.1/product') '/sys/bus/usb/devices/usb3/3-1/3-1.1/product')
self._add_usb_test('USB A口 (左下) 2.0', 0, 1, self._add_usb_test('USB A口 (左下) 2.0', 0, 1,
'/sys/bus/usb/devices/usb2/2-1/2-1.4/product') '/sys/bus/usb/devices/usb2/2-1/2-1.4/product')
self._add_usb_test('USB A口 (左下) 3.0', 1, 1, self._add_usb_test('USB A口 (左下) 3.0', 1, 1,
'/sys/bus/usb/devices/usb3/3-1/3-1.4/product') '/sys/bus/usb/devices/usb3/3-1/3-1.4/product')
self._add_usb_test('USB A口 (右上) 2.0', 0, 2, self._add_usb_test('USB A口 (右上) 2.0', 0, 2,
'/sys/bus/usb/devices/usb2/2-1/2-1.3/product') '/sys/bus/usb/devices/usb2/2-1/2-1.3/product')
self._add_usb_test('USB A口 (右上) 3.0', 1, 2, self._add_usb_test('USB A口 (右上) 3.0', 1, 2,
@ -461,7 +405,7 @@ class MainWindow(QMainWindow, SimpleLang):
'/sys/bus/usb/devices/usb2/2-1/2-1.2/product') '/sys/bus/usb/devices/usb2/2-1/2-1.2/product')
self._add_usb_test('USB A口 (右下) 3.0', 1, 3, self._add_usb_test('USB A口 (右下) 3.0', 1, 3,
'/sys/bus/usb/devices/usb3/3-1/3-1.2/product') '/sys/bus/usb/devices/usb3/3-1/3-1.2/product')
self.tests_layout.addWidget(self.usb_frame, row, column, row_span, column_span) self.tests_layout.addWidget(self.usb_frame, row, column, row_span, column_span)
# [end] Check the usb to see if the device is inserted # [end] Check the usb to see if the device is inserted
@ -488,26 +432,13 @@ class MainWindow(QMainWindow, SimpleLang):
qr_label.setPixmap(self._create_qrcode(sn)) qr_label.setPixmap(self._create_qrcode(sn))
sn_qrcode_layout.addWidget(qr_label) sn_qrcode_layout.addWidget(qr_label)
sn_label = QLabel(f'{self.get_text("sn")}: {sn}', sn_qrcode) sn_label = QLabel(f'{self.sl.get_text("sn")}: {sn}', sn_qrcode)
sn_label.setAlignment(Qt.AlignTop | Qt.AlignHCenter) sn_label.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
sn_qrcode_layout.addWidget(sn_label) sn_qrcode_layout.addWidget(sn_label)
self.others_item_layout.addWidget(sn_qrcode) self.others_item_layout.addWidget(sn_qrcode)
def _setup_wifi_mac_qrcode(self, mac):
mac_qrcode = QFrame(self.others_item)
mac_qrcode_layout = QVBoxLayout(mac_qrcode)
qr_label = QLabel(mac_qrcode)
qr_label.setAlignment(Qt.AlignCenter)
qr_label.setPixmap(self._create_qrcode(mac))
mac_qrcode_layout.addWidget(qr_label)
mac_label = QLabel(f'{self.get_text("wifi_mac")}: {mac}', mac_qrcode)
mac_label.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
mac_qrcode_layout.addWidget(mac_label)
self.others_item_layout.addWidget(mac_qrcode)
###################################################### ######################################################
# Handlers for setting a new project # Handlers for setting a new project
###################################################### ######################################################
@ -521,7 +452,7 @@ class MainWindow(QMainWindow, SimpleLang):
testcase = getattr(module, subModuleName) testcase = getattr(module, subModuleName)
if hasattr(testcase, 'LANGUAGES'): if hasattr(testcase, 'LANGUAGES'):
langs = getattr(testcase, 'LANGUAGES') langs = getattr(testcase, 'LANGUAGES')
lang = langs.get(self.current_lang) lang = langs.get(self.sl.current_lang)
if lang is not None: if lang is not None:
text = lang.get(key) text = lang.get(key)
if text is not None: if text is not None:
@ -580,7 +511,7 @@ class MainWindow(QMainWindow, SimpleLang):
pipeline = 'gst-pipeline: spacemitsrc location=/opt/factorytest/res/camtest_sensor0_mode0.json close-dmabuf=1 ! videoconvert ! video/x-raw,format=BGRx ! autovideosink sync=0' pipeline = 'gst-pipeline: spacemitsrc location=/opt/factorytest/res/camtest_sensor0_mode0.json close-dmabuf=1 ! videoconvert ! video/x-raw,format=BGRx ! autovideosink sync=0'
self.media_player.setMedia(QMediaContent(QUrl(pipeline))) self.media_player.setMedia(QMediaContent(QUrl(pipeline)))
self.media_player.play() self.media_player.play()
self.hdmi_thread = threading.Thread(target=self.hdmi_loop) self.hdmi_thread = threading.Thread(target=self.hdmi_loop)
self.hdmi_thread.start() self.hdmi_thread.start()
@ -590,7 +521,7 @@ class MainWindow(QMainWindow, SimpleLang):
self.cmd_run_all() self.cmd_run_all()
self.root.exec_() self.root.exec_()
def hdmi_loop(self): def hdmi_loop(self):
card = '/sys/class/drm/card2-HDMI-A-1' card = '/sys/class/drm/card2-HDMI-A-1'
if os.path.exists(card): if os.path.exists(card):
@ -611,25 +542,25 @@ class MainWindow(QMainWindow, SimpleLang):
if line.strip().startswith('Model'): if line.strip().startswith('Model'):
model = line.strip().split(':')[1].strip() model = line.strip().split(':')[1].strip()
self.hdmi_model.setText(f'{self.get_text("hdmi_model")}: {manufacturer} {model}') self.hdmi_model.setText(f'{self.sl.get_text("hdmi_model")}: {manufacturer} {model}')
def _play_wav(self, device, volume, path): def _play_wav(self, device, volume, path):
cmd = f'amixer -c 1 cset numid=1,iface=MIXER,name="DAC Playback Volume" {volume}' cmd = f'amixer -c 1 cset numid=1,iface=MIXER,name="DAC Playback Volume" {volume}'
proc = subprocess.run(cmd, shell=True, capture_output=True, text=True) proc = subprocess.run(cmd, shell=True, capture_output=True, text=True)
print(f'Set playback volume to {volume} return {proc.returncode}') # print(f'Set playback volume to {volume} return {proc.returncode}')
cmd = f'aplay -D{device} -r 48000 -f S16_LE {path}' cmd = f'aplay -D{device} -r 48000 -f S16_LE {path}'
proc = subprocess.run(cmd, shell=True, capture_output=True, text=True) proc = subprocess.run(cmd, shell=True, capture_output=True, text=True)
print(f'Play {path} on {device} return {proc.returncode}') # print(f'Play {path} on {device} return {proc.returncode}')
def _record_wav(self, device, volume, duration, path): def _record_wav(self, device, volume, duration, path):
cmd = f'amixer -c 1 cset numid=1,iface=MIXER,name="ADC Capture Volume" {volume},{volume}' cmd = f'amixer -c 1 cset numid=1,iface=MIXER,name="ADC Capture Volume" {volume},{volume}'
proc = subprocess.run(cmd, shell=True, capture_output=True, text=True) proc = subprocess.run(cmd, shell=True, capture_output=True, text=True)
print(f'Set capture volume to {volume} return {proc.returncode}') # print(f'Set capture volume to {volume} return {proc.returncode}')
cmd = f'arecord -D{device} -r 48000 -f S16_LE -d {duration} {path}' cmd = f'arecord -D{device} -r 48000 -f S16_LE -d {duration} {path}'
proc = subprocess.run(cmd, shell=True, capture_output=True, text=True) proc = subprocess.run(cmd, shell=True, capture_output=True, text=True)
print(f'Record {path} on {device} in {duration}s return {proc.returncode}') # print(f'Record {path} on {device} in {duration}s return {proc.returncode}')
def audio_loop(self): def audio_loop(self):
# sleep for a while # sleep for a while
@ -661,7 +592,7 @@ class MainWindow(QMainWindow, SimpleLang):
# color = self.lcd_color_list[self.lcd_color_index % len(self.lcd_color_list)] # color = self.lcd_color_list[self.lcd_color_index % len(self.lcd_color_list)]
# self.lcd_color_index += 1 # self.lcd_color_index += 1
# self.setPalette(QPalette(QColor(color))) # self.setPalette(QPalette(QColor(color)))
def set_brightness(self, brightness = 128): def set_brightness(self, brightness = 128):
path = '/sys/devices/platform/soc/soc:lcd_backlight/backlight/soc:lcd_backlight/brightness' path = '/sys/devices/platform/soc/soc:lcd_backlight/backlight/soc:lcd_backlight/brightness'
try: try:
@ -669,13 +600,13 @@ class MainWindow(QMainWindow, SimpleLang):
f.write(f'{brightness}') f.write(f'{brightness}')
except: except:
pass pass
# def keyPressEvent(self, event): # def keyPressEvent(self, event):
# super().keyPressEvent(event) # super().keyPressEvent(event)
# def mousePressEvent(self, event): # def mousePressEvent(self, event):
# super().mousePressEvent(event) # super().mousePressEvent(event)
###################################################### ######################################################
# User commands # User commands
###################################################### ######################################################
@ -684,7 +615,7 @@ class MainWindow(QMainWindow, SimpleLang):
# self.content.setVisible(False) # self.content.setVisible(False)
# self.lcd_color_index = 0 # self.lcd_color_index = 0
# self.update_lcd_color() # self.update_lcd_color()
def cmd_poweroff(self): def cmd_poweroff(self):
self.media_player.stop() self.media_player.stop()
self.stop() self.stop()
@ -727,7 +658,7 @@ class MainWindow(QMainWindow, SimpleLang):
if data is not None: if data is not None:
labels.append(data) labels.append(data)
if labels and (not self.executor[module] or if labels and (not self.executor[module] or
not self.executor[module].is_running): not self.executor[module].is_running):
self.run(module, labels=labels) self.run(module, labels=labels)
@ -738,7 +669,7 @@ class MainWindow(QMainWindow, SimpleLang):
remaining_seconds = seconds % 60 remaining_seconds = seconds % 60
return hours, minutes, remaining_seconds return hours, minutes, remaining_seconds
def update_aging_hints(self, error: str = None): def update_aging_hints(self, error: str = None):
hours, minutes, seconds = self._convert_seconds(self.aging_elapse) hours, minutes, seconds = self._convert_seconds(self.aging_elapse)
hints = '正在进行老化测试...\n' hints = '正在进行老化测试...\n'
@ -747,7 +678,7 @@ class MainWindow(QMainWindow, SimpleLang):
if error: if error:
hints += error hints += error
self.aging_dialog.setLabelText(hints) self.aging_dialog.setLabelText(hints)
def start_aging_test(self): def start_aging_test(self):
self.cpu_aging_proc = None self.cpu_aging_proc = None
self.ddr_aging_proc = None self.ddr_aging_proc = None
@ -859,15 +790,15 @@ class MainWindow(QMainWindow, SimpleLang):
self.vpu_aging_proc.kill() self.vpu_aging_proc.kill()
self.vpu_aging_proc.wait() self.vpu_aging_proc.wait()
self.vpu_aging_proc = None self.vpu_aging_proc = None
def cmd_aging(self): def cmd_aging(self):
self.aging_duration = int(self.aging_duration_choice.currentText()) * 3600 self.aging_duration = int(self.aging_duration_choice.currentText()) * 3600
self.aging_elapse = 0 self.aging_elapse = 0
self.aging_pass = True self.aging_pass = True
self.aging_dialog = QProgressDialog('', f'{self.get_text("aging_cancel")}', self.aging_dialog = QProgressDialog('', f'{self.sl.get_text("aging_cancel")}',
0, self.aging_duration, self) 0, self.aging_duration, self)
self.aging_dialog.setWindowTitle(self.get_text('aging_test')) self.aging_dialog.setWindowTitle(self.sl.get_text('aging_test'))
self.update_aging_hints() self.update_aging_hints()
self.aging_dialog.setValue(0) self.aging_dialog.setValue(0)
self.aging_dialog.setAutoClose(True) self.aging_dialog.setAutoClose(True)
@ -893,6 +824,11 @@ class MainWindow(QMainWindow, SimpleLang):
self.aging_button.setPalette(QPalette(QColor(PASS_COLOR))) self.aging_button.setPalette(QPalette(QColor(PASS_COLOR)))
else: else:
self.aging_button.setPalette(QPalette(QColor(FAIL_COLOR))) self.aging_button.setPalette(QPalette(QColor(FAIL_COLOR)))
#
def cmd_peripheral_test(self):
self.peripheral_test_view.exec_()
###################################################### ######################################################
# GUI Callbacks # GUI Callbacks
###################################################### ######################################################
@ -902,77 +838,6 @@ class MainWindow(QMainWindow, SimpleLang):
# update "run selected" button enabled state # update "run selected" button enabled state
self.set_selected_button_state() self.set_selected_button_state()
# wifi signal part
def on_wifiStatusUpdate(self):
self.set_wifi_signal_level()
QTimer.singleShot(3000, lambda: self.on_wifiStatusUpdate())
def set_wifi_signal_level(self):
ssid, signal_level = self._get_strongest_wifi()
if not ssid:
return
if signal_level <= -100:
self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % FAIL_COLOR)
value = 1
elif signal_level <= -88: # (-100, -88]
self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % FAIL_COLOR)
value = 2
elif signal_level <= -77: # (-88, -77]
self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % FAIL_COLOR)
value = 3
elif signal_level <= -55: # (-77, -55]
self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % PASS_COLOR)
value = 4
else: # > -55
self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % PASS_COLOR)
value = 5
self.wifi_signal_level.setFormat(f'{ssid}: {signal_level}')
self.wifi_signal_level.setValue(value)
def _get_strongest_wifi(self):
strongest_signal_level = -2147483648
strongest_ssid = None
timeout = 10
cmd = 'wpa_cli scan'
scan = subprocess.run(cmd, capture_output=True, text=True, shell=True, timeout=timeout)
if scan.returncode != 0:
return strongest_ssid, strongest_signal_level
cmd = 'wpa_cli scan_results'
proc = subprocess.run(cmd, capture_output=True, text=True, shell=True, timeout=timeout)
if proc.returncode != 0:
return strongest_ssid, strongest_signal_level
for line in proc.stdout.splitlines():
if not line.strip() or line.startswith('Selected interface') or line.startswith('bssid'):
continue
parts = line.split('\t')
if len(parts) < 5:
continue
signal_level = int(parts[2])
ssid = parts[4]
if signal_level > strongest_signal_level:
strongest_signal_level = signal_level
strongest_ssid = ssid
return strongest_ssid, strongest_signal_level
# wifi mac part
def _get_wifi_mac(self):
cmd = 'ifconfig wlan0'
proc = subprocess.run(cmd, capture_output=True, text=True, shell=True, timeout=2)
for line in proc.stdout.splitlines():
pattern = 'HWaddr'
if line.find(pattern) > 0:
return line.split(pattern)[1].strip()
def _get_sn(self): def _get_sn(self):
path = '/proc/device-tree/serial-number' path = '/proc/device-tree/serial-number'
if os.path.exists(path): if os.path.exists(path):
@ -1002,54 +867,54 @@ class MainWindow(QMainWindow, SimpleLang):
if os.path.exists(path): if os.path.exists(path):
with open(path, 'r') as f: with open(path, 'r') as f:
return round(int(f.readline().strip()) / 1000 / 1000 / 2, 1) return round(int(f.readline().strip()) / 1000 / 1000 / 2, 1)
def _get_DDR_size(self): def _get_DDR_size(self):
with open('/proc/meminfo', 'r') as f: with open('/proc/meminfo', 'r') as f:
for line in f.readlines(): for line in f.readlines():
if line.startswith('MemTotal:'): if line.startswith('MemTotal:'):
return round(int(line.split()[1]) / 1024 / 1024, 0) return round(int(line.split()[1]) / 1024 / 1024, 0)
def _get_CPU_model(self): def _get_CPU_model(self):
with open('/proc/cpuinfo', 'r') as f: with open('/proc/cpuinfo', 'r') as f:
for line in f.readlines(): for line in f.readlines():
if line.startswith('model name'): if line.startswith('model name'):
return line.split(':')[1].strip() return line.split(':')[1].strip()
def _get_CPU_freq(self): def _get_CPU_freq(self):
with open('/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq', 'r') as f: with open('/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq', 'r') as f:
return round(int(f.readline().strip()) / 1000 / 1000, 1) return round(int(f.readline().strip()) / 1000 / 1000, 1)
# cpu temp part # cpu temp part
def on_cpuTempUpdate(self): def on_cpuTempUpdate(self):
self.cpu_temp.setText(f'{self.get_text("cpu_temp")}: {self._get_CPU_Temp()} °C') self.cpu_temp.setText(f'{self.sl.get_text("cpu_temp")}: {self._get_CPU_Temp()} °C')
def _get_CPU_Temp(self): def _get_CPU_Temp(self):
thermal_base_path = "/sys/class/thermal/" thermal_base_path = "/sys/class/thermal/"
ret = "None" ret = "None"
try: try:
# Traverse the thermal_zone* directory # Traverse the thermal_zone* directory
for zone in os.listdir(thermal_base_path): for zone in os.listdir(thermal_base_path):
zone_path = os.path.join(thermal_base_path, zone) zone_path = os.path.join(thermal_base_path, zone)
type_path = os.path.join(zone_path, "type") type_path = os.path.join(zone_path, "type")
# Check whether the type file exists # Check whether the type file exists
if os.path.isfile(type_path): if os.path.isfile(type_path):
with open(type_path, 'r') as type_file: with open(type_path, 'r') as type_file:
type_content = type_file.read().strip() type_content = type_file.read().strip()
# Check whether the type file content matches # Check whether the type file content matches
if type_content == "cluster0_thermal": if type_content == "cluster0_thermal":
temp_path = os.path.join(zone_path, "temp") temp_path = os.path.join(zone_path, "temp")
if os.path.isfile(temp_path): if os.path.isfile(temp_path):
with open(temp_path, 'r') as temp_file: with open(temp_path, 'r') as temp_file:
temp_content = temp_file.read().strip() temp_content = temp_file.read().strip()
temp_content = int(temp_content)//1000 temp_content = int(temp_content)//1000
ret = str(temp_content) ret = str(temp_content)
except Exception as e: except Exception as e:
print(f"An error occurred when getting cpu temperature: {e}") print(f"An error occurred when getting cpu temperature: {e}")
return ret return ret
def on_nodeStatusUpdate(self, node): def on_nodeStatusUpdate(self, node):

View file

@ -0,0 +1,22 @@
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
class SingletonMeta(type):
"""
A metaclass that ensures a class follows the Singleton pattern.
All instances of the class and its subclasses share the same instance.
"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]

View file

@ -0,0 +1,170 @@
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QColor, QKeyEvent, QMouseEvent, QPixmap, QImage, QPalette
from PyQt5.QtWidgets import QFrame, QHBoxLayout, QVBoxLayout, QGridLayout, QLabel, QProgressBar, QSlider
import subprocess
from cricket.lang import SimpleLang
from cricket.loggermanager import LoggerManager
from cricket.macro import *
from cricket.utils import *
class StatusView(QFrame):
def __init__(self, parent):
super().__init__(parent)
self._setup_others_status()
def _setup_others_status(self):
self.others_status_layout = QHBoxLayout(self)
# wifi signal
self.wifi_signal_view = WifiSignalView(self)
self.others_status_layout.addWidget(self.wifi_signal_view)
self.wifi_signal_view.start_to_scan()
class WifiSignalView(QFrame):
def __init__(self, parent):
super().__init__(parent)
self.sl = SimpleLang()
self.log_manager = LoggerManager(name='WiFiSignalView')
self.logger = self.log_manager.get_logger()
self.wifi_text = self.sl.get_text("wifi")
self.wifi_ready = False
self.setup_wifi_signal_with_ui()
def setup_wifi_signal_with_ui(self):
wifi_layout = QGridLayout(self)
wifi_label = QLabel(f'{self.wifi_text}: ', self)
wifi_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
wifi_layout.addWidget(wifi_label, 0, 0)
self.wifi_signal_level = QProgressBar(self)
self.wifi_signal_level.setAlignment(Qt.AlignLeft)
self.wifi_signal_level.setMaximum(100)
wifi_layout.addWidget(self.wifi_signal_level, 0, 1)
self.logger.info(f'{self.sl.get_text("wifi_signal_init")}')
self.wifi_signal_level.setFormat(f'{self.sl.get_text("wifi_signal_init")}')
self.wifi_signal_level.setValue(0)
def start_to_scan(self):
self.on_wifiStatusUpdate()
def on_wifiStatusUpdate(self):
interface = 'wlan0'
status = self.check_interface_status(interface)
wifi_module_name = '8852bs'
kernel_module_wifi_status = self.check_module_loaded(wifi_module_name)
wpa_supplicant_status = self.check_process_running('wpa_supplicant')
if status and kernel_module_wifi_status and wpa_supplicant_status:
self.wifi_ready = True
pr = f"Interface {interface} is {status}"
self.set_wifi_signal_level()
else:
pr = f"fail wifi: {interface}:{status}, {wifi_module_name}:{kernel_module_wifi_status}, wpa_supplicant:{wpa_supplicant_status}"
self.logger.info(pr)
self.wifi_signal_level.setFormat(f'{self.sl.get_text("wifi_signal_init")}')
self.wifi_signal_level.setValue(0)
QTimer.singleShot(1000, lambda: self.on_wifiStatusUpdate())
def check_interface_status(self, interface):
try:
# Execute a command ip link show interface
result = subprocess.run(['ip', 'link', 'show', interface], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
# Check the return code of the command execution
if result.returncode != 0:
print(f"Error: {result.stderr}")
return None
# Analytic output
output = result.stdout
if interface in output:
return True
else:
return False
except Exception as e:
print(f"Exception occurred: {e}")
return False
def check_module_loaded(self, module_name):
"""Check whether the kernel module is loaded successfully"""
result = subprocess.run(['lsmod'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if module_name in result.stdout:
return True
return False
def check_process_running(self, process_name):
"""Check whether the process is running"""
result = subprocess.run(['ps', 'aux'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if process_name in result.stdout:
return True
return False
def set_wifi_signal_level(self):
ssid, signal_level = self._get_strongest_wifi()
if not ssid:
self.wifi_signal_level.setFormat(f'{self.sl.get_text("wifi_signal_init")}')
# self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % FAIL_COLOR)
self.wifi_signal_level.setValue(0)
return
if signal_level <= -100:
self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % FAIL_COLOR)
value = 20
elif signal_level <= -88: # (-100, -88]
self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % FAIL_COLOR)
value = 40
elif signal_level <= -55: # (-88, -55]
self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % FAIL_COLOR)
value = 60
elif signal_level <= -33: # (-33, -55]
self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % PASS_COLOR)
value = 80
else: # > -33
self.wifi_signal_level.setStyleSheet('QProgressBar { text-align: center; } QProgressBar::chunk { background-color: %s; }' % PASS_COLOR)
value = 100
# The value is a string encoded in UTF-8
byte_str = bytes(ssid, 'latin1').decode('unicode_escape').encode('latin1')
decoded_str = byte_str.decode('utf-8')
self.wifi_signal_level.setFormat(f'{decoded_str}: {signal_level}')
self.wifi_signal_level.setValue(value)
def _get_strongest_wifi(self):
strongest_signal_level = -2147483648
strongest_ssid = None
timeout = 5
cmd = 'wpa_cli scan'
scan = subprocess.run(cmd, capture_output=True, text=True, shell=True, timeout=timeout)
# if scan.returncode != 0:
# return strongest_ssid, strongest_signal_level
cmd = 'wpa_cli scan_results'
proc = subprocess.run(cmd, capture_output=True, text=True, shell=True, timeout=timeout)
if proc.returncode != 0:
return strongest_ssid, strongest_signal_level
for line in proc.stdout.splitlines():
if not line.strip() or line.startswith('Selected interface') or line.startswith('bssid'):
continue
parts = line.split('\t')
if len(parts) < 5:
continue
signal_level = int(parts[2])
ssid = parts[4]
if signal_level > strongest_signal_level:
strongest_signal_level = signal_level
strongest_ssid = ssid
return strongest_ssid, strongest_signal_level

View file

@ -0,0 +1,10 @@
from PyQt5.QtCore import Qt, QTimer, QObject
class DeviceStatusManager(QObject):
def __init__(self):
super().__init__()
self.time_sync = False
self.wifi_sync = False
self.check_mode = 1
self.set_file_name_flag = False

27
cricket/cricket/utils.py Normal file
View file

@ -0,0 +1,27 @@
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt, QTimer, QObject
from PIL.ImageQt import ImageQt
import os
import qrcode
def get_product_name():
path = '/proc/device-tree/model'
if os.path.exists(path):
with open(path, 'r') as f:
model = f.readline().strip(b'\0x00'.decode())
return model.replace('spacemit', '').replace('board', '').strip()
def create_qrcode(data):
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=8,
border=0,
)
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image(fill='black', back_color='white')
qt_image = ImageQt(img).convertToFormat(QImage.Format_RGB32)
return QPixmap.fromImage(qt_image)

View file

@ -0,0 +1,54 @@
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QFrame,QVBoxLayout,QLabel
import subprocess
from cricket.lang import SimpleLang
from cricket.utils import *
import re
class WifiMacView(QFrame):
def __init__(self, parent):
super().__init__(parent)
self.sl = SimpleLang()
self.wifi_mac_text = self.sl.get_text("wifi_mac")
self.setup_wifi_mac_with_ui()
def setup_wifi_mac_with_ui(self):
mac = self._get_wifi_mac()
if mac:
self._setup_wifi_mac_qrcode(mac)
else:
QTimer.singleShot(2000, self.setup_wifi_mac_with_ui)
def _get_wifi_mac(self):
cmd = 'ifconfig wlan0'
proc = subprocess.run(cmd, capture_output=True, text=True, shell=True, timeout=1)
text = proc.stdout
pattern = r"HWaddr\s+([0-9A-Fa-f:]{17})"
match = re.search(pattern, text)
if match:
mac_address = match.group(1)
return mac_address
else:
return None
def _setup_wifi_mac_qrcode(self, mac):
mac_qrcode_layout = QVBoxLayout(self)
qr_label = QLabel(self)
qr_label.setAlignment(Qt.AlignCenter)
qr_label.setPixmap(create_qrcode(mac))
mac_qrcode_layout.addWidget(qr_label)
mac_label = QLabel(f'{self.wifi_mac_text}: {mac}', self)
mac_label.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
mac_qrcode_layout.addWidget(mac_label)
self.mac_layout = mac_qrcode_layout
# wifi ip
self.wifi_ip = QLabel(' ', self)
self.wifi_ip.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
self.mac_layout.addWidget(self.wifi_ip)