优化版本提交
This commit is contained in:
parent
7053427249
commit
50a0fe8641
@ -29,7 +29,7 @@ depth_range_max = 1500
|
|||||||
|
|
||||||
[DEVICES]
|
[DEVICES]
|
||||||
imu_device_type = real
|
imu_device_type = real
|
||||||
imu_port = COM6
|
imu_port = COM3
|
||||||
imu_baudrate = 9600
|
imu_baudrate = 9600
|
||||||
pressure_device_type = real
|
pressure_device_type = real
|
||||||
pressure_use_mock = False
|
pressure_use_mock = False
|
||||||
|
@ -252,7 +252,7 @@ class DeviceManager:
|
|||||||
# logger.info('准备启动FemtoBolt设备...')
|
# logger.info('准备启动FemtoBolt设备...')
|
||||||
|
|
||||||
# 启动FemtoBolt设备
|
# 启动FemtoBolt设备
|
||||||
logger.info(f'尝试启动FemtoBolt设备...,参数详情是{self.femtobolt_config}')
|
# logger.info(f'尝试启动FemtoBolt设备...,参数详情是{self.femtobolt_config}')
|
||||||
self.femtobolt_camera = pykinect.start_device(config=self.femtobolt_config)
|
self.femtobolt_camera = pykinect.start_device(config=self.femtobolt_config)
|
||||||
if self.femtobolt_camera:
|
if self.femtobolt_camera:
|
||||||
self.device_status['femtobolt'] = True
|
self.device_status['femtobolt'] = True
|
||||||
|
@ -370,7 +370,7 @@ class CameraManager(BaseDevice):
|
|||||||
'device_id': self.device_id
|
'device_id': self.device_id
|
||||||
}
|
}
|
||||||
|
|
||||||
self._socketio.emit('camera_frame', data, namespace='/camera')
|
self._socketio.emit('camera_frame', data, namespace='/devices')
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"发送帧数据失败: {e}")
|
self.logger.error(f"发送帧数据失败: {e}")
|
||||||
|
@ -118,7 +118,7 @@ class DeviceCoordinator:
|
|||||||
"""
|
"""
|
||||||
注册Socket.IO命名空间
|
注册Socket.IO命名空间
|
||||||
"""
|
"""
|
||||||
namespaces = ['/camera', '/imu', '/pressure', '/femtobolt', '/coordinator']
|
namespaces = ['/devices', '/coordinator']
|
||||||
for namespace in namespaces:
|
for namespace in namespaces:
|
||||||
self.socket_manager.register_namespace(namespace)
|
self.socket_manager.register_namespace(namespace)
|
||||||
|
|
||||||
|
@ -537,7 +537,7 @@ class FemtoBoltManager(BaseDevice):
|
|||||||
'min': self.depth_range_min,
|
'min': self.depth_range_min,
|
||||||
'max': self.depth_range_max
|
'max': self.depth_range_max
|
||||||
}
|
}
|
||||||
}, namespace='/femtobolt')
|
}, namespace='/devices')
|
||||||
frame_count += 1
|
frame_count += 1
|
||||||
|
|
||||||
# 更新统计
|
# 更新统计
|
||||||
@ -640,7 +640,7 @@ class FemtoBoltManager(BaseDevice):
|
|||||||
send_data['color_image'] = color_data
|
send_data['color_image'] = color_data
|
||||||
|
|
||||||
# 发送到SocketIO
|
# 发送到SocketIO
|
||||||
self._socketio.emit('femtobolt_frame', send_data, namespace='/femtobolt')
|
self._socketio.emit('femtobolt_frame', send_data, namespace='/devices')
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"发送深度数据失败: {e}")
|
self.logger.error(f"发送深度数据失败: {e}")
|
||||||
|
@ -502,7 +502,7 @@ class IMUManager(BaseDevice):
|
|||||||
|
|
||||||
# 发送数据到前端
|
# 发送数据到前端
|
||||||
if self._socketio:
|
if self._socketio:
|
||||||
self._socketio.emit('imu_data', data, namespace='/imu')
|
self._socketio.emit('imu_data', data, namespace='/devices')
|
||||||
|
|
||||||
# 更新统计
|
# 更新统计
|
||||||
self.data_count += 1
|
self.data_count += 1
|
||||||
|
@ -807,14 +807,64 @@ class PressureManager(BaseDevice):
|
|||||||
if self.device:
|
if self.device:
|
||||||
pressure_data = self.device.read_data()
|
pressure_data = self.device.read_data()
|
||||||
|
|
||||||
if pressure_data:
|
if pressure_data and 'foot_pressure' in pressure_data:
|
||||||
|
foot_pressure = pressure_data['foot_pressure']
|
||||||
|
# 获取各区域压力值
|
||||||
|
left_front = foot_pressure['left_front']
|
||||||
|
left_rear = foot_pressure['left_rear']
|
||||||
|
right_front = foot_pressure['right_front']
|
||||||
|
right_rear = foot_pressure['right_rear']
|
||||||
|
left_total = foot_pressure['left_total']
|
||||||
|
right_total = foot_pressure['right_total']
|
||||||
|
|
||||||
|
# 计算总压力
|
||||||
|
total_pressure = left_total + right_total
|
||||||
|
|
||||||
|
# 计算平衡比例(左脚压力占总压力的比例)
|
||||||
|
balance_ratio = left_total / total_pressure if total_pressure > 0 else 0.5
|
||||||
|
|
||||||
|
# 计算压力中心偏移
|
||||||
|
pressure_center_offset = (balance_ratio - 0.5) * 100 # 转换为百分比
|
||||||
|
|
||||||
|
# 计算前后足压力分布
|
||||||
|
left_front_ratio = left_front / left_total if left_total > 0 else 0.5
|
||||||
|
right_front_ratio = right_front / right_total if right_total > 0 else 0.5
|
||||||
|
|
||||||
|
# 构建完整的足部压力数据
|
||||||
|
complete_pressure_data = {
|
||||||
|
# 分区压力值
|
||||||
|
'pressure_zones': {
|
||||||
|
'left_front': left_front,
|
||||||
|
'left_rear': left_rear,
|
||||||
|
'right_front': right_front,
|
||||||
|
'right_rear': right_rear,
|
||||||
|
'left_total': left_total,
|
||||||
|
'right_total': right_total,
|
||||||
|
'total_pressure': total_pressure
|
||||||
|
},
|
||||||
|
# 平衡分析
|
||||||
|
'balance_analysis': {
|
||||||
|
'balance_ratio': round(balance_ratio, 3),
|
||||||
|
'pressure_center_offset': round(pressure_center_offset, 2),
|
||||||
|
'balance_status': 'balanced' if abs(pressure_center_offset) < 10 else 'unbalanced',
|
||||||
|
'left_front_ratio': round(left_front_ratio, 3),
|
||||||
|
'right_front_ratio': round(right_front_ratio, 3)
|
||||||
|
},
|
||||||
|
# 压力图片
|
||||||
|
'pressure_image': pressure_data.get('pressure_image', ''),
|
||||||
|
'timestamp': pressure_data['timestamp']
|
||||||
|
}
|
||||||
|
|
||||||
# 更新统计信息
|
# 更新统计信息
|
||||||
self.packet_count += 1
|
self.packet_count += 1
|
||||||
self.last_data_time = time.time()
|
self.last_data_time = time.time()
|
||||||
|
|
||||||
# 发送数据到前端
|
# 发送数据到前端
|
||||||
if self._socketio:
|
if self._socketio:
|
||||||
self._socketio.emit('pressure_data', pressure_data, namespace='/pressure')
|
self._socketio.emit('pressure_data', {
|
||||||
|
'foot_pressure': complete_pressure_data,
|
||||||
|
'timestamp': datetime.now().isoformat()
|
||||||
|
}, namespace='/devices')
|
||||||
else:
|
else:
|
||||||
self.logger.warning("SocketIO实例为空,无法发送压力数据")
|
self.logger.warning("SocketIO实例为空,无法发送压力数据")
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -170,42 +170,35 @@ class DeviceTestServer:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
emit('test_status', {'status': 'error', 'message': str(e)})
|
emit('test_status', {'status': 'error', 'message': str(e)})
|
||||||
|
|
||||||
# 注册各设备命名空间的连接事件
|
# 注册统一设备命名空间的连接事件
|
||||||
@self.socketio.on('connect', namespace='/camera')
|
@self.socketio.on('connect', namespace='/devices')
|
||||||
def handle_camera_connect():
|
def handle_devices_connect():
|
||||||
self.logger.info('相机命名空间客户端连接')
|
self.logger.info('设备命名空间客户端连接')
|
||||||
emit('status', {'message': '相机命名空间连接成功'}, namespace='/camera')
|
emit('status', {'message': '设备命名空间连接成功'}, namespace='/devices')
|
||||||
|
|
||||||
@self.socketio.on('connect', namespace='/femtobolt')
|
@self.socketio.on('disconnect', namespace='/devices')
|
||||||
def handle_femtobolt_connect():
|
def handle_devices_disconnect():
|
||||||
self.logger.info('深度相机命名空间客户端连接')
|
self.logger.info('设备命名空间客户端断开连接')
|
||||||
emit('status', {'message': '深度相机命名空间连接成功'}, namespace='/femtobolt')
|
|
||||||
|
|
||||||
@self.socketio.on('connect', namespace='/imu')
|
@self.socketio.on('subscribe_device', namespace='/devices')
|
||||||
def handle_imu_connect():
|
def handle_subscribe_device(data):
|
||||||
self.logger.info('IMU命名空间客户端连接')
|
"""处理设备订阅事件"""
|
||||||
emit('status', {'message': 'IMU命名空间连接成功'}, namespace='/imu')
|
device_type = data.get('device_type')
|
||||||
|
self.logger.info(f'客户端订阅设备: {device_type}')
|
||||||
|
emit('subscription_status', {
|
||||||
|
'device_type': device_type,
|
||||||
|
'status': 'subscribed'
|
||||||
|
}, namespace='/devices')
|
||||||
|
|
||||||
@self.socketio.on('connect', namespace='/pressure')
|
@self.socketio.on('unsubscribe_device', namespace='/devices')
|
||||||
def handle_pressure_connect():
|
def handle_unsubscribe_device(data):
|
||||||
self.logger.info('压力板命名空间客户端连接')
|
"""处理设备取消订阅事件"""
|
||||||
emit('status', {'message': '压力板命名空间连接成功'}, namespace='/pressure')
|
device_type = data.get('device_type')
|
||||||
|
self.logger.info(f'客户端取消订阅设备: {device_type}')
|
||||||
@self.socketio.on('disconnect', namespace='/camera')
|
emit('subscription_status', {
|
||||||
def handle_camera_disconnect():
|
'device_type': device_type,
|
||||||
self.logger.info('相机命名空间客户端断开连接')
|
'status': 'unsubscribed'
|
||||||
|
}, namespace='/devices')
|
||||||
@self.socketio.on('disconnect', namespace='/femtobolt')
|
|
||||||
def handle_femtobolt_disconnect():
|
|
||||||
self.logger.info('深度相机命名空间客户端断开连接')
|
|
||||||
|
|
||||||
@self.socketio.on('disconnect', namespace='/imu')
|
|
||||||
def handle_imu_disconnect():
|
|
||||||
self.logger.info('IMU命名空间客户端断开连接')
|
|
||||||
|
|
||||||
@self.socketio.on('disconnect', namespace='/pressure')
|
|
||||||
def handle_pressure_disconnect():
|
|
||||||
self.logger.info('压力板命名空间客户端断开连接')
|
|
||||||
|
|
||||||
def start_device_test(self):
|
def start_device_test(self):
|
||||||
"""开始设备测试"""
|
"""开始设备测试"""
|
||||||
@ -329,8 +322,8 @@ class DeviceTestServer:
|
|||||||
# 生成模拟数据
|
# 生成模拟数据
|
||||||
data = generator.generate_data()
|
data = generator.generate_data()
|
||||||
|
|
||||||
# 发送到对应的命名空间
|
# 发送到统一的设备命名空间
|
||||||
namespace = f'/{device_name}'
|
namespace = '/devices'
|
||||||
event_name = self._get_event_name(device_name)
|
event_name = self._get_event_name(device_name)
|
||||||
|
|
||||||
self.socketio.emit(event_name, data, namespace=namespace)
|
self.socketio.emit(event_name, data, namespace=namespace)
|
||||||
|
@ -840,7 +840,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理压力板数据
|
// 处理压力板数据(兼容新老数据结构)
|
||||||
function handlePressureData(data) {
|
function handlePressureData(data) {
|
||||||
if (!isTesting) return;
|
if (!isTesting) return;
|
||||||
|
|
||||||
@ -848,20 +848,50 @@
|
|||||||
document.getElementById('pressureDeviceStatus').textContent = '已连接';
|
document.getElementById('pressureDeviceStatus').textContent = '已连接';
|
||||||
document.getElementById('pressureDeviceStatus').classList.add('connected');
|
document.getElementById('pressureDeviceStatus').classList.add('connected');
|
||||||
|
|
||||||
if (data.pressure_image) {
|
// 后端新结构:{ foot_pressure: { pressure_zones, balance_analysis, pressure_image }, timestamp }
|
||||||
|
// 旧结构:{ pressure_image, pressure_data: { left_total, right_total, total_pressure, balance_ratio } }
|
||||||
|
const footPressure = data && (data.foot_pressure || null);
|
||||||
|
const zones = footPressure && (footPressure.pressure_zones || footPressure.pressureZones || null);
|
||||||
|
const analysis = footPressure && (footPressure.balance_analysis || footPressure.balanceAnalysis || null);
|
||||||
|
|
||||||
|
// 压力图像(优先新结构,其次旧结构)
|
||||||
|
const pressureImage = (footPressure && footPressure.pressure_image) || data.pressure_image || null;
|
||||||
|
if (pressureImage) {
|
||||||
const img = document.getElementById('pressureImage');
|
const img = document.getElementById('pressureImage');
|
||||||
img.src = 'data:image/jpeg;base64,' + data.pressure_image;
|
img.src = 'data:image/jpeg;base64,' + pressureImage;
|
||||||
img.style.display = 'block';
|
img.style.display = 'block';
|
||||||
document.getElementById('pressureNoSignal').style.display = 'none';
|
document.getElementById('pressureNoSignal').style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新压力数据
|
// 数值数据:优先新结构的 pressure_zones/balance_analysis,回退到旧结构的 pressure_data
|
||||||
if (data.pressure_data) {
|
if (zones || analysis) {
|
||||||
|
const leftTotal = (zones && (zones.left_total ?? zones.leftTotal)) ?? 0;
|
||||||
|
const rightTotal = (zones && (zones.right_total ?? zones.rightTotal)) ?? 0;
|
||||||
|
const totalPressure = (zones && (zones.total_pressure ?? zones.totalPressure)) ?? (leftTotal + rightTotal);
|
||||||
|
let balanceRatioRaw = analysis && (analysis.balance_ratio ?? analysis.balanceRatio);
|
||||||
|
if (balanceRatioRaw == null && totalPressure) {
|
||||||
|
// 若缺失,按左右比例计算一个近似值
|
||||||
|
balanceRatioRaw = leftTotal / totalPressure; // 0~1
|
||||||
|
}
|
||||||
|
let balanceRatio = 0;
|
||||||
|
if (typeof balanceRatioRaw === 'number') {
|
||||||
|
balanceRatio = balanceRatioRaw <= 1 ? Math.round(balanceRatioRaw * 100) : Math.round(balanceRatioRaw);
|
||||||
|
}
|
||||||
|
document.getElementById('leftTotal').textContent = leftTotal;
|
||||||
|
document.getElementById('rightTotal').textContent = rightTotal;
|
||||||
|
document.getElementById('totalPressure').textContent = totalPressure;
|
||||||
|
document.getElementById('balanceRatio').textContent = `${balanceRatio}%`;
|
||||||
|
} else if (data && data.pressure_data) {
|
||||||
const pd = data.pressure_data;
|
const pd = data.pressure_data;
|
||||||
document.getElementById('leftTotal').textContent = pd.left_total;
|
const leftTotal = pd.left_total ?? pd.leftTotal ?? 0;
|
||||||
document.getElementById('rightTotal').textContent = pd.right_total;
|
const rightTotal = pd.right_total ?? pd.rightTotal ?? 0;
|
||||||
document.getElementById('totalPressure').textContent = pd.total_pressure;
|
const totalPressure = pd.total_pressure ?? pd.totalPressure ?? (leftTotal + rightTotal);
|
||||||
document.getElementById('balanceRatio').textContent = `${pd.balance_ratio}%`;
|
let balanceRatioRaw = pd.balance_ratio ?? pd.balanceRatio ?? 0;
|
||||||
|
const balanceRatio = balanceRatioRaw <= 1 ? Math.round(balanceRatioRaw * 100) : Math.round(balanceRatioRaw);
|
||||||
|
document.getElementById('leftTotal').textContent = leftTotal;
|
||||||
|
document.getElementById('rightTotal').textContent = rightTotal;
|
||||||
|
document.getElementById('totalPressure').textContent = totalPressure;
|
||||||
|
document.getElementById('balanceRatio').textContent = `${balanceRatio}%`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ backup_interval = 24
|
|||||||
max_backups = 7
|
max_backups = 7
|
||||||
|
|
||||||
[CAMERA]
|
[CAMERA]
|
||||||
device_index = 0
|
device_index = 3
|
||||||
width = 1280
|
width = 1280
|
||||||
height = 720
|
height = 720
|
||||||
fps = 30
|
fps = 30
|
||||||
@ -29,7 +29,7 @@ depth_range_max = 1500
|
|||||||
|
|
||||||
[DEVICES]
|
[DEVICES]
|
||||||
imu_device_type = real
|
imu_device_type = real
|
||||||
imu_port = COM6
|
imu_port = COM3
|
||||||
imu_baudrate = 9600
|
imu_baudrate = 9600
|
||||||
pressure_device_type = real
|
pressure_device_type = real
|
||||||
pressure_use_mock = False
|
pressure_use_mock = False
|
||||||
|
@ -43,7 +43,7 @@ class SocketManager:
|
|||||||
注册设备命名空间
|
注册设备命名空间
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
namespace: 命名空间路径(如 '/camera')
|
namespace: 命名空间路径(如 '/devices')
|
||||||
device_name: 设备名称
|
device_name: 设备名称
|
||||||
"""
|
"""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
@ -138,6 +138,7 @@ class AppServer:
|
|||||||
self.app,
|
self.app,
|
||||||
cors_allowed_origins='*',
|
cors_allowed_origins='*',
|
||||||
async_mode='threading',
|
async_mode='threading',
|
||||||
|
#async_mode='eventlet',
|
||||||
logger=False,
|
logger=False,
|
||||||
engineio_logger=False,
|
engineio_logger=False,
|
||||||
ping_timeout=60,
|
ping_timeout=60,
|
||||||
@ -926,70 +927,73 @@ class AppServer:
|
|||||||
if self.socketio is None:
|
if self.socketio is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
# 注册各设备命名空间的连接事件
|
# 注册统一设备命名空间的连接事件
|
||||||
@self.socketio.on('connect', namespace='/camera')
|
@self.socketio.on('connect', namespace='/devices')
|
||||||
def handle_camera_connect():
|
def handle_devices_connect():
|
||||||
self.logger.info('相机命名空间客户端连接')
|
self.logger.info('设备命名空间客户端连接')
|
||||||
emit('status', {'message': '相机命名空间连接成功'}, namespace='/camera')
|
emit('status', {'message': '设备命名空间连接成功'}, namespace='/devices')
|
||||||
|
|
||||||
@self.socketio.on('connect', namespace='/femtobolt')
|
@self.socketio.on('disconnect', namespace='/devices')
|
||||||
def handle_femtobolt_connect():
|
def handle_devices_disconnect():
|
||||||
self.logger.info('深度相机命名空间客户端连接')
|
self.logger.info('设备命名空间客户端断开连接')
|
||||||
emit('status', {'message': '深度相机命名空间连接成功'}, namespace='/femtobolt')
|
|
||||||
|
|
||||||
@self.socketio.on('connect', namespace='/imu')
|
# 注册设备订阅事件
|
||||||
def handle_imu_connect():
|
@self.socketio.on('subscribe_device', namespace='/devices')
|
||||||
self.logger.info('IMU命名空间客户端连接')
|
def handle_subscribe_device(data):
|
||||||
emit('status', {'message': 'IMU命名空间连接成功'}, namespace='/imu')
|
"""订阅特定设备数据"""
|
||||||
|
device_type = data.get('device_type')
|
||||||
@self.socketio.on('connect', namespace='/pressure')
|
if device_type in ['camera', 'femtobolt', 'imu', 'pressure']:
|
||||||
def handle_pressure_connect():
|
self.logger.info(f'客户端订阅{device_type}设备数据')
|
||||||
self.logger.info('压力板命名空间客户端连接')
|
emit('subscription_status', {
|
||||||
emit('status', {'message': '压力板命名空间连接成功'}, namespace='/pressure')
|
'device_type': device_type,
|
||||||
|
'status': 'subscribed',
|
||||||
@self.socketio.on('disconnect', namespace='/camera')
|
'message': f'{device_type}设备数据订阅成功'
|
||||||
def handle_camera_disconnect():
|
}, namespace='/devices')
|
||||||
self.logger.info('相机命名空间客户端断开连接')
|
else:
|
||||||
|
emit('subscription_status', {
|
||||||
@self.socketio.on('disconnect', namespace='/femtobolt')
|
'device_type': device_type,
|
||||||
def handle_femtobolt_disconnect():
|
'status': 'error',
|
||||||
self.logger.info('深度相机命名空间客户端断开连接')
|
'message': '不支持的设备类型'
|
||||||
|
}, namespace='/devices')
|
||||||
@self.socketio.on('disconnect', namespace='/imu')
|
|
||||||
def handle_imu_disconnect():
|
@self.socketio.on('unsubscribe_device', namespace='/devices')
|
||||||
self.logger.info('IMU命名空间客户端断开连接')
|
def handle_unsubscribe_device(data):
|
||||||
|
"""取消订阅特定设备数据"""
|
||||||
@self.socketio.on('disconnect', namespace='/pressure')
|
device_type = data.get('device_type')
|
||||||
def handle_pressure_disconnect():
|
self.logger.info(f'客户端取消订阅{device_type}设备数据')
|
||||||
self.logger.info('压力板命名空间客户端断开连接')
|
emit('subscription_status', {
|
||||||
|
'device_type': device_type,
|
||||||
|
'status': 'unsubscribed',
|
||||||
|
'message': f'{device_type}设备数据取消订阅成功'
|
||||||
|
}, namespace='/devices')
|
||||||
|
|
||||||
@self.socketio.on('start_push_data')
|
@self.socketio.on('start_push_data', namespace='/devices')
|
||||||
def handle_start_push_data():
|
def handle_start_push_data():
|
||||||
"""启动数据推送"""
|
"""启动数据推送"""
|
||||||
try:
|
try:
|
||||||
self.start_device_push_data()
|
self.start_device_push_data()
|
||||||
emit('test_status', {'status': 'started', 'message': '数据推送已开始'})
|
emit('test_status', {'status': 'started', 'message': '数据推送已开始'}, namespace='/devices')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
emit('test_status', {'status': 'error', 'message': str(e)})
|
emit('test_status', {'status': 'error', 'message': str(e)}, namespace='/devices')
|
||||||
|
|
||||||
@self.socketio.on('stop_push_data')
|
@self.socketio.on('stop_push_data', namespace='/devices')
|
||||||
def handle_stop_push_data():
|
def handle_stop_push_data():
|
||||||
"""停止数据推送"""
|
"""停止数据推送"""
|
||||||
try:
|
try:
|
||||||
self.stop_device_push_data()
|
self.stop_device_push_data()
|
||||||
emit('test_status', {'status': 'stopped', 'message': '数据推送已停止'})
|
emit('test_status', {'status': 'stopped', 'message': '数据推送已停止'}, namespace='/devices')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
emit('test_status', {'status': 'error', 'message': str(e)})
|
emit('test_status', {'status': 'error', 'message': str(e)}, namespace='/devices')
|
||||||
|
|
||||||
def start_device_push_data(self):
|
def start_device_push_data(self):
|
||||||
"""开始设备数据推送"""
|
"""开始设备数据推送"""
|
||||||
if self.is_testing:
|
if self.is_pushing_data:
|
||||||
self.logger.warning('设备数据推送已在运行')
|
self.logger.warning('设备数据推送已在运行')
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.logger.info('开始设备数据推送...')
|
self.logger.info('开始设备数据推送...')
|
||||||
self.is_testing = True
|
self.is_pushing_data = True
|
||||||
|
|
||||||
# 并行启动真实设备管理器
|
# 并行启动真实设备管理器
|
||||||
failed_devices = []
|
failed_devices = []
|
||||||
@ -1052,18 +1056,18 @@ class AppServer:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f'启动设备数据推送失败: {e}')
|
self.logger.error(f'启动设备数据推送失败: {e}')
|
||||||
self.is_testing = False
|
self.is_pushing_data = False
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def stop_device_push_data(self):
|
def stop_device_push_data(self):
|
||||||
"""停止设备数据推送"""
|
"""停止设备数据推送"""
|
||||||
if not self.is_testing:
|
if not self.is_pushing_data:
|
||||||
self.logger.warning('设备数据推送未运行')
|
self.logger.warning('设备数据推送未运行')
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.logger.info('停止设备数据推送...')
|
self.logger.info('停止设备数据推送...')
|
||||||
self.is_testing = False
|
self.is_pushing_data = False
|
||||||
|
|
||||||
# 停止设备管理器
|
# 停止设备管理器
|
||||||
for device_name, manager in self.device_managers.items():
|
for device_name, manager in self.device_managers.items():
|
||||||
|
@ -532,6 +532,7 @@ const patientInfo = ref({
|
|||||||
|
|
||||||
// WebSocket相关变量
|
// WebSocket相关变量
|
||||||
let socket = null
|
let socket = null
|
||||||
|
let devicesSocket = null
|
||||||
let cameraSocket = null
|
let cameraSocket = null
|
||||||
let femtoboltSocket = null
|
let femtoboltSocket = null
|
||||||
let imuSocket = null
|
let imuSocket = null
|
||||||
@ -809,8 +810,24 @@ function connectWebSocket() {
|
|||||||
socket.disconnect()
|
socket.disconnect()
|
||||||
socket = null
|
socket = null
|
||||||
}
|
}
|
||||||
|
if (cameraSocket) {
|
||||||
|
cameraSocket.disconnect()
|
||||||
|
cameraSocket = null
|
||||||
|
}
|
||||||
|
if (femtoboltSocket) {
|
||||||
|
femtoboltSocket.disconnect()
|
||||||
|
femtoboltSocket = null
|
||||||
|
}
|
||||||
|
if (imuSocket) {
|
||||||
|
imuSocket.disconnect()
|
||||||
|
imuSocket = null
|
||||||
|
}
|
||||||
|
if (pressureSocket) {
|
||||||
|
pressureSocket.disconnect()
|
||||||
|
pressureSocket = null
|
||||||
|
}
|
||||||
|
|
||||||
// 创建Socket.IO连接
|
// 创建主Socket.IO连接
|
||||||
socket = io(BACKEND_URL, {
|
socket = io(BACKEND_URL, {
|
||||||
transports: ['websocket', 'polling'],
|
transports: ['websocket', 'polling'],
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
@ -820,19 +837,29 @@ function connectWebSocket() {
|
|||||||
reconnectionDelay: 1000
|
reconnectionDelay: 1000
|
||||||
})
|
})
|
||||||
|
|
||||||
// 连接成功事件
|
// 创建统一设备命名空间连接
|
||||||
|
devicesSocket = io(BACKEND_URL + '/devices', {
|
||||||
|
transports: ['websocket', 'polling'],
|
||||||
|
timeout: 10000,
|
||||||
|
forceNew: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// 为了保持兼容性,将统一的设备socket赋值给各个设备变量
|
||||||
|
cameraSocket = devicesSocket
|
||||||
|
femtoboltSocket = devicesSocket
|
||||||
|
imuSocket = devicesSocket
|
||||||
|
pressureSocket = devicesSocket
|
||||||
|
|
||||||
|
// 主连接事件
|
||||||
socket.on('connect', () => {
|
socket.on('connect', () => {
|
||||||
console.log('✅ WebSocket连接成功!Socket ID:', socket.id)
|
console.log('✅ 主WebSocket连接成功!Socket ID:', socket.id)
|
||||||
isConnected.value = true
|
isConnected.value = true
|
||||||
// 连接成功后自动启动设备数据推送
|
|
||||||
startDeviceDataPush()
|
|
||||||
//绘制头部仪表盘
|
//绘制头部仪表盘
|
||||||
initchart()
|
initchart()
|
||||||
})
|
})
|
||||||
|
|
||||||
// 连接失败事件
|
|
||||||
socket.on('connect_error', (error) => {
|
socket.on('connect_error', (error) => {
|
||||||
console.error('❌ 连接失败:', error.message)
|
console.error('❌ 主连接失败:', error.message)
|
||||||
isConnected.value = false
|
isConnected.value = false
|
||||||
// 如果正在录像,停止录像
|
// 如果正在录像,停止录像
|
||||||
if (isRecording.value) {
|
if (isRecording.value) {
|
||||||
@ -841,9 +868,8 @@ function connectWebSocket() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 断开连接事件
|
|
||||||
socket.on('disconnect', (reason) => {
|
socket.on('disconnect', (reason) => {
|
||||||
console.log('⚠️ 连接断开:', reason)
|
console.log('⚠️ 主连接断开:', reason)
|
||||||
isConnected.value = false
|
isConnected.value = false
|
||||||
stopDeviceDataPush()
|
stopDeviceDataPush()
|
||||||
// 如果正在录像,停止录像
|
// 如果正在录像,停止录像
|
||||||
@ -853,96 +879,90 @@ function connectWebSocket() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 重连事件
|
|
||||||
socket.on('reconnect', (attemptNumber) => {
|
socket.on('reconnect', (attemptNumber) => {
|
||||||
console.log('🔄 WebSocket重连成功,尝试次数:', attemptNumber)
|
console.log('🔄 主WebSocket重连成功,尝试次数:', attemptNumber)
|
||||||
isConnected.value = true
|
isConnected.value = true
|
||||||
})
|
})
|
||||||
|
|
||||||
// 重连尝试事件
|
|
||||||
socket.on('reconnect_attempt', (attemptNumber) => {
|
socket.on('reconnect_attempt', (attemptNumber) => {
|
||||||
console.log('🔄 正在尝试重连...', attemptNumber)
|
console.log('🔄 正在尝试重连主连接...', attemptNumber)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 重连失败事件
|
|
||||||
socket.on('reconnect_failed', () => {
|
socket.on('reconnect_failed', () => {
|
||||||
console.error('❌ WebSocket重连失败')
|
console.error('❌ 主WebSocket重连失败')
|
||||||
isConnected.value = false
|
isConnected.value = false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// 监听测试状态事件
|
|
||||||
socket.on('test_status', (data) => {
|
socket.on('error', (error) => {
|
||||||
console.log('📊 测试状态:', data)
|
console.error('❌ 主Socket错误:', error)
|
||||||
if (data.status === 'started') {
|
|
||||||
console.log('✅ 设备数据推送已开始')
|
|
||||||
} else if (data.status === 'stopped') {
|
|
||||||
console.log('⏹️ 设备数据推送已停止')
|
|
||||||
} else if (data.status === 'error') {
|
|
||||||
console.error('❌ 设备数据推送错误:', data.message)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听相机命名空间状态
|
// 统一设备命名空间事件监听
|
||||||
cameraSocket = io(BACKEND_URL + '/camera')
|
devicesSocket.on('connect', () => {
|
||||||
cameraSocket.on('connect', () => {
|
console.log('🔗 设备命名空间连接成功')
|
||||||
console.log('📹 相机命名空间连接成功')
|
|
||||||
videoStatus.value = '已连接'
|
videoStatus.value = '已连接'
|
||||||
|
imuStatus.value = '已连接'
|
||||||
|
pressureStatus.value = '已连接'
|
||||||
|
|
||||||
|
// 连接成功后订阅所有设备数据
|
||||||
|
devicesSocket.emit('subscribe_device', { device_type: 'camera' })
|
||||||
|
devicesSocket.emit('subscribe_device', { device_type: 'femtobolt' })
|
||||||
|
devicesSocket.emit('subscribe_device', { device_type: 'imu' })
|
||||||
|
devicesSocket.emit('subscribe_device', { device_type: 'pressure' })
|
||||||
|
|
||||||
|
// 设备连接成功后启动数据推送
|
||||||
|
startDeviceDataPush()
|
||||||
})
|
})
|
||||||
cameraSocket.on('disconnect', () => {
|
|
||||||
console.log('📹 相机命名空间断开连接')
|
devicesSocket.on('disconnect', () => {
|
||||||
|
console.log('🔗 设备命名空间断开连接')
|
||||||
videoStatus.value = '未连接'
|
videoStatus.value = '未连接'
|
||||||
|
imuStatus.value = '未连接'
|
||||||
|
pressureStatus.value = '未连接'
|
||||||
})
|
})
|
||||||
cameraSocket.on('video_frame', (data) => {
|
|
||||||
|
devicesSocket.on('connect_error', (error) => {
|
||||||
|
console.error('❌ 设备命名空间连接失败:', error.message)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听各设备数据事件
|
||||||
|
devicesSocket.on('camera_frame', (data) => {
|
||||||
frameCount++
|
frameCount++
|
||||||
displayFrame(data.image)
|
displayFrame(data.image)
|
||||||
})
|
})
|
||||||
|
devicesSocket.on('video_frame', (data) => {
|
||||||
// 监听深度相机命名空间状态
|
frameCount++
|
||||||
femtoboltSocket = io(BACKEND_URL + '/femtobolt')
|
displayFrame(data.image)
|
||||||
femtoboltSocket.on('connect', () => {
|
|
||||||
console.log('🔍 深度相机命名空间连接成功')
|
|
||||||
})
|
})
|
||||||
femtoboltSocket.on('disconnect', () => {
|
|
||||||
console.log('🔍 深度相机命名空间断开连接')
|
devicesSocket.on('femtobolt_frame', (data) => {
|
||||||
|
displayDepthCameraFrame(data.depth_image || data.image)
|
||||||
})
|
})
|
||||||
femtoboltSocket.on('depth_camera_frame', (data) => {
|
devicesSocket.on('depth_camera_frame', (data) => {
|
||||||
displayDepthCameraFrame(data.image)
|
displayDepthCameraFrame(data.depth_image || data.image)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听IMU命名空间状态
|
devicesSocket.on('imu_data', (data) => {
|
||||||
imuSocket = io(BACKEND_URL + '/imu')
|
|
||||||
imuSocket.on('connect', () => {
|
|
||||||
console.log('🧭 IMU命名空间连接成功')
|
|
||||||
imuStatus.value = '已连接'
|
|
||||||
})
|
|
||||||
imuSocket.on('disconnect', () => {
|
|
||||||
console.log('🧭 IMU命名空间断开连接')
|
|
||||||
imuStatus.value = '未连接'
|
|
||||||
})
|
|
||||||
imuSocket.on('imu_data', (data) => {
|
|
||||||
handleIMUData(data)
|
handleIMUData(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听压力板命名空间状态
|
devicesSocket.on('pressure_data', (data) => {
|
||||||
pressureSocket = io(BACKEND_URL + '/pressure')
|
handlePressureData(data)
|
||||||
pressureSocket.on('connect', () => {
|
})
|
||||||
console.log('⚖️ 压力板命名空间连接成功')
|
|
||||||
pressureStatus.value = '已连接'
|
// 监听测试状态事件
|
||||||
})
|
devicesSocket.on('test_status', (data) => {
|
||||||
pressureSocket.on('disconnect', () => {
|
console.log('📊 测试状态:', data)
|
||||||
console.log('⚖️ 压力板命名空间断开连接')
|
if (data.status === 'started') {
|
||||||
pressureStatus.value = '未连接'
|
console.log('✅ 设备数据推送已开始')
|
||||||
})
|
} else if (data.status === 'stopped') {
|
||||||
pressureSocket.on('pressure_data', (data) => {
|
console.log('⏹️ 设备数据推送已停止')
|
||||||
handlePressureData(data)
|
} else if (data.status === 'error') {
|
||||||
})
|
console.error('❌ 设备数据推送错误:', data.message)
|
||||||
|
}
|
||||||
// 监听错误事件
|
})
|
||||||
socket.on('error', (error) => {
|
|
||||||
console.error('❌ Socket错误:', error)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('💥 连接异常:', error.message)
|
console.error('💥 连接异常:', error.message)
|
||||||
@ -952,21 +972,21 @@ function connectWebSocket() {
|
|||||||
|
|
||||||
// 启动设备数据推送
|
// 启动设备数据推送
|
||||||
function startDeviceDataPush() {
|
function startDeviceDataPush() {
|
||||||
if (socket && socket.connected) {
|
if (devicesSocket && devicesSocket.connected) {
|
||||||
console.log('🚀 发送启动设备数据推送请求...')
|
console.log('🚀 发送启动设备数据推送请求...')
|
||||||
socket.emit('start_push_data')
|
devicesSocket.emit('start_push_data')
|
||||||
} else {
|
} else {
|
||||||
console.warn('⚠️ Socket未连接,无法启动设备数据推送')
|
console.warn('⚠️ 设备Socket未连接,无法启动设备数据推送')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 停止设备数据推送
|
// 停止设备数据推送
|
||||||
function stopDeviceDataPush() {
|
function stopDeviceDataPush() {
|
||||||
if (socket && socket.connected) {
|
if (devicesSocket && devicesSocket.connected) {
|
||||||
console.log('🛑 发送停止设备数据推送请求...')
|
console.log('🛑 发送停止设备数据推送请求...')
|
||||||
socket.emit('stop_push_data')
|
devicesSocket.emit('stop_push_data')
|
||||||
} else {
|
} else {
|
||||||
console.warn('⚠️ Socket未连接,无法停止设备数据推送')
|
console.warn('⚠️ 设备Socket未连接,无法停止设备数据推送')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -986,29 +1006,21 @@ function disconnectWebSocket() {
|
|||||||
console.log('✅ 主WebSocket连接已断开')
|
console.log('✅ 主WebSocket连接已断开')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 断开所有命名空间连接
|
// 断开统一设备命名空间连接
|
||||||
if (cameraSocket && cameraSocket.connected) {
|
if (devicesSocket && devicesSocket.connected) {
|
||||||
cameraSocket.disconnect()
|
// 取消订阅所有设备
|
||||||
|
devicesSocket.emit('unsubscribe_device', { device_type: 'camera' })
|
||||||
|
devicesSocket.emit('unsubscribe_device', { device_type: 'femtobolt' })
|
||||||
|
devicesSocket.emit('unsubscribe_device', { device_type: 'imu' })
|
||||||
|
devicesSocket.emit('unsubscribe_device', { device_type: 'pressure' })
|
||||||
|
|
||||||
|
devicesSocket.disconnect()
|
||||||
|
devicesSocket = null
|
||||||
cameraSocket = null
|
cameraSocket = null
|
||||||
console.log('📹 相机命名空间连接已断开')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (femtoboltSocket && femtoboltSocket.connected) {
|
|
||||||
femtoboltSocket.disconnect()
|
|
||||||
femtoboltSocket = null
|
femtoboltSocket = null
|
||||||
console.log('🔍 深度相机命名空间连接已断开')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imuSocket && imuSocket.connected) {
|
|
||||||
imuSocket.disconnect()
|
|
||||||
imuSocket = null
|
imuSocket = null
|
||||||
console.log('🧭 IMU命名空间连接已断开')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pressureSocket && pressureSocket.connected) {
|
|
||||||
pressureSocket.disconnect()
|
|
||||||
pressureSocket = null
|
pressureSocket = null
|
||||||
console.log('⚖️ 压力板命名空间连接已断开')
|
console.log('🔗 统一设备命名空间连接已断开')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置状态
|
// 重置状态
|
||||||
@ -1098,20 +1110,32 @@ function handleIMUData(data) {
|
|||||||
const pVal = Math.round(pitch * 10) / 10
|
const pVal = Math.round(pitch * 10) / 10
|
||||||
const tVal = Math.round(tilt * 10) / 10
|
const tVal = Math.round(tilt * 10) / 10
|
||||||
|
|
||||||
if (rotationCharts) {
|
if (rotationCharts && !rotationCharts.isDisposed()) {
|
||||||
rotationCharts.setOption({
|
try {
|
||||||
series: [{ data: [{ value: rVal }] }]
|
rotationCharts.setOption({
|
||||||
})
|
series: [{ data: [{ value: rVal }] }]
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('rotationCharts setOption error:', e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pitchCharts) {
|
if (pitchCharts && !pitchCharts.isDisposed()) {
|
||||||
pitchCharts.setOption({
|
try {
|
||||||
series: [{ data: [{ value: pVal }] }]
|
pitchCharts.setOption({
|
||||||
})
|
series: [{ data: [{ value: pVal }] }]
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('pitchCharts setOption error:', e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (tiltCharts) {
|
if (tiltCharts && !tiltCharts.isDisposed()) {
|
||||||
tiltCharts.setOption({
|
try {
|
||||||
series: [{ data: [{ value: tVal }] }]
|
tiltCharts.setOption({
|
||||||
})
|
series: [{ data: [{ value: tVal }] }]
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('tiltCharts setOption error:', e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新最值跟踪逻辑使用原始数值(不做四舍五入)
|
// 更新最值跟踪逻辑使用原始数值(不做四舍五入)
|
||||||
@ -2007,45 +2031,72 @@ const initchart = () => {
|
|||||||
if (chartDom) {
|
if (chartDom) {
|
||||||
// 如果图表已经存在,先销毁
|
// 如果图表已经存在,先销毁
|
||||||
if (rotationCharts) {
|
if (rotationCharts) {
|
||||||
rotationCharts.dispose();
|
try {
|
||||||
|
rotationCharts.dispose();
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('rotationCharts dispose error:', e);
|
||||||
|
}
|
||||||
|
rotationCharts = null;
|
||||||
}
|
}
|
||||||
rotationCharts = echarts.init(chartDom);
|
rotationCharts = echarts.init(chartDom);
|
||||||
rotationCharts.setOption(chartoption.value);
|
rotationCharts.setOption(chartoption.value);
|
||||||
} else {
|
} else {
|
||||||
console.warn('找不到 ID 为 的 DOM 元素');
|
console.warn('找不到 ID 为 rotationChartId 的 DOM 元素');
|
||||||
}
|
}
|
||||||
const chartDom2 = document.getElementById('pitchChartId');
|
const chartDom2 = document.getElementById('pitchChartId');
|
||||||
if (chartDom2) {
|
if (chartDom2) {
|
||||||
// 如果图表已经存在,先销毁
|
// 如果图表已经存在,先销毁
|
||||||
if (pitchCharts) {
|
if (pitchCharts) {
|
||||||
pitchCharts.dispose();
|
try {
|
||||||
|
pitchCharts.dispose();
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('pitchCharts dispose error:', e);
|
||||||
|
}
|
||||||
|
pitchCharts = null;
|
||||||
}
|
}
|
||||||
pitchCharts = echarts.init(chartDom2);
|
pitchCharts = echarts.init(chartDom2);
|
||||||
pitchCharts.setOption(chartoption.value);
|
pitchCharts.setOption(chartoption.value);
|
||||||
} else {
|
} else {
|
||||||
console.warn('找不到 ID 为 的 DOM 元素');
|
console.warn('找不到 ID 为 pitchChartId 的 DOM 元素');
|
||||||
}
|
}
|
||||||
const chartDom3 = document.getElementById('tiltChartId');
|
const chartDom3 = document.getElementById('tiltChartId');
|
||||||
if (chartDom3) {
|
if (chartDom3) {
|
||||||
// 如果图表已经存在,先销毁
|
// 如果图表已经存在,先销毁
|
||||||
if (tiltCharts) {
|
if (tiltCharts) {
|
||||||
tiltCharts.dispose();
|
try {
|
||||||
|
tiltCharts.dispose();
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('tiltCharts dispose error:', e);
|
||||||
|
}
|
||||||
|
tiltCharts = null;
|
||||||
}
|
}
|
||||||
tiltCharts = echarts.init(chartDom3);
|
tiltCharts = echarts.init(chartDom3);
|
||||||
tiltCharts.setOption(chartoption.value);
|
tiltCharts.setOption(chartoption.value);
|
||||||
} else {
|
} else {
|
||||||
console.warn('找不到 ID 为 的 DOM 元素');
|
console.warn('找不到 ID 为 tiltChartId 的 DOM 元素');
|
||||||
}
|
}
|
||||||
// 添加窗口大小调整监听器
|
// 添加窗口大小调整监听器
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
if (rotationCharts) {
|
if (rotationCharts && !rotationCharts.isDisposed()) {
|
||||||
rotationCharts.resize();
|
try {
|
||||||
|
rotationCharts.resize();
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('rotationCharts resize error:', e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pitchCharts) {
|
if (pitchCharts && !pitchCharts.isDisposed()) {
|
||||||
pitchCharts.resize();
|
try {
|
||||||
|
pitchCharts.resize();
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('pitchCharts resize error:', e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (tiltCharts) {
|
if (tiltCharts && !tiltCharts.isDisposed()) {
|
||||||
tiltCharts.resize();
|
try {
|
||||||
|
tiltCharts.resize();
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('tiltCharts resize error:', e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -2101,13 +2152,28 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
// 清理图表资源
|
// 清理图表资源
|
||||||
if (tiltCharts) {
|
if (tiltCharts) {
|
||||||
tiltCharts.dispose();
|
try {
|
||||||
|
tiltCharts.dispose();
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('tiltCharts dispose error in onUnmounted:', e);
|
||||||
|
}
|
||||||
|
tiltCharts = null;
|
||||||
}
|
}
|
||||||
if (rotationCharts) {
|
if (rotationCharts) {
|
||||||
rotationCharts.dispose();
|
try {
|
||||||
|
rotationCharts.dispose();
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('rotationCharts dispose error in onUnmounted:', e);
|
||||||
|
}
|
||||||
|
rotationCharts = null;
|
||||||
}
|
}
|
||||||
if (pitchCharts) {
|
if (pitchCharts) {
|
||||||
pitchCharts.dispose();
|
try {
|
||||||
|
pitchCharts.dispose();
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('pitchCharts dispose error in onUnmounted:', e);
|
||||||
|
}
|
||||||
|
pitchCharts = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移除页面关闭事件监听器
|
// 移除页面关闭事件监听器
|
||||||
|
Loading…
Reference in New Issue
Block a user