You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
7.2 KiB
239 lines
7.2 KiB
import {Component, Injectable} from '@angular/core';
|
|
import {interval, Subject} from 'rxjs';
|
|
import {NzNotificationService} from 'ng-zorro-antd';
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class WebsocketService {
|
|
|
|
messageSubject; // subject对象,用于发送事件
|
|
private url; // 默认请求的url
|
|
private webSocket: WebSocket; // websocket对象
|
|
connectSuccess = false; // websocket 连接成功
|
|
period = 60 * 1000 * 10; // 10分钟检查一次
|
|
serverTimeoutSubscription = null; // 定时检测连接对象
|
|
reconnectFlag = false; // 重连
|
|
reconnectPeriod = 5 * 1000; // 重连失败,则5秒钟重连一次
|
|
reconnectSubscription = null; // 重连订阅对象
|
|
runTimeSubscription; // 记录运行连接subscription
|
|
runTimePeriod = 60 * 10000; // 记录运行连接时间
|
|
|
|
constructor(private notification: NzNotificationService) {
|
|
this.messageSubject = new Subject();
|
|
console.log('开始心跳检测');
|
|
// 进入程序就进行心跳检测,避免出现开始就连接中断,后续不重连
|
|
this.heartCheckStart();
|
|
this.calcRunTime();
|
|
}
|
|
|
|
/**
|
|
* 发送消息
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
* @param message 发送消息
|
|
*/
|
|
sendMessage(message) {
|
|
this.webSocket.send(message);
|
|
}
|
|
|
|
/**
|
|
* 创建新连接
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
* @param url 要连接的url
|
|
*/
|
|
connect(url) {
|
|
if (!!url) {
|
|
this.url = url;
|
|
}
|
|
// 创建websocket对象
|
|
this.createWebSocket();
|
|
}
|
|
|
|
/**
|
|
* 创建连接
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
*/
|
|
createWebSocket() {
|
|
// 如果没有建立过连接,才建立连接并且添加时间监听
|
|
this.webSocket = new WebSocket(this.url);
|
|
// 建立连接成功
|
|
this.webSocket.onopen = (e) => this.onOpen(e);
|
|
// 接收到消息
|
|
this.webSocket.onmessage = (e) => this.onMessage(e);
|
|
// 连接关闭
|
|
this.webSocket.onclose = (e) => this.onClose(e);
|
|
// 异常
|
|
this.webSocket.onerror = (e) => this.onError(e);
|
|
}
|
|
|
|
/**
|
|
* 连接打开
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
* @param e 打开事件
|
|
*/
|
|
onOpen(e) {
|
|
console.log('websocket 已连接');
|
|
// 设置连接成功
|
|
this.connectSuccess = true;
|
|
// 如果是重连中
|
|
if (this.reconnectFlag) {
|
|
// 1.停止重连
|
|
this.stopReconnect();
|
|
// 2.重新开启心跳
|
|
this.heartCheckStart();
|
|
// 3.重新开始计算运行时间
|
|
this.calcRunTime();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 接受到消息
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
* @param event 接受消息事件
|
|
*/
|
|
onMessage(event) {
|
|
const data = JSON.parse(event.data);
|
|
// 将接受到的消息发布出去
|
|
// console.log('接收到消息时间', new Date().getTime());
|
|
this.notification.success(
|
|
data['order']['gasName'] + '加油订单',
|
|
'<p>订单号:' + data['order']['orderNo'] + '</p>' +
|
|
'<p>加油金额:' + data['order']['totalPrice'] + '</p>' +
|
|
'<p>油号:' + data['order']['gasOilNo'] + '</p>' +
|
|
'<p>油枪号:' + data['order']['gasGunNo'] + '</p>'
|
|
);
|
|
const audio = new Audio();
|
|
audio.src = data['voice'];
|
|
audio.load();
|
|
audio.play().then(r => console.log(r));
|
|
this.messageSubject.next(true);
|
|
}
|
|
|
|
/**
|
|
* 连接关闭
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
*/
|
|
private onClose(e) {
|
|
console.log('连接关闭', e);
|
|
this.connectSuccess = false;
|
|
this.webSocket.close();
|
|
// 关闭时开始重连
|
|
this.reconnect();
|
|
this.stopRunTime();
|
|
// throw new Error('webSocket connection closed:)');
|
|
}
|
|
|
|
/**
|
|
* 连接异常
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
*/
|
|
private onError(e) {
|
|
// 出现异常时一定会进onClose,所以只在onClose做一次重连动作
|
|
console.log('连接异常', e);
|
|
this.connectSuccess = false;
|
|
// throw new Error('webSocket connection error:)');
|
|
}
|
|
|
|
/**
|
|
* 开始重新连接
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
*/
|
|
reconnect() {
|
|
// 如果已重连,则直接return,避免重复连接
|
|
if (this.connectSuccess) {
|
|
this.stopReconnect();
|
|
console.log('已经连接成功,停止重连');
|
|
return;
|
|
}
|
|
// 如果正在连接中,则直接return,避免产生多个轮训事件
|
|
if (this.reconnectFlag) {
|
|
console.log('正在重连,直接返回');
|
|
return;
|
|
}
|
|
// 开始重连
|
|
this.reconnectFlag = true;
|
|
// 如果没能成功连接,则定时重连
|
|
this.reconnectSubscription = interval(this.reconnectPeriod).subscribe(async (val) => {
|
|
console.log(`重连:${val}次`);
|
|
const url = this.url;
|
|
// 重新连接
|
|
this.connect(url);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 停止重连
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
*/
|
|
stopReconnect() {
|
|
// 连接标识置为false
|
|
this.reconnectFlag = false;
|
|
// 取消订阅
|
|
if (typeof this.reconnectSubscription !== 'undefined' && this.reconnectSubscription != null) {
|
|
this.reconnectSubscription.unsubscribe();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 开始心跳检测
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
*/
|
|
heartCheckStart() {
|
|
this.serverTimeoutSubscription = interval(this.period).subscribe((val) => {
|
|
// 保持连接状态,重置下
|
|
if (this.webSocket != null && this.webSocket.readyState === 1) {
|
|
console.log(val, '连接状态,发送消息保持连接');
|
|
} else {
|
|
// 停止心跳
|
|
this.heartCheckStop();
|
|
// 开始重连
|
|
this.reconnect();
|
|
console.log('连接已断开,重新连接');
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 停止心跳检测
|
|
* @author Sum1Dream
|
|
* @date 2019/1/22
|
|
*/
|
|
heartCheckStop() {
|
|
// 取消订阅停止心跳
|
|
if (typeof this.serverTimeoutSubscription !== 'undefined' && this.serverTimeoutSubscription != null) {
|
|
this.serverTimeoutSubscription.unsubscribe();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 开始计算运行时间
|
|
* @author Sum1Dream
|
|
* @date 2019/1/25
|
|
*/
|
|
calcRunTime() {
|
|
this.runTimeSubscription = interval(this.runTimePeriod).subscribe(period => {
|
|
console.log('运行时间', `${period}分钟`);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 停止计算运行时间
|
|
* @author Sum1Dream
|
|
* @date 2019/1/25
|
|
*/
|
|
stopRunTime() {
|
|
if (typeof this.runTimeSubscription !== 'undefined' && this.runTimeSubscription !== null) {
|
|
this.runTimeSubscription.unsubscribe();
|
|
}
|
|
}
|
|
}
|
|
|