蓝牙数据交互封装、数据请求封装

This commit is contained in:
魏少阳 2023-07-27 15:29:37 +08:00
parent 877dd8580d
commit c77ae41b47
27 changed files with 1246 additions and 32 deletions

View 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){
}
}
}
}

View 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){
}
}
}
}

View 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;
}

View 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 01AES1282SM43SM4
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;
}

View 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;
}
}

View 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();
}
}

View 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});
}

View 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->4List () 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);

View 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);
}
}

View File

@ -0,0 +1,6 @@
class CommandReciverManager {
}

View 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 = [];
// }
}

View 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);
}
}

View 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;
}
}

View 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;
}
}

View File

@ -29,21 +29,13 @@ class _StarLockMainState extends State<StarLockMain> with BaseWidget{
final flutterReactiveBle = FlutterReactiveBle();
List<DiscoveredDevice> deviceList = [];
@override
void setState(VoidCallback fn) {
// TODO: implement setState
super.setState(fn);
// BleScanner.to.startScan([
//
// ]);
GetxBle.call.scanner.startScan([]);
}
@override
Widget build(BuildContext context) {
// final logic = Get.put(GetxBle());
// // Get.lazyPut(()=>GetxBle());
// logic.scanner.startScan([]);
return Scaffold(
backgroundColor: const Color(0xFFF5F5F5),
appBar: TitleAppBar(barTitle: TranslationLoader.lanKeys!.starLock!.tr, haveBack:false, haveOtherLeftWidget: true, leftWidget: Builder(

View 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';
}

View 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';
}

View 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;
}
}

View 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);
// }
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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!);
}
}

View File

@ -40,6 +40,8 @@ class BleScanner extends GetxController {
_devices.clear();
_subscription?.cancel();
_subscription = _ble.scanForDevices(withServices: serviceIds).listen((device) {
print("11111111111111111:${device}");
final knownDeviceIndex = _devices.indexWhere((d) => d.id == device.id);
if (knownDeviceIndex >= 0) {

View File

@ -1,13 +1,15 @@
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import '../login/login/entity/LoginEntity.dart';
final box = GetStorage();
class StoreService<T> extends GetxService {
static StoreService get to => Get.find<StoreService>();
Future<StoreService<T>> init() async {
await GetStorage.init();
// await resetUserInfo();
await resetUserInfo();
return this;
}
@ -23,22 +25,22 @@ class StoreService<T> extends GetxService {
final String _userAccount = 'USER_ACCOUNT';
// LoginEntity _loginEntity;
// LoginEntity get loginEntity => _loginEntity;
// Future resetUserInfo() async{
// if(hasData(_loginUserInfoKey)){
// _loginEntity = LoginEntity.fromJson(box.read(_loginUserInfoKey));
// }
// }
// Future removeUserInfo() => remove(_loginUserInfoKey);
//
// Future saveLogInInfo(LoginEntity entity) {
// _loginEntity = LoginEntity.fromJson(entity.toJson());
// save(_loginUserInfoKey, entity.toJson());
// if(_loginEntity != null && _loginEntity.data != null && _loginEntity.data.email != null && _loginEntity.data.email.isNotEmpty) {
// save(_userAccount, _loginEntity.data.email);
// }
// }
LoginEntity? _loginEntity;
// LoginEntity get loginEntity => _loginEntity!;
Future resetUserInfo() async{
if(hasData(_loginUserInfoKey)){
_loginEntity = LoginEntity.fromJson(box.read(_loginUserInfoKey));
}
}
Future removeUserInfo() => remove(_loginUserInfoKey);
Future saveLogInInfo(LoginEntity entity) async {
_loginEntity = LoginEntity.fromJson(entity.toJson());
save(_loginUserInfoKey, entity.toJson());
if(_loginEntity != null && _loginEntity!.data != null && _loginEntity!.data!.email != null && _loginEntity!.data!.email!.isNotEmpty) {
save(_userAccount, _loginEntity?.data?.email);
}
}
// String getDeviceId() => hasData(_deviceUUID!) ? read(_deviceUUID!): "";
Future saveDeviceId(String uuid) => save(_deviceUUID, uuid);
@ -46,8 +48,8 @@ class StoreService<T> extends GetxService {
// String getLanguageCode() => hasData(_languageCode) ? read(_languageCode): "";
Future saveLanguageCode(String code) => save(_languageCode, code);
// bool get hadToken => loginEntity != null && loginEntity.data.token != null && loginEntity.data.token.isNotEmpty;
// String get userToken => hadToken ? loginEntity.data.token : "";
bool get hadToken => _loginEntity !=null && _loginEntity!.data!.token!.isNotEmpty;
String? get userToken => hadToken ? _loginEntity!.data!.token : "";
// String getLastUserAccount() => hasData(_userAccount) ? read(_userAccount): "";
void removeLastUserAccount() => remove(_userAccount);

View File

@ -70,6 +70,10 @@ dependencies:
flutter_reactive_ble: ^5.1.1
# flutter_blue_plus: ^1.10.5
event_bus: ^2.0.0
flutter_easyloading: ^3.0.5
dev_dependencies:
flutter_test:
sdk: flutter