From: SnickerSun Date: Fri, 28 Nov 2025 12:13:16 +0000 (+0800) Subject: 架构设计完毕,统一走TestPortController,4个设备独立。 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=1ed59c9d7ffd5887d8b54c6f75007a51cc92ac77;p=mirrors%2Ffactory_tool.git 架构设计完毕,统一走TestPortController,4个设备独立。 --- diff --git a/HiBTMacWriteTool.pro b/HiBTMacWriteTool.pro index 6ac13f3..be0c714 100644 --- a/HiBTMacWriteTool.pro +++ b/HiBTMacWriteTool.pro @@ -19,7 +19,8 @@ SOURCES += main.cpp\ custom.cpp \ sqldbmanager.cpp \ settings.cpp \ - dialogsettings.cpp + dialogsettings.cpp \ + test_port_controller.cpp HEADERS += mainwindow.h \ mythread.h \ @@ -28,7 +29,8 @@ HEADERS += mainwindow.h \ custom.h \ sqldbmanager.h \ settings.h \ - dialogsettings.h + dialogsettings.h \ + test_port_controller.h #HEADERS += ui_mac_settings.h \ # ui_mainwindow.h diff --git a/Setting.ini b/Setting.ini index 02406f5..7436ea5 100644 --- a/Setting.ini +++ b/Setting.ini @@ -1,6 +1,6 @@ [Uart_setting] uart_com=COM8 -uart_baud=18 +uart_baud=11 spp_addr= [Download_Setting] diff --git "a/docs/m1_\344\272\247\346\265\213\346\227\245\345\277\227.txt" "b/docs/m1_\344\272\247\346\265\213\346\227\245\345\277\227.txt" new file mode 100644 index 0000000..9097b46 --- /dev/null +++ "b/docs/m1_\344\272\247\346\265\213\346\227\245\345\277\227.txt" @@ -0,0 +1,477 @@ +eg info:int en:0,int:0,int sts:0. +APP|int clr:0,clr sts:0,int set:0. +APP|pmu_power_on_init begin +APP|pmu_power_�n_init end +chip temperature=25.000000(tmp=1770) +APP|Flash id is 186585, init success +APP|entering NormalMode +APP|partition init success +APP|upg init success +[osal_msg_queue_create:25]:qName:nv_write_task qID=0x0 +APP|calibration nv is not active + +cpu 0 entering scheduler +app_init start ok +APP|thread_main start +APP|find nand flash chip id: 0x0B52 +APP|nand flash XT26Q02D start init +APP| +nandflash init start. +APP|xt26q02d_init +APP|nandflash A0 Reg:0x0 +APP|nandflash B0 Reg:0x11 +APP|nandflash C0 Reg:0x2 +APP| +nandflash_qspi_init success +APP| + nandflash init end. +APP|nandflash init success +APP|Succ read lcd id! Lcd id: 0x5598 +get nv local_addr : ******68663c +CALLENDAR:year = 1970, month = 1, day = 1, hour = 0, minute = 0, second = 0 +callendar timestamp = 0 +sync time timestamp 0, timezone_in_quarters 0 +[A][aw88082_i2c_init:353]aw88082 i2c init success +[osal_msg_queue_create:25]:qName:sap_msg qID=0x1 +APP|audio init OK +APP|**********startup info********** +APP|os init class is liteos. +APP|store init class is nandflash. +APP|display init class is MIPI. +APP|board init class is E0B4. +APP|psram density is 32MB. +APP|**********startup info********** +APP|No need to upgrade... +[osal_msg_queue_create:25]:qName:at_queue qID=0x2 +[osal_msg_queue_create:25]:qName:graphic_at_service_queue qID=0x3 +[osal_msg_queue_create:25]:qName:app_at_service_queue qID=0x4 +[osal_msg_queue_create:25]:qName:audio_at_service_queue qID=0x5 +[osal_msg_queue_create:25]:qName:bt_cmd_queue qID=0x6 +[osal_msg_queue_create:25]:qName:media_at_service_queue qID=0x7 +[osal_msg_queue_create:25]:qName:dfx_msg qID=0x8 +[osal_msg_queue_create:25]:qName:transmit qID=0x9 +APP|Turning on LCD backlight... +kvPath: /kvstore +dataPath: +Set value ret: -1 +brightness:0 +Brightness: 0% → Fall Edge: 7 → LED Current: 2.5mA +APP|LCD backlight turned on (CUSTOM_UTILS + BOARD_LEINIAO) +[DISPLAY I/] GrallocInitialize: gralloc initialize success +[DISPLAY I/] LayerInitialize: layer initialize success +[DISPLAY I/] PrintLayerInfo: layerInfo: +[DISPLAY I/] PrintLayerInfo: type = 0 +[DISPLAY I/] PrintLayerInfo: width = 360 +[DISPLAY I/] PrintLayerInfo: height = 360 +[DISPLAY I/] PrintLayerInfo: bpp = 24 +[DISPLAY I/] PrintLayerInfo: pixFormat = 17 +[DISPLAY I/] VGUInitialize: VGU initializes successfully +[DISPLAY I/] InitMemPool: Memory Pool has been inited. +[DISPLAY I/] GrallocInitialize: gralloc initialize success +====InitDfxCmd=== +[Graphic Error] [ResumeSlice: 225]No valid slice to resume +APP|[POWER_MANAGER E/] filter_timer_execute_system_rule: filter timer, current default timeout:5000, keepon time:25000, event:5. +APP|No need to upgrade... +APP|SET DSP freq=3, div=6, codec freq=3, div=36 +[VAU_ERROR][vau_api_check_surface 108]input phy_addr is null! +[VAU_ERROR][vau_api_check_surface_list 144]vau check src surface[0] failed! +[VAU_ERROR][uapi_vau_compose 861]call vau_check_surface_list fail ret = 0x80004000! +[DISPLAY E/] BlitMultiImgOnce: uapi_vau_compose failure, ret = 0x80004000! +[DISPLAY E/] BlitMultiImgOnce: src[0] w:360 h:360 str:1472 fmt:0 cmp:0 rect:[0,0,360,360] outRect:[0,0,360,360] +[Graphic Error] [BlitImages: 889]RenderBlit failed! +[A][ALERT][sys_cmd_check_cmd_done:164] wait_time_us = 600 +[A][ALERT][drv_sys_pon:297] DSP0 power on +APP|lwip_main run start. +APP|audio manager init ok +APP|app_main run start. +[osal_msg_queue_create:25]:qName:app_queue qID=0xb +APP|uapi_battery_init ! +[osal_msg_queue_create:25]:qName:battery_queue qID=0xc +APP|charger not plugged ,disable charge ! +[WEARABLE E/] GetFeatureApi failed +APP|charger not plugged ,disable charge ! +[WEARABLE E/] GetFeatureApi failed +APP|uapi_custom_cmd_service_init ! +[osal_msg_queue_create:25]:qName:custom_cmd_service_queue qID=0xd +APP|uapi_custom_fileoperate_service_init ! +[osal_msg_queue_create:25]:qName:custom_fileoperate_service_queue qID=0xe +APP|No need to upgrade... +[WEARABLE I/] InitBroadcastService start! +[WEARABLE I/] start! topicSubscriberInfo=0x0x6c104e68 +[WEARABLE I/] InitBroadcastService end! +[WEARABLE E/] LoadManagementFromFile open fail +[WEARABLE E/] SaveManagementToFile open fail +I ams starts successfully +I bms starts successfully +[00:00:01:747][I][Init:37]Locator service starts successfully +[00:00:01:749][D][Init:56][SERVICE:sensor_service]: Init begin +[WEARABLE I/] WatchConnectCmdRegister +I ams feature init success +I [BMS] bms feature init success +[00:00:01:752][I][Init:56]Locator feature init success +[00:00:01:753][D][GetTaskConfig:80][SERVICE:sensor_service]: GetTaskConfig begin +[WEARABLE I/] BroadcastService featureId=4294967295, queueId=536924516, serviceId=2 +[WEARABLE I/] BroadcastFeature featureId=0, queueId=536924516, serviceId=2 +E Fail to open dir:/user/dialpubkey! +E Failed to create file +E Public key write failed! +[WEARABLE I/] NativeAbility InstallAbility +D MemUtils::InitPSRam g_psramMemory = 6c200000 +[WEARABLE I/] InitNativeLauncher: Minimal startup - Blue window only +[WEARABLE I/] Cleared all existing views from RootView +[WEARABLE I/] Blue window created and displayed: 360x360 +I AbilityMgrSliteFeature::OnFeatureInitialize featureId = 0, queueId = 536924708, serviceId = 6 +[WEARABLE I/] NativeAbility OnActive +[WEARABLE E/] NativeAbility ResumeAbility 0 failed +I BundleMgrService::ServiceMessageHandle +[00:00:02:527][I][OnFeatureInitialize:85]Locator feature init +[00:00:02:528][I][InitAbility:84]initAbility start +[00:00:02:529][I][Initialize:71]ability constructed. +[00:00:02:530][E][InitAbility:90]Initialize gps ability, result 1 +[00:00:02:531][I][Initialize:54]LocatorAbility Initialize. +[00:00:02:532][I][OnFeatureInitialize:89]LocatorAbility initialize success +APP|[POWER_MANAGER E/] filter_timer_execute_system_rule: filter timer, current default timeout:5000, keepon time:0, event:5. +[00:00:02:538][D][Initialize:62][SERVICE:sensor_service]: Initialize begin +[00:00:02:540][D][NewSensorInterfaceInstance:47]Get sensor device instance success +[A][ALERT][sys_cmd_check_cmd_done:164] wait_time_us = 900 +[A][ALERT][drv_sys_pd:331] DSP0 power down +APP|app_main run start. +APP|sys_slp: 0x1 +» AT^PMADDVOTE +» AT^PMADDVOTE +« MCU has got pm_id_debug vote + +MCU WAKEUP SUCCESS + +OK~ +[Graphic Error] [PauseSlice: 236]No valid slice to pause +APP|uapi_lcd_backlight_off +Output RESET_LCD_GPIO 1 , VCI_LCD_GPIO 0 +APP|app_main run start. +APP|sys_slp: 0x1 +» AT^GETIDS +« [nandflash id:] b52 +[norflash id:] 186585 +[sdk id:]1.0.9 +[soc id:] +0x5DD4 0x5790 0xD300 0x23C2 +0xC2D7 0xEF08 0x030A 0x0F78 +0x81C1 0x0001 + +OK~ +» AT^GETBTMAC +« get nv local_addr : ******68663c +fac:^^^^ BTMAC=28:11:06:68:66:3C ^^^^ CyweeChipInfo= +APP|app_main run start. +APP|sys_slp: 0x0 +» AT^BTENABLE +« package_common_cmd_to_bt strCmd 36 5A 00 03 00 09 01 9A 20 inParam (null) para_len 0 +commandID = 0x1 payload_len=0 +bt_manager_at_process cmdId=0x1 atId=0x901 +[bts][info] btsrv_set_log_type_level bts sert log type levle:ff2 +gap reg cbk ret 0 +func:audio_manager_init, line:69, success +a2dp reg cbk ret 0 +a2dp reg cbk ret 0 +avrcp reg cbk ret 0 +[osal_msg_queue_create:25]:qName:BT_SERVICE_MSG qID=0x19 +[bts][info] btsrv_task_init btsrv_init: task create success +gap_state_changed_callback transport: 1 status: 0 +[bts][info] btsdk_get_discovery_mode mode = 00 +[bts][info] gap_br_set_bt_scan_mode set scan mode old=0 new=4 +[bts][info] gap_br_set_bt_scan_mode btsdk_set_discovery_mode mode: d ret: 0 +[bts][info] pan_register_cbk pan service register cbk:A TO B start.[bts][info] btsdk_get_discovery_mode mode = 0d +gap_scan_mode_changed_callback mode: 4 + +[bts][info] bt_acore_get_config_sync_flash [ACore] bt read nv config succ, real_len:585. +gap_state_changed_callback transport: 2 status: 1 +gap_state_changed_callback transport: 1 status: 1 +bt enable ok + +OK~ +APP|app_main run start. +APP|sys_slp: 0x0 +» AT^BTSCANTEST=1 +« APP|[BtScan] Starting Bluetooth scan test... +APP|[BtScan] Enabling Bluetooth stack (same as AT^BTENABLE)... +APP|[BtScan] Waiting for Bluetooth stack ready... +APP|[BtScan] Inquiry parameters set successfully +APP|[BtScan] Discovery state changed: 1 +APP|[BtScan] Discovery state changed: 2 +[bts][info] btsrv_start_bt_discovery discovery started +APP|[BtScan] Discovery started successfully +APP|[BtScan] Bluetooth scan started successfully +APP|[BtScan] Scanning for devices... +BT SCAN TEST START: Success +APP|app_main run start. +APP|sys_slp: 0x0 +[bts][info] btsrv_handle_remote_device_found addr: ****a4a2ca05 [little endian: 05caa2a4**** ] name: 18J173203837 hdl: 0 +[bts][debug] btsrv_add_remote_dev_node addr: ****a4a2ca05 hdl: 0 +[bts][info] btsrv_notify_gap_discovery_result descovery result +APP|[BtScan] New device discovered: AC:3F:A4:A2:CA:05 +APP|[BtScan] Device name: 18J173203837 +[bts][info] btsrv_notify_gap_discovery_result found device addr: ****a4a2ca05 name: 18J173203837APP|[BtScan] Device: AC:3F:A4:A2:CA:05, RSSI=-93 dBm +APP|app_main run start. +APP|sys_slp: 0x0 +[bts][info] btsrv_handle_remote_device_found addr: ****a4a2ca05 [little endian: 05caa2a4**** ] name: 18J173203837 hdl: 0 +APP|app_main run start. +APP|sys_slp: 0x0 +» AT^BTSCANTEST=2 +« APP|[BtScan] Stopping Bluetooth scan test... +[bts][info] gap_br_cancel_discovery btsdk_stop_device_discovery ret=0x0 +[bts][info] gap_br_c[bts][info] btsrv_inquiry_complete_ind_callback inquiry complete +[bts][info] btsrv_handle_conn_event_msg set discovery status to stop +APP|[BtScan] Discovery state changed: 3 +ancel_discovery discovery stopped +APP|[BtScan] Discovery state changed: 3 +APP|[BtScan] Final scan results: +APP|[BtScan] Found 1 device(s): +APP|[BtScan] Device[1]: MAC=AC:3F:A4:A2:CA:05, RSSI=-93 dBmAPP|, Name=18J173203837APP| +APP|[BtScan] Bluetooth scan stopped +BT SCAN TEST STOP: Success +» AT^BTSCANTEST=2 +« APP|[BtScan] Stopping Bluetooth scan test... +APP|[BtScan] Scan not running +BT SCAN TEST STOP: Success +APP|app_main run start. +APP|sys_slp: 0x0 +» AT^BTSCANTEST=2 +« APP|[BtScan] Stopping Bluetooth scan test... +APP|[BtScan] Scan not running +BT SCAN TEST STOP: Success +APP|charger not plugged ,disable charge ! +[WEARABLE I/] MsgCenterNotify: args=0x0x6c103670, topic=10021 +[WEARABLE I/] MsgCenterNotifyProc:: LowPower Alarm ! +[WEARABLE I/] MsgCenterNotifyLowpowerProc: alarm_type=1 +kvPath: /kvstore +dataPath: +Set value ret: -1 +brightness:0 +Brightness: 0% → Fall Edge: 7 → LED Current: 2.5mA +[WEARABLE E/] MsgCenterNotifyLowpowerProc: ThunderBirdMainView::GetInstance() returned null +APP|mipi_tx has been enable! +APP|Succ read lcd id! Lcd id: 0x5598 +APP|timeout when wait phy ready +kvPath: /kvstore +dataPath: +Set value ret: -1 +brightness:0 +[Graphic Error] [ResumeSlice: 225]No valid slice to resume +APP|[POWER_MANAGER E/] filter_timer_execute_system_rule: filter timer, current default timeout:5000, keepon time:5000, event:5. +APP|app_main run start. +APP|sys_slp: 0x0 +» AT^GPIOTEST=2 +« APP|[GpioTest] Starting GPIO test... +APP|[GpioTest] No GPIO pairs configured, initializing with default config... +APP|[GpioTest] Invalid input pin name: HSUART_CTS +APP|[GpioTest] Parsed 34 GPIO pairs from JSON +APP|[GpioTest] Default config initialized successfully +APP|[GpioTest] Starting GPIO test with 34 pairs... +APP|[GpioTest] Testing pair 0: S_AGPIO_L23 (input) <-> S_AGPIO_L12 (output) +APP|[GpioTest] Pair 0: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 1: S_AGPIO_L13 (input) <-> S_AGPIO_L31 (output) +APP|[GpioTest] Pair 1: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 2: S_AGPIO_L3 (input) <-> S_AGPIO_L2 (output) +APP|[GpioTest] Pair 2: PASSED - S_AGPIO_L3 <-> S_AGPIO_L2 +APP|[GpioTest] Testing pair 3: S_AGPIO_L1 (input) <-> S_AGPIO_L4 (output) +APP|[GpioTest] Pair 3: PASSED - S_AGPIO_L1 <-> S_AGPIO_L4 +APP|[GpioTest] Testing pair 4: S_AGPIO_L0 (input) <-> S_AGPIO_R4 (output) +APP|[GpioTest] Pair 4: PASSED - S_AGPIO_L0 <-> S_AGPIO_R4 +APP|[GpioTest] Testing pair 5: S_AGPIO_R5 (input) <-> S_MGPIO14 (output) +APP|[GpioTest] Pair 5: PASSED - S_AGPIO_R5 <-> S_MGPIO14 +APP|[GpioTest] Testing pair 6: S_MGPIO13 (input) <-> S_AGPIO_R10 (output) +APP|[GpioTest] Pair 6: PASSED - S_MGPIO13 <-> S_AGPIO_R10 +APP|[GpioTest] Testing pair 7: S_MGPIO11 (input) <-> S_MGPIO12 (output) +APP|[GpioTest] Pair 7: PASSED - S_MGPIO11 <-> S_MGPIO12 +APP|[GpioTest] Testing pair 8: S_AGPIO_R2 (input) <-> S_AGPIO_R1 (output) +APP|[GpioTest] Pair 8: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 9: S_AGPIO_L24 (input) <-> S_AGPIO_L17 (output) +APP|[GpioTest] Pair 9: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 10: S_AGPIO_L21 (input) <-> S_AGPIO_L11 (output) +APP|[GpioTest] Pair 10: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 11: S_AGPIO_L19 (input) <-> S_AGPIO_R0 (output) +APP|[GpioTest] Pair 11: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 12: S_HGPIO13 (input) <-> S_AGPIO_R3 (output) +APP|[GpioTest] Pair 12: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 13: S_AGPIO_R6 (input) <-> S_MGPIO25 (output) +APP|[GpioTest] Pair 13: PASSED - S_AGPIO_R6 <-> S_MGPIO25 +APP|[GpioTest] Testing pair 14: S_MGPIO26 (input) <-> S_MGPIO23 (output) +APP|[GpioTest] Pair 14: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 15: S_MGPIO24 (input) <-> S_MGPIO31 (output) +APP|[GpioTest] Pair 15: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 16: S_MGPIO29 (input) <-> S_MGPIO30 (output) +APP|[GpioTest] Pair 16: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 17: S_MGPIO32 (input) <-> S_MGPIO28 (output) +APP|[GpioTest] Pair 17: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 18: S_MGPIO27 (input) <-> S_MGPIO22 (output) +APP|[GpioTest] Pair 18: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 19: S_MGPIO21 (input) <-> S_MGPIO19 (output) +APP|[GpioTest] Pair 19: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 20: S_MGPIO20 (input) <-> S_AGPIO_R7 (output) +APP|[GpioTest] Pair 20: PASSED - S_MGPIO20 <-> S_AGPIO_R7 +APP|[GpioTest] Testing pair 21: S_AGPIO_R8 (input) <-> S_AGPIO_R9 (output) +APP|[GpioTest] Pair 21: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 22: S_AGPIO_L30 (input) <-> S_AGPIO_L29 (output) +APP|[GpioTest] Pair 22: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 23: S_AGPIO_L32 (input) <-> S_AGPIO_L20 (output) +APP|[GpioTest] Pair 23: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 24: S_AGPIO_L15 (input) <-> S_HGPIO5 (output) +APP|[GpioTest] Pair 24: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 25: S_HGPIO4 (input) <-> S_HGPIO0 (output) +APP|[GpioTest] Pair 25: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 26: S_HGPIO1 (input) <-> S_HGPIO2 (output) +APP|[GpioTest] Pair 26: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 27: S_HGPIO3 (input) <-> S_MGPIO3 (output) +APP|[GpioTest] Pair 27: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 28: S_MGPIO1 (input) <-> S_MGPIO2 (output) +APP|[GpioTest] Pair 28: PASSED - S_MGPIO1 <-> S_MGPIO2 +APP|[GpioTest] Testing pair 29: S_MGPIO0 (input) <-> S_MGPIO6 (output) +APP|[GpioTest] Pair 29: FAILED - Output HIGH but input read 0 (expected HIGH) +APP|[GpioTest] Testing pair 30: S_MGPIO9 (input) <-> S_MGPIO8 (output) +APP|[GpioTest] Pair 30: PASSED - S_MGPIO9 <-> S_MGPIO8 +APP|[GpioTest] Testing pair 31: S_MGPIO7 (input) <-> S_MGPIO8 (output) +APP|[GpioTest] Pair 31: PASSED - S_MGPIO7 <-> S_MGPIO8 +APP|[GpioTest] Testing pair 32: S_AGPIO_L28 (input) <-> S_AGPIO_L18 (output) +APP|[GpioTest] Pair 32: PASSED - S_AGPIO_L28 <-> S_AGPIO_L18 +APP|[GpioTest] Testing pair 33: S_HGPIO9 (input) <-> S_AGPIO_L26 (output) +APP|[GpioTest] Pair 33: PASSED - S_HGPIO9 <-> S_AGPIO_L26 +APP|[GpioTest] Test completed: 13 passed, 21 failed +APP|[GpioTest] Failed pairs: +APP|[GpioTest] Pair 0: S_AGPIO_L23 (input) <-> S_AGPIO_L12 (output) +APP|[GpioTest] Pair 1: S_AGPIO_L13 (input) <-> S_AGPIO_L31 (output) +APP|[GpioTest] Pair 8: S_AGPIO_R2 (input) <-> S_AGPIO_R1 (output) +APP|[GpioTest] Pair 9: S_AGPIO_L24 (input) <-> S_AGPIO_L17 (output) +APP|[GpioTest] Pair 10: S_AGPIO_L21 (input) <-> S_AGPIO_L11 (output) +APP|[GpioTest] Pair 11: S_AGPIO_L19 (input) <-> S_AGPIO_R0 (output) +APP|[GpioTest] Pair 12: S_HGPIO13 (input) <-> S_AGPIO_R3 (output) +APP|[GpioTest] Pair 14: S_MGPIO26 (input) <-> S_MGPIO23 (output) +APP|[GpioTest] Pair 15: S_MGPIO24 (input) <-> S_MGPIO31 (output) +APP|[GpioTest] Pair 16: S_MGPIO29 (input) <-> S_MGPIO30 (output) +APP|[GpioTest] Pair 17: S_MGPIO32 (input) <-> S_MGPIO28 (output) +APP|[GpioTest] Pair 18: S_MGPIO27 (input) <-> S_MGPIO22 (output) +APP|[GpioTest] Pair 19: S_MGPIO21 (input) <-> S_MGPIO19 (output) +APP|[GpioTest] Pair 21: S_AGPIO_R8 (input) <-> S_AGPIO_R9 (output) +APP|[GpioTest] Pair 22: S_AGPIO_L30 (input) <-> S_AGPIO_L29 (output) +APP|[GpioTest] Pair 23: S_AGPIO_L32 (input) <-> S_AGPIO_L20 (output) +APP|[GpioTest] Pair 24: S_AGPIO_L15 (input) <-> S_HGPIO5 (output) +APP|[GpioTest] Pair 25: S_HGPIO4 (input) <-> S_HGPIO0 (output) +APP|[GpioTest] Pair 26: S_HGPIO1 (input) <-> S_HGPIO2 (output) +APP|[GpioTest] Pair 27: S_HGPIO3 (input) <-> S_MGPIO3 (output) +APP|[GpioTest] Pair 29: S_MGPIO0 (input) <-> S_MGPIO6 (output) +APP|[GpioTest] Test finished +GPIO TEST START: Success +APP|app_main run start. +APP|sys_slp: 0x0 +[Graphic Error] [PauseSlice: 236]No valid slice to pause +APP|uapi_lcd_backlight_off +Output RESET_LCD_GPIO 1 , VCI_LCD_GPIO 0 +APP|app_main run start. +APP|sys_slp: 0x0 +APP|app_main run start. +APP|sys_slp: 0x0 +APP|app_main run start. +APP|sys_slp: 0x0 +APP|app_main run start. +APP|sys_slp: 0x0 +APP|app_main run start. +APP|sys_slp: 0x0 +APP|app_main run start. +APP|sys_slp: 0x0 +APP|charger not plugged ,disable charge ! +[WEARABLE I/] MsgCenterNotify: args=0x0x6c103670, topic=10021 +[WEARABLE I/] MsgCenterNotifyProc:: LowPower Alarm ! +[WEARABLE I/] MsgCenterNotifyLowpowerProc: alarm_type=1 +kvPath: /kvstore +dataPath: +Set value ret: -1 +brightness:0 +Brightness: 0% → Fall Edge: 7 → LED Current: 2.5mA +[WEARABLE E/] MsgCenterNotifyLowpowerProc: ThunderBirdMainView::GetInstance() returned null +APP|mipi_tx has been enable! +APP|Succ read lcd id! Lcd id: 0x5598 +APP|timeout when wait phy ready +kvPath: /kvstore +dataPath: +Set value ret: -1 +brightness:0 +[Graphic Error] [ResumeSlice: 225]No valid slice to resume +APP|[POWER_MANAGER E/] filter_timer_execute_system_rule: filter timer, current default timeout:5000, keepon time:5000, event:5. +APP|app_main run start. +APP|sys_slp: 0x0 +» AT^AUDIOTEST=5 +« APP|[AudioTest] Starting audio test... +[00:01:30:051][W]{ai_media_service_init():808} AI media service already initialized +[00:01:30:052][E]{old_Start_AIVoice():1289} StartAIVoice +[00:01:30:053][I]{GetGlobalMutex():709} Global AI voice context mutex created successfully +[00:01:30:055][I]{old_Start_AIVoice():1325} Using custom input audio params: format=1, channels=1, sampleRate=16000 +[00:01:30:057][I]{old_Start_AIVoice():1340} Using custom output audio params: format=1, channels=1, sampleRate=16000 +[00:01:30:060][I]{old_Start_AIVoice():1356} OGG encapsulation disabled by parameter +[00:01:30:061][E]{old_Start_AIVoice():1362} g_aiVoiceContext->taskHandle +[00:01:30:063][I]{CreateAIVoiceQueue():747} AI voice input queue created successfully +APP|SET DSP freq=3, div=5, codec freq=3, div=36 +APP|set hifi mode=2. +APP|SET DSP freq=3, div=5, codec freq=3, div=36 +[A][ALERT][sys_cmd_check_cmd_done:164] wait_time_us = 500 +[A][ALERT][drv_sys_pon:297] DSP0 power on +[00:01:30:104][I]{old_Start_AIVoice():1392} AI voice thread created successfully with name: AIVoiceThread +APP|[AudioTest] Play thread started +APP|[AudioTest] Pre-filled 5 periods (160 bytes, 5.0 ms) of PCM data +[00:01:30:108] E/TrackHandle :{StreamWriteTrack():720} track[0] is neither running or pause, write failed +[00:01:30:110] E/AudioManagerCWrapper :{AudioStreamOutStreamWrite():365} audio stream out play failed 0xffffffff +APP|[AudioTest] Audio test started successfully +APP|[AudioTest] Playing 1kHz tone, monitoring volume every 0.5s... +AUDIO TEST START: Success + Playing 1kHz tone, monitoring volume every 0.5s... +aw_sysst_check succed +aw_pa_start +[00:01:30:367][I]{CreateAIVoiceInputThread():960} AI voice input thread created successfully +[00:01:30:368][I]{RunAIVoice():1045} RunAIVoice: waiting for queue data... +[00:01:30:369][I]{AIVoiceInputThreadFunc():978} AI voice input thread started +APP|[AudioTest] Volume - RMS: 0.02% (-75.19 dB), Peak: 0.45% (-46.96 dB), Level: 静音 +APP|app_main run start. +APP|sys_slp: 0x0 +APP|[AudioTest] Volume - RMS: 13.79% (-17.21 dB), Peak: 36.59% (-8.73 dB), Level: 中 +APP|[AudioTest] Volume - RMS: 15.28% (-16.32 dB), Peak: 31.50% (-10.04 dB), Level: 中 +APP|[AudioTest] Volume - RMS: 14.13% (-17.00 dB), Peak: 31.48% (-10.04 dB), Level: 中 +APP|[AudioTest] Volume - RMS: 14.53% (-16.76 dB), Peak: 31.32% (-10.08 dB), Level: 中 +APP|[AudioTest] Volume - RMS: 14.11% (-17.01 dB), Peak: 31.38% (-10.07 dB), Level: 中 +» AT^AUDIOTEST=6 +« APP|[AudioTest] Stopping audio test... +APP|[AudioTest] Play thread stopped +APP|[AudioTest] Calling StopAIVoice()... +Waiting for AI voice thread to stop... +Thread validation passed, waiting for thread: AIVoiceThread +osThreadJoin failed (-3), using state check... +[00:01:34:050][I]{AIVoiceInputThreadFunc():1027} AI voice input thread stopped +[Graphic Error] [PauseSlice: 236]No valid slice to pause +Waiting... 1/50 (state: 3, running: yes) +APP|uapi_lcd_backlight_off +Output RESET_LCD_GPIO 1 , VCI_LCD_GPIO 0 +Waiting... 2/50 (state: 3, running: yes) +[A][ALERT][core_adp_destroy:414] adp = 0x6D000001 +[A][ALERT][core_mod_free:316] mod_node->mid.u32 = 0x6D000001 +APP|SET DSP freq=3, div=6, codec freq=3, div=36 +APP|set hifi mode=1. +[A][ALERT][core_adp_destroy:414] adp = 0x6D000101 +[A][ALERT][core_mod_free:316] mod_node->mid.u32 = 0x6D000101 +[A][aw88082_i2c_deinit:373]aw88082 i2c deinit success +[00:01:34:376][I]{DeinitAIVoiceResources():811} AI voice input queue deleted +AI voice thread cleanup completed +Waiting... 3/50 (state: 0, running: no) +AI voice thread stopped successfully (state check) +AI voice stopped and resources cleaned up +APP|[AudioTest] Audio test stopped +AUDIO TEST STOP: Success +APP|app_main run start. +APP|sys_slp: 0x0 +[A][ALERT][sys_cmd_check_cmd_done:164] wait_time_us = 700 +[A][ALERT][drv_sys_pd:331] DSP0 power down +» AT^AUDIOTEST=7 0.5 +« APP|[AudioTest] Play volume set to 0.50 (50%) +AUDIO TEST SET VOLUME: Success (0.00, 0%) +APP|app_main run start. +APP|sys_slp: 0x0 +APP|app_main run start. +APP|sys_slp: 0x0 +APP|app_main run start. +APP|sys_slp: 0x0 diff --git a/mainwindow.cpp b/mainwindow.cpp index 89dd459..99f3305 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -8,311 +8,28 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi { ui->setupUi(this); - // 初始化串口对象 - serialport1 = new QSerialPort(this); - serialport2 = new QSerialPort(this); - serialport3 = new QSerialPort(this); - serialport4 = new QSerialPort(this); - - QSerialPort *ports[MAX_SERIAL_PORTS] = {serialport1, serialport2, serialport3, serialport4}; - - // 初始化统一配置结构 - for (int i = 0; i < MAX_SERIAL_PORTS; i++) { - // 创建串口上下文 - port_contexts[i] = new SerialPortContext(i + 1); - - // 创建定时器 - spp_timer_handles[i] = new QTimer(this); - - // 连接定时器信号(使用lambda捕获端口索引) - connect(spp_timer_handles[i], &QTimer::timeout, [this, i]() { - this->spp_timer_callback(i); - }); - - // 初始化上下文 - port_contexts[i]->init(ports[i], spp_timer_handles[i]); - - // 创建结果线程 - result_threads[i] = new Result_Thread(this, i + 1); - result_threads[i]->start(); - result_threads[i]->pause(); - } - - // 向后兼容:映射到数组 - result_thread1 = result_threads[0]; - result_thread2 = result_threads[1]; - result_thread3 = result_threads[2]; - result_thread4 = result_threads[3]; - - // 向后兼容:保留原有的定时器引用(映射到数组) - // 注意:spp_timer_handle1 将在后续代码中通过 port_contexts[0]->spp_timer_handle 访问 + // 创建测试端口控制器实例 + port_controller1 = new TestPortController(0, this); + port_controller2 = new TestPortController(1, this); + port_controller3 = new TestPortController(2, this); + port_controller4 = new TestPortController(3, this); + + // 连接信号槽 + connectPortControllerSignals(port_controller1, 0); + connectPortControllerSignals(port_controller2, 1); + connectPortControllerSignals(port_controller3, 2); + connectPortControllerSignals(port_controller4, 3); ui_setting_read(); } -// ui_show_result1已在后面实现为向后兼容函数 +// 旧的统一处理函数已移到TestPortController类中,以下函数保留用于向后兼容 -// 统一的readData函数 +// 向后兼容:readData(已废弃,数据读取现在由TestPortController内部处理) void MainWindow::readData(int port_index) { - if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { - qDebug() << tr("无效的端口索引:") << port_index; - return; - } - - SerialPortContext *ctx = port_contexts[port_index]; - if (ctx == nullptr || ctx->serialport == nullptr) { - qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; - return; - } - - const QByteArray data = ctx->serialport->readAll(); - // 调试输出 - if(ctx->uart_rx_flag) - qDebug() << tr("端口%1接收数据:").arg(port_index) << data; - - if (ctx->working_state == false) { - qDebug() << tr("端口%1写号结束,跳过读取串口").arg(port_index); - return; - } - - // 记录串口接收到的数据 - if (!data.isEmpty()) { - QString dataStr = QString::fromUtf8(data); - } - - // 将新数据添加到开机检测缓存中 - ctx->boot_detect_buffer.append(data); - - // 保持缓存大小合理,避免内存过度使用(保留最近8192字节) - if (ctx->boot_detect_buffer.length() > 8192) { - ctx->boot_detect_buffer = ctx->boot_detect_buffer.right(8192); - // 只在第一次超过限制时打印,避免重复打印 - static bool buffer_limit_warned[MAX_SERIAL_PORTS] = {false, false, false, false}; - if (!buffer_limit_warned[port_index]) { - qDebug() << tr("端口%1开机检测缓存过大,保留最近8192字节").arg(port_index); - buffer_limit_warned[port_index] = true; - } - } - - // 在缓存区中检测开机信号,处理分包情况 - if (ctx->boot_detect_buffer.indexOf(BOOT_UP_MSG) >= 0) { - UIPortWidgets widgets = getUIPortWidgets(port_index); - widgets.label_runtime_status->setText(tr("发现新设备")); - ctx->waiting_cmd = true; - ctx->cmd_index = 0; - QString avalible_mac = settings::getInstance().getAvalibleMac(); - widgets.ledit_spp_addr->setText(avalible_mac); - widgets.txtb_dispaly->clear(); - // 检测到开机信号后清理缓存,避免无限增长 - ctx->boot_detect_buffer.clear(); - qDebug() << tr("端口%1检测到开机信号(yaffs filesystem init start),清理缓存").arg(port_index); - } - - // 在缓存区中检测MAC地址信息,处理分包情况 - if (ctx->working_state && !ctx->waiting_cmd) { - // 使用正则表达式在缓存区中查找完整的MAC地址 - QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); - int macPos = macRegex.indexIn(ctx->boot_detect_buffer); - if (macPos >= 0) { - QString foundMac = macRegex.cap(1); // 提取MAC地址部分 (28:11:06:XX:XX:XX) - qDebug() << tr("端口%1在开机缓冲区中发现完整MAC地址:").arg(port_index) << foundMac; - - // 转换为无冒号格式 - QString macWithoutColon = foundMac.replace(":", "").toUpper(); - qDebug() << tr("端口%1转换后的MAC地址:").arg(port_index) << macWithoutColon; - - // 检查MAC地址是否已被使用 - bool mac_used = settings::getInstance().getMacUsed(macWithoutColon); - qDebug() << tr("端口%1 MAC地址是否已被使用:").arg(port_index) << mac_used; - - if (mac_used) { - ui_display(port_index, tr("手表地址") + macWithoutColon + tr("已占用\r\n"), LOG_DIRECT_OUT); - ui_show_result(port_index, tr("Mac地址已占用"), false); - } else { - ui_display(port_index, tr("手表当前地址") + macWithoutColon + tr(" 可用!\r\n"), LOG_DIRECT_IN); - qDebug() << tr("端口%1手表当前MAC地址可用:").arg(port_index) << macWithoutColon; - } - } - } - - // 在缓存区中检测命令时机信号,处理分包情况 - if (ctx->waiting_cmd && ctx->boot_detect_buffer.indexOf(TIME_FOR_CMD) >= 0) { - uart_send_data(port_index, ATCMD_ADD_VOTE); - // 检测到命令时机后也清理缓存 - ctx->boot_detect_buffer.clear(); - qDebug() << tr("端口%1检测到命令时机信号,清理缓存").arg(port_index); - } - - // 检测启动完成信号,需要同时检测到两个信号 - if (ctx->waiting_cmd && !ctx->startup_complete_detected && - ctx->boot_detect_buffer.indexOf(STARTUP_POST_INIT) >= 0 && - ctx->boot_detect_buffer.indexOf(STARTUP_POST_INIT_TASK) >= 0) { - ctx->startup_complete_detected = true; // 设置标志,防止重复触发 - qDebug() << tr("端口%1检测到启动完成信号,系统已完全启动").arg(port_index); - ui_display(port_index, tr("系统启动完成,可以执行GETIDS\r\n"), LOG_DIRECT_IN); - - // 清理缓存 - ctx->boot_detect_buffer.clear(); - qDebug() << tr("端口%1检测到启动完成信号,清理缓存").arg(port_index); - - // 如果当前正在等待GETIDS执行,且没有AT命令在执行,则触发GETIDS - if ((ctx->cmd_index == 3 || ctx->cmd_index == 4) && !ctx->uart_rx_flag) { - qDebug() << tr("端口%1启动完成且正在等待GETIDS,立即触发GETIDS执行").arg(port_index); - qDebug() << tr("端口%1当前cmd_index:").arg(port_index) << ctx->cmd_index; - - if (ctx->cmd_index == 3) { - ctx->cmd_index++; // 从3递增到4 - qDebug() << tr("端口%1 cmd_index从3递增到4").arg(port_index); - } - // 如果cmd_index已经是4,保持不变,重新执行case 4 - - // 清空之前的响应缓冲区,准备接收GETIDS响应 - ctx->uart_rx_buff_array.clear(); - qDebug() << tr("端口%1清空响应缓冲区,准备执行GETIDS").arg(port_index); - - // 重新执行switch逻辑,现在startup_complete_detected = true - switch(ctx->cmd_index) { - case 4: - qDebug() << tr("端口%1系统已完全启动,发送GETIDS指令").arg(port_index); - uart_send_data(port_index, ATCMD_GET_CPUID); - break; - default: - qDebug() << tr("端口%1启动完成回调中的cmd_index异常:").arg(port_index) << ctx->cmd_index; - break; - } - } - } - - if (ctx->uart_rx_flag) { - // 指令下达完毕,开始接收数据 - ctx->uart_rx_buff_array.append(data); - qDebug() << tr("端口%1 AT命令响应数据累积中,当前长度:").arg(port_index) << ctx->uart_rx_buff_array.length(); - qDebug() << tr("端口%1当前累积内容:").arg(port_index) << ctx->uart_rx_buff_array; - - // 检查各种可能的结束标志 - bool hasOK = ctx->uart_rx_buff_array.indexOf("OK~") >= 0; - bool hasPowerOff = ctx->uart_rx_buff_array.indexOf("power off device!") >= 0; - bool hasDSPPowerDown = ctx->uart_rx_buff_array.indexOf("DSP0 power down") >= 0; - - // 特殊处理:对于GETBTMAC命令,如果检测到完整的MAC地址响应,认为命令完成 - bool isGetMacComplete = false; - qDebug() << tr("端口%1当前命令G_cmd:").arg(port_index) << ctx->G_cmd; - qDebug() << tr("端口%1是否包含GETBTMAC:").arg(port_index) << ctx->G_cmd.contains("GETBTMAC"); - - if (ctx->G_cmd.contains("GETBTMAC")) { - qDebug() << tr("端口%1开始GETBTMAC特殊检测").arg(port_index); - // 检查是否包含完整的MAC地址格式和CyweeChipInfo - bool hasLocalAddr = ctx->uart_rx_buff_array.indexOf("get nv local_addr") >= 0; - bool hasBTMAC = ctx->uart_rx_buff_array.indexOf("BTMAC=") >= 0; - bool hasCyweeChipInfo = ctx->uart_rx_buff_array.indexOf("CyweeChipInfo=") >= 0; - - qDebug() << tr("端口%1检测结果 - hasLocalAddr:").arg(port_index) << hasLocalAddr - << tr("hasBTMAC:") << hasBTMAC << tr("hasCyweeChipInfo:") << hasCyweeChipInfo; - - if (hasLocalAddr && hasBTMAC && hasCyweeChipInfo) { - qDebug() << tr("端口%1基本条件满足,检查MAC地址格式").arg(port_index); - // 进一步检查是否包含完整的MAC地址格式 - QRegExp completeMacRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); - int macPos = completeMacRegex.indexIn(ctx->uart_rx_buff_array); - qDebug() << tr("端口%1 MAC地址正则匹配结果:").arg(port_index) << macPos; - - if (macPos >= 0) { - QString foundMac = completeMacRegex.cap(1); - qDebug() << tr("端口%1找到完整MAC地址:").arg(port_index) << foundMac; - isGetMacComplete = true; - qDebug() << tr("端口%1 GETBTMAC命令响应完整,包含完整MAC地址和CyweeChipInfo").arg(port_index); - } - } - } else { - qDebug() << tr("端口%1当前命令不是GETBTMAC,跳过GETBTMAC特殊检测").arg(port_index); - } - - qDebug() << tr("端口%1结束标志检查 - OK~:").arg(port_index) << hasOK - << tr("power off:") << hasPowerOff << tr("DSP0 power down:") << hasDSPPowerDown - << tr("GETMAC完整:") << isGetMacComplete; - - if (hasOK || hasPowerOff || hasDSPPowerDown || isGetMacComplete) { - qDebug() << tr("端口%1检测到结束标志,开始处理AT命令结果").arg(port_index); - - // 停止超时定时器 - if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { - ctx->spp_timer_handle->stop(); - qDebug() << tr("端口%1停止AT命令超时定时器").arg(port_index); - } - - ctx->uart_rx_flag = false; - uart_process(port_index); // 开始处理当前指令结果 - - if (ctx->cmd_index < 0) { - if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { - ctx->spp_timer_handle->stop(); - } - - if (ctx->uart_rx_buff_array.indexOf("power off device") >= 0) { - ui_display(port_index, tr("关机成功\r\n"), LOG_DIRECT_IN); - } - return; - } - - ctx->cmd_index++; // 开始执行下一指令 - qDebug() << tr("端口%1 next cmdindex").arg(port_index) << ctx->cmd_index; - - UIPortWidgets widgets = getUIPortWidgets(port_index); - switch(ctx->cmd_index) { - case 0: - { - // 空操作 - } - break; - case 1: - { - qDebug() << tr("端口%1执行case 1: 查询手表MAC地址").arg(port_index); - uart_send_data(port_index, ATCMD_GET_MAC); - } - break; - case 2: - { - QString set_mac_cmd = QString(ATCMD_SET_MAC).arg(widgets.ledit_spp_addr->text()); - uart_send_data(port_index, set_mac_cmd); - } - break; - case 3: - { - uart_send_data(port_index, ATCMD_GET_MAC); - } - break; - case 4: - { - // 只有在检测到启动完成信号后才发送GETIDS - if (ctx->startup_complete_detected) { - qDebug() << tr("端口%1系统已完全启动,发送GETIDS指令").arg(port_index); - uart_send_data(port_index, ATCMD_GET_CPUID); - } else { - qDebug() << tr("端口%1等待系统完全启动信号,暂不发送GETIDS").arg(port_index); - ui_display(port_index, tr("等待系统完全启动信号...\r\n"), LOG_DIRECT_OUT); - // 保持在case 4,等待启动完成信号 - ctx->cmd_index = 4; - return; - } - } - break; - case 5: - { - uart_send_data(port_index, ATCMD_POWEROFF); - } - break; - default: - { - ctx->cmd_index = -1; - if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { - ctx->spp_timer_handle->stop(); - } - } - break; - } - } - } + Q_UNUSED(port_index); + // 数据读取现在由TestPortController的onReadyRead槽处理 } // 向后兼容:readData1 @@ -339,32 +56,21 @@ MainWindow::~MainWindow() { ui_setting_save(); - // 停止所有线程和定时器 - for (int i = 0; i < MAX_SERIAL_PORTS; i++) { - if (spp_timer_handles[i] != nullptr) { - spp_timer_handles[i]->stop(); - } - if (result_threads[i] != nullptr) { - result_threads[i]->stop(); - result_threads[i]->wait(); - delete result_threads[i]; - } - if (port_contexts[i] != nullptr) { - delete port_contexts[i]; - } - } + // 删除端口控制器(会自动清理内部资源) + delete port_controller1; + delete port_controller2; + delete port_controller3; + delete port_controller4; delete ui; } -// 统一的poweroff_watch函数 +// 统一的poweroff_watch函数(使用TestPortController) void MainWindow::poweroff_watch(int port_index) { - if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { - qDebug() << tr("无效的端口索引:") << port_index; - return; + TestPortController* controller = getPortController(port_index); + if (controller) { + controller->poweroffWatch(); } - - uart_send_data(port_index, ATCMD_POWEROFF); } // 向后兼容:poweroff_watch1 @@ -389,7 +95,7 @@ MainWindow::UIPortWidgets MainWindow::getUIPortWidgets(int port_index) case 0: widgets.txtb_dispaly = ui->txtb_dispaly; widgets.label_runtime_status = ui->label_runtime_status1; - widgets.ledit_spp_addr = ui->ledit_spp_addr_1; + widgets.label_result_success = ui->label_result_success1; widgets.label_result_fail = ui->label_result_fail1; widgets.cbox_uart_com_select = ui->cbox_uart_com_select_1; @@ -398,7 +104,7 @@ MainWindow::UIPortWidgets MainWindow::getUIPortWidgets(int port_index) case 1: widgets.txtb_dispaly = ui->txtb_dispaly_2; widgets.label_runtime_status = ui->label_runtime_status2; - widgets.ledit_spp_addr = ui->ledit_spp_addr_2; + widgets.label_result_success = ui->label_result_success2; widgets.label_result_fail = ui->label_result_fail2; widgets.cbox_uart_com_select = ui->cbox_uart_com_select_2; @@ -407,7 +113,7 @@ MainWindow::UIPortWidgets MainWindow::getUIPortWidgets(int port_index) case 2: widgets.txtb_dispaly = ui->txtb_dispaly_3; widgets.label_runtime_status = ui->label_runtime_status3; - widgets.ledit_spp_addr = ui->ledit_spp_addr_3; + widgets.label_result_success = ui->label_result_success3; widgets.label_result_fail = ui->label_result_fail3; widgets.cbox_uart_com_select = ui->cbox_uart_com_select_3; @@ -416,7 +122,7 @@ MainWindow::UIPortWidgets MainWindow::getUIPortWidgets(int port_index) case 3: widgets.txtb_dispaly = ui->txtb_dispaly_4; widgets.label_runtime_status = ui->label_runtime_status4; - widgets.ledit_spp_addr = ui->ledit_spp_addr_4; + widgets.label_result_success = ui->label_result_success4; widgets.label_result_fail = ui->label_result_fail4; widgets.cbox_uart_com_select = ui->cbox_uart_com_select_4; @@ -425,7 +131,7 @@ MainWindow::UIPortWidgets MainWindow::getUIPortWidgets(int port_index) default: widgets.txtb_dispaly = ui->txtb_dispaly; widgets.label_runtime_status = ui->label_runtime_status1; - widgets.ledit_spp_addr = ui->ledit_spp_addr_1; + widgets.label_result_success = ui->label_result_success1; widgets.label_result_fail = ui->label_result_fail1; widgets.cbox_uart_com_select = ui->cbox_uart_com_select_1; @@ -435,57 +141,122 @@ MainWindow::UIPortWidgets MainWindow::getUIPortWidgets(int port_index) return widgets; } -// 统一的UI显示函数 -void MainWindow::ui_display(int port_index, QString str, bool inOrOut) +// 获取指定端口的控制器 +TestPortController* MainWindow::getPortController(int port_index) { - if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { - qDebug() << tr("无效的端口索引:") << port_index; - return; - } - - UIPortWidgets widgets = getUIPortWidgets(port_index); - if (widgets.txtb_dispaly == nullptr) { - qDebug() << tr("UI控件未找到,端口索引:") << port_index; - return; - } - - widgets.txtb_dispaly->moveCursor(QTextCursor::End); - if(inOrOut){ - widgets.txtb_dispaly->setTextColor(QColor(127, 255, 0)); - }else{ - widgets.txtb_dispaly->setTextColor(Qt::red); + switch(port_index) { + case 0: return port_controller1; + case 1: return port_controller2; + case 2: return port_controller3; + case 3: return port_controller4; + default: return port_controller1; } - widgets.txtb_dispaly->insertPlainText(str); - widgets.txtb_dispaly->moveCursor(QTextCursor::End); } -// 统一的结果显示函数 -void MainWindow::ui_show_result(int port_index, QString msg, bool success) +// 连接端口控制器的信号槽 +void MainWindow::connectPortControllerSignals(TestPortController* controller, int port_index) { - if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { - qDebug() << tr("无效的端口索引:") << port_index; - return; - } + if (!controller) return; - SerialPortContext *ctx = port_contexts[port_index]; UIPortWidgets widgets = getUIPortWidgets(port_index); - if (widgets.label_runtime_status == nullptr) { - qDebug() << tr("UI控件未找到,端口索引:") << port_index; - return; - } + // 连接显示消息信号 + connect(controller, &TestPortController::displayMessage, [widgets](QString str, bool inOrOut) { + if (widgets.txtb_dispaly) { + widgets.txtb_dispaly->moveCursor(QTextCursor::End); + if (inOrOut) { + widgets.txtb_dispaly->setTextColor(QColor(127, 255, 0)); + } else { + widgets.txtb_dispaly->setTextColor(Qt::red); + } + widgets.txtb_dispaly->insertPlainText(str); + widgets.txtb_dispaly->moveCursor(QTextCursor::End); + } + }); - widgets.label_runtime_status->setText(msg); - if (success) { - ctx->write_success_count++; - widgets.label_result_success->setText(tr("成功%1").arg(ctx->write_success_count)); - } else { - ctx->write_fail_count++; - widgets.label_result_fail->setText(tr("失败%1").arg(ctx->write_fail_count)); - poweroff_watch(port_index); + // 连接结果显示信号 + connect(controller, &TestPortController::showResult, [this, controller, widgets](QString msg, bool success) { + if (widgets.label_runtime_status) { + widgets.label_runtime_status->setText(msg); + } + if (success) { + if (widgets.label_result_success) { + widgets.label_result_success->setText(tr("成功%1").arg(controller->successCount())); + } + } else { + if (widgets.label_result_fail) { + widgets.label_result_fail->setText(tr("失败%1").arg(controller->failCount())); + } + controller->poweroffWatch(); + } + }); + + // 连接状态变化信号 + connect(controller, &TestPortController::statusChanged, [widgets](QString status) { + if (widgets.label_runtime_status) { + widgets.label_runtime_status->setText(status); + } + }); + + // 连接成功计数变化信号 + connect(controller, &TestPortController::successCountChanged, [widgets](int count) { + if (widgets.label_result_success) { + widgets.label_result_success->setText(tr("成功%1").arg(count)); + } + }); + + // 连接失败计数变化信号 + connect(controller, &TestPortController::failCountChanged, [widgets](int count) { + if (widgets.label_result_fail) { + widgets.label_result_fail->setText(tr("失败%1").arg(count)); + } + }); + + // 连接MAC地址变化信号(UI中暂无显示MAC地址的控件,保留信号连接以备将来使用) + connect(controller, &TestPortController::macAddressChanged, [](QString mac) { + Q_UNUSED(mac); + // MAC地址变化信号已连接,但UI中暂无显示控件 + }); + + // 连接按钮文本变化信号 + connect(controller, &TestPortController::buttonTextChanged, [widgets](QString text) { + if (widgets.pbtn_spp_reconnect) { + widgets.pbtn_spp_reconnect->setText(text); + } + }); + + // 连接清空显示信号 + connect(controller, &TestPortController::clearDisplay, [widgets]() { + if (widgets.txtb_dispaly) { + widgets.txtb_dispaly->clear(); + } + }); + + // 连接MAC状态更新信号(用于更新textBrowser_result) + connect(controller, &TestPortController::updateMacStatus, [this](QString status) { + if (ui->textBrowser_result) { + ui->textBrowser_result->setText(status); + } + }); +} + +// 统一的UI显示函数(保留用于向后兼容,实际由信号槽处理) +void MainWindow::ui_display(int port_index, QString str, bool inOrOut) +{ + TestPortController* controller = getPortController(port_index); + if (controller) { + // 通过公共方法触发信号(在connectPortControllerSignals中已连接) + controller->triggerDisplayMessage(str, inOrOut); } - if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { - ctx->spp_timer_handle->stop(); +} + +// 统一的结果显示函数(保留用于向后兼容,实际由信号槽处理) +void MainWindow::ui_show_result(int port_index, QString msg, bool success) +{ + TestPortController* controller = getPortController(port_index); + if (controller) { + // 通过公共方法触发信号(在connectPortControllerSignals中已连接) + controller->triggerShowResult(msg, success); } } @@ -544,295 +315,51 @@ void MainWindow::ui_setting_save() // 读取config配置 void MainWindow::ui_setting_read() { + // 先更新所有串口选择框(包含最新串口列表和None选项) uart_com_select(); + QSettings *msettings = new QSettings("Setting.ini", QSettings::IniFormat); - ui->cbox_uart_com_select_1->ChangeItem(msettings->value("Uart_setting/uart_com").toString()); + QString saved_com = msettings->value("Uart_setting/uart_com").toString(); + + // 如果保存的串口存在,则设置为当前选择;否则保持为None + if (!saved_com.isEmpty() && saved_com != tr("None") && saved_com != "None") { + int index = ui->cbox_uart_com_select_1->findText(saved_com); + if (index >= 0) { + ui->cbox_uart_com_select_1->setCurrentIndex(index); + } + } + ui->cbox_uart_baud_select->setCurrentIndex(msettings->value("Uart_setting/uart_baud").toInt()); settings::getInstance().load_settings(); ui->textBrowser_result->setText(settings::getInstance().getmacStatusFull()); - } /* --------------------------------uart操作--------------------------- */ -// 统一的uart_process函数 +// 统一的uart_process函数(已废弃,逻辑在TestPortController中) void MainWindow::uart_process(int port_index) { - if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { - qDebug() << tr("无效的端口索引:") << port_index; - return; - } - - SerialPortContext *ctx = port_contexts[port_index]; - if (ctx == nullptr) { - qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; - return; - } - - UIPortWidgets widgets = getUIPortWidgets(port_index); - - qDebug() << tr("端口%1 uart_process").arg(port_index) << ctx->cmd_index; - // 处理指令结果 - switch(ctx->cmd_index) { - case 0: - ui_display(port_index, tr("阻止休眠\r\n"), LOG_DIRECT_IN); - qDebug() << tr("端口%1阻止休眠").arg(port_index); - break; - case 1: - { - // 检查当前的号是否已经是写过的号,防止重复写号造成的浪费 - qDebug() << tr("端口%1执行case 1: 查询手表MAC地址").arg(port_index); - qDebug() << tr("端口%1 uart_rx_buff_array长度:").arg(port_index) << ctx->uart_rx_buff_array.length(); - qDebug() << tr("端口%1 uart_rx_buff_array内容:").arg(port_index) << ctx->uart_rx_buff_array; - - // 使用正则表达式查找MAC地址格式: BTMAC=28:11:06:XX:XX:XX,支持多包检测 - qDebug() << tr("端口%1开始在AT响应中查找MAC地址").arg(port_index); - qDebug() << tr("端口%1当前缓存内容:").arg(port_index) << ctx->uart_rx_buff_array; - qDebug() << tr("端口%1缓存长度:").arg(port_index) << ctx->uart_rx_buff_array.length(); - - QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); - int ret = macRegex.indexIn(ctx->uart_rx_buff_array); - qDebug() << tr("端口%1正则表达式查找结果:").arg(port_index) << ret; - - // 如果正则表达式没找到,尝试简单的BTMAC=查找来调试 - int simple_ret = ctx->uart_rx_buff_array.indexOf("BTMAC="); - qDebug() << tr("端口%1简单BTMAC=查找结果:").arg(port_index) << simple_ret; - - if (simple_ret >= 0) { - // 显示BTMAC=后面的内容,看看是否完整 - QString after_btmac = ctx->uart_rx_buff_array.mid(simple_ret); - qDebug() << tr("端口%1 BTMAC=后面的内容:").arg(port_index) << after_btmac; - - // 备用方法:如果正则表达式失败,尝试手动提取MAC地址 - if (ret < 0) { - qDebug() << tr("端口%1正则表达式失败,尝试备用提取方法").arg(port_index); - - // 查找BTMAC=后面是否有足够的字符来组成MAC地址 - QString remaining = ctx->uart_rx_buff_array.mid(simple_ret + 6); // 跳过"BTMAC=" - qDebug() << tr("端口%1 BTMAC=后的剩余内容:").arg(port_index) << remaining; - - // 尝试提取MAC地址,即使不完整也显示当前状态 - QRegExp partialMacRegex("([0-9A-Fa-f:]+)"); - if (partialMacRegex.indexIn(remaining) >= 0) { - QString partialMac = partialMacRegex.cap(1); - qDebug() << tr("端口%1部分MAC地址:").arg(port_index) << partialMac; - - // 检查是否是完整的MAC地址(应该有5个冒号) - int colonCount = partialMac.count(':'); - qDebug() << tr("端口%1冒号数量:").arg(port_index) << colonCount << tr("(完整MAC地址应该有5个冒号)"); - - if (colonCount == 5) { - qDebug() << tr("端口%1检测到完整MAC地址,使用备用方法处理").arg(port_index); - QString unit = partialMac.replace(":", "").toUpper(); - qDebug() << tr("端口%1备用方法提取的MAC地址:").arg(port_index) << unit; - - bool mac_used = settings::getInstance().getMacUsed(unit.toUpper()); - qDebug() << tr("端口%1 MAC地址是否已被使用:").arg(port_index) << mac_used; - - if (mac_used) { - ui_display(port_index, tr("手表地址") + unit + tr("已占用\r\n"), LOG_DIRECT_OUT); - ui_show_result(port_index, tr("Mac地址已占用"), false); - ctx->cmd_index = -1; - } else { - ui_display(port_index, tr("手表当前地址") + unit + tr(" 可用!\r\n"), LOG_DIRECT_IN); - } - - // 跳过后面的正常处理 - break; - } else { - qDebug() << tr("端口%1 MAC地址不完整,等待更多数据").arg(port_index); - } - } - } - } - - if (ret >= 0) { - QString mac_with_colon = macRegex.cap(1); // 提取MAC地址部分 (28:11:06:4D:29:EF) - qDebug() << tr("端口%1找到BTMAC=,位置:").arg(port_index) << ret; - qDebug() << tr("端口%1提取的MAC地址(带冒号):").arg(port_index) << mac_with_colon; - - QString unit = mac_with_colon.replace(":", "").toUpper(); // "28110604D29EF" - qDebug() << tr("端口%1处理后的MAC地址(无冒号):").arg(port_index) << unit; - - bool mac_used = settings::getInstance().getMacUsed(unit.toUpper()); - qDebug() << tr("端口%1 MAC地址是否已被使用:").arg(port_index) << mac_used; - - if (mac_used) { - ui_display(port_index, tr("手表地址") + unit + tr("已占用\r\n"), LOG_DIRECT_OUT); - ui_show_result(port_index, tr("Mac地址已占用"), false); - ctx->cmd_index = -1; - } else { - ui_display(port_index, tr("手表当前地址") + unit + tr(" 可用!\r\n"), LOG_DIRECT_IN); - } - } else { - qDebug() << tr("端口%1在uart_rx_buff_array中未找到BTMAC=").arg(port_index); - qDebug() << tr("端口%1完整缓存内容(十六进制):").arg(port_index) << ctx->uart_rx_buff_array.toHex(); - ui_display(port_index, tr("查询手表Mac失败!\r\n"), LOG_DIRECT_OUT); - ctx->cmd_index = -1; - ui_show_result(port_index, tr("查询手表Mac失败"), false); - } - } - break; - case 2: - { - QString new_mac = widgets.ledit_spp_addr->text(); - ui_display(port_index, tr("执行设置地址\r\n"), LOG_DIRECT_OUT); - qDebug() << tr("端口%1执行case 2: 设置MAC地址完成").arg(port_index); - qDebug() << tr("端口%1设置的MAC地址:").arg(port_index) << new_mac; - ui_display(port_index, tr("MAC地址设置完成,等待设备处理...\r\n"), LOG_DIRECT_IN); - } - break; - case 3: - { - // 验证设置的MAC地址是否成功 - QString unit = widgets.ledit_spp_addr->text(); - qDebug() << tr("端口%1执行case 3: 验证设置的MAC地址").arg(port_index); - qDebug() << tr("端口%1期望的MAC地址:").arg(port_index) << unit; - qDebug() << tr("端口%1响应数据长度:").arg(port_index) << ctx->uart_rx_buff_array.length(); - - if (ctx->uart_rx_buff_array.length() < 50) { - qDebug() << tr("端口%1响应数据较短,可能是超时或设备重启中").arg(port_index); - } - - // 使用正则表达式查找MAC地址格式: BTMAC=28:11:06:XX:XX:XX,支持多包检测 - QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); - int ret = macRegex.indexIn(ctx->uart_rx_buff_array); - if (ret >= 0) { - // 提取MAC地址部分 - QString mac_with_colon = macRegex.cap(1); // "28:11:06:4D:29:EF" - QString unit_watch = mac_with_colon.replace(":", "").toUpper(); // "28110604D29EF" - - qDebug() << tr("端口%1手表返回的MAC地址:").arg(port_index) << unit_watch; - qDebug() << tr("端口%1期望的MAC地址:").arg(port_index) << unit; - - if (unit_watch.toUpper() == unit.toUpper()) { - ui_display(port_index, tr("设置Mac") + unit_watch + tr("成功\r\n"), LOG_DIRECT_IN); - } else { - ui_display(port_index, tr("设置Mac") + unit_watch + tr("失败\r\n"), LOG_DIRECT_OUT); - ctx->cmd_index = -2; - ui_show_result(port_index, tr("Mac地址设置失败"), false); - } - } else { - ui_display(port_index, tr("设置Mac") + unit + tr("失败\r\n"), LOG_DIRECT_OUT); - ctx->cmd_index = -3; - ui_show_result(port_index, tr("查询手表Mac失败"), false); - } - } - break; - case 4: - { - qDebug() << tr("端口%1执行case 4: 获取CPU ID").arg(port_index); - qDebug() << tr("端口%1响应内容:").arg(port_index) << ctx->uart_rx_buff_array; - qDebug() << tr("端口%1响应长度:").arg(port_index) << ctx->uart_rx_buff_array.length(); - - // 使用分包检测方式查找CPU ID信息 - int ret = ctx->uart_rx_buff_array.indexOf("[soc id:]"); - qDebug() << tr("端口%1 [soc id:]查找结果:").arg(port_index) << ret; - - if (ret >= 0) { - // 查找[soc id:]后面的内容,直到遇到OK~或其他结束标志 - QString soc_section = ctx->uart_rx_buff_array.mid(ret); - qDebug() << tr("端口%1 SOC部分内容:").arg(port_index) << soc_section; - - // 检查是否包含完整的数据结束标志 - bool hasCompleteData = soc_section.contains("OK~") || soc_section.contains("\r\n\r\n"); - qDebug() << tr("端口%1是否包含完整数据标志:").arg(port_index) << hasCompleteData; - - // 提取所有的十六进制数据(0x开头的),支持分包和多行格式 - QRegExp hexRegex("0x[0-9A-Fa-f]{4}"); - QStringList hexValues; - int pos = 0; - - while ((pos = hexRegex.indexIn(soc_section, pos)) != -1) { - hexValues << hexRegex.cap(0); - pos += hexRegex.matchedLength(); - qDebug() << tr("端口%1找到十六进制值:").arg(port_index) << hexRegex.cap(0) << tr("位置:") << pos; - } - - qDebug() << tr("端口%1提取的十六进制值:").arg(port_index) << hexValues; - qDebug() << tr("端口%1十六进制值数量:").arg(port_index) << hexValues.size(); - - // 检查数据完整性:需要至少10个十六进制值且有结束标志 - if (hexValues.size() >= 10 && hasCompleteData) { - // 将所有十六进制值连接成CPU ID(去掉0x前缀) - QString cpu_id = ""; - for (const QString &hex : hexValues) { - cpu_id += hex.mid(2); // 去掉"0x"前缀 - } - - qDebug() << tr("端口%1组合的CPU ID:").arg(port_index) << cpu_id; - ui_display(port_index, "cpuid: " + cpu_id + "\r\n", LOG_DIRECT_IN); - - int db_ret = settings::getInstance().set_mac_used(widgets.ledit_spp_addr->text(), cpu_id, true); - qDebug() << tr("端口%1 set mac used").arg(port_index) << widgets.ledit_spp_addr->text() << cpu_id << tr("ret") << db_ret; - - if (db_ret == 1) { - ui->textBrowser_result->setText(settings::getInstance().getmacStatusFull()); - ui_display(port_index, tr("设置mac成功\r\n"), LOG_DIRECT_IN); - } else { - ui_show_result(port_index, tr("获取cpuid失败\r\n"), false); - } - } else { - qDebug() << tr("端口%1 CPU ID数据不完整 - 十六进制值:").arg(port_index) << hexValues.size() << tr("完整标志:") << hasCompleteData; - - if (!hasCompleteData) { - qDebug() << tr("端口%1等待完整的AT^GETIDS响应数据").arg(port_index); - ui_display(port_index, tr("等待CPU ID完整数据...\r\n"), LOG_DIRECT_OUT); - return; // 等待更多数据 - } else if (hexValues.size() < 10) { - qDebug() << tr("端口%1十六进制值数量不足,期望>=10,实际:").arg(port_index) << hexValues.size(); - ui_display(port_index, tr("CPU ID格式不正确\r\n"), LOG_DIRECT_OUT); - ctx->cmd_index = -4; - ui_show_result(port_index, tr("获取CPU ID失败"), false); - } - } - } else { - qDebug() << tr("端口%1未找到[soc id:]标志,可能数据分包传输中").arg(port_index); - ui_display(port_index, tr("等待CPU ID数据...\r\n"), LOG_DIRECT_OUT); - - // 不使用备用CPU ID,直接失败 - ctx->cmd_index = -4; - ui_show_result(port_index, tr("获取CPU ID失败"), false); - } - } - break; - case 5: - { - int ret = ctx->uart_rx_buff_array.indexOf("power off device"); - if (ret >= 0) { - ui_display(port_index, tr("关机成功\r\n"), LOG_DIRECT_IN); - } else { - ui_display(port_index, tr("关机失败\r\n"), LOG_DIRECT_OUT); - } - ui_show_result(port_index, tr("设置mac成功\r\n"), true); - } - break; - default: - { - ctx->cmd_index = -1; - } - break; - } + // 此函数已废弃,处理逻辑现在由TestPortController内部处理 + Q_UNUSED(port_index); } -// 向后兼容:uart_process1 +// 向后兼容:uart_process1-4(已废弃,逻辑在TestPortController中) void MainWindow::uart_process1() { - uart_process(0); + Q_UNUSED(0); } -// 向后兼容:uart_process2/3/4 void MainWindow::uart_process2() { - uart_process(1); + Q_UNUSED(1); } void MainWindow::uart_process3() { - uart_process(2); + Q_UNUSED(2); } void MainWindow::uart_process4() { - uart_process(3); + Q_UNUSED(3); } //void MainWindow::uart_open(QString com,QString com_baud) //{ @@ -842,48 +369,12 @@ void MainWindow::uart_process4() //{ //} -// 统一的uart_send_data函数 +// 统一的uart_send_data函数(已废弃,逻辑在TestPortController中) void MainWindow::uart_send_data(int port_index, QString cmd) { - if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { - qDebug() << tr("无效的端口索引:") << port_index; - return; - } - - SerialPortContext *ctx = port_contexts[port_index]; - if (ctx == nullptr || ctx->serialport == nullptr) { - qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; - return; - } - - qint64 ret = 0; - - // 发送AT指令之前清空缓存区,确保响应数据的准确性 - ctx->uart_rx_buff_array.clear(); - qDebug() << tr("端口%1发送AT指令前清空缓存区").arg(port_index); - - qDebug() << tr("端口%1 uart_send_data").arg(port_index) << cmd; - ret = ctx->serialport->write(cmd.toUtf8()); - ctx->m_bytesToWrite = ret; - qDebug() << tr("端口%1 uart_send_data").arg(port_index) << cmd << tr(" ret") << ctx->m_bytesToWrite; - - ctx->G_cmd = cmd; - if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { - ctx->spp_timer_handle->stop(); - } - - // 对于特定命令使用更长的超时时间 - if (cmd.contains("GETIDS")) { - ctx->spp_timer_handle->start(5000); // 5秒超时 - qDebug() << tr("端口%1 GETIDS命令使用5秒超时").arg(port_index); - } else if (cmd.contains("GETBTMAC")) { - ctx->spp_timer_handle->start(3000); // GETBTMAC命令3秒超时 - qDebug() << tr("端口%1 GETBTMAC命令使用3秒超时").arg(port_index); - } else { - ctx->spp_timer_handle->start(1500); // 其他命令1.5秒超时 - } - // 发送指令,在发送结束的handleBytesWritten中,设置接收状态, - // 接收函数 readData 中确认指令是否执行完毕,然后执行下一个指令。 + // 此函数已废弃,发送逻辑现在由TestPortController内部处理 + Q_UNUSED(port_index); + Q_UNUSED(cmd); } // 向后兼容:uart_send_data1 @@ -905,39 +396,11 @@ void MainWindow::uart_send_data4(QString cmd) uart_send_data(3, cmd); } -// 统一的spp_timer_callback函数 +// 统一的spp_timer_callback函数(已废弃,逻辑在TestPortController中) void MainWindow::spp_timer_callback(int port_index) { - if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { - qDebug() << tr("无效的端口索引:") << port_index; - return; - } - - SerialPortContext *ctx = port_contexts[port_index]; - if (ctx == nullptr) { - qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; - return; - } - - ctx->uart_rx_flag = false; - qDebug() << tr("端口%1 AT命令超时:").arg(port_index) << ctx->G_cmd; - - if (ctx->G_cmd == ATCMD_ADD_VOTE) { - uart_send_data(port_index, ATCMD_ADD_VOTE); - } else if (ctx->G_cmd.contains("GETIDS")) { - // GETIDS命令超时,跳过CPU ID获取,继续执行关机 - ui_display(port_index, tr("获取CPU ID超时,跳过此步骤\r\n"), LOG_DIRECT_OUT); - - // 直接跳到关机步骤 - ctx->cmd_index = 4; // 设置为4,这样下次会执行case 5(关机) - ctx->uart_rx_flag = false; - uart_process(port_index); // 直接处理,跳过CPU ID - } else { - ui_display(port_index, tr("AT命令超时: %1\r\n").arg(ctx->G_cmd), LOG_DIRECT_OUT); - if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) { - ctx->spp_timer_handle->stop(); - } - } + // 此函数已废弃,超时处理现在由TestPortController内部处理 + Q_UNUSED(port_index); } // 向后兼容:spp_timer_callback1 @@ -945,55 +408,79 @@ void MainWindow::spp_timer_callback1() { spp_timer_callback(0); } -// uart收到的数据进行回显到显示栏 +// uart收到的数据进行回显到显示栏(已废弃,现在由TestPortController处理) void MainWindow::uart_rx_dispaly1(int buf_len, u8Piont buf) { - // 使用端口0的上下文 - SerialPortContext *ctx = port_contexts[0]; - if (ctx) { - ctx->uart_rx_flag = true; - if (ctx->uart_rx_Ignoring_display) { - QString str((char *)buf); - if(str.contains("ADDR")){ -// ui->ledit_dongle_mac->setText(str.mid(str.indexOf("=",0)+1,12)); - } - return; - } + Q_UNUSED(buf_len); + Q_UNUSED(buf); + // 此函数已废弃,数据回显现在由TestPortController处理 + if (buf) { + free(buf); } - QString str; - QByteArray data((const char*)buf, buf_len); -// if (ui->ckbox_Hex_Display->isChecked()) { -// for (int i = 0; i < data.size(); i++) { -// str += QString("%1 ").arg((quint8)data.at(i), 2, 16, QChar('0')); -// } -// str=str.toUpper(); -// } else { -// for (int i = 0; i < data.size(); i++) { -// str += QString(data.at(i)); -// } -// } - ui_display1(str,true); - free(buf); } +// 统一的串口选择更新函数 - 更新所有4个串口选择框 void MainWindow::uart_com_select() { - ui->cbox_uart_com_select_1->clear(); + // 获取可用串口列表 QStringList strlist = uart_get_enable_comm_or_port(); + + // 排序串口列表(按COM编号) qSort(strlist.begin(), strlist.end(),[](const QString& s1, const QString& s2){ QString a1=s1;QString a2=s2; - return a1.replace("COM","").toInt() < a2.replace("COM","").toInt(); }); - ui->cbox_uart_com_select_1->addItems(strlist); + return a1.replace("COM","").toInt() < a2.replace("COM","").toInt(); + }); + + // 保存当前选中的串口(如果有) + QStringList currentSelections; + currentSelections << ui->cbox_uart_com_select_1->currentText(); + currentSelections << ui->cbox_uart_com_select_2->currentText(); + currentSelections << ui->cbox_uart_com_select_3->currentText(); + currentSelections << ui->cbox_uart_com_select_4->currentText(); + + // 更新所有4个串口选择框 + QComboBox *comboBoxes[] = { + ui->cbox_uart_com_select_1, + ui->cbox_uart_com_select_2, + ui->cbox_uart_com_select_3, + ui->cbox_uart_com_select_4 + }; + + for (int i = 0; i < MAX_SERIAL_PORTS; i++) { + comboBoxes[i]->clear(); + // 添加 "None" 作为第一个选项(默认值) + comboBoxes[i]->addItem(tr("None")); + // 添加可用串口列表 + comboBoxes[i]->addItems(strlist); + + // 尝试恢复之前的选择(如果仍然存在) + if (!currentSelections[i].isEmpty() && currentSelections[i] != tr("None")) { + int index = comboBoxes[i]->findText(currentSelections[i]); + if (index >= 0) { + comboBoxes[i]->setCurrentIndex(index); + } else { + // 如果之前的串口不存在了,设置为 "None" + comboBoxes[i]->setCurrentIndex(0); + } + } else { + // 如果没有之前的选择,设置为 "None" + comboBoxes[i]->setCurrentIndex(0); + } + } + + qDebug() << tr("已更新所有串口选择框,共找到") << strlist.size() << tr("个可用串口"); } void MainWindow::uart_com_switch(QString com) { + Q_UNUSED(com); QString str_uart_baud = ui->cbox_uart_baud_select->currentText(); - + Q_UNUSED(str_uart_baud); } void MainWindow::uart_baud_switch(QString baud) { - QString str_com = ui->cbox_uart_com_select_1->currentText(); - + Q_UNUSED(baud); + QString str_com = ui->cbox_uart_com_select_1->currentText(); + Q_UNUSED(str_com); } // nIndex为索引号 bValue选择返回值为key还是value,默认为value QString MainWindow::uart_get_comm_or_port(int nIndex, bool bValue) @@ -1056,7 +543,10 @@ QStringList MainWindow::uart_get_enable_comm_or_port() /* ------------------------------------------------------------------- */ void MainWindow::spp_connected_callback() { - ui_display1("com send cmd failed! ",false); + // 使用端口0的控制器 + if (port_controller1) { + port_controller1->triggerDisplayMessage("com send cmd failed! ", false); + } } // 向后兼容:spp_timer_callback2/3/4 void MainWindow::spp_timer_callback2() @@ -1074,7 +564,7 @@ void MainWindow::spp_timer_callback4() // spp_timer_callback1已在后面实现为向后兼容函数 -// 统一的spp_connect函数 +// 统一的spp_connect函数(使用TestPortController) void MainWindow::spp_connect(int port_index) { if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { @@ -1082,105 +572,30 @@ void MainWindow::spp_connect(int port_index) return; } - SerialPortContext *ctx = port_contexts[port_index]; - if (ctx == nullptr || ctx->serialport == nullptr) { - qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; + TestPortController* controller = getPortController(port_index); + if (!controller) { + qDebug() << tr("端口控制器未初始化,端口索引:") << port_index; return; } UIPortWidgets widgets = getUIPortWidgets(port_index); - if (ctx->working_state == false) { + if (!controller->isWorking()) { // 开始工作 QString baud_rate = ui->cbox_uart_baud_select->currentText(); QString com_name = widgets.cbox_uart_com_select->currentText(); - - qDebug() << tr("=== 开始连接串口%1 ===").arg(port_index + 1); - qDebug() << tr("串口名称:") << com_name; - qDebug() << tr("波特率:") << baud_rate; - - ctx->serialport->setPortName(com_name); - ctx->serialport->setBaudRate(baud_rate.toInt()); - // 设置串口参数以提高兼容性 - ctx->serialport->setDataBits(QSerialPort::Data8); - ctx->serialport->setParity(QSerialPort::NoParity); - ctx->serialport->setStopBits(QSerialPort::OneStop); - ctx->serialport->setFlowControl(QSerialPort::NoFlowControl); - - // 设置更大的读缓冲区,提高数据处理能力 - ctx->serialport->setReadBufferSize(32768); // 32KB缓冲区 - qDebug() << tr("端口%1串口配置 - 波特率:").arg(port_index) << ctx->serialport->baudRate(); - qDebug() << tr("端口%1串口配置 - 数据位:").arg(port_index) << ctx->serialport->dataBits(); - qDebug() << tr("端口%1串口配置 - 停止位:").arg(port_index) << ctx->serialport->stopBits(); - qDebug() << tr("端口%1串口配置 - 校验位:").arg(port_index) << ctx->serialport->parity(); - qDebug() << tr("端口%1串口配置 - 流控制:").arg(port_index) << ctx->serialport->flowControl(); - qDebug() << tr("端口%1串口读缓冲区大小:").arg(port_index) << ctx->serialport->readBufferSize(); - - widgets.txtb_dispaly->clear(); - if (ctx->serialport->isOpen()) { - qDebug() << tr("端口%1串口已经打开,重置命令索引").arg(port_index); - ctx->cmd_index = 0; - } else { - if (ctx->serialport->open(QIODevice::ReadWrite)) { - qDebug() << tr("端口%1串口打开成功,连接信号槽").arg(port_index); - - // 使用lambda捕获port_index来连接信号槽 - connect(ctx->serialport, &QSerialPort::readyRead, [this, port_index]() { - this->readData(port_index); - }); - connect(ctx->serialport, &QSerialPort::bytesWritten, [this, port_index](qint64 bytes) { - this->handleBytesWritten(port_index, bytes); - }); - - ctx->cmd_index = 0; - } else { - qDebug() << tr("端口%1串口打开失败:").arg(port_index) << ctx->serialport->errorString(); - QMessageBox::critical(this, tr("Error"), ctx->serialport->errorString()); - ui_display(port_index, tr("Open error\r\n"), false); - return; - } + // 检查是否选择了 "None" + if (com_name.isEmpty() || com_name == tr("None") || com_name == "None") { + qDebug() << tr("端口%1未选择串口(选择了None),跳过打开串口操作").arg(port_index + 1); + QMessageBox::information(this, tr("提示"), tr("端口%1未选择串口,请先选择串口").arg(port_index + 1)); + return; } - - // 开始工作 - qDebug() << tr("端口%1开始写地址工作模式").arg(port_index); - ctx->working_state = true; - ctx->write_fail_count = 0; - ctx->write_success_count = 0; - - // 初始化开机检测缓存 - ctx->boot_detect_buffer.clear(); - ctx->waiting_cmd = false; // 重置等待命令状态 - ctx->startup_complete_detected = false; // 重置启动完成检测标志 - qDebug() << tr("端口%1初始化开机检测缓存").arg(port_index); - widgets.label_result_fail->setText(tr("失败%1").arg(ctx->write_fail_count)); - widgets.label_result_success->setText(tr("成功%1").arg(ctx->write_success_count)); - widgets.pbtn_spp_reconnect->setText(tr("停止写地址")); - widgets.label_runtime_status->setText(tr("等待手表开机")); - - qDebug() << tr("端口%1工作状态设置: working_state = true").arg(port_index); - qDebug() << tr("端口%1等待检测手表开机信号:").arg(port_index) << BOOT_UP_MSG; - qDebug() << tr("端口%1等待检测命令时机信号:").arg(port_index) << TIME_FOR_CMD; - - qDebug() << settings::getInstance().getmacStatusFull(); + controller->connectPort(com_name, baud_rate.toInt()); } else { // 停止工作 - qDebug() << tr("端口%1停止写地址工作模式").arg(port_index); - widgets.pbtn_spp_reconnect->setText(tr("开始写地址")); - widgets.label_runtime_status->setText(tr("已停止写地址...")); - ctx->working_state = false; - - // 清空开机检测缓存 - ctx->boot_detect_buffer.clear(); - qDebug() << tr("端口%1清空开机检测缓存").arg(port_index); - - widgets.txtb_dispaly->clear(); - if (ctx->serialport->isOpen()) { - ctx->serialport->close(); - } - disconnect(ctx->serialport, &QSerialPort::readyRead, this, nullptr); - disconnect(ctx->serialport, &QSerialPort::bytesWritten, this, nullptr); + controller->disconnectPort(); } } @@ -1191,26 +606,12 @@ void MainWindow::spp_connect_1() } -// 统一的handleBytesWritten函数 +// 统一的handleBytesWritten函数(已废弃,逻辑在TestPortController中) void MainWindow::handleBytesWritten(int port_index, qint64 bytes) { - if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) { - qDebug() << tr("无效的端口索引:") << port_index; - return; - } - - SerialPortContext *ctx = port_contexts[port_index]; - if (ctx == nullptr) { - qDebug() << tr("串口上下文未初始化,端口索引:") << port_index; - return; - } - - qDebug() << tr("端口%1 handleBytesWritten m_bytesToWrite").arg(port_index) << ctx->m_bytesToWrite << tr("written") << bytes; - ctx->m_bytesToWrite -= bytes; - if (ctx->m_bytesToWrite == 0) { - ctx->uart_rx_flag = true; - ctx->uart_rx_buff_array.clear(); - } + // 此函数已废弃,发送完成处理现在由TestPortController内部处理 + Q_UNUSED(port_index); + Q_UNUSED(bytes); } // 向后兼容:handleBytesWritten1 @@ -1234,23 +635,11 @@ void MainWindow::spp_connect_4() void MainWindow::spp_connect_all() { - // 使用端口0的上下文 - SerialPortContext *ctx = port_contexts[0]; - if (ctx) { - ctx->uart_rx_Ignoring_display = true; - } -// dongle_is_connected = false; -// dongle_try_count = 0; -// spp_try_count = 0; -// uapi_uart_callback_register(uart_callback); -// at_handler->at_send_cmd_board(DONGLE_MODE_ADDR,NULL); - ui_display1("spp connectting...",false); - - // spp查询定时器周期为1500ms - if (spp_timer_handles[0]) { - spp_timer_handles[0]->start(1500); + // 使用端口0的控制器 + if (port_controller1) { + port_controller1->displayMessage("spp connectting...", false); } -// ui->pbtn_spp_connect->setEnabled(false); + // 注意:此函数的功能可能需要根据实际需求调整 } //void MainWindow::at_check_send_status(bool flag) diff --git a/mainwindow.h b/mainwindow.h index eedfe6c..8e2797e 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -19,7 +19,7 @@ #include "sqldbmanager.h" #include "settings.h" -#include "serial_port_context.h" +#include "test_port_controller.h" #include #include #include @@ -49,27 +49,16 @@ private: bool LOG_DIRECT_OUT=false; bool LOG_DIRECT_IN=true; /* ------------------------uart------------------------------- */ - // 统一配置:4个串口的上下文数组 - SerialPortContext *port_contexts[MAX_SERIAL_PORTS]; - QTimer *spp_timer_handles[MAX_SERIAL_PORTS]; - Result_Thread *result_threads[MAX_SERIAL_PORTS]; - - // 向后兼容:保留原有变量名(映射到port_contexts[0]) - // 这些变量将在实现中通过宏或内联函数映射到port_contexts[0] - QSerialPort *serialport1; - QSerialPort *serialport2; - QSerialPort *serialport3; - QSerialPort *serialport4; - Result_Thread *result_thread1; - Result_Thread *result_thread2; - Result_Thread *result_thread3; - Result_Thread *result_thread4; + // 测试端口控制器实例(不使用数组) + TestPortController *port_controller1; + TestPortController *port_controller2; + TestPortController *port_controller3; + TestPortController *port_controller4; // UI控件映射辅助结构 struct UIPortWidgets { QTextBrowser *txtb_dispaly; QLabel *label_runtime_status; - QLineEdit *ledit_spp_addr; QLabel *label_result_success; QLabel *label_result_fail; QComboBox *cbox_uart_com_select; // 串口选择框 @@ -79,22 +68,28 @@ private: // 获取指定端口的UI控件 UIPortWidgets getUIPortWidgets(int port_index); - // 统一处理函数(支持多端口) + // 获取指定端口的控制器 + TestPortController* getPortController(int port_index); + + // 连接端口控制器的信号槽 + void connectPortControllerSignals(TestPortController* controller, int port_index); + + // 向后兼容函数(保留原有接口) + void ui_display1(QString str,bool inOrOut); + void ui_show_result1(QString msg,bool success); + void poweroff_watch1(); + void uart_send_data1(QString cmd); + + // 废弃的统一处理函数(保留用于向后兼容,实际逻辑在TestPortController中) void readData(int port_index); void uart_process(int port_index); void uart_send_data(int port_index, QString cmd); void handleBytesWritten(int port_index, qint64 bytes); void spp_timer_callback(int port_index); void spp_connect(int port_index); + void poweroff_watch(int port_index); void ui_display(int port_index, QString str, bool inOrOut); void ui_show_result(int port_index, QString msg, bool success); - void poweroff_watch(int port_index); - - // 向后兼容:保留原有函数名(调用统一函数,port_index=0) - void ui_display1(QString str,bool inOrOut); - void ui_show_result1(QString msg,bool success); - void poweroff_watch1(); - void uart_send_data1(QString cmd); /*----------写地址任务相关变量---end------------*/ diff --git a/mainwindow.ui b/mainwindow.ui index 3d8081f..b51b7a9 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -1,1011 +1,1092 @@ - - - MainWindow - - - - 0 - 0 - 1398 - 758 - - - - - 黑体 - 50 - false - - - - BTMacWriteTool V1.3 - - - - :/icon/windows.ico:/icon/windows.ico - - - 1.000000000000000 - - - Qt::LeftToRight - - - - - - 1060 - 20 - 306 - 701 - - - - - Arial - 14 - - - - - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - ArrowCursor - - - false - - - 500000 - - - 11 - - - true - - - - 4800 - - - - - 9600 - - - - - 14400 - - - - - 19200 - - - - - 38400 - - - - - 57600 - - - - - 115200 - - - - - 128000 - - - - - 230400 - - - - - 256000 - - - - - 460800 - - - - - 500000 - - - - - 512000 - - - - - 600000 - - - - - 750000 - - - - - 921600 - - - - - 1000000 - - - - - 1500000 - - - - - 2000000 - - - - - - - - true - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - 全部开始测试 - - - false - - - - - - - - Arial - 14 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Arial','Arial','黑体'; font-size:14pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">已测试xxx设备</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">xxx成功,xxx失败。</p></body></html> - - - - - - - - Arial - 14 - - - - 打开日志路径 - - - - - - - - - 10 - 20 - 1032 - 701 - - - - - Arial - 14 - - - - Qt::Horizontal - - - - - Arial - 14 - - - - - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - - COM1 - - - - - - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - - - - MAC地址 - - - - - - - true - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - 开始测试 - - - false - - - - - - - - Arial - 14 - - - - true - - - QTextBrowser{background-color:rgb(26, 26, 26); - color:rgb(127, 255, 0)} - - - 1 - - - Qt::ScrollBarAlwaysOn - - - Qt::TextBrowserInteraction - - - - - - - - - false - - - color:rgb(0, 170, 0); -font: 75 18pt "Agra"; - - - 0 - - - 成功0 - - - - - - - false - - - color:rgb(170, 0, 0); -font: 75 18pt "Agra"; - - - 0 - - - 失败0 - - - - - - - - - 已停止测试... - - - - - - - - - Arial - 14 - - - - - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - - COM1 - - - - - - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - - - - MAC地址 - - - - - - - true - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - 开始测试 - - - false - - - - - - - - Arial - 14 - - - - true - - - QTextBrowser{background-color:rgb(26, 26, 26); - color:rgb(127, 255, 0)} - - - Qt::ScrollBarAlwaysOn - - - Qt::TextBrowserInteraction - - - - - - - - - false - - - color:rgb(0, 170, 0); -font: 75 18pt "Agra"; - - - 0 - - - 成功0 - - - - - - - false - - - color:rgb(170, 0, 0); -font: 75 18pt "Agra"; - - - 0 - - - 失败0 - - - - - - - - - 已停止测试... - - - - - - - - - Arial - 14 - - - - - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - - COM1 - - - - - - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - - - - MAC地址 - - - - - - - true - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - 开始测试 - - - false - - - - - - - - Arial - 14 - - - - true - - - QTextBrowser{background-color:rgb(26, 26, 26); - color:rgb(127, 255, 0)} - - - Qt::ScrollBarAlwaysOn - - - Qt::TextBrowserInteraction - - - - - - - - - false - - - color:rgb(0, 170, 0); -font: 75 18pt "Agra"; - - - 0 - - - 成功0 - - - - - - - false - - - color:rgb(170, 0, 0); -font: 75 18pt "Agra"; - - - 0 - - - 失败0 - - - - - - - - - 已停止测试... - - - - - - - - - Arial - 14 - - - - - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - - COM1 - - - - - - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - - - - MAC地址 - - - - - - - true - - - - 0 - 0 - - - - - Arial - 14 - 50 - false - - - - 开始测试 - - - false - - - - - - - - Arial - 14 - - - - true - - - QTextBrowser{background-color:rgb(26, 26, 26); - color:rgb(127, 255, 0)} - - - Qt::ScrollBarAlwaysOn - - - Qt::TextBrowserInteraction - - - - - - - - - false - - - color:rgb(0, 170, 0); -font: 75 18pt "Agra"; - - - 0 - - - 成功0 - - - - - - - false - - - color:rgb(170, 0, 0); -font: 75 18pt "Agra"; - - - 0 - - - 失败0 - - - - - - - - - 已停止测试... - - - - - - - splitter - verticalLayoutWidget_2 - - - - true - - - true - - - - - - MyComboBox - QComboBox -
custom.h
- - mouse_clicked(bool) - -
-
- - - - pbtn_spp_reconnect_2 - clicked() - MainWindow - spp_connect_2() - - - 386 - 126 - - - 676 - 346 - - - - - pbtn_spp_reconnect_3 - clicked() - MainWindow - spp_connect_3() - - - 645 - 126 - - - 676 - 346 - - - - - pbtn_spp_reconnect_4 - clicked() - MainWindow - spp_connect_4() - - - 905 - 126 - - - 676 - 346 - - - - - pbtn_spp_connect_all - clicked() - MainWindow - spp_connect_all() - - - 1192 - 79 - - - 676 - 346 - - - - - pushButton_openlogfolder - clicked() - MainWindow - openLogfolder() - - - 1192 - 608 - - - 676 - 346 - - - - - pbtn_spp_reconnect_1 - clicked() - MainWindow - spp_connect_1() - - - 126 - 126 - - - 676 - 346 - - - - - - ui_open_mac_config() - uart_process1() - readData1() - readData2() - readData3() - readData4() - uart_rx_dispaly1(int,uint8_t*) - spp_connect_1() - spp_connect_2() - spp_connect_3() - spp_connect_4() - spp_timer_callback1() - spp_connect_all() - uart_process2() - uart_process3() - uart_process4() - openLogfolder() - spp_timer_callback2() - spp_timer_callback3() - spp_timer_callback4() - -
+ + + MainWindow + + + + 0 + 0 + 1398 + 758 + + + + + 黑体 + 50 + false + + + + BTMacWriteTool V1.3 + + + + :/icon/windows.ico:/icon/windows.ico + + + 1.000000000000000 + + + Qt::LeftToRight + + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Qt::Horizontal + + + + Arial + 14 + + + + + + Arial + 14 + + + + + + + + + DUT + + + + + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + + COM1 + + + + + + + + + + + + RGB + + + + + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + + COM1 + + + + + + + + + + true + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + 开始测试 + + + false + + + + + + + + Arial + 14 + + + + true + + + QTextBrowser{background-color:rgb(26, 26, 26); + color:rgb(127, 255, 0)} + + + 1 + + + Qt::ScrollBarAlwaysOn + + + Qt::TextBrowserInteraction + + + + + + + + + false + + + color:rgb(0, 170, 0); +font: 75 18pt "Agra"; + + + 0 + + + 成功0 + + + + + + + false + + + color:rgb(170, 0, 0); +font: 75 18pt "Agra"; + + + 0 + + + 失败0 + + + + + + + + + 已停止测试... + + + + + + + + + Arial + 14 + + + + + + + + + DUT + + + + + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + + COM1 + + + + + + + + + + + + RGB + + + + + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + + COM1 + + + + + + + + + + true + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + 开始测试 + + + false + + + + + + + + Arial + 14 + + + + true + + + QTextBrowser{background-color:rgb(26, 26, 26); + color:rgb(127, 255, 0)} + + + Qt::ScrollBarAlwaysOn + + + Qt::TextBrowserInteraction + + + + + + + + + false + + + color:rgb(0, 170, 0); +font: 75 18pt "Agra"; + + + 0 + + + 成功0 + + + + + + + false + + + color:rgb(170, 0, 0); +font: 75 18pt "Agra"; + + + 0 + + + 失败0 + + + + + + + + + 已停止测试... + + + + + + + + + Arial + 14 + + + + + + + + + DUT + + + + + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + + COM1 + + + + + + + + + + + + RGB + + + + + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + + COM1 + + + + + + + + + + true + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + 开始测试 + + + false + + + + + + + + Arial + 14 + + + + true + + + QTextBrowser{background-color:rgb(26, 26, 26); + color:rgb(127, 255, 0)} + + + Qt::ScrollBarAlwaysOn + + + Qt::TextBrowserInteraction + + + + + + + + + false + + + color:rgb(0, 170, 0); +font: 75 18pt "Agra"; + + + 0 + + + 成功0 + + + + + + + false + + + color:rgb(170, 0, 0); +font: 75 18pt "Agra"; + + + 0 + + + 失败0 + + + + + + + + + 已停止测试... + + + + + + + + + Arial + 14 + + + + + + + + + DUT + + + + + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + + COM1 + + + + + + + + + + + + RGB + + + + + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + + COM1 + + + + + + + + + + true + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + 开始测试 + + + false + + + + + + + + Arial + 14 + + + + true + + + QTextBrowser{background-color:rgb(26, 26, 26); + color:rgb(127, 255, 0)} + + + Qt::ScrollBarAlwaysOn + + + Qt::TextBrowserInteraction + + + + + + + + + false + + + color:rgb(0, 170, 0); +font: 75 18pt "Agra"; + + + 0 + + + 成功0 + + + + + + + false + + + color:rgb(170, 0, 0); +font: 75 18pt "Agra"; + + + 0 + + + 失败0 + + + + + + + + + 已停止测试... + + + + + + + + + + + + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + ArrowCursor + + + false + + + 500000 + + + 11 + + + true + + + + 4800 + + + + + 9600 + + + + + 14400 + + + + + 19200 + + + + + 38400 + + + + + 57600 + + + + + 115200 + + + + + 128000 + + + + + 230400 + + + + + 256000 + + + + + 460800 + + + + + 500000 + + + + + 512000 + + + + + 600000 + + + + + 750000 + + + + + 921600 + + + + + 1000000 + + + + + 1500000 + + + + + 2000000 + + + + + + + + true + + + + 0 + 0 + + + + + Arial + 14 + 50 + false + + + + 全部开始测试 + + + false + + + + + + + + Arial + 14 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial','Arial','黑体'; font-size:14pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">已测试xxx设备</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">xxx成功,xxx失败。</p></body></html> + + + + + + + + Arial + 14 + + + + 打开日志路径 + + + + + + + + + + + true + + + true + + + + + + MyComboBox + QComboBox +
custom.h
+ + mouse_clicked(bool) + +
+
+ + + + pbtn_spp_reconnect_2 + clicked() + MainWindow + spp_connect_2() + + + 386 + 126 + + + 676 + 346 + + + + + pbtn_spp_reconnect_3 + clicked() + MainWindow + spp_connect_3() + + + 645 + 126 + + + 676 + 346 + + + + + pbtn_spp_reconnect_4 + clicked() + MainWindow + spp_connect_4() + + + 905 + 126 + + + 676 + 346 + + + + + pbtn_spp_connect_all + clicked() + MainWindow + spp_connect_all() + + + 1192 + 79 + + + 676 + 346 + + + + + pushButton_openlogfolder + clicked() + MainWindow + openLogfolder() + + + 1192 + 608 + + + 676 + 346 + + + + + pbtn_spp_reconnect_1 + clicked() + MainWindow + spp_connect_1() + + + 126 + 126 + + + 676 + 346 + + + + + + ui_open_mac_config() + uart_process1() + readData1() + readData2() + readData3() + readData4() + uart_rx_dispaly1(int,uint8_t*) + spp_connect_1() + spp_connect_2() + spp_connect_3() + spp_connect_4() + spp_timer_callback1() + spp_connect_all() + uart_process2() + uart_process3() + uart_process4() + openLogfolder() + spp_timer_callback2() + spp_timer_callback3() + spp_timer_callback4() + +
diff --git a/test_port_controller.cpp b/test_port_controller.cpp new file mode 100644 index 0000000..b792cc5 --- /dev/null +++ b/test_port_controller.cpp @@ -0,0 +1,540 @@ +#include "test_port_controller.h" +#include "settings.h" +#include +#include +#include + +TestPortController::TestPortController(int port_index, QObject *parent) + : QObject(parent) + , m_port_index(port_index) + , m_dut_serial(new QSerialPort(this)) + , m_rgb_serial(new QSerialPort(this)) + , m_spp_timer_handle(new QTimer(this)) + , m_result_thread(new Result_Thread(nullptr, port_index + 1)) + , m_bytesToWrite(0) + , m_cmd_index(0) + , m_working_state(false) + , m_waiting_cmd(false) + , m_startup_complete_detected(false) + , m_uart_rx_flag(false) + , m_uart_rx_Ignoring_display(false) + , m_write_success_count(0) + , m_write_fail_count(0) +{ + // 连接定时器信号 + connect(m_spp_timer_handle, &QTimer::timeout, this, &TestPortController::onTimerTimeout); + + // 连接串口信号 + connect(m_dut_serial, &QSerialPort::readyRead, this, &TestPortController::onReadyRead); + connect(m_dut_serial, &QSerialPort::bytesWritten, this, &TestPortController::onBytesWritten); + + // 启动结果线程 + m_result_thread->start(); + m_result_thread->pause(); +} + +TestPortController::~TestPortController() +{ + disconnectPort(); + if (m_result_thread) { + m_result_thread->stop(); + m_result_thread->wait(); + delete m_result_thread; + } +} + +void TestPortController::connectPort(const QString& com_name, int baud_rate) +{ + if (m_working_state) { + // 停止工作 + disconnectPort(); + return; + } + + // 检查是否选择了 "None" + if (com_name.isEmpty() || com_name == tr("None") || com_name == "None") { + qDebug() << tr("端口%1未选择串口(选择了None),跳过打开串口操作").arg(m_port_index + 1); + emit displayMessage(tr("未选择串口,请先选择串口\r\n"), false); + return; + } + + qDebug() << tr("=== 开始连接串口%1 ===").arg(m_port_index + 1); + qDebug() << tr("串口名称:") << com_name; + qDebug() << tr("波特率:") << baud_rate; + + m_dut_serial->setPortName(com_name); + m_dut_serial->setBaudRate(baud_rate); + m_dut_serial->setDataBits(QSerialPort::Data8); + m_dut_serial->setParity(QSerialPort::NoParity); + m_dut_serial->setStopBits(QSerialPort::OneStop); + m_dut_serial->setFlowControl(QSerialPort::NoFlowControl); + m_dut_serial->setReadBufferSize(32768); // 32KB缓冲区 + + emit clearDisplay(); + + if (m_dut_serial->isOpen()) { + qDebug() << tr("端口%1串口已经打开,重置命令索引").arg(m_port_index); + m_cmd_index = 0; + } else { + if (m_dut_serial->open(QIODevice::ReadWrite)) { + qDebug() << tr("端口%1串口打开成功").arg(m_port_index); + m_cmd_index = 0; + } else { + qDebug() << tr("端口%1串口打开失败:").arg(m_port_index) << m_dut_serial->errorString(); + emit displayMessage(tr("Open error\r\n"), false); + return; + } + } + + // 开始工作 + qDebug() << tr("端口%1开始写地址工作模式").arg(m_port_index); + m_working_state = true; + m_write_fail_count = 0; + m_write_success_count = 0; + + // 初始化开机检测缓存 + m_boot_detect_buffer.clear(); + m_waiting_cmd = false; + m_startup_complete_detected = false; + + emit successCountChanged(m_write_success_count); + emit failCountChanged(m_write_fail_count); + emit buttonTextChanged(tr("停止写地址")); + emit statusChanged(tr("等待手表开机")); +} + +void TestPortController::disconnectPort() +{ + qDebug() << tr("端口%1停止写地址工作模式").arg(m_port_index); + emit buttonTextChanged(tr("开始写地址")); + emit statusChanged(tr("已停止写地址...")); + m_working_state = false; + + // 清空开机检测缓存 + m_boot_detect_buffer.clear(); + + emit clearDisplay(); + + if (m_dut_serial->isOpen()) { + m_dut_serial->close(); + } +} + +void TestPortController::poweroffWatch() +{ + uart_send_data(ATCMD_POWEROFF); +} + +void TestPortController::setMacAddress(const QString& mac) +{ + m_mac_address = mac; + emit macAddressChanged(mac); +} + +void TestPortController::triggerDisplayMessage(QString str, bool inOrOut) +{ + emit displayMessage(str, inOrOut); +} + +void TestPortController::triggerShowResult(QString msg, bool success) +{ + emit showResult(msg, success); +} + +void TestPortController::onReadyRead() +{ + readData(); +} + +void TestPortController::onBytesWritten(qint64 bytes) +{ + handleBytesWritten(bytes); +} + +void TestPortController::onTimerTimeout() +{ + spp_timer_callback(); +} + +void TestPortController::readData() +{ + const QByteArray data = m_dut_serial->readAll(); + + if (m_uart_rx_flag) { + qDebug() << tr("端口%1接收数据:").arg(m_port_index) << data; + } + + if (!m_working_state) { + qDebug() << tr("端口%1写号结束,跳过读取串口").arg(m_port_index); + return; + } + + // 将新数据添加到开机检测缓存中 + m_boot_detect_buffer.append(data); + + // 保持缓存大小合理 + if (m_boot_detect_buffer.length() > 8192) { + m_boot_detect_buffer = m_boot_detect_buffer.right(8192); + static bool buffer_limit_warned[4] = {false, false, false, false}; + if (!buffer_limit_warned[m_port_index]) { + qDebug() << tr("端口%1开机检测缓存过大,保留最近8192字节").arg(m_port_index); + buffer_limit_warned[m_port_index] = true; + } + } + + // 检测开机信号 + if (m_boot_detect_buffer.indexOf(BOOT_UP_MSG) >= 0) { + emit statusChanged(tr("发现新设备")); + m_waiting_cmd = true; + m_cmd_index = 0; + QString avalible_mac = settings::getInstance().getAvalibleMac(); + setMacAddress(avalible_mac); + emit clearDisplay(); + m_boot_detect_buffer.clear(); + qDebug() << tr("端口%1检测到开机信号,清理缓存").arg(m_port_index); + } + + // 检测MAC地址信息 + if (m_working_state && !m_waiting_cmd) { + QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); + int macPos = macRegex.indexIn(m_boot_detect_buffer); + if (macPos >= 0) { + QString foundMac = macRegex.cap(1); + QString macWithoutColon = foundMac.replace(":", "").toUpper(); + + bool mac_used = settings::getInstance().getMacUsed(macWithoutColon); + + if (mac_used) { + emit displayMessage(tr("手表地址") + macWithoutColon + tr("已占用\r\n"), false); + emit showResult(tr("Mac地址已占用"), false); + } else { + emit displayMessage(tr("手表当前地址") + macWithoutColon + tr(" 可用!\r\n"), true); + } + } + } + + // 检测命令时机信号 + if (m_waiting_cmd && m_boot_detect_buffer.indexOf(TIME_FOR_CMD) >= 0) { + uart_send_data(ATCMD_ADD_VOTE); + m_boot_detect_buffer.clear(); + qDebug() << tr("端口%1检测到命令时机信号,清理缓存").arg(m_port_index); + } + + // 检测启动完成信号 + if (m_waiting_cmd && !m_startup_complete_detected && + m_boot_detect_buffer.indexOf(STARTUP_POST_INIT) >= 0 && + m_boot_detect_buffer.indexOf(STARTUP_POST_INIT_TASK) >= 0) { + m_startup_complete_detected = true; + qDebug() << tr("端口%1检测到启动完成信号").arg(m_port_index); + emit displayMessage(tr("系统启动完成,可以执行GETIDS\r\n"), true); + m_boot_detect_buffer.clear(); + + if ((m_cmd_index == 3 || m_cmd_index == 4) && !m_uart_rx_flag) { + if (m_cmd_index == 3) { + m_cmd_index++; + } + m_uart_rx_buff_array.clear(); + if (m_cmd_index == 4) { + uart_send_data(ATCMD_GET_CPUID); + } + } + } + + if (m_uart_rx_flag) { + m_uart_rx_buff_array.append(data); + + // 检查结束标志 + bool hasOK = m_uart_rx_buff_array.indexOf("OK~") >= 0; + bool hasPowerOff = m_uart_rx_buff_array.indexOf("power off device!") >= 0; + bool hasDSPPowerDown = m_uart_rx_buff_array.indexOf("DSP0 power down") >= 0; + + bool isGetMacComplete = false; + if (m_G_cmd.contains("GETBTMAC")) { + bool hasLocalAddr = m_uart_rx_buff_array.indexOf("get nv local_addr") >= 0; + bool hasBTMAC = m_uart_rx_buff_array.indexOf("BTMAC=") >= 0; + bool hasCyweeChipInfo = m_uart_rx_buff_array.indexOf("CyweeChipInfo=") >= 0; + + if (hasLocalAddr && hasBTMAC && hasCyweeChipInfo) { + QRegExp completeMacRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); + if (completeMacRegex.indexIn(m_uart_rx_buff_array) >= 0) { + isGetMacComplete = true; + } + } + } + + if (hasOK || hasPowerOff || hasDSPPowerDown || isGetMacComplete) { + if (m_spp_timer_handle && m_spp_timer_handle->isActive()) { + m_spp_timer_handle->stop(); + } + + m_uart_rx_flag = false; + uart_process(); + + if (m_cmd_index < 0) { + if (m_spp_timer_handle && m_spp_timer_handle->isActive()) { + m_spp_timer_handle->stop(); + } + + if (m_uart_rx_buff_array.indexOf("power off device") >= 0) { + emit displayMessage(tr("关机成功\r\n"), true); + } + return; + } + + m_cmd_index++; + + switch(m_cmd_index) { + case 0: + break; + case 1: + uart_send_data(ATCMD_GET_MAC); + break; + case 2: + { + QString set_mac_cmd = QString(ATCMD_SET_MAC).arg(m_mac_address); + uart_send_data(set_mac_cmd); + } + break; + case 3: + uart_send_data(ATCMD_GET_MAC); + break; + case 4: + { + if (m_startup_complete_detected) { + uart_send_data(ATCMD_GET_CPUID); + } else { + emit displayMessage(tr("等待系统完全启动信号...\r\n"), false); + m_cmd_index = 4; + return; + } + } + break; + case 5: + uart_send_data(ATCMD_POWEROFF); + break; + default: + m_cmd_index = -1; + if (m_spp_timer_handle && m_spp_timer_handle->isActive()) { + m_spp_timer_handle->stop(); + } + break; + } + } + } +} + +void TestPortController::uart_process() +{ + qDebug() << tr("端口%1 uart_process").arg(m_port_index) << m_cmd_index; + + switch(m_cmd_index) { + case 0: + emit displayMessage(tr("阻止休眠\r\n"), true); + break; + case 1: + { + QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); + int ret = macRegex.indexIn(m_uart_rx_buff_array); + + if (ret >= 0) { + QString mac_with_colon = macRegex.cap(1); + QString unit = mac_with_colon.replace(":", "").toUpper(); + + bool mac_used = settings::getInstance().getMacUsed(unit.toUpper()); + + if (mac_used) { + emit displayMessage(tr("手表地址") + unit + tr("已占用\r\n"), false); + m_write_fail_count++; + emit failCountChanged(m_write_fail_count); + emit showResult(tr("Mac地址已占用"), false); + m_cmd_index = -1; + } else { + emit displayMessage(tr("手表当前地址") + unit + tr(" 可用!\r\n"), true); + } + } else { + emit displayMessage(tr("查询手表Mac失败!\r\n"), false); + m_cmd_index = -1; + m_write_fail_count++; + emit failCountChanged(m_write_fail_count); + emit showResult(tr("查询手表Mac失败"), false); + } + } + break; + case 2: + emit displayMessage(tr("执行设置地址\r\n"), false); + emit displayMessage(tr("MAC地址设置完成,等待设备处理...\r\n"), true); + break; + case 3: + { + QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})"); + int ret = macRegex.indexIn(m_uart_rx_buff_array); + if (ret >= 0) { + QString mac_with_colon = macRegex.cap(1); + QString unit_watch = mac_with_colon.replace(":", "").toUpper(); + + if (unit_watch.toUpper() == m_mac_address.toUpper()) { + emit displayMessage(tr("设置Mac") + unit_watch + tr("成功\r\n"), true); + } else { + emit displayMessage(tr("设置Mac") + unit_watch + tr("失败\r\n"), false); + m_cmd_index = -2; + m_write_fail_count++; + emit failCountChanged(m_write_fail_count); + emit showResult(tr("Mac地址设置失败"), false); + } + } else { + emit displayMessage(tr("设置Mac") + m_mac_address + tr("失败\r\n"), false); + m_cmd_index = -3; + m_write_fail_count++; + emit failCountChanged(m_write_fail_count); + emit showResult(tr("查询手表Mac失败"), false); + } + } + break; + case 4: + { + int ret = m_uart_rx_buff_array.indexOf("[soc id:]"); + if (ret >= 0) { + QString soc_section = m_uart_rx_buff_array.mid(ret); + bool hasCompleteData = soc_section.contains("OK~") || soc_section.contains("\r\n\r\n"); + + QRegExp hexRegex("0x[0-9A-Fa-f]{4}"); + QStringList hexValues; + int pos = 0; + + while ((pos = hexRegex.indexIn(soc_section, pos)) != -1) { + hexValues << hexRegex.cap(0); + pos += hexRegex.matchedLength(); + } + + if (hexValues.size() >= 10 && hasCompleteData) { + QString cpu_id = ""; + for (const QString &hex : hexValues) { + cpu_id += hex.mid(2); + } + + emit displayMessage("cpuid: " + cpu_id + "\r\n", true); + + int db_ret = settings::getInstance().set_mac_used(m_mac_address, cpu_id, true); + + if (db_ret == 1) { + emit displayMessage(tr("设置mac成功\r\n"), true); + // 更新MAC状态显示 + emit updateMacStatus(settings::getInstance().getmacStatusFull()); + } else { + m_write_fail_count++; + emit failCountChanged(m_write_fail_count); + emit showResult(tr("获取cpuid失败\r\n"), false); + } + } else { + if (!hasCompleteData) { + emit displayMessage(tr("等待CPU ID完整数据...\r\n"), false); + return; + } else if (hexValues.size() < 10) { + emit displayMessage(tr("CPU ID格式不正确\r\n"), false); + m_cmd_index = -4; + m_write_fail_count++; + emit failCountChanged(m_write_fail_count); + emit showResult(tr("获取CPU ID失败"), false); + } + } + } else { + emit displayMessage(tr("等待CPU ID数据...\r\n"), false); + m_cmd_index = -4; + m_write_fail_count++; + emit failCountChanged(m_write_fail_count); + emit showResult(tr("获取CPU ID失败"), false); + } + } + break; + case 5: + { + int ret = m_uart_rx_buff_array.indexOf("power off device"); + if (ret >= 0) { + emit displayMessage(tr("关机成功\r\n"), true); + } else { + emit displayMessage(tr("关机失败\r\n"), false); + } + m_write_success_count++; + emit successCountChanged(m_write_success_count); + emit showResult(tr("设置mac成功\r\n"), true); + } + break; + default: + m_cmd_index = -1; + break; + } +} + +void TestPortController::uart_send_data(const QString& cmd) +{ + m_uart_rx_buff_array.clear(); + qDebug() << tr("端口%1 uart_send_data").arg(m_port_index) << cmd; + + qint64 ret = m_dut_serial->write(cmd.toUtf8()); + m_bytesToWrite = ret; + + m_G_cmd = cmd; + if (m_spp_timer_handle && m_spp_timer_handle->isActive()) { + m_spp_timer_handle->stop(); + } + + if (cmd.contains("GETIDS")) { + m_spp_timer_handle->start(5000); + } else if (cmd.contains("GETBTMAC")) { + m_spp_timer_handle->start(3000); + } else { + m_spp_timer_handle->start(1500); + } +} + +void TestPortController::handleBytesWritten(qint64 bytes) +{ + m_bytesToWrite -= bytes; + if (m_bytesToWrite == 0) { + m_uart_rx_flag = true; + m_uart_rx_buff_array.clear(); + } +} + +void TestPortController::spp_timer_callback() +{ + m_uart_rx_flag = false; + qDebug() << tr("端口%1 AT命令超时:").arg(m_port_index) << m_G_cmd; + + if (m_G_cmd == ATCMD_ADD_VOTE) { + uart_send_data(ATCMD_ADD_VOTE); + } else if (m_G_cmd.contains("GETIDS")) { + emit displayMessage(tr("获取CPU ID超时,跳过此步骤\r\n"), false); + m_cmd_index = 4; + m_uart_rx_flag = false; + uart_process(); + } else { + emit displayMessage(tr("AT命令超时: %1\r\n").arg(m_G_cmd), false); + if (m_spp_timer_handle && m_spp_timer_handle->isActive()) { + m_spp_timer_handle->stop(); + } + } +} + +void TestPortController::resetState() +{ + m_bytesToWrite = 0; + m_cmd_index = 0; + m_G_cmd.clear(); + m_working_state = false; + m_waiting_cmd = false; + m_startup_complete_detected = false; + m_uart_rx_flag = false; + m_uart_rx_Ignoring_display = false; + m_uart_rx_buff_array.clear(); + m_boot_detect_buffer.clear(); + m_write_success_count = 0; + m_write_fail_count = 0; +} + +void TestPortController::clearBuffers() +{ + m_uart_rx_buff_array.clear(); + m_boot_detect_buffer.clear(); +} + diff --git a/test_port_controller.h b/test_port_controller.h new file mode 100644 index 0000000..b25c36b --- /dev/null +++ b/test_port_controller.h @@ -0,0 +1,113 @@ +#ifndef TEST_PORT_CONTROLLER_H +#define TEST_PORT_CONTROLLER_H + +#include +#include +#include +#include +#include +#include "result_thread.h" +#include "settings.h" + +// 前向声明 +class QSerialPort; +class QTimer; +class Result_Thread; + +// 测试端口控制器类 - 封装每个测试端口的所有变量和函数 +class TestPortController : public QObject +{ + Q_OBJECT + +public: + explicit TestPortController(int port_index, QObject *parent = nullptr); + ~TestPortController(); + + // 端口索引 (0-3) + int portIndex() const { return m_port_index; } + + // 串口对象访问 + QSerialPort* dutSerial() const { return m_dut_serial; } + QSerialPort* rgbSerial() const { return m_rgb_serial; } + + // 状态访问 + bool isWorking() const { return m_working_state; } + int successCount() const { return m_write_success_count; } + int failCount() const { return m_write_fail_count; } + + // 公共接口函数 + void connectPort(const QString& com_name, int baud_rate); + void disconnectPort(); + void poweroffWatch(); + void setMacAddress(const QString& mac); + + // 用于向后兼容的公共方法(触发信号) + void triggerDisplayMessage(QString str, bool inOrOut); + void triggerShowResult(QString msg, bool success); + +signals: + // UI更新信号 + void displayMessage(QString str, bool inOrOut); // 显示消息 (inOrOut: true=输入/绿色, false=输出/红色) + void showResult(QString msg, bool success); // 显示结果 + void statusChanged(QString status); // 状态文本变化 + void successCountChanged(int count); // 成功计数变化 + void failCountChanged(int count); // 失败计数变化 + void macAddressChanged(QString mac); // MAC地址变化 + void buttonTextChanged(QString text); // 按钮文本变化 + void clearDisplay(); // 清空显示 + void updateMacStatus(QString status); // 更新MAC状态显示(用于textBrowser_result) + +private slots: + void onReadyRead(); + void onBytesWritten(qint64 bytes); + void onTimerTimeout(); + +private: + // 端口索引 (0-3) + int m_port_index; + + // 串口对象 + QSerialPort *m_dut_serial; + QSerialPort *m_rgb_serial; + + // 定时器 + QTimer *m_spp_timer_handle; + + // 结果线程 + Result_Thread *m_result_thread; + + // 指令相关 + qint64 m_bytesToWrite; // 指令长度 + int m_cmd_index; // 指令顺序: 0=AT投票, 1=GET_MAC, 2=SET_MAC, 3=GET_MAC验证, 4=GET_CPUID, 5=POWEROFF + QString m_G_cmd; // 当前执行的AT命令 + + // 状态标志 + bool m_working_state; // true=写号执行中, false=写号结束 + bool m_waiting_cmd; // 等待命令时机 + bool m_startup_complete_detected; // 启动完成信号已检测标志 + bool m_uart_rx_flag; // 是否有uart通路数据上报 + bool m_uart_rx_Ignoring_display; // 是否忽略uart数据,不回显 + + // 数据缓冲区 + QByteArray m_uart_rx_buff_array; // AT命令响应缓冲区 + QByteArray m_boot_detect_buffer; // 开机检测数据缓存,处理分包情况 + + // 统计 + int m_write_success_count; // 成功计数 + int m_write_fail_count; // 失败计数 + + // MAC地址 + QString m_mac_address; // 当前MAC地址 + + // 内部处理函数 + void readData(); + void uart_process(); + void uart_send_data(const QString& cmd); + void handleBytesWritten(qint64 bytes); + void spp_timer_callback(); + void resetState(); + void clearBuffers(); +}; + +#endif // TEST_PORT_CONTROLLER_H +