【m】聊天消息接入
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
import store from './store.js';
|
import store from './store.js';
|
||||||
import UIRenderer from './renderer.js';
|
import UIRenderer from './renderer.js';
|
||||||
import apiClient from './api.js';
|
import apiClient from './api.js';
|
||||||
import wsManager from './websocket.js';
|
// import wsManager from './websocket.js';
|
||||||
import { mockCallSession } from './models.js';
|
import { mockCallSession } from './models.js';
|
||||||
import { showNotification, generateId } from './utils.js';
|
import { showNotification, generateId } from './utils.js';
|
||||||
|
|
||||||
@@ -39,75 +39,75 @@ let connectionId = "";
|
|||||||
* 绑定WebSocket事件
|
* 绑定WebSocket事件
|
||||||
*/
|
*/
|
||||||
function bindWebSocketEvents() {
|
function bindWebSocketEvents() {
|
||||||
wsManager.on('connect', () => {
|
// wsManager.on('connect', () => {
|
||||||
console.log('WebSocket connected');
|
// console.log('WebSocket connected');
|
||||||
showNotification('已连接到服务器');
|
// showNotification('已连接到服务器');
|
||||||
});
|
// });
|
||||||
|
|
||||||
wsManager.on('disconnect', () => {
|
// wsManager.on('disconnect', () => {
|
||||||
console.log('WebSocket disconnected');
|
// console.log('WebSocket disconnected');
|
||||||
showNotification('与服务器的连接已断开', 5000);
|
// showNotification('与服务器的连接已断开', 5000);
|
||||||
});
|
// });
|
||||||
|
|
||||||
wsManager.on('message-received', (data) => {
|
// wsManager.on('message-received', (data) => {
|
||||||
console.log('Message received:', data);
|
// console.log('Message received:', data);
|
||||||
store.addMessage(data.message);
|
// store.addMessage(data.message);
|
||||||
});
|
// });
|
||||||
|
|
||||||
wsManager.on('user-joined', (data) => {
|
// wsManager.on('user-joined', (data) => {
|
||||||
console.log('User joined:', data);
|
// console.log('User joined:', data);
|
||||||
showNotification(`${data.userId} 加入了通话`);
|
// showNotification(`${data.userId} 加入了通话`);
|
||||||
});
|
// });
|
||||||
|
|
||||||
wsManager.on('user-left', (data) => {
|
// wsManager.on('user-left', (data) => {
|
||||||
console.log('User left:', data);
|
// console.log('User left:', data);
|
||||||
showNotification(`${data.userId} 离开了通话`);
|
// showNotification(`${data.userId} 离开了通话`);
|
||||||
});
|
// });
|
||||||
|
|
||||||
wsManager.on('media-state-changed', (data) => {
|
// wsManager.on('media-state-changed', (data) => {
|
||||||
console.log('Media state changed:', data);
|
// console.log('Media state changed:', data);
|
||||||
// 更新远端媒体状态
|
// // 更新远端媒体状态
|
||||||
if (data.userId !== store.getLocalUser().id) {
|
// if (data.userId !== store.getLocalUser().id) {
|
||||||
store.updateRemoteMedia(data);
|
// store.updateRemoteMedia(data);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
wsManager.on('network-quality', (data) => {
|
// wsManager.on('network-quality', (data) => {
|
||||||
console.log('Network quality changed:', data);
|
// console.log('Network quality changed:', data);
|
||||||
// 更新网络质量
|
// // 更新网络质量
|
||||||
const state = store.getState();
|
// const state = store.getState();
|
||||||
if (data.userId === state.session.remoteUser.id) {
|
// if (data.userId === state.session.remoteUser.id) {
|
||||||
state.session.remoteUser.networkQuality = data.quality;
|
// state.session.remoteUser.networkQuality = data.quality;
|
||||||
store.notify({ type: 'NETWORK_CHANGE', quality: data.quality });
|
// store.notify({ type: 'NETWORK_CHANGE', quality: data.quality });
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
wsManager.on('call-ended', (data) => {
|
// wsManager.on('call-ended', (data) => {
|
||||||
console.log('Call ended:', data);
|
// console.log('Call ended:', data);
|
||||||
store.endCall();
|
// store.endCall();
|
||||||
showNotification('通话已结束', 3000);
|
// showNotification('通话已结束', 3000);
|
||||||
});
|
// });
|
||||||
|
|
||||||
wsManager.on('call-request', (data) => {
|
// wsManager.on('call-request', (data) => {
|
||||||
console.log('Call request received:', data);
|
// console.log('Call request received:', data);
|
||||||
// 显示通话请求弹窗
|
// // 显示通话请求弹窗
|
||||||
if (window.showCallRequest) {
|
// if (window.showCallRequest) {
|
||||||
const caller = {
|
// const caller = {
|
||||||
name: mockCallSession.remoteUser.name,
|
// name: mockCallSession.remoteUser.name,
|
||||||
avatar: mockCallSession.remoteUser.avatar
|
// avatar: mockCallSession.remoteUser.avatar
|
||||||
};
|
// };
|
||||||
window.showCallRequest(caller);
|
// window.showCallRequest(caller);
|
||||||
connectionId = data.connectionId;
|
// connectionId = data.connectionId;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
//处理发送消息响应
|
// //处理发送消息响应
|
||||||
wsManager.on('chat-message', (data) => {
|
// wsManager.on('chat-message', (data) => {
|
||||||
console.log('chat-message:', data);
|
// console.log('chat-message:', data);
|
||||||
// 显示消息
|
// // 显示消息
|
||||||
store.addMessage({
|
// store.addMessage({
|
||||||
data: data.message,
|
// data: data.message,
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -216,8 +216,8 @@ function bindDomEvents() {
|
|||||||
|
|
||||||
if (content) {
|
if (content) {
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
const newMessage = {
|
const message = {
|
||||||
id: generateId(),
|
id: state.id,
|
||||||
senderId: state.session.localUser.id,
|
senderId: state.session.localUser.id,
|
||||||
senderName: state.session.localUser.name,
|
senderName: state.session.localUser.name,
|
||||||
senderAvatar: state.session.localUser.avatar,
|
senderAvatar: state.session.localUser.avatar,
|
||||||
@@ -227,14 +227,25 @@ function bindDomEvents() {
|
|||||||
isSelf: true
|
isSelf: true
|
||||||
};
|
};
|
||||||
|
|
||||||
store.addMessage(newMessage);
|
store.addMessage(message);
|
||||||
chatInput.value = '';
|
|
||||||
const message = {
|
|
||||||
connectionId: connectionId,
|
const newMessage = {
|
||||||
message: newMessage
|
id: state.id,
|
||||||
|
senderId: state.session.remoteUser.id,
|
||||||
|
senderName: state.session.remoteUser.name,
|
||||||
|
senderAvatar: state.session.remoteUser.avatar,
|
||||||
|
content: content,
|
||||||
|
type: 'text',
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
isSelf: false
|
||||||
|
|
||||||
};
|
};
|
||||||
|
chatInput.value = '';
|
||||||
// 发送消息到服务器
|
// 发送消息到服务器
|
||||||
wsManager.send('chat-message', message);
|
store.sendChatMessage(newMessage);
|
||||||
|
|
||||||
|
//wsManager.send('chat-message', message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -367,4 +378,4 @@ window.addEventListener('DOMContentLoaded', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 导出全局变量
|
// 导出全局变量
|
||||||
export { store, renderer, apiClient, wsManager };
|
export { store, renderer, apiClient };
|
||||||
|
|||||||
@@ -6,13 +6,14 @@ import { mockCallSession, mockMessages } from './models.js';
|
|||||||
import { Signaling, WebSocketSignaling } from "../../module/signaling.js";// 信令管理
|
import { Signaling, WebSocketSignaling } from "../../module/signaling.js";// 信令管理
|
||||||
import { RenderStreaming } from "../../module/renderstreaming.js"; // WebRTC连接管理
|
import { RenderStreaming } from "../../module/renderstreaming.js"; // WebRTC连接管理
|
||||||
import { getServerConfig, getRTCConfiguration } from "../js/config.js";//服务器配置和RTC配置
|
import { getServerConfig, getRTCConfiguration } from "../js/config.js";//服务器配置和RTC配置
|
||||||
import { showNotification } from './utils.js'; // 导入通知函数
|
import { showNotification, generateId } from './utils.js'; // 导入通知函数
|
||||||
// 默认视频流尺寸
|
// 默认视频流尺寸
|
||||||
const defaultStreamWidth = 1280;
|
const defaultStreamWidth = 1280;
|
||||||
const defaultStreamHeight = 720;
|
const defaultStreamHeight = 720;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CallStateManager {
|
class CallStateManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
const renderstreaming = null; // WebRTC连接管理实例
|
const renderstreaming = null; // WebRTC连接管理实例
|
||||||
@@ -20,6 +21,7 @@ class CallStateManager {
|
|||||||
const connectionId = null; // 连接ID
|
const connectionId = null; // 连接ID
|
||||||
// 核心状态
|
// 核心状态
|
||||||
this.state = {
|
this.state = {
|
||||||
|
id: generateId(),
|
||||||
session: {
|
session: {
|
||||||
...mockCallSession,
|
...mockCallSession,
|
||||||
status: 'idle' // 初始状态为空闲
|
status: 'idle' // 初始状态为空闲
|
||||||
@@ -255,6 +257,7 @@ class CallStateManager {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置WebRTC连接
|
* 设置WebRTC连接
|
||||||
* @async
|
* @async
|
||||||
@@ -362,7 +365,17 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// 初始化 RenderStreaming 实例后
|
||||||
|
this.renderstreaming.onMessage = (data) => {
|
||||||
|
console.log('收到聊天消息:', data);
|
||||||
|
if (data.type === 'chat-message') {
|
||||||
|
// 处理聊天消息
|
||||||
|
// 添加到消息列表并更新UI
|
||||||
|
store.addMessage(data.message);
|
||||||
|
} else if (data.type === 'on-message') {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
// 启动WebRTC连接
|
// 启动WebRTC连接
|
||||||
await this.renderstreaming.start();
|
await this.renderstreaming.start();
|
||||||
await this.renderstreaming.createConnection(connectionId);
|
await this.renderstreaming.createConnection(connectionId);
|
||||||
@@ -454,7 +467,15 @@ class CallStateManager {
|
|||||||
|
|
||||||
this.notify({ type: 'NEW_MESSAGE', message, unreadCount: this.state.unreadCount });
|
this.notify({ type: 'NEW_MESSAGE', message, unreadCount: this.state.unreadCount });
|
||||||
}
|
}
|
||||||
|
sendChatMessage(message) {
|
||||||
|
if (this.renderstreaming) {
|
||||||
|
|
||||||
|
this.renderstreaming.sendMessage({
|
||||||
|
type: 'chat-message',
|
||||||
|
message: message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
// 切换侧边栏
|
// 切换侧边栏
|
||||||
toggleSidebar() {
|
toggleSidebar() {
|
||||||
this.state.isSidebarOpen = !this.state.isSidebarOpen;
|
this.state.isSidebarOpen = !this.state.isSidebarOpen;
|
||||||
@@ -595,7 +616,7 @@ class CallStateManager {
|
|||||||
console.error('Error detecting network quality:', error);
|
console.error('Error detecting network quality:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 真实音频活动检测 - 远端
|
// 真实音频活动检测 - 远端
|
||||||
startRemoteActivityDetection() {
|
startRemoteActivityDetection() {
|
||||||
// 检查是否有远端音频流
|
// 检查是否有远端音频流
|
||||||
if (!this.state.remoteStream) {
|
if (!this.state.remoteStream) {
|
||||||
|
|||||||
@@ -1,303 +1,303 @@
|
|||||||
/**
|
// /**
|
||||||
* WebSocket管理
|
// * WebSocket管理
|
||||||
* 管理WebSocket连接,处理WebSocket事件
|
// * 管理WebSocket连接,处理WebSocket事件
|
||||||
*/
|
// */
|
||||||
import { RenderStreaming } from "../../module/renderstreaming.js"; // WebRTC连接管理
|
// import { RenderStreaming } from "../../module/renderstreaming.js"; // WebRTC连接管理
|
||||||
|
|
||||||
class WebSocketManager {
|
// class WebSocketManager {
|
||||||
constructor() {
|
// constructor() {
|
||||||
this.isConnected = false;
|
// this.isConnected = false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 获取默认WebSocket URL
|
// * 获取默认WebSocket URL
|
||||||
* @returns {string} WebSocket URL
|
// * @returns {string} WebSocket URL
|
||||||
*/
|
// */
|
||||||
getDefaultWebSocketUrl() {
|
// getDefaultWebSocketUrl() {
|
||||||
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
// const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||||
return `${protocol}//${location.host}`;
|
// return `${protocol}//${location.host}`;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 连接WebSocket
|
// * 连接WebSocket
|
||||||
*/
|
// */
|
||||||
init() {
|
// init() {
|
||||||
try {
|
// try {
|
||||||
|
|
||||||
RenderStreaming.onConnect = () => {
|
// RenderStreaming.onConnect = () => {
|
||||||
console.log('WebSocket connected');
|
// console.log('WebSocket connected');
|
||||||
this.isConnected = true;
|
// this.isConnected = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// // 发送连接消息
|
// // // 发送连接消息
|
||||||
// this.sendConnectMessage();
|
// // this.sendConnectMessage();
|
||||||
|
|
||||||
// // 启动心跳
|
// // // 启动心跳
|
||||||
this.startHeartbeat();
|
// this.startHeartbeat();
|
||||||
|
|
||||||
// this.emit('connect');
|
// // this.emit('connect');
|
||||||
};
|
// };
|
||||||
|
|
||||||
RenderStreaming.onDisconnect = () => {
|
// RenderStreaming.onDisconnect = () => {
|
||||||
console.log('WebSocket disconnected');
|
// console.log('WebSocket disconnected');
|
||||||
this.isConnected = false;
|
// this.isConnected = false;
|
||||||
this.stopHeartbeat();
|
// this.stopHeartbeat();
|
||||||
//this.emit('disconnect');
|
// //this.emit('disconnect');
|
||||||
//this.attemptReconnect();
|
// //this.attemptReconnect();
|
||||||
};
|
// };
|
||||||
|
|
||||||
RenderStreaming.onmessage = (event) => {
|
// RenderStreaming.onmessage = (event) => {
|
||||||
try {
|
// try {
|
||||||
const message = JSON.parse(event.data);
|
// const message = JSON.parse(event.data);
|
||||||
this.handleMessage(message);
|
// this.handleMessage(message);
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.error('Error parsing WebSocket message:', error);
|
// console.error('Error parsing WebSocket message:', error);
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
this.socket.onerror = (error) => {
|
// this.socket.onerror = (error) => {
|
||||||
console.error('WebSocket error:', error);
|
// console.error('WebSocket error:', error);
|
||||||
this.emit('error', error);
|
// this.emit('error', error);
|
||||||
};
|
// };
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.error('Error connecting to WebSocket:', error);
|
// console.error('Error connecting to WebSocket:', error);
|
||||||
this.emit('error', error);
|
// this.emit('error', error);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 断开WebSocket连接
|
// * 断开WebSocket连接
|
||||||
*/
|
// */
|
||||||
disconnect() {
|
// disconnect() {
|
||||||
if (this.socket) {
|
// if (this.socket) {
|
||||||
this.socket.close();
|
// this.socket.close();
|
||||||
this.socket = null;
|
// this.socket = null;
|
||||||
this.isConnected = false;
|
// this.isConnected = false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 发送消息
|
// * 发送消息
|
||||||
* @param {string} type - 消息类型
|
// * @param {string} type - 消息类型
|
||||||
* @param {Object} data - 消息数据
|
// * @param {Object} data - 消息数据
|
||||||
*/
|
// */
|
||||||
send(type, data) {
|
// send(type, data) {
|
||||||
if (this.isConnected && this.socket) {
|
// if (this.isConnected && this.socket) {
|
||||||
try {
|
// try {
|
||||||
let message;
|
// let message;
|
||||||
|
|
||||||
// 根据消息类型构建不同的消息格式
|
// // 根据消息类型构建不同的消息格式
|
||||||
if (type === 'connect' || type === 'disconnect') {
|
// if (type === 'connect' || type === 'disconnect') {
|
||||||
message = JSON.stringify({ type, connectionId: this.connectionId });
|
// message = JSON.stringify({ type, connectionId: this.connectionId });
|
||||||
} else if (type === 'offer' || type === 'answer' || type === 'candidate') {
|
// } else if (type === 'offer' || type === 'answer' || type === 'candidate') {
|
||||||
message = JSON.stringify({ type, data });
|
// message = JSON.stringify({ type, data });
|
||||||
} else if (type === 'broadcast') {
|
// } else if (type === 'broadcast') {
|
||||||
message = JSON.stringify({ type, message: data.message, targetConnectionId: data.targetConnectionId });
|
// message = JSON.stringify({ type, message: data.message, targetConnectionId: data.targetConnectionId });
|
||||||
} else if (type === 'ping' || type === 'pong') {
|
// } else if (type === 'ping' || type === 'pong') {
|
||||||
message = JSON.stringify({ type });
|
// message = JSON.stringify({ type });
|
||||||
} else {
|
// } else {
|
||||||
// 兼容旧格式,用于自定义事件
|
// // 兼容旧格式,用于自定义事件
|
||||||
message = JSON.stringify({ event: type, data });
|
// message = JSON.stringify({ event: type, data });
|
||||||
}
|
// }
|
||||||
|
|
||||||
this.socket.send(message);
|
// this.socket.send(message);
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.error('Error sending WebSocket message:', error);
|
// console.error('Error sending WebSocket message:', error);
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
console.warn('WebSocket not connected, cannot send message');
|
// console.warn('WebSocket not connected, cannot send message');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 处理接收到的消息
|
// * 处理接收到的消息
|
||||||
* @param {Object} message - 消息对象
|
// * @param {Object} message - 消息对象
|
||||||
*/
|
// */
|
||||||
handleMessage(message) {
|
// handleMessage(message) {
|
||||||
if (message.type) {
|
// if (message.type) {
|
||||||
console.log('Received message:', message);
|
// console.log('Received message:', message);
|
||||||
switch (message.type) {
|
// switch (message.type) {
|
||||||
case 'user-joined':
|
// case 'user-joined':
|
||||||
this.emit('user-joined', message.data);
|
// this.emit('user-joined', message.data);
|
||||||
break;
|
// break;
|
||||||
case 'user-left':
|
// case 'user-left':
|
||||||
this.emit('user-left', message.data);
|
// this.emit('user-left', message.data);
|
||||||
break;
|
// break;
|
||||||
case 'media-state-changed':
|
// case 'media-state-changed':
|
||||||
this.emit('media-state-changed', message.data);
|
// this.emit('media-state-changed', message.data);
|
||||||
break;
|
// break;
|
||||||
case 'message-received':
|
// case 'message-received':
|
||||||
this.emit('message-received', message.data);
|
// this.emit('message-received', message.data);
|
||||||
break;
|
// break;
|
||||||
case 'network-quality':
|
// case 'network-quality':
|
||||||
this.emit('network-quality', message.data);
|
// this.emit('network-quality', message.data);
|
||||||
break;
|
// break;
|
||||||
case 'call-ended':
|
// case 'call-ended':
|
||||||
this.emit('call-ended', message.data);
|
// this.emit('call-ended', message.data);
|
||||||
break;
|
// break;
|
||||||
case 'call-request':
|
// case 'call-request':
|
||||||
this.emit('call-request', message.data);
|
// this.emit('call-request', message.data);
|
||||||
break;
|
// break;
|
||||||
case 'ping':
|
// case 'ping':
|
||||||
// 处理心跳请求,回复pong
|
// // 处理心跳请求,回复pong
|
||||||
this.send('pong');
|
// this.send('pong');
|
||||||
break;
|
// break;
|
||||||
case 'pong':
|
// case 'pong':
|
||||||
// 处理心跳响应
|
// // 处理心跳响应
|
||||||
this.emit('pong');
|
// this.emit('pong');
|
||||||
break;
|
// break;
|
||||||
case 'offer':
|
// case 'offer':
|
||||||
this.emit('offer', message.data);
|
// this.emit('offer', message.data);
|
||||||
break;
|
// break;
|
||||||
case 'answer':
|
// case 'answer':
|
||||||
this.emit('answer', message.data);
|
// this.emit('answer', message.data);
|
||||||
break;
|
// break;
|
||||||
case 'candidate':
|
// case 'candidate':
|
||||||
this.emit('candidate', message.data);
|
// this.emit('candidate', message.data);
|
||||||
break;
|
// break;
|
||||||
case 'chat-message':
|
// case 'chat-message':
|
||||||
this.emit('chat-message', message.data);
|
// this.emit('chat-message', message.data);
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
// 处理旧格式消息
|
// // 处理旧格式消息
|
||||||
if (message.event) {
|
// if (message.event) {
|
||||||
this.emit(message.event, message.data);
|
// this.emit(message.event, message.data);
|
||||||
} else {
|
// } else {
|
||||||
this.emit('message', message);
|
// this.emit('message', message);
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
} else if (message.event) {
|
// } else if (message.event) {
|
||||||
// 处理旧格式消息
|
// // 处理旧格式消息
|
||||||
this.emit(message.event, message.data);
|
// this.emit(message.event, message.data);
|
||||||
} else {
|
// } else {
|
||||||
this.emit('message', message);
|
// this.emit('message', message);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 尝试重连
|
// * 尝试重连
|
||||||
*/
|
// */
|
||||||
attemptReconnect() {
|
// attemptReconnect() {
|
||||||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
// if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||||||
this.reconnectAttempts++;
|
// this.reconnectAttempts++;
|
||||||
const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
|
// const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
|
||||||
|
|
||||||
console.log(`Attempting to reconnect in ${delay}ms...`);
|
// console.log(`Attempting to reconnect in ${delay}ms...`);
|
||||||
|
|
||||||
setTimeout(() => {
|
// setTimeout(() => {
|
||||||
console.log(`Reconnect attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}`);
|
// console.log(`Reconnect attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}`);
|
||||||
this.connect();
|
// this.connect();
|
||||||
}, delay);
|
// }, delay);
|
||||||
} else {
|
// } else {
|
||||||
console.error('Max reconnect attempts reached');
|
// console.error('Max reconnect attempts reached');
|
||||||
this.emit('reconnect-failed');
|
// this.emit('reconnect-failed');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 生成连接ID
|
// * 生成连接ID
|
||||||
* @returns {string} 连接ID
|
// * @returns {string} 连接ID
|
||||||
*/
|
// */
|
||||||
generateConnectionId() {
|
// generateConnectionId() {
|
||||||
return 'conn_' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
// return 'conn_' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 发送连接消息
|
// * 发送连接消息
|
||||||
*/
|
// */
|
||||||
sendConnectMessage() {
|
// sendConnectMessage() {
|
||||||
this.send('connect');
|
// this.send('connect');
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 发送断开连接消息
|
// * 发送断开连接消息
|
||||||
*/
|
// */
|
||||||
sendDisconnectMessage() {
|
// sendDisconnectMessage() {
|
||||||
this.send('disconnect');
|
// this.send('disconnect');
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 启动心跳
|
// * 启动心跳
|
||||||
*/
|
// */
|
||||||
startHeartbeat() {
|
// startHeartbeat() {
|
||||||
this.heartbeatInterval = setInterval(() => {
|
// this.heartbeatInterval = setInterval(() => {
|
||||||
if (this.isConnected) {
|
// if (this.isConnected) {
|
||||||
this.send('ping');
|
// this.send('ping');
|
||||||
}
|
// }
|
||||||
}, 30000); // 每30秒发送一次心跳
|
// }, 30000); // 每30秒发送一次心跳
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 停止心跳
|
// * 停止心跳
|
||||||
*/
|
// */
|
||||||
stopHeartbeat() {
|
// stopHeartbeat() {
|
||||||
if (this.heartbeatInterval) {
|
// if (this.heartbeatInterval) {
|
||||||
clearInterval(this.heartbeatInterval);
|
// clearInterval(this.heartbeatInterval);
|
||||||
this.heartbeatInterval = null;
|
// this.heartbeatInterval = null;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 获取连接ID
|
// * 获取连接ID
|
||||||
* @returns {string} 连接ID
|
// * @returns {string} 连接ID
|
||||||
*/
|
// */
|
||||||
getConnectionId() {
|
// getConnectionId() {
|
||||||
return this.connectionId;
|
// return this.connectionId;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 订阅事件
|
// * 订阅事件
|
||||||
* @param {string} event - 事件名称
|
// * @param {string} event - 事件名称
|
||||||
* @param {Function} callback - 回调函数
|
// * @param {Function} callback - 回调函数
|
||||||
*/
|
// */
|
||||||
on(event, callback) {
|
// on(event, callback) {
|
||||||
if (!this.listeners.has(event)) {
|
// if (!this.listeners.has(event)) {
|
||||||
this.listeners.set(event, []);
|
// this.listeners.set(event, []);
|
||||||
}
|
// }
|
||||||
this.listeners.get(event).push(callback);
|
// this.listeners.get(event).push(callback);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 取消订阅事件
|
// * 取消订阅事件
|
||||||
* @param {string} event - 事件名称
|
// * @param {string} event - 事件名称
|
||||||
* @param {Function} callback - 回调函数
|
// * @param {Function} callback - 回调函数
|
||||||
*/
|
// */
|
||||||
off(event, callback) {
|
// off(event, callback) {
|
||||||
if (this.listeners.has(event)) {
|
// if (this.listeners.has(event)) {
|
||||||
const callbacks = this.listeners.get(event);
|
// const callbacks = this.listeners.get(event);
|
||||||
this.listeners.set(event, callbacks.filter(cb => cb !== callback));
|
// this.listeners.set(event, callbacks.filter(cb => cb !== callback));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 触发事件
|
// * 触发事件
|
||||||
* @param {string} event - 事件名称
|
// * @param {string} event - 事件名称
|
||||||
* @param {*} data - 事件数据
|
// * @param {*} data - 事件数据
|
||||||
*/
|
// */
|
||||||
emit(event, data) {
|
// emit(event, data) {
|
||||||
if (this.listeners.has(event)) {
|
// if (this.listeners.has(event)) {
|
||||||
this.listeners.get(event).forEach(callback => {
|
// this.listeners.get(event).forEach(callback => {
|
||||||
try {
|
// try {
|
||||||
callback(data);
|
// callback(data);
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.error(`Error in event listener for ${event}:`, error);
|
// console.error(`Error in event listener for ${event}:`, error);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 检查连接状态
|
// * 检查连接状态
|
||||||
* @returns {boolean} 是否连接
|
// * @returns {boolean} 是否连接
|
||||||
*/
|
// */
|
||||||
getIsConnected() {
|
// getIsConnected() {
|
||||||
return this.isConnected;
|
// return this.isConnected;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 创建单例实例
|
// // 创建单例实例
|
||||||
const wsManager = new WebSocketManager();
|
// const wsManager = new WebSocketManager();
|
||||||
|
|
||||||
export default wsManager;
|
// export default wsManager;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export class RenderStreaming {
|
|||||||
this.onGotAnswer = function (connectionId) { Logger.log(`On got Answer on ${connectionId}.`); };
|
this.onGotAnswer = function (connectionId) { Logger.log(`On got Answer on ${connectionId}.`); };
|
||||||
this.onTrackEvent = function (data) { Logger.log(`OnTrack event peer with data:${data}`); };
|
this.onTrackEvent = function (data) { Logger.log(`OnTrack event peer with data:${data}`); };
|
||||||
this.onAddChannel = function (data) { Logger.log(`onAddChannel event peer with data:${data}`); };
|
this.onAddChannel = function (data) { Logger.log(`onAddChannel event peer with data:${data}`); };
|
||||||
|
this.onMessage = function (data) { Logger.log(`On message: ${data}`); };
|
||||||
this._config = config;
|
this._config = config;
|
||||||
this._signaling = signaling;
|
this._signaling = signaling;
|
||||||
this._signaling.addEventListener('connect', this._onConnect.bind(this));
|
this._signaling.addEventListener('connect', this._onConnect.bind(this));
|
||||||
@@ -30,6 +30,7 @@ export class RenderStreaming {
|
|||||||
this._signaling.addEventListener('offer', this._onOffer.bind(this));
|
this._signaling.addEventListener('offer', this._onOffer.bind(this));
|
||||||
this._signaling.addEventListener('answer', this._onAnswer.bind(this));
|
this._signaling.addEventListener('answer', this._onAnswer.bind(this));
|
||||||
this._signaling.addEventListener('candidate', this._onIceCandidate.bind(this));
|
this._signaling.addEventListener('candidate', this._onIceCandidate.bind(this));
|
||||||
|
this._signaling.addEventListener('on-message', this._onMessage.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onConnect(e) {
|
async _onConnect(e) {
|
||||||
@@ -85,7 +86,11 @@ export class RenderStreaming {
|
|||||||
await this._peer.onGotCandidate(candidate.connectionId, iceCandidate);
|
await this._peer.onGotCandidate(candidate.connectionId, iceCandidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 在 RenderStreaming 类中添加
|
||||||
|
async _onMessage(e) {
|
||||||
|
const data = e.detail;
|
||||||
|
this.onMessage(data);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* if not set argument, a generated uuid is used.
|
* if not set argument, a generated uuid is used.
|
||||||
* @param {string | null} connectionId
|
* @param {string | null} connectionId
|
||||||
@@ -98,6 +103,7 @@ export class RenderStreaming {
|
|||||||
async deleteConnection() {
|
async deleteConnection() {
|
||||||
await this._signaling.deleteConnection(this._connectionId);
|
await this._signaling.deleteConnection(this._connectionId);
|
||||||
}
|
}
|
||||||
|
// 在 RenderStreaming 类中添加
|
||||||
|
|
||||||
_preparePeerConnection(connectionId, polite) {
|
_preparePeerConnection(connectionId, polite) {
|
||||||
if (this._peer) {
|
if (this._peer) {
|
||||||
@@ -182,6 +188,11 @@ export class RenderStreaming {
|
|||||||
return this._peer.getTransceivers(this._connectionId);
|
return this._peer.getTransceivers(this._connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendMessage(message) {
|
||||||
|
if (this._signaling && this._connectionId) {
|
||||||
|
this._signaling.sendMessage(this._connectionId, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
async start() {
|
async start() {
|
||||||
await this._signaling.start();
|
await this._signaling.start();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,17 +18,17 @@ export class Signaling extends EventTarget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url(method, parameter='') {
|
url(method, parameter = '') {
|
||||||
let ret = location.origin + '/signaling';
|
let ret = location.origin + '/signaling';
|
||||||
if(method)
|
if (method)
|
||||||
ret += '/' + method;
|
ret += '/' + method;
|
||||||
if(parameter)
|
if (parameter)
|
||||||
ret += '?' + parameter;
|
ret += '?' + parameter;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
if(this.running) {
|
if (this.running) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ export class Signaling extends EventTarget {
|
|||||||
|
|
||||||
const messages = data.messages;
|
const messages = data.messages;
|
||||||
|
|
||||||
for(const msg of messages) {
|
for (const msg of messages) {
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case "connect":
|
case "connect":
|
||||||
break;
|
break;
|
||||||
@@ -63,14 +63,17 @@ export class Signaling extends EventTarget {
|
|||||||
this.dispatchEvent(new CustomEvent('disconnect', { detail: msg }));
|
this.dispatchEvent(new CustomEvent('disconnect', { detail: msg }));
|
||||||
break;
|
break;
|
||||||
case "offer":
|
case "offer":
|
||||||
this.dispatchEvent(new CustomEvent('offer', { detail: msg } ));
|
this.dispatchEvent(new CustomEvent('offer', { detail: msg }));
|
||||||
break;
|
break;
|
||||||
case "answer":
|
case "answer":
|
||||||
this.dispatchEvent(new CustomEvent('answer', { detail: msg } ));
|
this.dispatchEvent(new CustomEvent('answer', { detail: msg }));
|
||||||
break;
|
break;
|
||||||
case "candidate":
|
case "candidate":
|
||||||
this.dispatchEvent(new CustomEvent('candidate', { detail: msg }));
|
this.dispatchEvent(new CustomEvent('candidate', { detail: msg }));
|
||||||
break;
|
break;
|
||||||
|
case "on-message":
|
||||||
|
this.dispatchEvent(new CustomEvent('on-message', { detail: msg.data }));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -125,7 +128,14 @@ export class Signaling extends EventTarget {
|
|||||||
Logger.log('sendCandidate:' + data);
|
Logger.log('sendCandidate:' + data);
|
||||||
await fetch(this.url('candidate'), { method: 'POST', headers: this.headers(), body: JSON.stringify(data) });
|
await fetch(this.url('candidate'), { method: 'POST', headers: this.headers(), body: JSON.stringify(data) });
|
||||||
}
|
}
|
||||||
|
// 在 Signaling 类中添加
|
||||||
|
async sendMessage(connectionId, message) {
|
||||||
|
const data = {
|
||||||
|
'message': message,
|
||||||
|
'connectionId': connectionId
|
||||||
|
};
|
||||||
|
await fetch(this.url('on-message'), { method: 'POST', headers: this.headers(), body: JSON.stringify(data) });
|
||||||
|
}
|
||||||
async getAll(fromTime = 0) {
|
async getAll(fromTime = 0) {
|
||||||
return await fetch(this.url(``, `fromtime=${fromTime}`), { method: 'GET', headers: this.headers() });
|
return await fetch(this.url(``, `fromtime=${fromTime}`), { method: 'GET', headers: this.headers() });
|
||||||
}
|
}
|
||||||
@@ -180,6 +190,8 @@ export class WebSocketSignaling extends EventTarget {
|
|||||||
case "candidate":
|
case "candidate":
|
||||||
this.dispatchEvent(new CustomEvent('candidate', { detail: { connectionId: msg.from, candidate: msg.data.candidate, sdpMLineIndex: msg.data.sdpMLineIndex, sdpMid: msg.data.sdpMid } }));
|
this.dispatchEvent(new CustomEvent('candidate', { detail: { connectionId: msg.from, candidate: msg.data.candidate, sdpMLineIndex: msg.data.sdpMLineIndex, sdpMid: msg.data.sdpMid } }));
|
||||||
break;
|
break;
|
||||||
|
case "on-message":
|
||||||
|
this.dispatchEvent(new CustomEvent('on-message', { detail: msg.data }));
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -236,4 +248,15 @@ export class WebSocketSignaling extends EventTarget {
|
|||||||
Logger.log(sendJson);
|
Logger.log(sendJson);
|
||||||
this.websocket.send(sendJson);
|
this.websocket.send(sendJson);
|
||||||
}
|
}
|
||||||
|
// 在 WebSocketSignaling 类中添加
|
||||||
|
sendMessage(connectionId, message) {
|
||||||
|
const data = {
|
||||||
|
'message': message,
|
||||||
|
'senderId': message.senderId,
|
||||||
|
'connectionId': connectionId
|
||||||
|
};
|
||||||
|
const sendJson = JSON.stringify({ type: "on-message", data: data });
|
||||||
|
Logger.log(sendJson);
|
||||||
|
this.websocket.send(sendJson);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ function onCandidate(ws: WebSocket, message: any): void {
|
|||||||
* @param ws WebSocket连接实例
|
* @param ws WebSocket连接实例
|
||||||
* @param message 消息数据
|
* @param message 消息数据
|
||||||
*/
|
*/
|
||||||
function onChatMessage(ws: WebSocket, message: any): void {
|
function onMessage(ws: WebSocket, message: any): void {
|
||||||
// 获取连接ID
|
// 获取连接ID
|
||||||
const connectionId = message.connectionId;
|
const connectionId = message.connectionId;
|
||||||
const chatMessage = message.message;
|
const chatMessage = message.message;
|
||||||
@@ -376,11 +376,11 @@ function onCandidate(ws: WebSocket, message: any): void {
|
|||||||
const otherSessionWs = pair[0] == ws ? pair[1] : pair[0];
|
const otherSessionWs = pair[0] == ws ? pair[1] : pair[0];
|
||||||
if (otherSessionWs) {
|
if (otherSessionWs) {
|
||||||
// 发送chat-message消息
|
// 发送chat-message消息
|
||||||
otherSessionWs.send(JSON.stringify({ from: connectionId, to: "", type: "chat-message", data: chatMessage }));
|
otherSessionWs.send(JSON.stringify({ from: connectionId, to: "", type: "on-message", data: chatMessage }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 导出WebSocket处理器函数
|
* 导出WebSocket处理器函数
|
||||||
*/
|
*/
|
||||||
export { reset, add, remove, onConnect, onDisconnect, onOffer, onAnswer, onCandidate, onCallConnectionId, onBroadcast, onGetAllConnectionIds, AddHeartbeat, RemoveHeartbeat ,onChatMessage};
|
export { reset, add, remove, onConnect, onDisconnect, onOffer, onAnswer, onCandidate, onCallConnectionId, onBroadcast, onGetAllConnectionIds, AddHeartbeat, RemoveHeartbeat ,onMessage};
|
||||||
|
|||||||
@@ -108,9 +108,9 @@ export default class WSSignaling {
|
|||||||
// 处理callConnectionId信令
|
// 处理callConnectionId信令
|
||||||
handler.onCallConnectionId(ws, msg.data);
|
handler.onCallConnectionId(ws, msg.data);
|
||||||
break;
|
break;
|
||||||
case 'chat-message'://接受连接ConnectionId
|
case 'on-message'://接受连接ConnectionId
|
||||||
// 处理chat-message信令
|
// 处理chat-message信令
|
||||||
handler.onChatMessage(ws, msg.data);
|
handler.onMessage(ws, msg.data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// 忽略未知消息类型
|
// 忽略未知消息类型
|
||||||
|
|||||||
Reference in New Issue
Block a user