project: 增加web和adb控制,未测试
This commit is contained in:
109
WebRTCControllerWeb/server/index.js
Normal file
109
WebRTCControllerWeb/server/index.js
Normal file
@@ -0,0 +1,109 @@
|
||||
// 轻量信令服务器,协议与 WebRTCSignalServer (Spring) 完全兼容。
|
||||
// 端点: ws://host:PORT/ws/signal
|
||||
// 支持消息: REGISTER / DEVICE_LIST / OFFER / ANSWER / ICE_CANDIDATE / CONTROL_COMMAND / CONNECTION_REJECTED
|
||||
// 支持通知: REGISTER_SUCCESS / DEVICE_LIST / TARGET_OFFLINE / REQUEST_ERROR / REQUEST_TIMEOUT
|
||||
import { WebSocketServer } from 'ws';
|
||||
|
||||
const PORT = Number(process.env.PORT || 8088);
|
||||
const PATH = process.env.WS_PATH || '/ws/signal';
|
||||
|
||||
const wss = new WebSocketServer({ port: PORT, path: PATH });
|
||||
|
||||
// deviceId -> { ws, type }
|
||||
const sessions = new Map();
|
||||
// "from->to" -> true(等待被控端确认)
|
||||
const pending = new Map();
|
||||
|
||||
const keyOf = (a, b) => `${a}->${b}`;
|
||||
|
||||
function send(ws, obj) {
|
||||
if (ws && ws.readyState === ws.OPEN) ws.send(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
wss.on('connection', (ws) => {
|
||||
ws.on('message', (data) => {
|
||||
let msg;
|
||||
try {
|
||||
msg = JSON.parse(data.toString());
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
const type = (msg.type || '').toUpperCase();
|
||||
switch (type) {
|
||||
case 'REGISTER': handleRegister(ws, msg); break;
|
||||
case 'DEVICE_LIST': handleDeviceList(ws); break;
|
||||
case 'OFFER': handleOffer(msg); break;
|
||||
case 'ANSWER':
|
||||
case 'CONNECTION_REJECTED':
|
||||
pending.delete(keyOf(msg.toDeviceId, msg.fromDeviceId));
|
||||
forward(msg);
|
||||
break;
|
||||
case 'ICE_CANDIDATE':
|
||||
case 'CONTROL_COMMAND':
|
||||
forward(msg);
|
||||
break;
|
||||
default:
|
||||
forward(msg);
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
for (const [id, s] of sessions) {
|
||||
if (s.ws === ws) { sessions.delete(id); break; }
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function handleRegister(ws, msg) {
|
||||
const id = msg.fromDeviceId;
|
||||
const type = (msg.deviceType || '').toUpperCase();
|
||||
if (!id || !type) return;
|
||||
sessions.set(id, { ws, type });
|
||||
send(ws, { type: 'REGISTER_SUCCESS', deviceId: id });
|
||||
console.log(`设备注册: ${id} (${type})`);
|
||||
}
|
||||
|
||||
function handleDeviceList(ws) {
|
||||
const controllers = [];
|
||||
const controlled = [];
|
||||
for (const [id, s] of sessions) {
|
||||
if (s.type === 'CONTROLLER') controllers.push(id);
|
||||
else if (s.type === 'CONTROLLED') controlled.push(id);
|
||||
}
|
||||
send(ws, { type: 'DEVICE_LIST', controllers, controlled });
|
||||
}
|
||||
|
||||
function handleOffer(msg) {
|
||||
const from = msg.fromDeviceId;
|
||||
const to = msg.toDeviceId;
|
||||
const fromType = sessions.get(from)?.type;
|
||||
const toType = sessions.get(to)?.type;
|
||||
|
||||
if (fromType !== 'CONTROLLER' || toType !== 'CONTROLLED') {
|
||||
send(sessions.get(from)?.ws, {
|
||||
type: 'REQUEST_ERROR',
|
||||
toDeviceId: to,
|
||||
payload: '连接请求只能由 CONTROLLER 发往 CONTROLLED',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const target = sessions.get(to)?.ws;
|
||||
if (!target) {
|
||||
send(sessions.get(from)?.ws, {
|
||||
type: 'TARGET_OFFLINE',
|
||||
toDeviceId: to,
|
||||
payload: '目标被控端不在线,请确认设备已开启并连接服务器',
|
||||
});
|
||||
return;
|
||||
}
|
||||
pending.set(keyOf(from, to), true);
|
||||
forward(msg);
|
||||
}
|
||||
|
||||
function forward(msg) {
|
||||
const target = sessions.get(msg.toDeviceId)?.ws;
|
||||
if (!target) return;
|
||||
send(target, msg);
|
||||
}
|
||||
|
||||
console.log(`信令服务器已启动: ws://localhost:${PORT}${PATH}`);
|
||||
Reference in New Issue
Block a user