Merge branch 'master' of https://gitee.com/weishaoyang/star_lock
# Conflicts: # star_lock/lib/network/request_interceptor.dart
This commit is contained in:
commit
3c37828adb
@ -4,6 +4,7 @@ import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
|||||||
import 'package:star_lock/blue/sender_manage.dart';
|
import 'package:star_lock/blue/sender_manage.dart';
|
||||||
|
|
||||||
import '../app_settings/app_settings.dart';
|
import '../app_settings/app_settings.dart';
|
||||||
|
import 'io_tool/io_manager.dart';
|
||||||
import 'io_tool/io_tool.dart';
|
import 'io_tool/io_tool.dart';
|
||||||
import 'io_tool/manager_event_bus.dart';
|
import 'io_tool/manager_event_bus.dart';
|
||||||
import 'reciver_data.dart';
|
import 'reciver_data.dart';
|
||||||
@ -52,7 +53,6 @@ class BlueManage{
|
|||||||
} else {
|
} else {
|
||||||
_scanDevices.add(device);
|
_scanDevices.add(device);
|
||||||
}
|
}
|
||||||
// EventBusManager().eventBusFir(_scanDevices);
|
|
||||||
scanResultCallBack(_scanDevices);
|
scanResultCallBack(_scanDevices);
|
||||||
}
|
}
|
||||||
// _pushState();
|
// _pushState();
|
||||||
@ -62,13 +62,15 @@ class BlueManage{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 连接监听状态
|
/// 连接监听状态
|
||||||
Future<void> connect(String deviceMAC) async {
|
Future<void> connect(String deviceMAC, String deviceName) async {
|
||||||
print("connect:$deviceMAC");
|
print("connect:$deviceMAC");
|
||||||
_flutterReactiveBle!.connectToDevice(id: deviceMAC).listen((connectionStateUpdate) {
|
_flutterReactiveBle!.connectToDevice(id: deviceMAC).listen((connectionStateUpdate) {
|
||||||
print('ConnectionState for device $deviceMAC : ${connectionStateUpdate.connectionState}');
|
print('ConnectionState for device $deviceMAC : ${connectionStateUpdate.connectionState}');
|
||||||
// EventBusManager().eventBusFir(connectionStateUpdate);
|
// EventBusManager().eventBusFir(connectionStateUpdate);
|
||||||
if(connectionStateUpdate.connectionState == DeviceConnectionState.connected){
|
if(connectionStateUpdate.connectionState == DeviceConnectionState.connected){
|
||||||
// getPublicKey(update.deviceId);
|
// getPublicKey(update.deviceId);
|
||||||
|
// 先配置lockId
|
||||||
|
IoManager().configCurrentDeviceLockId(deviceName);
|
||||||
// 如果状态是连接的开始发现服务
|
// 如果状态是连接的开始发现服务
|
||||||
discoverServices(deviceMAC);
|
discoverServices(deviceMAC);
|
||||||
}
|
}
|
||||||
@ -137,7 +139,7 @@ class BlueManage{
|
|||||||
_flutterReactiveBle!.subscribeToCharacteristic(characteristic).listen((data) {
|
_flutterReactiveBle!.subscribeToCharacteristic(characteristic).listen((data) {
|
||||||
// code to handle incoming data
|
// code to handle incoming data
|
||||||
print("subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data");
|
print("subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data");
|
||||||
CommandReciverManager.appDataReceive(data, "");
|
CommandReciverManager.appDataReceive(data);
|
||||||
}, onError: (dynamic error) {
|
}, onError: (dynamic error) {
|
||||||
print("subscribeToCharacteristic error:$error");
|
print("subscribeToCharacteristic error:$error");
|
||||||
});
|
});
|
||||||
@ -145,7 +147,7 @@ class BlueManage{
|
|||||||
|
|
||||||
// 写入
|
// 写入
|
||||||
Future<void> writeCharacteristicWithResponse(QualifiedCharacteristic characteristic, List<int> value) async {
|
Future<void> writeCharacteristicWithResponse(QualifiedCharacteristic characteristic, List<int> value) async {
|
||||||
print('Write with characteristicId:${characteristic.characteristicId} serviceId:${characteristic.serviceId} deviceId:${characteristic.deviceId} value : $value \nhexStr:${radixString(value)}');
|
print('Write with characteristicId:${characteristic.characteristicId} serviceId:${characteristic.serviceId} deviceId:${characteristic.deviceId} value : $value \nhexStr:${radixHex16String(value)}');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<int> valueList = value;
|
List<int> valueList = value;
|
||||||
|
|||||||
@ -1,13 +1,18 @@
|
|||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../../tools/storage.dart';
|
||||||
|
import '../io_tool/io_manager.dart';
|
||||||
import '../io_tool/io_tool.dart';
|
import '../io_tool/io_tool.dart';
|
||||||
|
import '../sm4Encipher/sm4.dart';
|
||||||
import 'io_reply.dart';
|
import 'io_reply.dart';
|
||||||
import 'io_sender.dart';
|
import 'io_sender.dart';
|
||||||
import 'io_type.dart';
|
import 'io_type.dart';
|
||||||
|
import 'package:crypto/crypto.dart' as crypto;
|
||||||
|
|
||||||
//TODO:添加用户
|
//TODO:添加用户
|
||||||
class AddUserCommand extends SenderProtocol {
|
class AddUserCommand extends SenderProtocol {
|
||||||
|
|
||||||
int? cmdID;
|
|
||||||
String? lockID;
|
String? lockID;
|
||||||
String? authUserID;
|
String? authUserID;
|
||||||
String? keyID;
|
String? keyID;
|
||||||
@ -18,11 +23,11 @@ class AddUserCommand extends SenderProtocol {
|
|||||||
int? expireDate;
|
int? expireDate;
|
||||||
int? role;
|
int? role;
|
||||||
String? password;
|
String? password;
|
||||||
int? token;
|
int? needAuthor;
|
||||||
int? authCodeLen;
|
List<int>? publicKey;
|
||||||
String? authCode;
|
List<int>? privateKey;
|
||||||
|
List<int>? token;
|
||||||
AddUserCommand({
|
AddUserCommand({
|
||||||
this.cmdID,
|
|
||||||
this.lockID,
|
this.lockID,
|
||||||
this.authUserID,
|
this.authUserID,
|
||||||
this.keyID,
|
this.keyID,
|
||||||
@ -33,28 +38,127 @@ class AddUserCommand extends SenderProtocol {
|
|||||||
this.expireDate,
|
this.expireDate,
|
||||||
this.role,
|
this.role,
|
||||||
this.password,
|
this.password,
|
||||||
this.token,
|
this.needAuthor,
|
||||||
this.authCodeLen,
|
this.publicKey,
|
||||||
this.authCode,
|
this.privateKey,
|
||||||
|
this.token
|
||||||
}) : super(CommandType.addUser);
|
}) : super(CommandType.addUser);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<int> messageDetail() {
|
List<int> messageDetail() {
|
||||||
List<int> data = [];
|
List<int> data = [];
|
||||||
// data.add(0x21);
|
List<int> ebcData = [];
|
||||||
// int d = direction!.toInt();
|
|
||||||
// data.addAll(intToByte2ListHigh(d));
|
// 指令类型
|
||||||
// data.add(0x22);
|
int type = commandType!.typeValue;
|
||||||
// int s = speed!.toInt();
|
double typeDouble = type / 256;
|
||||||
// data.add(s);
|
int type1 = typeDouble.toInt();
|
||||||
return data;
|
int type2 = type % 256;
|
||||||
|
data.add(type1);
|
||||||
|
data.add(type2);
|
||||||
|
|
||||||
|
// 锁id 40
|
||||||
|
int lockIDLength = utf8.encode(lockID!).length;
|
||||||
|
data.addAll(utf8.encode(lockID!));
|
||||||
|
data = getFixedLengthList(data, 40 - lockIDLength);
|
||||||
|
|
||||||
|
//authUserID 20
|
||||||
|
int authUserIDLength = utf8.encode(authUserID!).length;
|
||||||
|
data.addAll(utf8.encode(authUserID!));
|
||||||
|
data = getFixedLengthList(data, 20 - authUserIDLength);
|
||||||
|
|
||||||
|
//KeyID 40
|
||||||
|
int keyIDLength = utf8.encode(keyID!).length;
|
||||||
|
data.addAll(utf8.encode(keyID!));
|
||||||
|
data = getFixedLengthList(data, 40 - keyIDLength);
|
||||||
|
|
||||||
|
//userID 要接受钥匙的用户的useid 20
|
||||||
|
int userIDLength = utf8.encode(authUserID!).length;
|
||||||
|
data.addAll(utf8.encode(authUserID!));
|
||||||
|
data = getFixedLengthList(data, 20 - authUserIDLength);
|
||||||
|
|
||||||
|
// openModel
|
||||||
|
data.add(openMode!);
|
||||||
|
|
||||||
|
// keyType
|
||||||
|
data.add(keyType!);
|
||||||
|
|
||||||
|
int? d1, d2;
|
||||||
|
if(role == 255){
|
||||||
|
d1 = 0;//Date.parse(new Date()) / 1000;
|
||||||
|
d2 = 0xffffffff;//d1 + 86440;
|
||||||
|
}else{
|
||||||
|
d1 = startDate;
|
||||||
|
d2 = expireDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartDate 4
|
||||||
|
data.add((d1! & 0xff000000) >> 24);
|
||||||
|
data.add((d1 & 0xff0000) >> 16);
|
||||||
|
data.add((d1 & 0xff00) >> 8);
|
||||||
|
data.add((d1 & 0xff));
|
||||||
|
|
||||||
|
// expireDate 4
|
||||||
|
data.add((d2! & 0xff000000) >> 24);
|
||||||
|
data.add((d2 & 0xff0000) >> 16);
|
||||||
|
data.add((d2 & 0xff00) >> 8);
|
||||||
|
data.add((d2 & 0xff));
|
||||||
|
|
||||||
|
// role 长度1 用户角色,0:普通用户,1:管理员,0xff:超级管理员
|
||||||
|
data.add(role!);
|
||||||
|
|
||||||
|
//password 超级管理员领锁时需验证该密码 20
|
||||||
|
int passwordLength = utf8.encode(password!).length;
|
||||||
|
data.addAll(utf8.encode(password!));
|
||||||
|
data = getFixedLengthList(data, 20 - passwordLength);
|
||||||
|
|
||||||
|
if(needAuthor == 0){
|
||||||
|
// 当token失效或者第一次发送的时候token为0
|
||||||
|
//Token 4
|
||||||
|
data.addAll(token!);
|
||||||
|
|
||||||
|
//AuthCodeLen 1
|
||||||
|
data.add(0);
|
||||||
|
} else {
|
||||||
|
// token 长度4 首次请求 Token 填 0,如果锁需要鉴权 操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。
|
||||||
|
data.addAll(token!);
|
||||||
|
|
||||||
|
List<int> authCodeData = [];
|
||||||
|
|
||||||
|
//KeyID
|
||||||
|
authCodeData.addAll(utf8.encode(keyID!));
|
||||||
|
|
||||||
|
//authUserID
|
||||||
|
authCodeData.addAll(utf8.encode(authUserID!));
|
||||||
|
|
||||||
|
//token 4 首次请求 Token 填 0,如果锁需要鉴权操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。
|
||||||
|
data.addAll([0, 0, 0, 0]);
|
||||||
|
|
||||||
|
authCodeData.addAll(publicKey!);
|
||||||
|
|
||||||
|
// 把KeyID、authUserID、时间戳、公钥通过md5加密之后就是authCode
|
||||||
|
var authCode = crypto.md5.convert(authCodeData);
|
||||||
|
|
||||||
|
data.add(authCode.bytes.length);
|
||||||
|
data.addAll(authCode.bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((data.length % 16) != 0) {
|
||||||
|
int add = (16 - data.length % 16);
|
||||||
|
for (int i = 0; i < add; i++) {
|
||||||
|
data.add(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print("addUserSM4Data:$data");
|
||||||
|
// 拿到数据之后通过LockId进行SM4 ECB加密 key:544d485f633335373034383064613864
|
||||||
|
ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB);
|
||||||
|
return ebcData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AddUserReply extends Reply {
|
class AddUserReply extends Reply {
|
||||||
AddUserReply.parseData(CommandType commandType, List<int> dataDetail)
|
AddUserReply.parseData(CommandType commandType, List<int> dataDetail)
|
||||||
: super.parseData(commandType, dataDetail) {
|
: super.parseData(commandType, dataDetail) {
|
||||||
int index = 0;
|
data = dataDetail;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,13 +3,16 @@ import 'dart:convert';
|
|||||||
import 'package:star_lock/blue/sm4Encipher/sm4.dart';
|
import 'package:star_lock/blue/sm4Encipher/sm4.dart';
|
||||||
|
|
||||||
import '../../tools/storage.dart';
|
import '../../tools/storage.dart';
|
||||||
|
import '../io_tool/io_manager.dart';
|
||||||
import '../io_tool/io_tool.dart';
|
import '../io_tool/io_tool.dart';
|
||||||
|
import '../sender_manage.dart';
|
||||||
import 'io_reply.dart';
|
import 'io_reply.dart';
|
||||||
import 'io_sender.dart';
|
import 'io_sender.dart';
|
||||||
import 'io_type.dart';
|
import 'io_type.dart';
|
||||||
|
|
||||||
import 'package:crypto/crypto.dart' as a;
|
import 'package:crypto/crypto.dart' as crypto;
|
||||||
import 'package:convert/convert.dart';
|
|
||||||
|
List<int>publicKeyDataList = [];
|
||||||
|
|
||||||
class GetPrivateKeyCommand extends SenderProtocol {
|
class GetPrivateKeyCommand extends SenderProtocol {
|
||||||
String? lockID;
|
String? lockID;
|
||||||
@ -29,6 +32,7 @@ class GetPrivateKeyCommand extends SenderProtocol {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
List<int> messageDetail() {
|
List<int> messageDetail() {
|
||||||
|
publicKeyDataList = publicKeyData!;
|
||||||
List<int> data = [];
|
List<int> data = [];
|
||||||
List<int> ebcData = [];
|
List<int> ebcData = [];
|
||||||
// print("lockID:${lockID!} lockID.utf8.encode${utf8.encode(lockID!)}");
|
// print("lockID:${lockID!} lockID.utf8.encode${utf8.encode(lockID!)}");
|
||||||
@ -88,19 +92,10 @@ class GetPrivateKeyCommand extends SenderProtocol {
|
|||||||
authCodeData.add((d1 & 0xff00) >> 8);
|
authCodeData.add((d1 & 0xff00) >> 8);
|
||||||
authCodeData.add((d1 & 0xff));
|
authCodeData.add((d1 & 0xff));
|
||||||
|
|
||||||
// String pubKey = "";
|
|
||||||
// Storage.getData("bluePublicKey").then((res) => {
|
|
||||||
// pubKey = res
|
|
||||||
// });
|
|
||||||
// var pubKey = "ovOvAHuL5+dBCw7L3Qt7IQ==";
|
|
||||||
// print("pubKey:$pubKey");
|
|
||||||
// List<int> pubKeyData = base64.decode(pubKey.toString());
|
|
||||||
// print("pubKeyData:$pubKeyData");
|
|
||||||
authCodeData.addAll(publicKeyData!);
|
authCodeData.addAll(publicKeyData!);
|
||||||
|
|
||||||
// 把KeyID、authUserID、时间戳、公钥通过md5加密之后就是authCode
|
// 把KeyID、authUserID、时间戳、公钥通过md5加密之后就是authCode
|
||||||
var authCode = a.md5.convert(authCodeData);
|
var authCode = crypto.md5.convert(authCodeData);
|
||||||
// print("authCodeData:$authCodeData \nauthCode:$authCode \nauthCodeBytes:${authCode.bytes}");
|
|
||||||
|
|
||||||
data.add(authCode.bytes.length);
|
data.add(authCode.bytes.length);
|
||||||
data.addAll(authCode.bytes);
|
data.addAll(authCode.bytes);
|
||||||
@ -112,13 +107,10 @@ class GetPrivateKeyCommand extends SenderProtocol {
|
|||||||
data.add(0);
|
data.add(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print("SM4Data:$data");
|
// print("SM4Data:$data");
|
||||||
// 拿到数据之后通过LockId进行SM4 ECB加密 key:544d485f633335373034383064613864
|
// 拿到数据之后通过LockId进行SM4 ECB加密 key:544d485f633335373034383064613864
|
||||||
String key = SM4.createHexKey(key: 'TMH_c3570480da8d');
|
ebcData = SM4.encrypt(data, key: utf8.encode(IoManager().getCurrentDeviceLockId), mode: SM4CryptoMode.ECB);
|
||||||
ebcData = SM4.encrypt(data, key: key, mode: SM4CryptoMode.ECB);
|
|
||||||
ebcData.removeRange(ebcData.length - 16, ebcData.length);
|
|
||||||
// ebcData = utf8.encode(getSM4Str(data, "TMH_c3570480da8d"));
|
|
||||||
print("ebcData:$ebcData");
|
|
||||||
return ebcData;
|
return ebcData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,24 +118,8 @@ class GetPrivateKeyCommand extends SenderProtocol {
|
|||||||
class GetPrivateKeyReply extends Reply {
|
class GetPrivateKeyReply extends Reply {
|
||||||
GetPrivateKeyReply.parseData(CommandType commandType, List<int> dataDetail)
|
GetPrivateKeyReply.parseData(CommandType commandType, List<int> dataDetail)
|
||||||
: super.parseData(commandType, dataDetail) {
|
: super.parseData(commandType, dataDetail) {
|
||||||
print('获取私钥');
|
data = dataDetail.sublist(2);
|
||||||
switch(dataDetail[0]){
|
status = data[0];
|
||||||
case 0x00:
|
// print("getData:$getData");
|
||||||
//成功
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 0x07:
|
|
||||||
//无权限
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 0x0f:
|
|
||||||
//用户已存在
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
//失败
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import '../../tools/storage.dart';
|
import '../../tools/storage.dart';
|
||||||
|
import '../io_tool/io_manager.dart';
|
||||||
import '../io_tool/io_tool.dart';
|
import '../io_tool/io_tool.dart';
|
||||||
import '../sender_manage.dart';
|
import '../sender_manage.dart';
|
||||||
import 'io_reply.dart';
|
import 'io_reply.dart';
|
||||||
@ -26,15 +27,15 @@ class GetPublicKeyCommand extends SenderProtocol {
|
|||||||
int type2 = type%256;
|
int type2 = type%256;
|
||||||
data.add(type1);
|
data.add(type1);
|
||||||
data.add(type2);
|
data.add(type2);
|
||||||
print("type:$type");
|
// print("type:$type");
|
||||||
print("type1:$type1");
|
// print("type1:$type1");
|
||||||
print("type2:$type2");
|
// print("type2:$type2");
|
||||||
|
|
||||||
print("lockID:${lockID!} lockID.utf8.encode${utf8.encode(lockID!)}");
|
print("lockID:${lockID!} lockID.utf8.encode${utf8.encode(lockID!)}");
|
||||||
int length = utf8.encode(lockID!).length;
|
int length = utf8.encode(lockID!).length;
|
||||||
data.addAll(utf8.encode(lockID!));
|
data.addAll(utf8.encode(lockID!));
|
||||||
data = getFixedLengthList(data, 40 - length);
|
data = getFixedLengthList(data, 40 - length);
|
||||||
print("dataaaaaa:$data");
|
// print("dataaaaaa:$data");
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,29 +43,7 @@ class GetPublicKeyCommand extends SenderProtocol {
|
|||||||
class GetPublicKeyReply extends Reply {
|
class GetPublicKeyReply extends Reply {
|
||||||
GetPublicKeyReply.parseData(CommandType commandType, List<int> dataDetail)
|
GetPublicKeyReply.parseData(CommandType commandType, List<int> dataDetail)
|
||||||
: super.parseData(commandType, dataDetail) {
|
: super.parseData(commandType, dataDetail) {
|
||||||
var tokenData = dataDetail.sublist(3);
|
status = dataDetail[2];
|
||||||
print('获取公钥:dataDetail:$dataDetail tokenData:$tokenData');
|
data = dataDetail;
|
||||||
switch(dataDetail[2]){
|
|
||||||
case 0x00:
|
|
||||||
//成功
|
|
||||||
String stringEncoded = base64.encode(tokenData);
|
|
||||||
print('获取公钥成功 publickey:$stringEncoded');
|
|
||||||
// 储存公钥
|
|
||||||
Storage.setData("bluePublicKey", stringEncoded);
|
|
||||||
IoSenderManage.getPrivateKey("TMH_c3570480da8d", "1", "1", 1, tokenData, 1);
|
|
||||||
break;
|
|
||||||
case 0x07:
|
|
||||||
//无权限
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 0x0f:
|
|
||||||
//用户已存在
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
//失败
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,22 +1,13 @@
|
|||||||
import 'io_type.dart';
|
import 'io_type.dart';
|
||||||
|
|
||||||
abstract class Reply{
|
abstract class Reply{
|
||||||
//value字节长度
|
|
||||||
int? packetHeader = 4; // 包头4个字节
|
|
||||||
int? packetType = 1; // 包类型1个字节
|
|
||||||
int? packetNumber = 1; // 包序号
|
|
||||||
int? packetIdentifier = 1; // 包标识
|
|
||||||
int? packetLength = 4; // 包标识
|
|
||||||
CommandType? commandType;
|
CommandType? commandType;
|
||||||
int? packetMcrc = 2; // 校验位
|
|
||||||
|
|
||||||
//command key flag
|
//command key flag
|
||||||
int commandKey = 0;
|
int status = 0;
|
||||||
|
List<int> data = [];
|
||||||
Reply.parseData(this.commandType, List<int> dataDetail);
|
Reply.parseData(this.commandType, List<int> dataDetail);
|
||||||
// Reply({this.result});
|
|
||||||
|
|
||||||
|
|
||||||
// bool get isSuccessfully => packetHeader == EF01EE02;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -48,17 +48,9 @@ abstract class SenderProtocol extends IOData {
|
|||||||
// print("_commandIndex:$_commandIndex commandIndexChang1$commandIndexChang1 commandIndexChang2:$commandIndexChang2");
|
// print("_commandIndex:$_commandIndex commandIndexChang1$commandIndexChang1 commandIndexChang2:$commandIndexChang2");
|
||||||
|
|
||||||
// 包标识
|
// 包标识
|
||||||
// 指令类型
|
// 指令类型 高 4 位表示包版本,低 4 位用来指示后面数据的加密类型,长度为 1 字节,加密类型取值说明,0:明文,1:AES128,2:SM4(事先约定密钥),3:SM4(设备指定密钥)
|
||||||
int type = commandType!.typeValue;
|
commandList.add(commandType!.identifierValue);
|
||||||
if(type == 0x3090){
|
print("commandType!.identifierValue:${commandType!.identifierValue}");
|
||||||
// 不加密
|
|
||||||
identifier = 0x20;
|
|
||||||
}else if(type == 0x3091){
|
|
||||||
// 不加密
|
|
||||||
identifier = 0x22;
|
|
||||||
}
|
|
||||||
commandList.add(identifier);
|
|
||||||
// print("identifier:$identifier");
|
|
||||||
|
|
||||||
// 数据长度
|
// 数据长度
|
||||||
int dataLen = dataSourceLength();
|
int dataLen = dataSourceLength();
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
//TODO:发送指令类型
|
//TODO:发送指令类型
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
enum CommandType {
|
enum CommandType {
|
||||||
addUser, //增加用户 = 0x3001
|
addUser, //增加用户 = 0x3001
|
||||||
deletUser , //删除用户 = 0x3002
|
deletUser , //删除用户 = 0x3002
|
||||||
@ -164,6 +166,22 @@ extension ExtensionCommandType on CommandType {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get identifierValue {
|
||||||
|
int type = 0x23;
|
||||||
|
switch(this){
|
||||||
|
case CommandType.getLockPublicKey:
|
||||||
|
type = 0x20;
|
||||||
|
break;
|
||||||
|
case CommandType.getLockPrivateKey:
|
||||||
|
type = 0x22;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type = 0x23;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
String get typeName {
|
String get typeName {
|
||||||
String t = '';
|
String t = '';
|
||||||
switch(typeValue){
|
switch(typeValue){
|
||||||
|
|||||||
@ -3,6 +3,11 @@ enum DataTransmissionMode {
|
|||||||
ble,
|
ble,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const saveBluePublicKey = "BluePublicKey";
|
||||||
|
const saveBluePrivateKey = "BluePrivateKey";
|
||||||
|
const saveBlueSignKey = "BlueSignKey";
|
||||||
|
const saveBlueToken = "BlueToken";
|
||||||
|
|
||||||
class IoManager {
|
class IoManager {
|
||||||
|
|
||||||
static IoManager? _ioManager;
|
static IoManager? _ioManager;
|
||||||
@ -21,18 +26,20 @@ class IoManager {
|
|||||||
///蓝牙传输协议
|
///蓝牙传输协议
|
||||||
void bleTransmission() => _dataTransmissionMode = DataTransmissionMode.ble;
|
void bleTransmission() => _dataTransmissionMode = DataTransmissionMode.ble;
|
||||||
|
|
||||||
int _commandIndex = 1; //割草机协议帧序号
|
///割草机协议帧序号
|
||||||
|
int _commandIndex = 1;
|
||||||
configCommandIdx(int idx) => _commandIndex = idx;
|
configCommandIdx(int idx) => _commandIndex = idx;
|
||||||
Future<void> increaseCommandIndex() async {
|
Future<void> increaseCommandIndex() async {
|
||||||
_commandIndex < 255 ? _commandIndex++ : _commandIndex = 0;
|
_commandIndex < 255 ? _commandIndex++ : _commandIndex = 0;
|
||||||
}
|
}
|
||||||
|
void resetCommandIndex() => _commandIndex = 0;
|
||||||
void resetCommandIndex(){
|
|
||||||
_commandIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get commandIndex => _commandIndex;
|
int get commandIndex => _commandIndex;
|
||||||
|
|
||||||
|
/// 当前设备连接的lockId
|
||||||
|
String _currentDeviceLockId = "";
|
||||||
|
configCurrentDeviceLockId(String lockId) => _currentDeviceLockId = lockId;
|
||||||
|
String get getCurrentDeviceLockId => _currentDeviceLockId;
|
||||||
|
|
||||||
void resetAllFlags() {
|
void resetAllFlags() {
|
||||||
resetCommandIndex();
|
resetCommandIndex();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,28 +4,44 @@ import 'dart:typed_data';
|
|||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:encrypt/encrypt.dart' as ddd;
|
import 'package:encrypt/encrypt.dart' as ddd;
|
||||||
// import 'package:sm_crypto/sm_crypto.dart';
|
|
||||||
|
|
||||||
// String getSM4Str(List<int>data, String key) {
|
List<String> changeIntListToStringList(List<int> list){
|
||||||
// String dataStr = radixString(data);
|
List<String> strList = [];
|
||||||
// String iv = SM4.createHexKey(key: key);
|
for(int i = 0; i<list.length; i++)
|
||||||
|
{
|
||||||
|
strList.add(list[i].toRadixString(16));
|
||||||
|
}
|
||||||
|
return strList;
|
||||||
|
}
|
||||||
|
|
||||||
// String cbcEncryptData = SM4.encrypt(
|
List<int> changeStringListToIntList(List<String> list){
|
||||||
// data: dataStr,
|
List<int> intList = [];
|
||||||
// key: iv,
|
for(int i = 0; i<list.length; i++)
|
||||||
// mode: SM4CryptoMode.ECB,
|
{
|
||||||
// iv: iv,
|
intList.add(_hexToInt(list[i]));
|
||||||
// );
|
}
|
||||||
|
return intList;
|
||||||
|
}
|
||||||
|
|
||||||
// print("getDNSAPIStrData:$data \ngetDNSAPIStrkey:$key \ngetDNSAPIStrDataStr:$dataStr \niv:$iv\ncbcEncryptData:$cbcEncryptData");
|
int _hexToInt(String hex) {
|
||||||
// return cbcEncryptData;
|
int val = 0;
|
||||||
|
int len = hex.length;
|
||||||
// // final iv = ddd.IV.fromLength(32);
|
for (int i = 0; i < len; i++) {
|
||||||
// // final encrypter = ddd.Encrypter(ddd.AES(ddd.Key.fromUtf8(key), mode: ddd.AESMode.ecb, padding: 'PKCS7'));
|
int hexDigit = hex.codeUnitAt(i);
|
||||||
// // final encrypted = encrypter.encrypt(key, iv: iv);
|
if (hexDigit >= 48 && hexDigit <= 57) {
|
||||||
// //
|
val += (hexDigit - 48) * (1 << (4 * (len - 1 - i)));
|
||||||
// // return encrypted;
|
} else if (hexDigit >= 65 && hexDigit <= 70) {
|
||||||
// }
|
// A..F
|
||||||
|
val += (hexDigit - 55) * (1 << (4 * (len - 1 - i)));
|
||||||
|
} else if (hexDigit >= 97 && hexDigit <= 102) {
|
||||||
|
// a..f
|
||||||
|
val += (hexDigit - 87) * (1 << (4 * (len - 1 - i)));
|
||||||
|
} else {
|
||||||
|
throw new FormatException("Invalid hexadecimal value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
String md5Crypto(List<int> data) {
|
String md5Crypto(List<int> data) {
|
||||||
final dig = md5.convert(data);
|
final dig = md5.convert(data);
|
||||||
@ -238,7 +254,7 @@ List<List<T>> splitList<T>(List<T> list, int len) {
|
|||||||
//TODO:int->两个字节 List 高字节在前,低字节在后(小端存储) 本工程只有配置 WiFi用到的!!!!
|
//TODO:int->两个字节 List 高字节在前,低字节在后(小端存储) 本工程只有配置 WiFi用到的!!!!
|
||||||
List<int> intToByte2ListLow(int value) => [value >> 8, value];
|
List<int> intToByte2ListLow(int value) => [value >> 8, value];
|
||||||
|
|
||||||
String radixString(List<int> codeUnits) {
|
String radixHex16String(List<int> codeUnits) {
|
||||||
String result = '';
|
String result = '';
|
||||||
codeUnits.forEach((value) {
|
codeUnits.forEach((value) {
|
||||||
result += value.toRadixString(16).padLeft(2, '0');
|
result += value.toRadixString(16).padLeft(2, '0');
|
||||||
|
|||||||
@ -1,18 +1,22 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../tools/storage.dart';
|
||||||
import 'io_protocol/io_addUser.dart';
|
import 'io_protocol/io_addUser.dart';
|
||||||
import 'io_protocol/io_getPrivateKey.dart';
|
import 'io_protocol/io_getPrivateKey.dart';
|
||||||
import 'io_protocol/io_getPublicKey.dart';
|
import 'io_protocol/io_getPublicKey.dart';
|
||||||
import 'io_protocol/io_openDoor.dart';
|
import 'io_protocol/io_openDoor.dart';
|
||||||
import 'io_protocol/io_reply.dart';
|
import 'io_protocol/io_reply.dart';
|
||||||
import 'io_protocol/io_type.dart';
|
import 'io_protocol/io_type.dart';
|
||||||
|
import 'io_tool/io_manager.dart';
|
||||||
import 'io_tool/io_tool.dart';
|
import 'io_tool/io_tool.dart';
|
||||||
import 'io_tool/manager_event_bus.dart';
|
import 'io_tool/manager_event_bus.dart';
|
||||||
import 'sm4Encipher/sm4.dart';
|
import 'sm4Encipher/sm4.dart';
|
||||||
|
|
||||||
class CommandReciverManager {
|
class CommandReciverManager {
|
||||||
|
|
||||||
static void appDataReceive(List<int> data, String lockId) async {
|
static void appDataReceive(List<int> data) async {
|
||||||
///解析数据
|
///解析数据
|
||||||
if(data.isEmpty){
|
if(data.isEmpty){
|
||||||
return;
|
return;
|
||||||
@ -22,7 +26,7 @@ class CommandReciverManager {
|
|||||||
if(data_size < 13){
|
if(data_size < 13){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
print("appDataReceiveData:$data");
|
// print("appDataReceiveData:$data");
|
||||||
if((data[0] == 0xEF)&&(data[1] == 0x01)&&(data[2] == 0xEE)&&(data[3] == 0x02)&&(data[4] == 0x11)){
|
if((data[0] == 0xEF)&&(data[1] == 0x01)&&(data[2] == 0xEE)&&(data[3] == 0x02)&&(data[4] == 0x11)){
|
||||||
var tmpType = (data[7] & 0x0f);// 包标识
|
var tmpType = (data[7] & 0x0f);// 包标识
|
||||||
print("temType:$tmpType");
|
print("temType:$tmpType");
|
||||||
@ -36,33 +40,36 @@ class CommandReciverManager {
|
|||||||
// for (var i = 0; i < oriLen ; i++) {
|
// for (var i = 0; i < oriLen ; i++) {
|
||||||
// oriDataList.add(data[12 + i]);
|
// oriDataList.add(data[12 + i]);
|
||||||
// }
|
// }
|
||||||
oriDataList = data.sublist(12, 12 + oriLen);
|
oriDataList = data.sublist(12, 12 + dataLen);
|
||||||
print("不加密 oriDataList:$oriDataList");
|
print("不加密 oriDataList:$oriDataList");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
//AES128
|
//AES128
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
//SM4(事先约定密钥)
|
// SM4(事先约定密钥)
|
||||||
String key = SM4.createHexKey(key: 'TMH_c3570480da8d');
|
// 获取的加密数组
|
||||||
oriDataList = SM4.decrypt(data, key: key, mode: SM4CryptoMode.ECB);
|
var getDataList = data.sublist(12, 12 + dataLen);
|
||||||
|
|
||||||
|
// 解密
|
||||||
|
// String key = SM4.createHexKey(key: IoManager().getCurrentDeviceLockId);
|
||||||
|
oriDataList = SM4.decrypt(getDataList, key: utf8.encode(IoManager().getCurrentDeviceLockId), mode: SM4CryptoMode.ECB);
|
||||||
|
oriDataList = oriDataList.sublist(0, oriLen);
|
||||||
print("SM4 oriDataList:$oriDataList");
|
print("SM4 oriDataList:$oriDataList");
|
||||||
break;
|
break;
|
||||||
case 3: //SM4(设备指定密钥)
|
case 3:
|
||||||
// for (var i = 0; i < dataLen ; i++) {
|
//SM4(设备指定密钥)
|
||||||
// dataView[i] = uint8Recv[12 + i];
|
// 获取的加密数组
|
||||||
// }
|
var getDataList = data.sublist(12, 12 + dataLen);
|
||||||
// console.log("dataView.length = ", dataView.length);
|
|
||||||
// console.log("currCommStru.pairCommKey = ", currCommStru.pairCommKey);
|
var res = await Storage.getStringList(saveBluePrivateKey);
|
||||||
// var commKey1 = base64js.toByteArray(currCommStru.pairCommKey);
|
List<int> getPrivateKeyList = changeStringListToIntList(res!);
|
||||||
// console.log("commKey1 = ", commKey1);
|
|
||||||
// var d_cbc = cbc.decrypt_ecb(dataView, commKey1, false, "nobase64");
|
// 解密
|
||||||
// console.log("d_cbc = ", d_cbc);
|
// String key = SM4.createHexKey(key: radixHex16String(getPrivateKeyList!));
|
||||||
// console.log("oriLen = ", oriLen);
|
oriDataList = SM4.decrypt(getDataList, key: getPrivateKeyList, mode: SM4CryptoMode.ECB);
|
||||||
// for (var i = 0; i < oriLen ; i++) {
|
oriDataList = oriDataList.sublist(0, oriLen);
|
||||||
// oriDataView[i] = d_cbc[i];
|
print("SM4 oriDataList:$oriDataList");
|
||||||
// }
|
|
||||||
// console.log("oriDataView = ", oriDataView);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -77,6 +84,7 @@ class CommandReciverManager {
|
|||||||
if(data.isNotEmpty){
|
if(data.isNotEmpty){
|
||||||
var cmd = data[0] * 256 + data[1];
|
var cmd = data[0] * 256 + data[1];
|
||||||
CommandType commandType = ExtensionCommandType.getCommandType(cmd);
|
CommandType commandType = ExtensionCommandType.getCommandType(cmd);
|
||||||
|
await IoManager().increaseCommandIndex();
|
||||||
// data.removeRange(0, 2);
|
// data.removeRange(0, 2);
|
||||||
print("111111data cmd:$cmd commandType:$commandType data:$data");
|
print("111111data cmd:$cmd commandType:$commandType data:$data");
|
||||||
var reply;
|
var reply;
|
||||||
|
|||||||
@ -24,9 +24,9 @@ class CommandSenderManager {
|
|||||||
bool canSendControlCommand = false;
|
bool canSendControlCommand = false;
|
||||||
|
|
||||||
//TODO:发送常规数据
|
//TODO:发送常规数据
|
||||||
void managerSendData ({
|
Future<void> managerSendData ({
|
||||||
required SenderProtocol command,
|
required SenderProtocol command,
|
||||||
CommandSendCallBack? callBack}) {
|
CommandSendCallBack? callBack}) async {
|
||||||
if (callBack != null) {
|
if (callBack != null) {
|
||||||
// if (!BluetoothManager().connected) {
|
// if (!BluetoothManager().connected) {
|
||||||
print('❌ 蓝牙断开了');
|
print('❌ 蓝牙断开了');
|
||||||
@ -38,7 +38,7 @@ class CommandSenderManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<int> value = command.packageData();
|
List<int> value = await command.packageData();
|
||||||
// print("sendData:${value}");
|
// print("sendData:${value}");
|
||||||
_sendNormalData(value);
|
_sendNormalData(value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,50 +8,66 @@ import 'sender_data.dart';
|
|||||||
class IoSenderManage {
|
class IoSenderManage {
|
||||||
|
|
||||||
//todo:获取公钥
|
//todo:获取公钥
|
||||||
static void getPublicKey(String lockId ,{CommandSendCallBack? callBack}) {
|
static void getPublicKey({String? lockId ,CommandSendCallBack? callBack}) {
|
||||||
CommandSenderManager().managerSendData(command: GetPublicKeyCommand(
|
CommandSenderManager().managerSendData(command: GetPublicKeyCommand(
|
||||||
lockID: lockId,
|
lockID: lockId,
|
||||||
), callBack:callBack);
|
), callBack:callBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo:获取私钥
|
//todo:获取私钥
|
||||||
static void getPrivateKey(
|
static void getPrivateKey({
|
||||||
String? lockId,
|
String? lockId,
|
||||||
String? keyID, // 钥匙ID
|
String? keyID, // 钥匙ID
|
||||||
String? authUserID,// 钥匙授权人ID
|
String? authUserID,// 钥匙授权人ID
|
||||||
int? nowTime,
|
int? nowTime,
|
||||||
List<int>? publicKeyData,
|
List<int>? publicKeyData,
|
||||||
int? needAuthor, {CommandSendCallBack? callBack}) {
|
int? needAuthor,
|
||||||
|
CommandSendCallBack? callBack}) {
|
||||||
CommandSenderManager().managerSendData(command: GetPrivateKeyCommand(
|
CommandSenderManager().managerSendData(command: GetPrivateKeyCommand(
|
||||||
lockID: lockId,
|
lockID: lockId,
|
||||||
keyID: keyID,
|
keyID: keyID,
|
||||||
authUserID: authUserID,
|
authUserID: authUserID,
|
||||||
nowTime: nowTime,
|
nowTime: nowTime,
|
||||||
publicKeyData:publicKeyData,
|
publicKeyData:publicKeyData,
|
||||||
needAuthor: needAuthor,
|
needAuthor: needAuthor,
|
||||||
), callBack:callBack);
|
), callBack:callBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo:添加用户
|
//todo:添加用户
|
||||||
// static void senderAddUser({CommandSendCallBack? callBack}) {
|
static void senderAddUser({
|
||||||
// CommandSenderManager().managerSendData(
|
String? lockID,
|
||||||
// command: AddUserCommand(
|
String? authUserID,
|
||||||
// cmdID: 0,
|
String? keyID,
|
||||||
// lockID: "",
|
String? userID,
|
||||||
// authUserID: "",
|
int? openMode,
|
||||||
// keyID: "",
|
int? keyType,
|
||||||
// userID: "",
|
int? startDate,
|
||||||
// openMode: 0,
|
int? expireDate,
|
||||||
// keyType: 0,
|
int? role,
|
||||||
// startDate: 0,
|
String? password,
|
||||||
// expireDate: 0,
|
int? needAuthor,
|
||||||
// role: 0,
|
List<int>? publicKey,
|
||||||
// password: "",
|
List<int>? privateKey,
|
||||||
// token: 0,
|
List<int>? token,
|
||||||
// authCodeLen: 0,
|
CommandSendCallBack? callBack}) {
|
||||||
// authCode: "",
|
CommandSenderManager().managerSendData(
|
||||||
// ), callBack:callBack);
|
command: AddUserCommand(
|
||||||
// }
|
lockID: lockID,
|
||||||
|
authUserID: authUserID,
|
||||||
|
keyID: keyID,
|
||||||
|
userID: userID,
|
||||||
|
openMode: openMode,
|
||||||
|
keyType: keyType,
|
||||||
|
startDate: startDate,
|
||||||
|
expireDate: expireDate,
|
||||||
|
role: role,
|
||||||
|
password: password,
|
||||||
|
needAuthor: needAuthor,
|
||||||
|
publicKey: publicKey,
|
||||||
|
privateKey: privateKey,
|
||||||
|
token: token
|
||||||
|
), callBack:callBack);
|
||||||
|
}
|
||||||
|
|
||||||
//todo:开锁
|
//todo:开锁
|
||||||
// static void senderOpenDoor({CommandSendCallBack? callBack}) {
|
// static void senderOpenDoor({CommandSendCallBack? callBack}) {
|
||||||
|
|||||||
@ -359,8 +359,8 @@ class SM4 {
|
|||||||
return roundKey;
|
return roundKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setKey(String key) {
|
static void setKey(List<int> key) {
|
||||||
List<int> keyBytes = SMUtils.hexStringToBytes(key);
|
List<int> keyBytes = key;
|
||||||
List<int> intermediateKeys = List<int>.filled(36, 0);
|
List<int> intermediateKeys = List<int>.filled(36, 0);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
intermediateKeys[i] = _readUint32BE(keyBytes, i * 4) ^ FK[i];
|
intermediateKeys[i] = _readUint32BE(keyBytes, i * 4) ^ FK[i];
|
||||||
@ -411,9 +411,11 @@ class SM4 {
|
|||||||
}
|
}
|
||||||
return paddedList;
|
return paddedList;
|
||||||
} else {
|
} else {
|
||||||
final lastByte = input.last;
|
// final lastByte = input.last;
|
||||||
final cutLen = input.length - lastByte;
|
// final cutLen = input.length - lastByte;
|
||||||
return input.sublist(0, cutLen);
|
// print("object input.length:${input.length} lastByte:$lastByte input:$input cutLen:$cutLen");
|
||||||
|
// return input.sublist(0, cutLen);
|
||||||
|
return input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,7 +520,7 @@ class SM4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static List<int> encrypt(List<int> data,
|
static List<int> encrypt(List<int> data,
|
||||||
{String? key, SM4CryptoMode mode = SM4CryptoMode.ECB, String? iv}) {
|
{List<int>? key, SM4CryptoMode mode = SM4CryptoMode.ECB, String? iv}) {
|
||||||
if (key != null) setKey(key);
|
if (key != null) setKey(key);
|
||||||
List<int> input = data;
|
List<int> input = data;
|
||||||
List<int> output = _crypto(input, SM4_ENCRYPT, mode, iv);
|
List<int> output = _crypto(input, SM4_ENCRYPT, mode, iv);
|
||||||
@ -534,7 +536,7 @@ class SM4 {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
static decrypt(List<int> data,
|
static decrypt(List<int> data,
|
||||||
{String? key, SM4CryptoMode mode = SM4CryptoMode.ECB, String? iv}) {
|
{List<int>? key, SM4CryptoMode mode = SM4CryptoMode.ECB, String? iv}) {
|
||||||
if (key != null) setKey(key);
|
if (key != null) setKey(key);
|
||||||
List<int> input = data;
|
List<int> input = data;
|
||||||
List<int> output = _crypto(input, SM4_DECRYPT, mode, iv);
|
List<int> output = _crypto(input, SM4_DECRYPT, mode, iv);
|
||||||
|
|||||||
@ -2,12 +2,20 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
import 'package:flutter_reactive_ble/flutter_reactive_ble.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 'package:star_lock/tools/baseGetXController.dart';
|
||||||
|
|
||||||
import '../../../blue/blue_manage.dart';
|
import '../../../blue/blue_manage.dart';
|
||||||
|
import '../../../blue/io_protocol/io_addUser.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_model.dart';
|
||||||
|
import '../../../blue/io_tool/io_tool.dart';
|
||||||
import '../../../blue/io_tool/manager_event_bus.dart';
|
import '../../../blue/io_tool/manager_event_bus.dart';
|
||||||
import '../../../blue/sender_manage.dart';
|
import '../../../blue/sender_manage.dart';
|
||||||
|
import '../../../tools/storage.dart';
|
||||||
import 'nearbyLock_state.dart';
|
import 'nearbyLock_state.dart';
|
||||||
|
|
||||||
class NearbyLockLogic extends BaseGetXController{
|
class NearbyLockLogic extends BaseGetXController{
|
||||||
@ -15,26 +23,18 @@ class NearbyLockLogic extends BaseGetXController{
|
|||||||
final NearbyLockState state = NearbyLockState();
|
final NearbyLockState state = NearbyLockState();
|
||||||
|
|
||||||
// 点击复合要求的设备之后 连接
|
// 点击复合要求的设备之后 连接
|
||||||
void connect(String lockId){
|
void connect(String lockId, String deviceName){
|
||||||
BlueManage().connect(lockId);
|
BlueManage().connect(lockId, deviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听蓝牙连接的状态
|
// 监听蓝牙连接的状态
|
||||||
late StreamSubscription _streamSubscription;
|
late StreamSubscription _streamSubscription;
|
||||||
void _startListenIO(){
|
void _startListenIO(){
|
||||||
_streamSubscription = EventBusManager().eventBus!.on<QualifiedCharacteristic>().listen((event) async {
|
_streamSubscription = EventBusManager().eventBus!.on<QualifiedCharacteristic>().listen((event) async {
|
||||||
IoSenderManage.getPublicKey(state.seletLockName.value);
|
IoSenderManage.getPublicKey(lockId:state.seletLockName.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 状态在线之后发现服务
|
|
||||||
// Future<void> scanDiscoverServices(String lockId) async {
|
|
||||||
// // 获取特征值 处理特征值
|
|
||||||
// List<DiscoveredService> list = await BlueManage().discoverServices(lockId);
|
|
||||||
// // 发送获取公钥
|
|
||||||
// IoSenderManage.getPublicKey(state.seletLockName.value);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 获取公钥
|
// 获取公钥
|
||||||
// void getPublicKey(String lockId){
|
// void getPublicKey(String lockId){
|
||||||
// // print("seletGetPublicKey:${lockId}");
|
// // print("seletGetPublicKey:${lockId}");
|
||||||
@ -57,6 +57,146 @@ class NearbyLockLogic extends BaseGetXController{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
late StreamSubscription<Reply> _replySubscription;
|
||||||
|
void _initReplySubscription() {
|
||||||
|
_replySubscription = EventBusManager().eventBus!.on<Reply>().listen((reply) {
|
||||||
|
if(reply is GetPublicKeyReply) {
|
||||||
|
_replyGetPublicKey(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(reply is GetPrivateKeyReply) {
|
||||||
|
_replyGetPrivateKeyKey(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(reply is AddUserReply) {
|
||||||
|
_replyAddUserKey(reply);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _replyGetPublicKey(Reply reply){
|
||||||
|
// 获取公钥
|
||||||
|
switch(reply.status){
|
||||||
|
case 0x00:
|
||||||
|
//成功
|
||||||
|
// 储存公钥
|
||||||
|
var tokenData = reply.data.sublist(3);
|
||||||
|
var saveStrList = changeIntListToStringList(tokenData);
|
||||||
|
Storage.setStringList(saveBluePublicKey, saveStrList);
|
||||||
|
IoSenderManage.getPrivateKey(
|
||||||
|
lockId:IoManager().getCurrentDeviceLockId,
|
||||||
|
keyID:"1",
|
||||||
|
authUserID:"1",
|
||||||
|
nowTime:1,
|
||||||
|
publicKeyData:tokenData,
|
||||||
|
needAuthor:1);
|
||||||
|
break;
|
||||||
|
case 0x07:
|
||||||
|
//无权限
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0x0f:
|
||||||
|
//用户已存在
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//失败
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _replyGetPrivateKeyKey(Reply reply){
|
||||||
|
switch(reply.status){
|
||||||
|
case 0x00:
|
||||||
|
//成功
|
||||||
|
print('获取私钥成功');
|
||||||
|
reply.data.removeAt(0);
|
||||||
|
|
||||||
|
// 私钥
|
||||||
|
List<int> privateKey = reply.data.sublist(0, 16);
|
||||||
|
var savePrivateKeyList = changeIntListToStringList(privateKey);
|
||||||
|
Storage.setStringList(saveBluePrivateKey, savePrivateKeyList);
|
||||||
|
|
||||||
|
// signKey
|
||||||
|
List<int> signKey = reply.data.sublist(16);
|
||||||
|
var savesignKeyList = changeIntListToStringList(signKey);
|
||||||
|
Storage.setStringList(saveBlueSignKey, savesignKeyList);
|
||||||
|
|
||||||
|
print("privateKey:$privateKey signKey:$signKey");
|
||||||
|
IoSenderManage.senderAddUser(
|
||||||
|
lockID:IoManager().getCurrentDeviceLockId,
|
||||||
|
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: [0,0,0,0]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 0x07:
|
||||||
|
//无权限
|
||||||
|
print('获取私钥无权限');
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0x0f:
|
||||||
|
//用户已存在
|
||||||
|
print('获取私钥:用户已存在');
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//失败
|
||||||
|
print('获取私钥失败');
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _replyAddUserKey(Reply reply){
|
||||||
|
var lockId = reply.data.sublist(2, 42);
|
||||||
|
print("lockId:$lockId");
|
||||||
|
var token = reply.data.sublist(42, 46);
|
||||||
|
List<String> strTokenList = changeIntListToStringList(token);
|
||||||
|
Storage.setStringList(saveBlueToken, strTokenList);
|
||||||
|
print("token:$token");
|
||||||
|
int status = reply.data[46];
|
||||||
|
print("status:$status");
|
||||||
|
switch(status){
|
||||||
|
case 0x00:
|
||||||
|
//成功
|
||||||
|
print("添加用户数据解析成功");
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0x06:
|
||||||
|
//无权限
|
||||||
|
print("需要鉴权");
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0x07:
|
||||||
|
//无权限
|
||||||
|
print("用户无权限");
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0x09:
|
||||||
|
// 权限校验错误
|
||||||
|
print("权限校验错误");
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//失败
|
||||||
|
print("领锁失败");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onReady() {
|
void onReady() {
|
||||||
// TODO: implement onReady
|
// TODO: implement onReady
|
||||||
@ -65,6 +205,7 @@ class NearbyLockLogic extends BaseGetXController{
|
|||||||
|
|
||||||
_startListenIO();
|
_startListenIO();
|
||||||
_initSendStreamSubscription();
|
_initSendStreamSubscription();
|
||||||
|
_initReplySubscription();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -75,10 +216,8 @@ class NearbyLockLogic extends BaseGetXController{
|
|||||||
|
|
||||||
// 进来第一步开始扫描
|
// 进来第一步开始扫描
|
||||||
BlueManage().startScan((v){
|
BlueManage().startScan((v){
|
||||||
bool isHave = state.devices.any((element) => element.id == v[0].id);
|
state.devices.clear();
|
||||||
if (isHave == false){
|
state.devices.addAll(v);
|
||||||
state.devices.addAll(v);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +227,7 @@ class NearbyLockLogic extends BaseGetXController{
|
|||||||
super.onClose();
|
super.onClose();
|
||||||
_streamSubscription.cancel();
|
_streamSubscription.cancel();
|
||||||
_sendStreamSubscription.cancel();
|
_sendStreamSubscription.cancel();
|
||||||
|
_replySubscription.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ class _NearbyLockPageState extends State<NearbyLockPage> {
|
|||||||
// Navigator.pushNamed(context, Routers.lockAddressPage);
|
// Navigator.pushNamed(context, Routers.lockAddressPage);
|
||||||
// logic.getPublicKey(state.devices[index].serviceUuids[0].toString());
|
// logic.getPublicKey(state.devices[index].serviceUuids[0].toString());
|
||||||
state.seletLockName.value = state.devices[index].name;
|
state.seletLockName.value = state.devices[index].name;
|
||||||
logic.connect(state.devices[index].id);
|
logic.connect(state.devices[index].id, state.devices[index].name);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
separatorBuilder: (BuildContext context, int index) {
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
|
|||||||
@ -6,6 +6,6 @@ import 'package:get/get.dart';
|
|||||||
|
|
||||||
class NearbyLockState {
|
class NearbyLockState {
|
||||||
|
|
||||||
var devices = <DiscoveredDevice>[].obs;
|
RxList<DiscoveredDevice> devices = <DiscoveredDevice>[].obs;
|
||||||
var seletLockName = "".obs;
|
var seletLockName = "".obs;
|
||||||
}
|
}
|
||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@ -8,47 +7,44 @@ import '../../login/login/entity/LoginEntity.dart';
|
|||||||
import '../../tools/storage.dart';
|
import '../../tools/storage.dart';
|
||||||
|
|
||||||
class StarLockMineState {
|
class StarLockMineState {
|
||||||
|
|
||||||
final loginData = LoginEntity().obs;
|
final loginData = LoginEntity().obs;
|
||||||
|
|
||||||
///本地存储 登录信息
|
///本地存储 登录信息
|
||||||
void saveLoginData(LoginEntity data) async {
|
void saveLoginData(LoginEntity data) async {
|
||||||
print("saveLoginData:${data.data!.mobile}");
|
print("saveLoginData:${data.data!.mobile}");
|
||||||
await Storage.setData('userLoginData',jsonEncode(data));
|
await Storage.setString('userLoginData', jsonEncode(data));
|
||||||
loginData.value=data;
|
loginData.value = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
///初始化本地数据
|
///初始化本地数据
|
||||||
void initLoginData() async {
|
void initLoginData() async {
|
||||||
final data = await Storage.getData<String>('userLoginData');
|
final data = await Storage.getString('userLoginData');
|
||||||
print("getLoginData:$data");
|
print("getLoginData:$data");
|
||||||
if(data != null && data.isNotEmpty){
|
if (data != null && data.isNotEmpty) {
|
||||||
loginData.value = LoginEntity.fromJson(jsonDecode(data));
|
loginData.value = LoginEntity.fromJson(jsonDecode(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///退出登录
|
///退出登录
|
||||||
void logOut() async {
|
void logOut() async {
|
||||||
await Storage.setData('userLoginData','');
|
await Storage.setString('userLoginData', '');
|
||||||
loginData.value = LoginEntity();
|
loginData.value = LoginEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
///用户登录token
|
///用户登录token
|
||||||
String token(){
|
String token() {
|
||||||
return loginData.value.data?.accessToken??'';
|
return loginData.value.data?.accessToken ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
String mobile(){
|
String mobile() {
|
||||||
return loginData.value.data?.mobile??'-';
|
return loginData.value.data?.mobile ?? '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
///用户头像
|
///用户头像
|
||||||
String headUrl(){
|
String headUrl() {
|
||||||
return loginData.value.data!.headUrl??'';
|
return loginData.value.data!.headUrl ?? '';
|
||||||
// return "https://img2.woyaogexing.com/2022/04/14/156cdbabd5bc496abee2cd0fca527434!400x400.jpeg";
|
// return "https://img2.woyaogexing.com/2022/04/14/156cdbabd5bc496abee2cd0fca527434!400x400.jpeg";
|
||||||
}
|
}
|
||||||
|
|
||||||
void onClose() {
|
void onClose() {}
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ FutureOr<Request> requestInterceptor(Request request) async {
|
|||||||
// request.headers['token'] = StoreService.to.userToken!;
|
// request.headers['token'] = StoreService.to.userToken!;
|
||||||
// print("11111${StoreService.to.userToken}");
|
// print("11111${StoreService.to.userToken}");
|
||||||
String? xToken = '';
|
String? xToken = '';
|
||||||
final data = await Storage.getData<String>('userLoginData');
|
final data = await Storage.getString('userLoginData');
|
||||||
if (data != null && data.isNotEmpty) {
|
if (data != null && data.isNotEmpty) {
|
||||||
xToken = LoginEntity.fromJson(jsonDecode(data)).data!.accessToken;
|
xToken = LoginEntity.fromJson(jsonDecode(data)).data!.accessToken;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,34 +3,114 @@
|
|||||||
* */
|
* */
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class Storage{
|
class Storage {
|
||||||
///存数据
|
// Storage._internal();
|
||||||
static Future<void> setData(key, value) async {
|
//
|
||||||
|
// factory Storage() => _instance;
|
||||||
|
//
|
||||||
|
// static late final Storage _instance = Storage._internal();
|
||||||
|
//
|
||||||
|
// static late SharedPreferences _preferences;
|
||||||
|
//
|
||||||
|
// static Future<Storage> getInstance() async {
|
||||||
|
// _preferences = await SharedPreferences.getInstance();
|
||||||
|
// return _instance;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ///存数据
|
||||||
|
// static Future<void> setData(key, value) async {
|
||||||
|
// SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
// if (value is int) {
|
||||||
|
// await sp.setInt(key, value);
|
||||||
|
// } else if (value is bool) {
|
||||||
|
// await sp.setBool(key, value);
|
||||||
|
// } else if (value is double) {
|
||||||
|
// await sp.setDouble(key, value);
|
||||||
|
// } else if (value is String) {
|
||||||
|
// await sp.setString(key, value);
|
||||||
|
// } else if (value is List<String>) {
|
||||||
|
// await sp.setStringList(key, value);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ///取数据
|
||||||
|
// ///
|
||||||
|
// static Future<T?> getData<T>(key) async {
|
||||||
|
// SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
// switch(T){
|
||||||
|
// case int: return (sp.getInt(key) ?? 0) as T;
|
||||||
|
// case bool: return (sp.getBool(key) ?? false) as T;
|
||||||
|
// case double: return (sp.getDouble(key) ?? 0.0) as T;
|
||||||
|
// case String: return (sp.getString(key) ?? '') as T;
|
||||||
|
// case List: return (sp.getStringList(key) ?? []) as T;
|
||||||
|
// default: return null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int
|
||||||
|
static Future<void> setInt(key, value) async {
|
||||||
SharedPreferences sp = await SharedPreferences.getInstance();
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
if (value is int) {
|
sp.setInt(key, value);
|
||||||
await sp.setInt(key, value);
|
|
||||||
} else if (value is bool) {
|
|
||||||
await sp.setBool(key, value);
|
|
||||||
} else if (value is double) {
|
|
||||||
await sp.setDouble(key, value);
|
|
||||||
} else if (value is String) {
|
|
||||||
await sp.setString(key, value);
|
|
||||||
} else if (value is List<String>) {
|
|
||||||
await sp.setStringList(key, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///取数据
|
static Future<int?> getInt(key) async {
|
||||||
///
|
|
||||||
static Future<T?> getData<T>(key) async {
|
|
||||||
SharedPreferences sp = await SharedPreferences.getInstance();
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
switch(T){
|
return sp.getInt(key);
|
||||||
case int: return (sp.getInt(key) ?? 0) as T;
|
|
||||||
case bool: return (sp.getBool(key) ?? false) as T;
|
|
||||||
case double: return (sp.getDouble(key) ?? 0.0) as T;
|
|
||||||
case String: return (sp.getString(key) ?? '') as T;
|
|
||||||
case List: return (sp.getStringList(key) ?? []) as T;
|
|
||||||
default: return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// bool
|
||||||
|
static Future<void> setBool(key, value) async {
|
||||||
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
sp.setBool(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<bool?> getBool(key) async {
|
||||||
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
return sp.getBool(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// double
|
||||||
|
static Future<void> setDouble(key, value) async {
|
||||||
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
sp.setDouble(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<double?> getDouble(key) async {
|
||||||
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
return sp.getDouble(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// string
|
||||||
|
static Future<void> setString(key, value) async {
|
||||||
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
sp.setString(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<String?> getString(key) async {
|
||||||
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
return sp.getString(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 字符串数组
|
||||||
|
static Future<void> setStringList(key, value) async {
|
||||||
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
sp.setStringList(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<List<String>?> getStringList(key) async {
|
||||||
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
return sp.getStringList(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除数据
|
||||||
|
static Future<void> removeData(key) async {
|
||||||
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
sp.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除所有的键值对
|
||||||
|
static Future<void> clearAll() async {
|
||||||
|
SharedPreferences sp = await SharedPreferences.getInstance();
|
||||||
|
sp.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user