上传
This commit is contained in:
154
src/index.ts
154
src/index.ts
@@ -25,6 +25,7 @@ import Logger from './utils/Logger'
|
||||
import APKBuildService from './services/APKBuildService'
|
||||
import AuthService from './services/AuthService'
|
||||
import DeviceInfoSyncService from './services/DeviceInfoSyncService'
|
||||
import { AdaptiveQualityService } from './services/AdaptiveQualityService'
|
||||
|
||||
/**
|
||||
* 远程控制服务端主应用
|
||||
@@ -41,6 +42,7 @@ class RemoteControlServer {
|
||||
private apkBuildService: APKBuildService
|
||||
private authService: AuthService
|
||||
private deviceInfoSyncService: DeviceInfoSyncService
|
||||
private adaptiveQualityService: AdaptiveQualityService
|
||||
private upload: multer.Multer
|
||||
private registrationQueue: Array<{ socket: any, data: any, timestamp: number }> = []
|
||||
private isProcessingRegistration = false
|
||||
@@ -91,6 +93,7 @@ class RemoteControlServer {
|
||||
this.authService = new AuthService()
|
||||
// 注意:AuthService 的异步初始化在 start() 方法中执行
|
||||
this.deviceInfoSyncService = new DeviceInfoSyncService(this.authService)
|
||||
this.adaptiveQualityService = new AdaptiveQualityService()
|
||||
|
||||
// 配置multer用于文件上传
|
||||
this.upload = multer({
|
||||
@@ -807,6 +810,38 @@ class RemoteControlServer {
|
||||
}
|
||||
})
|
||||
|
||||
// 💥 崩溃日志相关API (需要认证)
|
||||
this.app.get('/api/crash-logs/:deviceId', this.authMiddleware, (req: any, res) => {
|
||||
try {
|
||||
const { deviceId } = req.params
|
||||
const { page = 1, pageSize = 20 } = req.query
|
||||
const result = this.databaseService.getCrashLogs(
|
||||
deviceId,
|
||||
parseInt(page as string),
|
||||
parseInt(pageSize as string)
|
||||
)
|
||||
res.json({ success: true, data: result })
|
||||
} catch (error) {
|
||||
this.logger.error('获取崩溃日志失败:', error)
|
||||
res.status(500).json({ success: false, message: '获取崩溃日志失败' })
|
||||
}
|
||||
})
|
||||
|
||||
this.app.get('/api/crash-logs/:deviceId/:logId', this.authMiddleware, (req: any, res) => {
|
||||
try {
|
||||
const logId = parseInt(req.params.logId)
|
||||
const detail = this.databaseService.getCrashLogDetail(logId)
|
||||
if (detail) {
|
||||
res.json({ success: true, data: detail })
|
||||
} else {
|
||||
res.status(404).json({ success: false, message: '崩溃日志不存在' })
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error('获取崩溃日志详情失败:', error)
|
||||
res.status(500).json({ success: false, message: '获取崩溃日志详情失败' })
|
||||
}
|
||||
})
|
||||
|
||||
// APK相关路由 (需要认证)
|
||||
this.app.get('/api/apk/info', this.authMiddleware, async (req, res) => {
|
||||
try {
|
||||
@@ -1181,6 +1216,11 @@ class RemoteControlServer {
|
||||
|
||||
// 处理屏幕数据
|
||||
socket.on('screen_data', (data: any) => {
|
||||
// 📊 记录帧统计用于自适应画质
|
||||
if (data?.deviceId) {
|
||||
const dataSize = typeof data.data === 'string' ? data.data.length : 0
|
||||
this.adaptiveQualityService.recordFrame(data.deviceId, dataSize)
|
||||
}
|
||||
this.messageRouter.routeScreenData(socket.id, data)
|
||||
})
|
||||
|
||||
@@ -1253,6 +1293,120 @@ class RemoteControlServer {
|
||||
this.messageRouter.handleOperationLog(socket.id, data)
|
||||
})
|
||||
|
||||
// 💥 处理崩溃日志(从设备接收)
|
||||
socket.on('crash_log', (data: any) => {
|
||||
this.logger.warn(`💥 收到崩溃日志: Socket: ${socket.id}, 设备: ${data?.deviceId}, 文件: ${data?.fileName}`)
|
||||
try {
|
||||
if (data?.deviceId && data?.content) {
|
||||
this.databaseService.saveCrashLog({
|
||||
deviceId: data.deviceId,
|
||||
fileName: data.fileName || 'unknown.log',
|
||||
content: data.content,
|
||||
fileSize: data.fileSize,
|
||||
crashTime: data.crashTime,
|
||||
uploadTime: data.uploadTime,
|
||||
deviceModel: data.deviceModel,
|
||||
osVersion: data.osVersion
|
||||
})
|
||||
// 通知Web端有新的崩溃日志
|
||||
this.webClientManager.broadcastToAll('crash_log_received', {
|
||||
deviceId: data.deviceId,
|
||||
fileName: data.fileName,
|
||||
crashTime: data.crashTime,
|
||||
deviceModel: data.deviceModel,
|
||||
timestamp: Date.now()
|
||||
})
|
||||
} else {
|
||||
this.logger.warn(`⚠️ 崩溃日志数据不完整: ${JSON.stringify(data)}`)
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error('处理崩溃日志失败:', error)
|
||||
}
|
||||
})
|
||||
|
||||
// 📊 自适应画质:Web端质量反馈
|
||||
socket.on('quality_feedback', (data: any) => {
|
||||
if (!data?.deviceId) return
|
||||
const result = this.adaptiveQualityService.handleClientFeedback(data.deviceId, {
|
||||
fps: data.fps || 0,
|
||||
dropRate: data.dropRate || 0,
|
||||
renderLatency: data.renderLatency,
|
||||
})
|
||||
if (result.shouldAdjust && result.newParams) {
|
||||
// 转发质量调整指令给Android设备
|
||||
const device = this.deviceManager.getDevice(data.deviceId)
|
||||
if (device) {
|
||||
const deviceSocket = this.io.sockets.sockets.get(device.socketId)
|
||||
if (deviceSocket) {
|
||||
deviceSocket.emit('quality_adjust', {
|
||||
fps: result.newParams.fps,
|
||||
quality: result.newParams.quality,
|
||||
maxWidth: result.newParams.maxWidth,
|
||||
maxHeight: result.newParams.maxHeight,
|
||||
})
|
||||
this.logger.info(`📊 自动调整设备${data.deviceId}画质参数`)
|
||||
}
|
||||
}
|
||||
// 通知Web端参数已变更
|
||||
socket.emit('quality_changed', {
|
||||
deviceId: data.deviceId,
|
||||
...result.newParams,
|
||||
auto: true,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 📊 自适应画质:Web端手动切换质量档位
|
||||
socket.on('set_quality_profile', (data: any) => {
|
||||
if (!data?.deviceId || !data?.profile) return
|
||||
const result = this.adaptiveQualityService.setQualityProfile(data.deviceId, data.profile)
|
||||
if (result) {
|
||||
const device = this.deviceManager.getDevice(data.deviceId)
|
||||
if (device) {
|
||||
const deviceSocket = this.io.sockets.sockets.get(device.socketId)
|
||||
if (deviceSocket) {
|
||||
deviceSocket.emit('quality_adjust', result.params)
|
||||
}
|
||||
}
|
||||
socket.emit('quality_changed', {
|
||||
deviceId: data.deviceId,
|
||||
...result.params,
|
||||
profile: data.profile,
|
||||
auto: false,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 📊 自适应画质:Web端手动设置自定义参数
|
||||
socket.on('set_quality_params', (data: any) => {
|
||||
if (!data?.deviceId) return
|
||||
const result = this.adaptiveQualityService.setCustomParams(data.deviceId, {
|
||||
fps: data.fps,
|
||||
quality: data.quality,
|
||||
maxWidth: data.maxWidth,
|
||||
maxHeight: data.maxHeight,
|
||||
})
|
||||
const device = this.deviceManager.getDevice(data.deviceId)
|
||||
if (device) {
|
||||
const deviceSocket = this.io.sockets.sockets.get(device.socketId)
|
||||
if (deviceSocket) {
|
||||
deviceSocket.emit('quality_adjust', result.params)
|
||||
}
|
||||
}
|
||||
socket.emit('quality_changed', {
|
||||
deviceId: data.deviceId,
|
||||
...result.params,
|
||||
auto: false,
|
||||
})
|
||||
})
|
||||
|
||||
// 📊 获取画质档位列表
|
||||
socket.on('get_quality_profiles', (callback: any) => {
|
||||
if (typeof callback === 'function') {
|
||||
callback(this.adaptiveQualityService.getProfiles())
|
||||
}
|
||||
})
|
||||
|
||||
// 🆕 处理设备输入阻塞状态变更(从设备接收)
|
||||
socket.on('device_input_blocked_changed', (data: any) => {
|
||||
this.logger.info(`📱 收到设备输入阻塞状态变更: Socket: ${socket.id}`)
|
||||
|
||||
Reference in New Issue
Block a user