优化版本提交

This commit is contained in:
zhaozilong12 2025-08-17 16:42:05 +08:00
parent 7053427249
commit 50a0fe8641
14 changed files with 4856 additions and 226 deletions

View File

@ -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

View File

@ -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

View File

@ -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}")

View File

@ -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)

View File

@ -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}")

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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}%`;
}
}

View File

@ -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

View File

@ -43,7 +43,7 @@ class SocketManager:
注册设备命名空间
Args:
namespace: 命名空间路径 '/camera'
namespace: 命名空间路径 '/devices'
device_name: 设备名称
"""
with self._lock:

View File

@ -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('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('connect', namespace='/pressure')
def handle_pressure_connect():
self.logger.info('压力板命名空间客户端连接')
emit('status', {'message': '压力板命名空间连接成功'}, namespace='/pressure')
@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('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('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():

View File

@ -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,26 +879,81 @@ 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('error', (error) => {
console.error('❌ 主Socket错误:', error)
})
//
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()
})
devicesSocket.on('disconnect', () => {
console.log('🔗 设备命名空间断开连接')
videoStatus.value = '未连接'
imuStatus.value = '未连接'
pressureStatus.value = '未连接'
})
devicesSocket.on('connect_error', (error) => {
console.error('❌ 设备命名空间连接失败:', error.message)
})
//
devicesSocket.on('camera_frame', (data) => {
frameCount++
displayFrame(data.image)
})
devicesSocket.on('video_frame', (data) => {
frameCount++
displayFrame(data.image)
})
devicesSocket.on('femtobolt_frame', (data) => {
displayDepthCameraFrame(data.depth_image || data.image)
})
devicesSocket.on('depth_camera_frame', (data) => {
displayDepthCameraFrame(data.depth_image || data.image)
})
devicesSocket.on('imu_data', (data) => {
handleIMUData(data)
})
devicesSocket.on('pressure_data', (data) => {
handlePressureData(data)
})
//
socket.on('test_status', (data) => {
devicesSocket.on('test_status', (data) => {
console.log('📊 测试状态:', data)
if (data.status === 'started') {
console.log('✅ 设备数据推送已开始')
@ -883,67 +964,6 @@ function connectWebSocket() {
}
})
//
cameraSocket = io(BACKEND_URL + '/camera')
cameraSocket.on('connect', () => {
console.log('📹 相机命名空间连接成功')
videoStatus.value = '已连接'
})
cameraSocket.on('disconnect', () => {
console.log('📹 相机命名空间断开连接')
videoStatus.value = '未连接'
})
cameraSocket.on('video_frame', (data) => {
frameCount++
displayFrame(data.image)
})
//
femtoboltSocket = io(BACKEND_URL + '/femtobolt')
femtoboltSocket.on('connect', () => {
console.log('🔍 深度相机命名空间连接成功')
})
femtoboltSocket.on('disconnect', () => {
console.log('🔍 深度相机命名空间断开连接')
})
femtoboltSocket.on('depth_camera_frame', (data) => {
displayDepthCameraFrame(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) => {
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)
})
} catch (error) {
console.error('💥 连接异常:', error.message)
isConnected.value = false
@ -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) {
if (rotationCharts && !rotationCharts.isDisposed()) {
try {
rotationCharts.setOption({
series: [{ data: [{ value: rVal }] }]
})
} catch (e) {
console.warn('rotationCharts setOption error:', e);
}
if (pitchCharts) {
}
if (pitchCharts && !pitchCharts.isDisposed()) {
try {
pitchCharts.setOption({
series: [{ data: [{ value: pVal }] }]
})
} catch (e) {
console.warn('pitchCharts setOption error:', e);
}
if (tiltCharts) {
}
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) {
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) {
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) {
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) {
if (rotationCharts && !rotationCharts.isDisposed()) {
try {
rotationCharts.resize();
} catch (e) {
console.warn('rotationCharts resize error:', e);
}
if (pitchCharts) {
}
if (pitchCharts && !pitchCharts.isDisposed()) {
try {
pitchCharts.resize();
} catch (e) {
console.warn('pitchCharts resize error:', e);
}
if (tiltCharts) {
}
if (tiltCharts && !tiltCharts.isDisposed()) {
try {
tiltCharts.resize();
} catch (e) {
console.warn('tiltCharts resize error:', e);
}
}
});
});
@ -2101,13 +2152,28 @@ onUnmounted(() => {
//
if (tiltCharts) {
try {
tiltCharts.dispose();
} catch (e) {
console.warn('tiltCharts dispose error in onUnmounted:', e);
}
tiltCharts = null;
}
if (rotationCharts) {
try {
rotationCharts.dispose();
} catch (e) {
console.warn('rotationCharts dispose error in onUnmounted:', e);
}
rotationCharts = null;
}
if (pitchCharts) {
try {
pitchCharts.dispose();
} catch (e) {
console.warn('pitchCharts dispose error in onUnmounted:', e);
}
pitchCharts = null;
}
//