diff --git a/star_lock/android/app/src/main/AndroidManifest.xml b/star_lock/android/app/src/main/AndroidManifest.xml index 8678a200..66743f72 100644 --- a/star_lock/android/app/src/main/AndroidManifest.xml +++ b/star_lock/android/app/src/main/AndroidManifest.xml @@ -5,11 +5,15 @@ - - - - + + + + + + + @@ -40,5 +44,9 @@ + + + + diff --git a/star_lock/images/lan/lan_en.json b/star_lock/images/lan/lan_en.json index 06d704ca..4fc21bb8 100644 --- a/star_lock/images/lan/lan_en.json +++ b/star_lock/images/lan/lan_en.json @@ -191,6 +191,7 @@ "lanChinese":"Chinese", "multilingual":"Multilingual", "addLock":"Add Lock", + "lockAddress":"Lock Address", "selectLockType":"Select lock type", "videoIntercomDoorLock":"Video intercom door lock", "NFCPassiveLock":"NFC Passive Lock", diff --git a/star_lock/images/lan/lan_keys.json b/star_lock/images/lan/lan_keys.json index bf52f4ae..de90f57e 100644 --- a/star_lock/images/lan/lan_keys.json +++ b/star_lock/images/lan/lan_keys.json @@ -191,6 +191,7 @@ "lanChinese":"lanChinese", "multilingual":"multilingual", "addLock":"addLock", + "lockAddress":"lockAddress", "selectLockType":"selectLockType", "videoIntercomDoorLock":"videoIntercomDoorLock", "NFCPassiveLock":"NFCPassiveLock", diff --git a/star_lock/images/lan/lan_zh.json b/star_lock/images/lan/lan_zh.json index bf47020d..b772a3e0 100644 --- a/star_lock/images/lan/lan_zh.json +++ b/star_lock/images/lan/lan_zh.json @@ -191,6 +191,7 @@ "lanChinese":"中文", "multilingual":"多语言", "addLock":"添加锁", + "lockAddress":"锁地址", "selectLockType":"选择锁类型", "videoIntercomDoorLock":"可视对讲门锁", "NFCPassiveLock":"NFC无源锁", diff --git a/star_lock/images/main/icon_addUserAddressShowTime.png b/star_lock/images/main/icon_addUserAddressShowTime.png new file mode 100644 index 00000000..076b5ca5 Binary files /dev/null and b/star_lock/images/main/icon_addUserAddressShowTime.png differ diff --git a/star_lock/images/main/icon_addUserShowAddress.png b/star_lock/images/main/icon_addUserShowAddress.png new file mode 100644 index 00000000..9ed9953c Binary files /dev/null and b/star_lock/images/main/icon_addUserShowAddress.png differ diff --git a/star_lock/ios/Podfile.lock b/star_lock/ios/Podfile.lock index baa14261..23da6cd3 100644 --- a/star_lock/ios/Podfile.lock +++ b/star_lock/ios/Podfile.lock @@ -1,6 +1,17 @@ PODS: - aj_captcha_flutter (0.0.1): - Flutter + - AMap3DMap (9.7.0): + - AMapFoundation (>= 1.8.0) + - amap_flutter_location (0.0.1): + - AMapLocation + - Flutter + - amap_flutter_map (0.0.1): + - AMap3DMap + - Flutter + - AMapFoundation (1.8.2) + - AMapLocation (2.10.0): + - AMapFoundation (>= 1.8.0) - device_info_plus (0.0.1): - Flutter - Flutter (1.0.0) @@ -16,6 +27,8 @@ PODS: - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS + - permission_handler_apple (9.1.1): + - Flutter - Protobuf (3.23.4) - reactive_ble_mobile (0.0.1): - Flutter @@ -31,6 +44,8 @@ PODS: DEPENDENCIES: - aj_captcha_flutter (from `.symlinks/plugins/aj_captcha_flutter/ios`) + - amap_flutter_location (from `.symlinks/plugins/amap_flutter_location/ios`) + - amap_flutter_map (from `.symlinks/plugins/amap_flutter_map/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - Flutter (from `Flutter`) - flutter_native_contact_picker (from `.symlinks/plugins/flutter_native_contact_picker/ios`) @@ -38,12 +53,16 @@ DEPENDENCIES: - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - reactive_ble_mobile (from `.symlinks/plugins/reactive_ble_mobile/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) SPEC REPOS: trunk: + - AMap3DMap + - AMapFoundation + - AMapLocation - Protobuf - SwiftProtobuf - Toast @@ -51,6 +70,10 @@ SPEC REPOS: EXTERNAL SOURCES: aj_captcha_flutter: :path: ".symlinks/plugins/aj_captcha_flutter/ios" + amap_flutter_location: + :path: ".symlinks/plugins/amap_flutter_location/ios" + amap_flutter_map: + :path: ".symlinks/plugins/amap_flutter_map/ios" device_info_plus: :path: ".symlinks/plugins/device_info_plus/ios" Flutter: @@ -65,6 +88,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/darwin" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" reactive_ble_mobile: :path: ".symlinks/plugins/reactive_ble_mobile/ios" shared_preferences_foundation: @@ -74,6 +99,11 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: aj_captcha_flutter: dd7af1aa064bdd621ae335b819bab07309c3c023 + AMap3DMap: dce25dd3e51e6b92109caa7d0c97fc6055830fb3 + amap_flutter_location: 44ff5beb64f42e0bf5feb402fe299dac0013af6f + amap_flutter_map: 979e54d227cedac6c7504a2151bfbf3bcf96760a + AMapFoundation: 9885c48fc3a78fdfb84a0299a2293e56ea3c9fec + AMapLocation: 5248aec2455ebb5d104b367813c946430a2ee033 device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_native_contact_picker: bd430ba0fbf82768bb50c2c52a69a65759a8f907 @@ -81,6 +111,7 @@ SPEC CHECKSUMS: image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 Protobuf: c6bc59bbab3d38a71c67f62d7cb7ca8f8ea4eca1 reactive_ble_mobile: 9ce6723d37ccf701dbffd202d487f23f5de03b4c shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 diff --git a/star_lock/ios/Runner.xcodeproj/project.pbxproj b/star_lock/ios/Runner.xcodeproj/project.pbxproj index 6fa290ed..f1877154 100644 --- a/star_lock/ios/Runner.xcodeproj/project.pbxproj +++ b/star_lock/ios/Runner.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ 09D8B2FA2B26BA5BFF31AB2A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 33BF41252A96174D009D92E2 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; @@ -114,6 +115,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 33BF41252A96174D009D92E2 /* Runner.entitlements */, 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 97C146FA1CF9000F007C117D /* Main.storyboard */, @@ -149,6 +151,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + D9B107A6B141D5F15BC356F2 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -259,6 +262,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + D9B107A6B141D5F15BC356F2 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -351,6 +371,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 7NLFRKNVY3; ENABLE_BITCODE = NO; @@ -478,6 +499,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 7NLFRKNVY3; ENABLE_BITCODE = NO; @@ -498,6 +520,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 7NLFRKNVY3; ENABLE_BITCODE = NO; diff --git a/star_lock/ios/Runner/Info.plist b/star_lock/ios/Runner/Info.plist index 705a553a..c9c9e8bf 100644 --- a/star_lock/ios/Runner/Info.plist +++ b/star_lock/ios/Runner/Info.plist @@ -24,6 +24,11 @@ ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + LSRequiresIPhoneOS NSBluetoothAlwaysUsageDescription @@ -38,6 +43,12 @@ 用于音频插件 NSPhotoLibraryUsageDescription 用于相册 + NSLocationWhenInUseUsageDescription + 应用在前台的时候可以搜到更新的位置信息 + NSLocationAlwaysUsageDescription + 应用在后台的时候可以搜到更新的位置信息 + NSLocationAlwaysAndWhenInUseUsageDescription + 应用在前台和后台的时候可以搜到更新的位置信息 UIApplicationSupportsIndirectInputEvents UIBackgroundModes diff --git a/star_lock/ios/Runner/Runner.entitlements b/star_lock/ios/Runner/Runner.entitlements new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/star_lock/ios/Runner/Runner.entitlements @@ -0,0 +1,5 @@ + + + + + diff --git a/star_lock/lib/blue/blue_manage.dart b/star_lock/lib/blue/blue_manage.dart index 1cd981c4..a8513887 100644 --- a/star_lock/lib/blue/blue_manage.dart +++ b/star_lock/lib/blue/blue_manage.dart @@ -95,6 +95,10 @@ class BlueManage{ print("connectDeviceId:$connectDeviceId connectDeviceName:$connectDeviceName"); EasyLoading.show(); + Future.delayed(const Duration(seconds: 30), () { //asynchronous delay + print("30s之后 菊花没有隐藏的话,强制隐藏菊花"); + EasyLoading.dismiss(); + }); _flutterReactiveBle!.connectToDevice(id: connectDeviceId, connectionTimeout: const Duration(seconds: 15)).listen((connectionStateUpdate) async { // 获取状态 deviceConnectionState = connectionStateUpdate.connectionState; @@ -174,6 +178,10 @@ class BlueManage{ Future judgeReconnect(String deviceMAC, String deviceName, ConnectStateCallBack? connectStateCallBack) async { if(deviceConnectionState == DeviceConnectionState.connected){ EasyLoading.show(); + Future.delayed(const Duration(seconds: 30), () { //asynchronous delay + print("30s之后 菊花没有隐藏的话,强制隐藏菊花"); + EasyLoading.dismiss(); + }); connectStateCallBack!(deviceConnectionState!); }else{ connect(deviceMAC, deviceName, connectStateCallBack: (state){ diff --git a/star_lock/lib/blue/io_protocol/io_factoryDataReset.dart b/star_lock/lib/blue/io_protocol/io_factoryDataReset.dart new file mode 100644 index 00000000..9a219511 --- /dev/null +++ b/star_lock/lib/blue/io_protocol/io_factoryDataReset.dart @@ -0,0 +1,105 @@ + +//TODO:添加用户 +import 'dart:convert'; + +import '../../tools/storage.dart'; +import '../blue_manage.dart'; +import '../io_tool/io_manager.dart'; +import '../io_tool/io_tool.dart'; +import '../sender_manage.dart'; +import '../sm4Encipher/sm4.dart'; +import 'io_reply.dart'; +import 'io_sender.dart'; +import 'io_type.dart'; +import 'package:crypto/crypto.dart' as crypto; + +class FactoryDataResetCommand extends SenderProtocol { + + String? lockID; + String? userID; + String? keyID; + List? publicKey; + List? privateKey; + List? token; + int? needAuthor; + FactoryDataResetCommand({ + this.lockID, + this.userID, + this.keyID, + this.token, + this.needAuthor, + this.publicKey, + this.privateKey, + }) : super(CommandType.factoryDataReset); + + @override + List messageDetail() { + List data = []; + List 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; + // print("${commandType!.typeValue}LockIDLength:$lockIDLength utf8.encode(lockID!)${utf8.encode(lockID!)}"); + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - lockIDLength); + + //userID 20 + int userIDLength = utf8.encode(userID!).length; + // print("${commandType!.typeValue}IDLength:$authUserIDLength utf8.encode(authUserID!)${utf8.encode(authUserID!)}"); + data.addAll(utf8.encode(userID!)); + data = getFixedLengthList(data, 20 - userIDLength); + + // token 长度4 首次请求 Token 填 0,如果锁需要鉴权 操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 当token失效或者第一次发送的时候token为0 + data.addAll(token!); + print("恢复出厂设置、pubToken:$token"); + + if(needAuthor == 0){ + //AuthCodeLen 1 + data.add(0); + } else { + List authCodeData = []; + + //userID + authCodeData.addAll(utf8.encode(lockID!)); + + //token 4 首次请求 Token 填 0,如果锁需要鉴权操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 + authCodeData.addAll(token!); + + authCodeData.addAll(publicKey!); + + print("${commandType!.typeValue}-authCodeData:$authCodeData"); + + // 把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); + } + } + print("${commandType!.typeName} SM4Data:$data"); + // 拿到数据之后通过LockId进行SM4 ECB加密 key:544d485f633335373034383064613864 + ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB); + return ebcData; + } +} + +class FactoryDataResetReply extends Reply { + FactoryDataResetReply.parseData(CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + } +} \ No newline at end of file diff --git a/star_lock/lib/blue/io_protocol/io_transferPermissions.dart b/star_lock/lib/blue/io_protocol/io_transferPermissions.dart new file mode 100644 index 00000000..eae821fc --- /dev/null +++ b/star_lock/lib/blue/io_protocol/io_transferPermissions.dart @@ -0,0 +1,125 @@ + +import 'dart:convert'; + +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; + +//TODO:转移权限 +class TransferPermissionsCommand extends SenderProtocol { + + String? lockID; + String? authUserID; + String? keyID; + String? oldUserID; + String? newUserID; + int? needAuthor; + List? publicKey; + List? privateKey; + List? token; + TransferPermissionsCommand({ + this.lockID, + this.authUserID, + this.keyID, + this.oldUserID, + this.newUserID, + this.needAuthor, + this.publicKey, + this.privateKey, + this.token + }) : super(CommandType.transferPermissions); + + @override + List messageDetail() { + List data = []; + List 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; + print("${commandType!.typeValue} lockID:$lockID LockIDLength:$lockIDLength utf8.encode(lockID!)${utf8.encode(lockID!)}"); + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - lockIDLength); + + //authUserID 20 + int authUserIDLength = utf8.encode(authUserID!).length; + // print("${commandType!.typeValue}IDLength:$authUserIDLength utf8.encode(authUserID!)${utf8.encode(authUserID!)}"); + data.addAll(utf8.encode(authUserID!)); + data = getFixedLengthList(data, 20 - authUserIDLength); + + //KeyID 40 + int keyIDLength = utf8.encode(keyID!).length; + // print("${commandType!.typeValue}keyIDLength:$keyIDLength utf8.encode(keyID!)${utf8.encode(keyID!)}"); + data.addAll(utf8.encode(keyID!)); + data = getFixedLengthList(data, 40 - keyIDLength); + + //oldUserID 20 + int oldUserIDLength = utf8.encode(oldUserID!).length; + // print("${commandType!.typeValue}userIDLength:$userIDLength utf8.encode(userID!)${utf8.encode(userID!)}"); + data.addAll(utf8.encode(oldUserID!)); + data = getFixedLengthList(data, 20 - oldUserIDLength); + + //newUserID 20 + int newUserIDLength = utf8.encode(newUserID!).length; + // print("${commandType!.typeValue}userIDLength:$userIDLength utf8.encode(userID!)${utf8.encode(userID!)}"); + data.addAll(utf8.encode(newUserID!)); + data = getFixedLengthList(data, 20 - newUserIDLength); + + // token 长度4 首次请求 Token 填 0,如果锁需要鉴权 操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 当token失效或者第一次发送的时候token为0 + data.addAll(token!); + print("pubToken:$token"); + + if(needAuthor == 0){ + //AuthCodeLen 1 + data.add(0); + } else { + List authCodeData = []; + + //authUserID + authCodeData.addAll(utf8.encode(authUserID!)); + + //KeyID + authCodeData.addAll(utf8.encode(keyID!)); + + //token 4 首次请求 Token 填 0,如果锁需要鉴权操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 + authCodeData.addAll(token!); + + authCodeData.addAll(publicKey!); + + print("${commandType!.typeValue}-authCodeData:$authCodeData"); + + // 把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); + } + } + print("${commandType!.typeName} SM4Data:$data"); + ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB); + return ebcData; + } +} + +class TransferPermissionsReply extends Reply { + TransferPermissionsReply.parseData(CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + } +} \ No newline at end of file diff --git a/star_lock/lib/blue/io_tool/io_manager.dart b/star_lock/lib/blue/io_tool/io_manager.dart index bd200c3e..07a4e7d8 100644 --- a/star_lock/lib/blue/io_tool/io_manager.dart +++ b/star_lock/lib/blue/io_tool/io_manager.dart @@ -7,6 +7,8 @@ const saveBluePublicKey = "BluePublicKey"; const saveBluePrivateKey = "BluePrivateKey"; const saveBlueSignKey = "BlueSignKey"; const saveBlueToken = "BlueGetToken"; +const currentConnectionLockId = "CurrentConnectionLockId"; +const currentConnectionMacAddress = "CurrentConnectionMacAddress"; class IoManager { diff --git a/star_lock/lib/blue/reciver_data.dart b/star_lock/lib/blue/reciver_data.dart index 5b0de909..5814d185 100644 --- a/star_lock/lib/blue/reciver_data.dart +++ b/star_lock/lib/blue/reciver_data.dart @@ -6,7 +6,9 @@ import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:star_lock/blue/blue_manage.dart'; 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_transferPermissions.dart'; import '../tools/storage.dart'; import 'io_protocol/io_addUser.dart'; @@ -73,10 +75,9 @@ class CommandReciverManager { // print("getPrivateKeyList$getPrivateKeyList"); // 解密 - // String key = SM4.createHexKey(key: radixHex16String(getPrivateKeyList!)); oriDataList = SM4.decrypt(getDataList, key: getPrivateKeyList, mode: SM4CryptoMode.ECB); oriDataList = oriDataList.sublist(0, oriLen); - // print("SM4 oriDataList:$oriDataList"); + print("SM4 oriDataList:$oriDataList"); break; } @@ -132,6 +133,16 @@ class CommandReciverManager { reply = EditUserReply.parseData(commandType, data); } break; + case CommandType.transferPermissions: + { + reply = TransferPermissionsReply.parseData(commandType, data); + } + break; + case CommandType.factoryDataReset: + { + reply = FactoryDataResetReply.parseData(commandType, data); + } + break; } return reply; } diff --git a/star_lock/lib/blue/sender_manage.dart b/star_lock/lib/blue/sender_manage.dart index ff2c89be..9a471bdc 100644 --- a/star_lock/lib/blue/sender_manage.dart +++ b/star_lock/lib/blue/sender_manage.dart @@ -4,9 +4,11 @@ import 'package:star_lock/blue/io_protocol/io_getLockStatu.dart'; import 'io_protocol/io_addUser.dart'; import 'io_protocol/io_editUser.dart'; +import 'io_protocol/io_factoryDataReset.dart'; import 'io_protocol/io_getPrivateKey.dart'; import 'io_protocol/io_getPublicKey.dart'; import 'io_protocol/io_openLock.dart'; +import 'io_protocol/io_transferPermissions.dart'; import 'sender_data.dart'; class IoSenderManage { @@ -170,4 +172,53 @@ class IoSenderManage { privateKey: privateKey, ), callBack:callBack); } + + //todo:转移权限 + static void senderTransferPermissions({ + String? lockID, + String? authUserID, + String? keyID, + String? oldUserID, + String? newUserID, + int? needAuthor, + List? publicKey, + List? privateKey, + List? token, + CommandSendCallBack? callBack}) { + CommandSenderManager().managerSendData( + command: TransferPermissionsCommand( + lockID: lockID, + authUserID: authUserID, + keyID: keyID, + oldUserID: oldUserID, + newUserID: newUserID, + needAuthor: needAuthor, + publicKey: publicKey, + privateKey: privateKey, + token: token + ), callBack:callBack); + } + + //todo:恢复出厂设置 + static void senderFactoryDataReset({ + String? lockID, + String? userID, + String? keyID, + List? publicKey, + List? privateKey, + List? token, + int? needAuthor, + CommandSendCallBack? callBack}) { + CommandSenderManager().managerSendData( + command: FactoryDataResetCommand( + lockID: lockID, + userID: userID, + keyID: keyID, + needAuthor: needAuthor, + publicKey: publicKey, + privateKey: privateKey, + token: token + ), callBack:callBack); + } + } \ No newline at end of file diff --git a/star_lock/lib/main.dart b/star_lock/lib/main.dart index 76da243e..a220b85f 100644 --- a/star_lock/lib/main.dart +++ b/star_lock/lib/main.dart @@ -31,7 +31,11 @@ class MyApp extends StatefulWidget { State createState() => _MyAppState(); } +// 注册 RouteObserver 作为 navigation observer. +final RouteObserver routeObserver = RouteObserver(); + class _MyAppState extends State with WidgetsBindingObserver, BaseWidget { + @override Widget build(BuildContext context) { return ScreenUtilInit( @@ -41,6 +45,7 @@ class _MyAppState extends State with WidgetsBindingObserver, BaseWidget { GetMaterialApp _initMaterialApp() => GetMaterialApp( title: 'Star Lock', + navigatorObservers: [routeObserver], translations: TranslationMessage(), supportedLocales: appDept.deptSupportedLocales, localizationsDelegates: const [ @@ -134,4 +139,4 @@ Future _setCommonServices() async { await Get.putAsync(() => PlatformInfoService().init()); await Get.putAsync(() => DeviceInfoService().init()); Get.log(PlatformInfoService.to.info.version); -} +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index 43f9c6b0..27a97f78 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:flutter_reactive_ble/flutter_reactive_ble.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_type.dart'; @@ -10,7 +11,6 @@ import '../../../blue/blue_manage.dart'; import '../../../blue/io_protocol/io_openLock.dart'; import '../../../blue/io_protocol/io_reply.dart'; import '../../../blue/io_tool/io_manager.dart'; -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'; @@ -21,9 +21,11 @@ import 'lockDetail_state.dart'; class LockDetailLogic extends BaseGetXController{ final LockDetailState state = LockDetailState(); + // 监听设备返回的数据 late StreamSubscription _replySubscription; void _initReplySubscription() { _replySubscription = EventBusManager().eventBus!.on().listen((reply) async { + // 开门 if(reply is OpenDoorReply) { _replyOpenLock(reply); } @@ -37,9 +39,15 @@ class LockDetailLogic extends BaseGetXController{ if(reply is EditUserReply){ _replyEditUserKey(reply); } + + // 恢复出厂设置 + if(reply is FactoryDataResetReply){ + _replyFactoryDataResetKey(reply); + } }); } + // 开门数据解析 Future _replyOpenLock(Reply reply) async { var privateKey = await Storage.getStringList(saveBluePrivateKey); List getPrivateKeyList = changeStringListToIntList(privateKey!); @@ -97,6 +105,7 @@ class LockDetailLogic extends BaseGetXController{ } } + // 获取锁状态数据解析 Future _replyGetLockStatus(Reply reply) async { int status = reply.data[2]; switch(status){ @@ -169,6 +178,7 @@ class LockDetailLogic extends BaseGetXController{ } } + // 编辑用户数据解析 Future _replyEditUserKey(Reply reply) async { var token = reply.data.sublist(2, 6); var saveStrList = changeIntListToStringList(token); @@ -217,7 +227,7 @@ class LockDetailLogic extends BaseGetXController{ break; case 0x09: // 权限校验错误 - print("${reply.commandType!.typeValue} 添加用户权限校验错误"); + print("${reply.commandType!.typeValue} 权限校验错误"); break; default: @@ -228,6 +238,63 @@ class LockDetailLogic extends BaseGetXController{ } } + // 恢复出厂设置数据解析 + Future _replyFactoryDataResetKey(Reply reply) async { + var token = reply.data.sublist(2, 6); + var saveStrList = changeIntListToStringList(token); + print("_replyFactoryDataResetKeyToken:$token"); + Storage.setStringList(saveBlueToken, saveStrList); + + int status = reply.data[6]; + print("status:$status"); + + switch(status){ + case 0x00: + //成功 + print("${reply.commandType!.typeValue} 数据解析成功"); + + break; + case 0x06: + //无权限 + print("${reply.commandType!.typeValue} 需要鉴权"); + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + + IoSenderManage.senderFactoryDataReset( + lockID:BlueManage().connectDeviceName, + userID:"100001", + keyID:"1", + needAuthor:1, + publicKey:publicKeyDataList, + privateKey:getPrivateKeyList, + token: getTokenList + ); + break; + case 0x07: + //无权限 + print("${reply.commandType!.typeValue} 用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType!.typeValue} 权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType!.typeValue} 失败"); + + break; + } + } + + // 点击开门事件 Future openDoorAction() async { BlueManage().judgeReconnect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", (DeviceConnectionState state) async { if (state == DeviceConnectionState.connected){ @@ -255,6 +322,7 @@ class LockDetailLogic extends BaseGetXController{ }); } + // 编辑用户事件 Future editLockUserAction() async { BlueManage().judgeReconnect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", (DeviceConnectionState state) async { if (state == DeviceConnectionState.connected){ @@ -289,19 +357,75 @@ class LockDetailLogic extends BaseGetXController{ }); } + // 转移权限 + Future transferPermissionsAction() async { + BlueManage().judgeReconnect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", (DeviceConnectionState state) async { + if (state == DeviceConnectionState.connected){ + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + print("openDoorTokenPubToken:$getTokenList"); + + IoSenderManage.senderTransferPermissions( + lockID:BlueManage().connectDeviceName, + authUserID:"100001", + keyID:"1", + oldUserID:"100001", + newUserID:"100002", + needAuthor:1, + publicKey:publicKeyDataList, + privateKey:getPrivateKeyList, + token: getTokenList + ); + } + }); + } + + // 恢复出厂设置 + Future factoryDataResetAction() async { + BlueManage().judgeReconnect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", (DeviceConnectionState state) async { + if (state == DeviceConnectionState.connected){ + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + + IoSenderManage.senderFactoryDataReset( + lockID:BlueManage().connectDeviceName, + userID:"100001", + keyID:"1", + needAuthor:1, + publicKey:publicKeyDataList, + privateKey:getPrivateKeyList, + token: getTokenList + ); + } + }); + } + + // 备用逻辑,进入管理钥匙界面默认连接 Future connectBlue() async { // 进来之后首先连接 - // BlueManage().connect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", connectStateCallBack: (DeviceConnectionState state) async { - // if (state == DeviceConnectionState.connected){ - // var privateKey = await Storage.getStringList(saveBluePrivateKey); - // List getPrivateKeyList = changeStringListToIntList(privateKey!); - // IoSenderManage.senderGetLockStatu( - // lockID:BlueManage().connectDeviceName, - // userID:"100001", - // privateKey:getPrivateKeyList, - // ); - // } - // }); + BlueManage().connect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", connectStateCallBack: (DeviceConnectionState state) async { + if (state == DeviceConnectionState.connected){ + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + IoSenderManage.senderGetLockStatu( + lockID:BlueManage().connectDeviceName, + userID:"100001", + privateKey:getPrivateKeyList, + ); + } + }); } @override @@ -310,6 +434,10 @@ class LockDetailLogic extends BaseGetXController{ super.onReady(); print("onReady()"); _initReplySubscription(); + + BlueManage().startScan((v){ + + }); } @override @@ -318,8 +446,11 @@ class LockDetailLogic extends BaseGetXController{ super.onInit(); print("onInit()"); + BlueManage().connectDeviceName = "TMH_c3570480da8d"; + BlueManage().connectDeviceId = "AD01447A-30B5-A780-E778-DED3BDCB613E"; + // 进来第一步开始扫描 - connectBlue(); + // connectBlue(); } @override diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart index d09d89f0..368942ae 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -4,6 +4,8 @@ import 'package:get/get.dart'; import '../../../appRouters.dart'; import '../../../app_settings/app_colors.dart'; +import '../../../blue/io_tool/io_manager.dart'; +import '../../../tools/storage.dart'; import '../../../tools/titleAppBar.dart'; import '../../../translations/trans_lib.dart'; import 'lockDetail_logic.dart'; @@ -21,6 +23,7 @@ class _LockDetailPageState extends State { @override Widget build(BuildContext context) { + return Scaffold( backgroundColor: Colors.white, appBar: TitleAppBar( @@ -76,8 +79,10 @@ class _LockDetailPageState extends State { Center( child: GestureDetector( onTap: (){ + // logic.transferPermissionsAction(); // logic.openDoorAction(); - logic.editLockUserAction(); + // logic.editLockUserAction(); + logic.factoryDataResetAction(); }, child: Image.asset('images/main/icon_main_openLockBtn.png', width: 268.w, height: 268.w), diff --git a/star_lock/lib/main/lockMian/lockMain_binding.dart b/star_lock/lib/main/lockMian/lockMain_binding.dart index 8634e968..512fc14c 100644 --- a/star_lock/lib/main/lockMian/lockMain_binding.dart +++ b/star_lock/lib/main/lockMian/lockMain_binding.dart @@ -1,6 +1,5 @@ import 'package:get/get.dart'; - import 'lockMain_logic.dart'; class LockMainBinding extends Bindings { diff --git a/star_lock/lib/mine/addLock/lockAddress/lockAddressGaoDe_page.dart b/star_lock/lib/mine/addLock/lockAddress/lockAddressGaoDe_page.dart new file mode 100644 index 00000000..7a4cdbcf --- /dev/null +++ b/star_lock/lib/mine/addLock/lockAddress/lockAddressGaoDe_page.dart @@ -0,0 +1,319 @@ + +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:amap_flutter_location/amap_flutter_location.dart'; +import 'package:amap_flutter_location/amap_location_option.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:amap_flutter_map/amap_flutter_map.dart'; +import 'package:amap_flutter_base/amap_flutter_base.dart'; + +import '../../../app_settings/app_colors.dart'; +import '../../../main.dart'; + +class LockAddressGaoDePage extends StatefulWidget { + const LockAddressGaoDePage({Key? key}) : super(key: key); + + @override + State createState() => _LockAddressGaoDePageState(); +} + +class _LockAddressGaoDePageState extends State{ + // 高德地图 + Map? _locationResult; + StreamSubscription>? _locationListener; + final AMapFlutterLocation _locationPlugin = AMapFlutterLocation(); + late AMapController _mapController; + + static const CameraPosition _kInitialPosition = CameraPosition( + target: LatLng(113.919112, 22.653728), + zoom: 10.0, + ); + + List get _approvalNumberWidget => []; + + @override + void initState() { + super.initState(); + /// 设置是否已经包含高德隐私政策并弹窗展示显示用户查看,如果未包含或者没有弹窗展示,高德定位SDK将不会工作 + /// + /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy + /// 必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意 + /// + /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy + /// + /// [hasContains] 隐私声明中是否包含高德隐私政策说明 + /// + /// [hasShow] 隐私权政策是否弹窗展示告知用户 + AMapFlutterLocation.updatePrivacyShow(true, true); + + /// 设置是否已经取得用户同意,如果未取得用户同意,高德定位SDK将不会工作 + /// + /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy + /// + /// 必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意 + /// + /// [hasAgree] 隐私权政策是否已经取得用户同意 + AMapFlutterLocation.updatePrivacyAgree(true); + + /// 动态申请定位权限 + requestPermission(); + + ///设置Android和iOS的apiKey
+ ///key的申请请参考高德开放平台官网说明
+ ///Android: https://lbs.amap.com/api/android-location-sdk/guide/create-project/get-key + ///iOS: https://lbs.amap.com/api/ios-location-sdk/guide/create-project/get-key + AMapFlutterLocation.setApiKey("1dbf56e2e8a4d0e4cdc2df9efd36bc71", "dfb64c0463cb53927914364b5c09aba0"); + + ///iOS 获取native精度类型 + if (Platform.isIOS) { + requestAccuracyAuthorization(); + } + + ///注册定位结果监听 + _locationListener = _locationPlugin.onLocationChanged().listen((Map result) { + setState(() { + _locationResult = result; + if (_locationResult != null) { + _locationResult?.forEach((key, value) { + print("key:$key value:$value"); + }); + } + }); + }); + + _startLocation(); + } + + @override + Widget build(BuildContext context) { + ///使用默认属性创建一个地图 + final AMapWidget map = AMapWidget( + apiKey: const AMapApiKey(androidKey: '900f72eeee0f21e435cebb0ef155582a', iosKey: '4dfdec97b7bf0b8c13e94777103015a9'), + onMapCreated: onMapCreated, + // initialCameraPosition: _kInitialPosition + ); + + return Stack( + children: [ + Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: map, + ), + Positioned( + left: 10.w, bottom: 30.h, + child: Container( + alignment: Alignment.centerLeft, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: _approvalNumberWidget), + ) + ), + Positioned( + left: 20.w, right: 20.w, bottom: 100.h, + child: Container( + // height: h(106), + decoration: BoxDecoration( + color: AppColors.mainColor, + borderRadius: BorderRadius.circular(15.w), + ), + child:Column( + children: [ + Container( + // height: h(53), + padding: EdgeInsets.only(top: 15.h, bottom: 15, left:15.w, right: 15.w), + child: Row( + children: [ + Image.asset('images/main/icon_addUserShowAddress.png', width: 30.w, height: 30.w), + SizedBox(width: 10.w), + Expanded( + child: Text("广东省深圳市宏发科技园", style: const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500, overflow: TextOverflow.clip)) + ), + ], + ), + ), + Container(height: 1.h, color: const Color(0xFF021732),), + Container( + // height: h(52), + padding: EdgeInsets.only(top: 15.h, bottom: 15, left:15.w, right: 15.w), + child: Row( + children: [ + Image.asset('images/main/icon_addUserAddressShowTime.png', width: 30.w, height: 30.w), + SizedBox(width: 10.w,), + Expanded( + child: Text("2023.8.22 15.14", style: const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500),) + ), + ], + ), + ), + ], + ) + ),), + ], + ); + } + + void onMapCreated(AMapController controller) { + setState(() { + _mapController = controller; + getApprovalNumber(); + }); + } + + /// 获取审图号 + void getApprovalNumber() async { + //普通地图审图号 + String? mapContentApprovalNumber = + await _mapController.getMapContentApprovalNumber(); + //卫星地图审图号 + String? satelliteImageApprovalNumber = + await _mapController.getSatelliteImageApprovalNumber(); + setState(() { + if (null != mapContentApprovalNumber) { + _approvalNumberWidget.add(Text(mapContentApprovalNumber)); + } + if (null != satelliteImageApprovalNumber) { + _approvalNumberWidget.add(Text(satelliteImageApprovalNumber)); + } + }); + print('地图审图号(普通地图): $mapContentApprovalNumber'); + print('地图审图号(卫星地图): $satelliteImageApprovalNumber'); + } + + ///设置定位参数 + void _setLocationOption() { + AMapLocationOption locationOption = new AMapLocationOption(); + + ///是否单次定位 + locationOption.onceLocation = false; + + ///是否需要返回逆地理信息 + 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.Hight_Accuracy; + + ///设置iOS端的定位最小更新距离
    + locationOption.distanceFilter = -1; + + ///设置iOS端期望的定位精度 + /// 可选值:
    + ///
  • [DesiredAccuracy.Best] 最高精度
  • + ///
  • [DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度
  • + ///
  • [DesiredAccuracy.NearestTenMeters] 10米
  • + ///
  • [DesiredAccuracy.Kilometer] 1000米
  • + ///
  • [DesiredAccuracy.ThreeKilometers] 3000米
  • + locationOption.desiredAccuracy = DesiredAccuracy.Best; + + ///设置iOS端是否允许系统暂停定位 + locationOption.pausesLocationUpdatesAutomatically = false; + + ///将定位参数设置给定位插件 + _locationPlugin.setLocationOption(locationOption); + } + + ///开始定位 + void _startLocation() { + ///开始定位之前设置定位参数 + _setLocationOption(); + _locationPlugin.startLocation(); + } + + ///停止定位 + void _stopLocation() { + _locationPlugin.stopLocation(); + } + + ///获取iOS native的accuracyAuthorization类型 + void requestAccuracyAuthorization() async { + AMapAccuracyAuthorization currentAccuracyAuthorization = await _locationPlugin.getSystemAccuracyAuthorization(); + if (currentAccuracyAuthorization == AMapAccuracyAuthorization.AMapAccuracyAuthorizationFullAccuracy) { + print("精确定位类型"); + } else if (currentAccuracyAuthorization == AMapAccuracyAuthorization.AMapAccuracyAuthorizationReducedAccuracy) { + print("模糊定位类型"); + } else { + print("未知定位类型"); + } + } + + /// 动态申请定位权限 + void requestPermission() async { + // 申请权限 + bool hasLocationPermission = await requestLocationPermission(); + if (hasLocationPermission) { + print("定位权限申请通过"); + } else { + print("定位权限申请不通过"); + } + } + + /// 申请定位权限 + /// 授予定位权限返回true, 否则返回false + Future requestLocationPermission() async { + //获取当前的权限 + var status = await Permission.location.status; + if (status == PermissionStatus.granted) { + //已经授权 + return true; + } else { + //未授权则发起一次申请 + status = await Permission.location.request(); + if (status == PermissionStatus.granted) { + return true; + } else { + return false; + } + } + } + + // @override + // void dispose() { + // super.dispose(); + // + // _stopLocation(); + // + // ///移除定位监听 + // if (null != _locationListener) { + // _locationListener?.cancel(); + // } + // + // ///销毁定位 + // _locationPlugin.destroy(); + // + // print("高德地图定位销毁了"); + // } + + @override + void dispose() { + super.dispose(); + + _stopLocation(); + + ///移除定位监听 + if (null != _locationListener) { + _locationListener?.cancel(); + } + + ///销毁定位 + _locationPlugin.destroy(); + + print("地图界面销毁了"); + } +} diff --git a/star_lock/lib/mine/addLock/lockAddress/lockAddressGoogle_page.dart b/star_lock/lib/mine/addLock/lockAddress/lockAddressGoogle_page.dart new file mode 100644 index 00000000..0c0a3aab --- /dev/null +++ b/star_lock/lib/mine/addLock/lockAddress/lockAddressGoogle_page.dart @@ -0,0 +1,16 @@ + +import 'package:flutter/material.dart'; + +class LockAddressGooglePage extends StatefulWidget { + const LockAddressGooglePage({Key? key}) : super(key: key); + + @override + State createState() => _LockAddressGooglePageState(); +} + +class _LockAddressGooglePageState extends State { + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/star_lock/lib/mine/addLock/lockAddress/lockAddress_logic.dart b/star_lock/lib/mine/addLock/lockAddress/lockAddress_logic.dart new file mode 100644 index 00000000..dbbd7ccc --- /dev/null +++ b/star_lock/lib/mine/addLock/lockAddress/lockAddress_logic.dart @@ -0,0 +1,32 @@ + +import '../../../tools/baseGetXController.dart'; +import 'lockAddress_state.dart'; + +class LockAddressLogic extends BaseGetXController { + + final LockAddressState state = LockAddressState(); + + @override + void onReady() { + // TODO: implement onReady + super.onReady(); + print("onReady()"); + + } + + @override + void onInit() { + // TODO: implement onInit + super.onInit(); + print("onInit()"); + + } + + @override + void onClose() { + // TODO: implement onClose + super.onClose(); + print("地图界面onClose()"); + } + +} \ No newline at end of file diff --git a/star_lock/lib/mine/addLock/lockAddress/lockAddress_page.dart b/star_lock/lib/mine/addLock/lockAddress/lockAddress_page.dart index c9b9f818..77bef59a 100644 --- a/star_lock/lib/mine/addLock/lockAddress/lockAddress_page.dart +++ b/star_lock/lib/mine/addLock/lockAddress/lockAddress_page.dart @@ -1,12 +1,18 @@ +import 'dart:async'; +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import '../../../appRouters.dart'; import '../../../app_settings/app_colors.dart'; +import '../../../main.dart'; import '../../../tools/titleAppBar.dart'; import '../../../translations/trans_lib.dart'; +import 'lockAddressGaoDe_page.dart'; + class LockAddressPage extends StatefulWidget { const LockAddressPage({Key? key}) : super(key: key); @@ -14,27 +20,58 @@ class LockAddressPage extends StatefulWidget { State createState() => _LockAddressPageState(); } -class _LockAddressPageState extends State { +class _LockAddressPageState extends State with RouteAware{ + @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.mainBackgroundColor, appBar: TitleAppBar( - barTitle: "锁地址", + barTitle: TranslationLoader.lanKeys!.lockAddress!.tr, haveBack: true, backgroundColor: AppColors.mainColor, actionsList: [ TextButton( child: Text( - "保存", + TranslationLoader.lanKeys!.next!.tr, style: TextStyle(color: Colors.white, fontSize: 24.sp), ), onPressed: () { - Navigator.pushNamed(context, Routers.saveLockPage); + Get.toNamed(Routers.saveLockPage)!.then((value) { + dispose(); + }); + // Navigator.pushNamed(context, Routers.saveLockPage); }, ), ], ), - body: Container()); + body: LockAddressGaoDePage()); } + + @override + void dispose() { + super.dispose(); + routeObserver.unsubscribe(this); + print("地图界面销毁了"); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); +// 订阅 routeObserver,之后就会尝试调用抽象类 RouteAware 的方法 + routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute); + } + + @override + void didPush() { + // 当前页面入栈 + print("当前页面入栈"); + } + + @override + void didPopNext() { + // 当前路由的下个路由出栈,且当前页面显示 + print("当前路由的下个路由出栈,且当前页面显示"); + } + } diff --git a/star_lock/lib/mine/addLock/lockAddress/lockAddress_state.dart b/star_lock/lib/mine/addLock/lockAddress/lockAddress_state.dart new file mode 100644 index 00000000..3926eed4 --- /dev/null +++ b/star_lock/lib/mine/addLock/lockAddress/lockAddress_state.dart @@ -0,0 +1,5 @@ + + +class LockAddressState { + +} \ 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 1303d9c4..fdcbfe48 100644 --- a/star_lock/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart +++ b/star_lock/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart @@ -1,12 +1,15 @@ import 'dart:async'; +import 'package:flutter/material.dart'; import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; +import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:star_lock/blue/io_protocol/io_getPrivateKey.dart'; import 'package:star_lock/blue/io_protocol/io_getPublicKey.dart'; import 'package:star_lock/tools/baseGetXController.dart'; +import '../../../appRouters.dart'; import '../../../blue/blue_manage.dart'; import '../../../blue/io_protocol/io_addUser.dart'; import '../../../blue/io_protocol/io_reply.dart'; @@ -38,10 +41,6 @@ class NearbyLockLogic extends BaseGetXController{ if(reply is GetPrivateKeyReply) { _replyGetPrivateKeyKey(reply); } - - if(reply is AddUserReply) { - _replyAddUserKey(reply); - } }); } @@ -91,34 +90,7 @@ class NearbyLockLogic extends BaseGetXController{ var savePrivateKeyList = changeIntListToStringList(privateKey); Storage.setStringList(saveBluePrivateKey, savePrivateKeyList); - // signKey - List signKey = reply.data.sublist(16); - var savesignKeyList = changeIntListToStringList(signKey); - Storage.setStringList(saveBlueSignKey, savesignKeyList); - - var token = await Storage.getStringList(saveBlueToken); - List getTokenList = [0,0,0,0]; - if(token != null){ - getTokenList = changeStringListToIntList(token); - } - - print("privateKey:$privateKey signKey:$signKey"); - IoSenderManage.senderAddUser( - lockID:BlueManage().connectDeviceName, - authUserID:"100001", - keyID:"1", - userID:"100001", - openMode:1, - keyType:1, - startDate:0x11223344, - expireDate:0x11223344, - role:255, - password:"123456", - needAuthor:1, - publicKey:publicKeyDataList, - privateKey:privateKey, - token: getTokenList - ); + Get.toNamed(Routers.lockAddressPage); break; case 0x07: //无权限 @@ -136,68 +108,6 @@ class NearbyLockLogic extends BaseGetXController{ } } - Future _replyAddUserKey(Reply reply) async { - var lockId = reply.data.sublist(2, 42); - print("lockId:$lockId"); - - var token = reply.data.sublist(42, 46); - List strTokenList = changeIntListToStringList(token); - Storage.setStringList(saveBlueToken, strTokenList); - print("token:$token"); - - int status = reply.data[46]; - print("status:$status"); - - switch(status){ - case 0x00: - //成功 - print("添加用户数据解析成功"); - - break; - case 0x06: - //无权限 - print("需要鉴权"); - var privateKey = await Storage.getStringList(saveBluePrivateKey); - List getPrivateKeyList = changeStringListToIntList(privateKey!); - - var publicKey = await Storage.getStringList(saveBluePublicKey); - List publicKeyDataList = changeStringListToIntList(publicKey!); - - IoSenderManage.senderAddUser( - lockID:BlueManage().connectDeviceName, - authUserID:"100001", - keyID:"1", - userID:"100001", - openMode:1, - keyType:1, - startDate:0x11223344, - expireDate:0x11223344, - role:255, - password:"123456", - needAuthor:1, - publicKey:publicKeyDataList, - privateKey:getPrivateKeyList, - token: token - ); - break; - case 0x07: - //无权限 - print("用户无权限"); - - break; - case 0x09: - // 权限校验错误 - print("添加用户权限校验错误"); - - break; - default: - //失败 - print("领锁失败"); - - break; - } - } - @override void onReady() { // TODO: implement onReady diff --git a/star_lock/lib/mine/addLock/saveLock/entity/SaveLockEntity.dart b/star_lock/lib/mine/addLock/saveLock/entity/SaveLockEntity.dart new file mode 100644 index 00000000..98cad9d3 --- /dev/null +++ b/star_lock/lib/mine/addLock/saveLock/entity/SaveLockEntity.dart @@ -0,0 +1,56 @@ + +class SaveLockEntity { + int? errorCode; + String? description; + String? errorMsg; + SaveLockEntityData? data; + + SaveLockEntity( + {this.errorCode, this.description, this.errorMsg, this.data}); + + SaveLockEntity.fromJson(Map json) { + errorCode = json['errorCode']; + description = json['description']; + errorMsg = json['errorMsg']; + data = json['data'] != null + ? SaveLockEntityData.fromJson(json['data']) + : null; + } + + Map toJson() { + final Map data = {}; + data['errorCode'] = errorCode; + data['description'] = description; + data['errorMsg'] = errorMsg; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + return data; + } +} + +class SaveLockEntityData { + String? lockId; + String? nbRegisterSuccess; + String? keyId; + + SaveLockEntityData( + { this.lockId, + this.nbRegisterSuccess, + this.keyId}); + + SaveLockEntityData.fromJson(Map json) { + lockId = json['lockId']; + nbRegisterSuccess = json['nbRegisterSuccess']; + keyId = json['keyId']; + } + + Map toJson() { + final Map data = {}; + data['lockId'] = lockId; + data['nbRegisterSuccess'] = nbRegisterSuccess; + data['keyId'] = keyId; + + return data; + } +} diff --git a/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart b/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart new file mode 100644 index 00000000..d991300f --- /dev/null +++ b/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart @@ -0,0 +1,281 @@ + + +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; +import 'package:get/get.dart'; + +import '../../../blue/blue_manage.dart'; +import '../../../blue/io_protocol/io_addUser.dart'; +import '../../../blue/io_protocol/io_getLockStatu.dart'; +import '../../../blue/io_protocol/io_reply.dart'; +import '../../../blue/io_tool/io_manager.dart'; +import '../../../blue/io_tool/io_tool.dart'; +import '../../../blue/io_tool/manager_event_bus.dart'; +import '../../../blue/sender_manage.dart'; +import '../../../network/api_repository.dart'; +import '../../../tools/baseGetXController.dart'; +import '../../../tools/storage.dart'; +import 'saveLock_state.dart'; + +class SaveLockLogic extends BaseGetXController { + + final SaveLockState state = SaveLockState(); + + // 获取解析后的数据 + late StreamSubscription _replySubscription; + void _initReplySubscription() { + _replySubscription = EventBusManager().eventBus!.on().listen((reply) { + if(reply is AddUserReply) { + _replyAddUserKey(reply); + } + + // 获取锁状态 + if(reply is GetLockStatuReply) { + _replyGetLockStatus(reply); + } + }); + } + + Future _replyAddUserKey(Reply reply) async { + var lockId = reply.data.sublist(2, 42); + print("lockId:$lockId"); + + var token = reply.data.sublist(42, 46); + List strTokenList = changeIntListToStringList(token); + Storage.setStringList(saveBlueToken, strTokenList); + print("token:$token"); + + int status = reply.data[46]; + print("status:$status"); + + switch(status){ + case 0x00: + //成功 + print("添加用户数据解析成功"); + bindBlueAdmin(); + break; + case 0x06: + //无权限 + print("需要鉴权"); + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + IoSenderManage.senderAddUser( + lockID:BlueManage().connectDeviceName, + authUserID:"100001", + keyID:"1", + userID:"100001", + openMode:1, + keyType:1, + startDate:0x11223344, + expireDate:0x11223344, + role:255, + password:"123456", + needAuthor:1, + publicKey:publicKeyDataList, + privateKey:getPrivateKeyList, + token: token + ); + break; + case 0x07: + //无权限 + print("用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("添加用户权限校验错误"); + + break; + default: + //失败 + print("领锁失败"); + + break; + } + } + + // 获取锁状态数据解析 + Future _replyGetLockStatus(Reply reply) async { + int status = reply.data[2]; + switch(status){ + case 0x00: + //成功 + print("${reply.commandType}数据解析成功"); + var softVersion = reply.data.sublist(3, 7); + print("softVersion:$softVersion"); + + var power = reply.data[7]; + print("power:$power"); + + // APP 用户数量 + var appUserCount = reply.data.sublist(50, 53); + print("appUserCount:$appUserCount"); + + // 黑名单用户数量 + var blacklistCount = reply.data[53]; + print("blacklistCount:$blacklistCount"); + + // 蓝牙钥匙数量 + var bleKeyCount = reply.data[54]; + print("bleKeyCount:$bleKeyCount"); + + // 剩余可添加用户数量 + var remainCount = reply.data.sublist(54, 56); + print("remainCount:$remainCount"); + + // 未上传开锁记录数量 + var notUploadCount = reply.data.sublist(56, 58); + print("notUploadCount:$notUploadCount"); + + // 已设置开门密码数量 + var pwdCount = reply.data[58]; + print("pwdCount:$pwdCount"); + + // 已设置开门指纹数量 + var fingerprintCount = reply.data[59]; + print("fingerprintCount:$fingerprintCount"); + + // 锁当前时间 + var lockTime = reply.data.sublist(60, 64); + print("lockTime:$lockTime"); + + // 硬件版本信息,为固件升级提供判断依据 + var hardVersion = reply.data.sublist(64, 68); + print("hardVersion:$hardVersion"); + + break; + case 0x06: + //无权限 + print("${reply.commandType}需要鉴权"); + + break; + case 0x07: + //无权限 + print("${reply.commandType}用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType}权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType}失败"); + + break; + } + } + + // 保存事件,先调用蓝牙,蓝牙调用成功后再调用后台接口 + _saveLockAction(){ + addUserConnectBlue(); + } + + // 添加用户 + Future addUserConnectBlue() async { + // 进来之后首先连接 + BlueManage().connect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", connectStateCallBack: (DeviceConnectionState state) async { + if (state == DeviceConnectionState.connected){ + // 私钥 + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = [0,0,0,0]; + if(token != null){ + getTokenList = changeStringListToIntList(token); + } + + IoSenderManage.senderAddUser( + lockID:BlueManage().connectDeviceName, + authUserID:"100001", + keyID:"1", + userID:"100001", + openMode:1, + keyType:1, + startDate:0x11223344, + expireDate:0x11223344, + role:255, + password:"123456", + needAuthor:1, + publicKey:publicKeyDataList, + privateKey:getPrivateKeyList, + token: getTokenList + ); + } + }); + } + + void bindBlueAdmin() async{ + var lockData = ""; + var lockDataMap = {}; + lockDataMap['lockId'] = BlueManage().connectDeviceName; + lockDataMap['lockMac'] = BlueManage().connectDeviceId; + lockData = json.encode(lockDataMap); + + var entity = await ApiRepository.to.bindingBlueAdmin( + bindingDate:DateTime.now().millisecondsSinceEpoch.toString(), + hotelMode:"2", + lockAlias:state.aliName.value, + lockData:lockData, + nbInitSuccess:"0", + position:"113.918912, 22.653670", + deviceNo:"123456" + ); + if(entity.errorCode!.codeIsSuccessful){ + Get.close(3); + } + } + + // 获取锁状态 + Future _getLockStatus() async { + // 进来之后首先连接 + BlueManage().judgeReconnect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", (DeviceConnectionState state) async { + if (state == DeviceConnectionState.connected) { + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + IoSenderManage.senderGetLockStatu( + lockID:BlueManage().connectDeviceName, + userID:"100001", + privateKey:getPrivateKeyList, + ); + } + }); + } + + @override + void onReady() { + // TODO: implement onReady + super.onReady(); + print("onReady()"); + + _initReplySubscription(); + } + + @override + void onInit() { + // TODO: implement onInit + super.onInit(); + print("onInit()"); + + _getLockStatus(); + } + + @override + void onClose() { + // TODO: implement onClose + super.onClose(); + _replySubscription.cancel(); + } + +} \ No newline at end of file diff --git a/star_lock/lib/mine/addLock/saveLock/saveLock_page.dart b/star_lock/lib/mine/addLock/saveLock/saveLock_page.dart index 77856223..59188105 100644 --- a/star_lock/lib/mine/addLock/saveLock/saveLock_page.dart +++ b/star_lock/lib/mine/addLock/saveLock/saveLock_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; @@ -6,6 +7,7 @@ import '../../../app_settings/app_colors.dart'; import '../../../tools/submitBtn.dart'; import '../../../tools/titleAppBar.dart'; import '../../../translations/trans_lib.dart'; +import 'saveLock_logic.dart'; class SaveLockPage extends StatefulWidget { const SaveLockPage({Key? key}) : super(key: key); @@ -15,6 +17,9 @@ class SaveLockPage extends StatefulWidget { } class _SaveLockPageState extends State { + final logic = Get.put(SaveLockLogic()); + final state = Get.find().state; + @override Widget build(BuildContext context) { return Scaffold( @@ -37,7 +42,14 @@ class _SaveLockPageState extends State { // color: Colors.red, padding: EdgeInsets.only(left: 50.w, right: 50.w), child: TextField( + controller: state.aliNameController, + onChanged: (v){ + state.aliName.value = v; + }, textAlign:TextAlign.center, + inputFormatters: [ + LengthLimitingTextInputFormatter(32), + ], // style:TextStyle(height: 1.1, fontSize: 36.sp, fontWeight: FontWeight.w400, color:AppColors.mainColor), decoration: InputDecoration( hintText: '请填写信息', diff --git a/star_lock/lib/mine/addLock/saveLock/saveLock_state.dart b/star_lock/lib/mine/addLock/saveLock/saveLock_state.dart new file mode 100644 index 00000000..9ce77df0 --- /dev/null +++ b/star_lock/lib/mine/addLock/saveLock/saveLock_state.dart @@ -0,0 +1,21 @@ + + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../blue/blue_manage.dart'; + +class SaveLockState { + + var aliName = ''.obs; + TextEditingController aliNameController = TextEditingController(); + + SaveLockState() { + aliName.value = BlueManage().connectDeviceName; + aliNameController.text = aliName.value; + } + + void onClose() { + aliNameController.dispose(); + } +} \ No newline at end of file diff --git a/star_lock/lib/network/api.dart b/star_lock/lib/network/api.dart index 26223310..093e2155 100644 --- a/star_lock/lib/network/api.dart +++ b/star_lock/lib/network/api.dart @@ -17,4 +17,7 @@ abstract class Api { final String keyOperationRecordURL = '/lockRecords/list'; //电子钥匙操作记录 final String uploadElectricQuantityURL = '/room/uploadElectricQuantity'; //锁电量更新 + + final String bindingBlueAdminURL = + '/lock/bindAdmin'; //绑定蓝牙管理员 } diff --git a/star_lock/lib/network/api_provider.dart b/star_lock/lib/network/api_provider.dart index 1fa0f21b..2b55bc31 100644 --- a/star_lock/lib/network/api_provider.dart +++ b/star_lock/lib/network/api_provider.dart @@ -195,6 +195,27 @@ class ApiProvider extends BaseProvider { 'searchStr': searchStr, 'timezoneRawOffSet': timezoneRawOffSet })); + + // 绑定蓝牙管理员 + Future bindingBlueAdmin( + String bindingDate, + String hotelMode, + String lockAlias, + String lockData, + String nbInitSuccess, + String position, + String deviceNo) => + post( + bindingBlueAdminURL.toUrl, + jsonEncode({ + 'bindingDate': bindingDate, + 'hotelMode': hotelMode, + "lockAlias": lockAlias, + 'lockData': lockData, + "nbInitSuccess": nbInitSuccess, + 'position': position, + 'deviceNo': deviceNo + })); } extension ExtensionString on String { diff --git a/star_lock/lib/network/api_repository.dart b/star_lock/lib/network/api_repository.dart index a84a6b92..be7061fb 100644 --- a/star_lock/lib/network/api_repository.dart +++ b/star_lock/lib/network/api_repository.dart @@ -5,6 +5,7 @@ import '../common/safetyVerification/entity/CheckSafetyVerificationEntity.dart'; import '../common/safetyVerification/entity/SafetyVerificationEntity.dart'; import '../login/login/entity/LoginEntity.dart'; import '../login/register/entity/SendValidationCodeEntity.dart'; +import '../mine/addLock/saveLock/entity/SaveLockEntity.dart'; import 'api_provider.dart'; class ApiRepository { @@ -168,4 +169,24 @@ class ApiRepository { timezoneRawOffSet); return KeyOperationRecordEntity.fromJson(res.body); } + + // 绑定蓝牙管理员 + Future bindingBlueAdmin({ + required String bindingDate, + required String hotelMode, + required String lockAlias, + required String lockData, + required String nbInitSuccess, + required String position, + required String deviceNo}) async { + final res = await apiProvider.bindingBlueAdmin( + bindingDate, + hotelMode, + lockAlias, + lockData, + nbInitSuccess, + position, + deviceNo); + return SaveLockEntity.fromJson(res.body); + } } diff --git a/star_lock/lib/tools/tf_loginInput.dart b/star_lock/lib/tools/tf_loginInput.dart index 06a9294b..e3dc9d6b 100644 --- a/star_lock/lib/tools/tf_loginInput.dart +++ b/star_lock/lib/tools/tf_loginInput.dart @@ -49,6 +49,7 @@ class LoginInput extends StatelessWidget { controller: controller, onChanged: onchangeAction, autofocus: false, + inputFormatters:inputFormatters, decoration: InputDecoration( //输入里面输入文字内边距设置 contentPadding: const EdgeInsets.only( diff --git a/star_lock/lib/translations/lanKeyEntity.dart b/star_lock/lib/translations/lanKeyEntity.dart index c3973591..2234b02f 100644 --- a/star_lock/lib/translations/lanKeyEntity.dart +++ b/star_lock/lib/translations/lanKeyEntity.dart @@ -188,6 +188,7 @@ class LanKeyEntity { this.lanChinese, this.multilingual, this.addLock, + this.lockAddress, this.selectLockType, this.videoIntercomDoorLock, this.NFCPassiveLock, @@ -573,6 +574,7 @@ class LanKeyEntity { lanChinese = json['lanChinese']; multilingual = json['multilingual']; addLock = json['addLock']; + lockAddress = json["lockAddress"]; selectLockType = json['selectLockType']; videoIntercomDoorLock = json['videoIntercomDoorLock']; NFCPassiveLock = json['NFCPassiveLock']; @@ -975,6 +977,7 @@ class LanKeyEntity { String? lanChinese; String? multilingual; String? addLock; + String? lockAddress; String? selectLockType; String? videoIntercomDoorLock; String? NFCPassiveLock; @@ -1374,6 +1377,7 @@ class LanKeyEntity { map['lanChinese'] = lanChinese; map['multilingual'] = multilingual; map['addLock'] = addLock; + map['lockAddress'] = lockAddress; map['selectLockType'] = selectLockType; map['videoIntercomDoorLock'] = videoIntercomDoorLock; map['NFCPassiveLock'] = NFCPassiveLock; diff --git a/star_lock/pubspec.yaml b/star_lock/pubspec.yaml index 8da6a97d..096a5a02 100644 --- a/star_lock/pubspec.yaml +++ b/star_lock/pubspec.yaml @@ -88,6 +88,13 @@ dependencies: encrypt: ^5.0.1 crypto: ^3.0.3 + #高德地图定位 + amap_flutter_location: ^3.0.0 + #权限使用 + permission_handler: ^10.4.3 + #高德地图地图 + amap_flutter_map: ^3.0.0 + dev_dependencies: flutter_test: sdk: flutter diff --git a/star_lock/windows/flutter/generated_plugin_registrant.cc b/star_lock/windows/flutter/generated_plugin_registrant.cc index c0814364..e2cbdfa4 100644 --- a/star_lock/windows/flutter/generated_plugin_registrant.cc +++ b/star_lock/windows/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { @@ -15,6 +16,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("AjCaptchaFlutterPluginCApi")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/star_lock/windows/flutter/generated_plugins.cmake b/star_lock/windows/flutter/generated_plugins.cmake index 5f570cfc..fda93fcf 100644 --- a/star_lock/windows/flutter/generated_plugins.cmake +++ b/star_lock/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST aj_captcha_flutter file_selector_windows + permission_handler_windows url_launcher_windows )