diff --git a/README-EN.md b/README-EN.md new file mode 100644 index 0000000..82b6a33 --- /dev/null +++ b/README-EN.md @@ -0,0 +1,224 @@ +# QuecPython Production Test Tool Application Guide + +## Overview + +The QuecPython production test tool (hereinafter referred to as the production test tool) is used for production testing of products developed based on QuecPython. This tool is available for Windows 7 and above operating systems. + +The basic functions of the production testing tool are as follows: + +1. Load test scripts and configuration files + + a. Users are required to write test scripts that can be run in the product in units of unit test functions. + + b. Users can bind test information for each test in the configuration file, including test item name, test function name, test method, etc. + +2. Supports both automatic and manual testing methods + + a. The automatic test method does not require manual intervention. It automatically tests according to the order in the configuration file and automatically saves the test results. It directly encounters manual test items. + + b. In manual testing, when the current test ends, a window will pop up so that the tester can manually confirm the test results; the tool will save the manually confirmed results. + +3. Supports display of test details and viewing of test reports + + a. The test results of each item will be displayed in different colours on the main interface. + + b. The complete test report will be saved in the root directory of the tool for overall viewing. + +4. Supports 1 to 4 tests. + +## Tool Download + +[Click here to go to the download page](https://github.com/QuecPython/FactoryTool/releases)to obtain the production testing tool `FactoryTool.zip`。 + +![download-page.jpg](./media/download-page.jpg) + +## Interface + +- **Menu bar**:Includes edit tab and log tab + + - **Edit tab**:For editing test scripts and Excel log files + + - **Log tab**: Used to view test log files and tool run log files + + - **Setting tab**: Used for some advanced settings + +- **Load area**:Includes loading test scripts and configuration files + - **Load Test Script**:A collection of test functions + - **Load Config File**:Bind test information to each test, including test item name, test function name, test method, etc + +- **Factory Test**:Includes device connection ports, test item names, test methods, and test results. The tool has four test areas. Up to four devices can be tested simultaneously at one time, or a device can be tested individually. + +> **Ensure that the interaction port of the tested module is not blocked, otherwise the test will fail.** + +![1692598668142](./media/1701828343176.jpg) + +## Setting Menu - Advanced Settings +![1692598668142](./media/1701828550273.jpg) + +After modifying the items in the advanced setting, you need to click on the lower right conner **confirm** for the settings to apply. + +1. Start testing automatically + + The test will start automatically when the interaction port is detected. + +2. Automatic restart + + The module will automatically restart after testing. + +3. IMEI matching + + The IMEI number will be matched with the IMEI number in **IMEI.txt** in the local tool directory. If it exists, the test will pass. Otherwise, the test will not pass. + +4. Version detection + + The software version number (the software version number acquisition method can be configured by yourself, **uos.uname()** is used by default to obtain it) will be matched with the configured version number. If it matches, the test will pass. Otherwise, the test will not pass. + +5. Test item configuration + + Before configuring this item, you need to select the JSON file. You can select all test items in the JSON file. Only the test items added to the right will be tested (the default is that all test items will be tested) + +## Test Script + +When writing test scripts, you need to be careful not to change the original template code structure. It is recommended to manually run the test in the module after writing to confirm whether the running results meet expectations. There are two locations that need to be changed in the test script template. + +**Import module**:Import the python library used in testing + +**Test function**:Write your own test function. The function name can be customized, but it needs to be a **static method** and cannot pass parameters. The function body content is customized according to the test requirements. The function needs to have a return value, which **must be a bool value.** + +Test script example: + +```python +# Write the modules that need to be imported here +import sim +import net +import uos +import utime + +class TestBase(object): + # ------This area is for testing code------ + @staticmethod + def det_signal(args): + utime.sleep(2) + if sim.getStatus() == 1: + if net.getConfig()[0] == 5: + return True + else: + return False + else: + return False + + @staticmethod + def det_file_space(): + utime.sleep(2) + if uos.statvfs('usr')[3] > 5: + return True + else: + return False + # ------This area is for testing code------ +``` + +## Configuration file +The configuration file is a JSON file, and three-dimensional list needs to be configured, which are: test item name, test function name, test mode (1 for manual testing, 0 for automatic testing) + +Test script example: + +```json +{ + // Test item name, Function of test item, Test method: 0/1/2 + "info": [["Memory test", "det_file_space()", 0], + ["Signal test", "det_signal('test')", 0]], + // Test mode 0: Fully automatic test + // Test mode 1: Manual confirmation of start and manual confirmation of test items results – “tips” is the content of the pop-up window for confirmation at the start + // Test mode 2: Manual confirmation is required to start and automatic confirmation of test items results - Confirm the pop-up window prompts content at the start + + // Test item name: Prompt information corresponding to the test item + "tips": {"Memory test": "Please press button 1"} +} +``` + +If tips are configured, the text box below the interface test item display will display the prompt information when testing this item. + +## Test principle + +The production testing tool uses python scripts to test the business functions of QuecPython products. The test scripts are executed through the command interaction port REPL of QuecPython. The test scripts can be adjusted according to the test requirements to complete the production test function. + +1. Get module parameters and running status through QuecPython's API interface. +2. Obtain business running status by accessing objects in running business code. +3. Test business functions or hardware functions by calling the interface provided by the business code. +4. Transfer configuration files or write product parameters through the QuecPython API interface. + +## Test steps + +**Step 1**:Edit test scripts and configuration files + +Edit the **module_test.py** test code and **sort_setting.json**,configuration file. The test code and configuration file examples are shown in the figure above. + +**Step 2**:Open the tool and select the test script and configuration file + +After opening the tool, click the **Select** button to select the test code and configuration file edited in the previous step. If a serial port is detected, each test name and test method will be displayed under the serial port. + +![1692599729648](./media/1692599729648.jpg) + +**Step 3**:Start testing + +- Click the **Start All** button: Start testing all connected modules. + +- Click the **Start** button: Start testing the corresponding module. + +If manual detection is performed, a pop-up window will prompt whether it is successful. You can manually click **Yes/No** to confirm the result. +![1692599919725](./media/1692599919725.jpg) + +**Step 4**:View test results + +You can see the test results directly in the test result field: +1. Pass: Green background colour, test result file mark: Pass +2. Failed: Red background colour, test result field mark: Fail +3. Testing: Yellow background colour indicates that the test item is being tested, test result field mark: Testing + +![1692599801694](./media/1692599801694.jpg) + +**Step 5**:View the test log + +Generate the **Test-Result.xlsx** file in the same directory as the tool, including test project content and test result logs. + +## Test results + +The test results of each module will be written to excel and exported. The excel file can be **opened** through the **Edit Excel file** menu in the menu bar. + +Each test will generate a test record in excel (regardless of whether the test is successful or failed). Multiple tests will have multiple records, which are distinguished according to the COM port of the test device. + +This file will be saved in the directory of the same level as the tool and will be automatically appended during the test process. + +## Secondary development of production test tools + +### How to pull from repository + +If you have secondary development needs, you can directly pull the code repository. + +```shell +git clone --recurse-submodules https://github.com/QuecPython/FactoryTool.git -b interventionable +``` + +### Configure environment + +**Installing dependencies** + +```shell +pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple +# If the above method fails to install, you can use a separate installation method. +pip install wxpython -i https://pypi.tuna.tsinghua.edu.cn/simple +pip install pypubsub -i https://pypi.tuna.tsinghua.edu.cn/simple +``` +**Run code** + +```shell +python main.py +``` +**Compile into executable program** + +```shell +# If you use a separate installation method above, you need to install the pyinstaller library +pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple +# Compile it into an exe program, and the output exe directory is under ./dist/ +pyinstaller -F -w --win-private-assemblies --icon images/quectel.ico -w ./main.py +``` diff --git a/README.md b/README.md index 33fb734..a98f0e0 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,81 @@ -# QuecPython产测工具使用指导手册 +# QuecPython 产测工具应用指导 -## 文档历史 +## 概述 -| 版本 | 日期 | 作者 | 变更描述 | -| ---- | ---------- | ---- | ------------ | -| 1.0 | 2022-10-08 | 袁帅 | 初版 | -| 2.0 | 2023-04-23 | 袁帅 | 更新使用说明 | +QuecPython 产测工具(下称产测工具)用于对基于 QuecPython 开发的产品进行生产测试。该工具适用于 Windows 7 及以上版本操作系统。 -## 简介 +产测工具的基础功能如下: -QuecPython产测工具是专用于QuecPython项目模块出厂测试的工具,方便对出厂前已经烧录正式固件的模块进行相关的功能测试,本文档主要介绍如何使用该工具,在电脑使用以下任一种操作系统时,该工具可直接使用 +1. 加载测试脚本和配置文件 -- **Windows7** -- **Windows10** -- **Windows11** + a. 要求用户以单元测试函数为单位编写可运行在产品中的测试脚本。 -适用模块: + b. 用户可在配置文件中为每一项测试绑定测试信息,包括测试项名称、 测试函数名称、测试方式等。 -所有使用QuecPython开发的模块均可使用 +2. 支持自动和人工两种测试方式 -## 如何拉取仓库 + a. 自动测试方式无需人工干预,按照配置文件中的顺序自动测试,并自动保存测试结果,直接遇到人工测试项。 -```shell -git clone --recurse-submodules https://github.com/QuecPython/FactoryTool.git -``` + b. 人工测试在当前项测试结束时,会弹出窗口,以便测试人员手动确认测试结果;工具会保存手动确认的结果。 + +3. 支持测试明细展示和测试报告查看 + + a. 主界面上会以不同的颜色展示每一项的测试结果。 + + b. 完整的测试报告将会保存在工具的根目录,以便整体查看。 + +4. 支持 1 拖 4 测试。 + +## 工具获取 + +[点此进入下载页面](https://github.com/QuecPython/FactoryTool/releases)获取产测工具 `FactoryTool.zip`。 + +![download-page.jpg](./media/download-page.jpg) ## 页面介绍 -**菜单栏** 包括配置菜单和日志菜单 +- **菜单栏**:包括编辑菜单和日志菜单 + + - **编辑菜单**:用于编辑测试脚本和Excel日志文件。 + + - **日志菜单** 用于查看测试日志文件和工具运行日志文件。 + + - **设置菜单** 用于一些高级设置。 + +- **加载区域**:包括加载测试脚本和配置文件 + - **测试脚本**:测试函数的集合 + - **配置文件**:为每一项测试绑定测试信息,包括测试项名称、 测试函数名称、测试方式等。 + +- **测试区域**:包括设备连接端口、测试项名称、测试的方式、测试结果,工具有四个测试区域,最多可一次性同时测试四个设备,也可以单独测试某个设备。 + +> **测试的模块需要保证交互口不处于堵塞状态,否则测试将失败**。 + +![1692598668142](./media/1701828343176.jpg) + +## 设置菜单 - 高级设置 +![1692598668142](./media/1701828550273.jpg) + +高级设置项修改后,需点右下角 **确认** 才可生效 + +1. 自动开始测试 -**配置菜单** 用于配置自动检测串口以及测试脚本和测试结果文件 + 勾选后,检测到交互口自行开始测试 -**日志菜单** 用于查看测试日志文件和工具运行日志文件 +2. 自动重启 -**加载栏** 包括 加载测试文件和配置文件,其中测试文件为要测试的测试文件,配置文件为测试完成之后要写入到模块的配置文件 + 勾选后,测完模组自动重启 -**测试区域** 包括 端口、IMEI、ICCID、测试时间、测试结果和测试日志,其中测试日志按钮可以查看测试脚本执行的日志结果,工具有八个测试栏位最多可一次性同时测试八个设备,也可以单独测试某个设备。 +3. Imei号匹配 -**状态栏** 包括欢迎标语和状态信息以及时间信息,其中状态信息会伴随工具运行状态进行切换,时间信息会跟随系统时间变化 + 勾选后会把Imei号和本地工具目录下 **imei.txt** 里的imei号匹配,若存在则通过,否则该项测试不通过。 -> **注意:测试的模块需要保证交互口不处于堵塞状态,否则测试将失败** +4. 版本号检测 -![1665207910586](./media/1665207910586.png) + 勾选后会把软件的版本号(软件版本号获取方式可自行配置,默认用 **uos.uname()** 去获取)和配置的版本号进行匹配,若匹配上测该项测试通过,否则该项测试不通过。 + +5. 测项配置 + + 配置该项前需先选择json文件,可对json文件内所有测项进行选择,添加到右边的测项才会检测(默认是所有测项都会测试) ## 测试脚本 @@ -49,58 +83,123 @@ git clone --recurse-submodules https://github.com/QuecPython/FactoryTool.git **导入模块**:导入测试中用到的python库 -**测试函数**:自行编写测试函数,函数名可以自定义,但是需要是静态方法且无法传参,函数体内容根据测试需求自定义,函数需要有返回值,可以是bool或者其他类型(其他类型不会校验测试结果),返回值会在日志中体现,当测试结果不满足预期,需要将测试结果设置为失败时,只需返回布尔值False即可,测试函数案例如下: +**测试函数**:自行编写测试函数,函数名可以自定义,但是需要是**静态方法**且无法传参,函数体内容根据测试需求自定义,函数需要有返回值,**必须是bool值** + +测试脚本示例: ```python -# 检测sim卡状态正常并且驻网状态为LTE时测试成功,否则返回失败测试结果 -@staticmethod -def det_signal(): - if sim.getStatus() == 1: - if net.getConfig()[0] == 5: - return True - else: - return False +# Write the modules that need to be imported here +import sim +import net +import uos +import utime + +class TestBase(object): + # ------This area is for testing code------ + @staticmethod + def det_signal(args): + utime.sleep(2) + if sim.getStatus() == 1: + if net.getConfig()[0] == 5: + return True + else: + return False + else: + return False + + @staticmethod + def det_file_space(): + utime.sleep(2) + if uos.statvfs('usr')[3] > 5: + return True + else: + return False + # ------This area is for testing code------ ``` +## 配置文件 +配置文件为json文件,需要配置三维数据,分别为: 测试项名称, 测试函数的名称, 测试方式(1为人工测试 0为自动测试) + 测试脚本示例: -![1665208145345](./media/1665208145345.png) +```json +{ + // 测项名称 测项的function 延时时间 测试方式:0/1/2 + "info": [["Memory test", "det_file_space()", 0, 0], + ["Signal test", "det_signal('test')", 0, 0]], + // 测试方式 0: 全自动测试 + // 测试方式 1: 需手动确认开始 和 手动确认结果测试项 - 确认开始的弹窗提示tips内容 + // 测试方式 2: 需手动确认开始 和 自动确认结果测试项 - 确认开始的弹窗提示tips内容 + + // 测项名称 该测项对应的提示信息 + "tips": {"Memory test": "Please press button 1"} +} +``` + +若有配置tips,则在测试该项时,界面测项显示下面的文本框会显示该提示信息 ## 测试原理 -产测工具利用python脚本的形式来测试QuecPython产品的业务功能,通过CDC口来执行测试脚本,测试脚本根据测试需求可以自行调整以达成完成生产测试的功能 +产测工具利用python脚本的形式来测试QuecPython产品的业务功能,通过 QuecPython 的命令交互口 REPL 来执行测试脚本,测试脚本根据测试需求可以自行调整以达成完成生产测试的功能。 -1. 通过QuecPython的API接口来获取模组参数和运行状态 -2. 通过访问正在运行的业务代码中的对象来获取业务运行情况 -3. 通过调用业务代码提供的接口才测试业务功能或者硬件功能 -4. 通过QuecPython API接口传输配置文件或者写入产品参数 +1. 通过QuecPython的API接口来获取模组参数和运行状态。 +2. 通过访问正在运行的业务代码中的对象来获取业务运行情况。 +3. 通过调用业务代码提供的接口来测试业务功能或者硬件功能。 +4. 通过QuecPython API接口传输配置文件或者写入产品参数。 ## 测试步骤 -**步骤一**:编辑测试**module_test.py**代码,测试代码案例如上图所示 +**步骤一**:编辑测试脚本和配置文件 + +编辑测试**module_test.py**代码 和 配置文件**sort_setting.json**,测试代码和配置文件案例如上图所示。 + +**步骤二**:打开工具,选择测试脚本和配置文件 + +打开工具后,点击 **选择** 按钮,分别选择上一步编辑好的测试代码和配置文件,若有检测到串口,则该串口下会显示每一项测试名称以及测试方式。 -**步骤二**:打开 **Factory Tool**,点击 **Load Py File** 按钮,选择上一步编辑好的测试代码 +![1692599729648](./media/1692599729648.jpg) -**步骤三**:如果测试完有需要写入到模块中的配置文件,点击 **Load Json File **选择要写入的配置文件,将会在测试成功之后将该配置文件写入模块 +**步骤三**:开始测试 -**步骤四**:点击 **Start All** 按钮开始测试所有已接入的模块,也可以通过单独点击端口对应列的 **Start** 按钮来测试某一个模块,测试超时时间2min +- 点击 **全部开始** 按钮: 开始测试所有已接入的模块。 -**步骤五**:测试完成后可在测试结果栏位看到测试结果,如果测试结果失败,可点击对应失败的那一列的日志按钮来查看测试日志,从而可定位到具体哪一项测试失败 +- 点击 **开始** 按钮: 开始测试对应的那一个模块。 -**步骤六**:测试完成后会在工具同级目录下生成**Test-Result.xlsx**文件,包含测试项目内容以及测试结果日志 +若是人工检测会弹窗提示是否成功,可人工点击 **是/否** 来确认该项结果。 +![1692599919725](./media/1692599919725.jpg) + +**步骤四**:查看测试结果 + +可在测试结果栏位直接看到测试结果: +1. 通过: 绿色背景色,测试结果栏位标记: 通过。 +2. 不通过: 红色背景色,测试结果栏位标记: 不通过 。 +3. 测试中: 黄色背景色,表示该测试项正在检测中。 + +![1692599801694](./media/1692599801694.jpg) + +**步骤五**:查看测试日志 + +在工具同级目录下生成**Test-Result.xlsx**文件,包含测试项目内容以及测试结果日志。 ## 测试结果 -每一个模块的的测试结果会写入到excel中导出,可以通过菜单栏的 **配置** 中的 **测试结果文件 **菜单打开该excel文件 +每一个模块的的测试结果会写入到excel中导出,可以通过菜单栏的 **编辑** 中的 **编辑Excel文件**菜单打开该excel文件 -每一次测试会在excel中生成一条测试记录(无论测试成功或者失败),多次测试会有多条记录,根据测试设备的IMEI区分 +每一次测试会在excel中生成一条测试记录(无论测试成功或者失败),多次测试会有多条记录,根据测试设备的COM口区分 该文件会保存在工具同级目录下,测试过程中自动追加 -同时测试结果会上传到云端生成报表以供云端查看整体测试结果(开发中) +## 产测工具二次开发 +### 如何拉取仓库 + +若有二次开发需求,可直接拉取代码仓库。 + +```shell +git clone --recurse-submodules https://github.com/QuecPython/FactoryTool.git -b interventionable +``` -## 环境配置 +### 环境配置 **安装依赖库** diff --git a/file_handler.py b/file_handler.py index 3946440..247e405 100644 --- a/file_handler.py +++ b/file_handler.py @@ -8,6 +8,7 @@ """ import serial_handler import openpyxl +from openpyxl.styles import PatternFill, Color import codecs import json import sys @@ -20,22 +21,15 @@ class ExcelHandler(object): handle test result Excel excel_file: filename include full path """ - def __init__(self, excel_file, sheet_name): + def __init__(self, excel_file): self.file = excel_file if os.path.exists(self.file): pass else: wb = openpyxl.Workbook() - ws = wb[wb.sheetnames[0]] - ws.title = sheet_name wb.save(self.file) self.wb = openpyxl.load_workbook(self.file) - if sheet_name in self.wb.sheetnames[0]: - pass - else: - self.wb.create_sheet(sheet_name) - self.ws = self.wb[sheet_name] - + self.ws = self.wb[self.wb.sheetnames[0]] def get_rows_columns(self): rows = self.ws.max_row @@ -59,9 +53,17 @@ def get_row_values(self, row): rows_data.append(self.ws.cell(row=row, column=i).value) return rows_data - def set_cell_value(self, row, column, cell_value): + def set_cell_value(self, row, column, cell_value, fill=None): try: self.ws.cell(row=row, column=column).value = cell_value + if fill == "Green": + fill = PatternFill('solid', fgColor=Color("00FF00")) + self.ws.cell(row=row, column=column).fill = fill + elif fill == "Red": + fill = PatternFill('solid', fgColor=Color("FF0000")) + self.ws.cell(row=row, column=column).fill = fill + else: + pass except KeyError as e: self.ws.cell(row=row, column=column).value = "Write Fail" print(e) diff --git a/locale/en/LC_MESSAGES/English.mo b/locale/en/LC_MESSAGES/English.mo index d1d8ce1..b90f275 100644 Binary files a/locale/en/LC_MESSAGES/English.mo and b/locale/en/LC_MESSAGES/English.mo differ diff --git a/locale/en/LC_MESSAGES/English.po b/locale/en/LC_MESSAGES/English.po index 1c0acb0..484e48d 100644 --- a/locale/en/LC_MESSAGES/English.po +++ b/locale/en/LC_MESSAGES/English.po @@ -65,7 +65,7 @@ msgid " msgstr "Test Time" msgid "Խ" -msgstr "Test Result" +msgstr "T-Result" msgid "鿴־" msgstr "View Log" @@ -86,11 +86,83 @@ msgstr " Current status: ready..." msgid "ӭʹQuecPython" msgstr " Welcome to QuecPython" +msgid "ģ־" +msgstr "Module Log" + +msgid "" +msgstr "Test-Item" + +msgid "Էʽ" +msgstr "T-Method" + +msgid "˹" +msgstr "Manual Test" + +msgid "Զ" +msgstr "Automated Test" + +msgid "ͨ" +msgstr "Pass" + +msgid "ͨ" +msgstr "Fail" + +msgid "" +msgstr "Testing" + +msgid " ǰΪ: " +msgstr " The current test item is: " + +msgid "\r\n\r\n ȷϸò Ƿͨ" +msgstr "\r\n\r\n Please confirm the test result [Passed or Not]" + +msgid "Ƿָϴļ" +msgstr "Do you want to restore the last file" + +msgid "ļ" +msgstr "File does not exist" + +msgid "Imeiƥ" +msgstr "Imei matching" + +msgid "Զ" +msgstr "Automatic restart" + +msgid "汾ż" +msgstr "Version detection" + +msgid "汾: " +msgstr "Version: " + +msgid "Զʼ" +msgstr "Start testing automatically" + +msgid "" +msgstr "Add" + +msgid "ɾ" +msgstr "Delete" +msgid "" +msgstr "Clear" +msgid "ȫѡ" +msgstr "Select all" +msgid "ȷ" +msgstr "Confirm" +msgid "ȡ" +msgstr "Cancel" +msgid " " +msgstr " Test item configuration" +msgid "" +msgstr "Setting" +msgid "߼" +msgstr "Advanced Settings" +msgid "ʱ: " +msgstr "Countdown: " \ No newline at end of file diff --git a/main.py b/main.py index 25fc84d..bdbd0cb 100644 --- a/main.py +++ b/main.py @@ -20,28 +20,291 @@ import file_handler import serial_list import serial_handler +import configparser +from wx import stc from log_redirect import RedirectErr, RedirectStd from pubsub import pub from queue import Queue import codecs import json -# PROJECT_ABSOLUTE_PATH = os.path.dirname(os.path.abspath(__file__)) - if hasattr(sys, '_MEIPASS'): PROJECT_ABSOLUTE_PATH = os.path.dirname(os.path.realpath(sys.executable)) else: PROJECT_ABSOLUTE_PATH = os.path.dirname(os.path.abspath(__file__)) + +def set_config(PROJECT_ABSOLUTE_PATH, frame): + if not os.path.exists(PROJECT_ABSOLUTE_PATH+"\\config.ini"): + return + conf = configparser.ConfigParser(interpolation=None) + conf.read(PROJECT_ABSOLUTE_PATH+"\\config.ini", encoding='utf-8') + py_file = conf.get("software", "py_file") + json_file = conf.get("software", "json_file") + + if py_file or json_file: + no_exist = [] + msg = wx.MessageBox(_(u'是否恢复上次文件'), _(u'提示'), wx.YES_NO) + if msg == wx.YES: + if py_file: + if os.path.exists(py_file): + try: + relative_path = os.path.relpath(py_file, PROJECT_ABSOLUTE_PATH) + frame.text_ctrl_py.SetValue(relative_path) + except Exception as e: + frame.text_ctrl_py.SetValue(py_file) + else: + conf.set("software", "py_file", "") + wx.MessageBox(py_file + _(u"文件不存在"), _(u"提示"), wx.YES_DEFAULT | wx.ICON_INFORMATION) + + if json_file: + if os.path.exists(json_file): + try: + relative_path = os.path.relpath(json_file, PROJECT_ABSOLUTE_PATH) + frame.text_ctrl_json.SetValue(relative_path) + except Exception as e: + frame.text_ctrl_json.SetValue(json_file) + frame.load_json_file(0, json_file) + else: + conf.set("software", "json_file", "") + wx.MessageBox(json_file + _(u"文件不存在"), _(u"提示"), wx.YES_DEFAULT | wx.ICON_INFORMATION) + + with open(PROJECT_ABSOLUTE_PATH + "\\config.ini", "w+", encoding='utf-8') as f: + conf.write(f) + + elif msg == wx.NO: + conf.set("software", "py_file", "") + conf.set("software", "json_file", "") + with open(PROJECT_ABSOLUTE_PATH + "\\config.ini", "w+", encoding='utf-8') as f: + conf.write(f) + + +class AdvancedSettings(wx.Dialog): + # automated, self.testMessages, selectedList + def __init__(self, parent, automated, selectedList, json_file): + super(AdvancedSettings, self).__init__(parent, title="Advanced Settings", size=(350, 200)) + self.SetSize(wx.DLG_UNIT(self, wx.Size(400, 280))) + + if json_file: + with codecs.open(json_file, 'r', 'utf-8') as f: + data = json.load(f) + info = data["info"] + self.funcList = [i[0] for i in info] + else: + self.funcList = [] + + # self.funcList = funcList + self.parent = parent + self.add_partition_box = wx.CheckBox(self, 100, _(u"自动开始测试")) + if automated == "True": + self.add_partition_box.SetValue(True) + else: + self.add_partition_box.SetValue(False) + + self.restart_box = wx.CheckBox(self, 107, _(u"自动重启")) + if restartSign == "True": + self.restart_box.SetValue(True) + else: + self.restart_box.SetValue(False) + + self.imei_box = wx.CheckBox(self, wx.ID_ANY, _(u"Imei号匹配")) + if self.parent.conf.get("detection", "imei") == "True": + self.imei_box.SetValue(True) + else: + self.imei_box.SetValue(False) + + self.version_box = wx.CheckBox(self, 106, _(u"版本号检测")) + self.label_1 = wx.StaticText(self, wx.ID_ANY, _(u"cmd: ")) + self.cmd_txt = wx.TextCtrl(self, wx.ID_ANY, self.parent.conf.get("version", "cmd")) + self.label_2 = wx.StaticText(self, wx.ID_ANY, _(u"版本号: ")) + self.version_txt = wx.TextCtrl(self, wx.ID_ANY, self.parent.conf.get("version", "version")) + if versionDetection == "True": + self.version_box.SetValue(True) + else: + self.version_box.SetValue(False) + + self.funcSelector = wx.Choice(self, wx.ID_ANY, choices=self.funcList) + self.selectedListBox = wx.ListBox(self, wx.ID_ANY, choices=selectedList) + self.add = wx.Button(self, 101, _(u"添加")) + self.delete = wx.Button(self, 102, _(u"删除")) + self.clear = wx.Button(self, 103, _(u"清空")) + self.selectAll = wx.Button(self, 104, _(u"全选")) + self.confirm = wx.Button(self, 105, _(u"确认")) + self.buttonFotaCancel = wx.Button(self, wx.ID_CANCEL, _(u"取消")) + + # self.Bind(wx.EVT_CHECKBOX, self.key_processing, self.add_partition_box) + # self.Bind(wx.EVT_CHECKBOX, self.key_processing, self.version_box) + self.Bind(wx.EVT_BUTTON, self.key_processing, self.add) + self.Bind(wx.EVT_BUTTON, self.key_processing, self.delete) + self.Bind(wx.EVT_BUTTON, self.key_processing, self.clear) + self.Bind(wx.EVT_BUTTON, self.key_processing, self.selectAll) + self.Bind(wx.EVT_BUTTON, self.key_processing, self.confirm) + + self.__set_properties() + self.__do_layout() + self.Center() + + def __set_properties(self): + self.funcSelector.SetMinSize((150, 25)) + self.selectedListBox.SetMinSize((150, 300)) + + # self.label_1.SetMinSize((50, 25)) + self.cmd_txt.SetMinSize((200, 20)) + # self.label_1.SetMinSize((50, 25)) + self.version_txt.SetMinSize((200, 20)) + + def __do_layout(self): + sizer_1 = wx.BoxSizer(wx.VERTICAL) + sizer_2 = wx.BoxSizer(wx.VERTICAL) + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_3_ = wx.BoxSizer(wx.HORIZONTAL) + sizer_3_1 = wx.BoxSizer(wx.HORIZONTAL) + + + sizer_3.Add((20, 0), 0, 0, 0) + sizer_3.Add(self.add_partition_box, 0, 0, 0) + + sizer_3_.Add((20, 0), 0, 0, 0) + sizer_3_.Add(self.restart_box, 0, 0, 0) + + sizer_3_1.Add((20, 0), 0, 0, 0) + sizer_3_1.Add(self.imei_box, 0, 0, 0) + + sizer_4.Add((20, 0), 0, 0, 0) + sizer_4.Add(self.version_box, 0, 0, 0) + sizer_4.Add((20, 0), 0, 0, 0) + sizer_4.Add(self.label_1, 0, 0, 0) + sizer_4.Add(self.cmd_txt, 0, 0, 0) + sizer_4.Add((20, 0), 0, 0, 0) + sizer_4.Add(self.label_2, 0, 0, 0) + sizer_4.Add(self.version_txt, 0, 0, 0) + + sizer_box_1 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _(u" 测项配置 ")), wx.HORIZONTAL) + + + sizer_2.Add(self.add, 0, 0, 0) + sizer_2.Add((0, 20), 0, 0, 0) + sizer_2.Add(self.delete, 0, 0, 0) + sizer_2.Add((0, 20), 0, 0, 0) + sizer_2.Add(self.clear, 0, 0, 0) + sizer_2.Add((0, 20), 0, 0, 0) + sizer_2.Add(self.selectAll, 0, 0, 0) + # sizer_2.Add((0, 20), 0, 0, 0) + # sizer_2.Add(self.confirm, 0, 0, 0) + + sizer_box_1.Add(self.funcSelector, 0, 0, 0) + sizer_box_1.Add((20, 0), 0, 0, 0) + sizer_box_1.Add(sizer_2, 0, 0, 0) + sizer_box_1.Add((20, 0), 0, 0, 0) + sizer_box_1.Add(self.selectedListBox, 0, 0, 0) + + sizer_1.Add((0, 10), 0, 0, 0) + sizer_1.Add(sizer_3, 0, 0, 0) + sizer_1.Add((0, 20), 0, 0, 0) + sizer_1.Add(sizer_3_, 0, 0, 0) + sizer_1.Add((0, 20), 0, 0, 0) + sizer_1.Add(sizer_3_1, 0, 0, 0) + sizer_1.Add((0, 20), 0, 0, 0) + sizer_1.Add(sizer_4, 0, 0, 0) + sizer_1.Add((0, 20), 0, 0, 0) + sizer_1.Add(sizer_box_1, 0, 0, 0) + + sizer_5 = wx.BoxSizer(wx.HORIZONTAL) + sizer_5.Add(self.confirm, 0, 0, 0) + sizer_5.Add(self.buttonFotaCancel, 0, wx.LEFT, 10) + sizer_1.Add((0, 10), 0, 0, 0) + sizer_1.Add(sizer_5, 0, wx.ALIGN_RIGHT | wx.ALL, 5) + self.SetSizer(sizer_1) + + def key_processing(self, event): + + if event.GetId() == 101: + funcName = self.funcSelector.GetString(self.funcSelector.GetSelection()) + + if funcName and self.selectedListBox.FindString(funcName, caseSensitive = True) == -1: + self.selectedListBox.Append(funcName) + + elif event.GetId() == 102: + deleted_item = self.selectedListBox.GetSelection() + if deleted_item != -1: + projectName = self.selectedListBox.GetString(deleted_item) + print(projectName) + self.selectedListBox.Delete(deleted_item) + + elif event.GetId() == 103: + self.selectedListBox.Clear() + + elif event.GetId() == 104: + self.selectedListBox.Clear() + for x in self.funcList: + self.selectedListBox.Append(x) + + elif event.GetId() == 105: + global selectedList, automated, versionDetection, restartSign + + # 自动开始测试配置 + if self.add_partition_box.GetValue(): + automated = "True" + else: + automated = "False" + + self.parent.conf.set("detection", "automated", automated) + + # 自动重启配置 + if self.restart_box.GetValue(): + restartSign = "True" + else: + restartSign = "False" + + self.parent.conf.set("detection", "restart", restartSign) + + # Imei号匹配配置 + if self.imei_box.GetValue(): + imei = "True" + else: + imei = "False" + + self.parent.conf.set("detection", "imei", imei) + + # 版本号测试配置 + if self.version_box.GetValue(): + versionDetection = "True" + else: + versionDetection = "False" + self.parent.conf.set("version", "ifdetect", versionDetection) + self.parent.conf.set("version", "cmd", self.cmd_txt.GetValue()) + self.parent.conf.set("version", "version", self.version_txt.GetValue()) + + # 测项配置 + selectedList = [] + for i in range(self.selectedListBox.GetCount()): + projectName = self.selectedListBox.GetString(i) + selectedList.append(projectName) + + self.parent.conf.set("detection", "item", ",".join(selectedList)) + with open(PROJECT_ABSOLUTE_PATH + "\\config.ini", "w+", encoding='utf-8') as f: + self.parent.conf.write(f) + + json_file = self.parent.text_ctrl_json.GetValue() + if json_file: + self.parent.load_json_file(0, json_file) + self.Destroy() + + class FactoryFrame(wx.Frame): def __init__(self, *args, **kwargs): kwargs["style"] = kwargs.get("style", 0) | wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwargs) - self.SetSize((876, 600)) + self.SetTitle("FactoryTool") + _icon = wx.NullIcon + _icon.CopyFromBitmap(wx.Bitmap(PROJECT_ABSOLUTE_PATH + "\\media\\quectel.ico", wx.BITMAP_TYPE_ICO)) + self.SetIcon(_icon) + self.SetSize((1120, 700)) self.Center() # stdout log - # sys.stderr = RedirectErr(self, PROJECT_ABSOLUTE_PATH) - # sys.stdout = RedirectStd(self, PROJECT_ABSOLUTE_PATH) + sys.stderr = RedirectErr(self, PROJECT_ABSOLUTE_PATH) + sys.stdout = RedirectStd(self, PROJECT_ABSOLUTE_PATH) # module log self.logger = ModuleLog() # Menu Bar @@ -59,225 +322,114 @@ def __init__(self, *args, **kwargs): wxg_tmp_menu_1.Append(2001, _(u"工具日志"), "") self.Bind(wx.EVT_MENU, self.__menu_handler, id=2001) wxg_tmp_menu_1.AppendSeparator() - wxg_tmp_menu_1.Append(2002, _(u"工具日志"), "") + wxg_tmp_menu_1.Append(2002, _(u"模块日志"), "") self.Bind(wx.EVT_MENU, self.__menu_handler, id=2002) self.menuBar.Append(wxg_tmp_menu_1, _(u"日志")) + + wxg_tmp_menu_2 = wx.Menu() + wxg_tmp_menu_2.Append(3001, _(u"高级设置"), "") + self.Bind(wx.EVT_MENU, self.__menu_handler, id=3001) + self.menuBar.Append(wxg_tmp_menu_2, _(u"设置")) + self.SetMenuBar(self.menuBar) # Menu Bar end - self.statusBar = self.CreateStatusBar(3) + # self.statusBar = self.CreateStatusBar(3) self.main_panel = wx.Panel(self, wx.ID_ANY) self.load_py = wx.Button(self.main_panel, wx.ID_ANY, _("选择")) self.text_ctrl_py = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) self.load_json = wx.Button(self.main_panel, wx.ID_ANY, _("选择")) self.text_ctrl_json = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.button_3 = wx.Button(self.main_panel, wx.ID_ANY, _("全部开始"), style=wx.BU_TOP) - self.button_4 = wx.Button(self.main_panel, 100, _("开始")) - self.text_ctrl_7 = wx.TextCtrl(self.main_panel, 10, "", style=wx.TE_READONLY) - self.text_ctrl_8 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_9 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_10 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_11 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.button_2 = wx.Button(self.main_panel, 200, _("日志")) - - self.button_5 = wx.Button(self.main_panel, 101, _("开始")) - self.text_ctrl_13 = wx.TextCtrl(self.main_panel, 11, "", style=wx.TE_READONLY) - self.text_ctrl_14 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_15 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_16 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_17 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.button_12 = wx.Button(self.main_panel, 201, _("日志")) - - self.button_6 = wx.Button(self.main_panel, 102, _("开始")) - self.text_ctrl_19 = wx.TextCtrl(self.main_panel, 12, "", style=wx.TE_READONLY) - self.text_ctrl_20 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_21 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_22 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_23 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.button_13 = wx.Button(self.main_panel, 202, _("日志")) - - self.button_7 = wx.Button(self.main_panel, 103, _("开始")) - self.text_ctrl_25 = wx.TextCtrl(self.main_panel, 13, "", style=wx.TE_READONLY) - self.text_ctrl_26 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_27 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_28 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_29 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.button_14 = wx.Button(self.main_panel, 203, _("日志")) - - self.button_8 = wx.Button(self.main_panel, 104, _("开始")) - self.text_ctrl_31 = wx.TextCtrl(self.main_panel, 14, "", style=wx.TE_READONLY) - self.text_ctrl_32 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_33 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_34 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_35 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.button_15 = wx.Button(self.main_panel, 204, _("日志")) - - self.button_9 = wx.Button(self.main_panel, 105, _("开始")) - self.text_ctrl_37 = wx.TextCtrl(self.main_panel, 15, "", style=wx.TE_READONLY) - self.text_ctrl_38 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_39 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_40 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_41 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.button_16 = wx.Button(self.main_panel, 205, _("日志")) - - self.button_10 = wx.Button(self.main_panel, 106, _("开始")) - self.text_ctrl_43 = wx.TextCtrl(self.main_panel, 16, "", style=wx.TE_READONLY) - self.text_ctrl_44 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_45 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_46 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_47 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.button_17 = wx.Button(self.main_panel, 206, _("日志")) - - self.button_11 = wx.Button(self.main_panel, 107, _("开始")) - self.text_ctrl_49 = wx.TextCtrl(self.main_panel, 17, "", style=wx.TE_READONLY) - self.text_ctrl_50 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_51 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_52 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.text_ctrl_53 = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) - self.button_18 = wx.Button(self.main_panel, 207, _("日志")) - - # button list - self.button_start_list = (self.button_4, self.button_5, self.button_6, self.button_7, self.button_8, self.button_9, self.button_10, self.button_11) - self.button_log_list = (self.button_2, self.button_12, self.button_13, self.button_14, self.button_15, self.button_16, self.button_17, self.button_18) - [i.Enable(False) for i in self.button_start_list] - [i.Enable(False) for i in self.button_log_list] - # text_ctrl list - self.port_ctrl_list = (self.text_ctrl_7, self.text_ctrl_13, self.text_ctrl_19, self.text_ctrl_25, - self.text_ctrl_31, self.text_ctrl_37, self.text_ctrl_43, self.text_ctrl_49) - self.port_imei_list = (self.text_ctrl_8, self.text_ctrl_14, self.text_ctrl_20, self.text_ctrl_26, - self.text_ctrl_32, self.text_ctrl_38, self.text_ctrl_44, self.text_ctrl_50) - self.port_iccid_list = (self.text_ctrl_9, self.text_ctrl_15, self.text_ctrl_21, self.text_ctrl_27, - self.text_ctrl_33, self.text_ctrl_39, self.text_ctrl_45, self.text_ctrl_51) - self.port_time_list = (self.text_ctrl_10, self.text_ctrl_16, self.text_ctrl_22, self.text_ctrl_28, - self.text_ctrl_34, self.text_ctrl_40, self.text_ctrl_46, self.text_ctrl_52) - self.port_result_list = (self.text_ctrl_11, self.text_ctrl_17, self.text_ctrl_23, self.text_ctrl_29, - self.text_ctrl_35, self.text_ctrl_41, self.text_ctrl_47, self.text_ctrl_53) - self.__py_exec_result = list(" ") * 8 - self.__py_test_fp = None # 测试的脚本文件 + + self.button_all_start = wx.Button(self.main_panel, wx.ID_ANY, _("全部开始")) + + self.button_start_list = [] + self.ListCtrl_list = [] + self.port_ctrl_list = [] + self.Imei_ctrl_list = [] + self.tips_ctrl_list = [] + for i in range(4): + ListCtrl = wx.ListCtrl(self.main_panel, 200+i, style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES) + ListCtrl.SetMinSize((-1, 250)) + ListCtrl.AppendColumn(_(u"测项"), format=wx.LIST_FORMAT_LEFT, width=130) + ListCtrl.AppendColumn(_(u"测试方式"), format=wx.LIST_FORMAT_LEFT, width=70) + ListCtrl.AppendColumn(_(u"测试结果"), format=wx.LIST_FORMAT_LEFT, width=70) + + tips_ctrl = wx.TextCtrl(self.main_panel, wx.ID_ANY, style=wx.TE_MULTILINE|wx.TE_WORDWRAP|wx.TE_READONLY|wx.TE_RICH2) + button = wx.Button(self.main_panel, 100+i, _("开始")) + button.Enable(False) + text_ctrl = wx.TextCtrl(self.main_panel, 300+i, "", style=wx.TE_READONLY) + text_ctrl_imei = wx.TextCtrl(self.main_panel, wx.ID_ANY, "", style=wx.TE_READONLY) + + # tips_ctrl.AppendText("请按键") + + self.ListCtrl_list.append(ListCtrl) + self.button_start_list.append(button) + self.port_ctrl_list.append(text_ctrl) + self.Imei_ctrl_list.append(text_ctrl_imei) + self.tips_ctrl_list.append(tips_ctrl) + self.__exec_py_cmd_list = ["from usr.test import TestBase"] - self.__test_result = [0 for i in range(8)] # 测试结果 - self.statusBarTimer = wx.Timer(self) - self.Bind(wx.EVT_TIMER, self.__status_bar_timer_fresh, self.statusBarTimer) - self.statusBarTimer.Start(100) - pub.subscribe(self.__update_status_bar, "statusBarUpdate") + self.__init_excel() # event message queue self.message_queue = Queue(maxsize=10) self._channel_list = [] + self.testMessages = [] threading.Thread(target=self.port_process_handler, args=()).start() # bind Func self.Bind(wx.EVT_BUTTON, self.__load_py_file, self.load_py) - self.Bind(wx.EVT_BUTTON, self.__load_json_file, self.load_json) - self.Bind(wx.EVT_BUTTON, self.test_all_start, self.button_3) - self.Bind(wx.EVT_BUTTON, self.test_start, self.button_4) - self.Bind(wx.EVT_BUTTON, self.test_start, self.button_5) - self.Bind(wx.EVT_BUTTON, self.test_start, self.button_6) - self.Bind(wx.EVT_BUTTON, self.test_start, self.button_7) - self.Bind(wx.EVT_BUTTON, self.test_start, self.button_8) - self.Bind(wx.EVT_BUTTON, self.test_start, self.button_9) - self.Bind(wx.EVT_BUTTON, self.test_start, self.button_10) - self.Bind(wx.EVT_BUTTON, self.test_start, self.button_11) - self.Bind(wx.EVT_BUTTON, self.log_terminal, self.button_2) - self.Bind(wx.EVT_BUTTON, self.log_terminal, self.button_12) - self.Bind(wx.EVT_BUTTON, self.log_terminal, self.button_13) - self.Bind(wx.EVT_BUTTON, self.log_terminal, self.button_14) - self.Bind(wx.EVT_BUTTON, self.log_terminal, self.button_15) - self.Bind(wx.EVT_BUTTON, self.log_terminal, self.button_16) - self.Bind(wx.EVT_BUTTON, self.log_terminal, self.button_17) - self.Bind(wx.EVT_BUTTON, self.log_terminal, self.button_18) - self.Bind(wx.EVT_CLOSE, self.close_window) + self.Bind(wx.EVT_BUTTON, self.load_json_file, self.load_json) + self.Bind(wx.EVT_BUTTON, self.test_all_start, self.button_all_start) + - # bind Timer - self.statusBarTimer = wx.Timer(self) - self.Bind(wx.EVT_TIMER, self.statusbar_fresh, self.statusBarTimer) - self.statusBarTimer.Start(100) + self.procese_num = 0 + + for i in self.button_start_list: + self.Bind(wx.EVT_BUTTON, self.test_start, i) + self.Bind(wx.EVT_CLOSE, self.close_window) # pub message pub.subscribe(self.port_update, "serialUpdate") + self.conf = configparser.ConfigParser(interpolation=None) + if not os.path.exists(PROJECT_ABSOLUTE_PATH+"\\config.ini"): + self.initConfigFile() + self.conf.read(PROJECT_ABSOLUTE_PATH+"\\config.ini", encoding='utf-8') + + global automated, selectedList, versionDetection, restartSign + automated = self.conf.get("detection", "automated") + restartSign = self.conf.get("detection", "restart") + selectedList = [i for i in self.conf.get("detection", "item").split(",") if i != ""] + versionDetection = self.conf.get("version", "ifdetect") + self.__set_properties() self.__do_layout() def __set_properties(self): - self.SetTitle("Factory Tool") - # _icon = wx.NullIcon - # _icon.CopyFromBitmap(wx.Bitmap(PROJECT_ABSOLUTE_PATH + "\\images\\quectel.ico", wx.BITMAP_TYPE_ICO)) - # self.SetIcon(_icon) - self.SetBackgroundColour(wx.NullColour) - self.SetForegroundColour(wx.Colour(0, 0, 0)) - self.statusBar.SetStatusWidths([200, -1, 155]) - - # statusbar fields - statusBar_fields = [_(u" Welcome to QuecPython"), _(u" Current status: ready..."), " 0000-00-00 00:00:00"] - for i in range(len(statusBar_fields)): - self.statusBar.SetStatusText(statusBar_fields[i], i) - - self.load_py.SetMinSize((80, 25)) - self.load_json.SetMinSize((80, 25)) - self.text_ctrl_7.SetMinSize((74, 25)) - self.text_ctrl_8.SetMinSize((117, 25)) - self.text_ctrl_9.SetMinSize((123, 25)) - self.text_ctrl_11.SetMinSize((148, 25)) - self.button_2.SetMinSize((98, 25)) - self.text_ctrl_13.SetMinSize((74, 25)) - self.text_ctrl_14.SetMinSize((117, 25)) - self.text_ctrl_15.SetMinSize((123, 25)) - self.text_ctrl_17.SetMinSize((148, 25)) - self.button_12.SetMinSize((98, 25)) - self.text_ctrl_19.SetMinSize((74, 25)) - self.text_ctrl_20.SetMinSize((117, 25)) - self.text_ctrl_21.SetMinSize((123, 25)) - self.text_ctrl_23.SetMinSize((148, 25)) - self.button_13.SetMinSize((98, 25)) - self.text_ctrl_25.SetMinSize((74, 25)) - self.text_ctrl_26.SetMinSize((117, 25)) - self.text_ctrl_27.SetMinSize((123, 25)) - self.text_ctrl_29.SetMinSize((148, 25)) - self.button_14.SetMinSize((98, 25)) - self.text_ctrl_31.SetMinSize((74, 25)) - self.text_ctrl_32.SetMinSize((117, 25)) - self.text_ctrl_33.SetMinSize((123, 25)) - self.text_ctrl_35.SetMinSize((148, 25)) - self.button_15.SetMinSize((98, 25)) - self.text_ctrl_37.SetMinSize((74, 25)) - self.text_ctrl_38.SetMinSize((117, 25)) - self.text_ctrl_39.SetMinSize((123, 25)) - self.text_ctrl_41.SetMinSize((148, 25)) - self.button_16.SetMinSize((98, 25)) - self.text_ctrl_43.SetMinSize((74, 25)) - self.text_ctrl_44.SetMinSize((117, 25)) - self.text_ctrl_45.SetMinSize((123, 25)) - self.text_ctrl_47.SetMinSize((148, 25)) - self.button_17.SetMinSize((98, 25)) - self.text_ctrl_49.SetMinSize((74, 25)) - self.text_ctrl_50.SetMinSize((117, 25)) - self.text_ctrl_51.SetMinSize((123, 25)) - self.text_ctrl_53.SetMinSize((148, 25)) - self.button_18.SetMinSize((98, 25)) + for i in range(4): + self.button_start_list[i].SetMinSize((150, 50)) + self.port_ctrl_list[i].SetMinSize((80, 25)) + self.Imei_ctrl_list[i].SetMinSize((190, 25)) + self.tips_ctrl_list[i].SetMinSize((250, 100)) + + self.button_all_start.SetMinSize((150, 50)) def __do_layout(self): sizer_1 = wx.BoxSizer(wx.VERTICAL) sizer_2 = wx.BoxSizer(wx.VERTICAL) - sizer_5 = wx.StaticBoxSizer(wx.StaticBox(self.main_panel, wx.ID_ANY, _("工厂测试")), wx.VERTICAL) - sizer_14 = wx.BoxSizer(wx.HORIZONTAL) - sizer_13 = wx.BoxSizer(wx.HORIZONTAL) - sizer_12 = wx.BoxSizer(wx.HORIZONTAL) - sizer_11 = wx.BoxSizer(wx.HORIZONTAL) - sizer_10 = wx.BoxSizer(wx.HORIZONTAL) - sizer_9 = wx.BoxSizer(wx.HORIZONTAL) - sizer_8 = wx.BoxSizer(wx.HORIZONTAL) - sizer_7 = wx.BoxSizer(wx.HORIZONTAL) - sizer_6 = wx.BoxSizer(wx.HORIZONTAL) - sizer_4 = wx.StaticBoxSizer(wx.StaticBox(self.main_panel, wx.ID_ANY, _("选择配置文件")), wx.HORIZONTAL) sizer_3 = wx.StaticBoxSizer(wx.StaticBox(self.main_panel, wx.ID_ANY, _("选择测试脚本")), wx.HORIZONTAL) - sizer_1.Add((20, 4), 0, 0, 0) - sizer_2.Add((20, 4), 0, 0, 0) + sizer_4 = wx.StaticBoxSizer(wx.StaticBox(self.main_panel, wx.ID_ANY, _("选择配置文件")), wx.HORIZONTAL) + sizer_5 = wx.StaticBoxSizer(wx.StaticBox(self.main_panel, wx.ID_ANY, _("工厂测试")), wx.HORIZONTAL) + sizer_3.Add((4, 20), 0, 0, 0) sizer_3.Add(self.load_py, 0, 0, 0) sizer_3.Add((20, 20), 0, 0, 0) sizer_3.Add(self.text_ctrl_py, 1, 0, 0) sizer_3.Add((20, 20), 0, 0, 0) + # sizer_2.Add((5, 20), 0, 0, 0) sizer_2.Add(sizer_3, 0, wx.EXPAND, 0) + sizer_4.Add((4, 20), 0, 0, 0) sizer_4.Add(self.load_json, 0, 0, 0) sizer_4.Add((20, 20), 0, 0, 0) @@ -285,193 +437,29 @@ def __do_layout(self): sizer_4.Add((20, 20), 0, 0, 0) sizer_2.Add((20, 4), 0, 0, 0) sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) - sizer_6.Add((20, 20), 0, 0, 0) - sizer_6.Add(self.button_3, 0, 0, 0) - sizer_6.Add((20, 20), 0, 0, 0) - label_9 = wx.StaticText(self.main_panel, wx.ID_ANY, _(u"端口")) - sizer_6.Add(label_9, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_6.Add((60, 20), 0, 0, 0) - label_10 = wx.StaticText(self.main_panel, wx.ID_ANY, _("IMEI")) - sizer_6.Add(label_10, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_6.Add((100, 20), 0, 0, 0) - label_11 = wx.StaticText(self.main_panel, wx.ID_ANY, _("ICCID")) - sizer_6.Add(label_11, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_6.Add((100, 20), 0, 0, 0) - label_12 = wx.StaticText(self.main_panel, wx.ID_ANY, _(u"测试时间")) - sizer_6.Add(label_12, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_6.Add((10, 20), 0, 0, 0) - label_13 = wx.StaticText(self.main_panel, wx.ID_ANY, _(u"测试结果")) - sizer_6.Add(label_13, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_6.Add((100, 20), 0, 0, 0) - label_14 = wx.StaticText(self.main_panel, wx.ID_ANY, _(u"查看日志")) - sizer_6.Add(label_14, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_6.Add((50, 20), 0, 0, 0) - sizer_5.Add(sizer_6, 0, wx.EXPAND | wx.TOP, 0) - sizer_5.Add((20, 5), 0, 0, 0) - label_15 = wx.StaticText(self.main_panel, wx.ID_ANY, "1", style=wx.ALIGN_CENTER) - label_15.SetMinSize((20, 18)) - sizer_7.Add(label_15, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_7.Add(self.button_4, 0, 0, 0) - sizer_7.Add((20, 20), 0, 0, 0) - sizer_7.Add(self.text_ctrl_7, 0, wx.ALL, 0) - sizer_7.Add((10, 20), 0, 0, 0) - sizer_7.Add(self.text_ctrl_8, 0, 0, 0) - sizer_7.Add((10, 20), 0, 0, 0) - sizer_7.Add(self.text_ctrl_9, 0, 0, 0) - sizer_7.Add((10, 20), 0, 0, 0) - sizer_7.Add(self.text_ctrl_10, 1, 0, 0) - sizer_7.Add((10, 20), 0, 0, 0) - sizer_7.Add(self.text_ctrl_11, 0, 0, 0) - sizer_7.Add((10, 20), 0, 0, 0) - sizer_7.Add(self.button_2, 0, 0, 0) - sizer_7.Add((10, 20), 0, 0, 0) - sizer_5.Add(sizer_7, 0, wx.ALL | wx.EXPAND, 0) - sizer_5.Add((20, 20), 0, 0, 0) - label_16 = wx.StaticText(self.main_panel, wx.ID_ANY, "2", style=wx.ALIGN_CENTER) - label_16.SetMinSize((20, 18)) - sizer_8.Add(label_16, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_8.Add(self.button_5, 0, 0, 0) - sizer_8.Add((20, 20), 0, 0, 0) - sizer_8.Add(self.text_ctrl_13, 0, wx.ALL, 0) - sizer_8.Add((10, 20), 0, 0, 0) - sizer_8.Add(self.text_ctrl_14, 0, 0, 0) - sizer_8.Add((10, 20), 0, 0, 0) - sizer_8.Add(self.text_ctrl_15, 0, 0, 0) - sizer_8.Add((10, 20), 0, 0, 0) - sizer_8.Add(self.text_ctrl_16, 1, 0, 0) - sizer_8.Add((10, 20), 0, 0, 0) - sizer_8.Add(self.text_ctrl_17, 0, 0, 0) - sizer_8.Add((10, 20), 0, 0, 0) - sizer_8.Add(self.button_12, 0, 0, 0) - sizer_8.Add((10, 20), 0, 0, 0) - sizer_5.Add(sizer_8, 0, wx.ALL | wx.EXPAND, 0) - sizer_5.Add((20, 20), 0, 0, 0) - label_17 = wx.StaticText(self.main_panel, wx.ID_ANY, "3", style=wx.ALIGN_CENTER) - label_17.SetMinSize((20, 18)) - sizer_9.Add(label_17, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_9.Add(self.button_6, 0, 0, 0) - sizer_9.Add((20, 20), 0, 0, 0) - sizer_9.Add(self.text_ctrl_19, 0, wx.ALL, 0) - sizer_9.Add((10, 20), 0, 0, 0) - sizer_9.Add(self.text_ctrl_20, 0, 0, 0) - sizer_9.Add((10, 20), 0, 0, 0) - sizer_9.Add(self.text_ctrl_21, 0, 0, 0) - sizer_9.Add((10, 20), 0, 0, 0) - sizer_9.Add(self.text_ctrl_22, 1, 0, 0) - sizer_9.Add((10, 20), 0, 0, 0) - sizer_9.Add(self.text_ctrl_23, 0, 0, 0) - sizer_9.Add((10, 20), 0, 0, 0) - sizer_9.Add(self.button_13, 0, 0, 0) - sizer_9.Add((10, 20), 0, 0, 0) - sizer_5.Add(sizer_9, 0, wx.ALL | wx.EXPAND, 0) - sizer_5.Add((20, 20), 0, 0, 0) - label_18 = wx.StaticText(self.main_panel, wx.ID_ANY, "4", style=wx.ALIGN_CENTER) - label_18.SetMinSize((20, 18)) - sizer_10.Add(label_18, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_10.Add(self.button_7, 0, 0, 0) - sizer_10.Add((20, 20), 0, 0, 0) - sizer_10.Add(self.text_ctrl_25, 0, wx.ALL, 0) - sizer_10.Add((10, 20), 0, 0, 0) - sizer_10.Add(self.text_ctrl_26, 0, 0, 0) - sizer_10.Add((10, 20), 0, 0, 0) - sizer_10.Add(self.text_ctrl_27, 0, 0, 0) - sizer_10.Add((10, 20), 0, 0, 0) - sizer_10.Add(self.text_ctrl_28, 1, 0, 0) - sizer_10.Add((10, 20), 0, 0, 0) - sizer_10.Add(self.text_ctrl_29, 0, 0, 0) - sizer_10.Add((10, 20), 0, 0, 0) - sizer_10.Add(self.button_14, 0, 0, 0) - sizer_10.Add((10, 20), 0, 0, 0) - sizer_5.Add(sizer_10, 0, wx.ALL | wx.EXPAND, 0) - sizer_5.Add((20, 20), 0, 0, 0) - label_19 = wx.StaticText(self.main_panel, wx.ID_ANY, "5", style=wx.ALIGN_CENTER) - label_19.SetMinSize((20, 18)) - sizer_11.Add(label_19, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_11.Add(self.button_8, 0, 0, 0) - sizer_11.Add((20, 20), 0, 0, 0) - sizer_11.Add(self.text_ctrl_31, 0, wx.ALL, 0) - sizer_11.Add((10, 20), 0, 0, 0) - sizer_11.Add(self.text_ctrl_32, 0, 0, 0) - sizer_11.Add((10, 20), 0, 0, 0) - sizer_11.Add(self.text_ctrl_33, 0, 0, 0) - sizer_11.Add((10, 20), 0, 0, 0) - sizer_11.Add(self.text_ctrl_34, 1, 0, 0) - sizer_11.Add((10, 20), 0, 0, 0) - sizer_11.Add(self.text_ctrl_35, 0, 0, 0) - sizer_11.Add((10, 20), 0, 0, 0) - sizer_11.Add(self.button_15, 0, 0, 0) - sizer_11.Add((10, 20), 0, 0, 0) - sizer_5.Add(sizer_11, 0, wx.ALL | wx.EXPAND, 0) - sizer_5.Add((20, 20), 0, 0, 0) - label_20 = wx.StaticText(self.main_panel, wx.ID_ANY, "6", style=wx.ALIGN_CENTER) - label_20.SetMinSize((20, 18)) - sizer_12.Add(label_20, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_12.Add(self.button_9, 0, 0, 0) - sizer_12.Add((20, 20), 0, 0, 0) - sizer_12.Add(self.text_ctrl_37, 0, wx.ALL, 0) - sizer_12.Add((10, 20), 0, 0, 0) - sizer_12.Add(self.text_ctrl_38, 0, 0, 0) - sizer_12.Add((10, 20), 0, 0, 0) - sizer_12.Add(self.text_ctrl_39, 0, 0, 0) - sizer_12.Add((10, 20), 0, 0, 0) - sizer_12.Add(self.text_ctrl_40, 1, 0, 0) - sizer_12.Add((10, 20), 0, 0, 0) - sizer_12.Add(self.text_ctrl_41, 0, 0, 0) - sizer_12.Add((10, 20), 0, 0, 0) - sizer_12.Add(self.button_16, 0, 0, 0) - sizer_12.Add((10, 20), 0, 0, 0) - sizer_5.Add(sizer_12, 0, wx.ALL | wx.EXPAND, 0) - sizer_5.Add((20, 20), 0, 0, 0) - label_21 = wx.StaticText(self.main_panel, wx.ID_ANY, "7", style=wx.ALIGN_CENTER) - label_21.SetMinSize((20, 18)) - sizer_13.Add(label_21, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_13.Add(self.button_10, 0, 0, 0) - sizer_13.Add((20, 20), 0, 0, 0) - sizer_13.Add(self.text_ctrl_43, 0, wx.ALL, 0) - sizer_13.Add((10, 20), 0, 0, 0) - sizer_13.Add(self.text_ctrl_44, 0, 0, 0) - sizer_13.Add((10, 20), 0, 0, 0) - sizer_13.Add(self.text_ctrl_45, 0, 0, 0) - sizer_13.Add((10, 20), 0, 0, 0) - sizer_13.Add(self.text_ctrl_46, 1, 0, 0) - sizer_13.Add((10, 20), 0, 0, 0) - sizer_13.Add(self.text_ctrl_47, 0, 0, 0) - sizer_13.Add((10, 20), 0, 0, 0) - sizer_13.Add(self.button_17, 0, 0, 0) - sizer_13.Add((10, 20), 0, 0, 0) - sizer_5.Add(sizer_13, 0, wx.ALL | wx.EXPAND, 0) - sizer_5.Add((20, 20), 0, 0, 0) - label_22 = wx.StaticText(self.main_panel, wx.ID_ANY, "8", style=wx.ALIGN_CENTER) - label_22.SetMinSize((20, 18)) - sizer_14.Add(label_22, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_14.Add(self.button_11, 0, 0, 0) - sizer_14.Add((20, 20), 0, 0, 0) - sizer_14.Add(self.text_ctrl_49, 0, wx.ALL, 0) - sizer_14.Add((10, 20), 0, 0, 0) - sizer_14.Add(self.text_ctrl_50, 0, 0, 0) - sizer_14.Add((10, 20), 0, 0, 0) - sizer_14.Add(self.text_ctrl_51, 0, 0, 0) - sizer_14.Add((10, 20), 0, 0, 0) - sizer_14.Add(self.text_ctrl_52, 1, 0, 0) - sizer_14.Add((10, 20), 0, 0, 0) - sizer_14.Add(self.text_ctrl_53, 0, 0, 0) - sizer_14.Add((10, 20), 0, 0, 0) - sizer_14.Add(self.button_18, 0, 0, 0) - sizer_14.Add((10, 20), 0, 0, 0) - sizer_5.Add(sizer_14, 0, wx.ALL | wx.EXPAND, 0) - sizer_5.Add((20, 20), 0, 0, 0) - sizer_2.Add(sizer_5, 0, wx.ALL | wx.EXPAND, 1) + + for i in range(4): + sizer_6 = wx.BoxSizer(wx.VERTICAL) + sizer_7 = wx.BoxSizer(wx.HORIZONTAL) + sizer_7.Add(self.port_ctrl_list[i], 0, 0, 1) + sizer_7.Add(self.Imei_ctrl_list[i], 0, 0, 1) + sizer_6.Add(sizer_7, 0, 0, 1) + sizer_6.Add(self.ListCtrl_list[i], 1, 1, 1) + sizer_6.Add((0, 10), 0, 0, 0) + sizer_6.Add(self.tips_ctrl_list[i], 0, 1, 0) + sizer_6.Add((0, 10), 0, 0, 0) + sizer_6.Add(self.button_start_list[i], 0, 1, 0) + sizer_5.Add(sizer_6, 1, 0, 0) + sizer_2.Add(sizer_5, 0, wx.EXPAND, 0) + + sizer_2.Add((0, 10), 0, 1, 1) + sizer_2.Add(self.button_all_start, 0, 1, 1) + self.main_panel.SetSizer(sizer_2) sizer_1.Add(self.main_panel, 1, wx.EXPAND | wx.TOP, 0) self.SetSizer(sizer_1) self.Layout() - - def __status_bar_timer_fresh(self, event): - now = datetime.datetime.now() - self.statusBar.SetStatusText(" " + now.strftime("%Y-%m-%d %H:%M:%S"), 2) - - def __update_status_bar(self, arg1): - self.statusBar.SetStatusText(arg1[0], arg1[1]) + # sizer_5.SetLabel(_("测试中")) def __menu_handler(self, event): # wxGlade: FactoryFrame. if event.GetId() == 1001: @@ -483,15 +471,34 @@ def __menu_handler(self, event): # wxGlade: FactoryFrame. raw_app_path = r'%s' % app_path subprocess.call([raw_file_path, raw_app_path]) elif event.GetId() == 1003: - excel_file = subprocess.Popen(["start", "/WAIT", PROJECT_ABSOLUTE_PATH + "Test-Result.xlsx"], shell=True) + excel_file = subprocess.Popen(["start", "/WAIT", PROJECT_ABSOLUTE_PATH + "\\Test-Result.xlsx"], shell=True) # psutil.Process(excel_file.pid).get_children()[0].kill() excel_file.poll() elif event.GetId() == 2001: p = subprocess.Popen("explorer.exe " + PROJECT_ABSOLUTE_PATH + "\\logs\\software\\", shell=True) elif event.GetId() == 2002: p = subprocess.Popen("explorer.exe " + PROJECT_ABSOLUTE_PATH + "\\logs\\apps\\", shell=True) + elif event.GetId() == 3001: + global automated, selectedList + AdvancedSettings(self, automated, selectedList, self.text_ctrl_json.GetValue()).ShowModal() event.Skip() + def initConfigFile(self): + self.conf.add_section("software") + self.conf.set("software", "py_file", "") + self.conf.set("software", "json_file", "") + self.conf.add_section("detection") + self.conf.set("detection", "automated", "False") + self.conf.set("detection", "item", "") + self.conf.set("detection", "restart", "False") + self.conf.set("detection", "imei", "False") + self.conf.add_section("version") + self.conf.set("version", "ifdetect", "False") + self.conf.set("version", "cmd", "import uos\\r\\nuos.uname()") + self.conf.set("version", "version", "") + with open(PROJECT_ABSOLUTE_PATH + "\\config.ini", "w+", encoding='utf-8') as f: + self.conf.write(f) + def __load_py_file(self, event): defDir, defFile = '', '' # default dir/ default file dlg = wx.FileDialog(self, u'Open Py File', defDir, defFile, 'Python file (*.py)|*.py', @@ -500,174 +507,373 @@ def __load_py_file(self, event): return py_cmd = file_handler.ScriptHandler(dlg.GetPath()) if py_cmd.script_check(): - self.text_ctrl_py.SetValue(dlg.GetPath()) + try: + relative_path = os.path.relpath(dlg.GetPath(), PROJECT_ABSOLUTE_PATH) + self.text_ctrl_py.SetValue(relative_path) + except Exception as e: + self.text_ctrl_py.SetValue(dlg.GetPath()) + + self.conf.set("software", "py_file", dlg.GetPath()) + with open(PROJECT_ABSOLUTE_PATH + "\\config.ini", "w+", encoding='utf-8') as f: + self.conf.write(f) else: wx.MessageBox(_(u'py代码有语法错误'), u'Warn', wx.YES_DEFAULT | wx.ICON_INFORMATION) - def __load_json_file(self, event): + def load_json_file(self, event, json_file=None): print("json button is press") - defDir, defFile = '', '' # default dir/ default file - dlg = wx.FileDialog(self, u'Open Config File', defDir, defFile, 'Config file (*)|*', - wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) - if dlg.ShowModal() == wx.ID_CANCEL: + if event != 0: + defDir, defFile = '', '' # default dir/ default file + dlg = wx.FileDialog(self, u'Open Config File', defDir, defFile, 'Config file (*.json)|*.json', + wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) + if dlg.ShowModal() == wx.ID_CANCEL: + return + json_file = dlg.GetPath() + try: + with codecs.open(json_file, 'r', 'utf-8') as f: + data = json.load(f) + print(data) + info = data["info"] + + self.testFunctions = [] + self.testMessages = [] + + print("versionDetection: ", versionDetection) + if versionDetection == "True": + self.testFunctions.append([self.conf.get("version", "cmd"), 0, 0]) + self.testMessages.append(_("版本号检测")) + + if self.conf.get("detection", "imei") == "True": + self.testFunctions.append(["Imei号匹配", 0, 0]) + self.testMessages.append(_("Imei号匹配")) + + if selectedList: + info = [i for i in info if i[0] in selectedList] + self.testFunctions += [i[1:] for i in info] + self.testMessages += [i[0] for i in info] + self.tips_info = {} + try: + self.tips_info = data["tips"] + except Exception as e: + print("523 e: ", e) + + try: + relative_path = os.path.relpath(json_file, PROJECT_ABSOLUTE_PATH) + self.text_ctrl_json.SetValue(relative_path) + except Exception as e: + self.text_ctrl_json.SetValue(json_file) + + self.conf.set("software", "json_file", json_file) + with open(PROJECT_ABSOLUTE_PATH + "\\config.ini", "w+", encoding='utf-8') as f: + self.conf.write(f) + + for i, port_ctrl in enumerate(self.port_ctrl_list): + if port_ctrl.GetValue(): + self.ListCtrl_list[i].DeleteAllItems() + self.Imei_ctrl_list[i].SetValue("") + self.tips_ctrl_list[i].SetValue("") + for j, element in enumerate(self.testFunctions): + ListCtrl = self.ListCtrl_list[i] + # testFunction = self.testFunctions[j] + ListCtrl.InsertItem(j, j) + ListCtrl.SetItem(j, 0, self.testMessages[j]) + if element[-1] == 1: + ListCtrl.SetItem(j, 1, _(u"人工检测")) + elif element[-1] == 2: + ListCtrl.SetItem(j, 1, _(u"自动检测-2")) + else: + ListCtrl.SetItem(j, 1, _(u"自动检测")) + if automated == "True": + self.test_all_start(0) + + except Exception as e: + print("line 292: ", e) + wx.MessageBox(_(u'请选择正确的配置文件'), u'提示', wx.YES_DEFAULT | wx.ICON_INFORMATION) return - self.text_ctrl_json.SetValue(dlg.GetPath()) - # TODO ymodem处理文件 def test_start(self, event): - button_event_id = event.GetId() - 100 # button ID 100开始 + if isinstance(event, int): + button_event_id = event - 100 + else: + button_event_id = event.GetId() - 100 # button ID 100开始 - jsonName = PROJECT_ABSOLUTE_PATH + "\\sort_setting.json" - with codecs.open(jsonName, 'r', 'utf-8') as f: - data = json.load(f) - self.testFunctions = data["sort"] - self.testMessages = data["message"] + if self.text_ctrl_json.GetValue(): + pass + else: + wx.MessageBox(_(u'请先选择配置文件'), u'提示', wx.YES_DEFAULT | wx.ICON_INFORMATION) + return if self.text_ctrl_py.GetValue(): if self.port_ctrl_list[button_event_id].GetValue(): # 点击开始时再初始化 - self.__port_det(True) # 检测停止 + # self.__port_det(True) # 检测停止 + self.procese_num += 1 + self.button_start_list[button_event_id].Enable(False) + self.button_all_start.Enable(False) self.message_queue.put( - {"id": button_event_id, "msg_id": "PortInit", "PortInfo": self.port_ctrl_list[button_event_id].GetValue(), - "imei": self.port_imei_list[button_event_id], "iccid": self.port_iccid_list[button_event_id]}) + {"id": button_event_id, "msg_id": "PortInit", "PortInfo": self.port_ctrl_list[button_event_id].GetValue()}) else: return None else: wx.MessageBox(_(u'请先选择测试文件'), u'提示', wx.YES_DEFAULT | wx.ICON_INFORMATION) def test_all_start(self, event): - self.__port_det(True) # 检测停止 + # self.__port_det(True) # 检测停止 + + if self.text_ctrl_json.GetValue(): + pass + else: + wx.MessageBox(_(u'请先选择配置文件'), u'提示', wx.YES_DEFAULT | wx.ICON_INFORMATION) + return + if self.text_ctrl_py.GetValue(): pass else: wx.MessageBox(_(u'请先选择测试文件'), u'提示', wx.YES_DEFAULT | wx.ICON_INFORMATION) return None + for i in self.port_ctrl_list: - button_event_id = i.GetId() - 10 + button_event_id = i.GetId() - 300 if i.GetValue(): + self.procese_num += 1 + self.button_all_start.Enable(False) + self.button_start_list[button_event_id].Enable(False) self.message_queue.put( {"id": button_event_id, "msg_id": "PortInit", - "PortInfo": self.port_ctrl_list[button_event_id].GetValue(), - "imei": self.port_imei_list[button_event_id], "iccid": self.port_iccid_list[button_event_id]}) - # time.sleep(2) - # self.message_queue.put( - # {"id": button_event_id, "msg_id": "PortTest", - # "PortInfo": self.port_ctrl_list[button_event_id].GetValue(), - # "script": self.__py_test_fp, "time": self.port_time_list[button_event_id], - # "result": self.port_result_list[button_event_id]}) + "PortInfo": self.port_ctrl_list[button_event_id].GetValue()}) else: return None - def log_terminal(self, event): - event_id = event.GetId() - # print(self.port_ctrl_list[event_id-200].GetValue(), self.__py_exec_result[event_id-200]) - dia = DialogControl(self, self.port_ctrl_list[event_id-200].GetValue(), self.__py_exec_result[event_id-200]) - # - res = dia.Show() - - def statusbar_fresh(self, event): - # self.statusBar.SetStatusText(u" 当前状态: 就绪...", 1) - now = datetime.datetime.now() - self.statusBar.SetStatusText(" " + now.strftime("%Y-%m-%d %H:%M:%S"), 2) - def port_update(self, arg1): - # print("message:{}".format(arg1)) + print("message:{}".format(arg1)) self.message_queue.put({"msg_id": "PortUpdate", "PortInfo": arg1}) + def automated_start(self): + if self.text_ctrl_json.GetValue(): + test_all_start(1) + def port_update_handler(self, arg1): + # arg1: {'msg_id': 'PortUpdate', 'PortInfo': ['COM15']} + # print("message: ", arg1) # TODO 设置log按钮状态 - port_list = arg1["PortInfo"][:8] if len(arg1["PortInfo"]) > 8 else arg1["PortInfo"] - if len(port_list) < 8: - self.button_3.Enable(False) if len(port_list) == 0 else self.button_3.Enable(True) - port_list = port_list + [""] * (8 - len(port_list)) + port_list = arg1["PortInfo"][:4] if len(arg1["PortInfo"]) > 4 else arg1["PortInfo"] + + if self._channel_list == []: + self.button_all_start.Enable(False) if len(port_list) == 0 else self.button_all_start.Enable(True) + if len(port_list) == 0: + self.button_all_start.Enable(False) + if self._channel_list == [] or self._channel_list != port_list: self._channel_list = port_list - for j in [self.port_ctrl_list, self.port_imei_list, self.port_iccid_list, self.port_time_list, - self.port_result_list]: - [i.SetValue("") for i in j] - for i, element in enumerate(self.button_start_list): - self.button_log_list[i].Enable(False) - # self.button_next_list[i].Enable(False) - if self._channel_list[i]: - self.port_ctrl_list[i].SetValue(self._channel_list[i]) - self.button_start_list[i].Enable(True) - else: + + exists_port = [] + for i, port_ctrl in enumerate(self.port_ctrl_list): + if port_ctrl.GetValue() and port_ctrl.GetValue() not in self._channel_list: + port_ctrl.SetValue("") + self.Imei_ctrl_list[i].SetValue("") + self.tips_ctrl_list[i].SetValue("") + self.ListCtrl_list[i].DeleteAllItems() self.button_start_list[i].Enable(False) + elif port_ctrl.GetValue() and port_ctrl.GetValue() in self._channel_list: + exists_port.append(port_ctrl.GetValue()) + + new_ports = [x for x in self._channel_list if x not in exists_port] + for new_port in new_ports: + for port_ctrl in self.port_ctrl_list: + if port_ctrl.GetValue() == "": + port_ctrl.SetValue(new_port) + break + + for i, port_ctrl in enumerate(self.port_ctrl_list): + if port_ctrl.GetValue() and port_ctrl.GetValue() in new_ports: + self.button_start_list[i].Enable(True) + if self.text_ctrl_json.GetValue(): + for j, element in enumerate(self.testFunctions): + ListCtrl = self.ListCtrl_list[i] + # testFunction = self.testFunctions[j] + ListCtrl.InsertItem(j, j) + ListCtrl.SetItem(j, 0, self.testMessages[j]) + if element[-1] == 1: + ListCtrl.SetItem(j, 1, _(u"人工检测")) + elif element[-1] == 2: + ListCtrl.SetItem(j, 1, _(u"自动检测-2")) + else: + ListCtrl.SetItem(j, 1, _(u"自动检测")) + print("automated: ", automated) + if automated == "True": + self.test_start(100+i) + def port_init_handler(self, arg1): - self.port_imei_list[arg1["id"]].SetValue("") - self.port_iccid_list[arg1["id"]].SetValue("") - self.port_time_list[arg1["id"]].SetValue("") - self.port_result_list[arg1["id"]].SetValue("") - self.button_log_list[arg1["id"]].Enable(False) + ID = arg1["id"] + # print(ID) + self.tips_ctrl_list[ID].SetValue("") + for i in range(len(self.testFunctions)): + ListCtrl = self.ListCtrl_list[ID] + ListCtrl.SetItem(i, 2, "") + ListCtrl.SetItemBackgroundColour(i, (255, 255, 255, 255)) + # 重复测试结果重置 - self.__test_result[arg1["id"]] = 0 - self.__py_exec_result[arg1["id"]] = "" - ser = serial_handler.SerialHandler(arg1["PortInfo"]) - imei, iccid = asyncio.run(ser.init_module(arg1["imei"], arg1["iccid"])) + # ser = serial_handler.SerialHandler(arg1["PortInfo"]) + # imei, iccid = asyncio.run(ser.init_module(arg1["imei"], arg1["iccid"])) self.__py_test_fp = open(self.text_ctrl_py.GetValue(), "r", encoding="utf8") self.message_queue.put( - {"id": arg1["id"], "msg_id": "PortTest", "PortInfo": self.port_ctrl_list[arg1["id"]].GetValue(), "Imei": imei, "Iccid": iccid, - "script": self.__py_test_fp, "time": self.port_time_list[arg1["id"]], "result": self.port_result_list[arg1["id"]]}) + {"id": arg1["id"], "msg_id": "PortTest", "PortInfo": self.port_ctrl_list[arg1["id"]].GetValue(), + "script": self.__py_test_fp}) def port_test_handler(self, arg1): - ser = serial_handler.SerialHandler(arg1["PortInfo"]) - # 测试时间&结果页面刷新 线程ID - test_res_display = threading.Thread(target=self.__test_time_bar, args=(arg1["id"], arg1["time"], arg1["result"])) - test_res_display.start() - ser.write_module(arg1["script"], self.__exec_py_cmd_list) # 写入脚本开始测试 - ser.ret_result() - - ret_result = [] - log = "" - length = len(self.testFunctions) - for i in range(length): - testFunction = self.testFunctions[i] - message = self.testMessages[i] - - cmd = "TestBase." + testFunction[0] + "()" - ser.exec_cmd(cmd) - - test_result = ser.ret_result() # get recv list - log += test_result - boolean = test_result.split("\r\n")[1:-1] - - if testFunction[1] == 1: - dlg = wx.MessageBox(" 当前测试项为: " + message + "\r\n\r\n 请确认该测试项 【是否通过】", self.port_ctrl_list[arg1["id"]].GetValue(), wx.YES_NO) - if dlg == wx.YES: - boolean = ["True"] - else: + print("start test", arg1["PortInfo"]) + ID = arg1["id"] + self.ListCtrl_list[ID].SetItem(0, 2, _(u"测试中")) + self.ListCtrl_list[ID].SetItemBackgroundColour(0, "Yellow") + try: + ser = serial_handler.SerialHandler(arg1["PortInfo"]) + ser.write_module(arg1["script"], self.__exec_py_cmd_list) # 写入脚本开始测试 + ser.ret_result() + except Exception as e: + print("line 406: ", arg1["PortInfo"], e) + wx.MessageBox(arg1["PortInfo"]+"串口异常,测试脚本写入失败, error %s"%str(e), u'Error', wx.YES_DEFAULT | wx.ICON_INFORMATION) + self.message_queue.put({"id": arg1["id"], "msg_id": "PortTestEnd", "result": 1}) + self.button_start_list[arg1["id"]].Enable(True) + self.procese_num -= 1 + if self.procese_num == 0: + self.button_all_start.Enable(True) + return + + try: + imei = ser.getImei() + print("imei: ", imei) + if imei: + self.Imei_ctrl_list[ID].SetValue(imei) + + ret_result = [] + log = "" + length = len(self.testFunctions) + all_result = "" + for i, testFunction in enumerate(self.testFunctions): + try: + self.ListCtrl_list[ID].SetItem(i, 2, _(u"测试中")) + self.ListCtrl_list[ID].SetItemBackgroundColour(i, "Yellow") + + message = self.testMessages[i] + if testFunction[-1] in [1, 2]: + tips = self.tips_info.get(message) + if tips: + dlg = wx.MessageBox(tips, self.port_ctrl_list[ID].GetValue(), wx.YES_DEFAULT | wx.ICON_INFORMATION) + + if message == _("版本号检测"): + ser.exec_cmd(testFunction[0].replace("\\r\\n", "\r\n")) + test_result = ser.ret_result() + all_result += test_result + print("test_result: ", test_result) + version = self.conf.get("version", "version") + print("version: ", version) + if version in test_result: + boolean = ["True"] + else: + boolean = ["False"] + + elif message == _("Imei号匹配"): + print(os.path.exists(os.path.join(PROJECT_ABSOLUTE_PATH, "imei.txt"))) + if os.path.exists(os.path.join(PROJECT_ABSOLUTE_PATH, "imei.txt")): + f = open(os.path.join(PROJECT_ABSOLUTE_PATH, "imei.txt")) + cont = f.read() + f.close() + print(imei.replace("'","").replace('"',"")) + if imei.replace("'","").replace('"',"") in cont: + boolean = ["True"] + else: + boolean = ["False"] + else: + boolean = ["False"] + else: + cmd = "TestBase." + testFunction[0] + ser.exec_cmd(cmd) + + if self.tips_info.get(message): + test_result = ser.ret_result(self.tips_ctrl_list[ID], self.tips_info.get(message)) + else: + test_result = ser.ret_result() # get recv list + all_result += test_result + print("test_result: ", test_result) + self.logger.write_file(arg1["PortInfo"], test_result) + + boolean = test_result.split("\r\n") + print("boolean: ", boolean) + if boolean[-2] == "False": + boolean = ["False"] + else: + if boolean[-2] == "True": + boolean = ["True"] + elif boolean[-2] == cmd: + boolean = ["True"] + else: + boolean = ["False"] + + except Exception as e: + print("line 445: ", e) boolean = ["False"] - ret_result += boolean - arg1["result"].SetValue("process: "+str(int(i/length*100))+"%") + if testFunction[-1] == 1: + dlg = wx.MessageBox(_(u" 当前测试项为: ") + message + _(u"\r\n\r\n 请确认该测试项 【是否通过】"), self.port_ctrl_list[ID].GetValue(), wx.YES_NO) + if dlg == wx.YES: + boolean = ["True"] + else: + boolean = ["False"] + + if boolean == ["False"]: + self.ListCtrl_list[ID].SetItem(i, 2, _(u"不通过")) + self.ListCtrl_list[ID].SetItemBackgroundColour(i, "Red") + else: + self.ListCtrl_list[ID].SetItem(i, 2, _(u"通过")) + self.ListCtrl_list[ID].SetItemBackgroundColour(i, "Green") + + if len(testFunction) == 3 and (isinstance(testFunction[1], int) or isinstance(testFunction[1], float)) and testFunction[1] > 0: + time.sleep(testFunction[1]) + + ret_result += boolean + + print("all_result: ", all_result) + self.tips_ctrl_list[ID].SetValue(all_result) + except Exception as e: + print("i: ", i) + print("line 464: ", arg1["PortInfo"], e) + wx.MessageBox(arg1["PortInfo"]+"测试异常, error %s"%str(e), u'Error', wx.YES_DEFAULT | wx.ICON_INFORMATION) + self.message_queue.put({"id": arg1["id"], "msg_id": "PortTestEnd", "result": 1}) + self.button_start_list[arg1["id"]].Enable(True) + self.procese_num -= 1 + if self.procese_num == 0: + self.button_all_start.Enable(True) + return - self.__py_exec_result[arg1["id"]] = "\r\n".join([i[0]+": "+i[1] for i in list(zip(self.testMessages, ret_result))]) # 设置测试结果 - self.logger.write_file(arg1["PortInfo"], log) + ser.exec_cmd("uos.remove('/usr/test.py')") + if restartSign == "True": + ser.exec_cmd("from misc import Power\r\nPower.powerRestart()") + + self.button_start_list[arg1["id"]].Enable(True) + self.procese_num -= 1 + if self.procese_num == 0: + self.button_all_start.Enable(True) - self.__init_excel(self.port_ctrl_list[arg1["id"]].GetValue() + "_" + self.port_imei_list[arg1["id"]].GetValue()) # TODO excel写入不要列表形式 + now_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") if "False" not in ret_result: - self.message_queue.put({"id": arg1["id"], "msg_id": "PortTestEnd", "result": 1}) - self.__excel_write([arg1["PortInfo"], arg1["Imei"], arg1["Iccid"], "Success", str(list(zip(self.testMessages, ret_result)))]) + # self.message_queue.put({"id": arg1["id"], "msg_id": "PortTestEnd", "result": 1}) + self.__excel_write([arg1["PortInfo"], now_time, imei, "Success", str(list(zip(self.testMessages, ret_result)))]) else: - self.message_queue.put({"id": arg1["id"], "msg_id": "PortTestEnd", "result": 2}) - self.__excel_write([arg1["PortInfo"], arg1["Imei"], arg1["Iccid"], "Fail", str(list(zip(self.testMessages, ret_result)))]) + # self.message_queue.put({"id": arg1["id"], "msg_id": "PortTestEnd", "result": 2}) + self.__excel_write([arg1["PortInfo"], now_time, imei, "Fail", str(list(zip(self.testMessages, ret_result)))]) - def port_test_end_handler(self, arg1): - self.__test_result[arg1["id"]] = arg1["result"] # 设置测试结果 - self.button_log_list[arg1["id"]].Enable(True) - pub.sendMessage('statusBarUpdate', arg1=["The test has been completed", 1]) - self.__port_det(False) + # def port_test_end_handler(self, arg1): + # self.__port_det(False) - def __init_excel(self, sheet_name): - self.__excel_handler = file_handler.ExcelHandler(PROJECT_ABSOLUTE_PATH + "\\Test-Result.xlsx", sheet_name) # Init Excel + def __init_excel(self): + self.__excel_handler = file_handler.ExcelHandler(PROJECT_ABSOLUTE_PATH + "\\Test-Result.xlsx") # Init Excel rows, columns = self.__excel_handler.get_rows_columns() if rows == 1 and columns == 1: self.__excel_handler.set_cell_value(1, 1, "No.") self.__excel_handler.set_cell_value(1, 2, "Com Port") - self.__excel_handler.set_cell_value(1, 3, "IMEI") - self.__excel_handler.set_cell_value(1, 4, "ICCID") + self.__excel_handler.set_cell_value(1, 3, "Time") + self.__excel_handler.set_cell_value(1, 4, "IMEI") self.__excel_handler.set_cell_value(1, 5, "Test Result") self.__excel_handler.set_cell_value(1, 6, "Test Log") @@ -676,31 +882,12 @@ def __excel_write(self, result): rows, columns = self.__excel_handler.get_rows_columns() self.__excel_handler.set_cell_value(rows + 1, 1, rows) for i, value in enumerate(result): - self.__excel_handler.set_cell_value(rows + 1, i + 2, value) - - def __test_time_bar(self, test_id, time_bar, result_bar): - result_bar.SetValue("Testing") - for i in range(1, 60): - if self.__test_result[test_id] == 0: - time_bar.SetValue(str(i) + "S") - time.sleep(1) - elif self.__test_result[test_id] == 1: - result_bar.SetValue("Test Pass") - break - elif self.__test_result[test_id] == 2: - result_bar.SetValue("Test Fail") - break - else: - result_bar.SetValue("Test the timeout") - - @staticmethod - def __port_det(flag): - if flag: - tSerialDet.exit_event() - pub.sendMessage('statusBarUpdate', arg1=["Port Detect Close", 1]) - else: - tSerialDet.enter_event() - pub.sendMessage('statusBarUpdate', arg1=["Port Detect Start", 1]) + if value == "Success": + self.__excel_handler.set_cell_value(rows + 1, i + 2, value, "Green") + elif value == "Fail": + self.__excel_handler.set_cell_value(rows + 1, i + 2, value, "Red") + else: + self.__excel_handler.set_cell_value(rows + 1, i + 2, value) def port_process_handler(self): while True: @@ -708,29 +895,42 @@ def port_process_handler(self): message = self.message_queue.get(True, 5) except Exception as e: message = None - try: - if message: - # print("message:{}".format(message)) - msg_id = message.get("msg_id") - if msg_id == "exit": - pass - elif msg_id == "PortUpdate": - self.port_update_handler(message) - elif msg_id == "PortInit": - self.port_init_handler(message) - elif msg_id == "PortTest": - self.port_test_handler(message) - elif msg_id == "PortTestEnd": - self.port_test_end_handler(message) - else: - pass - except Exception as e: - print(e) + # try: + if message: + msg_id = message.get("msg_id") + if msg_id == "exit": + pass + elif msg_id == "PortUpdate": + # threading.Thread(target=self.port_update_handler, args=(message,)).start() + self.port_update_handler(message) + elif msg_id == "PortInit": + # threading.Thread(target=self.port_init_handler, args=(message,)).start() + self.port_init_handler(message) + elif msg_id == "PortTest": + threading.Thread(target=self.port_test_handler, args=(message,)).start() + # self.port_test_handler(message) + # elif msg_id == "PortTestEnd": + # threading.Thread(target=self.port_test_end_handler, args=(message,)).start() + # self.port_test_end_handler(message) + else: + pass + # except Exception as e: + # print("line 546: ", e) + + @staticmethod + def __port_det(flag): + if flag: + tSerialDet.exit_event() + else: + tSerialDet.enter_event() # end of class FactoryFrame def close_window(self, event): self.Destroy() - self.__excel_handler.close() + try: + self.__excel_handler.close() + except Exception as e: + pass time.sleep(0.2) wx.GetApp().ExitMainLoop() wx.Exit() @@ -738,39 +938,12 @@ def close_window(self, event): p = subprocess.Popen(process_name, shell=True) -class DialogControl(wx.Dialog): - def __init__(self, parent, title, log_data): - super(DialogControl, self).__init__(parent, title=title, size=(350, 400)) - self.data = log_data - self.panel = wx.Panel(self) - self.main_sizer = wx.BoxSizer(wx.VERTICAL) - self.panel_sizer = wx.BoxSizer(wx.VERTICAL) - self.vbox1 = wx.BoxSizer(wx.VERTICAL) - self.cmd_content = wx.StaticText(self.panel, wx.ID_ANY, _(u"测试日志:")) - self.vbox1.Add(self.cmd_content, proportion=1, flag=wx.LEFT | wx.EXPAND,) - self.text_content = wx.TextCtrl(self.panel, wx.ID_ANY, style=wx.TE_MULTILINE) - self.text_content.SetMinSize((300, 350)) - self.vbox1.Add(self.text_content) - # set sizer - self.panel_sizer.Add(self.vbox1, flag=wx.TOP | wx.EXPAND, border=15) - self.panel.SetSizer(self.panel_sizer) - self.main_sizer.Add(self.panel, - proportion=1, - flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, - border=15 - ) - # Apply sizer and display dialog panel - self.SetSizerAndFit(self.main_sizer) - self.Layout() - self.Center() - # 设置log显示内容 - self.text_content.SetValue(self.data) - - class MyApp(wx.App): languageTab = locale.getdefaultlocale()[0] print("languageTab: ", languageTab) + # languageTab = "en" # 根据系统语言自动设置语言 + # languageTab = "en" if languageTab == "zh_CN": t = gettext.translation('Chinese', PROJECT_ABSOLUTE_PATH + "\\locale", languages=["zh_CN"]) t.install() @@ -793,6 +966,14 @@ def OnInit(self): self.factory_frame = FactoryFrame(None, wx.ID_ANY, "") self.SetTopWindow(self.factory_frame) self.factory_frame.Show() + + # 串口检测线程 + global tSerialDet + tSerialDet = serial_list.SerialDetection() + tSerialDet.setDaemon(True) # set as deamon, stop thread while main frame exit + tSerialDet.start() + + set_config(PROJECT_ABSOLUTE_PATH, self.factory_frame) return True @@ -821,11 +1002,6 @@ def write_file(self, port, data): if __name__ == "__main__": - # 串口检测线程 - tSerialDet = serial_list.SerialDetection() - tSerialDet.setDaemon(True) # set as deamon, stop thread while main frame exit - tSerialDet.start() - file_name = os.path.basename(sys.executable) app = MyApp() - app.MainLoop() + app.MainLoop() \ No newline at end of file diff --git a/media/1665207910586.png b/media/1665207910586.png deleted file mode 100644 index 0379070..0000000 Binary files a/media/1665207910586.png and /dev/null differ diff --git a/media/1665208145345.png b/media/1665208145345.png deleted file mode 100644 index a0f6e8e..0000000 Binary files a/media/1665208145345.png and /dev/null differ diff --git a/media/1692599729648.jpg b/media/1692599729648.jpg new file mode 100644 index 0000000..e0d874f Binary files /dev/null and b/media/1692599729648.jpg differ diff --git a/media/1692599801694.jpg b/media/1692599801694.jpg new file mode 100644 index 0000000..4a9b2df Binary files /dev/null and b/media/1692599801694.jpg differ diff --git a/media/1692599919725.jpg b/media/1692599919725.jpg new file mode 100644 index 0000000..25615de Binary files /dev/null and b/media/1692599919725.jpg differ diff --git a/media/1701828343176.jpg b/media/1701828343176.jpg new file mode 100644 index 0000000..0e59df6 Binary files /dev/null and b/media/1701828343176.jpg differ diff --git a/media/1701828550273.jpg b/media/1701828550273.jpg new file mode 100644 index 0000000..da6fddc Binary files /dev/null and b/media/1701828550273.jpg differ diff --git a/media/download-page.jpg b/media/download-page.jpg new file mode 100644 index 0000000..8cf39aa Binary files /dev/null and b/media/download-page.jpg differ diff --git a/media/quectel.ico b/media/quectel.ico new file mode 100644 index 0000000..a9b82f9 Binary files /dev/null and b/media/quectel.ico differ diff --git a/media/quectel.png b/media/quectel.png new file mode 100644 index 0000000..954fd56 Binary files /dev/null and b/media/quectel.png differ diff --git a/module_test.py b/module_test.py index b58993d..f95ea47 100644 --- a/module_test.py +++ b/module_test.py @@ -2,12 +2,13 @@ import sim import net import uos - +import utime class TestBase(object): # ------该区域为测试代码------ @staticmethod - def det_signal(): + def det_signal(args): + utime.sleep(2) if sim.getStatus() == 1: if net.getConfig()[0] == 5: return True @@ -18,6 +19,7 @@ def det_signal(): @staticmethod def det_file_space(): + utime.sleep(2) if uos.statvfs('usr')[3] > 5: return True else: diff --git a/serial_handler.py b/serial_handler.py index c7953b8..bb8390d 100644 --- a/serial_handler.py +++ b/serial_handler.py @@ -9,6 +9,7 @@ import serial import time import asyncio +import wx class SerialPort(object): @@ -21,13 +22,11 @@ def __init__(self, port, baud): self._conn = None def _open_conn(self): - try: - self._conn = serial.Serial(self._port, self._baud) - return self._conn - except IOError as e: - print("Failed reason: %s" % str(e)) + self._conn = serial.Serial(self._port, self._baud) + return self._conn def _close_conn(self): + print("================== close ===================") self._conn.close() self._conn = None @@ -60,60 +59,41 @@ def __init__(self, port, baud=115200): super(SerialHandler, self).__init__(port, baud) self.init() - async def init_module(self, imei_text_ctrl, iccid_text_ctrl): - self._send_cmd("import sim") - self._send_cmd("import modem") - await asyncio.sleep(.1) - self._conn.flushInput() # 丢弃接收缓存中的所有数据 - try: - self._send_cmd("modem.getDevImei()") - await asyncio.sleep(.1) - imei = self.ret_result().split("\r\n")[1] - # print("imei: {}".format(imei)) - except Exception as e: - print("get imei error: {}".format(e)) - imei = "-1" - finally: - imei_text_ctrl.SetValue(imei[1:-1]) - try: - self._send_cmd("sim.getIccid()") - await asyncio.sleep(.1) - iccid = self.ret_result().split("\r\n")[1] - # print("iccid: {}".format(iccid)) - if iccid == "-1": - iccid = "'No SIM card'" - except Exception as e: - print("get iccid error: {}".format(e)) - iccid = "-1" - finally: - iccid_text_ctrl.SetValue(iccid[1:-1]) - return imei[1:-1], iccid[1:-1] + def write_module(self, source, py_cmd, filename="test.py"): + time.sleep(2) + self._conn.write(b"\x03") + self._conn.write(b"\x03") + self._conn.write(b"\x01") + self._conn.write(b"\x04") + self._conn.write(b"\x02") + # await asyncio.sleep(.1) + time.sleep(2) + self._conn.flushInput() + self._test_conn() - def write_module(self, source, py_cmd, filename="test.py"): - try: - if self._test_conn(): - self._conn.write(b"\x01") - self._send_cmd("f=open('/usr/" + filename + "','wb')") # 写入文件 - self._send_cmd("w=f.write") - while True: - time.sleep(.1) - data = source.read(255) - if not data: - break - else: - self._send_cmd("w(" + repr(data) + ")") - self._conn.write(b"\x04") - self._send_cmd("f.close()") - self._conn.write(b"\x04") - self._conn.write(b"\x02") + self._conn.write(b"\x01") + self._send_cmd("f=open('/usr/" + filename + "','wb')") # 写入文件 + self._send_cmd("w=f.write") + while True: + time.sleep(.1) + data = source.read(255) + if not data: + break else: - print("串口异常") - except Exception as e: - print("文件写入异常:{}".format(e)) - finally: - source.close() - return self.exec_cmd(py_cmd[0]) + self._send_cmd("w(" + repr(data) + ")") + self._conn.write(b"\x04") + self._send_cmd("f.close()") + self._conn.write(b"\x04") + self._conn.write(b"\x02") + + self._conn.write(b"\x01") + self._conn.write(b"\x04") + self._conn.write(b"\x02") + + source.close() + self.exec_cmd(py_cmd[0]) + return True def exec_py(self, cmd): self._send_cmd(cmd[0]) @@ -134,13 +114,49 @@ async def run_cmd(self,source:list, log_text_ctrl): log_text_ctrl.SetValue(result_list) return result_list - def ret_result(self): + def getImei(self): + self._send_cmd("import modem") + # await asyncio.sleep(.1) + time.sleep(.1) + self._conn.flushInput() # 丢弃接收缓存中的所有数据 + try: + self._send_cmd("modem.getDevImei()") + # await asyncio.sleep(.1) + imei = self.ret_result().split("\r\n")[1] + # print("imei: {}".format(imei)) + except Exception as e: + print("get imei error: {}".format(e)) + imei = "-1" + return imei + + def ret_result(self, tips_ctrl=None, tips_info=None): data = "" - for i in range(30): + for i in range(60): + if tips_info: + tips_ctrl.SetValue("") + + font1 = wx.Font(15, wx.MODERN, wx.NORMAL, wx.NORMAL, False, 'Consolas') + tips_ctrl.SetFont(font1) + tips_ctrl.SetDefaultStyle(wx.TextAttr(wx.RED)) + tips_ctrl.AppendText(_(u"倒计时: ")+str(60-i)) + + font1 = wx.Font(10, wx.MODERN, wx.NORMAL, wx.NORMAL, False, 'Consolas') + tips_ctrl.SetFont(font1) + tips_ctrl.SetDefaultStyle(wx.TextAttr(wx.RED)) + tips_ctrl.AppendText("\r\n") + tips_ctrl.AppendText(tips_info) data += self._conn.read(self._conn.inWaiting()).decode("utf-8", errors="ignore") if data.endswith(">>> "): break + time.sleep(1) + + if tips_info: + tips_ctrl.SetValue("") + + if not data.endswith(">>> "): + self._conn.write(b"\x03") time.sleep(0.5) + data += self._conn.read(self._conn.inWaiting()).decode("utf-8", errors="ignore") return data def exit_test(self): diff --git a/serial_list.py b/serial_list.py index 3e023b4..d411900 100644 --- a/serial_list.py +++ b/serial_list.py @@ -1,10 +1,10 @@ #!/usr/bin/env python # -*- coding: UTF-8 -*- """ -@Project:Factory_test +@Project:Factory_test @File:serial_list.py @Author:rivern.yuan -@Date:2022/9/6 15:59 +@Date:2022/9/6 15:59 """ import time @@ -28,12 +28,23 @@ def exit_event(self): def enter_event(self): self._exit = False - def get_com_number(self, vid_pid, location): + def get_com_number(self): port_list = [] + repl_port = [("0x2C7C:0x0901", "x.8"), # Unisoc + ("0x2C7C:0x6001", "x.5"), # N 系列 + ("0x2C7C:0x6002", "x.5"), # M 系列 + ("0x2C7C:0x6005", "x.5"), # A 系列 + ("0x2C7C:0x0700", "x.1"), # BG95 + ("0x2C7C:0x0903", "x.5"), # Eigen + ("0x2C7C:0x6002", "x.20")] # M 系列 新驱动 for p in list(self.serPort.comports()): - if p.vid == int(vid_pid.split(":")[0], 16) and p.pid == int(vid_pid.split(":")[1], 16): - if location in p.location: + print(p.description) + for vid_pid, location in repl_port: + location_ = p.location if p.location is not None else "" + if (p.vid == int(vid_pid.split(":")[0], 16) and p.pid == int(vid_pid.split(":")[1], 16) and location in location_) or "Quectel USB REPL Port" in p.description: port_list.append(p.device) + break + return port_list def run(self): @@ -43,11 +54,8 @@ def run(self): pass else: if serial_list == [] or serial_list != self.serPort.comports(): - # serial_port = self.get_com_number("0x2C7C:0x6005", "x.8") - # serial_port.extend(self.get_com_number("0x2C7C:0x6005", "x.5")) - serial_port = self.get_com_number("0x2C7C:0x0901", "x.8") - serial_port.extend(self.get_com_number("0x2C7C:0x6001", "x.5")) - # print("设备列表为{}".format(serial_port)) + serial_list = self.serPort.comports() + serial_port = self.get_com_number() pub.sendMessage('serialUpdate', arg1=serial_port) time.sleep(1) diff --git a/sort_setting.json b/sort_setting.json index d58feb9..4c70b8d 100644 --- a/sort_setting.json +++ b/sort_setting.json @@ -1,4 +1,5 @@ { - "sort": [["det_file_space", 1], ["det_signal", 0]], - "message": ["内存检测", "信号检测"] + "info": [["Memory test", "det_file_space()", 1], + ["Signal test", "det_signal('test')", 0]], + "tips": {"Signal test": "Please press button 1"} } \ No newline at end of file pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy