优化蓝牙逻辑、调试编辑用户蓝牙协议

This commit is contained in:
魏少阳 2023-08-18 16:25:41 +08:00
parent 44b6e1edf9
commit 450b721cf8
14 changed files with 354 additions and 36 deletions

View File

@ -92,7 +92,7 @@ class BlueManage{
Future<void> connect(String deviceMAC, String deviceName, {ConnectStateCallBack? connectStateCallBack, bool? isFrist = false}) async {
connectDeviceId = deviceMAC;
connectDeviceName = deviceName;
print("connectDeviceId:$connectDeviceId");
print("connectDeviceId:$connectDeviceId connectDeviceName:$connectDeviceName");
EasyLoading.show();
_flutterReactiveBle!.connectToDevice(id: connectDeviceId, connectionTimeout: const Duration(seconds: 15)).listen((connectionStateUpdate) async {
@ -100,6 +100,10 @@ class BlueManage{
deviceConnectionState = connectionStateUpdate.connectionState;
print('ConnectionState for device $deviceMAC : ${connectionStateUpdate.connectionState}');
if(connectionStateUpdate.connectionState != DeviceConnectionState.connected){
EasyLoading.dismiss();
}
if(connectionStateUpdate.connectionState == DeviceConnectionState.connected){
//
// await discoverServices(connectDeviceId, connectDeviceName);
@ -127,15 +131,17 @@ class BlueManage{
}
}
}
_subScribeToCharacteristic(QualifiedCharacteristic(characteristicId: characteristicIdSubscription, serviceId: Uuid.parse("fff0"), deviceId: deviceMAC));
print('Discovering services finished');
if(isFrist == true){
//
IoSenderManage.getPublicKey(lockId: deviceName);
}
connectStateCallBack!(connectionStateUpdate.connectionState);
}else{
EasyLoading.dismiss();
}
_subScribeToCharacteristic(QualifiedCharacteristic(characteristicId: characteristicIdSubscription, serviceId: Uuid.parse("fff0"), deviceId: deviceMAC));
print('Discovering services finished');
if(isFrist == true){
//
IoSenderManage.getPublicKey(lockId: deviceName);
}
connectStateCallBack!(connectionStateUpdate.connectionState);
} on Exception catch (e) {
EasyLoading.dismiss();
print('Error occurred when discovering services: $e');
@ -167,6 +173,7 @@ class BlueManage{
//
Future<void> judgeReconnect(String deviceMAC, String deviceName, ConnectStateCallBack? connectStateCallBack) async {
if(deviceConnectionState == DeviceConnectionState.connected){
EasyLoading.show();
connectStateCallBack!(deviceConnectionState!);
}else{
connect(deviceMAC, deviceName, connectStateCallBack: (state){

View File

@ -57,25 +57,25 @@ class AddUserCommand extends SenderProtocol {
// id 40
int lockIDLength = utf8.encode(lockID!).length;
print("${commandType!.typeValue}LockIDLength:$lockIDLength utf8.encode(lockID!)${utf8.encode(lockID!)}");
// print("${commandType!.typeValue}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!)}");
// 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!)}");
// print("${commandType!.typeValue}keyIDLength:$keyIDLength utf8.encode(keyID!)${utf8.encode(keyID!)}");
data.addAll(utf8.encode(keyID!));
data = getFixedLengthList(data, 40 - keyIDLength);
//userID useid 20
int userIDLength = utf8.encode(userID!).length;
print("${commandType!.typeValue}userIDLength:$userIDLength utf8.encode(userID!)${utf8.encode(userID!)}");
// print("${commandType!.typeValue}userIDLength:$userIDLength utf8.encode(userID!)${utf8.encode(userID!)}");
data.addAll(utf8.encode(userID!));
data = getFixedLengthList(data, 20 - userIDLength);
@ -150,7 +150,7 @@ class AddUserCommand extends SenderProtocol {
data.add(0);
}
}
print("${commandType!.typeValue} SM4Data:$data");
print("${commandType!.typeName} SM4Data:$data");
// LockId进行SM4 ECB加密 key:544d485f633335373034383064613864
ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB);
return ebcData;

View File

@ -46,19 +46,19 @@ class DeletUserCommand extends SenderProtocol {
// id 40
int lockIDLength = utf8.encode(lockID!).length;
print("${commandType!.typeValue}LockIDLength:$lockIDLength utf8.encode(lockID!)${utf8.encode(lockID!)}");
// print("${commandType!.typeValue}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}authUserIDLength:$authUserIDLength utf8.encode(authUserID!)${utf8.encode(authUserID!)}");
// print("${commandType!.typeValue}authUserIDLength:$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!)}");
// print("${commandType!.typeValue}keyIDLength:$keyIDLength utf8.encode(keyID!)${utf8.encode(keyID!)}");
data.addAll(utf8.encode(keyID!));
data = getFixedLengthList(data, 40 - keyIDLength);
@ -79,7 +79,7 @@ class DeletUserCommand extends SenderProtocol {
authCodeData.addAll(publicKey!);
print("${commandType!.typeValue}-authCodeData:$authCodeData");
// print("${commandType!.typeValue}-authCodeData:$authCodeData");
// KeyIDauthUserIDmd5加密之后就是authCode
var authCode = crypto.md5.convert(authCodeData);
@ -94,7 +94,7 @@ class DeletUserCommand extends SenderProtocol {
data.add(0);
}
}
print("${commandType!.typeValue} SM4Data:$data");
print("${commandType!.typeName} SM4Data:$data");
// LockId进行SM4 ECB加密 key:544d485f633335373034383064613864
ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB);
return ebcData;

View File

@ -0,0 +1,166 @@
//TODO:
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;
class EditUserCommand extends SenderProtocol {
String? lockID;
String? authUserID;
String? keyID;
String? userID;
int? openMode;
int? keyType;
int? startDate;
int? expireDate;
int? role;
String? password;
int? needAuthor;
List<int>? publicKey;
List<int>? privateKey;
List<int>? token;
EditUserCommand({
this.lockID,
this.authUserID,
this.keyID,
this.userID,
this.openMode,
this.keyType,
this.startDate,
this.expireDate,
this.role,
this.password,
this.needAuthor,
this.publicKey,
this.privateKey,
this.token
}) : super(CommandType.editUser);
@override
List<int> messageDetail() {
List<int> data = [];
List<int> ebcData = [];
//
int type = commandType!.typeValue;
double typeDouble = type / 256;
int type1 = typeDouble.toInt();
int type2 = type % 256;
data.add(type1);
data.add(type2);
// id 40
int lockIDLength = utf8.encode(lockID!).length;
// print("${commandType!.typeValue}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);
//userID useid 20
int userIDLength = utf8.encode(userID!).length;
// print("${commandType!.typeValue}userIDLength:$userIDLength utf8.encode(userID!)${utf8.encode(userID!)}");
data.addAll(utf8.encode(userID!));
data = getFixedLengthList(data, 20 - userIDLength);
// 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 010xff
data.add(role!);
//password 20
int passwordLength = utf8.encode(password!).length;
data.addAll(utf8.encode(password!));
data = getFixedLengthList(data, 20 - passwordLength);
// token 4 Token 0 token失效或者第一次发送的时候token为0
data.addAll(token!);
print("pubToken:$token");
if(needAuthor == 0){
//AuthCodeLen 1
data.add(0);
} else {
List<int> 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");
// KeyIDauthUserIDmd5加密之后就是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 EditUserReply extends Reply {
EditUserReply.parseData(CommandType commandType, List<int> dataDetail)
: super.parseData(commandType, dataDetail) {
data = dataDetail;
}
}

View File

@ -34,13 +34,13 @@ class GetLockStatuCommand extends SenderProtocol {
// id 40
int lockIDLength = utf8.encode(lockID!).length;
print("addUserLockIDLength:$lockIDLength utf8.encode(lockID!)${utf8.encode(lockID!)}");
// print("addUserLockIDLength:$lockIDLength utf8.encode(lockID!)${utf8.encode(lockID!)}");
data.addAll(utf8.encode(lockID!));
data = getFixedLengthList(data, 40 - lockIDLength);
//userID useid 20
int userIDLength = utf8.encode(userID!).length;
print("userIDLength:$userIDLength utf8.encode(userID!)${utf8.encode(userID!)}");
// print("userIDLength:$userIDLength utf8.encode(userID!)${utf8.encode(userID!)}");
data.addAll(utf8.encode(userID!));
data = getFixedLengthList(data, 20 - userIDLength);
@ -50,7 +50,7 @@ class GetLockStatuCommand extends SenderProtocol {
data.add(0);
}
}
print("addUserSM4Data:$data");
print("${commandType!.typeName} SM4Data:$data");
// LockId进行SM4 ECB加密 key:544d485f633335373034383064613864
ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB);
return ebcData;
@ -66,7 +66,7 @@ class GetLockStatuReply extends Reply {
switch(status){
case 0x00:
//
print("获取锁状态数据解析成功");
print("${commandType.typeValue} 数据解析成功");
var softVersion = data.sublist(3, 7);
// print("softVersion:$softVersion");
@ -111,22 +111,22 @@ class GetLockStatuReply extends Reply {
break;
case 0x06:
//
// print("获取锁状态需要鉴权");
print("${commandType.typeValue} 需要鉴权");
break;
case 0x07:
//
print("获取锁状态用户无权限");
print("${commandType.typeValue} 用户无权限");
break;
case 0x09:
//
print("获取锁状态权限校验错误");
print("${commandType.typeValue} 权限校验错误");
break;
default:
//
print("获取锁状态领锁失败");
print("${commandType.typeValue} 领锁失败");
break;
}

View File

@ -106,7 +106,7 @@ class GetPrivateKeyCommand extends SenderProtocol {
data.add(0);
}
}
// print("SM4Data:$data");
print("${commandType!.typeName} SM4Data:$data");
// LockId进行SM4 ECB加密 key:544d485f633335373034383064613864
ebcData = SM4.encrypt(data, key: utf8.encode(BlueManage().connectDeviceName), mode: SM4CryptoMode.ECB);

View File

@ -95,7 +95,7 @@ class OpenLockCommand extends SenderProtocol {
data.add(0);
}
}
print("addUserSM4Data:$data");
print("${commandType!.typeName} SM4Data:$data");
// LockId进行SM4 ECB加密 key:544d485f633335373034383064613864
ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB);
return ebcData;

View File

@ -50,12 +50,12 @@ abstract class SenderProtocol extends IOData {
//
// 4 4 1 01AES1282SM43SM4
commandList.add(commandType!.identifierValue);
print("commandType!.identifierValue:${commandType!.identifierValue}");
// print("commandType!.identifierValue:${commandType!.identifierValue}");
//
int dataLen = dataSourceLength();
// commandList.add(dataLength);
print("dataLen:$dataLen");
// print("dataLen:$dataLen");
// var dataLen = 42;
double dataLength = dataLen/256;
commandList.add(dataLength.toInt());

View File

@ -4,7 +4,7 @@ import 'package:get/get.dart';
enum CommandType {
addUser, // = 0x3001
deletUser , // = 0x3002
modifyingUser , // = 0x3003
editUser , // = 0x3003
factoryDataReset , // = 0x3004
openLock , // = 0x3005
readLockStatusInfo, // = 0x300A
@ -37,7 +37,7 @@ extension ExtensionCommandType on CommandType {
break;
case 0x3003:
{
type = CommandType.modifyingUser;
type = CommandType.editUser;
}
break;
case 0x3004:
@ -118,7 +118,7 @@ extension ExtensionCommandType on CommandType {
case CommandType.deletUser:
type = 0x3002;
break;
case CommandType.modifyingUser:
case CommandType.editUser:
type = 0x3003;
break;
case CommandType.factoryDataReset:

View File

@ -5,6 +5,7 @@ import 'dart:convert';
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_getLockStatu.dart';
import '../tools/storage.dart';
@ -126,6 +127,11 @@ class CommandReciverManager {
reply = GetLockStatuReply.parseData(commandType, data);
}
break;
case CommandType.editUser:
{
reply = EditUserReply.parseData(commandType, data);
}
break;
}
return reply;
}

View File

@ -3,6 +3,7 @@ import 'package:star_lock/blue/io_protocol/io_deletUser.dart';
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_getPrivateKey.dart';
import 'io_protocol/io_getPublicKey.dart';
import 'io_protocol/io_openLock.dart';
@ -72,6 +73,42 @@ class IoSenderManage {
), callBack:callBack);
}
//todo:
static void senderEditUser({
String? lockID,
String? authUserID,
String? keyID,
String? userID,
int? openMode,
int? keyType,
int? startDate,
int? expireDate,
int? role,
String? password,
int? needAuthor,
List<int>? publicKey,
List<int>? privateKey,
List<int>? token,
CommandSendCallBack? callBack}) {
CommandSenderManager().managerSendData(
command: EditUserCommand(
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:
static void deletUser({
String? lockID,

View File

@ -2,7 +2,9 @@
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_getLockStatu.dart';
import 'package:star_lock/blue/io_protocol/io_type.dart';
import '../../../blue/blue_manage.dart';
import '../../../blue/io_protocol/io_openLock.dart';
@ -26,9 +28,15 @@ class LockDetailLogic extends BaseGetXController{
_replyOpenLock(reply);
}
//
if(reply is GetLockStatuReply) {
_replyGetLockStatus(reply);
}
//
if(reply is EditUserReply){
_replyEditUserKey(reply);
}
});
}
@ -161,6 +169,65 @@ class LockDetailLogic extends BaseGetXController{
}
}
Future<void> _replyEditUserKey(Reply reply) async {
var token = reply.data.sublist(2, 6);
var saveStrList = changeIntListToStringList(token);
print("_replyEditUserKeyToken:$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<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var publicKey = await Storage.getStringList(saveBluePublicKey);
List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
IoSenderManage.senderEditUser(
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("${reply.commandType!.typeValue} 用户无权限");
break;
case 0x09:
//
print("${reply.commandType!.typeValue} 添加用户权限校验错误");
break;
default:
//
print("${reply.commandType!.typeValue} 失败");
break;
}
}
Future<void> openDoorAction() async {
BlueManage().judgeReconnect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", (DeviceConnectionState state) async {
if (state == DeviceConnectionState.connected){
@ -188,6 +255,40 @@ class LockDetailLogic extends BaseGetXController{
});
}
Future<void> editLockUserAction() async {
BlueManage().judgeReconnect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", (DeviceConnectionState state) async {
if (state == DeviceConnectionState.connected){
var publicKey = await Storage.getStringList(saveBluePublicKey);
List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var token = await Storage.getStringList(saveBlueToken);
List<int> getTokenList = changeStringListToIntList(token!);
print("openDoorTokenPubToken:$getTokenList");
print("privateKey:$privateKey token:$token");
IoSenderManage.senderEditUser(
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
);
}
});
}
Future<void> connectBlue() async {
//
// BlueManage().connect("AD01447A-30B5-A780-E778-DED3BDCB613E", "TMH_c3570480da8d", connectStateCallBack: (DeviceConnectionState state) async {

View File

@ -76,7 +76,8 @@ class _LockDetailPageState extends State<LockDetailPage> {
Center(
child: GestureDetector(
onTap: (){
logic.openDoorAction();
// logic.openDoorAction();
logic.editLockUserAction();
},
child: Image.asset('images/main/icon_main_openLockBtn.png',
width: 268.w, height: 268.w),

View File

@ -24,7 +24,7 @@ class NearbyLockLogic extends BaseGetXController{
//
void connect(String lockId, String deviceName){
BlueManage().connect(lockId, deviceName, isFrist: false);
BlueManage().connect(lockId, deviceName, isFrist: true);
}
//