2023-07-04 15:58:32 +08:00

261 lines
7.3 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:common_utils/common_utils.dart';
import 'package:crypto/crypto.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
import './Message.pb.dart' as messages;
import './ReplyBody.pb.dart' as replybody;
import './SentBody.pb.dart' as sentbody;
import 'package:fixnum/fixnum.dart';
import 'package:convert/convert.dart';
//PONG
// ignore: constant_identifier_names
const PONG_TYPE = 0;
//发送消息类型
// ignore: constant_identifier_names
const Message_TYPE = 2;
//强制下线类型
// ignore: constant_identifier_names
const ACTION_999 = 999;
//响应消息类型
// ignore: constant_identifier_names
const REPLY_BODY = 4;
//消息发送
// ignore: constant_identifier_names
const SEND_BODY = 3;
//PING
// ignore: constant_identifier_names
const PING_TYPE = 1;
// ignore: constant_identifier_names
const DATA_HEADER_LENGTH = 1;
const sOCKETAPPVERSION = '100';
class CIMSocket extends ChangeNotifier {
late Socket? socket;
late String? uri;
late int? port;
late int? uid;
late String endCode = "0";
final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
late TimerUtil timer = TimerUtil()
..mTotalTime = 10000
..setOnTimerTickCallback((millisUntilFinished) {
if (millisUntilFinished == 0 && uid != null) {
connect();
}
});
late bool isConnected = false;
late messages.Model? _model = null;
messages.Model? get model => _model;
Future init(String uri, int port, int uid) async {
this.uri = uri;
this.port = port;
this.uid = uid;
}
//登录
Future connect() async {
if (uri == null || port == null || uid == null) {
throw IOException;
}
Socket.connect(uri, port!).then((Socket sock) {
sock.listen((data) async {
int l = (data[1] & 0xff);
int h = (data[2] & 0xff);
int length = (l | h << 8);
if (data[0] == PING_TYPE) {
sendPong();
} else if (data[0] == REPLY_BODY) {
var message = data.sublist(3, length + 3);
replybody.Model info = replybody.Model();
info.mergeFromBuffer(message);
} else if (data[0] == Message_TYPE) {
var message = data.sublist(3, length + 3);
messages.Model model = messages.Model();
model.mergeFromBuffer(message);
switchMessage(model);
}
}, onError: (error, StackTrace trace) {
socket = null;
isConnected = false;
if (!timer.isActive()) {
timer.setTotalTime(12000);
timer.startCountDown();
}
notifyListeners();
}, onDone: () {
socket = null;
isConnected = false;
notifyListeners();
if (endCode != "999") {
timer.setTotalTime(12000);
timer.startCountDown();
}
}, cancelOnError: true);
socket = sock;
sendLoginMsg();
}).catchError((e) {
socket = null;
isConnected = false;
notifyListeners();
timer.setTotalTime(12000);
timer.startCountDown();
});
}
//登出
Future disConnect() async {
if (socket != null) {
endCode = '999';
await socket!.close();
}
}
//发送登录消息
Future sendLoginMsg() async {
SystemInfo systemInfo = SystemInfo();
await systemInfo.init();
String deviceName = systemInfo.deviceName;
// DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
String channel = systemInfo.deviceName;
String systemVersion = systemInfo.version;
String deviceId = hex.encode(
md5.convert(const Utf8Encoder().convert(systemInfo.deviceId)).bytes);
Map<String, String> map = {
"uid": uid.toString(), //主id
"channel": channel,
"appVersion": sOCKETAPPVERSION,
"osVersion": systemVersion,
"packageName": "cn.asihe.cim",
"deviceId": deviceId,
// (await PlatformDeviceId.getDeviceId)!.replaceAll("-", ""), //应用id
"deviceName": '$deviceName ${systemInfo.model}',
"language": "zh-CN",
};
int time = DateTime.now().millisecondsSinceEpoch;
Int64 timeStamp = Int64.parseInt(time.toString());
var body = sentbody.Model(data: map);
body.key = "client_bind";
body.timestamp = timeStamp;
var data = body.writeToBuffer();
var protobuf = Uint8List(data.length + 3);
protobuf[0] = 3;
protobuf[1] = (data.length & 0xff);
protobuf[2] = ((data.length >> 8) & 0xff);
protobuf.setRange(3, data.length + 3, data);
socket!.add(protobuf);
await socket!.flush();
isConnected = true;
if (timer.isActive()) {
timer.cancel();
}
notifyListeners();
}
/// 发送群组聊天 tag
Future<int> sendTag(String tag) async {
Map<String, String> map1 = {"tag": tag};
int time = DateTime.now().millisecondsSinceEpoch;
Int64 timeStamp = Int64.parseInt(time.toString());
var body = sentbody.Model(data: map1);
body.key = "client_set_tag";
body.timestamp = timeStamp;
var data = body.writeToBuffer();
var protobuf = Uint8List(data.length + 3);
protobuf[0] = 3;
protobuf[1] = (data.length & 0xff);
protobuf[2] = ((data.length >> 8) & 0xff);
protobuf.setRange(3, data.length + 3, data);
socket!.add(protobuf);
await socket!.flush();
return 2;
}
//发送PONG响应
Future sendPong() async {
var pONG = Uint8List(7);
var pONGBODY = Uint8List(4);
pONGBODY[0] = 80;
pONGBODY[1] = 79;
pONGBODY[2] = 78;
pONGBODY[3] = 71;
pONG[0] = PONG_TYPE;
pONG[1] = (pONGBODY.length & 0xff);
pONG[2] = ((pONGBODY.length >> 8) & 0xff);
pONG.setRange(3, 6, pONGBODY);
socket!.add(pONG);
await socket!.flush();
isConnected = true;
if (timer.isActive()) {
timer.cancel();
}
notifyListeners();
}
///消息分发器
Future switchMessage(messages.Model model) async {
_model = model;
notifyListeners();
}
}
class SystemInfo {
String deviceName = 'cim_entity';
String version = '0.0.1';
String deviceId = 'CIM Entity';
String model = "10";
final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
Future init() async {
if (Platform.isAndroid) {
// Android相关代码
var value = await deviceInfoPlugin.androidInfo;
deviceName = 'android';
version = value.version.release;
deviceId = value.id;
model = value.model;
} else if (Platform.isIOS) {
// iOS相关代码
var value = await deviceInfoPlugin.iosInfo;
deviceName = 'ios';
version = value.systemVersion!;
deviceId = value.identifierForVendor!;
model = value.model!;
} else if (Platform.isMacOS) {
// MacOS相关代码
var value = await deviceInfoPlugin.macOsInfo;
deviceName = 'macos';
version = value.kernelVersion;
deviceId = value.model;
model = value.model;
} else if (Platform.isWindows) {
// Windows相关代码
var value = await deviceInfoPlugin.windowsInfo;
deviceName = 'windows';
version = value.displayVersion;
deviceId = value.deviceId;
model = value.majorVersion.toString();
} else if (Platform.isLinux) {
// Linux相关代码
var value = await deviceInfoPlugin.linuxInfo;
deviceName = 'linux';
version = value.version!;
deviceId = value.id;
model = value.version!;
}
}
}