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