Initial commit
This commit is contained in:
222
src/main/utils/WebSocketClient.js
Normal file
222
src/main/utils/WebSocketClient.js
Normal file
@@ -0,0 +1,222 @@
|
||||
import WebSocket from 'ws';
|
||||
import logger from './logger'
|
||||
import { getStoreValue } from '../store.js'
|
||||
|
||||
import { Notification } from "electron";
|
||||
|
||||
class WebSocketClient {
|
||||
constructor(options = {}) {
|
||||
this.reconnectInterval = 5000; // 重连间隔时间
|
||||
this.lockReconnect = false;
|
||||
this.ws = null;
|
||||
this.pingTimeout = null;
|
||||
this.reconnectAttempts = 0;
|
||||
this.messageHandlers = new Map();
|
||||
this.isConnected = false;
|
||||
|
||||
// 初始化时立即创建连接
|
||||
this.createConnect();
|
||||
}
|
||||
|
||||
createConnect() {
|
||||
try {
|
||||
const apiUrl = getStoreValue("apiUrl");
|
||||
const userInfo = getStoreValue("userInfo");
|
||||
const token = getStoreValue("token");
|
||||
|
||||
// 检查必要的连接信息是否存在
|
||||
if (!apiUrl || !userInfo || !token) {
|
||||
logger.error("WebSocket连接信息不完整,等待重试");
|
||||
logger.error("apiUrl:", apiUrl);
|
||||
logger.error("userInfo:", userInfo);
|
||||
logger.error("token:", token);
|
||||
this.scheduleReconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 处理基础URL
|
||||
let baseUrl = apiUrl.replace("https://", "wss://").replace("http://", "ws://");
|
||||
// 移除末尾的斜杠(如果有)
|
||||
baseUrl = baseUrl.replace(/\/$/, '');
|
||||
|
||||
// 构建完整的WebSocket URL
|
||||
this.url = `${baseUrl}/bqw-ai/websocket/${userInfo.id}`;
|
||||
// this.url = `${baseUrl}/bqw-ai/${userInfo.id}`;
|
||||
|
||||
logger.info("==================== WebSocketClient create WebSocketClient");
|
||||
logger.info("WebSocket URL: " + this.url);
|
||||
|
||||
// 设置WebSocket选项
|
||||
this.options = {
|
||||
headers: {
|
||||
'User-Agent': 'WebSocketClient',
|
||||
'Connection': 'Upgrade',
|
||||
'Upgrade': 'websocket',
|
||||
'Sec-WebSocket-Version': '13'
|
||||
},
|
||||
handshakeTimeout: 10000,
|
||||
perMessageDeflate: false,
|
||||
followRedirects: true,
|
||||
rejectUnauthorized: false
|
||||
};
|
||||
|
||||
logger.info("Token:", token); // 添加token日志
|
||||
// 创建连接
|
||||
this.connect();
|
||||
} catch (error) {
|
||||
logger.error("创建WebSocket连接时发生错误:", error);
|
||||
this.scheduleReconnect();
|
||||
}
|
||||
}
|
||||
|
||||
scheduleReconnect() {
|
||||
if (this.lockReconnect) return;
|
||||
|
||||
this.lockReconnect = true;
|
||||
logger.info("==================== WebSocketClient schedule reconnect");
|
||||
|
||||
setTimeout(() => {
|
||||
this.lockReconnect = false;
|
||||
this.createConnect(); // 重新获取本地缓存并创建连接
|
||||
}, this.reconnectInterval);
|
||||
}
|
||||
|
||||
connect() {
|
||||
logger.info("==================== WebSocketClient begin connect");
|
||||
if (this.lockReconnect) return;
|
||||
|
||||
try {
|
||||
const token = getStoreValue("token");
|
||||
// 直接在构造函数中传递协议
|
||||
this.ws = new WebSocket(this.url, token, this.options);
|
||||
|
||||
this.ws.on('open', () => {
|
||||
logger.info('😀😀😀😀 WebSocket connect create ok 😀😀😀😀');
|
||||
logger.info('😀😀😀😀 WebSocket connect create ok 😀😀😀😀');
|
||||
logger.info('😀😀😀😀 WebSocket connect create ok 😀😀😀😀');
|
||||
logger.info('WebSocket protocol:', this.ws.protocol); // 添加协议日志
|
||||
this.isConnected = true;
|
||||
this.reconnectAttempts = 0;
|
||||
this.lockReconnect = false;
|
||||
this.startHeartbeat();
|
||||
this.emit('open');
|
||||
});
|
||||
|
||||
this.ws.on('message', (data) => {
|
||||
try {
|
||||
logger.info('收到消息:', data.toString());
|
||||
const message = JSON.parse(data);
|
||||
this.handleMessage(message);
|
||||
} catch (error) {
|
||||
logger.error('消息解析错误:', error);
|
||||
}
|
||||
});
|
||||
|
||||
this.ws.on('close', (code, reason) => {
|
||||
logger.info(`WebSocket连接已关闭,代码: ${code}, 原因: ${reason}`);
|
||||
this.isConnected = false;
|
||||
this.stopHeartbeat();
|
||||
this.emit('close', { code, reason });
|
||||
this.scheduleReconnect();
|
||||
});
|
||||
|
||||
this.ws.on('error', (error) => {
|
||||
logger.error('WebSocket error:', error);
|
||||
this.emit('error', error);
|
||||
this.scheduleReconnect();
|
||||
});
|
||||
|
||||
this.ws.on('unexpected-response', (request, response) => {
|
||||
logger.info(`收到响应: ${response.statusCode} ${response.statusMessage}`);
|
||||
logger.info('响应头:', response.headers);
|
||||
if (response.statusCode === 101) {
|
||||
logger.info('WebSocket升级成功');
|
||||
return;
|
||||
}
|
||||
this.scheduleReconnect();
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
logger.error('WebSocket connect error:', error);
|
||||
this.scheduleReconnect();
|
||||
}
|
||||
}
|
||||
|
||||
startHeartbeat() {
|
||||
this.pingTimeout = setInterval(() => {
|
||||
if (this.isConnected) {
|
||||
this.ws.send("heartcheck");
|
||||
}
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
stopHeartbeat() {
|
||||
if (this.pingTimeout) {
|
||||
clearInterval(this.pingTimeout);
|
||||
this.pingTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
send(message) {
|
||||
if (!this.isConnected) {
|
||||
console.error('WebSocket未连接');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = typeof message === 'string' ? message : JSON.stringify(message);
|
||||
this.ws.send(data);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('发送消息失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
on(event, handler) {
|
||||
if (!this.messageHandlers.has(event)) {
|
||||
this.messageHandlers.set(event, new Set());
|
||||
}
|
||||
this.messageHandlers.get(event).add(handler);
|
||||
}
|
||||
|
||||
off(event, handler) {
|
||||
if (this.messageHandlers.has(event)) {
|
||||
this.messageHandlers.get(event).delete(handler);
|
||||
}
|
||||
}
|
||||
|
||||
emit(event, data) {
|
||||
if (this.messageHandlers.has(event)) {
|
||||
this.messageHandlers.get(event).forEach(handler => {
|
||||
try {
|
||||
handler(data);
|
||||
} catch (error) {
|
||||
console.error(`事件处理器错误 (${event}):`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleMessage(message) {
|
||||
if (message.cmd==="Notification") {
|
||||
logger.info("Notification:", message)
|
||||
const msg=JSON.parse(message.msgTxt)
|
||||
// systemMsgType
|
||||
const isNotification = getStoreValue("Notification_"+msg.systemMsgType);
|
||||
if (isNotification!=0){
|
||||
new Notification({ title: msg.title, body: msg.content }).show()
|
||||
}
|
||||
}
|
||||
this.emit('message', message);
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.ws) {
|
||||
this.ws.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default WebSocketClient;
|
||||
Reference in New Issue
Block a user