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.

210 lines
4.8 KiB

import 'dart:async';
3 years ago
import 'package:bot_toast/bot_toast.dart';
import 'package:power_logger/power_logger.dart';
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
3 years ago
const String baseUri = 'wss://shop.kaidalai.cn/websocket/butlerApp';
enum SOCKETSTATUS {
CONNECTED, //已连接
BREAKOFF, //已断开
CLOSED, //已关闭
}
class WebSocketUtil {
static final WebSocketUtil _socket = WebSocketUtil._();
//内部构造函数
WebSocketUtil._();
//单例模式
factory WebSocketUtil() => _socket;
IOWebSocketChannel? _webSocket;
///用户设置不同的服务器地址
String _user = 'admin';
///连接状态
SOCKETSTATUS _socketStatus = SOCKETSTATUS.CLOSED;
///心跳计时器;
Timer? _heartTimer;
///心跳间隔
Duration _heartDuration = Duration(seconds: 30);
///重连计数器
int _reconnectCount = 0;
///重连最大次数
int _reconnectTimes = 30;
///重连计时器
Timer? _reconnectTimer;
///连接错误回调
Function(dynamic e)? onError;
///开启回调
Function? onStart;
///接收消息回调
Function(String message)? onReceiveMes;
///关闭连接回调;
Function? onClosed;
///控制台输出
bool _consolePrint = true;
///注册websocket
void initWebSocket(
{Duration? heartDuration,
bool? consolePrint,
Function? onStart,
Function(String message)? onReceiveMes,
Function? onClosed,
Function(dynamic e)? onError}) {
this.onStart = onStart;
this.onReceiveMes = onReceiveMes;
this.onClosed = onClosed;
this.onError = onError;
if (consolePrint != null) {
this._consolePrint = consolePrint;
}
if (heartDuration != null) {
this._heartDuration = heartDuration;
}
print('——————————webSocket init ——————————');
}
///设置用户
void setUser(String user) {
this._user = user;
}
///开启websocket
void startWebSocket() {
closeWebSocket();
try {
_webSocket = IOWebSocketChannel.connect(Uri.parse('$baseUri/$_user'));
print('webSocket已连接服务器$baseUri/$_user');
_socketStatus = SOCKETSTATUS.CONNECTED;
endReconnect();
onStart?.call();
_webSocket!.stream.listen(
(event) => webSocketReceiveMessage(event as String),
onError: webSocketOnError,
onDone: webSocketClosed);
initHeartBeat();
} catch (e) {
BotToast.showText(text: 'webSocket连接失败');
onError?.call(e);
LoggerData.addData(e);
}
}
//接收消息回调
webSocketReceiveMessage(message) {
if (message == '心跳正常') {
_dPrint('心跳正常————————${DateTime.now()}');
} else {
onReceiveMes?.call(message);
}
}
//关闭连接回调
webSocketClosed() {
closeWebSocket();
onClosed?.call();
}
//连接出错回调
webSocketOnError(e) {
WebSocketChannelException ex = e;
_socketStatus = SOCKETSTATUS.BREAKOFF;
onError?.call(ex.message);
print('——————连接断开,开始重连');
startReconnect();
}
//启动重连计时
void startReconnect() {
endReconnect();
_reconnectTimer = Timer.periodic(Duration(milliseconds: 5000), (timer) {
_reconnectCount++;
print('——————第${_reconnectCount}次重连');
startWebSocket();
if (_reconnectCount >= _reconnectTimes) {
print('——————重连失败');
closeWebSocket();
}
});
}
//重置重连计时
void endReconnect() {
_reconnectTimer?.cancel();
_reconnectTimer = null;
_reconnectCount = 0;
}
///初始化心跳
void initHeartBeat() {
destoryHeart();
_heartTimer = Timer.periodic(_heartDuration, (timer) {
sentHeart();
});
}
//发送心跳
void sentHeart() {
sendMessage('heartbeat');
}
///销毁心跳
void destoryHeart() {
_heartTimer?.cancel();
_heartTimer = null;
}
///关闭websocket
void closeWebSocket() {
if (_webSocket != null) {
_webSocket!.sink.close();
print('——————websocket连接已关闭');
}
endReconnect();
destoryHeart();
_socketStatus = SOCKETSTATUS.CLOSED;
}
///向websocket服务器发送消息
void sendMessage(message) {
if (_webSocket != null) {
switch (_socketStatus) {
case SOCKETSTATUS.CONNECTED:
_dPrint('发送中:' + message);
_webSocket!.sink.add(message);
break;
case SOCKETSTATUS.CLOSED:
print('连接已关闭');
break;
case SOCKETSTATUS.BREAKOFF:
print('发送失败');
break;
default:
break;
}
}
}
//封装print
void _dPrint(dynamic data) {
if (this._consolePrint) {
print(data);
}
}
}