12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589 |
- import 'dart:async';
- import 'dart:collection';
- import 'dart:convert';
- import 'dart:core';
- import 'dart:io';
- import 'dart:math';
- import 'dart:typed_data';
- import 'package:broadcast/broadcast.dart';
- import 'package:buffer/buffer.dart';
- import 'package:device_info/device_info.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
- import 'package:get_it/get_it.dart';
- import 'package:package_info/package_info.dart';
- import 'package:path_provider/path_provider.dart';
- import 'package:permission_handler/permission_handler.dart';
- import 'package:shared_preferences/shared_preferences.dart';
- import 'package:sport/application.dart';
- import 'package:sport/bean/hardware.dart';
- import 'package:sport/db/bluetooth_db.dart';
- import 'package:sport/db/step_db.dart';
- import 'package:sport/pages/my/dfu_update_page.dart';
- import 'package:sport/services/Converter.dart';
- import 'package:sport/services/api/inject_api.dart';
- import 'package:sport/services/api/rest_client.dart';
- import 'package:sport/utils/toast.dart';
- import 'package:sport/utils/version.dart';
- import 'package:sport/widgets/dialog/alert_dialog.dart';
- const BLE_CODE_0 = 0x00;
- const BLE_CODE_1 = 0x01;
- class BLE {
- BLE._();
- static const BLE_Client_T_MOTION = 0x04;
- static const BLE_Client_T_UPDATE = 0xA1;
- static const BLE_Client_T_GAMEMODE = 0xA2;
- static const BLE_Client_T_CONNET_R = 0xA3;
- static const BLE_Client_T_SHOCK = 0xA4;
- static const BLE_Client_T_REALTIMESTEP = 0xA5;
- static const BLE_Client_T_DFU = 0xA6;
- static const BLE_Client_T_CHARGE = 0xA7;
- static const BLE_Client_T_LIGHTING = 0xAC;
- static const BLE_Client_T_ERR = 0xAD;
- }
- class BLE_UPDATE {
- BLE_UPDATE._();
- static const BASIC = 0x00;
- static const DATA = 0x01;
- static const STEP = 0x02;
- static const STEP_DELETE = 0x03;
- }
- const BLE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
- class Bluetooth with ChangeNotifier, InjectApi {
- static final String PREF_KEY = "SHOES";
- factory Bluetooth() => _getInstance();
- static Bluetooth? _instance;
- // 获取对象
- static Bluetooth _getInstance() {
- if (_instance == null) {
- // 使用私有的构造方法来创建对象
- _instance = Bluetooth._internal();
- }
- return _instance!;
- }
- Bluetooth._internal() {
- //初始化(设置一些默认的)...
- }
- final List<StreamSubscription<dynamic>> _streamSubscriptions = <StreamSubscription<dynamic>>[];
- void addSubscription(StreamSubscription<dynamic> streamSubscription) {
- _streamSubscriptions.add(streamSubscription);
- }
- void disposeSubscription() {
- for (StreamSubscription<dynamic> subscription in _streamSubscriptions) {
- subscription.cancel();
- }
- _streamSubscriptions.clear();
- characteristicNotify?.cancel();
- }
- // ignore: close_sinks
- final StreamController<bool> _queryController = StreamController.broadcast();
- Stream<bool> get queryStream => _queryController.stream;
- // ignore: close_sinks
- final StreamController<bool> _stateController = StreamController.broadcast();
- Stream<bool> get stateStream => _stateController.stream;
- // ignore: close_sinks
- final StreamController<Uint8List> _dataController = StreamController.broadcast();
- Stream<Uint8List> get dataStream => _dataController.stream;
- // ignore: close_sinks
- final StreamController<int> _connectRightController = StreamController.broadcast();
- Stream<int> get connectRightStream => _connectRightController.stream;
- final ValueNotifier<DiscoveredDevice?> deviceNotifier = ValueNotifier(null);
- final ValueNotifier<Map> infoNotifier = ValueNotifier<Map>({});
- final ValueNotifier<String> versionNotifier = ValueNotifier<String>("");
- final ValueNotifier<Map> dataNotifier = ValueNotifier<Map>({});
- final ValueNotifier<int> electricityNotifier = ValueNotifier<int>(0);
- final ValueNotifier<int> stepNotifier = ValueNotifier<int>(0);
- final ValueNotifier<int> stepTotalNotifier = ValueNotifier<int>(0);
- final ValueNotifier<int> stepTotalTestNotifier = ValueNotifier<int>(0);
- final ValueNotifier<int> actionNotifier = ValueNotifier<int>(0);
- final ValueNotifier<List<int>> byteNotifier = ValueNotifier<List<int>>([]);
- final ValueNotifier<int> vibrateNotifier = ValueNotifier<int>(400);
- final ValueNotifier<int> stepRealtimeNotifier = ValueNotifier<int>(-1);
- final ValueNotifier<bool> stepRealtimePageNotifier = ValueNotifier<bool>(false);
- final ValueNotifier<Hardware?> verNotifier = ValueNotifier(null);
- final ValueNotifier<Map<int, int>> stateNotifier = ValueNotifier({1: 0, 0: 0});
- final ValueNotifier<bool> h5gameRNotifier = ValueNotifier<bool>(false);
- final ValueNotifier<bool> deviceWriteNotifier = ValueNotifier<bool>(false);
- final ValueNotifier<bool> deviceReadNotifier = ValueNotifier<bool>(false);
- final ValueNotifier<bool> deviceReadNotifyNotifier = ValueNotifier<bool>(false);
- final ValueNotifier<int> rssiNotifier = ValueNotifier<int>(0);
- final ValueNotifier<Map<String, int>> timeUseNotifier = ValueNotifier<Map<String, int>>({});
- DiscoveredDevice? _connectingDevice, _connectedDevice;
- bool _listen = false;
- bool _online = false;
- bool _uploadLoged = false;
- String? _deviceId;
- PartInfo? _partInfo;
- Completer<bool>? _completerStep;
- Completer<bool>? _completerStepDel;
- Completer<bool>? _completerSetupDeviceVer;
- StreamSubscription? scanStreamSubscription;
- QualifiedCharacteristic? characteristicWrite;
- StreamSubscription? characteristicNotify;
- late FlutterReactiveBle flutterReactiveBle;
- Timer? stepRealTimeTimer;
- Timer? gameModeTimer;
- Timer? timerConnected;
- Timer? rssiTimer;
- Timer? disconnectTimer;
- int disconnectTimes = 0;
- DateTime? startTime;
- List<int> timeUse = [];
- int testDfu = 0;
- int _isRightError = 0;
- bool get isConnected => _online;
- bool get isNotReady => isDebugShoe ? false : !(_online == true && electricityNotifier.value > 0);
- bool get isRightError => _isRightError != 1;
- late BuildContext _context;
- bool _showChargeDialog = false;
- DateTime? electricityTime;
- resetData() {
- stepNotifier.value = 0;
- stepTotalNotifier.value = 0;
- actionNotifier.value = 0;
- }
- DiscoveredDevice? get device => _connectedDevice;
- set device(DiscoveredDevice? device) {
- _connectedDevice = device;
- notifyListeners();
- }
- bool _dfu = false;
- set dfu(bool dfu) {
- _dfu = dfu;
- }
- Future<String> _saveDevice(DiscoveredDevice device) async {
- var id = device.id.toString();
- var prefs = await SharedPreferences.getInstance();
- prefs.setString(PREF_KEY, id);
- return id;
- }
- clearDevice({bool deleteStep = false}) async {
- var prefs = await SharedPreferences.getInstance();
- prefs.remove(PREF_KEY);
- if (deleteStep == true) {
- var db = StepDB();
- db.deleteAll();
- }
- startTime = null;
- await disconnectDevice("清空设备");
- this.device = _connectedDevice = null;
- }
- Future<String?> getHistoryDevice() async {
- var prefs = await SharedPreferences.getInstance();
- return prefs.getString(PREF_KEY);
- }
- init(BuildContext context) async {
- this._context = context;
- this._listen = true;
- if (Platform.isAndroid) {
- DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
- AndroidDeviceInfo info = await deviceInfo.androidInfo;
- if (info.version.sdkInt < 31) {
- if (await Permission.locationWhenInUse.status.isGranted != true) return;
- } else {
- Map<Permission, PermissionStatus> statuses = await [
- Permission.bluetoothScan,
- Permission.bluetoothConnect,
- ].request();
- if (statuses.isNotEmpty == true && statuses.values.any((element) => element.isGranted) != true) {
- return;
- }
- }
- }
- flutterReactiveBle = FlutterReactiveBle();
- flutterReactiveBle.statusStream.listen((state) {
- print("bluetooth -- instance state $state");
- if (state == BleStatus.ready) {
- connectDevice();
- } else if (state == BleStatus.unknown) {
- } else if (state == BleStatus.poweredOff) {
- disconnectDevice("蓝牙状态不可用");
- ToastUtil.show("蓝牙服务已关闭");
- } else {}
- });
- flutterReactiveBle.connectedDeviceStream.listen((event) {
- print("bluetooth -- state $event!");
- if (event.connectionState == DeviceConnectionState.connected) {
- if (_deviceId == event.deviceId) {
- final deviceId = _deviceId!;
- notifyConnectTime("C");
- discoverServices(flutterReactiveBle, deviceId).then((value) {
- notifyConnectTime("D$value");
- if (value == 2) {
- setupGameMode(h5gameRNotifier.value);
- queryDeviceRight();
- timerConnected = Timer(Duration(seconds: 30), () {
- if (isRightError) clearDevice();
- });
- } else {}
- });
- }
- } else if (event.connectionState == DeviceConnectionState.disconnected) {
- if (event.failure?.code == ConnectionError.failedToConnect) {
- disconnectDevice("${event.failure?.message}");
- if (event.failure?.message?.contains("133") == true) {
- Future.microtask(() {
- connectDevice(id: event.deviceId);
- });
- }
- }
- }
- });
- versionNotifier.addListener(() {
- if (versionNotifier.value.isNotEmpty) {
- checkUpdate();
- }
- });
- connectRightStream.listen((event) {
- print("bluetooth -- connect right ${_connectingDevice?.name} ${event}!");
- if (event == 1 && _isRightError != event) {
- notifyConnectTime("R");
- timerConnected?.cancel();
- dataNotifier.value = {};
- infoNotifier.value = {};
- verNotifier.value = null;
- if (_connectingDevice != null) {
- _saveDevice(_connectingDevice!);
- _connected(_connectingDevice!);
- _query();
- }
- }
- _isRightError = event;
- });
- }
- Future listen(BuildContext context, {bool init = false}) async {
- this._context = context;
- this._listen = true;
- print("bluetooth -- listen");
- Broadcast.broadcast("SHOE.SDK.BLUE_DISCONNECT");
- var prefs = await SharedPreferences.getInstance();
- if (!prefs.containsKey("token")) {
- return;
- }
- disconnectTimer?.cancel();
- disconnectTimes = 0;
- if (_dfu == true) return;
- if (!isConnected) {
- connectDevice();
- }
- }
- void runTimer() {
- addSubscription(Stream.periodic(Duration(seconds: 60)).listen((event) async {
- if (device == null) return;
- if (!_online) return;
- await queryDeviceData();
- await queryDeviceStep();
- }));
- }
- Future background(BuildContext context) async {
- this._listen = false;
- if (_showChargeDialog == true) {
- Navigator.maybePop(context);
- }
- disconnectTimer?.cancel();
- disconnectTimer = Timer.periodic(Duration(seconds: 5), (t) {
- disconnectTimes++;
- if (disconnectTimes >= 20) {
- disconnectDevice("后台时断开连接");
- t.cancel();
- }
- });
- }
- Future disposeBluetooth(BuildContext context) async {
- if (_dfu == true) return;
- // // 实时计步中不主动断开
- if (stepRealtimePageNotifier.value == true) return;
- gameModeTimer?.cancel();
- this._listen = false;
- if (_showChargeDialog == true) {
- Navigator.maybePop(context);
- }
- // if (Platform.isIOS) {
- await disconnectDevice("app退后台");
- // }
- }
- resetNotifierData() {
- dataNotifier.value = {};
- infoNotifier.value = {};
- verNotifier.value = null;
- electricityNotifier.value = -1;
- _connectRightController.add(0);
- stateNotifier.value = {0: 0, 1: 0};
- deviceWriteNotifier.value = false;
- deviceReadNotifier.value = false;
- deviceReadNotifyNotifier.value = false;
- _online = false;
- _stateController.add(false);
- }
- Future disconnectDevice(String msg) async {
- print("bluetooth -- disconnect $msg $device");
- _deviceId = null;
- disposeSubscription();
- deviceNotifier.value = null;
- timerConnected?.cancel();
- resetNotifierData();
- disconnectTimes = 0;
- _uploadLoged = false;
- device = _connectedDevice = _connectingDevice = null;
- errQueue.clear();
- }
- Future connectDevice({DiscoveredDevice? device, String? id, bool again = false}) async {
- await disconnectDevice("主动连接");
- if (again != true) {
- timeUse = [];
- timeUseNotifier.value = {};
- }
- if (device != null) {
- startTime = null;
- BluetoothDB().insert(device);
- }
- notifyConnectTime("F");
- String? deviceId = id;
- if (device == null) {
- if (deviceId == null) {
- deviceId = await getHistoryDevice();
- }
- print("bluetooth -- connect from $deviceId $device");
- if (deviceId == null || deviceId.isEmpty) {
- return null;
- }
- try {
- device = await discoverDevice(deviceId: deviceId);
- } catch (e) {
- print(e);
- return;
- }
- }
- if (device == null) return;
- _deviceId = deviceId = device.id;
- print("bluetooth -- connect $deviceId!");
- notifyConnectTime("S");
- addSubscription(flutterReactiveBle
- .connectToDevice(
- id: deviceId,
- connectionTimeout: const Duration(seconds: 8),
- )
- .listen((update) {
- _connectingDevice = device!;
- // print("bluetooth -- connect state $deviceId $update!");
- }, onError: (Object e) {
- print("bluetooth -- connect error $deviceId $e!");
- _connectingDevice = null;
- }));
- }
- Future<DiscoveredDevice?> discoverDevice({String? deviceId, String? deviceName}) async {
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test I/System.out: 00001800-0000-1000-8000-00805f9b34fb
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test I/System.out: 00002a00-0000-1000-8000-00805f9b34fb
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test I/System.out: 00002a01-0000-1000-8000-00805f9b34fb
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test I/System.out: 00002a04-0000-1000-8000-00805f9b34fb
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test I/System.out: 00002aa6-0000-1000-8000-00805f9b34fb
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test I/System.out: 00001801-0000-1000-8000-00805f9b34fb
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test I/System.out: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test I/System.out: 6e400002-b5a3-f393-e0a9-e50e24dcca9e
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test D/BluetoothController: discovered characteristic write android.bluetooth.BluetoothGatt@28bbf97 android.bluetooth.BluetoothGattCharacteristic@81cd69e
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test I/System.out: 6e400003-b5a3-f393-e0a9-e50e24dcca9e
- // 2022-04-26 11:10:53.285 17454-17479/com.ouj.sdk.test D/BluetoothGatt: setCharacteristicNotification() - uuid: 6e400003-b5a3-f393-e0a9-e50e24dcca9e enable: true
- // 2022-04-26 11:10:53.286 17454-17479/com.ouj.sdk.test D/BluetoothController: discovered characteristic notify android.bluetooth.BluetoothGatt@28bbf97 android.bluetooth.BluetoothGattCharacteristic@9dfb57f
- // 2022-04-26 11:10:53.286 17454-17479/com.ouj.sdk.test I/System.out: 0000fe59-0000-1000-8000-00805f9b34fb
- // 2022-04-26 11:10:53.286 17454-17479/com.ouj.sdk.test I/System.out: 8ec90003-f315-4f60-9fb8-838830daea50
- scanStreamSubscription?.cancel();
- final completer = Completer<DiscoveredDevice?>();
- Timer timeout = Timer(Duration(seconds: 20), () {
- completer.completeError("timeout");
- });
- scanStreamSubscription = flutterReactiveBle.scanForDevices(withServices: [Uuid.parse(BLE_UUID)]).listen((event) {
- print('bluetooth -- scan device : ${event.id} ${event.name}');
- if (event.id == deviceId || event.name == deviceName || (deviceName != null && event.name.contains(deviceName))) {
- if (completer.isCompleted != true) completer.complete(event);
- }
- });
- var device;
- try {
- device = await completer.future.catchError((error, stackTrace) => throw error);
- timeout.cancel();
- } catch (e) {
- print("bluetooth -- shoe right fail $e");
- print(e);
- } finally {
- scanStreamSubscription?.cancel();
- }
- print('bluetooth -- found: ${device?.id} ${device?.name}');
- return device;
- }
- Future<int> discoverServices(FlutterReactiveBle flutterReactiveBle, String deviceId) async {
- int result = 0;
- characteristicNotify?.cancel();
- for (var i = 0; i < 3; i++) {
- bool findWrite = false;
- bool findRead = false;
- try {
- var services = await flutterReactiveBle.discoverServices(deviceId);
- for (DiscoveredService service in services) {
- for (var characteristic in service.characteristics) {
- if (characteristic.isWritableWithoutResponse) {
- characteristicWrite = QualifiedCharacteristic(serviceId: service.serviceId, characteristicId: characteristic.characteristicId, deviceId: deviceId);
- findWrite = true;
- deviceWriteNotifier.value = true;
- }
- if (characteristic.isNotifiable) {
- deviceReadNotifier.value = true;
- findRead = true;
- final qualifiedCharacteristic = QualifiedCharacteristic(serviceId: service.serviceId, characteristicId: characteristic.characteristicId, deviceId: deviceId);
- characteristicNotify = flutterReactiveBle.subscribeToCharacteristic(qualifiedCharacteristic).listen((event) {
- deviceReadNotifyNotifier.value = true;
- if (this._listen == true) {
- byteNotifier.value = event;
- parse(event);
- }
- });
- }
- }
- }
- } catch (e) {
- print(e);
- print("bluetooth -- service error $e");
- characteristicNotify?.cancel();
- }
- if (findWrite && findRead) {
- print("bluetooth -- service write: $findWrite, read: $findRead");
- result = 2;
- break;
- } else {
- await Future.delayed(Duration(seconds: 2));
- }
- }
- return result;
- }
- _query() async {
- queryDeviceInfo();
- queryDeviceRight();
- queryDeviceStep();
- queryDeviceCharge();
- queryDeviceData();
- }
- _connected(DiscoveredDevice newDevice) async {
- _stateController.add(true);
- _online = true;
- deviceNotifier.value = newDevice;
- this.device = newDevice;
- if (isDebugShoe) {
- ToastUtil.show("${newDevice.name} 已连接");
- }
- if ((startTime?.difference(DateTime.now()).inHours ?? 1) > 0) {
- notifyConnected();
- startTime = DateTime.now();
- }
- runTimer();
- flutterReactiveBle.connectedDeviceStream.toList().then((value) {
- value.forEach((element) {
- if (element.deviceId != newDevice.id) flutterReactiveBle.clearGattCache(element.deviceId);
- });
- });
- }
- notifyConnectTime(String tag) {
- int now = DateTime.now().millisecondsSinceEpoch;
- Map<String, int> result = timeUseNotifier.value;
- // print("111111111111111111 ${now} ${timeUse}");
- result[tag] = now - (timeUse.isNotEmpty ? timeUse.last : now);
- timeUseNotifier.value = result;
- timeUse.add(now);
- }
- notifyConnected() {
- this.vibrate(200);
- this.lighting(10000);
- }
- checkUpdate() async {
- var info = infoNotifier.value;
- print("bluetooth -- checkUpdate ${info}");
- if (info.isEmpty == true) return;
- String softwareVer = info['softwareVer'];
- String hardwareVer = info['hardwareVer'];
- List<String> device = info['device'];
- PackageInfo packageInfo = await PackageInfo.fromPlatform();
- String appVer = packageInfo.version;
- Hardware? updateInfo = (await GetIt.I<RestClient>().checkHardwareUpdate(hardwareVer, appVer)).data;
- if (updateInfo != null) {
- // PackageInfo packageInfo = await PackageInfo.fromPlatform();
- // if (updateInfo.min_app_ver?.isNotEmpty == true && versionCompare(packageInfo.version, updateInfo.min_app_ver ?? "0") < 0) {
- // debugPrint("bluetooth -- dfu update app ver ${packageInfo.version} min ${updateInfo.min_app_ver}");
- // return;
- // }
- // if (updateInfo.max_app_ver?.isNotEmpty == true && versionCompare(packageInfo.version, updateInfo.max_app_ver ?? "0") > 0) {
- // debugPrint("bluetooth -- dfu update app ver ${packageInfo.version} max ${updateInfo.max_app_ver}");
- // return;
- // }
- //
- // if (updateInfo.min_hardware_ver?.isNotEmpty == true && versionCompare(hardwareVer, updateInfo.min_hardware_ver ?? "0") < 0) {
- // debugPrint("bluetooth -- dfu update hardware ver ${hardwareVer} min ${updateInfo.min_hardware_ver}");
- // return;
- // }
- //
- // if (updateInfo.max_hardware_ver?.isNotEmpty == true && versionCompare(hardwareVer, updateInfo.max_hardware_ver ?? "0") > 0) {
- // debugPrint("bluetooth -- dfu update hardware ver ${hardwareVer} max ${updateInfo.max_hardware_ver}");
- // return;
- // }
- updateInfo.devices = [];
- updateInfo.localVer = softwareVer;
- print("bluetooth -- dfu versionCompare ${versionCompare(softwareVer, updateInfo.ver ?? "0.0")}");
- bool cancelable = this.testDfu >= 5
- ? true
- : Platform.isAndroid
- ? !inProduction
- : false;
- if (cancelable == false) {
- if (versionCompare(softwareVer, updateInfo.ver ?? "0.0") >= 0) {
- return;
- }
- }
- for (var i = device.length - 1; i >= 0; i--) {
- updateInfo.devices!.add(device[i]);
- }
- verNotifier.value = updateInfo;
- if (isDebugShoe) {
- var context = _context;
- var value = updateInfo;
- var closeable = 0;
- var result = await showDialog(
- context: context,
- barrierDismissible: false,
- builder: (context) => CustomAlertDialog(
- title: '发现新的鞋子固件',
- child: WillPopScope(
- onWillPop: () async {
- return false;
- },
- child: GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () {
- closeable++;
- if (closeable >= 5) {
- Navigator.of(context).pop(false);
- }
- },
- child: Container(
- width: double.infinity,
- padding: const EdgeInsets.symmetric(horizontal: 24.0),
- child: Text(
- "${value.name}\n${value.localVer} -> ${value.ver}\n${value.msg}",
- style: TextStyle(fontSize: 14, color: Color(0xff333333), height: 1.8),
- )),
- ),
- ),
- textOk: '立即升级',
- cancelable: cancelable,
- ok: () => Navigator.of(context).pop(true)),
- );
- if (result != true) return;
- result = await showDialog(
- context: context,
- barrierDismissible: false,
- builder: (context) => SimpleDialog(
- children: <Widget>[
- DfuUpdatePage(
- hardware: value,
- )
- ],
- ));
- }
- }
- }
- void parse(List<int> event) {
- if (event.isEmpty == true) return;
- if (!_listen) return;
- ByteDataReader reader = ByteDataReader();
- reader.add(event);
- int flagAA = reader.readUint8();
- // int flagBB = reader.readUint8();
- // int flagCC = reader.readUint8();
- int len = reader.readUint8();
- int len1 = 0xFF - reader.readUint8();
- // int index = reader.readUint8();
- int cmd = reader.readUint8();
- // print(" change --> ${flagAA} ${len} ${~len} ${cmd}");
- // print(" change --> ${len} ${~len} ${len1}");
- // print(" change --> ${index} ${cmd}");
- if (!(flagAA == 0xAA)) return;
- if (len != len1) return;
- Uint8List byteArray = reader.read(event.length - 5);
- int ver = 0;
- for (int i = 0; i < event.length - 1; i++) {
- ver += event[i];
- }
- if (ver.toUnsigned(8) != event[event.length - 1]) return;
- parseCmd(cmd, byteArray);
- }
- void parseCmd(int cmd, Uint8List byteArray) {
- // if (isDebugShoe) print(" cmd $cmd data --> $byteArray");
- switch (cmd) {
- case 0x01:
- _parseAction(byteArray);
- break;
- case BLE.BLE_Client_T_MOTION:
- disconnectTimes = 0;
- _dataController.add(byteArray);
- break;
- case 0xA0:
- break;
- case BLE.BLE_Client_T_UPDATE:
- _parseQuery(byteArray);
- break;
- case BLE.BLE_Client_T_CONNET_R:
- _connectRightController.add(byteArray.first);
- break;
- case BLE.BLE_Client_T_REALTIMESTEP:
- _parseStepRealtime(byteArray);
- break;
- case BLE.BLE_Client_T_DFU:
- if (_completerSetupDeviceVer?.isCompleted != true) _completerSetupDeviceVer?.complete(true);
- break;
- case BLE.BLE_Client_T_CHARGE: //充电
- _parseCharge(byteArray);
- break;
- case BLE.BLE_Client_T_ERR: //异常
- _parseErr(byteArray);
- break;
- case BLE.BLE_Client_T_GAMEMODE:
- break;
- }
- }
- void _parseAction(Uint8List byteArray) {
- ByteDataReader reader = ByteDataReader();
- reader.add(byteArray);
- int action = reader.readUint8();
- int t = reader.readUint16();
- print("action: $action ");
- actionNotifier.value = action;
- }
- void _parseQuery(Uint8List byteArray) {
- ByteDataReader reader = ByteDataReader();
- reader.add(byteArray);
- int cmd = reader.readUint8();
- switch (cmd) {
- case BLE_UPDATE.BASIC: // 设备基本信息
- Map<String, dynamic> info = {};
- List<int> name = [];
- for (var i = 0; i < 64; i++) {
- name.add(reader.readUint8());
- }
- info['name'] = String.fromCharCodes(name).replaceAll("\u0000", "");
- List<int> softwareVer = [];
- List<int> hardwareVer = [];
- List<String> device = [];
- for (var i = 0; i < 2; i++) {
- List<String> macList = [];
- for (var j = 0; j < 6; j++) {
- macList.add(reader.readUint8().toRadixString(16).padLeft(2, "0"));
- }
- var mac = macList.join(":").toUpperCase();
- print("mac $i = $mac");
- for (var k = 0; k < 4; k++) {
- hardwareVer.add(reader.readUint8());
- }
- softwareVer.add(reader.readUint8());
- device.add(mac);
- }
- print("bluetooth dfu info $hardwareVer $softwareVer");
- if (hardwareVer.length != 8 || softwareVer.length != 2) return;
- String leftHardware = hardwareVer.sublist(1, 4).join(".");
- String rightHardware = hardwareVer.sublist(4 + 1, hardwareVer.length).join(".");
- int compareHardware = versionCompare(leftHardware, rightHardware);
- String minHardwareVersion = compareHardware < 0 ? leftHardware : rightHardware;
- print("bluetooth hardwareVer $leftHardware $rightHardware $compareHardware $minHardwareVersion");
- String leftSoftware = hardwareVer.sublist(1, 3).join(".") + ".${softwareVer[0]}";
- String rightSoftware = hardwareVer.sublist(4 + 1, 4 + 1 + 2).join(".") + ".${softwareVer[0]}";
- int compareSoftware = versionCompare(leftSoftware, rightSoftware);
- String minSoftwareVersion = compareSoftware < 0 ? leftSoftware : rightSoftware;
- print("bluetooth softwareVer $leftSoftware $rightSoftware $compareSoftware $minSoftwareVersion");
- shoeVersion = "$minHardwareVersion";
- info['softwareVer'] = minSoftwareVersion;
- info['hardwareVer'] = minHardwareVersion;
- info['mac'] = device.length > 1 ? device.first : "";
- info['device'] = device;
- infoNotifier.value = info;
- if (versionNotifier.value != minSoftwareVersion) versionNotifier.value = minSoftwareVersion;
- _uploadErr();
- if (_uploadLoged != true) {
- _uploadLog();
- }
- break;
- case BLE_UPDATE.DATA: // 设备数据(左鞋,右鞋)
- Map<String, dynamic> info = {};
- for (var i = 0; i < 2; i++) {
- info['${i}_electricity'] = reader.readUint8();
- info['${i}_temperature'] = reader.readUint8();
- info['${i}_pressure'] = reader.readUint(4);
- reader.readUint(4);
- }
- if (reader.remainingLength >= 4) {
- info['0_adc'] = reader.readUint16();
- info['1_adc'] = reader.readUint16();
- }
- // [170, 187, 204, 23, 232, 0, 161, 1, 50, 0, 33, 0, 0, 156, 41, 51, 0, 34, 0, 0, 150, 19, 232]
- dataNotifier.value = info;
- int electricity = min(info['0_electricity'] ?? 0, info['1_electricity'] ?? 0);
- electricityNotifier.value = electricity;
- if (electricity < 10) {
- if (electricityTime == null || (electricityTime?.difference(DateTime.now()).inMinutes.abs() ?? 0) >= 60) {
- if (_showChargeDialog != true) {
- ToastUtil.show("鞋子电量不足,请及时充电!");
- electricityTime = DateTime.now();
- }
- }
- }
- if (isDebugShoe) {
- _testElectricity(info);
- }
- break;
- case BLE_UPDATE.STEP: // 查询步数
- print("bluetooth -- step part ${_partInfo?.ready}");
- if (_partInfo == null) return;
- if (_partInfo?.ready == true) return;
- if (isDebugShoe) {
- _testStep(byteArray.toList().join(","));
- }
- int start = reader.readUint64();
- int serialCount = reader.readUint16();
- int serial = reader.readUint16();
- // if(serialCount == 0){
- // _completerStep?.complete(false);
- // return;
- // }
- List<int> data = [];
- while (reader.remainingLength > 0) {
- data.add(reader.readUint32());
- }
- if (serial == 0 && data.isNotEmpty) {
- stepTotalNotifier.value = data.last;
- }
- _partInfo!.start = start;
- _partInfo!.serialCount = serialCount + 1;
- _partInfo!.data[serial] = data;
- print("bluetooth -- step start $start read ($serial,$serialCount) --> $data");
- if (_partInfo!.data.length == _partInfo!.serialCount) {
- _partInfo!.ready = true;
- var partResult = _partInfo!;
- Future.microtask(() async {
- await partResult.prepare();
- print("bluetooth -- step end ... ");
- await _saveInfo(partResult);
- });
- if (_completerStep?.isCompleted != true) _completerStep?.complete(true);
- }
- break;
- case BLE_UPDATE.STEP_DELETE: // 步数回调
- if (_completerStepDel != null) _completerStepDel!.complete(true);
- break;
- }
- }
- void _parseStepRealtime(Uint8List byteArray) {
- ByteDataReader reader = ByteDataReader();
- reader.add(byteArray);
- int cmd = reader.readUint8();
- if (cmd == 0) {
- } else if (cmd == 1) {
- int left = 0;
- int right = 0;
- if (reader.remainingLength > 4) {
- left = reader.readUint32();
- right = reader.readUint32();
- } else {
- left = reader.readUint16();
- right = reader.readUint16();
- }
- int step = left + right;
- // print("left: ${left}, right: ${ right} = ${step}");
- stepRealtimeNotifier.value = step;
- // 已经不是在实时计步页面,但还收到数据,关了!
- if (stepRealtimePageNotifier.value == false) {
- write(BLE.BLE_Client_T_REALTIMESTEP, Uint8List.fromList([BLE_CODE_0]));
- }
- }
- }
- void _parseCharge(Uint8List byteArray) async {
- ByteDataReader reader = ByteDataReader();
- reader.add(byteArray);
- int cmd = reader.readUint8();
- int state = reader.readUint8();
- Map<int, int> _state = Map.from(stateNotifier.value);
- _state.update(cmd, (value) => state);
- stateNotifier.value = _state;
- // print("111111111111111111111111 $_state");
- if (_state[0]! <= 1 && _state[1]! <= 1) {
- if (_showChargeDialog == true) {
- Navigator.maybePop(_context);
- }
- return;
- }
- if (_state[0] == 3 && _state[1] == 3) {
- queryDeviceData();
- }
- final String _name = "dialog_charge";
- if (_showChargeDialog == true) return;
- _showChargeDialog = true;
- showDialog(
- context: _context,
- barrierColor: Colors.transparent,
- builder: (context) => GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () {
- Navigator.maybePop(context);
- },
- child: Scaffold(
- backgroundColor: Colors.transparent,
- body: Center(
- child: Container(
- constraints: BoxConstraints(maxWidth: 180.0),
- decoration: BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(10.0)),
- color: Colors.black.withOpacity(.75),
- ),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Align(
- child: GestureDetector(
- child: Padding(
- padding: const EdgeInsets.all(10.0),
- child: Image.asset(
- "lib/assets/img/btn_close_white.png",
- width: 18,
- ),
- ),
- onTap: () {
- Navigator.maybePop(context);
- },
- behavior: HitTestBehavior.opaque,
- ),
- alignment: Alignment.topRight,
- ),
- Padding(
- padding: const EdgeInsets.fromLTRB(20.0, 5, 20.0, 16.0),
- child: ValueListenableBuilder<Map<int, int>>(
- valueListenable: stateNotifier,
- builder: (context, val, __) {
- int totalState = (val[0]! + val[1]!) ~/ 2;
- List<int> keys = val.keys.toList();
- keys.sort();
- return Column(
- children: [
- Center(
- child: Row(
- children: keys.map((key) {
- int state = val[key]!;
- String label = key == 0 ? "left" : "right";
- return Padding(
- padding: EdgeInsets.symmetric(horizontal: 10),
- child: Image.asset(
- state == 3
- ? "lib/assets/img/pop_icon_${label}full.png"
- : state == 2
- ? "lib/assets/img/pop_icon_${label}charge.png"
- : "lib/assets/img/pop_icon_${label}fault.png",
- ),
- );
- }).toList(),
- mainAxisSize: MainAxisSize.min,
- ),
- ),
- const SizedBox(
- height: 15,
- ),
- ValueListenableBuilder(
- valueListenable: electricityNotifier,
- builder: (BuildContext context, int value, Widget? child) {
- int _power = max(0, (val[0]! > 1 && val[1]! > 1) ? value : 0);
- return Column(
- children: [
- Text(
- (_power > 1) ? "$_power%" : "",
- style: TextStyle(fontSize: 8.0, color: Colors.white),
- ),
- const SizedBox(
- height: 7,
- ),
- ClipRRect(
- child: SizedBox(
- height: 2,
- child: LinearProgressIndicator(
- backgroundColor: Color(0xff656565),
- valueColor: AlwaysStoppedAnimation(Color(0xff00DC42)),
- value: _power / 100,
- ),
- ),
- borderRadius: BorderRadius.circular(5),
- )
- ],
- );
- },
- ),
- const SizedBox(
- height: 11,
- ),
- Text(
- (val[0] == 3 && val[1] == 3)
- ? "智能鞋充电已完成"
- : (val[0]! > 1 && val[1]! > 1)
- ? "智能鞋充电中..."
- : (val[0]! <= 1 && val[1]! <= 1)
- ? "智能鞋连接异常"
- : val[0]! <= 1
- ? "左鞋充电连接异常"
- : val[1]! <= 1
- ? "右鞋充电连接异常"
- : "连接异常",
- style: TextStyle(fontSize: 12.0, color: Colors.white),
- ),
- ],
- );
- }),
- ),
- ],
- )),
- ),
- ),
- ),
- routeSettings: RouteSettings(name: _name))
- .then((value) => _showChargeDialog = false);
- await Future.delayed(Duration(seconds: 5));
- if (_showChargeDialog == true) {
- Map<int, int> val = stateNotifier.value;
- print("_parseCharge $val");
- if (val[0]! > 1 && val[1]! > 1) {
- Navigator.maybePop(_context);
- }
- }
- }
- Queue<Map<String, String>> errQueue = Queue();
- /**
- * 错误处理
- */
- void _parseErr(Uint8List byteArray) async {
- ByteDataReader r = ByteDataReader();
- r.add(byteArray);
- int leftOrRight = r.readUint8();
- int code = r.readUint8();
- List<int> msgData = r.read(r.remainingLength);
- String msg = String.fromCharCodes(msgData);
- print("bluetooth - _parseErr $leftOrRight $code $msg");
- var err = {"code": "$code", "msg": "${leftOrRight == 0 ? "左鞋" : "右鞋"}:$msg"};
- if (errQueue.where((element) => element["code"] == "$code").isEmpty) errQueue.addLast(err);
- if (isDebugShoe) {
- await _testErrLog();
- }
- _uploadErr();
- }
- void _uploadErr() async {
- if (infoNotifier.value.isEmpty) return;
- if (errQueue.isEmpty) return;
- var info = infoNotifier.value;
- PackageInfo packageInfo = await PackageInfo.fromPlatform();
- String mac = "${info['mac']}";
- String firmware = "${info['softwareVer']}";
- String hardware = "${info['hardwareVer']}";
- String app_ver = "${packageInfo.version}";
- while (errQueue.isNotEmpty) {
- var first = errQueue.removeFirst();
- var err_code = first['code'] as String;
- var err_msg = first['msg'] as String;
- var resp = await api.logHardwareErr(mac, firmware, hardware, app_ver, err_code, err_msg, "");
- if (resp.code != 0) {
- errQueue.addLast(first);
- await Future.delayed(Duration(seconds: 5));
- }
- }
- }
- Future _saveInfo(PartInfo? partInfo) async {
- if (partInfo == null) return;
- print("bluetooth -- step save $partInfo ${partInfo.items.length}");
- if (partInfo.items.isEmpty == true) return;
- List<PartItem> _items = [];
- for (var item in partInfo.items) {
- if (item.step == 0 && item.distance == 0) continue;
- _items.add(item);
- print("bluetooth -- step save ${item.time} ${item.step}");
- }
- await StepDB().insertAll(_items);
- _queryController.add(true);
- }
- Future<int> _uploadInfo(int startTime) async {
- var list = await StepDB().find(startTime);
- print("bluetooth -- step upload $startTime $list");
- if (list.isEmpty) return 0;
- List<List<int>> data = [];
- int step = 0;
- for (var item in list) {
- data.add([item['st'], item['di'], (item['time'] as int) ~/ 1000]);
- step += Converter.toInt(item['st']);
- }
- if (step > 5) {
- var resp = await api.addDaily(data: json.encode(data));
- if (resp.code == 0) {
- // await StepDB().delete(last);
- return 0;
- }
- }
- return -1;
- // Directory appDocDir = await getApplicationDocumentsDirectory();
- // String appDocPath = appDocDir.path;
- // Directory saveDir = Directory("$appDocPath/step");
- // var files = saveDir.listSync();
- // for(var file in files){
- // var f= new File(file.path);
- // var content = f.readAsStringSync();
- // await api.addDaily(data: content);
- // file.delete();
- // }
- }
- // 查询 设备基本信息
- Future queryDeviceCharge() async {
- await write(BLE.BLE_Client_T_CHARGE, Uint8List(0));
- }
- // 查询 设备右鞋
- Future queryDeviceRight() async {
- await write(BLE.BLE_Client_T_CONNET_R, Uint8List.fromList([]));
- }
- // 查询 设备基本信息
- Future queryDeviceInfo() async {
- await write(BLE.BLE_Client_T_UPDATE, Uint8List.fromList([BLE_CODE_0]));
- }
- // 查询 设备数据
- Future queryDeviceData() async {
- await write(BLE.BLE_Client_T_UPDATE, Uint8List.fromList([BLE_CODE_1]));
- }
- // 查询 查询步数
- Future queryDeviceStep({bool test = false}) async {
- if (!isConnected) return;
- // await Future.delayed(Duration(seconds: 3));
- // _queryController.add(true);
- if (test != true) if (stepTotalTestNotifier.value == 1) return;
- if (_partInfo != null) {
- print("bluetooth -- step _partInfo.now ${_partInfo!.now.difference(DateTime.now()).inSeconds}");
- if ((_partInfo!.now.difference(DateTime.now()).inSeconds) > -60) {
- return;
- }
- }
- print("bluetooth -- step init");
- _partInfo = PartInfo(0, 0);
- if (test == true) stepTotalNotifier.value = -1;
- // await write(0xA1, createTime(0x02));
- await write(BLE.BLE_Client_T_UPDATE, Uint8List.fromList([BLE_UPDATE.STEP, BLE_CODE_0, BLE_CODE_0]));
- if (_completerStep != null && _completerStep?.isCompleted != true) _completerStep?.complete(false);
- if (_completerStepDel != null && _completerStepDel?.isCompleted != true) _completerStepDel?.complete(false);
- _completerStep = Completer();
- _completerStepDel = Completer();
- var timer = Timer.periodic(Duration(seconds: 1), (timer) {
- if (_partInfo == null) return;
- Iterable<int> keys = _partInfo!.data.keys;
- if (keys.isEmpty) return;
- for (var i = 1; i < _partInfo!.serialCount; i++) {
- if (!keys.contains(i)) {
- print("bluetooth -- step request package $i");
- // 请求缺包
- ByteDataWriter writer = ByteDataWriter();
- writer.writeUint8(BLE_UPDATE.STEP);
- writer.writeUint16(i);
- write(BLE.BLE_Client_T_UPDATE, writer.toBytes());
- }
- }
- });
- Timer timeout = Timer(Duration(seconds: 20), () {
- if (_completerStep?.isCompleted != true) _completerStep?.complete(false);
- });
- var result = await _completerStep!.future;
- timeout.cancel();
- timer.cancel();
- int stepTotal = 0;
- if (result == true) {
- await _saveInfo(_partInfo);
- int code = await _uploadInfo(_partInfo!.start);
- if (isDebugShoe) {
- var now = DateTime.now();
- _partInfo?.items.forEach((element) {
- var info = {"t": element.time, "s": element.step, "total": element.absolute};
- _testStep("${now.hour},${now.minute},${now.second},${info['t']},${info['s']},${info['total']}");
- });
- }
- if (test == true) {
- if (_partInfo?.items.isNotEmpty == true) {
- stepTotal = _partInfo?.items.map((e) => e.step).reduce((value, element) => value + element) ?? 0;
- } else {
- stepTotal = 0;
- }
- }
- if (code == 0) {
- var timer = Timer.periodic(Duration(milliseconds: 1000), (timer) {
- write(BLE.BLE_Client_T_UPDATE, createTime(BLE_UPDATE.STEP_DELETE));
- });
- Timer timeout = Timer(Duration(seconds: 60), () {
- if (_completerStepDel?.isCompleted != true) _completerStepDel?.complete(false);
- });
- await _completerStepDel!.future;
- timer.cancel();
- timeout.cancel();
- }
- _completerStepDel = null;
- }
- _partInfo = null;
- print("bluetooth -- step reset");
- stepNotifier.value = stepTotal;
- }
- // 固件升级
- Future<bool> setupDeviceVer(int type) async {
- _completerSetupDeviceVer = Completer();
- try {
- write(BLE.BLE_Client_T_DFU, Uint8List.fromList([type]));
- } catch (e) {
- print(e);
- }
- Timer timeout = Timer(Duration(seconds: 10), () {
- if (_completerSetupDeviceVer?.isCompleted != true) _completerSetupDeviceVer?.complete(false);
- });
- var result = (await _completerSetupDeviceVer?.future) ?? false;
- timeout.cancel();
- return result;
- }
- // 游戏模式
- Future setupGameMode(bool mode) async {
- if (mode == false && h5gameRNotifier.value == true) {
- return;
- }
- gameModeTimer?.cancel();
- if (mode) {
- gameModeTimer = Timer.periodic(Duration(seconds: 60), (timer) {
- if (this._listen == true) write(BLE.BLE_Client_T_GAMEMODE, Uint8List.fromList([BLE_CODE_1]));
- });
- }
- await write(BLE.BLE_Client_T_GAMEMODE, mode ? Uint8List.fromList([BLE_CODE_1]) : Uint8List.fromList([BLE_CODE_0]));
- }
- Future setupGameMode4h5(bool mode) async {
- h5gameRNotifier.value = mode;
- setupGameMode(mode);
- }
- Future setupDataDebug(bool mode) async {
- await write(BLE.BLE_Client_T_GAMEMODE, mode ? Uint8List.fromList([BLE_CODE_1 + 1]) : Uint8List.fromList([BLE_CODE_0]));
- //
- // device?.rssi.listen((event) {
- // rssiNotifier.value = event;
- // });
- //
- // rssiTimer?.cancel();
- // if (mode == true) {
- // rssiTimer = Timer.periodic(Duration(seconds: 1), (timer) {
- // device?.requestRssi();
- // });
- // }
- }
- Future vibrate(int vibrate, {int leftOrRight = 0}) async {
- int duration = min(1000, max(100, vibrate));
- ByteDataWriter writer = ByteDataWriter();
- writer.writeUint16(duration);
- writer.writeUint8(leftOrRight);
- await write(BLE.BLE_Client_T_SHOCK, writer.toBytes());
- }
- Future lighting(int time) async {
- int duration = min(10000, max(100, time));
- ByteDataWriter writer = ByteDataWriter();
- writer.writeUint16(duration);
- await write(BLE.BLE_Client_T_LIGHTING, writer.toBytes());
- }
- Future stepRealTime(bool mode) async {
- stepRealtimeNotifier.value = -1;
- stepRealtimePageNotifier.value = mode;
- await write(BLE.BLE_Client_T_REALTIMESTEP, mode ? Uint8List.fromList([BLE_CODE_1]) : Uint8List.fromList([BLE_CODE_0]));
- stepRealTimeTimer?.cancel();
- if (mode == true) {
- stepRealTimeTimer = Timer.periodic(Duration(seconds: 10), (timer) {
- write(BLE.BLE_Client_T_REALTIMESTEP, Uint8List.fromList([BLE_CODE_1]));
- });
- }
- }
- Uint8List createTime(int cmd) {
- DateTime now = DateTime.now();
- DateTime offset = DateTime(now.year, now.month, now.day, now.hour);
- print("create now .. $now - $offset ($offset.millisecondsSinceEpoch)");
- ByteDataWriter writer = ByteDataWriter();
- writer.writeUint8(cmd);
- writer.writeUint64(offset.millisecondsSinceEpoch);
- writer.writeUint8(max(0, min(60, now.minute - offset.minute)));
- return writer.toBytes();
- }
- Future write(int cmd, Uint8List data) async {
- if (characteristicWrite == null) return;
- int length = data.length + 5;
- ByteDataWriter writer = ByteDataWriter();
- writer.writeUint8(0xAA);
- // writer.writeUint8(0xBB);
- // writer.writeUint8(0xCC);
- writer.writeUint8(length);
- writer.writeUint8(0xFF - length);
- // writer.writeUint8(0x00);
- writer.writeUint8(cmd);
- if (data.isNotEmpty) writer.write(data);
- int ver = writer.toBytes().reduce((value, element) => value + element);
- writer.writeUint8(ver);
- Uint8List out = writer.toBytes();
- print("out $out");
- // print("out ${out.map((e) => e.toRadixString(16)).join(",")}");
- for (var i = 0; i < 10; i++) {
- try {
- await flutterReactiveBle.writeCharacteristicWithoutResponse(characteristicWrite!, value: out);
- break;
- } catch (e) {
- print(e);
- await Future.delayed(Duration(milliseconds: 100));
- }
- }
- }
- Future writeUintList(Uint8List data) async {
- if (characteristicWrite == null) return;
- int length = data.length + 4;
- ByteDataWriter writer = ByteDataWriter();
- writer.writeUint8(0xAA);
- // writer.writeUint8(0xBB);
- // writer.writeUint8(0xCC);
- writer.writeUint8(length);
- writer.writeUint8(0xFF - length);
- // writer.writeUint8(0x00);
- if (data.isNotEmpty) writer.write(data);
- int ver = writer.toBytes().reduce((value, element) => value + element);
- writer.writeUint8(ver);
- Uint8List out = writer.toBytes();
- print("out $out");
- for (var i = 0; i < 10; i++) {
- try {
- await flutterReactiveBle.writeCharacteristicWithoutResponse(characteristicWrite!, value: out);
- break;
- } catch (e) {
- print(e);
- await Future.delayed(Duration(milliseconds: 10));
- }
- }
- }
- _uploadLog() async {
- DiscoveredDevice? device = this.device;
- if (device == null) return;
- var info = infoNotifier.value;
- if (info.isEmpty == true) return;
- final api = GetIt.I<RestClient>();
- PackageInfo packageInfo = await PackageInfo.fromPlatform();
- DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
- String os_name = Platform.operatingSystem;
- String os_ver = Platform.operatingSystemVersion;
- String phone_brand = "";
- String phone_model = "";
- if (Platform.isAndroid) {
- AndroidDeviceInfo androidDeviceInfo = await deviceInfo.androidInfo;
- phone_brand = androidDeviceInfo.brand;
- phone_model = androidDeviceInfo.model;
- } else if (Platform.isIOS) {
- IosDeviceInfo iosDeviceInfo = await deviceInfo.iosInfo;
- phone_brand = iosDeviceInfo.name;
- phone_model = iosDeviceInfo.model;
- }
- api.onConnBt("${info['mac']}", "${info['softwareVer']}", "${info['hardwareVer']}", "${packageInfo.version}", os_name, os_ver, "${locale?.languageCode}", phone_brand, phone_model).then((value) => _uploadLoged = true);
- }
- _testErrLog() async {
- Directory? dir = Platform.isAndroid ? await getExternalStorageDirectory() : await getTemporaryDirectory();
- if (dir != null) {
- var now = DateTime.now();
- File file = File("${dir.path}/shoe/err_${now.year}_${now.month}_${now.day}.csv");
- print("log file: $file $errQueue");
- if (!file.parent.existsSync()) {
- file.parent.createSync();
- }
- errQueue.forEach((element) {
- file.writeAsStringSync("$element\n", mode: FileMode.append, flush: true);
- });
- }
- }
- void _testElectricity(Map<String, dynamic> info) async {
- Directory? dir = Platform.isAndroid ? await getExternalStorageDirectory() : await getTemporaryDirectory();
- if (dir != null) {
- var now = DateTime.now();
- File file = File("${dir.path}/shoe/electricity_${now.year}_${now.month}_${now.day}.csv");
- print("log file: $file");
- if (!file.parent.existsSync()) {
- file.parent.createSync();
- }
- file.writeAsStringSync("${now.hour},${now.minute},${now.second},${info['0_electricity']},${info['1_electricity']},${info['0_adc']},${info['1_adc']}\n", mode: FileMode.append, flush: true);
- }
- }
- void _testStep(String line) async {
- Directory? dir = Platform.isAndroid ? await getExternalStorageDirectory() : await getTemporaryDirectory();
- if (dir != null) {
- var now = DateTime.now();
- File file = File("${dir.path}/shoe/step_${now.year}_${now.month}_${now.day}.csv");
- print("log file: $file");
- if (!file.parent.existsSync()) {
- file.parent.createSync();
- }
- file.writeAsStringSync("$line\n", mode: FileMode.append, flush: true);
- }
- }
- }
- class PartItem {
- int step;
- int distance;
- int absolute;
- int time;
- PartItem(this.step, this.absolute, this.distance, this.time);
- Map<String, dynamic> toJson() {
- final Map<String, dynamic> data = new Map<String, dynamic>();
- data['step'] = this.step;
- data['absolute'] = this.absolute;
- data['distance'] = this.distance;
- data['time'] = this.time;
- return data;
- }
- }
- class PartInfo {
- int start;
- int serial = 0;
- int serialCount;
- List<PartItem> items = [];
- late DateTime now;
- late DateTime maxTime;
- late Map<int, List<int>> data;
- bool ready = false;
- PartInfo(this.start, this.serialCount) {
- now = DateTime.now();
- maxTime = DateTime(now.year, now.month, now.day, now.hour);
- data = {};
- }
- final int offset = 60 * 60 * 1000;
- prepare() async {
- print("bluetooth -- step prepare ... ");
- if (data.isEmpty) return;
- if (start == 0) return;
- var current = data[0] ?? [];
- if (current.isEmpty) return;
- int currentStep = current.first;
- print("bluetooth -- step current ... $currentStep");
- var db = StepDB();
- var history = await db.findHistory(start);
- print("bluetooth -- step history ... $start $history");
- int startStep = 0;
- var p = PartItem(0, currentStep, 0, start - offset);
- if (history.isNotEmpty == true) {
- startStep = history.first['st'];
- if (startStep > currentStep) {
- await db.deleteAll();
- print("bluetooth -- history ... clear");
- startStep = currentStep;
- await db.insert(p);
- print("bluetooth -- step add history ... ${p.toJson()}");
- }
- } else {
- startStep = currentStep;
- await db.insert(p);
- print("bluetooth -- step add history ... ${p.toJson()}");
- }
- data[data.length] = current;
- for (var i = 1; i < data.length; i++) {
- var list = data[i] ?? [];
- for (int e in list) {
- int time = start + items.length * offset;
- int step = max(0, e - startStep);
- print("bluetooth -- step add $time $e s:$startStep step:$step");
- items.add(PartItem(step, e, 0, min(time, maxTime.millisecondsSinceEpoch)));
- startStep = e;
- }
- }
- }
- }
|