diff --git a/star_lock/lib/blue/blue_manage.dart b/star_lock/lib/blue/blue_manage.dart index 3a38a19e..d757eba7 100644 --- a/star_lock/lib/blue/blue_manage.dart +++ b/star_lock/lib/blue/blue_manage.dart @@ -28,10 +28,12 @@ class BlueManage{ String connectDeviceMacAddress = ""; String connectDeviceName = ""; - final int _limitLen = 20; + // final int _limitLen = 20; // 监听发送事件 StreamSubscription? _sendStreamSubscription; + StreamSubscription? _scanSubscription; + // 监听蓝牙连接状态 DeviceConnectionState? deviceConnectionState = DeviceConnectionState.disconnected; @@ -64,25 +66,41 @@ class BlueManage{ } /// 开始扫描蓝牙设备 - void startScan(ScanResultCallBack scanResultCallBack) { + void startScan(bool isScanAll, ScanResultCallBack scanResultCallBack) { _scanDevices.clear(); - _flutterReactiveBle!.scanForDevices(withServices: []).listen((device) { + _scanSubscription = _flutterReactiveBle!.scanForDevices(withServices: []).listen((device) { // 判断名字为空的直接剔除 if(device.name.isEmpty){ return; } - // print("startScanDevice:${device}"); - if (((device.serviceUuids.isNotEmpty ? device.serviceUuids[0] : "").toString().contains("758824")) && ((device.serviceUuids.isNotEmpty ? device.serviceUuids[0] : "").toString()[31] != "1") && (device.rssi >= -100)) { - final knownDeviceIndex = _scanDevices.indexWhere((d) => d.id == device.id); - - if (knownDeviceIndex >= 0) { - _scanDevices[knownDeviceIndex] = device; - } else { - _scanDevices.add(device); + print("startScanDevice:${device}"); + // 判断是否 + if(isScanAll == true){ + if (((device.serviceUuids.isNotEmpty ? device.serviceUuids[0] : "").toString().contains("758824"))&& (device.rssi >= -100)) { + // 查询id相同的元素 + final knownDeviceIndex = _scanDevices.indexWhere((d) => d.id == device.id); + // 不存在的时候返回-1 + if (knownDeviceIndex >= 0) { + _scanDevices[knownDeviceIndex] = device; + } else { + _scanDevices.add(device); + } + scanResultCallBack(_scanDevices); + } + }else{ + if (((device.serviceUuids.isNotEmpty ? device.serviceUuids[0] : "").toString().contains("758824")) && ((device.serviceUuids.isNotEmpty ? device.serviceUuids[0] : "").toString()[31] != "1") && (device.rssi >= -100)) { + // 查询id相同的元素 + final knownDeviceIndex = _scanDevices.indexWhere((d) => d.id == device.id); + // 不存在的时候返回-1 + if (knownDeviceIndex >= 0) { + _scanDevices[knownDeviceIndex] = device; + } else { + _scanDevices.add(device); + } + scanResultCallBack(_scanDevices); } - scanResultCallBack(_scanDevices); } - // _pushState(); + }, onError: (Object e) { print('Device scan fails with error: $e'); }); @@ -161,7 +179,7 @@ class BlueManage{ IoSenderManage.getPublicKey(lockId: deviceName); // } } - connectStateCallBack!(connectionStateUpdate.connectionState); + // connectStateCallBack!(connectionStateUpdate.connectionState); } on Exception catch (e) { EasyLoading.dismiss(); print('Error occurred when discovering services: $e'); @@ -175,6 +193,12 @@ class BlueManage{ ); } + /// 停止扫描蓝牙设备 + Future stopScan() async { + await _scanSubscription?.cancel(); + _scanSubscription = null; + } + // 断开连接 Future disconnect(String deviceMAC) async { try { @@ -263,24 +287,34 @@ class BlueManage{ // code to handle incoming data print("subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data"); var dataLen = 0;// 高16位用来指示后面数据块内容的长度 - if((data[0] != 0xEF)&&(data[1] != 0x01)&&(data[2] != 0xEE)&&(data[3] != 0x02)){ - // 分包 - allData.addAll(data); - }else{ + + if((data[0] == 0xEF)&&(data[1] == 0x01)&&(data[2] == 0xEE)&&(data[3] == 0x02)){ + // 当包有头时 + // 判断是否需要分包 dataLen = data[8] * 256 + data[9]; - allData = []; - // 初始化数组为空 - if(dataLen > (data.length - 12)){ - // 进来先添加,还有包等待接收 + print("dataLen1111:$dataLen getDataLength:${data.length}"); + if(dataLen + 12 > data.length){ + // 当前包的长度小于实际的包时 分包添加 不解析 allData.addAll(data); - return; }else{ - // 不需要分包的直接赋值 - allData = data; + // 当前包的长度小于实际的包时 不分包 解析 + allData.addAll(data); + CommandReciverManager.appDataReceive(allData); + // 发送完解析初始化数组 + allData = []; + } + }else{ + // 当包没有头时 是分包的包 直接添加 + allData.addAll(data); + // var len = allData[8] * 256 + allData[9]; + print("dataLen222:$dataLen"); + if(dataLen <= (allData.length - 14)){ + // 当长度小于等于当前包的数据时 直接解析数据 + CommandReciverManager.appDataReceive(allData); + // 发送完解析初始化数组 + allData = []; } } - - CommandReciverManager.appDataReceive(allData); }, onError: (dynamic error) { EasyLoading.dismiss(); print("subscribeToCharacteristic error:$error"); @@ -291,11 +325,11 @@ class BlueManage{ Future writeCharacteristicWithResponse(List value) async { QualifiedCharacteristic characteristic = QualifiedCharacteristic(characteristicId: characteristicIdWrite, serviceId: serviceId, deviceId: connectDeviceMacAddress); print('Write with characteristicId:${characteristic.characteristicId} serviceId:${characteristic.serviceId} deviceId:${characteristic.deviceId} value : $value \nhexStr:${radixHex16String(value)}'); - int mtuLength = await _flutterReactiveBle!.requestMtu(deviceId: characteristic.deviceId, mtu: 512); + int mtuLength = await _flutterReactiveBle!.requestMtu(deviceId: characteristic.deviceId, mtu: 250); print("mtuLength:$mtuLength"); try { List valueList = value; - List subData = splitList(valueList, _limitLen); + List subData = splitList(valueList, mtuLength); print('得到的分割数据:$subData'); for (int i = 0; i < subData.length; i++) { diff --git a/star_lock/lib/blue/io_protocol/io_getPrivateKey.dart b/star_lock/lib/blue/io_protocol/io_getPrivateKey.dart index 5112bc0f..5862925d 100644 --- a/star_lock/lib/blue/io_protocol/io_getPrivateKey.dart +++ b/star_lock/lib/blue/io_protocol/io_getPrivateKey.dart @@ -65,11 +65,11 @@ class GetPrivateKeyCommand extends SenderProtocol { //NowTime 4 // DateTime now = DateTime.now(); // int timestamp = now.millisecondsSinceEpoch; - var d1 = 0x11223344; - data.add((d1 & 0xff000000) >> 24); - data.add((d1 & 0xff0000) >> 16); - data.add((d1 & 0xff00) >> 8); - data.add((d1 & 0xff)); + // var d1 = 0x11223344; + data.add((nowTime! & 0xff000000) >> 24); + data.add((nowTime! & 0xff0000) >> 16); + data.add((nowTime! & 0xff00) >> 8); + data.add((nowTime! & 0xff)); if (needAuthor == 0) { data.add(0); @@ -85,11 +85,11 @@ class GetPrivateKeyCommand extends SenderProtocol { //NowTime 4 // DateTime now = DateTime.now(); // int timestamp = now.millisecondsSinceEpoch; - var d1 = 0x11223344; - authCodeData.add((d1 & 0xff000000) >> 24); - authCodeData.add((d1 & 0xff0000) >> 16); - authCodeData.add((d1 & 0xff00) >> 8); - authCodeData.add((d1 & 0xff)); + // var d1 = 0x11223344; + authCodeData.add((nowTime! & 0xff000000) >> 24); + authCodeData.add((nowTime! & 0xff0000) >> 16); + authCodeData.add((nowTime! & 0xff00) >> 8); + authCodeData.add((nowTime! & 0xff)); authCodeData.addAll(publicKeyData!); diff --git a/star_lock/lib/blue/io_tool/io_tool.dart b/star_lock/lib/blue/io_tool/io_tool.dart index 54c7dd3a..25103157 100644 --- a/star_lock/lib/blue/io_tool/io_tool.dart +++ b/star_lock/lib/blue/io_tool/io_tool.dart @@ -256,17 +256,25 @@ List intToByte2ListLow(int value) => [value >> 8, value]; String radixHex16String(List codeUnits) { String result = ''; - codeUnits.forEach((value) { + for (var value in codeUnits) { result += value.toRadixString(16).padLeft(2, '0'); + } + return result; +} + +String radixHex16StringTo2String(List codeUnits) { + String result = ''; + codeUnits.forEach((value) { + result += int.parse(value.toRadixString(16).padLeft(2, '0'),radix: 16).toRadixString(2); }); return result; } String asciiString(List codeUnits) { String result = ''; - codeUnits.forEach((value) { + for (var value in codeUnits) { result += String.fromCharCode(value); - }); + } return result; } diff --git a/star_lock/lib/main.dart b/star_lock/lib/main.dart index 7202e3ad..dce34459 100644 --- a/star_lock/lib/main.dart +++ b/star_lock/lib/main.dart @@ -15,6 +15,8 @@ import 'appRouters.dart'; import 'baseWidget.dart'; import 'tools/appRouteObserver.dart'; import 'tools/store_service.dart'; +import 'dart:io'; +import 'package:flutter/services.dart'; void main() async { @@ -24,6 +26,11 @@ void main() async { await _initTranslation(); runApp(MyApp()); + + if (Platform.isAndroid) { + SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle(statusBarColor: Colors.transparent); + SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle); + } } class MyApp extends StatefulWidget { diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index 266d1b37..c525ba4c 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -394,7 +394,7 @@ class LockDetailLogic extends BaseGetXController{ // 点击开门事件 Future openDoorAction() async { - BlueManage().judgeReconnect(state.keyInfos.value.bluetooth!.bluetoothDeviceId!, state.keyInfos.value.bluetooth!.bluetoothDeviceName!, (DeviceConnectionState state) async { + BlueManage().judgeReconnect(BlueManage().connectDeviceMacAddress, state.keyInfos.value.bluetooth!.bluetoothDeviceName!, (DeviceConnectionState state) async { if (state == DeviceConnectionState.connected){ var privateKey = await Storage.getStringList(saveBluePrivateKey); List getPrivateKeyList = changeStringListToIntList(privateKey!); @@ -483,9 +483,9 @@ class LockDetailLogic extends BaseGetXController{ } // 备用逻辑,进入管理钥匙界面获取锁状态 - Future connectBlue() async { + Future connectBlue(String bluetoothDeviceId, String bluetoothDeviceName) async { // 进来之后首先连接 - BlueManage().connect(state.keyInfos.value.bluetooth!.bluetoothDeviceId!, state.keyInfos.value.bluetooth!.bluetoothDeviceName!, connectStateCallBack: (DeviceConnectionState state) async { + BlueManage().connect(bluetoothDeviceId, bluetoothDeviceName, connectStateCallBack: (DeviceConnectionState state) async { if (state == DeviceConnectionState.connected){ var privateKey = await Storage.getStringList(saveBluePrivateKey); List getPrivateKeyList = changeStringListToIntList(privateKey!); @@ -503,6 +503,18 @@ class LockDetailLogic extends BaseGetXController{ }, isShowLoading: false); } + void startScanAction(){ + BlueManage().startScan(true, (v){ + // print("startScanAllDevice:${v}"); + final knownDeviceIndex = v.indexWhere((d) => d.name == state.keyInfos.value.bluetooth!.bluetoothDeviceName!); + // 当扫描到的时候 + if (knownDeviceIndex >= 0) { + connectBlue(v[knownDeviceIndex].id, state.keyInfos.value.bluetooth!.bluetoothDeviceName!); + BlueManage().connectDeviceMacAddress = v[knownDeviceIndex].id; + } + }); + } + @override void onReady() { // TODO: implement onReady @@ -510,9 +522,7 @@ class LockDetailLogic extends BaseGetXController{ print("onReady()"); _initReplySubscription(); - // BlueManage().startScan((v){ - // - // }); + startScanAction(); } @override diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart index d3ab0d5a..3207ef57 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -42,8 +42,8 @@ class _LockDetailPageState extends State with RouteAware { state.keyInfos.value = widget.keyInfo; BlueManage().connectDeviceName = state.keyInfos.value.bluetooth!.bluetoothDeviceName!; - BlueManage().connectDeviceMacAddress = - state.keyInfos.value.bluetooth!.bluetoothDeviceId!; + // BlueManage().connectDeviceMacAddress = + // state.keyInfos.value.bluetooth!.bluetoothDeviceId!; List publicKeyData = state.keyInfos.value.bluetooth!.publicKey!.cast(); @@ -63,7 +63,7 @@ class _LockDetailPageState extends State with RouteAware { Storage.setStringList(saveBlueSignKey, saveSignKeyList); // print("publicKeyData:$publicKeyData saveStrList:$saveStrList privateKeyData:$privateKeyData savePrivateKeyList:$savePrivateKeyList"); - logic.connectBlue(); + // logic.startScanAction(); } @override @@ -338,6 +338,7 @@ class _LockDetailPageState extends State with RouteAware { bottomItem( 'images/main/icon_main_set.png', TranslationLoader.lanKeys!.set!.tr, () { + BlueManage().stopScan(); Get.toNamed(Routers.lockSetPage, arguments: widget.keyInfo); }), ]; diff --git a/star_lock/lib/mine/addLock/addLock/addLock_page.dart b/star_lock/lib/mine/addLock/addLock/addLock_page.dart index cd10b81f..3ac9ff55 100644 --- a/star_lock/lib/mine/addLock/addLock/addLock_page.dart +++ b/star_lock/lib/mine/addLock/addLock/addLock_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:permission_handler/permission_handler.dart'; import '../../../appRouters.dart'; import '../../../app_settings/app_colors.dart'; @@ -70,13 +71,41 @@ class _AddLockPageState extends State with BaseWidget { btnName: TranslationLoader.lanKeys!.next!.tr, borderRadius: 20.w, onClick: () { - Navigator.pushNamed(context, Routers.nearbyLockPage); + getMicrophonePermission() + .then((value) { + if (value) { + // 有权限 + Navigator.pushNamed(context, Routers.nearbyLockPage); + }else{ + //没有权限 + openAppSettings();//打开app系统设置 + } + }); + }), ], ), ); } + ///请求录音相机权限 + Future getMicrophonePermission() async { + // You can request multiple permissions at once. + Map statuses = await [ + Permission.bluetoothScan, + Permission.bluetoothConnect, + Permission.location, + ].request(); + + //granted 通过,denied 被拒绝,permanentlyDenied 拒绝且不在提示 + if (statuses[Permission.bluetoothScan]!.isGranted && + statuses[Permission.bluetoothConnect]!.isGranted && + statuses[Permission.location]!.isGranted) { + return true; + } + return false; + } + void onShow() {} void onHide() {} diff --git a/star_lock/lib/mine/addLock/lockAddress/gaode/lockAddressGaoDe_page.dart b/star_lock/lib/mine/addLock/lockAddress/gaode/lockAddressGaoDe_page.dart index bb1c6e0c..1201d96c 100644 --- a/star_lock/lib/mine/addLock/lockAddress/gaode/lockAddressGaoDe_page.dart +++ b/star_lock/lib/mine/addLock/lockAddress/gaode/lockAddressGaoDe_page.dart @@ -16,11 +16,9 @@ import '../../../../app_settings/app_colors.dart'; import '../../../../tools/titleAppBar.dart'; import '../../../../tools/toast.dart'; import '../../../../translations/trans_lib.dart'; - -// typedef BlockAddressMapCallback = void Function(dynamic addressMap); +import 'lockAddressGaoDe_logic.dart'; class LockAddressGaoDePage extends StatefulWidget { - // BlockAddressMapCallback callback; const LockAddressGaoDePage({Key? key}) : super(key: key); @@ -29,11 +27,14 @@ class LockAddressGaoDePage extends StatefulWidget { } class _LockAddressGaoDePageState extends State{ + final logic = Get.put(LockAddressGaoDeLogic()); + final state = Get.find().state; + // 高德地图 static const AMapApiKey amapApiKeys = AMapApiKey(iosKey: '883a3355d2d77c2fdc2667030dc97ffe', androidKey: '11d49b3f4fc09c04a02bbb7500925ba2'); AMapController? mapController; - AMapFlutterLocation? location; + AMapFlutterLocation location = AMapFlutterLocation(); PermissionStatus? permissionStatus; Map? addressInfo; @@ -44,9 +45,12 @@ class _LockAddressGaoDePageState extends State{ AMapFlutterLocation.updatePrivacyAgree(true); AMapFlutterLocation.updatePrivacyShow(true, true); - AMapFlutterLocation.setApiKey("11d49b3f4fc09c04a02bbb7500925ba2", "883a3355d2d77c2fdc2667030dc97ffe"); requestPermission(); + + AMapFlutterLocation.setApiKey("11d49b3f4fc09c04a02bbb7500925ba2", "883a3355d2d77c2fdc2667030dc97ffe"); + + requestLocation(); } Future requestPermission() async { @@ -58,37 +62,29 @@ class _LockAddressGaoDePageState extends State{ print("拒绝"); break; case PermissionStatus.granted: - requestLocation(); + _setLocationOption(); + location.startLocation(); break; case PermissionStatus.limited: print("限制"); break; default: print("其他状态"); - requestLocation(); + // requestLocation(); break; } } Future requestLocation() async { - location = AMapFlutterLocation() - ..setLocationOption(AMapLocationOption()) - ..onLocationChanged().listen((event) { + location.onLocationChanged().listen((event) { print("listenLocationChanged$event"); - // double? latitude = double.parse(event['latitude']); - // double? longitude = double.parse(event['longitude'] as String); if (event.isNotEmpty) { - // widget.callback(event); setState(() { addressInfo = event; - // currentLocation = CameraPosition( - // target: LatLng(latitude, longitude), - // zoom: 10, - // ); }); + location.stopLocation(); } - }) - ..startLocation(); + }); } @override @@ -110,7 +106,10 @@ class _LockAddressGaoDePageState extends State{ Toast.show(msg:"还未获取到位置信息哦,请耐心等待一下!"); return; } - Get.toNamed(Routers.saveLockPage, arguments: addressInfo); + Get.toNamed(Routers.saveLockPage, arguments: { + "addressInfo": addressInfo, + "pwdTimestamp": state.pwdTimestamp.value, + }); // Navigator.pushNamed(context, Routers.saveLockPage); }, ), @@ -133,7 +132,7 @@ class _LockAddressGaoDePageState extends State{ // 初始化地图中心 initialCameraPosition: ( CameraPosition( - target: LatLng(double.parse(addressInfo!['latitude'] as String), double.parse(addressInfo!['longitude'] as String)), + target: LatLng(double.parse(addressInfo!['latitude'].toString()), double.parse(addressInfo!['longitude'].toString())), zoom: 10.0, ) ), @@ -202,11 +201,58 @@ class _LockAddressGaoDePageState extends State{ } + ///设置定位参数 + void _setLocationOption() { + AMapLocationOption locationOption = AMapLocationOption(); + + ///是否单次定位 + locationOption.onceLocation = true; + + ///是否需要返回逆地理信息 + locationOption.needAddress = true; + + ///逆地理信息的语言类型 + locationOption.geoLanguage = GeoLanguage.DEFAULT; + + locationOption.desiredLocationAccuracyAuthorizationMode = AMapLocationAccuracyAuthorizationMode.ReduceAccuracy; + + locationOption.fullAccuracyPurposeKey = "AMapLocationScene"; + + ///设置Android端连续定位的定位间隔 + locationOption.locationInterval = 2000; + + ///设置Android端的定位模式
+ ///可选值:
+ ///
  • [AMapLocationMode.Battery_Saving]
  • + ///
  • [AMapLocationMode.Device_Sensors]
  • + ///
  • [AMapLocationMode.Hight_Accuracy]
  • + locationOption.locationMode = AMapLocationMode.Battery_Saving; + + ///设置iOS端的定位最小更新距离
    + locationOption.distanceFilter = -1; + + ///设置iOS端期望的定位精度 + /// 可选值:
    + ///
  • [DesiredAccuracy.Best] 最高精度
  • + ///
  • [DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度
  • + ///
  • [DesiredAccuracy.NearestTenMeters] 10米
  • + ///
  • [DesiredAccuracy.Kilometer] 1000米
  • + ///
  • [DesiredAccuracy.ThreeKilometers] 3000米
  • + locationOption.desiredAccuracy = DesiredAccuracy.BestForNavigation; + + ///设置iOS端是否允许系统暂停定位 + locationOption.pausesLocationUpdatesAutomatically = false; + + ///将定位参数设置给定位插件 + location.setLocationOption(locationOption); + } + + @override void dispose() { super.dispose(); - location?.destroy(); + location.destroy(); print("地图界面销毁了"); } } diff --git a/star_lock/lib/mine/addLock/lockAddress/gaode/lockAddressGaoDe_state.dart b/star_lock/lib/mine/addLock/lockAddress/gaode/lockAddressGaoDe_state.dart index 55ce401a..58c56fc4 100644 --- a/star_lock/lib/mine/addLock/lockAddress/gaode/lockAddressGaoDe_state.dart +++ b/star_lock/lib/mine/addLock/lockAddress/gaode/lockAddressGaoDe_state.dart @@ -7,11 +7,9 @@ import 'package:permission_handler/permission_handler.dart'; class LockAddressGaoDeState{ -// AMapController? mapController; -// AMapFlutterLocation? location; -// // PermissionStatus? permissionStatus; -// -// final addressInfo = {}.obs; -// final latitude = 39.909187.obs; -// final longitude = 116.397451.obs; + var pwdTimestamp= 0.obs; + LockAddressGaoDeState() { + Map map = Get.arguments; + pwdTimestamp.value = map["pwdTimestamp"]; + } } \ No newline at end of file diff --git a/star_lock/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart b/star_lock/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart index bf78b58c..0cd02329 100644 --- a/star_lock/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart +++ b/star_lock/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart @@ -18,6 +18,7 @@ import '../../../blue/io_tool/io_model.dart'; import '../../../blue/io_tool/io_tool.dart'; import '../../../blue/io_tool/manager_event_bus.dart'; import '../../../blue/sender_manage.dart'; +import '../../../tools/dateTool.dart'; import '../../../tools/storage.dart'; import 'nearbyLock_state.dart'; @@ -27,7 +28,8 @@ class NearbyLockLogic extends BaseGetXController{ // 点击连接设备 void connect(String lockId, String deviceName){ - BlueManage().connect(lockId, deviceName, isFrist: true); + // BlueManage().stopScan(); + BlueManage().connect(lockId, deviceName, isFrist: true, isShowLoading: true); } // 获取解析后的数据 @@ -44,7 +46,7 @@ class NearbyLockLogic extends BaseGetXController{ }); } - void _replyGetPublicKey(Reply reply){ + Future _replyGetPublicKey(Reply reply) async { // 获取公钥 switch(reply.status){ case 0x00: @@ -58,8 +60,8 @@ class NearbyLockLogic extends BaseGetXController{ IoSenderManage.getPrivateKey( lockId:BlueManage().connectDeviceName, keyID:"1", - authUserID:"1", - nowTime:1, + authUserID:await Storage.getUid(), + nowTime:DateTime.now().millisecondsSinceEpoch~/1000, publicKeyData:publicKey, needAuthor:1); break; @@ -84,18 +86,33 @@ class NearbyLockLogic extends BaseGetXController{ //成功 print('获取私钥成功'); reply.data.removeAt(0); + print("reply.data:${reply.data}"); // 私钥 List privateKey = reply.data.sublist(0, 16); + print("privateKey:$privateKey"); var savePrivateKeyList = changeIntListToStringList(privateKey); Storage.setStringList(saveBluePrivateKey, savePrivateKeyList); // signKey List signKey = reply.data.sublist(16, 32); + print("signKey:$signKey"); var saveSignKeyList = changeIntListToStringList(signKey); Storage.setStringList(saveBlueSignKey, saveSignKeyList); - Get.toNamed(Routers.lockAddressGaoDePage); + // 时间戳 + List timestamp = reply.data.sublist(32, 36); + int timestampValue = ( + (0xff & timestamp[(0)]) << 24 | + (0xff & timestamp[1]) << 16 | + (0xff & timestamp[2]) << 8 | + (0xFF & timestamp[3])); + String timestampValueStr = DateTool().dateToYMDHNSString(timestampValue.toString()); + print("timestamp:$timestamp timestampValue:$timestampValue timestampValueStr:$timestampValueStr"); + + Get.toNamed(Routers.lockAddressGaoDePage, arguments: { + "pwdTimestamp": timestampValue*1000, + }); break; case 0x07: //无权限 @@ -129,7 +146,7 @@ class NearbyLockLogic extends BaseGetXController{ print("NearbyLockLogic onInit()"); // 进来第一步开始扫描 - BlueManage().startScan((v){ + BlueManage().startScan(false ,(v){ state.devices.clear(); state.devices.addAll(v); }); @@ -140,6 +157,7 @@ class NearbyLockLogic extends BaseGetXController{ // TODO: implement onClose super.onClose(); _replySubscription.cancel(); + BlueManage().stopScan(); } } diff --git a/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart b/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart index b126b8b0..39b98fa2 100644 --- a/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart +++ b/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart @@ -17,6 +17,7 @@ import '../../../blue/io_tool/manager_event_bus.dart'; import '../../../blue/sender_manage.dart'; import '../../../network/api_repository.dart'; import '../../../tools/baseGetXController.dart'; +import '../../../tools/dateTool.dart'; import '../../../tools/eventBusEventManage.dart'; import '../../../tools/storage.dart'; import 'saveLock_state.dart'; @@ -192,7 +193,8 @@ class SaveLockLogic extends BaseGetXController { print("${reply.commandType}数据解析成功"); // 厂商名称 var vendor = reply.data.sublist(3, 23); - print("softVersion:$vendor"); + var vendorStr = utf8String(vendor); + print("softVersion:$vendor vendorStr:$vendorStr"); // 锁设备类型 var product = reply.data[23]; @@ -200,11 +202,13 @@ class SaveLockLogic extends BaseGetXController { // 产品名称 var model = reply.data.sublist(24, 44); - print("model:$model"); + var modelStr = utf8String(model); + print("model:$model modelStr:$modelStr"); // 软件版本 var fwVersion = reply.data.sublist(44, 64); - print("fwVersion:$fwVersion"); + var fwVersionStr = utf8String(fwVersion); + print("fwVersion:$fwVersion fwVersionStr:$fwVersionStr"); // 硬件版本 var hwVersion = reply.data.sublist(64, 84); @@ -220,27 +224,54 @@ class SaveLockLogic extends BaseGetXController { // 蓝牙名称 var btDeviceName = reply.data.sublist(116, 132); - print("btDeviceName:$btDeviceName"); + var btDeviceNameStr = utf8String(btDeviceName); + print("btDeviceName:$btDeviceName btDeviceNameStr:$btDeviceNameStr"); // 电池剩余电量 var battRemCap = reply.data[132]; print("battRemCap:$battRemCap"); // 重置次数 - var restoreCounter = reply.data.sublist(133, 134); + var restoreCounter = reply.data.sublist(133, 135); print("restoreCounter:$restoreCounter"); // 重置时间 - var restoreDate = reply.data.sublist(134, 138); - print("restoreDate:$restoreDate"); + var restoreDate = reply.data.sublist(135, 139); + int restoreDateValue = ((0xff & restoreDate[(0)]) << 24 | (0xff & restoreDate[1]) << 16 | (0xff & restoreDate[2]) << 8 | (0xFF & restoreDate[3])); + String restoreDateStr = DateTool().dateToYMDHNSString(restoreDateValue.toString()); + print("restoreDate:$restoreDate restoreDateStr:$restoreDateStr"); // 主控芯片型号 - var icPartNo = reply.data.sublist(138, 148); - print("icPartNo:$icPartNo"); + var icPartNo = reply.data.sublist(139, 149); + var icPartNoStr = utf8String(icPartNo); + print("icPartNo:$icPartNo icPartNoStr:$icPartNoStr"); // 有效时间 - var indate = reply.data.sublist(148, 152); - print("indate:$indate"); + var indate = reply.data.sublist(149, 153); + int indateValue = ((0xff & restoreDate[(0)]) << 24 | (0xff & restoreDate[1]) << 16 | (0xff & restoreDate[2]) << 8 | (0xFF & restoreDate[3])); + String indateStr = DateTool().dateToYMDHNSString(indateValue.toString()); + print("indate:$indate indateStr:$indateStr"); + + var index = 153; + // 锁特征值字符串长度 + var featureValueLength = reply.data[153]; + // 锁特征值说明(本机能支持的功能) + // 获取到锁给的字符数组 + var featureValue = reply.data.sublist(index+1, index + featureValueLength+1); + List allFeatureValueTwoList = charListChangeIntList(featureValue); + // print("featureValueLength:$featureValueLength featureValue:$featureValue \n allFeatureValueTwoList:$allFeatureValueTwoList"); + index = index + featureValueLength + 1; + + // 使能特征值字符串长度 + var featureEnValLength = reply.data[index]; + // 使能锁特征值说明(本机启用的功能) + var featureEnVal = reply.data.sublist(index+1, index + featureEnValLength+1); + List allFeatureEnValTwoList = charListChangeIntList(featureEnVal); + // print("featureEnValLength:$featureEnValLength featureEnVal:$featureEnVal \n allFeatureEnValTwoList:$allFeatureEnValTwoList"); + index = index + featureEnValLength + 1; + + // 支持的带参数特征值的总条目数 + var featureParaTotal = reply.data[index]; break; case 0x06: @@ -266,6 +297,20 @@ class SaveLockLogic extends BaseGetXController { } } + List charListChangeIntList(List featureValue){ + // 字符数组转化为16进制字符串 + String featureValueStr = asciiString(featureValue); + // 16进制字符串转化为2进制的字符串 获取的是逆序的需要倒序 前面有0会消失 需要自动补全 暂时定位57个功能 要补全60 + String featureValueTwoStr = int.parse(featureValueStr,radix: 16).toRadixString(2); + List featureValueTwoList = []; + for(int i = 0;i _list = [ + "为了更好地应用体验,请确定权限", + "您第一次拒绝权限,请确定权限", + "您第二次拒绝权限,请去应用设置开启权限" + ]; + + final BuildContext _context ; + void checkPermission({PermissionStatus? status, BlockScuessStatus? blockScuessStatus}) async { + //申请权限 permission_handler: ^5.0.1+1 + + //位置权限 + Permission permission = Permission.location; + + status ??= await permission.status; + print("statusstatusstatus:$status"); + if (status.isDenied) { + //第一次申请 + showPermissionDialog(_list[0], "同意", permission); + } else if (status.isDenied) { + //第一次申请拒绝 + showPermissionDialog(_list[1], "重试", permission); + } else if (status.isPermanentlyDenied) { + //第二次申请 + showPermissionDialog(_list[2], "去应用市场", permission,isUndetermined: true); + } else if (status.isGranted) { + // 通过 + blockScuessStatus!(); + } else { + //通过 + + } + } + + ///是否去设置中心 + bool isGoAppSetteng = false; + + ///msg 提示文案 + ///rightMsg 右侧按钮显示文案 + ///要申请的权限 + /// isUndetermined 可选参数,传入的是当前是否去设置中心 + void showPermissionDialog( + String msg, String rightMsg, Permission permission,{bool isUndetermined = false}) { + //使用苹果的dialog + showCupertinoDialog( + builder: (BuildContext context) { + return CupertinoAlertDialog( + title: Text("温馨提示"), + content: Container( + child: Text(msg), + ), + actions: [ + //左边按钮 + CupertinoDialogAction( + child: Text("关闭应用"), + onPressed: (){ + //关闭引用 + closeAPP(); + }, + ), + //右边 + CupertinoDialogAction( + child: Text(rightMsg), + onPressed: () { + + //关闭弹框 + Navigator.pop(context); + if(isUndetermined){ + isGoAppSetteng = true; + //去设置中心 + openAppSettings(); + }else{ + //申请权限 + isGoAppSetteng = false; + requestPermission(context,permission); + } + + + }, + ), + ], + ); + }, + context: _context); + } + + void requestPermission(BuildContext context,Permission permission) async { + + //请求权限 + PermissionStatus status = await permission.request(); + + //校验 + checkPermission(status: status); + + } +//关闭应用 + void closeAPP() { + SystemChannels.platform.invokeMethod("SystemNavigator.pop"); + } + + +}