Merge branch 'master' of https://gitee.com/weishaoyang/star_lock
This commit is contained in:
commit
7a891b4c79
@ -28,10 +28,12 @@ class BlueManage{
|
||||
String connectDeviceMacAddress = "";
|
||||
String connectDeviceName = "";
|
||||
|
||||
final int _limitLen = 20;
|
||||
// final int _limitLen = 20;
|
||||
|
||||
// 监听发送事件
|
||||
StreamSubscription<EventSendModel>? _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<void> stopScan() async {
|
||||
await _scanSubscription?.cancel();
|
||||
_scanSubscription = null;
|
||||
}
|
||||
|
||||
// 断开连接
|
||||
Future<void> 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 = <int>[];
|
||||
// 初始化数组为空
|
||||
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 = <int>[];
|
||||
}
|
||||
}else{
|
||||
// 当包没有头时 是分包的包 直接添加
|
||||
allData.addAll(data);
|
||||
// var len = allData[8] * 256 + allData[9];
|
||||
print("dataLen222:$dataLen");
|
||||
if(dataLen <= (allData.length - 14)){
|
||||
// 当长度小于等于当前包的数据时 直接解析数据
|
||||
CommandReciverManager.appDataReceive(allData);
|
||||
// 发送完解析初始化数组
|
||||
allData = <int>[];
|
||||
}
|
||||
}
|
||||
|
||||
CommandReciverManager.appDataReceive(allData);
|
||||
}, onError: (dynamic error) {
|
||||
EasyLoading.dismiss();
|
||||
print("subscribeToCharacteristic error:$error");
|
||||
@ -291,11 +325,11 @@ class BlueManage{
|
||||
Future<void> writeCharacteristicWithResponse(List<int> 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<int> valueList = value;
|
||||
List subData = splitList(valueList, _limitLen);
|
||||
List subData = splitList(valueList, mtuLength);
|
||||
print('得到的分割数据:$subData');
|
||||
|
||||
for (int i = 0; i < subData.length; i++) {
|
||||
|
||||
@ -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!);
|
||||
|
||||
|
||||
@ -256,17 +256,25 @@ List<int> intToByte2ListLow(int value) => [value >> 8, value];
|
||||
|
||||
String radixHex16String(List<int> codeUnits) {
|
||||
String result = '';
|
||||
codeUnits.forEach((value) {
|
||||
for (var value in codeUnits) {
|
||||
result += value.toRadixString(16).padLeft(2, '0');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String radixHex16StringTo2String(List<int> codeUnits) {
|
||||
String result = '';
|
||||
codeUnits.forEach((value) {
|
||||
result += int.parse(value.toRadixString(16).padLeft(2, '0'),radix: 16).toRadixString(2);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
String asciiString(List<int> codeUnits) {
|
||||
String result = '';
|
||||
codeUnits.forEach((value) {
|
||||
for (var value in codeUnits) {
|
||||
result += String.fromCharCode(value);
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -394,7 +394,7 @@ class LockDetailLogic extends BaseGetXController{
|
||||
|
||||
// 点击开门事件
|
||||
Future<void> 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<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
|
||||
@ -483,9 +483,9 @@ class LockDetailLogic extends BaseGetXController{
|
||||
}
|
||||
|
||||
// 备用逻辑,进入管理钥匙界面获取锁状态
|
||||
Future<void> connectBlue() async {
|
||||
Future<void> 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<int> 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
|
||||
|
||||
@ -42,8 +42,8 @@ class _LockDetailPageState extends State<LockDetailPage> 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<int> publicKeyData =
|
||||
state.keyInfos.value.bluetooth!.publicKey!.cast<int>();
|
||||
@ -63,7 +63,7 @@ class _LockDetailPageState extends State<LockDetailPage> 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<LockDetailPage> with RouteAware {
|
||||
bottomItem(
|
||||
'images/main/icon_main_set.png', TranslationLoader.lanKeys!.set!.tr,
|
||||
() {
|
||||
BlueManage().stopScan();
|
||||
Get.toNamed(Routers.lockSetPage, arguments: widget.keyInfo);
|
||||
}),
|
||||
];
|
||||
|
||||
@ -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<AddLockPage> 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<bool> getMicrophonePermission() async {
|
||||
// You can request multiple permissions at once.
|
||||
Map<Permission, PermissionStatus> 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() {}
|
||||
|
||||
@ -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<LockAddressGaoDePage>{
|
||||
final logic = Get.put(LockAddressGaoDeLogic());
|
||||
final state = Get.find<LockAddressGaoDeLogic>().state;
|
||||
|
||||
// 高德地图
|
||||
static const AMapApiKey amapApiKeys = AMapApiKey(iosKey: '883a3355d2d77c2fdc2667030dc97ffe', androidKey: '11d49b3f4fc09c04a02bbb7500925ba2');
|
||||
|
||||
AMapController? mapController;
|
||||
AMapFlutterLocation? location;
|
||||
AMapFlutterLocation location = AMapFlutterLocation();
|
||||
|
||||
PermissionStatus? permissionStatus;
|
||||
Map<String, Object>? addressInfo;
|
||||
@ -44,9 +45,12 @@ class _LockAddressGaoDePageState extends State<LockAddressGaoDePage>{
|
||||
|
||||
AMapFlutterLocation.updatePrivacyAgree(true);
|
||||
AMapFlutterLocation.updatePrivacyShow(true, true);
|
||||
AMapFlutterLocation.setApiKey("11d49b3f4fc09c04a02bbb7500925ba2", "883a3355d2d77c2fdc2667030dc97ffe");
|
||||
|
||||
requestPermission();
|
||||
|
||||
AMapFlutterLocation.setApiKey("11d49b3f4fc09c04a02bbb7500925ba2", "883a3355d2d77c2fdc2667030dc97ffe");
|
||||
|
||||
requestLocation();
|
||||
}
|
||||
|
||||
Future<void> requestPermission() async {
|
||||
@ -58,37 +62,29 @@ class _LockAddressGaoDePageState extends State<LockAddressGaoDePage>{
|
||||
print("拒绝");
|
||||
break;
|
||||
case PermissionStatus.granted:
|
||||
requestLocation();
|
||||
_setLocationOption();
|
||||
location.startLocation();
|
||||
break;
|
||||
case PermissionStatus.limited:
|
||||
print("限制");
|
||||
break;
|
||||
default:
|
||||
print("其他状态");
|
||||
requestLocation();
|
||||
// requestLocation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> 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<LockAddressGaoDePage>{
|
||||
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<LockAddressGaoDePage>{
|
||||
// 初始化地图中心
|
||||
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<LockAddressGaoDePage>{
|
||||
|
||||
}
|
||||
|
||||
///设置定位参数
|
||||
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端的定位模式<br>
|
||||
///可选值:<br>
|
||||
///<li>[AMapLocationMode.Battery_Saving]</li>
|
||||
///<li>[AMapLocationMode.Device_Sensors]</li>
|
||||
///<li>[AMapLocationMode.Hight_Accuracy]</li>
|
||||
locationOption.locationMode = AMapLocationMode.Battery_Saving;
|
||||
|
||||
///设置iOS端的定位最小更新距离<br>
|
||||
locationOption.distanceFilter = -1;
|
||||
|
||||
///设置iOS端期望的定位精度
|
||||
/// 可选值:<br>
|
||||
/// <li>[DesiredAccuracy.Best] 最高精度</li>
|
||||
/// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
|
||||
/// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
|
||||
/// <li>[DesiredAccuracy.Kilometer] 1000米</li>
|
||||
/// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
|
||||
locationOption.desiredAccuracy = DesiredAccuracy.BestForNavigation;
|
||||
|
||||
///设置iOS端是否允许系统暂停定位
|
||||
locationOption.pausesLocationUpdatesAutomatically = false;
|
||||
|
||||
///将定位参数设置给定位插件
|
||||
location.setLocationOption(locationOption);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
|
||||
location?.destroy();
|
||||
location.destroy();
|
||||
print("地图界面销毁了");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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"];
|
||||
}
|
||||
}
|
||||
@ -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<void> _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<int> privateKey = reply.data.sublist(0, 16);
|
||||
print("privateKey:$privateKey");
|
||||
var savePrivateKeyList = changeIntListToStringList(privateKey);
|
||||
Storage.setStringList(saveBluePrivateKey, savePrivateKeyList);
|
||||
|
||||
// signKey
|
||||
List<int> signKey = reply.data.sublist(16, 32);
|
||||
print("signKey:$signKey");
|
||||
var saveSignKeyList = changeIntListToStringList(signKey);
|
||||
Storage.setStringList(saveBlueSignKey, saveSignKeyList);
|
||||
|
||||
Get.toNamed(Routers.lockAddressGaoDePage);
|
||||
// 时间戳
|
||||
List<int> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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<int> featureValue){
|
||||
// 字符数组转化为16进制字符串
|
||||
String featureValueStr = asciiString(featureValue);
|
||||
// 16进制字符串转化为2进制的字符串 获取的是逆序的需要倒序 前面有0会消失 需要自动补全 暂时定位57个功能 要补全60
|
||||
String featureValueTwoStr = int.parse(featureValueStr,radix: 16).toRadixString(2);
|
||||
List<int> featureValueTwoList = [];
|
||||
for(int i = 0;i<featureValueTwoStr.length;i++){
|
||||
featureValueTwoList.add(int.parse(featureValueTwoStr[i]));
|
||||
}
|
||||
featureValueTwoList = featureValueTwoList.reversed.toList();
|
||||
List allFeatureValueTwoList = getFixedLengthList(featureValueTwoList, 60 - featureValueTwoList.length);
|
||||
return allFeatureValueTwoList;
|
||||
}
|
||||
|
||||
// 保存事件,先调用蓝牙,蓝牙调用成功后再调用后台接口
|
||||
saveLockAction(){
|
||||
addUserConnectBlue();
|
||||
@ -312,18 +357,18 @@ class SaveLockLogic extends BaseGetXController {
|
||||
void bindBlueAdmin() async{
|
||||
var lockDataMap = {};
|
||||
lockDataMap['lockName'] = BlueManage().connectDeviceName;
|
||||
lockDataMap['lockMac'] = "AB:C1:40:61:54:61";
|
||||
lockDataMap['lockMac'] = BlueManage().connectDeviceMacAddress;
|
||||
// lockDataMap['lockMac'] = BlueManage().connectDeviceMacAddress;
|
||||
|
||||
var positionMap = {};
|
||||
positionMap['longitude'] = state.addressMap["longitude"];
|
||||
positionMap['latitude'] = state.addressMap["latitude"];
|
||||
positionMap['country'] = state.addressMap["country"];
|
||||
positionMap['province'] = state.addressMap["province"];
|
||||
positionMap['city'] = state.addressMap["city"];
|
||||
positionMap['district'] = state.addressMap["district"];
|
||||
positionMap['township'] = state.addressMap["street"];
|
||||
positionMap['address'] = state.addressMap["address"];
|
||||
positionMap['longitude'] = state.addressInfo["longitude"];
|
||||
positionMap['latitude'] = state.addressInfo["latitude"];
|
||||
positionMap['country'] = state.addressInfo["country"];
|
||||
positionMap['province'] = state.addressInfo["province"];
|
||||
positionMap['city'] = state.addressInfo["city"];
|
||||
positionMap['district'] = state.addressInfo["district"];
|
||||
positionMap['township'] = state.addressInfo["street"];
|
||||
positionMap['address'] = state.addressInfo["address"];
|
||||
|
||||
var bluetooth = {};
|
||||
bluetooth['bluetoothDeviceId'] = BlueManage().connectDeviceMacAddress;
|
||||
@ -354,7 +399,7 @@ class SaveLockLogic extends BaseGetXController {
|
||||
deviceNo:"123456",
|
||||
// lockUserNo:userNo.toString(),
|
||||
lockUserNo:"1234",
|
||||
pwdTimestamp:DateTime.now().millisecondsSinceEpoch.toString()
|
||||
pwdTimestamp:state.pwdTimestamp.value.toString()
|
||||
);
|
||||
if(entity.errorCode!.codeIsSuccessful){
|
||||
eventBus.fire(RefreshLockListInfoDataEvent());
|
||||
|
||||
@ -7,13 +7,17 @@ import '../../../blue/blue_manage.dart';
|
||||
class SaveLockState {
|
||||
|
||||
var aliName = ''.obs;
|
||||
var addressMap = {}.obs;
|
||||
var pwdTimestamp= 0.obs;
|
||||
var addressInfo = {}.obs;
|
||||
TextEditingController aliNameController = TextEditingController();
|
||||
|
||||
SaveLockState() {
|
||||
aliName.value = BlueManage().connectDeviceName;
|
||||
aliNameController.text = aliName.value;
|
||||
addressMap.value = Get.arguments as Map;
|
||||
|
||||
Map map = Get.arguments;
|
||||
pwdTimestamp.value = map["pwdTimestamp"];
|
||||
addressInfo.value = map["addressInfo"];
|
||||
}
|
||||
|
||||
void onClose() {
|
||||
|
||||
116
star_lock/lib/tools/permissionUtil.dart
Normal file
116
star_lock/lib/tools/permissionUtil.dart
Normal file
@ -0,0 +1,116 @@
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
/// @ClassName ${NAME}
|
||||
/// 作者: szj
|
||||
/// 时间: ${DATE} ${TIME}
|
||||
/// CSDN:https://blog.csdn.net/weixin_44819566
|
||||
/// 公众号:码上变有钱
|
||||
|
||||
typedef BlockScuessStatus = void Function();
|
||||
class PermissionUtil {
|
||||
PermissionUtil(this._context);
|
||||
|
||||
final List<String> _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");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user