2024-01-11 15:14:02 +08:00

777 lines
26 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import '../../../app_settings/app_colors.dart';
import '../../../blue/blue_manage.dart';
import '../../../blue/io_protocol/io_addUser.dart';
import '../../../blue/io_protocol/io_getStarLockStatusInfo.dart';
import '../../../blue/io_protocol/io_openLock.dart';
import '../../../blue/io_protocol/io_referEventRecordTime.dart';
import '../../../blue/io_reply.dart';
import '../../../blue/io_tool/io_tool.dart';
import '../../../blue/io_tool/manager_event_bus.dart';
import '../../../blue/sender_manage.dart';
import '../../../network/api_repository.dart';
import '../../../tools/baseGetXController.dart';
import '../../../tools/eventBusEventManage.dart';
import '../../../tools/storage.dart';
import '../electronicKey/electronicKeyDetail/keyOperationRecordEntity.dart';
import '../lockOperatingRecord/lockOperatingRecordGetLastRecordTime_entity.dart';
import 'lockDetail_state.dart';
import 'lockNetToken_entity.dart';
class LockDetailLogic extends BaseGetXController {
final LockDetailState state = LockDetailState();
// 监听设备返回的数据
late StreamSubscription<Reply> _replySubscription;
void _initReplySubscription() {
_replySubscription =
EventBusManager().eventBus!.on<Reply>().listen((reply) async {
// 开门
if (reply is OpenDoorReply) {
_replyOpenLock(reply);
}
// 编辑锁用户
// if(reply is EditUserReply){
// _replyEditUserKey(reply);
// }
// 获取星锁状态信息
if (reply is GetStarLockStatuInfoReply) {
_replyGetStarLockStatusInfo(reply);
}
// 开完锁之后上传记录
if (reply is SenderReferEventRecordTimeReply) {
_replyReferEventRecordTime(reply);
}
// 添加用户
if (reply is AddUserReply) {
_replyAddUserKey(reply);
}
});
}
// 开门数据解析
Future<void> _replyOpenLock(Reply reply) async {
int status = reply.data[6];
print("status:$status");
switch (status) {
case 0x00:
//成功
print("${reply.commandType}数据解析成功");
// _showFullScreenOverlay(Get.context!);
state.iSClosedUnlockSuccessfulPopup.value = true;
if(state.closedUnlockSuccessfulTimer != null){
state.closedUnlockSuccessfulTimer!.cancel();
state.closedUnlockSuccessfulTimer = null;
}
// 如果没有点击关闭弹窗3秒后自动关闭
state.closedUnlockSuccessfulTimer = Timer.periodic(3.seconds, (timer) {
state.iSClosedUnlockSuccessfulPopup.value = false;
timer.cancel();
});
// Future.delayed(const Duration(seconds: 3), () {
// state.iSClosedUnlockSuccessfulPopup.value = false;
// });
// 电量
int power = reply.data[7];
state.electricQuantity.value = power;
cancelBlueConnetctToastTimer();
getLockRecordLastUploadDataTime();
state.openLockBtnState.value = 0;
// state.animationController.reset();
// state.animationController.forward();
break;
case 0x06:
//无权限
print("${reply.commandType}需要鉴权");
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var signKey = await Storage.getStringList(saveBlueSignKey);
List<int> signKeyDataList = changeStringListToIntList(signKey!);
var tokenData = reply.data.sublist(2, 6);
var saveStrList = changeIntListToStringList(tokenData);
Storage.setStringList(saveBlueToken, saveStrList);
print("openDoorToken:$tokenData");
IoSenderManage.senderOpenLock(
keyID: BlueManage().connectDeviceName,
userID: await Storage.getUid(),
openMode: 1,
openTime: DateTime.now().millisecondsSinceEpoch ~/ 1000,
onlineToken: state.lockNetToken,
token: tokenData,
needAuthor: 1,
signKey: signKeyDataList,
privateKey: getPrivateKeyList,
);
break;
case 0x07:
//无权限
print("${reply.commandType}用户无权限");
break;
case 0x09:
// 权限校验错误
print("${reply.commandType}校验错误");
break;
default:
//失败
print("${reply.commandType}失败");
break;
}
}
// 获取锁状态数据解析
Future<void> _replyGetStarLockStatusInfo(Reply reply) async {
int status = reply.data[2];
switch (status) {
case 0x00:
//成功
print("${reply.commandType}数据解析成功");
// 厂商名称
var vendor = reply.data.sublist(3, 23);
// print("vendor:$vendor");
// 锁设备类型
var product = reply.data[23];
// print("product:$product");
// 产品名称
var model = reply.data.sublist(24, 44);
// print("model:$model");
// 软件版本
var fwVersion = reply.data.sublist(44, 64);
// print("fwVersion:$fwVersion");
// 硬件版本
var hwVersion = reply.data.sublist(64, 84);
// print("hwVersion:$hwVersion");
// 厂商序列号
var serialNum0 = reply.data.sublist(84, 100);
// print("serialNum0:$serialNum0");
// 成品商序列号
var serialNum1 = reply.data.sublist(100, 116);
// print("serialNum1:$serialNum1");
// 蓝牙名称
var btDeviceName = reply.data.sublist(116, 132);
// print("btDeviceName:$btDeviceName");
// 电池剩余电量
var battRemCap = reply.data[132];
// print("battRemCap:$battRemCap");
// 重置次数
var restoreCounter = reply.data.sublist(133, 135);
// print("restoreCounter:$restoreCounter");
// 重置时间
var restoreDate = reply.data.sublist(135, 139);
// print("restoreDate:$restoreDate");
// 主控芯片型号
var icPartNo = reply.data.sublist(139, 149);
// print("icPartNo:$icPartNo");
// 有效时间
var indate = reply.data.sublist(149, 153);
// print("indate:$indate");
break;
case 0x06:
//无权限
print("${reply.commandType}需要鉴权");
break;
case 0x07:
//无权限
print("${reply.commandType}用户无权限");
break;
case 0x09:
// 权限校验错误
print("${reply.commandType}权限校验错误");
break;
default:
//失败
print("${reply.commandType}失败");
break;
}
}
// 根据时间查解析数据
Future<void> _replyReferEventRecordTime(Reply reply) async {
int status = reply.data[2];
switch (status) {
case 0x00:
//成功
print("${reply.commandType}数据解析成功");
if (reply.data[5] > 0) {
reply.data.removeRange(0, 6);
// 把得到的数据按8位分割成数组 然后塞进一个新的数组里面
var getList = splitList(reply.data, 8);
// print("getList:$getList");
var uploadList = [];
for (int i = 0; i < getList.length; i++) {
var indexList = getList[i];
// print("indexList:$indexList");
var indexMap = {};
indexMap["seq"] = indexList[0].toString();
indexMap["user"] = indexList[3].toString();
indexMap["pwd"] = indexList[2].toString();
indexMap["success"] = "1";
indexMap["type"] = indexList[1].toString();
int value = ((0xff & indexList[(4)]) << 24 |
(0xff & indexList[5]) << 16 |
(0xff & indexList[6]) << 8 |
(0xFF & indexList[7]));
// indexMap["date"] = DateTool().dateToYMDHNSString("$value");
// print("value${DateTool().dateToYMDHNSString("$value")}");
indexMap["date"] = "${value * 1000}";
uploadList.add(indexMap);
}
lockRecordUploadData(uploadList);
// print("reply.data:${reply.data} getList:$getList}");
}
break;
case 0x06:
//无权限
print("${reply.commandType}需要鉴权");
break;
case 0x07:
//无权限
print("${reply.commandType}用户无权限");
break;
case 0x09:
// 权限校验错误
print("${reply.commandType}权限校验错误");
break;
default:
//失败
print("${reply.commandType}失败");
break;
}
}
// 添加用户
Future<void> _replyAddUserKey(Reply reply) async {
var lockId = reply.data.sublist(2, 42);
// print("lockId:$lockId");
var token = reply.data.sublist(42, 46);
List<String> strTokenList = changeIntListToStringList(token);
Storage.setStringList(saveBlueToken, strTokenList);
// print("token:$token");
int status = reply.data[46];
// print("status:$status reply.data:${reply.data}");
print("status:$status");
switch (status) {
case 0x00:
//成功
print("添加用户数据解析成功");
state.lockUserNo = reply.data[47] + 1;
// updateLockUserNo();
if (state.isOpenLockNeedOnline.value == 0) {
openDoorAction(1);
} else {
getLockNetToken();
}
break;
case 0x06:
//无权限
print("需要鉴权");
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var publicKey = await Storage.getStringList(saveBluePublicKey);
List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
IoSenderManage.senderAddUser(
lockID: BlueManage().connectDeviceName,
authUserID: state.senderUserId.toString(),
keyID: state.keyInfos.value.keyId.toString(),
userID: await Storage.getUid(),
openMode: 1,
keyType: 0,
startDate: DateTime.now().millisecondsSinceEpoch,
expireDate: 0x11223344,
role: 0,
password: "123456",
needAuthor: 1,
publicKey: publicKeyDataList,
privateKey: getPrivateKeyList,
token: token);
break;
case 0x07:
//无权限
print("用户无权限");
break;
case 0x09:
// 权限校验错误
print("添加用户权限校验错误");
break;
default:
//失败
print("领锁失败");
break;
}
}
// 添加用户(普通用户接收电子钥匙)
Future<void> addUserConnectBlue() async {
showBlueConnetctToastTimer(action:() {
state.openLockBtnState.value = 0;
// state.animationController.reset();
// state.animationController.forward();
});
BlueManage().bludSendData(state.keyInfos.value.bluetooth!.bluetoothDeviceName!, (DeviceConnectionState deviceConnectionState) async {
if (deviceConnectionState == DeviceConnectionState.connected) {
// 私钥
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var publicKey = await Storage.getStringList(saveBluePublicKey);
List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
var token = await Storage.getStringList(saveBlueToken);
List<int> getTokenList = [0, 0, 0, 0];
if (token != null) {
getTokenList = changeStringListToIntList(token);
}
print("BlueManage().connectDeviceName:${BlueManage().connectDeviceName} authUserID:${state.senderUserId.toString()} keyID:${state.keyInfos.value.keyId.toString()} userID:${await Storage.getUid()}");
IoSenderManage.senderAddUser(
lockID: BlueManage().connectDeviceName,
authUserID: state.senderUserId.toString(),
keyID: state.keyInfos.value.keyId.toString(),
userID: await Storage.getUid(),
openMode: 1,
keyType: 0,
startDate: DateTime.now().millisecondsSinceEpoch,
expireDate: 0x11223344,
role: 0,
password: "123456",
needAuthor: 1,
publicKey: publicKeyDataList,
privateKey: getPrivateKeyList,
token: getTokenList);
}else if (deviceConnectionState == DeviceConnectionState.disconnected){
cancelBlueConnetctToastTimer();
if(state.ifCurrentScreen.value == true){
showBlueConnetctToast();
}
state.openLockBtnState.value = 0;
// state.animationController.reset();
// state.animationController.forward();
}
});
}
// 点击开门事件
Future<void> openDoorAction(int openMode) async {
showBlueConnetctToastTimer(action:() {
state.openLockBtnState.value = 0;
BlueManage().stopScan();
// state.animationController.reset();
// state.animationController.forward();
});
BlueManage().bludSendData(state.keyInfos.value.bluetooth!.bluetoothDeviceName!, (DeviceConnectionState deviceConnectionState) async {
if (deviceConnectionState == DeviceConnectionState.connected){
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var signKey = await Storage.getStringList(saveBlueSignKey);
List<int> signKeyDataList = changeStringListToIntList(signKey!);
var token = await Storage.getStringList(saveBlueToken);
List<int> getTokenList = changeStringListToIntList(token!);
print("openDoorTokenPubToken:$getTokenList getPrivateKeyList:$getPrivateKeyList");
IoSenderManage.senderOpenLock(
keyID: BlueManage().connectDeviceName,
userID: await Storage.getUid(),
openMode: openMode,
openTime: DateTime.now().millisecondsSinceEpoch ~/ 1000,
onlineToken: state.lockNetToken,
token: getTokenList,
needAuthor: 1,
signKey: signKeyDataList,
privateKey: getPrivateKeyList,
);
}else if (deviceConnectionState == DeviceConnectionState.disconnected){
cancelBlueConnetctToastTimer();
if(state.ifCurrentScreen.value == true){
showBlueConnetctToast();
}
state.openLockBtnState.value = 0;
// state.animationController.reset();
// state.animationController.forward();
}
});
}
// 编辑用户事件
// Future<void> editLockUserAction() async {
// BlueManage().bludSendData(BlueManage().connectDeviceMacAddress, BlueManage().connectDeviceName, (DeviceConnectionState state) async {
// if (state == DeviceConnectionState.connected){
// var publicKey = await Storage.getStringList(saveBluePublicKey);
// List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
//
// var privateKey = await Storage.getStringList(saveBluePrivateKey);
// List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
//
// var token = await Storage.getStringList(saveBlueToken);
// List<int> getTokenList = changeStringListToIntList(token!);
// print("openDoorTokenPubToken:$getTokenList");
//
// print("publicKey:$publicKey publicKeyDataList:$publicKeyDataList privateKey:$privateKey getPrivateKeyList:$getPrivateKeyList token:$token getTokenList:$getTokenList");
// IoSenderManage.senderEditUser(
// lockID:BlueManage().connectDeviceName,
// authUserID:await Storage.getUid(),
// keyID:"1",
// userID:await Storage.getUid(),
// openMode:1,
// keyType:1,
// startDate:0x11223344,
// expireDate:0x11223344,
// role:255,
// password:"123456",
// needAuthor:1,
// publicKey:publicKeyDataList,
// privateKey:getPrivateKeyList,
// token: getTokenList
// );
// }
// });
// }
// 备用逻辑,进入管理钥匙界面获取锁状态
// Future<void> _connectBlue(String bluetoothDeviceName) async {
// // 进来之后首先连接
// BlueManage().connect(bluetoothDeviceName, (DeviceConnectionState state) async {
// if(EasyLoading.isShow){
// EasyLoading.dismiss();
// }
// if (state == DeviceConnectionState.connected){
// // var privateKey = await Storage.getStringList(saveBluePrivateKey);
// // List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
// // // IoSenderManage.senderGetLockStatu(
// // // lockID:BlueManage().connectDeviceName,
// // // userID:await Storage.getUid(),
// // // privateKey:getPrivateKeyList,
// // // );
// // IoSenderManage.senderGetStarLockStatuInfo(
// // lockID:BlueManage().connectDeviceName,
// // userID:await Storage.getUid(),
// // privateKey:getPrivateKeyList,
// // );
// }
// }, isShowLoading: false);
// }
// 查询事件记录(时间查询)
Future<void> senderReferEventRecordTime(int time) async {
BlueManage().bludSendData(BlueManage().connectDeviceName,
(DeviceConnectionState state) async {
if (state == DeviceConnectionState.connected) {
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var token = await Storage.getStringList(saveBlueToken);
List<int> getTokenList = changeStringListToIntList(token!);
var publicKey = await Storage.getStringList(saveBluePublicKey);
List<int> getPublicKeyList = changeStringListToIntList(publicKey!);
IoSenderManage.senderReferEventRecordTimeCommand(
keyID: BlueManage().connectDeviceName,
userID: await Storage.getUid(),
logsCount: 20,
// time:DateTime.now().millisecondsSinceEpoch~/1000,
time: time,
token: getTokenList,
needAuthor: 1,
publicKey: getPublicKeyList,
privateKey: getPrivateKeyList,
);
}
});
}
//
startOpenLock() {
if(state.openLockBtnState.value == 1){
return;
}
state.iSOpenLock.value = true;
state.iSClosedUnlockSuccessfulPopup.value = false;
state.openLockBtnState.value = 1;
state.animationController.forward();
if (state.lockUserNo == 0) {
// 电子钥匙lockUserNo为0 要先添加用户
addUserConnectBlue();
} else {
if (state.isOpenLockNeedOnline.value == 0) {
// 不需要联网
openDoorAction(1);
} else {
// 需要联网
getLockNetToken();
}
}
}
startUnLock() {
if(state.openLockBtnState.value == 1){
return;
}
state.iSOpenLock.value = false;
state.iSClosedUnlockSuccessfulPopup.value = false;
state.openLockBtnState.value = 1;
state.animationController.forward();
if (state.lockUserNo == 0) {
// 电子钥匙lockUserNo为0 要先添加用户
addUserConnectBlue();
} else {
openDoorAction(32);
}
}
// 获取手机联网token根据锁设置里面获取的开锁时是否联网来判断是否调用这个接口
void getLockNetToken() async {
LockNetTokenEntity entity = await ApiRepository.to
.getLockNetToken(lockId: state.keyInfos.value.lockId.toString());
if (entity.errorCode!.codeIsSuccessful) {
state.lockNetToken = entity.data!.token!;
print("state.lockNetToken:${state.lockNetToken}");
openDoorAction(1);
}
}
// 普通用户接收电子钥匙之后 更新锁用户NO
void updateLockUserNo() async {
LockNetTokenEntity entity = await ApiRepository.to.updateLockUserNo(
keyId: state.keyInfos.value.keyId.toString(),
lockUserNo: state.lockUserNo.toString());
if (entity.errorCode!.codeIsSuccessful) {
if (state.isOpenLockNeedOnline.value == 0) {
openDoorAction(1);
} else {
getLockNetToken();
}
}
}
// 查询锁记录最后时间
void getLockRecordLastUploadDataTime() async {
LockOperatingRecordGetLastRecordTimeEntity entity = await ApiRepository.to.getLockRecordLastUploadDataTime(lockId: state.keyInfos.value.lockId.toString());
if (entity.errorCode!.codeIsSuccessful) {
senderReferEventRecordTime(entity.data!.operateDate! ~/ 1000);
}
}
// 操作记录上传
void lockRecordUploadData(List list) async {
KeyOperationRecordEntity entity = await ApiRepository.to
.lockRecordUploadData(
lockId: state.keyInfos.value.lockId.toString(), records: list);
if (entity.errorCode!.codeIsSuccessful) {
// mockNetworkDataRequest();
}
}
// connectBlueAndAnimationController(){
// state.lockState.value = 1;
// state.animationController.forward();
// BlueManage().bludSendData(state.keyInfos.value.bluetooth!.bluetoothDeviceName!, (DeviceConnectionState deviceConnectionState) async {
// if (deviceConnectionState == DeviceConnectionState.connected){
// state.lockState.value = 2;
// }else if (deviceConnectionState == DeviceConnectionState.disconnected){
// showBlueConnetctToast();
//
// state.lockState.value = 4;
// state.animationController.reset();
// state.animationController.forward();
// }
// });
// }
/// 锁设置里面开启关闭考勤刷新锁详情
StreamSubscription?
_lockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceEvent;
void _initLockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceAction() {
// 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus
_lockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceEvent = eventBus.on<LockSetChangeSetRefreshLockDetailWithType>().listen((event) {
if (event.type == 0) {
// 0考勤
state.isAttendance.value = event.setResult;
state.keyInfos.value.lockSetting!.attendance = event.setResult;
} else if (event.type == 1) {
// 1 开锁时是否需联网
state.isOpenLockNeedOnline.value = event.setResult;
state.keyInfos.value.lockSetting!.appUnlockOnline = event.setResult;
} else if (event.type == 2) {
// 2 常开模式
state.isOpenPassageMode.value = event.setResult;
state.keyInfos.value.passageMode = event.setResult;
}
});
}
late StreamSubscription<List<DiscoveredDevice>>_scanListDiscoveredDeviceSubscription;
void _scanListDiscoveredDeviceSubscriptionAction() {
_scanListDiscoveredDeviceSubscription = EventBusManager().eventBus!.on<List<DiscoveredDevice>>().listen((List<DiscoveredDevice> list) {
final knownDeviceIndex = list.indexWhere((d) => d.name == state.keyInfos.value.bluetooth!.bluetoothDeviceName!);
if (knownDeviceIndex >= 0) {
// 存在的时候赋值
state.currentDeviceUUid.value = (list[knownDeviceIndex].serviceUuids.isNotEmpty ? list[knownDeviceIndex].serviceUuids[0] : "").toString();
}
});
}
//开锁成功弹出的小界面
void _showFullScreenOverlay(BuildContext context) {
Future.delayed(const Duration(seconds: 3), () {
if(state.iSClosedUnlockSuccessfulPopup.value != true){
state.iSClosedUnlockSuccessfulPopup.value = true;
Get.back();
}
});
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
if(state.iSClosedUnlockSuccessfulPopup.value != true){
state.iSClosedUnlockSuccessfulPopup.value = true;
Get.back();
}
},
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.black.withOpacity(0.2),
child: _unlockSuccessWidget(),
),
);
},
);
}
Widget _unlockSuccessWidget() {
return Stack(
alignment: Alignment.center,
children: [
Image.asset(
'images/main/unlocked_bg.png',
width: 358.w,
height: 348.h,
),
Positioned(
top: ScreenUtil().screenHeight / 2,
child: Column(
children: [
Text(
state.keyInfos.value.lockAlias!,
style: TextStyle(
color: AppColors.placeholderTextColor, fontSize: 24.sp),
),
SizedBox(
height: 10.h,
),
Text(
getCurrentFormattedTime(),
style: TextStyle(
color: AppColors.darkGrayTextColor, fontSize: 24.sp),
)
],
))
],
);
}
String getCurrentFormattedTime() {
// 获取当前时间
DateTime now = DateTime.now();
// 格式化日期和时间
String formattedTime = DateFormat('MM/dd HH:mm').format(now);
return formattedTime;
}
@override
void onReady() {
// TODO: implement onReady
super.onReady();
_initReplySubscription();
_initLockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceAction();
_scanListDiscoveredDeviceSubscriptionAction();
// Future.delayed(const Duration(seconds: 1)).then((value) {
//
// });
}
@override
void onInit() {
// TODO: implement onInit
super.onInit();
// 进来获取锁状态
// connectBlue();
}
@override
void onClose() {
// TODO: implement onClose
_replySubscription.cancel();
_lockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceEvent!.cancel();
_scanListDiscoveredDeviceSubscription.cancel();
}
}