Merge branch 'master' of gitee.com:starlock-cn/app-starlock
# Conflicts: # star_lock/images/lan/lan_en.json 合并代码
This commit is contained in:
commit
46c4c3df4b
@ -769,9 +769,6 @@
|
||||
"异常警告":"Abnormal warning",
|
||||
"短信提醒":"SMS reminder",
|
||||
"邮件提醒":"Email reminder",
|
||||
"关锁":"关锁",
|
||||
"功能":"功能",
|
||||
"配件":"配件",
|
||||
"N天未开门提醒":"N days did not open the door reminder",
|
||||
"当被胁迫要求强行开锁时,使用胁迫指纹会触发报警,报警消息会推送给管理员,该功能需要锁联网":"When forced to open the lock, the use of coercive fingerprint will trigger the alarm, the alarm message will be pushed to the administrator, the function requires the lock network",
|
||||
"胁迫指纹":"Stress fingerprint",
|
||||
@ -779,5 +776,8 @@
|
||||
"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网":"After the above set time, the lock is not opened, the system will send a reminder message to the specified object, this function requires the lock network",
|
||||
"打开提醒后,当锁电量低于20%、10%和5%,系统会给指定对象发送提醒消息。电量读取方式:网关读取或APP读取。":"After the reminder is enabled, when the lock power is below 20%, 10%, and 5%, the system will send a reminder message to the specified object. Power reading mode: gateway reading or APP reading.",
|
||||
"门未开时间":"Door not open time",
|
||||
"添加和使用面容开锁时:":"Add and use Face when unlocking:"
|
||||
"添加和使用面容开锁时:":"Add and use Face when unlocking:",
|
||||
"关锁":"close lock",
|
||||
"功能":"function",
|
||||
"配件":"parts"
|
||||
}
|
||||
|
||||
@ -41,7 +41,41 @@ PODS:
|
||||
- ReachabilitySwift
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- DKImagePickerController/Core (4.3.8):
|
||||
- DKImagePickerController/ImageDataManager
|
||||
- DKImagePickerController/Resource
|
||||
- DKImagePickerController/ImageDataManager (4.3.8)
|
||||
- DKImagePickerController/PhotoGallery (4.3.8):
|
||||
- DKImagePickerController/Core
|
||||
- DKPhotoGallery
|
||||
- DKImagePickerController/Resource (4.3.8)
|
||||
- DKPhotoGallery (0.0.17):
|
||||
- DKPhotoGallery/Core (= 0.0.17)
|
||||
- DKPhotoGallery/Model (= 0.0.17)
|
||||
- DKPhotoGallery/Preview (= 0.0.17)
|
||||
- DKPhotoGallery/Resource (= 0.0.17)
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Core (0.0.17):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Preview
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Model (0.0.17):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Preview (0.0.17):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Resource
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Resource (0.0.17):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- EMASRest (11.1.1.2)
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- Flutter
|
||||
- Flutter (1.0.0)
|
||||
- flutter_blue_plus (0.0.1):
|
||||
- Flutter
|
||||
@ -95,12 +129,16 @@ PODS:
|
||||
- permission_handler_apple (9.3.0):
|
||||
- Flutter
|
||||
- ReachabilitySwift (5.2.2)
|
||||
- SDWebImage (5.19.1):
|
||||
- SDWebImage/Core (= 5.19.1)
|
||||
- SDWebImage/Core (5.19.1)
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqflite (0.0.3):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- SwiftyGif (5.4.5)
|
||||
- system_settings (0.0.1):
|
||||
- Flutter
|
||||
- Toast (4.1.1)
|
||||
@ -126,6 +164,7 @@ DEPENDENCIES:
|
||||
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
|
||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_blue_plus (from `.symlinks/plugins/flutter_blue_plus/ios`)
|
||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||
@ -163,11 +202,15 @@ SPEC REPOS:
|
||||
- AMap3DMap
|
||||
- AMapFoundation
|
||||
- AMapLocation
|
||||
- DKImagePickerController
|
||||
- DKPhotoGallery
|
||||
- GoogleMaps
|
||||
- ios-voice-processor
|
||||
- JCore
|
||||
- JPush
|
||||
- ReachabilitySwift
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- Toast
|
||||
- WechatOpenSDK-XCFramework
|
||||
|
||||
@ -194,6 +237,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
file_picker:
|
||||
:path: ".symlinks/plugins/file_picker/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
flutter_blue_plus:
|
||||
@ -261,7 +306,10 @@ SPEC CHECKSUMS:
|
||||
camera_avfoundation: 8b8d780bcfb6a4a02b0fbe2b4bd17b5b71946e68
|
||||
connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
|
||||
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
|
||||
DKImagePickerController: a7836546cfdfe014171694f643a7d575bc8ace7f
|
||||
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
|
||||
EMASRest: 8df6f87836767a9415ad5cc4af739bc9d215b475
|
||||
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_blue_plus: 4837da7d00cf5d441fdd6635b3a57f936778ea96
|
||||
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
|
||||
@ -284,8 +332,10 @@ SPEC CHECKSUMS:
|
||||
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||
ReachabilitySwift: 2128f3a8c9107e1ad33574c6e58e8285d460b149
|
||||
SDWebImage: 40b0b4053e36c660a764958bff99eed16610acbb
|
||||
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
|
||||
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
system_settings: 8f5cdbfa72c677fc8d665b863bcc20d393d87e9d
|
||||
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
|
||||
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
|
||||
|
||||
@ -57,6 +57,7 @@ import 'login/login/starLock_login_page.dart';
|
||||
import 'login/register/starLock_register_page.dart';
|
||||
import 'login/selectCountryRegion/selectCountryRegion_page.dart';
|
||||
import 'main/lockDetail/card/addCardType/addCardManage/addCardTypeManage_page.dart';
|
||||
import 'main/lockDetail/card/addCardType/addCardType_page.dart';
|
||||
import 'main/lockDetail/card/addICCard/addICCard_page.dart';
|
||||
import 'main/lockDetail/card/cardDetail/cardDetail_page.dart';
|
||||
import 'main/lockDetail/card/cardList/cardList_page.dart';
|
||||
@ -416,7 +417,8 @@ abstract class Routers {
|
||||
'/AddRemoteControlManagePage'; // 添加遥控
|
||||
|
||||
static const cardListPage = '/CardListPage'; // 卡列表
|
||||
static const addCardTypeManagePage = '/AddCardTypeManagePage'; // 添加卡
|
||||
// static const addCardTypeManagePage = '/AddCardTypeManagePage'; // 添加卡
|
||||
static const addCardPage = '/AddCardPage'; // 添加卡
|
||||
static const cardDetailPage = '/CardDetailPage'; // 卡详情
|
||||
static const fingerprintListPage = '/FingerprintListPage'; // 指纹列表
|
||||
static const addFingerprintTypeManagePage =
|
||||
@ -1009,9 +1011,12 @@ abstract class AppRouters {
|
||||
name: Routers.addRemoteControlManagePage,
|
||||
page: () => const AddRemoteControlManagePage()),
|
||||
GetPage(name: Routers.cardListPage, page: () => const CardListPage()),
|
||||
// GetPage(
|
||||
// name: Routers.addCardTypeManagePage,
|
||||
// page: () => const AddCardTypeManagePage()),
|
||||
GetPage(
|
||||
name: Routers.addCardTypeManagePage,
|
||||
page: () => const AddCardTypeManagePage()),
|
||||
name: Routers.addCardPage,
|
||||
page: () => const AddCardPage()),
|
||||
GetPage(name: Routers.cardDetailPage, page: () => const CardDetailPage()),
|
||||
GetPage(
|
||||
name: Routers.fingerprintListPage,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
@ -12,7 +11,8 @@ import 'reciver_data.dart';
|
||||
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
|
||||
|
||||
//连接状态回调
|
||||
typedef ConnectStateCallBack = Function(BluetoothConnectionState connectionState);
|
||||
typedef ConnectStateCallBack = Function(
|
||||
BluetoothConnectionState connectionState);
|
||||
typedef ScanDevicesCallBack = Function(List<ScanResult>);
|
||||
|
||||
class BlueManage {
|
||||
@ -57,7 +57,8 @@ class BlueManage {
|
||||
ScanResult? scanResult;
|
||||
|
||||
// 监听蓝牙连接状态
|
||||
BluetoothConnectionState? bluetoothConnectionState = BluetoothConnectionState.disconnected;
|
||||
BluetoothConnectionState? bluetoothConnectionState =
|
||||
BluetoothConnectionState.disconnected;
|
||||
|
||||
BluetoothAdapterState? _adapterState = BluetoothAdapterState.unknown;
|
||||
StreamSubscription<BluetoothAdapterState>? _adapterStateStateSubscription;
|
||||
@ -80,6 +81,7 @@ class BlueManage {
|
||||
|
||||
void _initBlue() {
|
||||
Get.log("蓝牙功能初始化监听");
|
||||
FlutterBluePlus.setLogLevel(LogLevel.error, color: true);
|
||||
_initSendStreamSubscription();
|
||||
_initAdapterStateStateSubscription();
|
||||
// _initListenscanResults();
|
||||
@ -94,7 +96,8 @@ class BlueManage {
|
||||
}
|
||||
|
||||
void _initAdapterStateStateSubscription() {
|
||||
_adapterStateStateSubscription ??= FlutterBluePlus.adapterState.listen((state) {
|
||||
_adapterStateStateSubscription ??=
|
||||
FlutterBluePlus.adapterState.listen((state) {
|
||||
_adapterState = state;
|
||||
});
|
||||
}
|
||||
@ -142,14 +145,18 @@ class BlueManage {
|
||||
_connectionStateSubscription?.cancel();
|
||||
_connectionStateSubscription = null;
|
||||
|
||||
_connectionStateSubscription = bluetoothConnectDevice!.connectionState.listen((state) async {
|
||||
_connectionStateSubscription =
|
||||
bluetoothConnectDevice!.connectionState.listen((state) async {
|
||||
bluetoothConnectionState = state;
|
||||
print("蓝牙连接状态:$state");
|
||||
});
|
||||
}
|
||||
|
||||
void _initSendStreamSubscription() {
|
||||
_sendStreamSubscription ??= EventBusManager().eventBus!.on<EventSendModel>().listen((EventSendModel model) {
|
||||
_sendStreamSubscription ??= EventBusManager()
|
||||
.eventBus!
|
||||
.on<EventSendModel>()
|
||||
.listen((EventSendModel model) {
|
||||
if (model.sendChannel == DataChannel.ble) {
|
||||
FlutterBluePlus.isSupported.then((isAvailable) async {
|
||||
if (isAvailable) {
|
||||
@ -157,9 +164,7 @@ class BlueManage {
|
||||
// 蓝牙已开启,可以进行蓝牙操作
|
||||
writeCharacteristicWithResponse(model.data);
|
||||
} else {
|
||||
try {
|
||||
|
||||
} catch (e) {
|
||||
try {} catch (e) {
|
||||
print("Error Turning On:");
|
||||
}
|
||||
}
|
||||
@ -172,7 +177,8 @@ class BlueManage {
|
||||
}
|
||||
|
||||
/// 开始指定设备名称的扫描蓝牙设备
|
||||
Future<void> startScanSingle(String deviceName, int timeout, ScanDevicesCallBack scanDevicesCallBack) async {
|
||||
Future<void> startScanSingle(String deviceName, int timeout,
|
||||
ScanDevicesCallBack scanDevicesCallBack) async {
|
||||
FlutterBluePlus.isSupported.then((isAvailable) async {
|
||||
if (isAvailable) {
|
||||
if (_adapterState == BluetoothAdapterState.on) {
|
||||
@ -180,8 +186,10 @@ class BlueManage {
|
||||
FlutterBluePlus.startScan(timeout: Duration(seconds: timeout));
|
||||
Completer<dynamic> completer = Completer<dynamic>();
|
||||
var subscription = FlutterBluePlus.scanResults.listen((results) {
|
||||
print("startScanSingle扫描到的设备:$results");
|
||||
bool isExit = results.any((element) => (element.device.platformName == deviceName) || (element.advertisementData.advName == deviceName));
|
||||
// print("startScanSingle扫描到的设备:$results");
|
||||
bool isExit = results.any((element) =>
|
||||
(element.device.platformName == deviceName) ||
|
||||
(element.advertisementData.advName == deviceName));
|
||||
if (isExit) {
|
||||
for (var scanResult in results) {
|
||||
if (((scanResult.advertisementData.serviceUuids.isNotEmpty
|
||||
@ -191,8 +199,11 @@ class BlueManage {
|
||||
.contains("758824")) &&
|
||||
(scanResult.rssi >= -100)) {
|
||||
// 查询id相同的元素
|
||||
final knownDeviceIndex = scanDevices
|
||||
.indexWhere((d) => (d.device.platformName == scanResult.device.platformName) || (d.advertisementData.advName == scanResult.advertisementData.advName));
|
||||
final knownDeviceIndex = scanDevices.indexWhere((d) =>
|
||||
(d.device.platformName ==
|
||||
scanResult.device.platformName) ||
|
||||
(d.advertisementData.advName ==
|
||||
scanResult.advertisementData.advName));
|
||||
// 不存在的时候返回-1
|
||||
if (knownDeviceIndex >= 0) {
|
||||
scanDevices[knownDeviceIndex] = scanResult;
|
||||
@ -231,7 +242,8 @@ class BlueManage {
|
||||
}
|
||||
|
||||
/// 开始扫描蓝牙设备
|
||||
Future<void> startScan(int timeout, ScanDevicesCallBack scanDevicesCallBack, {List<Guid>? idList}) async {
|
||||
Future<void> startScan(int timeout, ScanDevicesCallBack scanDevicesCallBack,
|
||||
{List<Guid>? idList}) async {
|
||||
FlutterBluePlus.isSupported.then((isAvailable) async {
|
||||
if (isAvailable) {
|
||||
if (_adapterState == BluetoothAdapterState.on) {
|
||||
@ -255,8 +267,11 @@ class BlueManage {
|
||||
.contains("758824")) &&
|
||||
(scanResult.rssi >= -100)) {
|
||||
// 查询id相同的元素
|
||||
final knownDeviceIndex = scanDevices
|
||||
.indexWhere((d) => (d.device.platformName == scanResult.device.platformName) || (d.advertisementData.advName == scanResult.advertisementData.advName));
|
||||
final knownDeviceIndex = scanDevices.indexWhere((d) =>
|
||||
(d.device.platformName ==
|
||||
scanResult.device.platformName) ||
|
||||
(d.advertisementData.advName ==
|
||||
scanResult.advertisementData.advName));
|
||||
// 不存在的时候返回-1
|
||||
if (knownDeviceIndex >= 0) {
|
||||
scanDevices[knownDeviceIndex] = scanResult;
|
||||
@ -294,7 +309,9 @@ class BlueManage {
|
||||
}
|
||||
|
||||
/// 调用发送数据 List senderData,
|
||||
Future<void> bludSendData(String deviceName, ConnectStateCallBack stateCallBack, {bool isAddEquipment = false}) async {
|
||||
Future<void> bludSendData(
|
||||
String deviceName, ConnectStateCallBack stateCallBack,
|
||||
{bool isAddEquipment = false}) async {
|
||||
FlutterBluePlus.isSupported.then((isAvailable) async {
|
||||
if (isAvailable) {
|
||||
if (_adapterState == BluetoothAdapterState.on) {
|
||||
@ -321,33 +338,43 @@ class BlueManage {
|
||||
}
|
||||
|
||||
/// 连接
|
||||
Future<void> _connect(String deviceName, ConnectStateCallBack connectStateCallBack,
|
||||
Future<void> _connect(
|
||||
String deviceName, ConnectStateCallBack connectStateCallBack,
|
||||
{bool isAddEquipment = false}) async {
|
||||
connectDeviceName = deviceName;
|
||||
List<ScanResult> devicesList = scanDevices;
|
||||
//判断列表里面有设备则不开启扫描
|
||||
bool isExistDevice = scanDevices.any((element) => element.device.platformName == connectDeviceName || element.advertisementData.advName == connectDeviceName);
|
||||
bool isExistDevice = scanDevices.any((element) =>
|
||||
element.device.platformName == connectDeviceName ||
|
||||
element.advertisementData.advName == connectDeviceName);
|
||||
if (isAddEquipment == false && isExistDevice == false) {
|
||||
// startScan(10, (scanDevices){
|
||||
startScanSingle(deviceName, 10, (List<ScanResult> scanDevices) {
|
||||
print("扫描到的设备:$scanDevices");
|
||||
devicesList = scanDevices;
|
||||
_connectDevice(devicesList, deviceName, connectStateCallBack, isAddEquipment: isAddEquipment);
|
||||
_connectDevice(devicesList, deviceName, connectStateCallBack,
|
||||
isAddEquipment: isAddEquipment);
|
||||
});
|
||||
} else {
|
||||
_connectDevice(devicesList, deviceName, connectStateCallBack, isAddEquipment: isAddEquipment);
|
||||
_connectDevice(devicesList, deviceName, connectStateCallBack,
|
||||
isAddEquipment: isAddEquipment);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _connectDevice(
|
||||
List<ScanResult> devicesList, String deviceName, ConnectStateCallBack connectStateCallBack,
|
||||
Future<void> _connectDevice(List<ScanResult> devicesList, String deviceName,
|
||||
ConnectStateCallBack connectStateCallBack,
|
||||
{bool isAddEquipment = false}) async {
|
||||
// 判断数组列表里面是否有这个设备
|
||||
print("devicesList:$devicesList");
|
||||
final knownDeviceIndex = devicesList.indexWhere((d) => (d.device.platformName == deviceName) || (d.advertisementData.advName == deviceName));
|
||||
final knownDeviceIndex = devicesList.indexWhere((d) =>
|
||||
(d.device.platformName == deviceName) ||
|
||||
(d.advertisementData.advName == deviceName));
|
||||
if (knownDeviceIndex >= 0) {
|
||||
// 存在的时候赋值
|
||||
connectDeviceMacAddress = devicesList[knownDeviceIndex].advertisementData.advName.isNotEmpty ? devicesList[knownDeviceIndex].advertisementData.advName : devicesList[knownDeviceIndex].device.platformName;
|
||||
connectDeviceMacAddress =
|
||||
devicesList[knownDeviceIndex].advertisementData.advName.isNotEmpty
|
||||
? devicesList[knownDeviceIndex].advertisementData.advName
|
||||
: devicesList[knownDeviceIndex].device.platformName;
|
||||
|
||||
bluetoothConnectDevice = devicesList[knownDeviceIndex].device;
|
||||
print('bluetoothConnectDevice: $bluetoothConnectDevice');
|
||||
@ -356,7 +383,8 @@ class BlueManage {
|
||||
_initGetMtuSubscription();
|
||||
_initListenConnectionState();
|
||||
}
|
||||
print("1 connectDeviceId:$connectDeviceMacAddress connectDeviceName:$connectDeviceName");
|
||||
print(
|
||||
"1 connectDeviceId:$connectDeviceMacAddress connectDeviceName:$connectDeviceName");
|
||||
// stopScan();
|
||||
if (connectDeviceMacAddress.isEmpty) {
|
||||
// connectStateCallBack(BluetoothConnectionState.disconnected!);
|
||||
@ -366,7 +394,8 @@ class BlueManage {
|
||||
print("调用了停止扫描的方法");
|
||||
await stopScan();
|
||||
|
||||
if ((scanResult!.advertisementData.serviceUuids[0].toString()[31] == "0") && isAddEquipment == false) {
|
||||
if ((scanResult!.advertisementData.serviceUuids[0].toString()[31] == "0") &&
|
||||
isAddEquipment == false) {
|
||||
connectStateCallBack(BluetoothConnectionState.disconnected);
|
||||
EasyLoading.showToast("该锁已被重置", duration: 2000.milliseconds);
|
||||
return;
|
||||
@ -403,12 +432,14 @@ class BlueManage {
|
||||
" service.characteristics:${service.characteristics}"
|
||||
" service.includedServices:${service.includedServices}");
|
||||
if (service.uuid == _serviceIdConnect) {
|
||||
for (BluetoothCharacteristic characteristic in service.characteristics) {
|
||||
for (BluetoothCharacteristic characteristic
|
||||
in service.characteristics) {
|
||||
// Get.log("22222characteristic.remoteId:${characteristic.remoteId}"
|
||||
// " characteristic.uuid:${characteristic.uuid}"
|
||||
// " characteristic.secondaryServiceUuid:${characteristic.secondaryServiceUuid}"
|
||||
// " characteristic.characteristicUuid:${characteristic.characteristicUuid}");
|
||||
if (characteristic.characteristicUuid == _characteristicIdSubscription) {
|
||||
if (characteristic.characteristicUuid ==
|
||||
_characteristicIdSubscription) {
|
||||
_subScribeToCharacteristic(characteristic);
|
||||
print('Discovering services finished');
|
||||
bluetoothConnectionState = BluetoothConnectionState.connected;
|
||||
@ -446,18 +477,21 @@ class BlueManage {
|
||||
}
|
||||
// code to handle incoming data
|
||||
// print("subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data");
|
||||
if ((data[0] == 0xEF) && (data[1] == 0x01) && (data[2] == 0xEE) && (data[3] == 0x02)) {
|
||||
if ((data[0] == 0xEF) &&
|
||||
(data[1] == 0x01) &&
|
||||
(data[2] == 0xEE) &&
|
||||
(data[3] == 0x02)) {
|
||||
// 当包有头时
|
||||
// 判断是否需要分包
|
||||
dataLen = data[8] * 256 + data[9]; // 高16位用来指示后面数据块内容的长度
|
||||
print("dataLen1111:$dataLen getDataLength:${data.length} data:$data");
|
||||
// print("dataLen1111:$dataLen getDataLength:${data.length} data:$data");
|
||||
if (dataLen! + 12 > data.length) {
|
||||
// 当前包的长度小于实际的包时 分包添加 不解析
|
||||
allData.addAll(data);
|
||||
} else {
|
||||
// 当前包的长度小于实际的包时 不分包 解析
|
||||
allData.addAll(data);
|
||||
print("dataLen2222:$dataLen getDataLength:${data.length}");
|
||||
// print("dataLen2222:$dataLen getDataLength:${data.length}");
|
||||
CommandReciverManager.appDataReceive(allData);
|
||||
// 发送完解析初始化数组
|
||||
allData = <int>[];
|
||||
@ -466,7 +500,8 @@ class BlueManage {
|
||||
// 当包没有头时 是分包的包 直接添加
|
||||
allData.addAll(data);
|
||||
// var len = allData[8] * 256 + allData[9];
|
||||
print("dataLen3333:$dataLen allData.length:${allData.length} allData:$allData");
|
||||
print(
|
||||
"dataLen3333:$dataLen allData.length:${allData.length} allData:$allData");
|
||||
if ((dataLen! + 14) <= allData.length) {
|
||||
print("44444数据被解析了");
|
||||
// 当长度小于等于当前包的数据时 直接解析数据
|
||||
@ -530,44 +565,44 @@ class BlueManage {
|
||||
|
||||
// 写入
|
||||
Future<void> writeCharacteristicWithResponse(List<int> value) async {
|
||||
bluetoothConnectDevice!.discoverServices().then((services) async {
|
||||
for (BluetoothService service in services) {
|
||||
// print("33333 service.remoteId:${service.remoteId}"
|
||||
// " service.uuid:${service.uuid}\n\n"
|
||||
// " service.characteristics:${service.characteristics}\n\n"
|
||||
// " service.includedServices:${service.includedServices}");
|
||||
if (service.uuid == _serviceIdConnect) {
|
||||
for (BluetoothCharacteristic characteristic in service.characteristics) {
|
||||
// print("44444 characteristic.remoteId:${characteristic.remoteId}"
|
||||
// " characteristic.uuid:${characteristic.uuid}\n\n"
|
||||
// " characteristic.secondaryServiceUuid:${characteristic
|
||||
// .secondaryServiceUuid}\n\n"
|
||||
// " characteristic.characteristicUuid:${characteristic
|
||||
// .characteristicUuid}");
|
||||
if (characteristic.characteristicUuid == _characteristicIdWrite) {
|
||||
try {
|
||||
List<int> valueList = value;
|
||||
List subData = splitList(valueList, _mtuSize!);
|
||||
print('writeCharacteristicWithResponse _mtuSize:$_mtuSize 得到的分割数据:$subData');
|
||||
|
||||
for (int i = 0; i < subData.length; i++) {
|
||||
await characteristic.write(subData[i]).then((value) async {
|
||||
await Future.delayed(const Duration(milliseconds: 1)).then((
|
||||
value) async {
|
||||
print('分包发送成功了');
|
||||
});
|
||||
});
|
||||
}
|
||||
} on Exception catch (e, s) {
|
||||
print('Error occurred when writing: $e');
|
||||
// Get.log(s);
|
||||
rethrow;
|
||||
List<BluetoothService> services =
|
||||
await bluetoothConnectDevice!.discoverServices();
|
||||
for (BluetoothService service in services) {
|
||||
// print("33333 service.remoteId:${service.remoteId}"
|
||||
// " service.uuid:${service.uuid}\n\n"
|
||||
// " service.characteristics:${service.characteristics}\n\n"
|
||||
// " service.includedServices:${service.includedServices}");
|
||||
if (service.uuid == _serviceIdConnect) {
|
||||
for (BluetoothCharacteristic characteristic
|
||||
in service.characteristics) {
|
||||
// print("44444 characteristic.remoteId:${characteristic.remoteId}"
|
||||
// " characteristic.uuid:${characteristic.uuid}\n\n"
|
||||
// " characteristic.secondaryServiceUuid:${characteristic
|
||||
// .secondaryServiceUuid}\n\n"
|
||||
// " characteristic.characteristicUuid:${characteristic
|
||||
// .characteristicUuid}");
|
||||
if (characteristic.characteristicUuid == _characteristicIdWrite) {
|
||||
try {
|
||||
List<int> valueList = value;
|
||||
List subData = splitList(valueList, _mtuSize!);
|
||||
// print('writeCharacteristicWithResponse _mtuSize:$_mtuSize 得到的分割数据:$subData');
|
||||
for (int i = 0; i < subData.length; i++) {
|
||||
await characteristic.write(subData[i],withoutResponse: true).then((value) async {
|
||||
// await Future.delayed(const Duration(milliseconds: 1)).then((
|
||||
// value) async {
|
||||
// print('分包发送成功了');
|
||||
// });
|
||||
});
|
||||
}
|
||||
} on Exception catch (e, s) {
|
||||
print('Error occurred when writing: $e');
|
||||
// Get.log(s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// List<BluetoothService> services = await bluetoothConnectDevice!.discoverServices();
|
||||
// BluetoothCharacteristic characteristic = services
|
||||
// .firstWhere((service) => service.uuid == _serviceIdWrite)
|
||||
|
||||
13
star_lock/lib/blue/io_modelVendor.dart
Normal file
13
star_lock/lib/blue/io_modelVendor.dart
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
|
||||
class IoModelVendor {
|
||||
|
||||
static String vendor_XHJ = 'XHJ';
|
||||
static String model_XHJ_SYD = 'SYD-BLE-01';
|
||||
static String model_XHJ_JL = 'JL-BLE-01';
|
||||
|
||||
static String vendor_XL = 'XL';
|
||||
static String model_XL_BLE = 'JL-BLE-01';
|
||||
static String model_XL_WIFI = 'JL-WIFI-01';
|
||||
}
|
||||
149
star_lock/lib/blue/io_protocol/io_otaUpgrade.dart
Normal file
149
star_lock/lib/blue/io_protocol/io_otaUpgrade.dart
Normal file
@ -0,0 +1,149 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../io_tool/io_tool.dart';
|
||||
import '../sm4Encipher/sm4.dart';
|
||||
import '../io_reply.dart';
|
||||
import '../io_sender.dart';
|
||||
import '../io_type.dart';
|
||||
import 'package:crypto/crypto.dart' as crypto;
|
||||
|
||||
//oat升级
|
||||
class OTAUpgradeCommand extends SenderProtocol {
|
||||
String? lockID;
|
||||
String? userID;
|
||||
String? keyID;
|
||||
int? platform;
|
||||
int? product;
|
||||
String? hwVersion;
|
||||
String? fwVersion;
|
||||
int? fwSize;
|
||||
String? fwMD5;
|
||||
int? needAuthor;
|
||||
List<int>? publicKey;
|
||||
List<int>? privateKey;
|
||||
List<int>? token;
|
||||
|
||||
OTAUpgradeCommand(
|
||||
{this.lockID,
|
||||
this.userID,
|
||||
this.keyID,
|
||||
this.platform,
|
||||
this.product,
|
||||
this.hwVersion,
|
||||
this.fwVersion,
|
||||
this.fwSize,
|
||||
this.fwMD5,
|
||||
this.needAuthor,
|
||||
this.publicKey,
|
||||
this.privateKey,
|
||||
this.token})
|
||||
: super(CommandType.startOATUpgrade);
|
||||
|
||||
@override
|
||||
List<int> messageDetail() {
|
||||
List<int> data = [];
|
||||
List<int> ebcData = [];
|
||||
|
||||
// 指令类型
|
||||
int type = commandType!.typeValue;
|
||||
double typeDouble = type / 256;
|
||||
int type1 = typeDouble.toInt();
|
||||
int type2 = type % 256;
|
||||
data.add(type1);
|
||||
data.add(type2);
|
||||
|
||||
// 锁id 40
|
||||
int lockIDLength = utf8.encode(lockID!).length;
|
||||
data.addAll(utf8.encode(lockID!));
|
||||
data = getFixedLengthList(data, 40 - lockIDLength);
|
||||
|
||||
//userID 20
|
||||
int userIDLength = utf8.encode(userID!).length;
|
||||
data.addAll(utf8.encode(userID!));
|
||||
data = getFixedLengthList(data, 20 - userIDLength);
|
||||
|
||||
//platform 2
|
||||
int platform0 = (platform! & 0xFF00) >> 8;
|
||||
int platform1 = platform! & 0xFF;
|
||||
data.add(platform0);
|
||||
data.add(platform1);
|
||||
|
||||
//product 2
|
||||
int product0 = (product! & 0xFF00) >> 8;
|
||||
int product1 = product! & 0xFF;
|
||||
data.add(product0);
|
||||
data.add(product1);
|
||||
|
||||
//HwVersion 20
|
||||
int hwVersionLength = utf8.encode(hwVersion!).length;
|
||||
data.addAll(utf8.encode(hwVersion!));
|
||||
data = getFixedLengthList(data, 20 - hwVersionLength);
|
||||
|
||||
//FwVersion 20
|
||||
int fwVersionLength = utf8.encode(fwVersion!).length;
|
||||
data.addAll(utf8.encode(fwVersion!));
|
||||
data = getFixedLengthList(data, 20 - fwVersionLength);
|
||||
|
||||
//fwSize 4
|
||||
ByteData bytes = ByteData(4); // 创建一个长度为4的字节数据
|
||||
bytes.setInt32(0, fwSize!);
|
||||
List<int> byteList = bytes.buffer.asUint8List();
|
||||
data.addAll(byteList);
|
||||
|
||||
//fwMD5 16
|
||||
int fwMD5Length = utf8.encode(fwMD5!).length;
|
||||
data.addAll(utf8.encode(fwMD5!));
|
||||
data = getFixedLengthList(data, 16 - fwMD5Length);
|
||||
|
||||
// token 长度4 首次请求 Token 填 0,如果锁需要鉴权 操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 当token失效或者第一次发送的时候token为0
|
||||
data.addAll(token!);
|
||||
|
||||
if (needAuthor == 0) {
|
||||
//AuthCodeLen 1
|
||||
data.add(0);
|
||||
} else {
|
||||
List<int> authCodeData = [];
|
||||
|
||||
//authUserID
|
||||
authCodeData.addAll(utf8.encode(userID!));
|
||||
|
||||
//KeyID
|
||||
authCodeData.addAll(utf8.encode(keyID!));
|
||||
|
||||
//token 4 首次请求 Token 填 0,如果锁需要鉴权操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。
|
||||
authCodeData.addAll(token!);
|
||||
|
||||
authCodeData.addAll(publicKey!);
|
||||
|
||||
// 把KeyID、authUserID、时间戳、公钥通过md5加密之后就是authCode
|
||||
var authCode = crypto.md5.convert(authCodeData);
|
||||
|
||||
data.add(authCode.bytes.length);
|
||||
data.addAll(authCode.bytes);
|
||||
}
|
||||
|
||||
if ((data.length % 16) != 0) {
|
||||
int add = (16 - data.length % 16);
|
||||
for (int i = 0; i < add; i++) {
|
||||
data.add(0);
|
||||
}
|
||||
}
|
||||
|
||||
Get.log("${commandType!.typeName} SM4Data:$data");
|
||||
// 拿到数据之后通过LockId进行SM4 ECB加密 key:544d485f633335373034383064613864
|
||||
ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB);
|
||||
return ebcData;
|
||||
}
|
||||
}
|
||||
|
||||
class OTAUpgradeReply extends Reply {
|
||||
OTAUpgradeReply.parseData(CommandType commandType, List<int> dataDetail)
|
||||
: super.parseData(commandType, dataDetail) {
|
||||
data = dataDetail;
|
||||
int status = data[6];
|
||||
errorWithStstus(status);
|
||||
}
|
||||
}
|
||||
74
star_lock/lib/blue/io_protocol/io_processOtaUpgrade.dart
Normal file
74
star_lock/lib/blue/io_protocol/io_processOtaUpgrade.dart
Normal file
@ -0,0 +1,74 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../io_tool/io_tool.dart';
|
||||
import '../sm4Encipher/sm4.dart';
|
||||
import '../io_reply.dart';
|
||||
import '../io_sender.dart';
|
||||
import '../io_type.dart';
|
||||
import 'package:crypto/crypto.dart' as crypto;
|
||||
|
||||
//oat升级
|
||||
class ProcessOtaUpgradeCommand extends SenderProtocol {
|
||||
int? index;
|
||||
int? size;
|
||||
List<int>? data;
|
||||
|
||||
ProcessOtaUpgradeCommand({
|
||||
this.index,
|
||||
this.size,
|
||||
this.data,
|
||||
}) : super(CommandType.processOTAUpgrade);
|
||||
|
||||
@override
|
||||
List<int> messageDetail() {
|
||||
List<int> data = [];
|
||||
|
||||
// 指令类型
|
||||
int type = commandType!.typeValue;
|
||||
double typeDouble = type / 256;
|
||||
int type1 = typeDouble.toInt();
|
||||
int type2 = type % 256;
|
||||
data.add(type1);
|
||||
data.add(type2);
|
||||
|
||||
//index 2
|
||||
ByteData indexBytes = ByteData(2); // 创建一个长度为4的字节数据
|
||||
indexBytes.setInt16(0, index!);
|
||||
List<int> indexList = indexBytes.buffer.asUint8List();
|
||||
data.addAll(indexList);
|
||||
|
||||
//size 2
|
||||
ByteData bytes = ByteData(2); // 创建一个长度为4的字节数据
|
||||
bytes.setInt16(0, size!);
|
||||
List<int> byteList = bytes.buffer.asUint8List();
|
||||
data.addAll(byteList);
|
||||
|
||||
data.addAll(this.data!);
|
||||
|
||||
//不加密
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class ProcessOtaUpgradeReply extends Reply {
|
||||
ProcessOtaUpgradeReply.parseData(
|
||||
CommandType commandType, List<int> dataDetail)
|
||||
: super.parseData(commandType, dataDetail) {
|
||||
data = dataDetail;
|
||||
int status = data[2];
|
||||
errorWithStstus(status);
|
||||
}
|
||||
}
|
||||
|
||||
class ConfirmationOTAUpgradeReply extends Reply {
|
||||
ConfirmationOTAUpgradeReply.parseData(
|
||||
CommandType commandType, List<int> dataDetail)
|
||||
: super.parseData(commandType, dataDetail) {
|
||||
data = dataDetail;
|
||||
int status = data[2];
|
||||
errorWithStstus(status);
|
||||
}
|
||||
}
|
||||
@ -14,11 +14,11 @@ abstract class Reply{
|
||||
Reply.parseData(this.commandType, List<int> dataDetail);
|
||||
|
||||
void errorWithStstus(int status){
|
||||
Get.log("errorWithStstus status:$status commandType:$commandType");
|
||||
// Get.log("errorWithStstus status:$status commandType:$commandType");
|
||||
switch(status){
|
||||
case 0x00:
|
||||
// 成功
|
||||
Get.log("$commandType成功");
|
||||
// Get.log("$commandType成功");
|
||||
break;
|
||||
case 0x01:
|
||||
// 包格式错误
|
||||
@ -134,4 +134,9 @@ abstract class Reply{
|
||||
void showErrorMessage(String message){
|
||||
EasyLoading.showToast(message, duration: 2000.milliseconds);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Reply{commandType: $commandType, status: $status, data: $data}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,11 +12,17 @@ abstract class SenderProtocol extends IOData {
|
||||
// var uint8View1 = Uint8List(300);
|
||||
|
||||
CommandType? commandType; //指令类型
|
||||
final List<int> header = [0XEF, 0X01, 0XEE, 0X02]; //帧头 固定取值 0XEF01EE02,长度 4 字节
|
||||
final int ask = 0X01 ; // 包类型:0X01 表示请求包,0X11 表示应答包,长度 1 字节
|
||||
final List<int> header = [
|
||||
0XEF,
|
||||
0X01,
|
||||
0XEE,
|
||||
0X02
|
||||
]; //帧头 固定取值 0XEF01EE02,长度 4 字节
|
||||
final int ask = 0X01; // 包类型:0X01 表示请求包,0X11 表示应答包,长度 1 字节
|
||||
int? _commandIndex = 1; //包序号
|
||||
|
||||
int identifier = 0x20; // 高 4 位表示包版本,低 4 位用来指示后面数据的加密类型,长度为 1 字节,加密类型取值说明,0:明文,1:AES128,2:SM4(事先约定密钥),3:SM4(设备指定密钥)
|
||||
int identifier =
|
||||
0x20; // 高 4 位表示包版本,低 4 位用来指示后面数据的加密类型,长度为 1 字节,加密类型取值说明,0:明文,1:AES128,2:SM4(事先约定密钥),3:SM4(设备指定密钥)
|
||||
|
||||
List<int>? commandData = []; //数据块
|
||||
// final int? tail = 0xFF; //用来校验包的完整性,采用 CRC 校验方法,长度为 2 个字节
|
||||
@ -40,9 +46,9 @@ abstract class SenderProtocol extends IOData {
|
||||
|
||||
// 包序号
|
||||
int commandIndexChange = _commandIndex!;
|
||||
double commandIndexChangeDouble = commandIndexChange/256;
|
||||
double commandIndexChangeDouble = commandIndexChange / 256;
|
||||
int commandIndexChang1 = commandIndexChangeDouble.toInt();
|
||||
int commandIndexChang2 = commandIndexChange%256;
|
||||
int commandIndexChang2 = commandIndexChange % 256;
|
||||
commandList.add(commandIndexChang1);
|
||||
commandList.add(commandIndexChang2);
|
||||
// print("_commandIndex:$_commandIndex commandIndexChang1$commandIndexChang1 commandIndexChang2:$commandIndexChang2");
|
||||
@ -57,11 +63,11 @@ abstract class SenderProtocol extends IOData {
|
||||
// commandList.add(dataLength);
|
||||
// print("dataLen:$dataLen");
|
||||
// var dataLen = 42;
|
||||
double dataLength = dataLen/256;
|
||||
double dataLength = dataLen / 256;
|
||||
commandList.add(dataLength.toInt());
|
||||
commandList.add(dataLen%256);
|
||||
commandList.add(dataLen % 256);
|
||||
commandList.add(dataLength.toInt());
|
||||
commandList.add(dataLen%256);
|
||||
commandList.add(dataLen % 256);
|
||||
|
||||
// 数据块
|
||||
commandList.addAll(commandData!); //数据块
|
||||
@ -69,46 +75,284 @@ abstract class SenderProtocol extends IOData {
|
||||
|
||||
// 校验位
|
||||
var mcrc = crc_16(commandList);
|
||||
double mcrcDouble = mcrc/256;
|
||||
double mcrcDouble = mcrc / 256;
|
||||
int mcrcDouble1 = mcrcDouble.toInt();
|
||||
int mcrcDouble2 = mcrc%256;
|
||||
int mcrcDouble2 = mcrc % 256;
|
||||
commandList.add(mcrcDouble1); //帧尾
|
||||
commandList.add(mcrcDouble2);
|
||||
// print("mcrc:$mcrc");
|
||||
// print("mcrcDouble1:$mcrcDouble1");
|
||||
// print("mcrcDouble2:$mcrcDouble2");
|
||||
return commandList;
|
||||
}
|
||||
|
||||
//TODO:长度
|
||||
int dataSourceLength() => commandData!.length;
|
||||
|
||||
var crcTable =[
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0];
|
||||
var crcTable = [
|
||||
0x0000,
|
||||
0x1021,
|
||||
0x2042,
|
||||
0x3063,
|
||||
0x4084,
|
||||
0x50a5,
|
||||
0x60c6,
|
||||
0x70e7,
|
||||
0x8108,
|
||||
0x9129,
|
||||
0xa14a,
|
||||
0xb16b,
|
||||
0xc18c,
|
||||
0xd1ad,
|
||||
0xe1ce,
|
||||
0xf1ef,
|
||||
0x1231,
|
||||
0x0210,
|
||||
0x3273,
|
||||
0x2252,
|
||||
0x52b5,
|
||||
0x4294,
|
||||
0x72f7,
|
||||
0x62d6,
|
||||
0x9339,
|
||||
0x8318,
|
||||
0xb37b,
|
||||
0xa35a,
|
||||
0xd3bd,
|
||||
0xc39c,
|
||||
0xf3ff,
|
||||
0xe3de,
|
||||
0x2462,
|
||||
0x3443,
|
||||
0x0420,
|
||||
0x1401,
|
||||
0x64e6,
|
||||
0x74c7,
|
||||
0x44a4,
|
||||
0x5485,
|
||||
0xa56a,
|
||||
0xb54b,
|
||||
0x8528,
|
||||
0x9509,
|
||||
0xe5ee,
|
||||
0xf5cf,
|
||||
0xc5ac,
|
||||
0xd58d,
|
||||
0x3653,
|
||||
0x2672,
|
||||
0x1611,
|
||||
0x0630,
|
||||
0x76d7,
|
||||
0x66f6,
|
||||
0x5695,
|
||||
0x46b4,
|
||||
0xb75b,
|
||||
0xa77a,
|
||||
0x9719,
|
||||
0x8738,
|
||||
0xf7df,
|
||||
0xe7fe,
|
||||
0xd79d,
|
||||
0xc7bc,
|
||||
0x48c4,
|
||||
0x58e5,
|
||||
0x6886,
|
||||
0x78a7,
|
||||
0x0840,
|
||||
0x1861,
|
||||
0x2802,
|
||||
0x3823,
|
||||
0xc9cc,
|
||||
0xd9ed,
|
||||
0xe98e,
|
||||
0xf9af,
|
||||
0x8948,
|
||||
0x9969,
|
||||
0xa90a,
|
||||
0xb92b,
|
||||
0x5af5,
|
||||
0x4ad4,
|
||||
0x7ab7,
|
||||
0x6a96,
|
||||
0x1a71,
|
||||
0x0a50,
|
||||
0x3a33,
|
||||
0x2a12,
|
||||
0xdbfd,
|
||||
0xcbdc,
|
||||
0xfbbf,
|
||||
0xeb9e,
|
||||
0x9b79,
|
||||
0x8b58,
|
||||
0xbb3b,
|
||||
0xab1a,
|
||||
0x6ca6,
|
||||
0x7c87,
|
||||
0x4ce4,
|
||||
0x5cc5,
|
||||
0x2c22,
|
||||
0x3c03,
|
||||
0x0c60,
|
||||
0x1c41,
|
||||
0xedae,
|
||||
0xfd8f,
|
||||
0xcdec,
|
||||
0xddcd,
|
||||
0xad2a,
|
||||
0xbd0b,
|
||||
0x8d68,
|
||||
0x9d49,
|
||||
0x7e97,
|
||||
0x6eb6,
|
||||
0x5ed5,
|
||||
0x4ef4,
|
||||
0x3e13,
|
||||
0x2e32,
|
||||
0x1e51,
|
||||
0x0e70,
|
||||
0xff9f,
|
||||
0xefbe,
|
||||
0xdfdd,
|
||||
0xcffc,
|
||||
0xbf1b,
|
||||
0xaf3a,
|
||||
0x9f59,
|
||||
0x8f78,
|
||||
0x9188,
|
||||
0x81a9,
|
||||
0xb1ca,
|
||||
0xa1eb,
|
||||
0xd10c,
|
||||
0xc12d,
|
||||
0xf14e,
|
||||
0xe16f,
|
||||
0x1080,
|
||||
0x00a1,
|
||||
0x30c2,
|
||||
0x20e3,
|
||||
0x5004,
|
||||
0x4025,
|
||||
0x7046,
|
||||
0x6067,
|
||||
0x83b9,
|
||||
0x9398,
|
||||
0xa3fb,
|
||||
0xb3da,
|
||||
0xc33d,
|
||||
0xd31c,
|
||||
0xe37f,
|
||||
0xf35e,
|
||||
0x02b1,
|
||||
0x1290,
|
||||
0x22f3,
|
||||
0x32d2,
|
||||
0x4235,
|
||||
0x5214,
|
||||
0x6277,
|
||||
0x7256,
|
||||
0xb5ea,
|
||||
0xa5cb,
|
||||
0x95a8,
|
||||
0x8589,
|
||||
0xf56e,
|
||||
0xe54f,
|
||||
0xd52c,
|
||||
0xc50d,
|
||||
0x34e2,
|
||||
0x24c3,
|
||||
0x14a0,
|
||||
0x0481,
|
||||
0x7466,
|
||||
0x6447,
|
||||
0x5424,
|
||||
0x4405,
|
||||
0xa7db,
|
||||
0xb7fa,
|
||||
0x8799,
|
||||
0x97b8,
|
||||
0xe75f,
|
||||
0xf77e,
|
||||
0xc71d,
|
||||
0xd73c,
|
||||
0x26d3,
|
||||
0x36f2,
|
||||
0x0691,
|
||||
0x16b0,
|
||||
0x6657,
|
||||
0x7676,
|
||||
0x4615,
|
||||
0x5634,
|
||||
0xd94c,
|
||||
0xc96d,
|
||||
0xf90e,
|
||||
0xe92f,
|
||||
0x99c8,
|
||||
0x89e9,
|
||||
0xb98a,
|
||||
0xa9ab,
|
||||
0x5844,
|
||||
0x4865,
|
||||
0x7806,
|
||||
0x6827,
|
||||
0x18c0,
|
||||
0x08e1,
|
||||
0x3882,
|
||||
0x28a3,
|
||||
0xcb7d,
|
||||
0xdb5c,
|
||||
0xeb3f,
|
||||
0xfb1e,
|
||||
0x8bf9,
|
||||
0x9bd8,
|
||||
0xabbb,
|
||||
0xbb9a,
|
||||
0x4a75,
|
||||
0x5a54,
|
||||
0x6a37,
|
||||
0x7a16,
|
||||
0x0af1,
|
||||
0x1ad0,
|
||||
0x2ab3,
|
||||
0x3a92,
|
||||
0xfd2e,
|
||||
0xed0f,
|
||||
0xdd6c,
|
||||
0xcd4d,
|
||||
0xbdaa,
|
||||
0xad8b,
|
||||
0x9de8,
|
||||
0x8dc9,
|
||||
0x7c26,
|
||||
0x6c07,
|
||||
0x5c64,
|
||||
0x4c45,
|
||||
0x3ca2,
|
||||
0x2c83,
|
||||
0x1ce0,
|
||||
0x0cc1,
|
||||
0xef1f,
|
||||
0xff3e,
|
||||
0xcf5d,
|
||||
0xdf7c,
|
||||
0xaf9b,
|
||||
0xbfba,
|
||||
0x8fd9,
|
||||
0x9ff8,
|
||||
0x6e17,
|
||||
0x7e36,
|
||||
0x4e55,
|
||||
0x5e74,
|
||||
0x2e93,
|
||||
0x3eb2,
|
||||
0x0ed1,
|
||||
0x1ef0
|
||||
];
|
||||
|
||||
int crc_16(buffer) {
|
||||
var len = buffer.length;
|
||||
var value_ = 0x0000;//0xa635; //初始值,根据CRC类型设定
|
||||
var value_ = 0x0000; //0xa635; //初始值,根据CRC类型设定
|
||||
var tmp;
|
||||
for (var i = 0; i < buffer.length; i++)
|
||||
{
|
||||
for (var i = 0; i < buffer.length; i++) {
|
||||
tmp = reverse8(buffer[i]);
|
||||
value_ = ((value_ << 8) ^ crcTable[((value_ >> 8) ^ tmp) & 0xFF]) & 0xFFFF;
|
||||
value_ =
|
||||
((value_ << 8) ^ crcTable[((value_ >> 8) ^ tmp) & 0xFF]) & 0xFFFF;
|
||||
}
|
||||
value_ = reverse16(value_);
|
||||
return value_;
|
||||
@ -116,22 +360,21 @@ abstract class SenderProtocol extends IOData {
|
||||
|
||||
int reverse8(data) {
|
||||
var i;
|
||||
var temp=0;
|
||||
for(i=0;i<8;i++) {
|
||||
var temp = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
//字节反转
|
||||
temp |= ((data>>i) & 0x01)<<(7-i);
|
||||
temp |= ((data >> i) & 0x01) << (7 - i);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
int reverse16(data) {
|
||||
var i;
|
||||
var temp=0;
|
||||
for(i=0;i<16;i++) {
|
||||
var temp = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
//反转
|
||||
temp |= ((data>>i) & 0x0001)<<(15-i);
|
||||
temp |= ((data >> i) & 0x0001) << (15 - i);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
///发送数据类
|
||||
enum DataChannel{
|
||||
ble,
|
||||
udp
|
||||
}
|
||||
enum DataChannel { ble, udp }
|
||||
|
||||
extension Extension on DataChannel {
|
||||
bool get isBLE => this == DataChannel.ble;
|
||||
bool get isUDP => this == DataChannel.udp;
|
||||
bool get isBLE => this == DataChannel.ble;
|
||||
|
||||
bool get isUDP => this == DataChannel.udp;
|
||||
}
|
||||
|
||||
class EventSendModel {
|
||||
@ -20,8 +17,16 @@ class EventSendModel {
|
||||
String? deviceId;
|
||||
Uuid? serviceId;
|
||||
Uuid? characteristicId;
|
||||
bool? allowLongWrite = false;
|
||||
|
||||
EventSendModel({required this.data,this.topic,this.sendChannel, this.deviceId, this.serviceId, this.characteristicId});
|
||||
EventSendModel(
|
||||
{required this.data,
|
||||
this.topic,
|
||||
this.sendChannel,
|
||||
this.deviceId,
|
||||
this.serviceId,
|
||||
this.characteristicId,
|
||||
this.allowLongWrite});
|
||||
}
|
||||
|
||||
///接收数据类
|
||||
@ -30,26 +35,23 @@ class EventReceiveModel {
|
||||
String? tag = '';
|
||||
DataChannel? sendChannel;
|
||||
|
||||
EventReceiveModel({
|
||||
required this.data,
|
||||
this.sendChannel,
|
||||
this.tag});
|
||||
EventReceiveModel({required this.data, this.sendChannel, this.tag});
|
||||
}
|
||||
|
||||
|
||||
///解析数据域
|
||||
class EventParseModel {
|
||||
int? type;
|
||||
int? commandIndex;
|
||||
dynamic data;
|
||||
|
||||
EventParseModel({required this.type, required this.data, this.commandIndex});
|
||||
}
|
||||
|
||||
|
||||
///debug info model
|
||||
class StateModel {
|
||||
final String title;
|
||||
final String subTitle;
|
||||
final bool result;
|
||||
StateModel({this.title= '',this.subTitle = '',this.result = false});
|
||||
}
|
||||
|
||||
StateModel({this.title = '', this.subTitle = '', this.result = false});
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
//TODO:发送指令类型
|
||||
enum CommandType {
|
||||
addUser, //增加用户 = 0x3001
|
||||
@ -13,6 +12,9 @@ enum CommandType {
|
||||
getLockPrivateKey, // 获取锁私钥 = 0x3091
|
||||
calibrationTime, // 校时 = 0x30f0
|
||||
readStarLockStatusInfo, //读星锁状态信息 0x3040
|
||||
startOATUpgrade, //OTA升级开始 0x30E0
|
||||
confirmationOTAUpgrade, //OTA升级开始 0x30E1
|
||||
processOTAUpgrade, //OTA升级过程 0x30E2
|
||||
|
||||
generalExtendedCommond, // 通用扩展指令 = 0x3030
|
||||
gecChangeAdministratorPassword, // 通用扩展指令子命令-修改管理员密码 = 2
|
||||
@ -41,11 +43,10 @@ enum CommandType {
|
||||
gecAddFaceConfirmation, // 通用扩展指令子命令-添加人脸确认 = 84
|
||||
}
|
||||
|
||||
extension ExtensionCommandType on CommandType {
|
||||
|
||||
static CommandType getCommandType(int value){
|
||||
extension ExtensionCommandType on CommandType {
|
||||
static CommandType getCommandType(int value) {
|
||||
CommandType type = CommandType.readLockStatusInfo;
|
||||
switch(value){
|
||||
switch (value) {
|
||||
case 0x3001:
|
||||
{
|
||||
type = CommandType.addUser;
|
||||
@ -111,6 +112,21 @@ extension ExtensionCommandType on CommandType {
|
||||
type = CommandType.readStarLockStatusInfo;
|
||||
}
|
||||
break;
|
||||
case 0x30E0:
|
||||
{
|
||||
type = CommandType.startOATUpgrade;
|
||||
}
|
||||
break;
|
||||
case 0x30E1:
|
||||
{
|
||||
type = CommandType.processOTAUpgrade;
|
||||
}
|
||||
break;
|
||||
case 0x30E2:
|
||||
{
|
||||
type = CommandType.confirmationOTAUpgrade;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
type = CommandType.readLockStatusInfo;
|
||||
@ -122,7 +138,7 @@ extension ExtensionCommandType on CommandType {
|
||||
|
||||
int get typeValue {
|
||||
int type = 0x300A;
|
||||
switch(this){
|
||||
switch (this) {
|
||||
case CommandType.addUser:
|
||||
type = 0x3001;
|
||||
break;
|
||||
@ -162,6 +178,15 @@ extension ExtensionCommandType on CommandType {
|
||||
case CommandType.readStarLockStatusInfo:
|
||||
type = 0x3040;
|
||||
break;
|
||||
case CommandType.startOATUpgrade:
|
||||
type = 0x30E0;
|
||||
break;
|
||||
case CommandType.processOTAUpgrade:
|
||||
type = 0x30E1;
|
||||
break;
|
||||
case CommandType.confirmationOTAUpgrade:
|
||||
type = 0x30E2;
|
||||
break;
|
||||
default:
|
||||
type = 0x300A;
|
||||
break;
|
||||
@ -171,10 +196,13 @@ extension ExtensionCommandType on CommandType {
|
||||
return type;
|
||||
}
|
||||
|
||||
//加密类型
|
||||
int get identifierValue {
|
||||
int type = 0x23;
|
||||
switch(this){
|
||||
switch (this) {
|
||||
case CommandType.getLockPublicKey:
|
||||
case CommandType.processOTAUpgrade:
|
||||
//不加密
|
||||
type = 0x20;
|
||||
break;
|
||||
case CommandType.getLockPrivateKey:
|
||||
@ -187,64 +215,73 @@ extension ExtensionCommandType on CommandType {
|
||||
return type;
|
||||
}
|
||||
|
||||
String get typeName {
|
||||
String t = '';
|
||||
switch(typeValue){
|
||||
String get typeName {
|
||||
String t = '';
|
||||
switch (typeValue) {
|
||||
case 0x3001:
|
||||
t = '增加用户';
|
||||
t = '增加用户';
|
||||
break;
|
||||
case 0x3002:
|
||||
t = '删除用户';
|
||||
t = '删除用户';
|
||||
break;
|
||||
case 0x3003:
|
||||
t = '修改用户';
|
||||
t = '修改用户';
|
||||
break;
|
||||
case 0x3004:
|
||||
t = '恢复出厂设置';
|
||||
t = '恢复出厂设置';
|
||||
break;
|
||||
case 0x3005:
|
||||
t = '开门';
|
||||
t = '开门';
|
||||
break;
|
||||
case 0x300A:
|
||||
t = '读取锁状态信息';
|
||||
t = '读取锁状态信息';
|
||||
break;
|
||||
case 0x300B:
|
||||
t = '转移权限';
|
||||
t = '转移权限';
|
||||
break;
|
||||
case 0x3020:
|
||||
t = '开门记录上报';
|
||||
t = '开门记录上报';
|
||||
break;
|
||||
case 0x3030:
|
||||
t = '通用扩展指令';
|
||||
t = '通用扩展指令';
|
||||
break;
|
||||
case 0x3090:
|
||||
t = '获取锁公钥';
|
||||
t = '获取锁公钥';
|
||||
break;
|
||||
case 0x3091:
|
||||
t = '获取锁私钥';
|
||||
t = '获取锁私钥';
|
||||
break;
|
||||
case 0x30f0:
|
||||
t = '校时';
|
||||
t = '校时';
|
||||
break;
|
||||
case 0x30f1:
|
||||
t = '同步位置信息';
|
||||
t = '同步位置信息';
|
||||
break;
|
||||
case 0x30f2:
|
||||
t = '运维开锁';
|
||||
t = '运维开锁';
|
||||
break;
|
||||
case 0x3016:
|
||||
t = '写酒店信息';
|
||||
t = '写酒店信息';
|
||||
break;
|
||||
case 0x3017:
|
||||
t = '读酒店信息';
|
||||
t = '读酒店信息';
|
||||
break;
|
||||
case 0x3040:
|
||||
t = '读星锁状态信息';
|
||||
t = '读星锁状态信息';
|
||||
break;
|
||||
case 0x30E0:
|
||||
t = 'oat升级';
|
||||
break;
|
||||
case 0x30E2:
|
||||
t = '确认oat升级';
|
||||
break;
|
||||
case 0x30E1:
|
||||
t = 'oat升级过程';
|
||||
break;
|
||||
default:
|
||||
t = '读星锁状态信息';
|
||||
t = '读星锁状态信息';
|
||||
break;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ import 'package:star_lock/blue/io_protocol/io_deletUser.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_editUser.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_factoryDataReset.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_getLockStatu.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_otaUpgrade.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_processOtaUpgrade.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_queryingFaceStatus.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_readAdminPassword.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_readSupportFunctionsNoParameters.dart';
|
||||
@ -20,11 +22,14 @@ import 'package:star_lock/blue/io_protocol/io_timing.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_transferPermissions.dart';
|
||||
|
||||
import '../tools/storage.dart';
|
||||
|
||||
// import 'io_protocol/io_addFingerprint.dart';
|
||||
import 'io_protocol/io_addFingerprintWithTimeCycleCoercion.dart';
|
||||
|
||||
// import 'io_protocol/io_addICCard.dart';
|
||||
import 'io_protocol/io_addICCardWithTimeCycleCoercion.dart';
|
||||
import 'io_protocol/io_addStressFingerprint.dart';
|
||||
|
||||
// import 'io_protocol/io_addStressICCard.dart';
|
||||
import 'io_protocol/io_addStressPassword.dart';
|
||||
import 'io_protocol/io_addUser.dart';
|
||||
@ -59,7 +64,7 @@ class CommandReciverManager {
|
||||
return;
|
||||
}
|
||||
|
||||
Get.log("appDataReceiveData:$data"); // &&(data[4] == 0x11)
|
||||
// Get.log("appDataReceiveData:$data"); // &&(data[4] == 0x11)
|
||||
if ((data[0] == 0xEF) &&
|
||||
(data[1] == 0x01) &&
|
||||
(data[2] == 0xEE) &&
|
||||
@ -69,7 +74,7 @@ class CommandReciverManager {
|
||||
|
||||
var dataLen = data[8] * 256 + data[9]; // 高16位用来指示后面数据块内容的长度
|
||||
var oriLen = data[10] * 256 + data[11]; // 低16位用来指示数据加密前的原长度
|
||||
print("dataLen:$dataLen oriLen:$oriLen");
|
||||
// print("dataLen:$dataLen oriLen:$oriLen");
|
||||
// List<int> dataList = [];
|
||||
List<int> oriDataList = [];
|
||||
switch (tmpType) {
|
||||
@ -109,11 +114,11 @@ class CommandReciverManager {
|
||||
oriDataList = SM4.decrypt(getDataList,
|
||||
key: getPrivateKeyList, mode: SM4CryptoMode.ECB);
|
||||
oriDataList = oriDataList.sublist(0, oriLen);
|
||||
print("SM4 oriDataList:$oriDataList");
|
||||
// print("SM4 oriDataList:$oriDataList");
|
||||
break;
|
||||
}
|
||||
parseData(oriDataList).then((value) async {
|
||||
Get.log("parseData222 data:$value");
|
||||
// Get.log("parseData222 data:$value");
|
||||
EasyLoading.dismiss();
|
||||
await EventBusManager().eventBusFir(value);
|
||||
}).catchError((error) {
|
||||
@ -129,7 +134,7 @@ class CommandReciverManager {
|
||||
CommandType commandType = ExtensionCommandType.getCommandType(cmd);
|
||||
await IoManager().increaseCommandIndex();
|
||||
// data.removeRange(0, 2);
|
||||
Get.log("parseData cmd:$cmd commandType:$commandType data:$data");
|
||||
// Get.log("parseData cmd:$cmd commandType:$commandType data:$data");
|
||||
var reply;
|
||||
switch (commandType) {
|
||||
case CommandType.getLockPublicKey:
|
||||
@ -154,7 +159,7 @@ class CommandReciverManager {
|
||||
break;
|
||||
case CommandType.openLock:
|
||||
{
|
||||
Get.log("openLockReply data:$data");
|
||||
// Get.log("openLockReply data:$data");
|
||||
reply = OpenDoorReply.parseData(commandType, data);
|
||||
}
|
||||
break;
|
||||
@ -189,6 +194,21 @@ class CommandReciverManager {
|
||||
reply = GetStarLockStatuInfoReply.parseData(commandType, data);
|
||||
}
|
||||
break;
|
||||
case CommandType.startOATUpgrade:
|
||||
{
|
||||
reply = OTAUpgradeReply.parseData(commandType, data);
|
||||
}
|
||||
break;
|
||||
case CommandType.confirmationOTAUpgrade:
|
||||
{
|
||||
reply = ConfirmationOTAUpgradeReply.parseData(commandType, data);
|
||||
}
|
||||
break;
|
||||
case CommandType.processOTAUpgrade:
|
||||
{
|
||||
reply = ProcessOtaUpgradeReply.parseData(commandType, data);
|
||||
}
|
||||
break;
|
||||
case CommandType.generalExtendedCommond:
|
||||
{
|
||||
// 子命令类型
|
||||
@ -279,8 +299,9 @@ class CommandReciverManager {
|
||||
case 36:
|
||||
{
|
||||
// 注册指纹开始(带限时、循环、胁迫...)
|
||||
reply = SenderAddFingerprintWithTimeCycleCoercionReply.parseData(
|
||||
commandType, data);
|
||||
reply =
|
||||
SenderAddFingerprintWithTimeCycleCoercionReply.parseData(
|
||||
commandType, data);
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import '../app_settings/app_settings.dart';
|
||||
@ -11,22 +10,26 @@ import 'io_tool/manager_event_bus.dart';
|
||||
import 'sender_beforeDataManage.dart';
|
||||
|
||||
typedef CommandSendCallBack = void Function(ErrorType errorType);
|
||||
class CommandSenderManager {
|
||||
|
||||
class CommandSenderManager {
|
||||
static final CommandSenderManager _manager = CommandSenderManager._init();
|
||||
factory CommandSenderManager()=>_manager;
|
||||
static CommandSenderManager getInstance()=>_manager;
|
||||
CommandSenderManager._init(){
|
||||
|
||||
factory CommandSenderManager() => _manager;
|
||||
|
||||
static CommandSenderManager getInstance() => _manager;
|
||||
|
||||
CommandSenderManager._init() {
|
||||
init();
|
||||
}
|
||||
|
||||
init(){
|
||||
init() {
|
||||
initLockAddUserSucceedEvent();
|
||||
}
|
||||
|
||||
// 下级界面修改成功后传递数据
|
||||
StreamSubscription? _passCurrentLockInformationEvent;
|
||||
List<int> dataBeforeAddTheUser = [];
|
||||
|
||||
void initLockAddUserSucceedEvent() {
|
||||
// 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus
|
||||
_passCurrentLockInformationEvent = eventBus.on<LockAddUserSucceedEvent>().listen((event) {
|
||||
@ -55,7 +58,7 @@ class CommandSenderManager {
|
||||
}
|
||||
|
||||
List<int> value = command.packageData();
|
||||
print("CommonDataManage().currentLockUserNo:${CommonDataManage().currentLockUserNo}");
|
||||
// print("CommonDataManage().currentLockUserNo:${CommonDataManage().currentLockUserNo}");
|
||||
if(CommonDataManage().currentLockUserNo == 0){
|
||||
// 先添加用户
|
||||
var entity = await SenderBeforeDataManage().getAddUserKeyData();
|
||||
@ -63,7 +66,7 @@ class CommandSenderManager {
|
||||
dataBeforeAddTheUser = value;
|
||||
return;
|
||||
}else{
|
||||
print("继续发送数据了继续发送数据了继续发送数据了");
|
||||
// print("继续发送数据了继续发送数据了继续发送数据了");
|
||||
_sendNormalData(value);
|
||||
}
|
||||
}
|
||||
@ -132,4 +135,4 @@ class CommandSenderManager {
|
||||
dispose() {
|
||||
_passCurrentLockInformationEvent?.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import 'package:star_lock/blue/io_protocol/io_addFace.dart';
|
||||
|
||||
// import 'package:star_lock/blue/io_protocol/io_addICCard.dart';
|
||||
// import 'package:star_lock/blue/io_protocol/io_addStressICCard.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_changeAdministratorPassword.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_deletUser.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_getLockStatu.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_otaUpgrade.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_processOtaUpgrade.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_queryingFaceStatus.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_readAdminPassword.dart';
|
||||
|
||||
@ -359,23 +362,22 @@ class IoSenderManage {
|
||||
|
||||
//todo:添加指纹开始(带限时、循环、胁迫...)
|
||||
static void senderAddFingerprintWithTimeCycleCoercionCommand(
|
||||
{
|
||||
required String? keyID,
|
||||
required String? userID,
|
||||
required int? fingerNo,
|
||||
required int? useCountLimit,
|
||||
required int? isForce,
|
||||
required List<int>? token,
|
||||
required int? isRound,
|
||||
required int? weekRound,
|
||||
required int? startDate,
|
||||
required int? endDate,
|
||||
required String? startTime,
|
||||
required String? endTime,
|
||||
required int? needAuthor,
|
||||
required List<int>? signKey,
|
||||
required List<int>? privateKey,
|
||||
CommandSendCallBack? callBack}) {
|
||||
{required String? keyID,
|
||||
required String? userID,
|
||||
required int? fingerNo,
|
||||
required int? useCountLimit,
|
||||
required int? isForce,
|
||||
required List<int>? token,
|
||||
required int? isRound,
|
||||
required int? weekRound,
|
||||
required int? startDate,
|
||||
required int? endDate,
|
||||
required String? startTime,
|
||||
required String? endTime,
|
||||
required int? needAuthor,
|
||||
required List<int>? signKey,
|
||||
required List<int>? privateKey,
|
||||
CommandSendCallBack? callBack}) {
|
||||
CommandSenderManager().managerSendData(
|
||||
command: SenderAddFingerprintWithTimeCycleCoercionCommand(
|
||||
keyID: keyID,
|
||||
@ -428,23 +430,22 @@ class IoSenderManage {
|
||||
|
||||
//todo:添加卡开始(带限时、循环、胁迫...)
|
||||
static void senderAddCardWithTimeCycleCoercionCommand(
|
||||
{
|
||||
required String? keyID,
|
||||
required String? userID,
|
||||
required int? cardNo,
|
||||
required int? useCountLimit,
|
||||
required int? isForce,
|
||||
required List<int>? token,
|
||||
required int? isRound,
|
||||
required int? weekRound,
|
||||
required int? startDate,
|
||||
required int? endDate,
|
||||
required String? startTime,
|
||||
required String? endTime,
|
||||
required int? needAuthor,
|
||||
required List<int>? signKey,
|
||||
required List<int>? privateKey,
|
||||
CommandSendCallBack? callBack}) {
|
||||
{required String? keyID,
|
||||
required String? userID,
|
||||
required int? cardNo,
|
||||
required int? useCountLimit,
|
||||
required int? isForce,
|
||||
required List<int>? token,
|
||||
required int? isRound,
|
||||
required int? weekRound,
|
||||
required int? startDate,
|
||||
required int? endDate,
|
||||
required String? startTime,
|
||||
required String? endTime,
|
||||
required int? needAuthor,
|
||||
required List<int>? signKey,
|
||||
required List<int>? privateKey,
|
||||
CommandSendCallBack? callBack}) {
|
||||
CommandSenderManager().managerSendData(
|
||||
command: SenderAddICCardWithTimeCycleCoercionCommand(
|
||||
keyID: keyID,
|
||||
@ -469,20 +470,20 @@ class IoSenderManage {
|
||||
//todo:添加人脸开始
|
||||
static void senderAddFaceCommand(
|
||||
{required String? keyID,
|
||||
required String? userID,
|
||||
required int? faceNo,
|
||||
required int? useCountLimit,
|
||||
required int? isForce,
|
||||
required List<int>? token,
|
||||
required int? isRound,
|
||||
required int? weekRound,
|
||||
required int? startDate,
|
||||
required int? endDate,
|
||||
required String? startTime,
|
||||
required String? endTime,
|
||||
required int? needAuthor,
|
||||
required List<int>? signKey,
|
||||
required List<int>? privateKey,
|
||||
required String? userID,
|
||||
required int? faceNo,
|
||||
required int? useCountLimit,
|
||||
required int? isForce,
|
||||
required List<int>? token,
|
||||
required int? isRound,
|
||||
required int? weekRound,
|
||||
required int? startDate,
|
||||
required int? endDate,
|
||||
required String? startTime,
|
||||
required String? endTime,
|
||||
required int? needAuthor,
|
||||
required List<int>? signKey,
|
||||
required List<int>? privateKey,
|
||||
CommandSendCallBack? callBack}) {
|
||||
CommandSenderManager().managerSendData(
|
||||
command: SenderAddFaceCommand(
|
||||
@ -709,12 +710,12 @@ class IoSenderManage {
|
||||
//todo:wifi列表
|
||||
static void getWifiListCommand(
|
||||
{required String? keyID,
|
||||
required String? userID,
|
||||
required List<int>? token,
|
||||
required int? needAuthor,
|
||||
required List<int>? publicKey,
|
||||
required List<int>? privateKey,
|
||||
CommandSendCallBack? callBack}) {
|
||||
required String? userID,
|
||||
required List<int>? token,
|
||||
required int? needAuthor,
|
||||
required List<int>? publicKey,
|
||||
required List<int>? privateKey,
|
||||
CommandSendCallBack? callBack}) {
|
||||
CommandSenderManager().managerSendData(
|
||||
command: SenderGetWifiCommand(
|
||||
keyID: keyID,
|
||||
@ -977,4 +978,54 @@ class IoSenderManage {
|
||||
),
|
||||
callBack: callBack);
|
||||
}
|
||||
|
||||
//开始ota 升级
|
||||
static void senderOTAUpgradeCommand(
|
||||
{required String? lockID,
|
||||
required String? userID,
|
||||
required String? keyID,
|
||||
required int? platform,
|
||||
required int? product,
|
||||
required String? hwVersion,
|
||||
required String? fwVersion,
|
||||
required int? fwSize,
|
||||
required String? fwMD5,
|
||||
required int? needAuthor,
|
||||
required List<int>? token,
|
||||
required List<int>? publicKey,
|
||||
required List<int>? privateKey,
|
||||
CommandSendCallBack? callBack}) {
|
||||
CommandSenderManager().managerSendData(
|
||||
command: OTAUpgradeCommand(
|
||||
lockID: lockID,
|
||||
userID: userID,
|
||||
keyID: keyID,
|
||||
platform: platform,
|
||||
product: product,
|
||||
hwVersion: hwVersion,
|
||||
fwVersion: fwVersion,
|
||||
fwSize: fwSize,
|
||||
fwMD5: fwMD5,
|
||||
token: token,
|
||||
needAuthor: needAuthor,
|
||||
publicKey: publicKey,
|
||||
privateKey: privateKey,
|
||||
),
|
||||
callBack: callBack);
|
||||
}
|
||||
|
||||
//ota 升级过程
|
||||
static void senderProcessOtaUpgradeCommand(
|
||||
{required int? index,
|
||||
required int? size,
|
||||
required List<int>? data,
|
||||
CommandSendCallBack? callBack}) {
|
||||
CommandSenderManager().managerSendData(
|
||||
command: ProcessOtaUpgradeCommand(
|
||||
index: index,
|
||||
size: size,
|
||||
data: data,
|
||||
),
|
||||
callBack: callBack);
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,6 +50,7 @@ class _AddCardManageTabbarState extends State<AddCardManageTabbar>
|
||||
length: widget.fromType == 1 ? _itemTabs.length : _fromCheckInTypeItemTabs.length,
|
||||
initialIndex: widget.initialIndex);
|
||||
_tabController.addListener(() {
|
||||
print("_tabController.indexIsChanging:${_tabController.indexIsChanging} _tabController.index:${_tabController.index}");
|
||||
if (_tabController.animation!.value == _tabController.index) {
|
||||
FocusScope.of(context).requestFocus(FocusNode());
|
||||
}
|
||||
@ -107,8 +108,8 @@ class _AddCardManageTabbarState extends State<AddCardManageTabbar>
|
||||
controller: _tabController,
|
||||
children:
|
||||
widget.fromType == 1
|
||||
? _itemTabs.map((ItemView item) => AddCardPage(selectType: item.selectType, lockId: widget.lockId, fromType: widget.fromType, fromTypeTwoStaffName: widget.fromTypeTwoStaffName)).toList()
|
||||
: _fromCheckInTypeItemTabs.map((ItemView item) => AddCardPage(selectType: item.selectType, lockId: widget.lockId, fromType: widget.fromType, fromTypeTwoStaffName: widget.fromTypeTwoStaffName)).toList(),
|
||||
? _itemTabs.map((ItemView item) => AddCardPage()).toList()
|
||||
: _fromCheckInTypeItemTabs.map((ItemView item) => AddCardPage()).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -12,21 +12,23 @@ class AddCardTypeLogic extends BaseGetXController{
|
||||
|
||||
// 添加卡数据
|
||||
void addCardData() async {
|
||||
var fingerprintType = 0; // 永久:1;限时2,单次3,循环:4
|
||||
var carType = 0; // 永久:1;限时2,单次3,循环:4
|
||||
var startDate = "";
|
||||
var endDate = "";
|
||||
var startTime = "";
|
||||
var endTime = "";
|
||||
if (state.selectType.value == "0") {
|
||||
fingerprintType = 1;
|
||||
print("永久卡永久卡永久卡");
|
||||
carType = 1;
|
||||
startDate = "0";
|
||||
endDate = "0";
|
||||
startTime = "0";
|
||||
endTime = "0";
|
||||
} else if (state.selectType.value == "1") {
|
||||
fingerprintType = 2;
|
||||
startDate = DateTool().dateToTimestamp(state.beginTime.value, 1).toString();
|
||||
endDate = DateTool().dateToTimestamp(state.endTime.value, 1).toString();
|
||||
print("限时卡限时卡限时卡");
|
||||
carType = 2;
|
||||
startDate = DateTool().dateToTimestamp(state.timeLimitBeginTime.value, 1).toString();
|
||||
endDate = DateTool().dateToTimestamp(state.timeLimitEndTime.value, 1).toString();
|
||||
startTime = "0";
|
||||
endTime = "0";
|
||||
|
||||
@ -49,15 +51,16 @@ class AddCardTypeLogic extends BaseGetXController{
|
||||
return;
|
||||
}
|
||||
} else if (state.selectType.value == "2") {
|
||||
if (state.beginTime.value.isEmpty) {
|
||||
print("循环卡循环卡循环卡");
|
||||
if (state.cycleBeginTime.value.isEmpty) {
|
||||
showToast("请选择有效期".tr);
|
||||
return;
|
||||
}
|
||||
startDate = DateTool().dateToTimestamp(state.beginTime.value, 1).toString();
|
||||
endDate = DateTool().dateToTimestamp(state.endTime.value, 1).toString();
|
||||
startDate = DateTool().dateToTimestamp(state.cycleBeginTime.value, 1).toString();
|
||||
endDate = DateTool().dateToTimestamp(state.cycleEndTime.value, 1).toString();
|
||||
startTime = DateTool().dateToTimestamp(state.effectiveDateTime.value, 0).toString();
|
||||
endTime = DateTool().dateToTimestamp(state.failureDateTime.value, 0).toString();
|
||||
fingerprintType = 4;
|
||||
carType = 4;
|
||||
}
|
||||
|
||||
// var isCoerced = state.isStressFingerprint.value == false ? "1" : "2"; // 1:非胁迫卡 2:胁迫卡
|
||||
@ -67,7 +70,7 @@ class AddCardTypeLogic extends BaseGetXController{
|
||||
"addType": "1",
|
||||
"cardName": state.nameController.text,
|
||||
"cardNumber": "123456",
|
||||
"cardType": fingerprintType.toString(),
|
||||
"cardType": carType.toString(),
|
||||
"isCoerced": state.isStressFingerprint.value == false ? "1" : "2",
|
||||
"startDate": startDate,
|
||||
"weekDay": state.weekdaysList.value,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@ -8,110 +9,113 @@ import 'package:star_lock/tools/pickers/time_picker/model/date_mode.dart';
|
||||
|
||||
import '../../../../appRouters.dart';
|
||||
import '../../../../app_settings/app_colors.dart';
|
||||
import '../../../../tools/CustomUnderlineTabIndicator.dart';
|
||||
import '../../../../tools/commonItem.dart';
|
||||
import '../../../../tools/dateTool.dart';
|
||||
import '../../../../tools/storage.dart';
|
||||
import '../../../../tools/submitBtn.dart';
|
||||
import '../../../../tools/titleAppBar.dart';
|
||||
import '../../../../translations/trans_lib.dart';
|
||||
import 'addCardType_logic.dart';
|
||||
|
||||
class AddCardPage extends StatefulWidget {
|
||||
final String selectType; // 永久限时循环下标
|
||||
final int lockId;
|
||||
final int fromType; // // 1从添加钥匙列表进入 2从考勤添加员工入口进入
|
||||
final String fromTypeTwoStaffName; // 从添加员工进入 传入员工名字
|
||||
|
||||
const AddCardPage(
|
||||
{Key? key,
|
||||
required this.selectType,
|
||||
required this.lockId,
|
||||
required this.fromType,
|
||||
required this.fromTypeTwoStaffName})
|
||||
: super(key: key);
|
||||
const AddCardPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<AddCardPage> createState() => _AddCardPageState();
|
||||
}
|
||||
|
||||
class _AddCardPageState extends State<AddCardPage> {
|
||||
class _AddCardPageState extends State<AddCardPage> with SingleTickerProviderStateMixin {
|
||||
final logic = Get.put(AddCardTypeLogic());
|
||||
final state = Get.find<AddCardTypeLogic>().state;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
state.selectType.value = widget.selectType;
|
||||
state.lockId.value = widget.lockId;
|
||||
if (widget.fromTypeTwoStaffName.isNotEmpty) {
|
||||
state.nameController.text = widget.fromTypeTwoStaffName;
|
||||
}
|
||||
state.fromType.value = widget.fromType;
|
||||
|
||||
return SingleChildScrollView(
|
||||
child: indexChangeWidget()
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (state.selectType.value == "1") {
|
||||
state.beginTime.value = DateTool().dateToYMDHNString(
|
||||
DateTime.now().millisecondsSinceEpoch.toString()); //默认为当前时间
|
||||
state.endTime.value = DateTool().dateToYMDHNString(
|
||||
DateTime.now().millisecondsSinceEpoch.toString()); //默认为当前时间
|
||||
} else {
|
||||
state.beginTime.value = ""; //默认为当前时间
|
||||
state.endTime.value = ""; //默认为当前时间
|
||||
state.tabController = TabController(
|
||||
vsync: this,
|
||||
length: state.fromType.value == 1 ? _itemTabs.length : _fromCheckInTypeItemTabs.length,
|
||||
initialIndex: 0);
|
||||
state.tabController.addListener(() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
state.selectType.value = state.tabController.index.toString();
|
||||
});
|
||||
|
||||
if (state.tabController.animation!.value == state.tabController.index) {
|
||||
FocusScope.of(context).requestFocus(FocusNode());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.mainBackgroundColor,
|
||||
appBar: TitleAppBar(
|
||||
barTitle:
|
||||
"${TranslationLoader.lanKeys!.addTip!.tr}${TranslationLoader.lanKeys!.card!.tr}",
|
||||
haveBack: true,
|
||||
backgroundColor: AppColors.mainColor),
|
||||
body: Column(
|
||||
children: [
|
||||
_tabBar(),
|
||||
_pageWidget(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget indexChangeWidget() {
|
||||
switch (int.parse(widget.selectType)) {
|
||||
switch (int.parse(state.selectType.value)) {
|
||||
case 0:
|
||||
{
|
||||
// 永久
|
||||
return Column(
|
||||
children: [
|
||||
perpetualKeyWidget(
|
||||
TranslationLoader.lanKeys!.name!.tr,
|
||||
TranslationLoader.lanKeys!.pleaseEnter!.tr,
|
||||
state.nameController),
|
||||
keyBottomWidget()
|
||||
],
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
perpetualKeyWidget(
|
||||
TranslationLoader.lanKeys!.name!.tr,
|
||||
TranslationLoader.lanKeys!.pleaseEnter!.tr,
|
||||
state.nameController),
|
||||
keyBottomWidget()
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// 限时
|
||||
return Column(
|
||||
children: [
|
||||
perpetualKeyWidget(
|
||||
TranslationLoader.lanKeys!.name!.tr,
|
||||
TranslationLoader.lanKeys!.pleaseEnter!.tr,
|
||||
state.nameController),
|
||||
keyTimeLimitWidget(),
|
||||
// SizedBox(height: 10.h),
|
||||
keyBottomWidget()
|
||||
],
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
perpetualKeyWidget(
|
||||
TranslationLoader.lanKeys!.name!.tr,
|
||||
TranslationLoader.lanKeys!.pleaseEnter!.tr,
|
||||
state.nameController),
|
||||
keyTimeLimitWidget(),
|
||||
// SizedBox(height: 10.h),
|
||||
keyBottomWidget()
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
// 循环
|
||||
return Column(
|
||||
children: [
|
||||
perpetualKeyWidget(
|
||||
TranslationLoader.lanKeys!.name!.tr,
|
||||
TranslationLoader.lanKeys!.pleaseEnter!.tr,
|
||||
state.nameController),
|
||||
keyCyclicDate(),
|
||||
SizedBox(height: 10.h),
|
||||
keyBottomWidget()
|
||||
],
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
perpetualKeyWidget(
|
||||
TranslationLoader.lanKeys!.name!.tr,
|
||||
TranslationLoader.lanKeys!.pleaseEnter!.tr,
|
||||
state.nameController),
|
||||
keyCyclicDate(),
|
||||
SizedBox(height: 10.h),
|
||||
keyBottomWidget()
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
default:
|
||||
@ -140,23 +144,23 @@ class _AddCardPageState extends State<AddCardPage> {
|
||||
children: [
|
||||
Obx(() => CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr,
|
||||
rightTitle: state.beginTime.value,
|
||||
rightTitle: state.timeLimitBeginTime.value,
|
||||
isHaveLine: true,
|
||||
isHaveDirection: true,
|
||||
action: () async {
|
||||
Pickers.showDatePicker(context, mode: DateMode.YMDHM,
|
||||
onConfirm: (p) {
|
||||
state.beginTime.value = DateTool().getYMDHNDateString(p, 1);
|
||||
state.timeLimitBeginTime.value = DateTool().getYMDHNDateString(p, 1);
|
||||
});
|
||||
})),
|
||||
Obx(() => CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.failureTime!.tr,
|
||||
rightTitle: state.endTime.value,
|
||||
rightTitle: state.timeLimitEndTime.value,
|
||||
isHaveDirection: true,
|
||||
action: () {
|
||||
Pickers.showDatePicker(context, mode: DateMode.YMDHM,
|
||||
onConfirm: (p) {
|
||||
state.endTime.value = DateTool().getYMDHNDateString(p, 1);
|
||||
state.timeLimitEndTime.value = DateTool().getYMDHNDateString(p, 1);
|
||||
});
|
||||
})),
|
||||
Container(height: 10.h),
|
||||
@ -170,21 +174,21 @@ class _AddCardPageState extends State<AddCardPage> {
|
||||
children: [
|
||||
Obx(() => CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.periodValidity!.tr,
|
||||
rightTitle: "${state.beginTime.value}\n${state.endTime.value}",
|
||||
rightTitle:"${state.cycleBeginTime.value}\n${state.cycleEndTime.value}",
|
||||
isHaveDirection: true,
|
||||
isHaveLine: true,
|
||||
action: () async {
|
||||
var result = await Get.toNamed(Routers.seletKeyCyclicDatePage, arguments: {
|
||||
'validityValue': state.weekdaysList.value,
|
||||
'starDate': state.beginTime.value,
|
||||
'endDate': state.endTime.value,
|
||||
'starDate': state.cycleBeginTime.value,
|
||||
'endDate': state.cycleEndTime.value,
|
||||
'starTime': state.effectiveDateTime.value,
|
||||
'endTime': state.failureDateTime.value
|
||||
});
|
||||
if (result != null && result.isNotEmpty) {
|
||||
state.weekdaysList.value = result['validityValue'];
|
||||
state.beginTime.value = result['starDate'];
|
||||
state.endTime.value = result['endDate'];
|
||||
state.cycleBeginTime.value = result['starDate'];
|
||||
state.cycleEndTime.value = result['endDate'];
|
||||
state.effectiveDateTime.value = result['starTime'];
|
||||
state.failureDateTime.value = result['endTime'];
|
||||
}
|
||||
@ -197,18 +201,17 @@ class _AddCardPageState extends State<AddCardPage> {
|
||||
isHaveDirection: true,
|
||||
isHaveLine: true,
|
||||
action: () async {
|
||||
var result = await Get.toNamed(Routers.seletKeyCyclicDatePage,
|
||||
arguments: {
|
||||
'validityValue': state.weekdaysList.value,
|
||||
'starDate': state.beginTime.value,
|
||||
'endDate': state.endTime.value,
|
||||
'starTime': state.effectiveDateTime.value,
|
||||
'endTime': state.failureDateTime.value
|
||||
});
|
||||
var result = await Get.toNamed(Routers.seletKeyCyclicDatePage, arguments: {
|
||||
'validityValue': state.weekdaysList.value,
|
||||
'starDate': state.cycleBeginTime.value,
|
||||
'endDate': state.cycleEndTime.value,
|
||||
'starTime': state.effectiveDateTime.value,
|
||||
'endTime': state.failureDateTime.value
|
||||
});
|
||||
if (result != null && result.isNotEmpty) {
|
||||
state.weekdaysList.value = result['validityValue'];
|
||||
state.beginTime.value = result['starDate'];
|
||||
state.endTime.value = result['endDate'];
|
||||
state.cycleBeginTime.value = result['starDate'];
|
||||
state.cycleEndTime.value = result['endDate'];
|
||||
state.effectiveDateTime.value = result['starTime'];
|
||||
state.failureDateTime.value = result['endTime'];
|
||||
}
|
||||
@ -217,25 +220,22 @@ class _AddCardPageState extends State<AddCardPage> {
|
||||
visible: state.effectiveDateTime.value.isNotEmpty,
|
||||
child: CommonItem(
|
||||
leftTitel: "有效时间".tr,
|
||||
rightTitle:
|
||||
"${state.effectiveDateTime.value}-${state.failureDateTime.value}",
|
||||
rightTitle: "${state.effectiveDateTime.value}-${state.failureDateTime.value}",
|
||||
isHaveDirection: true,
|
||||
action: () async {
|
||||
var result = await Get.toNamed(Routers.seletKeyCyclicDatePage,
|
||||
arguments: {
|
||||
'validityValue': state.weekdaysList.value,
|
||||
'starDate': state.beginTime.value,
|
||||
'endDate': state.endTime.value,
|
||||
'starTime': state.effectiveDateTime.value,
|
||||
'endTime': state.failureDateTime.value
|
||||
});
|
||||
var result = await Get.toNamed(Routers.seletKeyCyclicDatePage, arguments: {
|
||||
'validityValue': state.weekdaysList.value,
|
||||
'starDate': state.cycleBeginTime.value,
|
||||
'endDate': state.cycleEndTime.value,
|
||||
'starTime': state.effectiveDateTime.value,
|
||||
'endTime': state.failureDateTime.value
|
||||
});
|
||||
if (result != null && result.isNotEmpty) {
|
||||
state.weekdaysList.value = result['validityValue'];
|
||||
state.beginTime.value = result['starDate'];
|
||||
state.endTime.value = result['endDate'];
|
||||
state.cycleBeginTime.value = result['starDate'];
|
||||
state.cycleEndTime.value = result['endDate'];
|
||||
state.effectiveDateTime.value = result['starTime'];
|
||||
state.failureDateTime.value = result['endTime'];
|
||||
Get.back(result: result);
|
||||
}
|
||||
}))),
|
||||
],
|
||||
@ -290,25 +290,6 @@ class _AddCardPageState extends State<AddCardPage> {
|
||||
);
|
||||
}
|
||||
|
||||
String getAppBarTitle(int type) {
|
||||
String title;
|
||||
switch (type) {
|
||||
case 0:
|
||||
title = TranslationLoader.lanKeys!.stressCard!.tr;
|
||||
break;
|
||||
case 1:
|
||||
title = TranslationLoader.lanKeys!.stressFingerprint!.tr;
|
||||
break;
|
||||
case 2:
|
||||
title = TranslationLoader.lanKeys!.remoteControl!.tr;
|
||||
break;
|
||||
default:
|
||||
title = "";
|
||||
break;
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
// 接受者信息输入框
|
||||
Widget getTFWidget(String tfStr) {
|
||||
return Container(
|
||||
@ -387,4 +368,70 @@ class _AddCardPageState extends State<AddCardPage> {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
final List<ItemView> _itemTabs = <ItemView>[
|
||||
ItemView(title: TranslationLoader.lanKeys!.permanent!.tr, selectType: "0"),
|
||||
ItemView(title: TranslationLoader.lanKeys!.timeLimit!.tr, selectType: "1"),
|
||||
ItemView(title: TranslationLoader.lanKeys!.circulation!.tr, selectType: "2"),
|
||||
];
|
||||
|
||||
final List<ItemView> _fromCheckInTypeItemTabs = <ItemView>[
|
||||
ItemView(title: TranslationLoader.lanKeys!.permanent!.tr, selectType: "0"),
|
||||
ItemView(title: TranslationLoader.lanKeys!.timeLimit!.tr, selectType: "1"),
|
||||
];
|
||||
|
||||
TabBar _tabBar() {
|
||||
return TabBar(
|
||||
controller: state.tabController,
|
||||
onTap: (index) {
|
||||
FocusScope.of(context).requestFocus(FocusNode());
|
||||
},
|
||||
tabs: state.fromType.value == 1 ? _itemTabs.map((ItemView item) => _tab(item)).toList() : _fromCheckInTypeItemTabs.map((ItemView item) => _tab(item)).toList(),
|
||||
isScrollable: true,
|
||||
indicatorColor: Colors.red,
|
||||
unselectedLabelColor: Colors.black,
|
||||
unselectedLabelStyle: TextStyle(
|
||||
color: AppColors.mainColor,
|
||||
fontSize: 24.sp,
|
||||
),
|
||||
automaticIndicatorColorAdjustment: true,
|
||||
labelColor: AppColors.mainColor,
|
||||
labelStyle: TextStyle(
|
||||
color: AppColors.mainColor,
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w600),
|
||||
indicator: CustomUnderlineTabIndicator(
|
||||
borderSide: BorderSide(color: AppColors.mainColor, width: 4.w),
|
||||
strokeCap: StrokeCap.round,
|
||||
width: 30.w),
|
||||
);
|
||||
}
|
||||
|
||||
Tab _tab(ItemView item) {
|
||||
return Tab(
|
||||
child: SizedBox(
|
||||
width: 1.sw / 5,
|
||||
child: Text(item.title, textAlign: TextAlign.center)));
|
||||
}
|
||||
|
||||
Widget _pageWidget() {
|
||||
return Expanded(
|
||||
child: TabBarView(
|
||||
controller: state.tabController,
|
||||
children:
|
||||
state.fromType.value == 1
|
||||
? _itemTabs.map((ItemView item) => Obx(() => indexChangeWidget())).toList()
|
||||
: _fromCheckInTypeItemTabs.map((ItemView item) => Obx(() => indexChangeWidget())).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ItemView {
|
||||
const ItemView({required this.title, required this.selectType});
|
||||
|
||||
final String title;
|
||||
final String selectType;
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../../tools/dateTool.dart';
|
||||
|
||||
class AddCardTypeState{
|
||||
|
||||
final lockId = 0.obs;
|
||||
@ -10,16 +12,24 @@ class AddCardTypeState{
|
||||
final isStressFingerprint = false.obs;
|
||||
final isAdministrator = false.obs;// 是否是管理员
|
||||
|
||||
var beginTime = "".obs;// 开始时间
|
||||
var endTime = "".obs;// 结束时间
|
||||
var timeLimitBeginTime = DateTool().dateToYMDHNString(DateTime.now().millisecondsSinceEpoch.toString()).obs;// 限时开始时间
|
||||
var timeLimitEndTime = DateTool().dateToYMDHNString(DateTime.now().millisecondsSinceEpoch.toString()).obs;// 限时结束时间
|
||||
var cycleBeginTime = "".obs;// 循环开始时间
|
||||
var cycleEndTime = "".obs;// 循环结束时间
|
||||
var effectiveDateTime = "".obs;// 生效时间
|
||||
var failureDateTime = "".obs;// 失效时间
|
||||
var weekdaysList = [].obs;
|
||||
var fromTypeTwoStaffName = "".obs; // 从添加员工进入 传入员工名字
|
||||
|
||||
final TextEditingController nameController = TextEditingController();
|
||||
late TabController tabController;
|
||||
AddCardTypeState() {
|
||||
// Map map = Get.arguments;
|
||||
// lockId.value = map["lockId"];
|
||||
// fromType.value = map["fromType"];
|
||||
Map map = Get.arguments;
|
||||
lockId.value = map["lockId"];
|
||||
fromType.value = map["fromType"];
|
||||
// 1从添加钥匙列表进入 2从考勤添加员工入口进入
|
||||
if(fromType.value == 2){
|
||||
fromTypeTwoStaffName.value = map["fromTypeTwoStaffName"]; // 从添加员工进入 传入员工名字
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ class _CardListPageState extends State<CardListPage> with RouteAware {
|
||||
AddBottomWhiteBtn(
|
||||
btnName: '${TranslationLoader.lanKeys!.add!.tr}${TranslationLoader.lanKeys!.card!.tr}',
|
||||
onClick: () async {
|
||||
var data = await Get.toNamed(Routers.addCardTypeManagePage, arguments: {
|
||||
var data = await Get.toNamed(Routers.addCardPage, arguments: {
|
||||
"lockId": state.lockId.value,
|
||||
"fromType": 1 // 1从添加钥匙列表进入 2从考勤添加员工入口进入
|
||||
});
|
||||
|
||||
@ -151,7 +151,7 @@ class _CheckingInAddStaffPageState extends State<CheckingInAddStaffPage> {
|
||||
}
|
||||
|
||||
var data = await Get.toNamed(
|
||||
Routers.addCardTypeManagePage,
|
||||
Routers.addCardPage,
|
||||
arguments: {
|
||||
"lockId": state.getKeyInfosData.value.lockId,
|
||||
"fromType": 2, // 1从添加钥匙列表进入 2从考勤添加员工入口进入
|
||||
|
||||
@ -34,7 +34,7 @@ class LockDetailLogic extends BaseGetXController {
|
||||
// 监听设备返回的数据
|
||||
void initReplySubscription() {
|
||||
state.replySubscription = EventBusManager().eventBus!.on<Reply>().listen((reply) async {
|
||||
Get.log("锁详情收到了蓝牙解析消息 reply:${reply.commandType}");
|
||||
// Get.log("锁详情收到了蓝牙解析消息 reply:${reply.commandType}");
|
||||
// 开门
|
||||
if (reply is OpenDoorReply && state.ifCurrentScreen.value == true) {
|
||||
_replyOpenLock(reply);
|
||||
@ -496,7 +496,7 @@ class LockDetailLogic extends BaseGetXController {
|
||||
void getLockNetToken() async {
|
||||
LockNetTokenEntity entity = await ApiRepository.to.getLockNetToken(lockId: state.keyInfos.value.lockId.toString());
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
state.lockNetToken = entity.data!.token!;
|
||||
state.lockNetToken = entity.data!.token!.toString();
|
||||
Get.log("state.lockNetToken:${state.lockNetToken}");
|
||||
openDoorAction();
|
||||
}else{
|
||||
|
||||
@ -27,7 +27,7 @@ class LockNetTokenEntity {
|
||||
}
|
||||
|
||||
class Data {
|
||||
String? token;
|
||||
int? token;
|
||||
|
||||
Data({this.token});
|
||||
|
||||
|
||||
@ -1,14 +1,41 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:star_lock/blue/blue_manage.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_otaUpgrade.dart';
|
||||
import 'package:star_lock/blue/io_protocol/io_processOtaUpgrade.dart';
|
||||
import 'package:star_lock/blue/io_reply.dart';
|
||||
import 'package:star_lock/blue/io_tool/io_tool.dart';
|
||||
import 'package:star_lock/blue/io_tool/manager_event_bus.dart';
|
||||
import 'package:star_lock/blue/sender_manage.dart';
|
||||
import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSet_logic.dart';
|
||||
import 'package:star_lock/permission/permission_dialog.dart';
|
||||
import 'package:star_lock/tools/advancedCalendar/src/datetime_util.dart';
|
||||
import 'package:star_lock/tools/baseGetXController.dart';
|
||||
import 'package:star_lock/tools/commonDataManage.dart';
|
||||
import 'package:star_lock/tools/pickers/time_picker/time_utils.dart';
|
||||
import 'package:star_lock/tools/storage.dart';
|
||||
|
||||
import 'lockEscalation_state.dart';
|
||||
|
||||
class LockEscalationLogic extends BaseGetXController{
|
||||
class LockEscalationLogic extends BaseGetXController {
|
||||
LockEscalationState state = LockEscalationState();
|
||||
StreamSubscription<Reply>? _replySubscription;
|
||||
|
||||
int otaCount = 0;
|
||||
int otaIndex = 0;
|
||||
Uint8List? otaBin;
|
||||
int startSecond = 0;
|
||||
|
||||
// 锁升级
|
||||
Future<void> setLockSetGeneralSetting() async{
|
||||
Future<void> setLockSetGeneralSetting() async {
|
||||
// var entity = await ApiRepository.to.getLockVersionInfoData(
|
||||
// lockId: state.getKeyInfosData.value.lockId.toString(),
|
||||
// );
|
||||
@ -17,24 +44,193 @@ class LockEscalationLogic extends BaseGetXController{
|
||||
// }
|
||||
}
|
||||
|
||||
//手动升级
|
||||
Future<void> otaUpdate() async {
|
||||
var status = await PermissionDialog.request(
|
||||
Permission.storage, '需要访问读写权限才能使用手动升级固件');
|
||||
if (status != true) {
|
||||
return;
|
||||
}
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles();
|
||||
if (result == null || result.files.single.path is! String) {
|
||||
return;
|
||||
}
|
||||
File file = File(result.files.single.path!);
|
||||
Uint8List data = await file.readAsBytes();
|
||||
Map? headJson = await getHeadFile(data);
|
||||
if (headJson is! Map) {
|
||||
return;
|
||||
}
|
||||
otaBin = await checkFile(data, headJson);
|
||||
if (otaBin == null) {
|
||||
return;
|
||||
}
|
||||
startOTAData();
|
||||
blueOTAUpgrade(headJson);
|
||||
}
|
||||
|
||||
//蓝牙操作 ota 升级
|
||||
void blueOTAUpgrade(Map data) {
|
||||
BlueManage().bludSendData(BlueManage().connectDeviceName,
|
||||
(BluetoothConnectionState deviceConnectionState) async {
|
||||
if (deviceConnectionState == BluetoothConnectionState.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!);
|
||||
String lockID = CommonDataManage.shareManager()
|
||||
?.currentLockSetInfoData
|
||||
.lockId
|
||||
?.toString() ??
|
||||
'';
|
||||
String keyID =
|
||||
CommonDataManage.shareManager()?.currentKeyInfo.keyId?.toString() ??
|
||||
'';
|
||||
BlueManage().writeCharacteristicWithResponse(OTAUpgradeCommand(
|
||||
lockID: lockID,
|
||||
userID: await Storage.getUid(),
|
||||
keyID: keyID,
|
||||
platform: int.tryParse(data['platform']) ?? 0,
|
||||
product: int.tryParse(data['product']) ?? 0,
|
||||
hwVersion: data['hwVersion'],
|
||||
fwVersion: data['fwVersion'],
|
||||
fwSize: data['fwSize'],
|
||||
fwMD5: data['fwMd5'],
|
||||
needAuthor: 1,
|
||||
token: getTokenList,
|
||||
publicKey: getPublicKeyList,
|
||||
privateKey: getPrivateKeyList)
|
||||
.packageData());
|
||||
} else if (deviceConnectionState ==
|
||||
BluetoothConnectionState.disconnected) {}
|
||||
});
|
||||
}
|
||||
|
||||
//循环传输升级固件包
|
||||
Future<void> processOtaUpgrade() async {
|
||||
if (!state.otaUpdateIng.value) {
|
||||
return;
|
||||
}
|
||||
int length = otaBin?.length ?? 0;
|
||||
if (otaCount == 0) {
|
||||
//首次
|
||||
int difference = length % 240;
|
||||
otaCount = length ~/ 240 + (difference > 0 ? 1 : 0);
|
||||
startSecond = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
}
|
||||
if (otaCount <= otaIndex) {
|
||||
int now = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
String msg = '传输完成 时间:${now - startSecond}秒';
|
||||
closeOTADAta();
|
||||
print(msg);
|
||||
showToast(msg);
|
||||
return;
|
||||
}
|
||||
int star = otaIndex * 240;
|
||||
int end = (otaIndex + 1) * 240;
|
||||
if (end > length) {
|
||||
end = length;
|
||||
}
|
||||
List<int> data = otaBin!.sublist(star, end);
|
||||
state.otaProgress.value = otaIndex / otaCount;
|
||||
await BlueManage().writeCharacteristicWithResponse(
|
||||
ProcessOtaUpgradeCommand(index: otaIndex, size: length, data: data)
|
||||
.packageData());
|
||||
}
|
||||
|
||||
//开始 ota升级
|
||||
void startOTAData() {
|
||||
state.otaUpdateIng.value = true;
|
||||
}
|
||||
|
||||
//清楚 ata 安装文件
|
||||
void closeOTADAta() {
|
||||
state.otaUpdateIng.value = false;
|
||||
state.otaProgress.value = 0;
|
||||
otaIndex = 0;
|
||||
otaCount = 0;
|
||||
startSecond = 0;
|
||||
otaBin = null;
|
||||
}
|
||||
|
||||
// 拦截返回事件
|
||||
void getBack() {
|
||||
if (state.otaUpdateIng.value) {
|
||||
closeOTADAta();
|
||||
} else {
|
||||
Get.back();
|
||||
}
|
||||
}
|
||||
|
||||
// 检查文件头
|
||||
Future<Map?> getHeadFile(Uint8List data) async {
|
||||
// 检查文件头
|
||||
String header = utf8.decode(data.sublist(0, 12));
|
||||
if (header != 'SYD-BIN-DATA') {
|
||||
showToast('非SYD固件,请选择正确的文件');
|
||||
return null;
|
||||
}
|
||||
// 解析元数据长度
|
||||
Uint8List metaLenList = data.sublist(12, 16);
|
||||
int metaLen = ByteData.sublistView(metaLenList).getUint32(0);
|
||||
if (metaLen < 2 || metaLen > 10240) {
|
||||
showToast('元数据长度错误');
|
||||
return null;
|
||||
}
|
||||
// 读取和解析元数据
|
||||
Uint8List metaStrList = data.sublist(16, 16 + metaLen);
|
||||
String metaStr = utf8.decode(metaStrList);
|
||||
print(metaStr);
|
||||
var meta = jsonDecode(metaStr);
|
||||
return meta..['metaLen'] = metaLen;
|
||||
}
|
||||
|
||||
//检测升级文件并读取 bin
|
||||
Future<Uint8List?> checkFile(Uint8List data, Map meta) async {
|
||||
num binOffset = 16 + (meta['metaLen'] ?? 0);
|
||||
// 获取固件数据部分
|
||||
Uint8List bin = data.sublist(binOffset.toInt(), data.length);
|
||||
//md5 校验有问题,暂时不解析
|
||||
// String md5Str = md5.convert(bin).toString();
|
||||
// if (md5Str != meta['fwMd5']) {
|
||||
// showToast('固件MD5校验失败');
|
||||
// return false;
|
||||
// }
|
||||
if (bin.length != meta['fwSize']) {
|
||||
showToast('固件校验失败');
|
||||
return null;
|
||||
}
|
||||
return bin;
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
// TODO: implement onReady
|
||||
super.onReady();
|
||||
print("onReady()");
|
||||
setLockSetGeneralSetting();
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
// TODO: implement onInit
|
||||
super.onInit();
|
||||
print("onInit()");
|
||||
_replySubscription =
|
||||
EventBusManager().eventBus!.on<Reply>().listen((reply) {
|
||||
if (reply is OTAUpgradeReply && reply.status == 0x00) {
|
||||
//验证通过,开始发送数据包
|
||||
processOtaUpgrade();
|
||||
} else if (reply is ProcessOtaUpgradeReply && reply.status == 0x00) {
|
||||
otaIndex++;
|
||||
processOtaUpgrade();
|
||||
} else if (reply is ConfirmationOTAUpgradeReply && reply.status == 0x00) {
|
||||
closeOTADAta();
|
||||
showToast('固件升级完成');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
_replySubscription?.cancel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -16,66 +16,152 @@ class LockEscalationPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _LockEscalationPageState extends State<LockEscalationPage> {
|
||||
final logic = Get.put(LockEscalationLogic());
|
||||
final state = Get.find<LockEscalationLogic>().state;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: TitleAppBar(
|
||||
barTitle: TranslationLoader.lanKeys!.lockEscalation!.tr,
|
||||
haveBack: true,
|
||||
backgroundColor: AppColors.mainColor),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(30.w),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 60.h,
|
||||
return GetBuilder<LockEscalationLogic>(
|
||||
init: LockEscalationLogic(),
|
||||
builder: (LockEscalationLogic logic) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: TitleAppBar(
|
||||
barTitle: TranslationLoader.lanKeys!.lockEscalation!.tr,
|
||||
haveBack: true,
|
||||
backgroundColor: AppColors.mainColor,
|
||||
backAction: logic.getBack,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'images/main/icon_main_lockSet_lockEscalation.png',
|
||||
width: 36.w,
|
||||
height: 36.w,
|
||||
),
|
||||
SizedBox(
|
||||
width: 10.w,
|
||||
),
|
||||
Text(
|
||||
TranslationLoader.lanKeys!.haveNewVersion!.tr,
|
||||
style:
|
||||
TextStyle(fontSize: 24.sp, fontWeight: FontWeight.w600),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 30.h,
|
||||
),
|
||||
Text(
|
||||
"${TranslationLoader.lanKeys!.currentVersion!.tr}:1.0.0",
|
||||
style: TextStyle(
|
||||
fontSize: 18.sp, color: AppColors.darkGrayTextColor),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
),
|
||||
Text(
|
||||
// "${TranslationLoader.lanKeys!.newVersion!.tr}:1.0.1",
|
||||
"未发现新版本",
|
||||
style: TextStyle(color: AppColors.mainColor, fontSize: 18.sp),
|
||||
),
|
||||
SizedBox(
|
||||
height: 40.h,
|
||||
),
|
||||
SubmitBtn(
|
||||
btnName: TranslationLoader.lanKeys!.upgrade!.tr,
|
||||
onClick: () {}),
|
||||
],
|
||||
),
|
||||
));
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(30.w),
|
||||
child: Column(
|
||||
children: [
|
||||
Obx(() {
|
||||
return logic.state.otaUpdateIng.value
|
||||
? PopScope(
|
||||
canPop: false,
|
||||
onPopInvoked: (didPop) async {
|
||||
if (logic.state.otaUpdateIng.value) {
|
||||
logic.closeOTADAta();
|
||||
}
|
||||
},
|
||||
child: SizedBox(),
|
||||
)
|
||||
: SizedBox();
|
||||
}),
|
||||
SizedBox(
|
||||
height: 60.h,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'images/main/icon_main_lockSet_lockEscalation.png',
|
||||
width: 36.w,
|
||||
height: 36.w,
|
||||
),
|
||||
SizedBox(
|
||||
width: 10.w,
|
||||
),
|
||||
Text(
|
||||
TranslationLoader.lanKeys!.haveNewVersion!.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 24.sp, fontWeight: FontWeight.w600),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 30.h,
|
||||
),
|
||||
Text(
|
||||
"${TranslationLoader.lanKeys!.currentVersion!.tr}:1.0.0",
|
||||
style: TextStyle(
|
||||
fontSize: 18.sp, color: AppColors.darkGrayTextColor),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
),
|
||||
Obx(() {
|
||||
return !logic.state.otaUpdateIng.value
|
||||
? Stack(
|
||||
children: [
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 8, bottom: 8),
|
||||
width: Get.width,
|
||||
child: Center(
|
||||
child: Text(
|
||||
// "${TranslationLoader.lanKeys!.newVersion!.tr}:1.0.1",
|
||||
"未发现新版本",
|
||||
style: TextStyle(
|
||||
color: AppColors.mainColor,
|
||||
fontSize: 18.sp),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 80.w,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
logic.otaUpdate();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
'手动升级',
|
||||
style: TextStyle(
|
||||
color: AppColors.mainColor,
|
||||
fontSize: 18.sp,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 50.w, vertical: 15.h),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'固件传输中',
|
||||
style: TextStyle(
|
||||
color: AppColors.mainColor,
|
||||
fontSize: 18.sp,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10.w,
|
||||
),
|
||||
Expanded(
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(10.r)),
|
||||
child: LinearProgressIndicator(
|
||||
value: logic
|
||||
.state.otaProgress.value, // 50% 进度
|
||||
backgroundColor: Colors.grey[200],
|
||||
valueColor:
|
||||
AlwaysStoppedAnimation<Color>(
|
||||
AppColors.mainColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
SizedBox(
|
||||
height: 40.h,
|
||||
),
|
||||
Obx(() {
|
||||
return !logic.state.otaUpdateIng.value
|
||||
? SubmitBtn(
|
||||
btnName: TranslationLoader.lanKeys!.upgrade!.tr,
|
||||
onClick: () {})
|
||||
: SizedBox();
|
||||
}),
|
||||
],
|
||||
),
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class LockEscalationState{
|
||||
|
||||
class LockEscalationState {
|
||||
var otaUpdateIng = false.obs;
|
||||
var otaProgress = 0.00.obs;
|
||||
}
|
||||
|
||||
@ -10,12 +10,14 @@ import 'package:star_lock/network/api_repository.dart';
|
||||
import 'package:star_lock/tools/eventBusEventManage.dart';
|
||||
|
||||
import '../../../../blue/blue_manage.dart';
|
||||
import '../../../../blue/io_modelVendor.dart';
|
||||
import '../../../../blue/io_reply.dart';
|
||||
import '../../../../blue/io_protocol/io_senderCustomPasswords.dart';
|
||||
import '../../../../blue/io_tool/io_tool.dart';
|
||||
import '../../../../blue/io_tool/manager_event_bus.dart';
|
||||
import '../../../../blue/sender_manage.dart';
|
||||
import '../../../../tools/baseGetXController.dart';
|
||||
import '../../../../tools/commonDataManage.dart';
|
||||
import '../../../../tools/dateTool.dart';
|
||||
import '../../../../tools/storage.dart';
|
||||
|
||||
@ -46,31 +48,36 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
|
||||
String lockId = state.keyInfo.value.lockId.toString();
|
||||
String getKeyType = state.widgetType.value.toString();
|
||||
|
||||
if (state.nameController.text.isEmpty) {
|
||||
showToast("请输入姓名".tr);
|
||||
return;
|
||||
}
|
||||
if (state.nameController.text.isEmpty) {
|
||||
showToast("请输入姓名".tr);
|
||||
return;
|
||||
}
|
||||
|
||||
//循环密码
|
||||
if (state.widgetType.value == 4) {
|
||||
if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) {
|
||||
showToast("生效时间不能小于当前时间".tr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (state.widgetType.value == 0) {
|
||||
//永久
|
||||
getKeyType = '2';
|
||||
} else if (state.widgetType.value == 1) {
|
||||
//限时
|
||||
if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) {
|
||||
showToast("生效时间不能小于当前时间".tr);
|
||||
return;
|
||||
// 鑫鸿佳不需要生效时间
|
||||
if(CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XHJ && (CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XHJ_SYD || CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XHJ_JL)){
|
||||
if (endDate <= DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) {
|
||||
showToast("失效时间要大于当前时间".tr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (startDate >= endDate) {
|
||||
showToast("失效时间要大于生效时间".tr);
|
||||
return;
|
||||
// 芯连需要生效时间
|
||||
if(CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XL && (CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_BLE || CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_WIFI)){
|
||||
//限时
|
||||
if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) {
|
||||
showToast("生效时间不能小于当前时间".tr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (startDate >= endDate) {
|
||||
showToast("失效时间要大于生效时间".tr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
getKeyType = '3';
|
||||
} else if (state.widgetType.value == 2) {
|
||||
@ -80,9 +87,16 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
|
||||
//自定义
|
||||
} else if (state.widgetType.value == 4) {
|
||||
//循环
|
||||
//限时
|
||||
if (endDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) {
|
||||
showToast("结束时间不能小于当前时间".tr);
|
||||
// 芯连需要结束时间
|
||||
if(CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XL && (CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_BLE || CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_WIFI)){
|
||||
if (endDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) {
|
||||
showToast("结束时间不能小于当前时间".tr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.loopStartHours.value >= state.loopEndHours.value) {
|
||||
showToast("失效时间要大于生效时间".tr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/app_settings/app_colors.dart';
|
||||
import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart';
|
||||
import 'package:star_lock/tools/commonDataManage.dart';
|
||||
import 'package:star_lock/tools/pickers/pickers.dart';
|
||||
import 'package:star_lock/tools/pickers/style/default_style.dart';
|
||||
import 'package:star_lock/tools/pickers/time_picker/model/date_mode.dart';
|
||||
@ -14,6 +15,7 @@ import 'package:star_lock/tools/storage.dart';
|
||||
|
||||
import '../../../../appRouters.dart';
|
||||
import '../../../../blue/blue_manage.dart';
|
||||
import '../../../../blue/io_modelVendor.dart';
|
||||
import '../../../../tools/NativeInteractionTool.dart';
|
||||
import '../../../../tools/appRouteObserver.dart';
|
||||
import '../../../../tools/commonItem.dart';
|
||||
@ -193,22 +195,25 @@ class _PasswordKeyPerpetualPageState extends State<PasswordKeyPerpetualPage> wit
|
||||
Widget keyTimeLimitWidget() {
|
||||
return Column(
|
||||
children: [
|
||||
CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr,
|
||||
rightTitle: state.beginTime.value,
|
||||
isHaveLine: true,
|
||||
isHaveDirection: true,
|
||||
action: () {
|
||||
Pickers.showDatePicker(context, mode: state.widgetType.value == 3 ? DateMode.YMDHM:DateMode.YMDH, onConfirm: (p) {
|
||||
if (state.widgetType.value == 3) {
|
||||
// 自定义
|
||||
state.beginTime.value = DateTool().getYMDHNDateString(p, 1);
|
||||
} else {
|
||||
state.beginTime.value = DateTool().getYMDHNDateString(p, 4);
|
||||
}
|
||||
Get.log("beginTime:${state.beginTime.value}");
|
||||
});
|
||||
}),
|
||||
Visibility(
|
||||
visible: CommonDataManage().currentKeyInfo.vendor == "XHJ" ? false : true,
|
||||
child: CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr,
|
||||
rightTitle: state.beginTime.value,
|
||||
isHaveLine: true,
|
||||
isHaveDirection: true,
|
||||
action: () {
|
||||
Pickers.showDatePicker(context, mode: state.widgetType.value == 3 ? DateMode.YMDHM:DateMode.YMDH, onConfirm: (p) {
|
||||
if (state.widgetType.value == 3) {
|
||||
// 自定义
|
||||
state.beginTime.value = DateTool().getYMDHNDateString(p, 1);
|
||||
} else {
|
||||
state.beginTime.value = DateTool().getYMDHNDateString(p, 4);
|
||||
}
|
||||
Get.log("beginTime:${state.beginTime.value}");
|
||||
});
|
||||
}),
|
||||
),
|
||||
CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.failureTime!.tr,
|
||||
rightTitle: state.endTime.value,
|
||||
@ -286,16 +291,19 @@ class _PasswordKeyPerpetualPageState extends State<PasswordKeyPerpetualPage> wit
|
||||
];
|
||||
showPickerView(context, pickerDataList);
|
||||
}),
|
||||
CommonItem(
|
||||
leftTitel: '结束日期',
|
||||
rightTitle: state.endTime.value,
|
||||
isHaveLine: true,
|
||||
isHaveDirection: true,
|
||||
action: () {
|
||||
Pickers.showDatePicker(context, mode: DateMode.YMDH, onConfirm: (p) {
|
||||
state.endTime.value = DateTool().getYMDHNDateString(p, 4);
|
||||
});
|
||||
}),
|
||||
Visibility(
|
||||
visible: (CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XL && (CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_BLE || CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_WIFI)) ? true : false,
|
||||
child: CommonItem(
|
||||
leftTitel: '结束日期',
|
||||
rightTitle: state.endTime.value,
|
||||
isHaveLine: true,
|
||||
isHaveDirection: true,
|
||||
action: () {
|
||||
Pickers.showDatePicker(context, mode: DateMode.YMDH, onConfirm: (p) {
|
||||
state.endTime.value = DateTool().getYMDHNDateString(p, 4);
|
||||
});
|
||||
}),
|
||||
),
|
||||
CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr,
|
||||
rightTitle: state.loopEffectiveDate.value,
|
||||
|
||||
@ -122,6 +122,10 @@ class LockListInfoItemEntity {
|
||||
int? senderUserId;
|
||||
int? electricQuantityDate;
|
||||
int? electricQuantityStandby;
|
||||
int? isOnlyManageSelf;
|
||||
int? restoreCount;
|
||||
String? model;
|
||||
String? vendor;
|
||||
Bluetooth? bluetooth;
|
||||
LockFeature? lockFeature;
|
||||
LockSetting? lockSetting;
|
||||
@ -153,7 +157,11 @@ class LockListInfoItemEntity {
|
||||
this.lockUserNo,
|
||||
this.electricQuantityDate,
|
||||
this.electricQuantityStandby,
|
||||
this.senderUserId});
|
||||
this.senderUserId,
|
||||
this.isOnlyManageSelf,
|
||||
this.restoreCount,
|
||||
this.model,
|
||||
this.vendor});
|
||||
|
||||
LockListInfoItemEntity.fromJson(Map<String, dynamic> json) {
|
||||
keyId = json['keyId'];
|
||||
@ -180,6 +188,10 @@ class LockListInfoItemEntity {
|
||||
senderUserId = json['senderUserId'];
|
||||
electricQuantityDate = json['electricQuantityDate'];
|
||||
electricQuantityStandby = json['electricQuantityStandby'];
|
||||
isOnlyManageSelf = json['isOnlyManageSelf'];
|
||||
restoreCount = json['restoreCount'];
|
||||
model = json['model'];
|
||||
vendor = json['vendor'];
|
||||
bluetooth = json['bluetooth'] != null
|
||||
? Bluetooth.fromJson(json['bluetooth'])
|
||||
: null;
|
||||
@ -217,6 +229,10 @@ class LockListInfoItemEntity {
|
||||
data['senderUserId'] = senderUserId;
|
||||
data['electricQuantityDate'] = electricQuantityDate;
|
||||
data['electricQuantityStandby'] = electricQuantityStandby;
|
||||
data['isOnlyManageSelf'] = isOnlyManageSelf;
|
||||
data['restoreCount'] = restoreCount;
|
||||
data['model'] = model;
|
||||
data['vendor'] = vendor;
|
||||
if (bluetooth != null) {
|
||||
data['bluetooth'] = bluetooth!.toJson();
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ class PermissionDialog {
|
||||
}
|
||||
|
||||
//显示权限判断申请框
|
||||
static Future<bool> request(Permission permission) async {
|
||||
static Future<bool> request(Permission permission, [String? content]) async {
|
||||
if (Get.context == null) {
|
||||
return false;
|
||||
}
|
||||
@ -99,7 +99,7 @@ class PermissionDialog {
|
||||
canPop: false,
|
||||
child: CupertinoAlertDialog(
|
||||
title: Text('${'申请'.tr}${titles[permission] ?? ''}${'权限'.tr}'),
|
||||
content: Text(contents[permission] ?? ''),
|
||||
content: Text(content ?? contents[permission] ?? ''),
|
||||
actions: [
|
||||
CupertinoDialogAction(
|
||||
child: Text('不允许'.tr),
|
||||
|
||||
@ -94,7 +94,7 @@ dependencies:
|
||||
#跳转到外部
|
||||
url_launcher: ^6.1.10
|
||||
#蓝牙
|
||||
# flutter_reactive_ble: ^5.1.1
|
||||
# flutter_reactive_ble: ^5.1.1
|
||||
flutter_blue_plus: ^1.31.16
|
||||
#
|
||||
event_bus: ^2.0.0
|
||||
@ -123,7 +123,7 @@ dependencies:
|
||||
|
||||
# 谷歌地图
|
||||
google_maps_flutter: ^2.2.5
|
||||
# geocoding: ^2.1.0
|
||||
# geocoding: ^2.1.0
|
||||
|
||||
# 允许App发现网络的相关信息并且进行相应的配置
|
||||
network_info_plus: ^4.0.2
|
||||
@ -144,12 +144,12 @@ dependencies:
|
||||
image_gallery_saver: ^2.0.3
|
||||
convert: ^3.1.1
|
||||
just_audio: ^0.9.36
|
||||
# flutter_sound: ^9.2.13
|
||||
# ffmpeg_kit_flutter: 5.1.0-LTS
|
||||
# flutter_sound: ^9.2.13
|
||||
# ffmpeg_kit_flutter: 5.1.0-LTS
|
||||
fast_gbk: ^1.0.0
|
||||
flutter_pcm_sound: ^1.1.0
|
||||
intl: ^0.18.0
|
||||
# flutter_audio_capture: <1.1.5
|
||||
# flutter_audio_capture: <1.1.5
|
||||
|
||||
flutter_voice_processor: ^1.1.1
|
||||
#监听网络连接状态
|
||||
@ -165,6 +165,7 @@ dependencies:
|
||||
system_settings: ^2.0.0
|
||||
expandable: ^5.0.1
|
||||
colorfilter_generator: ^0.0.8
|
||||
file_picker: ^5.3.1
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user