diff --git a/backend/config.ini b/backend/config.ini index 149d17f0..f84a9c3f 100644 --- a/backend/config.ini +++ b/backend/config.ini @@ -60,7 +60,7 @@ pressure_port = COM5 pressure_baudrate = 115200 [REMOTE] -enable = False +enable = True port = COM6 baudrate = 115200 timeout = 0.1 diff --git a/backend/database.py b/backend/database.py index 30b5cecf..48ee85f9 100644 --- a/backend/database.py +++ b/backend/database.py @@ -830,7 +830,7 @@ class DatabaseManager: cursor.execute(''' SELECT * FROM detection_data WHERE session_id = ? - ORDER BY timestamp + ORDER BY timestamp desc ''', (session_id,)) data_rows = cursor.fetchall() @@ -849,7 +849,7 @@ class DatabaseManager: cursor.execute(''' SELECT * FROM detection_video WHERE session_id = ? - ORDER BY timestamp + ORDER BY timestamp desc ''', (session_id,)) video_rows = cursor.fetchall() diff --git a/backend/devices/device_coordinator.py b/backend/devices/device_coordinator.py index 6f66d0c6..7c569fb4 100644 --- a/backend/devices/device_coordinator.py +++ b/backend/devices/device_coordinator.py @@ -291,9 +291,11 @@ class DeviceCoordinator: from .remote_control_manager import RemoteControlManager remote = RemoteControlManager(self.socketio, self.config_manager) self.devices['remote'] = remote - if remote.initialize(): - return True - return False + if not remote.initialize(): + return False + if hasattr(remote, 'start_streaming'): + return bool(remote.start_streaming()) + return True except Exception as e: self.logger.error(f"初始化遥控器失败: {e}") return False @@ -743,6 +745,12 @@ class DeviceCoordinator: except ImportError: from femtobolt_manager import FemtoBoltManager new_device = FemtoBoltManager(self.socketio, self.config_manager) + elif device_name == 'remote': + try: + from .remote_control_manager import RemoteControlManager + except ImportError: + from remote_control_manager import RemoteControlManager + new_device = RemoteControlManager(self.socketio, self.config_manager) else: raise ValueError(f"未知的设备类型: {device_name}") @@ -777,6 +785,17 @@ class DeviceCoordinator: init_time = (time.time() - init_start) * 1000 self.logger.info(f"{device_name} 设备初始化成功 (耗时: {init_time:.1f}ms)") + if device_name == 'remote' and hasattr(new_device, 'start_streaming'): + self.logger.info(f"正在启动 {device_name} 设备推流...") + try: + if not new_device.start_streaming(): + self.logger.error(f"启动 {device_name} 设备推流失败") + return False + was_streaming = True + except Exception as e: + self.logger.error(f"启动 {device_name} 推流异常: {e}") + return False + # 设备初始化成功后,确保状态广播正确 # 此时设备应该已经通过initialize()方法中的set_connected(True)触发了状态变化通知 # 但为了确保状态一致性,我们再次确认状态 diff --git a/backend/devices/remote_control_manager.py b/backend/devices/remote_control_manager.py index 68fb6538..cf0ff7cb 100644 --- a/backend/devices/remote_control_manager.py +++ b/backend/devices/remote_control_manager.py @@ -66,7 +66,7 @@ class RemoteControlManager(BaseDevice): def initialize(self) -> bool: try: self.logger.info(f"初始化遥控器串口: {self.port}, {self.baudrate}bps, 8N1") - self.set_connected(True) + self.set_connected(False) self._device_info['initialized_at'] = time.time() return True except Exception as e: @@ -88,6 +88,9 @@ class RemoteControlManager(BaseDevice): stopbits=self.stopbits, timeout=self.timeout, ) + self.set_connected(True) + self.update_heartbeat() + self.is_streaming = True self._running = True self._thread = threading.Thread(target=self._worker_loop, daemon=True) self._thread.start() @@ -110,6 +113,9 @@ class RemoteControlManager(BaseDevice): self._thread.join(timeout=2.0) if self._ser and self._ser.is_open: self._ser.close() + self._ser = None + self.set_connected(False) + self.is_streaming = False self.logger.info("遥控器串口监听已停止") return True except Exception as e: @@ -248,6 +254,7 @@ class RemoteControlManager(BaseDevice): time.sleep(0.05) continue chunk = self._ser.read(64) + self.update_heartbeat() if chunk: try: hexstr = ' '.join(f'{b:02X}' for b in chunk) @@ -262,5 +269,14 @@ class RemoteControlManager(BaseDevice): self.logger.debug("遥控器串口暂无数据") except Exception as e: self.logger.error(f"遥控器串口读取异常: {e}") + try: + if self._ser and self._ser.is_open: + self._ser.close() + except Exception: + pass + self._ser = None + self.set_connected(False) + self.is_streaming = False + self._running = False time.sleep(0.1) self.logger.info("遥控器串口线程结束") diff --git a/backend/devices/utils/config_manager.py b/backend/devices/utils/config_manager.py index 298bec7e..0feddb58 100644 --- a/backend/devices/utils/config_manager.py +++ b/backend/devices/utils/config_manager.py @@ -434,6 +434,8 @@ class ConfigManager: self.set_config_value('DEVICES', 'imu_use_mock', str(config_data['use_mock'])) if 'mac_address' in config_data: self.set_config_value('DEVICES', 'imu_mac_address', config_data['mac_address']) + if 'ble_name' in config_data: + self.set_config_value('DEVICES', 'imu_ble_name', config_data['ble_name']) results['imu'] = { 'success': True, diff --git a/frontend/src/renderer/src/views/Detection.vue b/frontend/src/renderer/src/views/Detection.vue index d2d58a3a..5e7ccc51 100644 --- a/frontend/src/renderer/src/views/Detection.vue +++ b/frontend/src/renderer/src/views/Detection.vue @@ -3,6 +3,7 @@
+
+
@@ -192,93 +193,74 @@
-
-
-
-
-
- 左前足 - - {{ footPressure.left_front }}% - -
-
- 左后足 - - {{ footPressure.left_rear }}% - -
- +
+
+
+
+ 左前足 + + {{ footPressure.left_front }}% +
-
-
-
-
左足
-
右足
+
+ 左后足 + + {{ footPressure.left_rear }}% +
-
- - -
- -
连接已断开!
-
-
-
- -
-
-
-
-
-
- 右前足 - - {{ footPressure.right_front }}% - -
-
- 右后足 - - {{ footPressure.right_rear }}% - -
- +
+ 左足总压力 + + {{ footPressure.left_total}}% +
-
-
- 左足总压力 - - {{ footPressure.left_total}}% - +
+
+
左足
+
右足
-
- 右足总压力 - - {{ footPressure.right_total}}% - +
+ + +
+ +
连接已断开!
+
+
+
+
+
+
+
+
+
+ 右前足 + + {{ footPressure.right_front }}% + +
+
+ 右后足 + + {{ footPressure.right_rear }}% + +
+
+ 右足总压力 + + {{ footPressure.right_total}}% + +
-
-
@@ -448,9 +430,9 @@
- -
+ +
@@ -462,7 +444,7 @@
+ class="userinfo-edit-img" style="cursor: pointer;" @click="handleEditUserInfo">
@@ -479,116 +461,61 @@
-
- -
-
出生日期
+
+
+
出生日期
{{ formatDate(patientInfo.birth_date) }}
-
-
身高
+
+
身高
{{ patientInfo.height ==''||patientInfo.height ==null ?'—':patientInfo.height}}cm
-
-
体重
+
+
体重
{{ patientInfo.weight ==''||patientInfo.weight ==null ?'—':patientInfo.weight}}kg
-
-
鞋码
+
+
鞋码
{{ patientInfo.shoe_size ==''||patientInfo.shoe_size ==null ?'—':patientInfo.shoe_size}}码
-
-
电话
+
+
电话
{{ patientInfo.phone ==''||patientInfo.phone ==null ?'—':patientInfo.phone}}
-
-
民族
+
+
民族
{{ patientInfo.nationality ==''||patientInfo.nationality ==null ?'—':patientInfo.nationality}}
-
-
身份证号
+
+
身份证号
{{ patientInfo.idcode ==''||patientInfo.idcode ==null ?'—':patientInfo.idcode}}
-
-
职业
+
+
职业
{{ patientInfo.occupation ==''||patientInfo.occupation ==null ?'—':patientInfo.occupation}}
-
-
- -
-
出生日期
-
- - {{ formatDate(patientInfo.birth_date) }} - -
-
-
-
身高
-
- {{ patientInfo.height ==''||patientInfo.height ==null ?'—':patientInfo.height}}cm -
-
-
-
体重
-
- {{ patientInfo.weight ==''||patientInfo.weight ==null ?'—':patientInfo.weight}}kg -
-
-
-
鞋码
-
- {{ patientInfo.shoe_size ==''||patientInfo.shoe_size ==null ?'—':patientInfo.shoe_size}}码
-
-
-
电话
-
- {{ patientInfo.phone ==''||patientInfo.phone ==null ?'—':patientInfo.phone}} -
-
-
-
民族
-
- {{ patientInfo.nationality ==''||patientInfo.nationality ==null ?'—':patientInfo.nationality}}
-
-
-
身份证号
-
- {{ patientInfo.idcode ==''||patientInfo.idcode ==null ?'—':patientInfo.idcode}} -
-
-
-
职业
-
- {{ patientInfo.occupation ==''||patientInfo.occupation ==null ?'—':patientInfo.occupation}}
-
-
-
居住地
+
+
居住地
{{ patientInfo.residence ==''||patientInfo.residence ==null ?'—':patientInfo.residence}}
-
-
邮箱
+
+
邮箱
{{ patientInfo.email ==''||patientInfo.email ==null ?'—':patientInfo.email}}
@@ -596,8 +523,7 @@
-
- +
@@ -612,14 +538,14 @@
-
+
camera1 + style="width: 100%; height: 100%;" />
连接已断开!
@@ -631,7 +557,7 @@
camera2 + style="width: 100%; height: 100%;" />
连接已断开!
@@ -640,7 +566,7 @@
- +
@@ -787,7 +713,6 @@
本次检测未截图或录像操作,不予存档记录!
本次检测未截图操作,存档记录不可生成报告!
-
取消
确定
@@ -2709,23 +2634,9 @@ const isPhotoAlbum = ref(false) function closePhotoAlbum(){ isPhotoAlbum.value = false } -function closecreatbox(e,info){ - if(e === '编辑'){ - patientInfo.value.age = info.age - patientInfo.value.birth_date = info.birth_date - patientInfo.value.email = info.email - patientInfo.value.gender = info.gender - patientInfo.value.height = info.height - patientInfo.value.id = info.id - patientInfo.value.idcode = info.idcode - patientInfo.value.name = info.name - patientInfo.value.nationality = info.nationality - patientInfo.value.occupation = info.occupation - patientInfo.value.phone = info.phone - patientInfo.value.residence = info.residence - patientInfo.value.shoe_size = info.shoe_size - patientInfo.value.weight = info.weight - // loadPatientInfo() +function closecreatbox(e){ + if(e === true){ + loadPatientInfo() } isCloseCreat.value = false } @@ -2767,7 +2678,7 @@ function viewClick(e){ .displaycontainer { width: 100%; - height: 46px; + height: 62px; display: flex; align-items: center; justify-content: space-between; @@ -2944,8 +2855,10 @@ function viewClick(e){ text-align: left; } .body-footbottom-box{ - height: calc(100% - 50px); - padding-bottom: 15px; + display: flex; + align-items: center; + justify-content: center; + height: calc(100% - 70px); } .body-footbottom-left{ width: 28%; @@ -2958,8 +2871,8 @@ function viewClick(e){ .body-footbottom-leftbox{ min-width: 215px; width: 80%; - min-height: 57px; - height: 57px; + min-height: 60px; + height: 20%; background: inherit; background-color: rgba(255, 255, 255, 0.1); border-radius: 4px; @@ -2969,8 +2882,8 @@ function viewClick(e){ padding: 0px 20px; } .body-footbottom-center{ - width: 37%; - height: calc(100% - 0px); + width: 40%; + height: calc(100%); } .body-footbottom-topbox{ display: flex; @@ -3005,7 +2918,7 @@ function viewClick(e){ display: flex; justify-content: center; flex-wrap: wrap; - align-content:space-around; + align-content:space-between ; } .body-userinfo-box{ @@ -3013,18 +2926,18 @@ function viewClick(e){ z-index: 10; width: 100%; height: 346px; + /* background: linear-gradient(135deg, rgba(42, 54, 73, 1) 0%, rgba(42, 54, 73, 1) 0%, rgba(34, 43, 56, 1) 100%, rgba(34, 43, 56, 1) 100%); */ background: linear-gradient(135deg, #1a1e2a 0%, #222b38 100%); border: 1px solid #242E3D; border-radius: 4px; } .body-userinfo-expandbox{ - height: 680px !important; + height: 638px ; } .body-userinfo-box1{ - position: relative; - z-index: 10; width: 100%; - height: 524px ; + height: 534px ; + /* background: linear-gradient(135deg, rgba(42, 54, 73, 1) 0%, rgba(42, 54, 73, 1) 0%, rgba(34, 43, 56, 1) 100%, rgba(34, 43, 56, 1) 100%); */ background: linear-gradient(135deg, #1a1e2a 0%, #222b38 100%); border: 1px solid #242E3D; border-radius: 4px; @@ -3050,7 +2963,7 @@ function viewClick(e){ } .body-video-box1{ width: 100%; - height: calc(100% - 534px - 4px) ; + height: calc(100% - 534px - 14px) ; background: linear-gradient(135deg, #1a1e2a 0%, #222b38 100%); border: 1px solid #242E3D; border-radius: 4px; @@ -3187,10 +3100,10 @@ function viewClick(e){ } .userinfo-disyplaypadding1{ width: calc(64%); - padding-bottom: 20px; + padding-bottom: 15px; } .padding10{ - padding-bottom: 10px; + padding-bottom: 5px; } .userinfo-disyplaypadding2{ width: calc(36%); @@ -3425,25 +3338,6 @@ function viewClick(e){ background:#14aaff; border:1px solid #14aaff; } -.tipclosebutton{ - width: 80px; - height: 40px; - background-color: #597194; - border-radius: 4px; - color: rgba(255, 255, 255, 0.6); - font-weight: 400; - font-style: normal; - font-size: 16px; - display: flex; - align-items: center; - justify-content: center; - margin-right: 20px; - cursor: pointer; -} -.tipclosebutton:hover{ - background-color: #14aaff; - color: #fff; -} .pop-up-tip-text{ width:100%; font-weight: 400;