蓝牙数据交互封装、数据请求封装
This commit is contained in:
parent
877dd8580d
commit
c77ae41b47
66
star_lock/lib/command/io_protocol/io_addUser.dart
Normal file
66
star_lock/lib/command/io_protocol/io_addUser.dart
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
|
||||||
|
import '../io_tool/io_tool.dart';
|
||||||
|
import 'io_reply.dart';
|
||||||
|
import 'io_sender.dart';
|
||||||
|
import 'io_type.dart';
|
||||||
|
|
||||||
|
//TODO:添加用户
|
||||||
|
class AddUserCommand extends SenderProtocol {
|
||||||
|
|
||||||
|
int? cmdID;
|
||||||
|
String? lockID;
|
||||||
|
String? authUserID;
|
||||||
|
String? keyID;
|
||||||
|
String? userID;
|
||||||
|
int? openMode;
|
||||||
|
int? keyType;
|
||||||
|
int? startDate;
|
||||||
|
int? expireDate;
|
||||||
|
int? role;
|
||||||
|
String? password;
|
||||||
|
int? token;
|
||||||
|
int? authCodeLen;
|
||||||
|
String? authCode;
|
||||||
|
AddUserCommand({
|
||||||
|
this.cmdID,
|
||||||
|
this.lockID,
|
||||||
|
this.authUserID,
|
||||||
|
this.keyID,
|
||||||
|
this.userID,
|
||||||
|
this.openMode,
|
||||||
|
this.keyType,
|
||||||
|
this.startDate,
|
||||||
|
this.expireDate,
|
||||||
|
this.role,
|
||||||
|
this.password,
|
||||||
|
this.token,
|
||||||
|
this.authCodeLen,
|
||||||
|
this.authCode,
|
||||||
|
}) : super(CommandType.addUser);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<int> messageDetail() {
|
||||||
|
List<int> data = [];
|
||||||
|
// data.add(0x21);
|
||||||
|
// int d = direction!.toInt();
|
||||||
|
// data.addAll(intToByte2ListHigh(d));
|
||||||
|
// data.add(0x22);
|
||||||
|
// int s = speed!.toInt();
|
||||||
|
// data.add(s);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RemoteControlReply extends Reply {
|
||||||
|
RemoteControlReply.parseData(CommandType commandType, List<int> dataDetail, int endIndex)
|
||||||
|
: super.parseData(commandType, dataDetail, endIndex) {
|
||||||
|
int index = 0;
|
||||||
|
while(index < endIndex){
|
||||||
|
commandKey = byteUInt8(dataDetail, index);
|
||||||
|
index += offset_1!;
|
||||||
|
switch(commandKey){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
star_lock/lib/command/io_protocol/io_openDoor.dart
Normal file
59
star_lock/lib/command/io_protocol/io_openDoor.dart
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../io_tool/io_tool.dart';
|
||||||
|
import 'io_reply.dart';
|
||||||
|
import 'io_sender.dart';
|
||||||
|
import 'io_type.dart';
|
||||||
|
|
||||||
|
//TODO:开门
|
||||||
|
class OpenDoorCommand extends SenderProtocol {
|
||||||
|
|
||||||
|
int? cmdID;
|
||||||
|
String? keyID;
|
||||||
|
String? userID;
|
||||||
|
int? openMode;
|
||||||
|
int? openTime;
|
||||||
|
int? token;
|
||||||
|
int? authCodeLen;
|
||||||
|
String? authCode;
|
||||||
|
OpenDoorCommand({
|
||||||
|
this.cmdID,
|
||||||
|
this.keyID,
|
||||||
|
this.userID,
|
||||||
|
this.openMode,
|
||||||
|
this.openTime,
|
||||||
|
this.token,
|
||||||
|
this.authCodeLen,
|
||||||
|
this.authCode,
|
||||||
|
}) : super(CommandType.openDoor);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<int> messageDetail() {
|
||||||
|
List<int> data = [];
|
||||||
|
data.addAll(intToInt8List(cmdID!));
|
||||||
|
data.addAll(utf8.encode(keyID!));
|
||||||
|
data.addAll(utf8.encode(userID!));
|
||||||
|
data.addAll(intToInt8List(openMode!));
|
||||||
|
data.addAll(intToInt8List(openTime!));
|
||||||
|
data.addAll(intToInt8List(token!));
|
||||||
|
data.addAll(intToInt8List(authCodeLen!));
|
||||||
|
data.addAll(utf8.encode(authCode!));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RemoteControlReply extends Reply {
|
||||||
|
RemoteControlReply.parseData(CommandType commandType, List<int> dataDetail, int endIndex)
|
||||||
|
: super.parseData(commandType, dataDetail, endIndex) {
|
||||||
|
int index = 0;
|
||||||
|
while(index < endIndex){
|
||||||
|
commandKey = byteUInt8(dataDetail, index);
|
||||||
|
index += offset_1!;
|
||||||
|
switch(commandKey){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
star_lock/lib/command/io_protocol/io_reply.dart
Normal file
23
star_lock/lib/command/io_protocol/io_reply.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'io_type.dart';
|
||||||
|
|
||||||
|
abstract class Reply{
|
||||||
|
//value字节长度
|
||||||
|
int? offset_19 = 19; //基准源长度
|
||||||
|
int? offset_8 = 8; //草坪名称
|
||||||
|
int? offset_6 = 6; //基准源识别码6个字节
|
||||||
|
int? offset_4 = 4;
|
||||||
|
int? offset_2 = 2;
|
||||||
|
int? offset_1 = 1;
|
||||||
|
CommandType? commandType;
|
||||||
|
int? result = 1; //1是正常 0 是异常
|
||||||
|
|
||||||
|
//command key flag
|
||||||
|
int commandKey = 0;
|
||||||
|
|
||||||
|
Reply.parseData(this.commandType,List<int> dataDetail,int endIndex);
|
||||||
|
Reply({this.result});
|
||||||
|
|
||||||
|
|
||||||
|
bool get isSuccessfully => result == 1;
|
||||||
|
|
||||||
|
}
|
||||||
49
star_lock/lib/command/io_protocol/io_sender.dart
Normal file
49
star_lock/lib/command/io_protocol/io_sender.dart
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import '../io_tool/io_manager.dart';
|
||||||
|
import '../io_tool/io_tool.dart';
|
||||||
|
import 'io_type.dart';
|
||||||
|
|
||||||
|
abstract class IOData {
|
||||||
|
List<int> messageDetail();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class SenderProtocol extends IOData {
|
||||||
|
|
||||||
|
CommandType? commandType; //指令类型
|
||||||
|
final int header = 0XEF01EE02; //帧头 固定取值 0XEF01EE02,长度 4 字节
|
||||||
|
final int ask = 0X01 ; // 包类型:0X01 表示请求包,0X11 表示应答包,长度 1 字节
|
||||||
|
int? _commandIndex; //帧序号
|
||||||
|
final int identifier = 0x22 ; // 高 4 位表示包版本,低 4 位用来指示后面数据的加密类型,长度为 1 字节,加密类型取值说明,0:明文,1:AES128,2:SM4(事先约定密钥),3:SM4(设备指定密钥)
|
||||||
|
|
||||||
|
List<int>? commandData = []; //数据域
|
||||||
|
final int? tail = 0xFF; //帧尾
|
||||||
|
|
||||||
|
SenderProtocol(this.commandType) {
|
||||||
|
_commandIndex = IoManager().commandIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO:拼装数据
|
||||||
|
List<int> packageData() {
|
||||||
|
commandData = messageDetail();
|
||||||
|
List<int> commandList = [];
|
||||||
|
commandList.add(header); //帧头
|
||||||
|
commandList.add(_commandIndex!); //帧序号
|
||||||
|
commandList.addAll(intToInt8List(dataSourceLength()));
|
||||||
|
int type = commandType!.typeValue;
|
||||||
|
commandList.addAll(intToInt8List(type)); //指令类型
|
||||||
|
commandList.addAll(commandData!); //数据域
|
||||||
|
commandList.add(checkSum(commandList)); //校验和
|
||||||
|
commandList.add(tail!); //帧尾
|
||||||
|
|
||||||
|
//帧头
|
||||||
|
// commandList.add(0xEF);
|
||||||
|
// commandList.add(0x01);
|
||||||
|
// commandList.add(0xEE);
|
||||||
|
// commandList.add(0x02);
|
||||||
|
|
||||||
|
return commandList;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO:校验和
|
||||||
|
int dataSourceLength() => commandData!.length;
|
||||||
|
|
||||||
|
}
|
||||||
222
star_lock/lib/command/io_protocol/io_type.dart
Normal file
222
star_lock/lib/command/io_protocol/io_type.dart
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
//TODO:发送指令类型
|
||||||
|
enum CommandType {
|
||||||
|
addUser, //增加用户 = 0x3001
|
||||||
|
deletUser , //删除用户 = 0x3002
|
||||||
|
modifyingUser , //修改用户 = 0x3003
|
||||||
|
factoryDataReset , //恢复出厂设置 = 0x3004
|
||||||
|
openDoor , //开门 = 0x3005
|
||||||
|
readLockStatusInfo, //读取锁状态信息 = 0x300A
|
||||||
|
transferPermissions, //转移权限 = 0x300B
|
||||||
|
reportDoorOpenRecord, //开门记录上报 = 0x3020
|
||||||
|
generalExtendedCommond , // 通用扩展指令 = 0x3030
|
||||||
|
getLockPublicKey , // 获取锁公钥 = 0x3090
|
||||||
|
getLockPrivateKey, // 获取锁私钥 = 0x3091
|
||||||
|
calibrationTime, // 校时 = 0x30f0
|
||||||
|
synchronizingLocationInformation, // 同步位置信息 = 0x30f1
|
||||||
|
opsUnlocks, // 运维开锁 0x30f2
|
||||||
|
writeHotelInfo, // 写酒店信息 = 0x3016
|
||||||
|
readHotelInfo, //读酒店信息 0x3017
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ExtensionCommandType on CommandType {
|
||||||
|
|
||||||
|
static CommandType getCommandType(int value){
|
||||||
|
CommandType type = CommandType.readLockStatusInfo;
|
||||||
|
switch(value){
|
||||||
|
case 0x3001:
|
||||||
|
{
|
||||||
|
type = CommandType.addUser;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3002:
|
||||||
|
{
|
||||||
|
type = CommandType.deletUser;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3003:
|
||||||
|
{
|
||||||
|
type = CommandType.modifyingUser;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3004:
|
||||||
|
{
|
||||||
|
type = CommandType.factoryDataReset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3005:
|
||||||
|
{
|
||||||
|
type = CommandType.openDoor;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x300A:
|
||||||
|
{
|
||||||
|
type = CommandType.readLockStatusInfo;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x300B:
|
||||||
|
{
|
||||||
|
type = CommandType.transferPermissions;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3020:
|
||||||
|
{
|
||||||
|
type = CommandType.reportDoorOpenRecord;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3030:
|
||||||
|
{
|
||||||
|
type = CommandType.generalExtendedCommond;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3090:
|
||||||
|
{
|
||||||
|
type = CommandType.getLockPublicKey;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3091:
|
||||||
|
{
|
||||||
|
type = CommandType.getLockPrivateKey;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x30f0:
|
||||||
|
{
|
||||||
|
type = CommandType.calibrationTime;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x30f1:
|
||||||
|
{
|
||||||
|
type = CommandType.synchronizingLocationInformation;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x30f2:
|
||||||
|
{
|
||||||
|
type = CommandType.opsUnlocks;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3016:
|
||||||
|
{
|
||||||
|
type = CommandType.writeHotelInfo;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3017:
|
||||||
|
{
|
||||||
|
type = CommandType.readHotelInfo;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get typeValue {
|
||||||
|
int type = 0x300A;
|
||||||
|
switch(this){
|
||||||
|
case CommandType.addUser:
|
||||||
|
type = 0x3001;
|
||||||
|
break;
|
||||||
|
case CommandType.deletUser:
|
||||||
|
type = 0x3002;
|
||||||
|
break;
|
||||||
|
case CommandType.modifyingUser:
|
||||||
|
type = 0x3003;
|
||||||
|
break;
|
||||||
|
case CommandType.factoryDataReset:
|
||||||
|
type = 0x3004;
|
||||||
|
break;
|
||||||
|
case CommandType.openDoor:
|
||||||
|
type = 0x3005;
|
||||||
|
break;
|
||||||
|
case CommandType.readLockStatusInfo:
|
||||||
|
type = 0x300A;
|
||||||
|
break;
|
||||||
|
case CommandType.transferPermissions:
|
||||||
|
type = 0x300B;
|
||||||
|
break;
|
||||||
|
case CommandType.reportDoorOpenRecord:
|
||||||
|
type = 0x3020;
|
||||||
|
break;
|
||||||
|
case CommandType.generalExtendedCommond:
|
||||||
|
type = 0x3030;
|
||||||
|
break;
|
||||||
|
case CommandType.getLockPublicKey:
|
||||||
|
type = 0x3090;
|
||||||
|
break;
|
||||||
|
case CommandType.getLockPrivateKey:
|
||||||
|
type = 0x3091;
|
||||||
|
break;
|
||||||
|
case CommandType.calibrationTime:
|
||||||
|
type = 0x30f0;
|
||||||
|
break;
|
||||||
|
case CommandType.synchronizingLocationInformation:
|
||||||
|
type = 0x30f1;
|
||||||
|
break;
|
||||||
|
case CommandType.opsUnlocks:
|
||||||
|
type = 0x30f2;
|
||||||
|
break;
|
||||||
|
case CommandType.writeHotelInfo:
|
||||||
|
type = 0x3016;
|
||||||
|
break;
|
||||||
|
case CommandType.readHotelInfo:
|
||||||
|
type = 0x3017;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// AppLog.log('数组组装指令类型:$name commandIndex:${IoManager
|
||||||
|
// ().commandIndex}');
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
String get typeName {
|
||||||
|
String t = '';
|
||||||
|
switch(typeValue){
|
||||||
|
case 0x3001:
|
||||||
|
t = '增加用户';
|
||||||
|
break;
|
||||||
|
case 0x3002:
|
||||||
|
t = '删除用户';
|
||||||
|
break;
|
||||||
|
case 0x3003:
|
||||||
|
t = '修改用户';
|
||||||
|
break;
|
||||||
|
case 0x3004:
|
||||||
|
t = '恢复出厂设置';
|
||||||
|
break;
|
||||||
|
case 0x3005:
|
||||||
|
t = '开门';
|
||||||
|
break;
|
||||||
|
case 0x300A:
|
||||||
|
t = '读取锁状态信息';
|
||||||
|
break;
|
||||||
|
case 0x300B:
|
||||||
|
t = '转移权限';
|
||||||
|
break;
|
||||||
|
case 0x3020:
|
||||||
|
t = '开门记录上报';
|
||||||
|
break;
|
||||||
|
case 0x3030:
|
||||||
|
t = '通用扩展指令';
|
||||||
|
break;
|
||||||
|
case 0x3090:
|
||||||
|
t = '获取锁公钥';
|
||||||
|
break;
|
||||||
|
case 0x3091:
|
||||||
|
t = '获取锁私钥';
|
||||||
|
break;
|
||||||
|
case 0x30f0:
|
||||||
|
t = '校时';
|
||||||
|
break;
|
||||||
|
case 0x30f1:
|
||||||
|
t = '同步位置信息';
|
||||||
|
break;
|
||||||
|
case 0x30f2:
|
||||||
|
t = '运维开锁';
|
||||||
|
break;
|
||||||
|
case 0x3016:
|
||||||
|
t = '写酒店信息';
|
||||||
|
break;
|
||||||
|
case 0x3017:
|
||||||
|
t = '读酒店信息';
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
star_lock/lib/command/io_tool/io_manager.dart
Normal file
39
star_lock/lib/command/io_tool/io_manager.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
enum DataTransmissionMode {
|
||||||
|
ble,
|
||||||
|
}
|
||||||
|
|
||||||
|
class IoManager {
|
||||||
|
|
||||||
|
static IoManager? _ioManager;
|
||||||
|
IoManager._init();
|
||||||
|
static IoManager share(){
|
||||||
|
_ioManager ??= IoManager._init();
|
||||||
|
return _ioManager!;
|
||||||
|
}
|
||||||
|
factory IoManager() => share();
|
||||||
|
IoManager get manager => share();
|
||||||
|
|
||||||
|
//数据传输方式
|
||||||
|
DataTransmissionMode _dataTransmissionMode = DataTransmissionMode.ble;
|
||||||
|
bool get isBleChannel =>_dataTransmissionMode == DataTransmissionMode.ble;
|
||||||
|
|
||||||
|
///蓝牙传输协议
|
||||||
|
void bleTransmission() => _dataTransmissionMode = DataTransmissionMode.ble;
|
||||||
|
|
||||||
|
int _commandIndex = 0; //割草机协议帧序号
|
||||||
|
configCommandIdx(int idx) => _commandIndex = idx;
|
||||||
|
Future<void> increaseCommandIndex() async {
|
||||||
|
_commandIndex < 255 ? _commandIndex++ : _commandIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetCommandIndex(){
|
||||||
|
_commandIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get commandIndex => _commandIndex;
|
||||||
|
|
||||||
|
void resetAllFlags() {
|
||||||
|
resetCommandIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
46
star_lock/lib/command/io_tool/io_model.dart
Normal file
46
star_lock/lib/command/io_tool/io_model.dart
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
///发送数据类
|
||||||
|
enum DataChannel{
|
||||||
|
ble
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Extension on DataChannel {
|
||||||
|
bool get isBLE => this == DataChannel.ble;
|
||||||
|
}
|
||||||
|
|
||||||
|
class EventSendModel {
|
||||||
|
List<int>? data = [];
|
||||||
|
String? topic = '';
|
||||||
|
DataChannel? sendChannel;
|
||||||
|
EventSendModel({required this.data,this.topic,this.sendChannel});
|
||||||
|
}
|
||||||
|
|
||||||
|
///接收数据类
|
||||||
|
class EventReceiveModel {
|
||||||
|
dynamic data;
|
||||||
|
String? tag = '';
|
||||||
|
DataChannel? sendChannel;
|
||||||
|
|
||||||
|
EventReceiveModel({
|
||||||
|
required this.data,
|
||||||
|
this.sendChannel,
|
||||||
|
this.tag});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///解析数据域
|
||||||
|
class EventParseModel {
|
||||||
|
int? type;
|
||||||
|
int? commandIndex;
|
||||||
|
dynamic data;
|
||||||
|
EventParseModel({required this.type, required this.data, this.commandIndex});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///debug info model
|
||||||
|
class StateModel {
|
||||||
|
final String title;
|
||||||
|
final String subTitle;
|
||||||
|
final bool result;
|
||||||
|
StateModel({this.title= '',this.subTitle = '',this.result = false});
|
||||||
|
}
|
||||||
229
star_lock/lib/command/io_tool/io_tool.dart
Normal file
229
star_lock/lib/command/io_tool/io_tool.dart
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
//TODO:int->两个字节 List 低字节在前,高字节在后(大端存储)=>嵌入式小端接收(协议用到)
|
||||||
|
|
||||||
|
int byteInt8(List<int> dataDetail, int index)=>_toInt8(dataDetail[index]);
|
||||||
|
int _toInt8(int value){
|
||||||
|
var buffer = Int8List(4).buffer;
|
||||||
|
var bData = ByteData.view(buffer);
|
||||||
|
bData.setInt8(0, value);
|
||||||
|
return bData.getInt8(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int byteInt16(List<int> dataDetail, int index)=>_byteInt16(dataDetail, index);
|
||||||
|
int _byteInt16(List<int> dataDetail, int index){
|
||||||
|
if(checkListIndex(dataDetail, index, 2)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int value = (dataDetail[index +1] & 0xff) << 8 | (dataDetail[index] & 0xff);
|
||||||
|
return _toInt16(value);
|
||||||
|
}
|
||||||
|
int _toInt16(int value){
|
||||||
|
var buffer = Int16List(1).buffer;
|
||||||
|
var bData = ByteData.view(buffer);
|
||||||
|
bData.setInt16(0, value);
|
||||||
|
int outputValue = bData.getInt16(0);
|
||||||
|
return outputValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int byteInt32(List<int> dataDetail, int index)=>_byteInt32(dataDetail, index);
|
||||||
|
int _byteInt32(List<int> dataDetail, int index){
|
||||||
|
if(checkListIndex(dataDetail, index, 4)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int value = ((0xFF &
|
||||||
|
dataDetail[(index + 3)]) << 24 | (0xFF &
|
||||||
|
dataDetail[index + 2]) << 16 | (0xFF & dataDetail[index + 1]) << 8 | 0xFF &
|
||||||
|
dataDetail[index]);
|
||||||
|
return _toInt32(value);
|
||||||
|
}
|
||||||
|
int _toInt32(int value){
|
||||||
|
var buffer = Int32List(2).buffer;
|
||||||
|
var bData = ByteData.view(buffer);
|
||||||
|
bData.setInt32(0, value);
|
||||||
|
int outputValue = bData.getInt32(0);
|
||||||
|
return outputValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> intToInt8List(int value) =>[value];
|
||||||
|
|
||||||
|
List<int> intToByte2ListHigh(int value) => [value,value >> 8];
|
||||||
|
|
||||||
|
//TODO:int->4个字节List 低字节在前,高字节在后(大端存储) 1byte = 8bit
|
||||||
|
List<int> intToByte4ListHigh(int value) => [value, value >> 8, value >> 16, value >> 24];
|
||||||
|
|
||||||
|
int byteUInt8(List<int> dataDetail, int index)=>_toUInt8(dataDetail[index]);
|
||||||
|
int _toUInt8(int value){
|
||||||
|
var buffer = Int8List(1).buffer;
|
||||||
|
var bData = ByteData.view(buffer);
|
||||||
|
bData.setInt8(0, value);
|
||||||
|
return bData.getUint8(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int byteUInt16(List<int> dataDetail, int index)=>_byteUInt16(dataDetail, index);
|
||||||
|
_byteUInt16(List<int> dataDetail, int index){
|
||||||
|
if(checkListIndex(dataDetail, index, 2)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int value = (dataDetail[index + 1]) << 8 | dataDetail[index];
|
||||||
|
return _toUInt16(value);
|
||||||
|
}
|
||||||
|
int _toUInt16(int value){
|
||||||
|
var buffer = Uint16List(2).buffer;
|
||||||
|
var bData = ByteData.view(buffer);
|
||||||
|
bData.setInt16(0, value);
|
||||||
|
return bData.getUint16(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int byteUInt32(List<int> dataDetail, int index)=>_byteUInt32(dataDetail, index);
|
||||||
|
|
||||||
|
int _byteUInt32(List<int> dataDetail, int index){
|
||||||
|
if(checkListIndex(dataDetail, index, 4)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int value = ((0xFF &
|
||||||
|
dataDetail[(index + 3)]) << 24 | (0xFF &
|
||||||
|
dataDetail[index + 2]) << 16 | (0xFF & dataDetail[index + 1]) << 8 | 0xFF &
|
||||||
|
dataDetail[index]);
|
||||||
|
return _toUInt32(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _toUInt32(int value){
|
||||||
|
var buffer = Int32List(2).buffer;
|
||||||
|
var bData = ByteData.view(buffer);
|
||||||
|
bData.setInt32(0, value);
|
||||||
|
int outputValue = bData.getUint32(0);
|
||||||
|
return outputValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkListIndex(List<int> dataDetail, int index, int offsetLength){
|
||||||
|
if(dataDetail == null){
|
||||||
|
print('❌解析 dataDetail == null');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var len = dataDetail.length;
|
||||||
|
bool result = index + offsetLength > len;
|
||||||
|
if(result){
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkSum(List<int> data) {
|
||||||
|
int sum = 0;
|
||||||
|
for(int v in data){
|
||||||
|
sum ^= v;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<int>> loadAssetsFile(String assetsPath) async{
|
||||||
|
var byteData = await rootBundle.load(assetsPath);
|
||||||
|
return byteData.buffer.asUint8List().toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO:获取数据包分包后包的数量
|
||||||
|
int getPackageCount(List<int> data,{required int averageLen}){
|
||||||
|
int len = data.length;
|
||||||
|
return len%averageLen > 0 ? (len~/averageLen + 1) : len~/averageLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> getSubData({
|
||||||
|
required int index,
|
||||||
|
required int average,
|
||||||
|
required List<int> data
|
||||||
|
}){
|
||||||
|
if(data == null || data.length == 0){
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
int totalLength = data.length;
|
||||||
|
if(average >= totalLength){
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index*average > totalLength){
|
||||||
|
if((index - 1)*average > totalLength){
|
||||||
|
return [];
|
||||||
|
}else{
|
||||||
|
int tempCount = average*(index - 1);
|
||||||
|
return data.sublist(tempCount,totalLength);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return data.sublist(average*(index - 1),average*index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> reverseList(List<int> srcData){
|
||||||
|
print('srcData:$srcData'); //[1,3]
|
||||||
|
int srcLen = srcData.length;
|
||||||
|
int halfLen = srcLen ~/2;
|
||||||
|
List<int> dstData = [];
|
||||||
|
dstData.addAll(srcData);
|
||||||
|
for(int i =0; i < halfLen; i++){
|
||||||
|
int begin = i;
|
||||||
|
int end = srcLen-i-1;
|
||||||
|
List<int> beginData = srcData.sublist(begin,begin+1);
|
||||||
|
List<int> endData = srcData.sublist(end,end + 1);
|
||||||
|
dstData.replaceRange(begin, begin+1, endData);
|
||||||
|
dstData.replaceRange(end, end+1, beginData);
|
||||||
|
}
|
||||||
|
print('dstData:$dstData');
|
||||||
|
return dstData;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO:int->两个字节 List 高字节在前,低字节在后(小端存储) 本工程只有配置 WiFi用到的!!!!
|
||||||
|
List<int> intToByte2ListLow(int value) =>[value >> 8,value];
|
||||||
|
|
||||||
|
|
||||||
|
int dealWeekDays({
|
||||||
|
required int mon,
|
||||||
|
required int tue,
|
||||||
|
required int wed,
|
||||||
|
required int thu,
|
||||||
|
required int fri,
|
||||||
|
required int sat,
|
||||||
|
required int sun,
|
||||||
|
}){
|
||||||
|
return mon + tue * 2 + wed * 4 + thu * 8 + fri * 16 + sat * 32 + sun * 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
String radixString(List<int> codeUnits){
|
||||||
|
String result = '';
|
||||||
|
codeUnits.forEach((value){
|
||||||
|
result += value.toRadixString(16).padLeft(2,'0');
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String asciiString(List<int> codeUnits){
|
||||||
|
String result = '';
|
||||||
|
codeUnits.forEach((value){
|
||||||
|
result += String.fromCharCode(value);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String utf8String(List<int> codeUnits){
|
||||||
|
return utf8.decode(codeUnits);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compareTwoList({List<int>? list1,List<int>? list2}) {
|
||||||
|
if(list1!.length != list2!.length)return false;
|
||||||
|
int ctn = list1.length;
|
||||||
|
for(int i = 0; i < ctn;i++){
|
||||||
|
int v1 = list1[i];
|
||||||
|
int v2 = list2[i];
|
||||||
|
if(v1 != v2){
|
||||||
|
print('不包含 $i');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> encodeStringToInt(String input)=>utf8.encode(input);
|
||||||
24
star_lock/lib/command/io_tool/manager_event_bus.dart
Normal file
24
star_lock/lib/command/io_tool/manager_event_bus.dart
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'package:event_bus/event_bus.dart';
|
||||||
|
|
||||||
|
class EventBusManager {
|
||||||
|
EventBus? eventBus;
|
||||||
|
|
||||||
|
static EventBusManager? _manager;
|
||||||
|
EventBusManager._init(){
|
||||||
|
eventBus = EventBus(sync: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EventBusManager shareManager(){
|
||||||
|
_manager ??= EventBusManager._init();
|
||||||
|
return _manager!;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory EventBusManager() => shareManager();
|
||||||
|
EventBusManager get manager => shareManager();
|
||||||
|
//发送事件
|
||||||
|
eventBusFir(dynamic event) {
|
||||||
|
eventBus?.fire(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
6
star_lock/lib/command/reciver_data.dart
Normal file
6
star_lock/lib/command/reciver_data.dart
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class CommandReciverManager {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
107
star_lock/lib/command/sender_data.dart
Normal file
107
star_lock/lib/command/sender_data.dart
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
import '../app_settings/app_settings.dart';
|
||||||
|
import 'io_protocol/io_sender.dart';
|
||||||
|
import 'io_protocol/io_type.dart';
|
||||||
|
import 'io_tool/io_model.dart';
|
||||||
|
import 'io_tool/manager_event_bus.dart';
|
||||||
|
|
||||||
|
typedef CommandSendCallBack = void Function(ErrorType errorType);
|
||||||
|
class CommandSenderManager {
|
||||||
|
|
||||||
|
static final CommandSenderManager _manager = CommandSenderManager
|
||||||
|
._init();
|
||||||
|
factory CommandSenderManager()=>_manager;
|
||||||
|
static CommandSenderManager getInstance()=>_manager;
|
||||||
|
CommandSenderManager._init(){
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
init(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandType lastCommandType = CommandType.readLockStatusInfo;
|
||||||
|
bool canSendControlCommand = false;
|
||||||
|
|
||||||
|
//TODO:发送常规数据
|
||||||
|
void managerSendData ({
|
||||||
|
required SenderProtocol command,
|
||||||
|
CommandSendCallBack? callBack}) {
|
||||||
|
if (callBack != null && command.commandType != CommandType.readLockStatusInfo) {
|
||||||
|
// if (!BluetoothManager().connected) {
|
||||||
|
print('❌ 蓝牙断开了');
|
||||||
|
if (callBack != null) {
|
||||||
|
print('managerSendData ❌ callBack');
|
||||||
|
// EasyLoading.dismiss();
|
||||||
|
callBack(ErrorType.notConnected);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> value = command.packageData();
|
||||||
|
_sendNormalData(value);
|
||||||
|
// startCommandCutDown(command.commandType, value, callBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _sendNormalData(List<int> data) async {
|
||||||
|
if (data != null && data.isNotEmpty) {
|
||||||
|
EventBusManager().eventBusFir(EventSendModel(data: data, sendChannel: DataChannel.ble));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer? _commandTimer;
|
||||||
|
// List<int>? bufferList = [];
|
||||||
|
// int? outTimeCount = 1;
|
||||||
|
// CommandType? sendCommandType; //发送指令类型
|
||||||
|
//
|
||||||
|
// void startCommandCutDown(CommandType? commandType, List<int>? data, Function? callBack) async {
|
||||||
|
//
|
||||||
|
// bool needCutDownTime = commandType.cutDown;
|
||||||
|
// int maxResendCount = commandType.resendCnt;
|
||||||
|
// int outMax = commandType.duration;
|
||||||
|
//
|
||||||
|
// if(needCutDownTime){
|
||||||
|
// lastCommandType = commandType;
|
||||||
|
// cancelCommandCutDown();
|
||||||
|
// if(needCutDownTime){
|
||||||
|
// bufferList = data;
|
||||||
|
// _commandTimer = Timer.periodic( Duration(
|
||||||
|
// milliseconds: outMax,
|
||||||
|
// ), (t){
|
||||||
|
// if(outTimeCount < maxResendCount){
|
||||||
|
// outTimeCount++;
|
||||||
|
// if(bufferList.length > 0){
|
||||||
|
// AppLog.log(''''
|
||||||
|
// ------->\n超时 第 $outTimeCount 次 重发 $commandType 指令 ''',error: true);
|
||||||
|
// // if(commandType != CommandType.upgrade){
|
||||||
|
// // print('重发重置帧序号');
|
||||||
|
// // bufferList.replaceRange(1, 2, [IoManager().commandIndex]);
|
||||||
|
// // }
|
||||||
|
// _sendNormalData(bufferList);
|
||||||
|
// }
|
||||||
|
// }else{
|
||||||
|
// bufferList = [];
|
||||||
|
// cancelCommandCutDown();
|
||||||
|
// print('managerSendData ❌ callBack');
|
||||||
|
// if(callBack != null){
|
||||||
|
// callBack(ErrorType.timeOut);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// void cancelCommandCutDown({CommandType commandType}){
|
||||||
|
// AppLog.log('发送指令类取消定时');
|
||||||
|
// if(commandType != null && commandType != lastCommandType)return;
|
||||||
|
// if(_commandTimer != null){
|
||||||
|
// _commandTimer.cancel();
|
||||||
|
// _commandTimer = null;
|
||||||
|
// }
|
||||||
|
// outTimeCount = 1;
|
||||||
|
// bufferList.clear();
|
||||||
|
// bufferList = [];
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
44
star_lock/lib/command/sender_manage.dart
Normal file
44
star_lock/lib/command/sender_manage.dart
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
import 'package:star_lock/command/sender_data.dart';
|
||||||
|
|
||||||
|
import 'io_protocol/io_addUser.dart';
|
||||||
|
import 'io_protocol/io_openDoor.dart';
|
||||||
|
|
||||||
|
class IoSenderManage {
|
||||||
|
|
||||||
|
//todo:添加用户
|
||||||
|
static void senderAddUser({CommandSendCallBack? callBack}) {
|
||||||
|
CommandSenderManager().managerSendData(
|
||||||
|
command: AddUserCommand(
|
||||||
|
cmdID: 0,
|
||||||
|
lockID: "",
|
||||||
|
authUserID: "",
|
||||||
|
keyID: "",
|
||||||
|
userID: "",
|
||||||
|
openMode: 0,
|
||||||
|
keyType: 0,
|
||||||
|
startDate: 0,
|
||||||
|
expireDate: 0,
|
||||||
|
role: 0,
|
||||||
|
password: "",
|
||||||
|
token: 0,
|
||||||
|
authCodeLen: 0,
|
||||||
|
authCode: "",
|
||||||
|
), callBack:callBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
//todo:开锁
|
||||||
|
static void senderOpenDoor({CommandSendCallBack? callBack}) {
|
||||||
|
CommandSenderManager().managerSendData(
|
||||||
|
command: OpenDoorCommand(
|
||||||
|
cmdID: 0,
|
||||||
|
keyID: "",
|
||||||
|
userID: "",
|
||||||
|
openMode: 0,
|
||||||
|
openTime: 0,
|
||||||
|
token: 0,
|
||||||
|
authCodeLen: 0,
|
||||||
|
authCode: "",
|
||||||
|
), callBack:callBack);
|
||||||
|
}
|
||||||
|
}
|
||||||
44
star_lock/lib/login/login/entity/Data.dart
Normal file
44
star_lock/lib/login/login/entity/Data.dart
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
class Data {
|
||||||
|
Data({
|
||||||
|
this.id,
|
||||||
|
this.tel,
|
||||||
|
this.email,
|
||||||
|
this.deviceId,
|
||||||
|
this.type,
|
||||||
|
this.token,
|
||||||
|
this.snName,
|
||||||
|
this.createTime,});
|
||||||
|
|
||||||
|
Data.fromJson(dynamic json) {
|
||||||
|
id = json['id'];
|
||||||
|
tel = json['tel'];
|
||||||
|
email = json['email'];
|
||||||
|
deviceId = json['deviceId'];
|
||||||
|
type = json['type'];
|
||||||
|
token = json['token'];
|
||||||
|
snName = json['snName'];
|
||||||
|
createTime = json['createTime'];
|
||||||
|
}
|
||||||
|
int? id;
|
||||||
|
String? tel;
|
||||||
|
String? email;
|
||||||
|
String? deviceId;
|
||||||
|
int? type;
|
||||||
|
String? token;
|
||||||
|
String? snName;
|
||||||
|
int? createTime;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final map = <String, dynamic>{};
|
||||||
|
map['id'] = id;
|
||||||
|
map['tel'] = tel;
|
||||||
|
map['email'] = email;
|
||||||
|
map['deviceId'] = deviceId;
|
||||||
|
map['type'] = type;
|
||||||
|
map['token'] = token;
|
||||||
|
map['snName'] = snName;
|
||||||
|
map['createTime'] = createTime;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
32
star_lock/lib/login/login/entity/LoginEntity.dart
Normal file
32
star_lock/lib/login/login/entity/LoginEntity.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import 'Data.dart';
|
||||||
|
|
||||||
|
class LoginEntity {
|
||||||
|
LoginEntity({
|
||||||
|
this.msg,
|
||||||
|
this.msgCode,
|
||||||
|
this.data,
|
||||||
|
this.code,});
|
||||||
|
|
||||||
|
LoginEntity.fromJson(dynamic json) {
|
||||||
|
msg = json['msg'];
|
||||||
|
msgCode = json['msgCode'];
|
||||||
|
data = json['data'] != null ? Data.fromJson(json['data']) : null;
|
||||||
|
code = json['code'];
|
||||||
|
}
|
||||||
|
String? msg;
|
||||||
|
int? msgCode;
|
||||||
|
Data? data;
|
||||||
|
int? code;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final map = <String, dynamic>{};
|
||||||
|
map['msg'] = msg;
|
||||||
|
map['msgCode'] = msgCode;
|
||||||
|
if (data != null) {
|
||||||
|
map['data'] = data!.toJson();
|
||||||
|
}
|
||||||
|
map['code'] = code;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -29,21 +29,13 @@ class _StarLockMainState extends State<StarLockMain> with BaseWidget{
|
|||||||
final flutterReactiveBle = FlutterReactiveBle();
|
final flutterReactiveBle = FlutterReactiveBle();
|
||||||
List<DiscoveredDevice> deviceList = [];
|
List<DiscoveredDevice> deviceList = [];
|
||||||
|
|
||||||
@override
|
|
||||||
void setState(VoidCallback fn) {
|
|
||||||
// TODO: implement setState
|
|
||||||
super.setState(fn);
|
|
||||||
|
|
||||||
// BleScanner.to.startScan([
|
|
||||||
//
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
GetxBle.call.scanner.startScan([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
// final logic = Get.put(GetxBle());
|
||||||
|
// // Get.lazyPut(()=>GetxBle());
|
||||||
|
// logic.scanner.startScan([]);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF5F5F5),
|
backgroundColor: const Color(0xFFF5F5F5),
|
||||||
appBar: TitleAppBar(barTitle: TranslationLoader.lanKeys!.starLock!.tr, haveBack:false, haveOtherLeftWidget: true, leftWidget: Builder(
|
appBar: TitleAppBar(barTitle: TranslationLoader.lanKeys!.starLock!.tr, haveBack:false, haveOtherLeftWidget: true, leftWidget: Builder(
|
||||||
|
|||||||
12
star_lock/lib/network/api.dart
Normal file
12
star_lock/lib/network/api.dart
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
abstract class Api {
|
||||||
|
|
||||||
|
final String baseUrl = "";
|
||||||
|
|
||||||
|
final String getVerificationCodeUrl = '/api/v1/vcode/email';
|
||||||
|
|
||||||
|
final String registerUrl = '/api/v1/vcode/email';
|
||||||
|
|
||||||
|
final String loginUrl = '/api/v1/vcode/email';
|
||||||
|
|
||||||
|
}
|
||||||
23
star_lock/lib/network/api_provider.dart
Normal file
23
star_lock/lib/network/api_provider.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'api_provider_base.dart';
|
||||||
|
|
||||||
|
class ApiProvider extends BaseProvider {
|
||||||
|
|
||||||
|
Future<Response> requestForVCode(String email) => post(getVerificationCodeUrl.toUrl, null,query: {
|
||||||
|
'email':email,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<Response> register(String email, String vCode,String password) => post(registerUrl.toUrl, null,query: {
|
||||||
|
'email':email,
|
||||||
|
'vCode':vCode,
|
||||||
|
"password":password
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<Response> login(String email,String password) => post(loginUrl.toUrl, null,query: {'email':email,'password':password});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ExtensionString on String {
|
||||||
|
String get toUrl => '/$this';
|
||||||
|
}
|
||||||
45
star_lock/lib/network/api_provider_base.dart
Normal file
45
star_lock/lib/network/api_provider_base.dart
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'api.dart';
|
||||||
|
import 'request_interceptor.dart';
|
||||||
|
import 'request_interceptor_log.dart';
|
||||||
|
import 'response_interceptor.dart';
|
||||||
|
import 'response_interceptor_log.dart';
|
||||||
|
|
||||||
|
class BaseProvider extends GetConnect with Api {
|
||||||
|
@override
|
||||||
|
void onInit() {
|
||||||
|
httpClient.baseUrl = baseUrl;
|
||||||
|
httpClient.addRequestModifier(requestInterceptor);
|
||||||
|
httpClient.addResponseModifier(responseInterceptor);
|
||||||
|
httpClient.addRequestModifier(requestLogInterceptor);
|
||||||
|
httpClient.addResponseModifier(responseLogInterceptor);
|
||||||
|
httpClient.timeout = 15.seconds;
|
||||||
|
super.onInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Response<T>> post<T>(String? url, body, {String? contentType, Map<String, String>? headers, Map<String, dynamic>? query, Decoder<T>? decoder, Progress? uploadProgress}) async {
|
||||||
|
var res = await super.post(url, body, contentType: contentType, headers:headers, query: query, decoder:decoder, uploadProgress: uploadProgress);
|
||||||
|
if(res.body == null){
|
||||||
|
if(EasyLoading.isShow)EasyLoading.dismiss(animation: true);
|
||||||
|
var rs = {
|
||||||
|
"msg": "Network Error!",
|
||||||
|
"msgCode": -1,
|
||||||
|
"data": null,
|
||||||
|
"code": 200
|
||||||
|
};
|
||||||
|
return Response(
|
||||||
|
request: res.request,
|
||||||
|
statusCode: -1,
|
||||||
|
bodyString: res.bodyString,
|
||||||
|
bodyBytes: res.bodyBytes,
|
||||||
|
body: rs as T,
|
||||||
|
statusText: res.statusText,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
28
star_lock/lib/network/api_repository.dart
Normal file
28
star_lock/lib/network/api_repository.dart
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'api_provider.dart';
|
||||||
|
|
||||||
|
class ApiRepository {
|
||||||
|
final ApiProvider apiProvider;
|
||||||
|
|
||||||
|
static ApiRepository get to => Get.find<ApiRepository>();
|
||||||
|
ApiRepository(this.apiProvider);
|
||||||
|
|
||||||
|
// Future<VerficationCodeEntity> requestForVCode(String email) async {
|
||||||
|
// final res = await apiProvider.requestForVCode(email);
|
||||||
|
// return VerficationCodeEntity.fromJson(res.body);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Future<LoginEntity> register(String email, String vCode,String password) async {
|
||||||
|
// final res = await apiProvider.register(email,vCode,SecrecyUtils.md5EncodeUpperCase(input: password));
|
||||||
|
// return LoginEntity.fromJson(res.body);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Future<LoginEntity> login({String? email,String? password}) async {
|
||||||
|
// final res = await apiProvider.login(email,SecrecyUtils.md5EncodeUpperCase(input: password));
|
||||||
|
// return LoginEntity.fromJson(res.body);
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
15
star_lock/lib/network/request_interceptor.dart
Normal file
15
star_lock/lib/network/request_interceptor.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:get/get_connect/http/src/request/request.dart';
|
||||||
|
|
||||||
|
import '../tools/platform_info_services.dart';
|
||||||
|
import '../tools/store_service.dart';
|
||||||
|
|
||||||
|
FutureOr<Request> requestInterceptor(Request request) async {
|
||||||
|
request.headers['User-Agent'] = 'Mower/CANDELA_18E/${PlatformInfoService.to.info.version}/${PlatformInfoService.to.info.buildNumber}/${GetPlatform.isAndroid ? 'Android' : 'iOS'}';
|
||||||
|
request.headers['Accept-Language'] = 'zh_CN';
|
||||||
|
request.headers['token'] = StoreService.to.userToken!;
|
||||||
|
return request;
|
||||||
|
}
|
||||||
13
star_lock/lib/network/request_interceptor_log.dart
Normal file
13
star_lock/lib/network/request_interceptor_log.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:get/get_connect/http/src/request/request.dart';
|
||||||
|
|
||||||
|
FutureOr<Request> requestLogInterceptor(Request request) async {
|
||||||
|
Get.log('GET HTTP REQUEST \n${request.url} \n${request.headers} ${request.toString()} ');
|
||||||
|
Get.log(request.headers.toString());
|
||||||
|
EasyLoading.show();
|
||||||
|
return request;
|
||||||
|
}
|
||||||
20
star_lock/lib/network/response_interceptor.dart
Normal file
20
star_lock/lib/network/response_interceptor.dart
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:get/get_connect/http/src/request/request.dart';
|
||||||
|
|
||||||
|
import '../tools/manager/client_manager.dart';
|
||||||
|
|
||||||
|
|
||||||
|
FutureOr<dynamic> responseInterceptor(Request request,Response response) async {
|
||||||
|
var statusCode = response.statusCode;
|
||||||
|
if(statusCode == 403){
|
||||||
|
await ClientManager().logOff();
|
||||||
|
// Get.offAllNamed(RouteConfig.homePage);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
if(response.isOk){
|
||||||
|
// Get.log('接口成功返回${response.body}');
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
11
star_lock/lib/network/response_interceptor_log.dart
Normal file
11
star_lock/lib/network/response_interceptor_log.dart
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:get/get_connect/http/src/request/request.dart';
|
||||||
|
|
||||||
|
FutureOr<dynamic> responseLogInterceptor(Request request,Response response) {
|
||||||
|
Get.log('HTTP RESPONSE =>\n stataCode:${response.statusCode} ${response.body} ${response.headers}');
|
||||||
|
EasyLoading.dismiss(animation: true);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
57
star_lock/lib/tools/manager/client_manager.dart
Normal file
57
star_lock/lib/tools/manager/client_manager.dart
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// import 'package:hookii_robot/get_dom/services/store_service.dart';
|
||||||
|
// import '../../get_dom/network/api_models/login/LoginEntity.dart';
|
||||||
|
// import '../mower_manager/model_equipment.dart';
|
||||||
|
import '../../login/login/entity/Data.dart' as ud;
|
||||||
|
import '../../login/login/entity/LoginEntity.dart';
|
||||||
|
import '../store_service.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class ClientManager {
|
||||||
|
ClientManager._init(){
|
||||||
|
|
||||||
|
}
|
||||||
|
static ClientManager? _manager;
|
||||||
|
|
||||||
|
static ClientManager shareManager(){
|
||||||
|
_manager ??= ClientManager._init();
|
||||||
|
return _manager!;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory ClientManager() => shareManager();
|
||||||
|
|
||||||
|
List<ud.Data> devices = <ud.Data>[];
|
||||||
|
|
||||||
|
String vCode = '',cardText = '',password = '';
|
||||||
|
bool isEmail = true;
|
||||||
|
|
||||||
|
bool hasCheckedAppVersion = false;
|
||||||
|
|
||||||
|
// void updateDevice(ud.Data data) {
|
||||||
|
// int idx = devices.indexWhere((element) => element.serialNumber == data.serialNumber);
|
||||||
|
// if(idx == -1) {
|
||||||
|
// devices.add(ud.Data.fromJson(data.toJson()));
|
||||||
|
// }else {
|
||||||
|
// devices[idx] = ud.Data.fromJson(data.toJson());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool checkAlias(String name) {
|
||||||
|
// int idx = devices.indexWhere((element) => element.alias == name);
|
||||||
|
// return idx != -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
void resetDevices() => devices = [];
|
||||||
|
|
||||||
|
Future logOff() async {
|
||||||
|
await StoreService.to.removeUserInfo();
|
||||||
|
resetDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future loginSuccess({LoginEntity? loginEntity,bool byToken = false}) async {
|
||||||
|
if(byToken){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await StoreService.to.saveLogInInfo(loginEntity!);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -40,6 +40,8 @@ class BleScanner extends GetxController {
|
|||||||
_devices.clear();
|
_devices.clear();
|
||||||
_subscription?.cancel();
|
_subscription?.cancel();
|
||||||
_subscription = _ble.scanForDevices(withServices: serviceIds).listen((device) {
|
_subscription = _ble.scanForDevices(withServices: serviceIds).listen((device) {
|
||||||
|
print("11111111111111111:${device}");
|
||||||
|
|
||||||
final knownDeviceIndex = _devices.indexWhere((d) => d.id == device.id);
|
final knownDeviceIndex = _devices.indexWhere((d) => d.id == device.id);
|
||||||
|
|
||||||
if (knownDeviceIndex >= 0) {
|
if (knownDeviceIndex >= 0) {
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:get_storage/get_storage.dart';
|
import 'package:get_storage/get_storage.dart';
|
||||||
|
|
||||||
|
import '../login/login/entity/LoginEntity.dart';
|
||||||
|
|
||||||
final box = GetStorage();
|
final box = GetStorage();
|
||||||
class StoreService<T> extends GetxService {
|
class StoreService<T> extends GetxService {
|
||||||
|
|
||||||
static StoreService get to => Get.find<StoreService>();
|
static StoreService get to => Get.find<StoreService>();
|
||||||
Future<StoreService<T>> init() async {
|
Future<StoreService<T>> init() async {
|
||||||
await GetStorage.init();
|
await GetStorage.init();
|
||||||
// await resetUserInfo();
|
await resetUserInfo();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,22 +25,22 @@ class StoreService<T> extends GetxService {
|
|||||||
final String _userAccount = 'USER_ACCOUNT';
|
final String _userAccount = 'USER_ACCOUNT';
|
||||||
|
|
||||||
|
|
||||||
// LoginEntity _loginEntity;
|
LoginEntity? _loginEntity;
|
||||||
// LoginEntity get loginEntity => _loginEntity;
|
// LoginEntity get loginEntity => _loginEntity!;
|
||||||
// Future resetUserInfo() async{
|
Future resetUserInfo() async{
|
||||||
// if(hasData(_loginUserInfoKey)){
|
if(hasData(_loginUserInfoKey)){
|
||||||
// _loginEntity = LoginEntity.fromJson(box.read(_loginUserInfoKey));
|
_loginEntity = LoginEntity.fromJson(box.read(_loginUserInfoKey));
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// Future removeUserInfo() => remove(_loginUserInfoKey);
|
Future removeUserInfo() => remove(_loginUserInfoKey);
|
||||||
//
|
|
||||||
// Future saveLogInInfo(LoginEntity entity) {
|
Future saveLogInInfo(LoginEntity entity) async {
|
||||||
// _loginEntity = LoginEntity.fromJson(entity.toJson());
|
_loginEntity = LoginEntity.fromJson(entity.toJson());
|
||||||
// save(_loginUserInfoKey, entity.toJson());
|
save(_loginUserInfoKey, entity.toJson());
|
||||||
// if(_loginEntity != null && _loginEntity.data != null && _loginEntity.data.email != null && _loginEntity.data.email.isNotEmpty) {
|
if(_loginEntity != null && _loginEntity!.data != null && _loginEntity!.data!.email != null && _loginEntity!.data!.email!.isNotEmpty) {
|
||||||
// save(_userAccount, _loginEntity.data.email);
|
save(_userAccount, _loginEntity?.data?.email);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// String getDeviceId() => hasData(_deviceUUID!) ? read(_deviceUUID!): "";
|
// String getDeviceId() => hasData(_deviceUUID!) ? read(_deviceUUID!): "";
|
||||||
Future saveDeviceId(String uuid) => save(_deviceUUID, uuid);
|
Future saveDeviceId(String uuid) => save(_deviceUUID, uuid);
|
||||||
@ -46,8 +48,8 @@ class StoreService<T> extends GetxService {
|
|||||||
// String getLanguageCode() => hasData(_languageCode) ? read(_languageCode): "";
|
// String getLanguageCode() => hasData(_languageCode) ? read(_languageCode): "";
|
||||||
Future saveLanguageCode(String code) => save(_languageCode, code);
|
Future saveLanguageCode(String code) => save(_languageCode, code);
|
||||||
|
|
||||||
// bool get hadToken => loginEntity != null && loginEntity.data.token != null && loginEntity.data.token.isNotEmpty;
|
bool get hadToken => _loginEntity !=null && _loginEntity!.data!.token!.isNotEmpty;
|
||||||
// String get userToken => hadToken ? loginEntity.data.token : "";
|
String? get userToken => hadToken ? _loginEntity!.data!.token : "";
|
||||||
|
|
||||||
// String getLastUserAccount() => hasData(_userAccount) ? read(_userAccount): "";
|
// String getLastUserAccount() => hasData(_userAccount) ? read(_userAccount): "";
|
||||||
void removeLastUserAccount() => remove(_userAccount);
|
void removeLastUserAccount() => remove(_userAccount);
|
||||||
|
|||||||
@ -70,6 +70,10 @@ dependencies:
|
|||||||
flutter_reactive_ble: ^5.1.1
|
flutter_reactive_ble: ^5.1.1
|
||||||
# flutter_blue_plus: ^1.10.5
|
# flutter_blue_plus: ^1.10.5
|
||||||
|
|
||||||
|
event_bus: ^2.0.0
|
||||||
|
|
||||||
|
flutter_easyloading: ^3.0.5
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user