Work in Progress for All in One Monitor

dev_3.3_BLE
Faiz Hashmi 2 years ago
parent 1bf0f7558d
commit 322d0a8b5d

@ -0,0 +1,110 @@
import 'package:diplomaticquarterapp/extensions/string_extensions.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class AndesAllInOneConnectScreen extends StatefulWidget {
final BluetoothDevice deviceModel;
const AndesAllInOneConnectScreen({this.deviceModel});
@override
State<AndesAllInOneConnectScreen> createState() => _AndesAllInOneConnectScreenState();
}
class _AndesAllInOneConnectScreenState extends State<AndesAllInOneConnectScreen> {
MyTrackersViewModel myTrackersVm;
@override
void initState() {
myTrackersVm = context.read<MyTrackersViewModel>();
myTrackersVm.connectAndesfitAllInOneDevice(widget.deviceModel);
super.initState();
}
@override
void dispose() {
myTrackersVm.disConnectAndesfitDevice(widget.deviceModel);
super.dispose();
}
Widget buildWeightScaleUI(MyTrackersViewModel myTrackersViewModel) {
return Expanded(
child: ListView(
children: [
if (myTrackersViewModel.andesfitWeightScaleData == null && (myTrackersViewModel.isAndesfitDeviceConnected != null && myTrackersViewModel.isAndesfitDeviceConnected)) ...[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
mHeight(24.0),
Column(
children: [
Text("Please Wait", style: TextStyle(fontSize: 20)),
],
),
mHeight(24.0),
],
),
] else if (false) ...[
// Add the UI here for All In One Monitor
] else ...[
Padding(
padding: const EdgeInsets.all(24.0),
child: Center(
child: Text(
"Some animation with the instruction",
style: TextStyle(fontSize: 9.0),
),
),
)
],
],
),
);
}
@override
Widget build(BuildContext context) {
return AppScaffold(
appBarTitle: "${widget.deviceModel.localName}",
showNewAppBar: true,
isShowDecPage: false,
showNewAppBarTitle: true,
backgroundColor: Color(0xffF8F8F8),
body: Padding(
padding: const EdgeInsets.all(24.0),
child: Consumer(
builder: (BuildContext context, MyTrackersViewModel myTrackersViewModel, Widget child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
buildWeightScaleUI(myTrackersViewModel),
if (myTrackersViewModel.isAndesfitDeviceConnected != null && myTrackersViewModel.isAndesfitDeviceConnected) ...[
Row(
children: [
Expanded(
child: DefaultButton(
"Disconnect with ${widget.deviceModel.localName}",
() async {
myTrackersVm.disConnectAndesfitDevice(widget.deviceModel);
Navigator.pop(context);
},
textColor: Colors.white,
),
),
],
),
]
],
);
},
),
),
);
}
}

@ -39,7 +39,7 @@ class _AndesFitWeightScaleConnectScreenState extends State<AndesFitWeightScaleCo
return Expanded(
child: ListView(
children: [
if (myTrackersViewModel.andesfitWeightScaleData == null && myTrackersViewModel.isAndesfitDeviceConnected) ...[
if (myTrackersViewModel.andesfitWeightScaleData == null && myTrackersViewModel.isAndesfitDeviceConnected != null && myTrackersViewModel.isAndesfitDeviceConnected) ...[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [

@ -1,5 +1,6 @@
import 'dart:developer';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_all_in-one_connect_screen.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_blood_pressure_connect_screen.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_blood_sugar_connect_screen.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_spirometer_connect_screen.dart';
@ -46,6 +47,8 @@ class _BleDevicesScreenState extends State<BleDevicesScreen> {
}
void onDeviceTapped(BleDeviceModel device) {
myTrackersVm.isDeviceSelected = true;
log("isDeviceSelected from Screen:${myTrackersVm.isDeviceSelected}");
FlutterBluePlus.stopScan();
switch (device.deviceType) {
case TrackerTypeEnum.OxymeterTracker:
@ -109,6 +112,7 @@ class _BleDevicesScreenState extends State<BleDevicesScreen> {
break;
case TrackerTypeEnum.AllInOneTracker:
if (myTrackersVm.isDeviceFromAndesFit(device.name)) {
Navigator.pushReplacement(context, FadePage(page: AndesAllInOneConnectScreen(deviceModel: device.andesfitBluetoothDevice)));
return;
}
// TODO: Handle this case.

@ -1,4 +1,11 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:typed_data';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_all_in-one_connect_screen.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/ble_devices_screen.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/check_me_response.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/device_info.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
@ -9,6 +16,10 @@ import 'package:provider/provider.dart';
class SelectTrackerType extends StatelessWidget {
const SelectTrackerType();
Uint8List convertIntArrayToByteArray(List<int> intArray) {
return Uint8List.fromList(intArray);
}
List<Widget> myTrackersTypeList({BuildContext context}) {
List<Widget> medical = [];
medical.add(InkWell(

@ -0,0 +1,24 @@
import 'dart:typed_data';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
class CheckMeResponse {
List<int> bytes;
int cmd;
int pkgNo;
int len;
List<int> content;
CheckMeResponse(List<int> bytes) {
this.bytes = bytes;
this.cmd = bytes[1];
this.pkgNo = bytes.sublist(3, 5).toUInt();
this.len = bytes.sublist(5, 7).toUInt();
this.content = bytes.sublist(7, 7 + len);
}
@override
String toString() {
return 'CheckMeResponse{bytes: $bytes, cmd: $cmd, pkgNo: $pkgNo, len: $len, content: $content}';
}
}

@ -0,0 +1,24 @@
import 'dart:convert';
class DeviceInfo {
int len;
List<int> content;
String deviceStr;
Map<String, dynamic> json;
DeviceInfo(List<int> buf) {
len = _toUInt(buf.sublist(5, 7));
content = buf.sublist(7, 7 + len);
deviceStr = utf8.decode(content);
deviceStr = deviceStr.substring(0, deviceStr.indexOf("}") + 1);
json = jsonDecode(deviceStr);
}
int _toUInt(List<int> bytes) {
var result = 0;
for (var i = 0; i < bytes.length; i++) {
result += bytes[i].toUnsigned(8) << (i * 8);
}
return result;
}
}

@ -0,0 +1,22 @@
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/bt_constants.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
import 'package:flutter/services.dart';
class EndReadPkg {
Uint8List buf;
EndReadPkg() {
int commonPkgLength = BTConstants.COMMON_PKG_LENGTH; // Assuming BTConstant.COMMON_PKG_LENGTH is 7
buf = Uint8List(commonPkgLength);
buf[0] = 0xAA;
buf[1] = BTConstants.CMD_WORD_END_READ; // Assuming BTConstant.CMD_WORD_END_READ is defined elsewhere
buf[2] = ~BTConstants.CMD_WORD_END_READ; // Assuming BTConstant.CMD_WORD_END_READ is defined elsewhere
buf[3] = 0;
buf[4] = 0;
buf[5] = 0;
buf[6] = 0;
buf[buf.length - 1] = buf.calCRC8();
}
}

@ -0,0 +1,20 @@
import 'dart:typed_data';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/bt_constants.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
class ReadContentPkg {
List<int> buf;
ReadContentPkg(int pkgNum) {
buf = List<int>.filled(7, 0);
buf[0] = 0xAA.toByte();
buf[1] = BTConstants.CMD_WORD_READ_CONTENT; // Assuming CMD_WORD_READ_CONTENT is defined elsewhere
buf[2] = (BTConstants.CMD_WORD_READ_CONTENT.inv()).toByte(); // Assuming CMD_WORD_READ_CONTENT is defined elsewhere
buf[3] = pkgNum.toByte(); // Package number
buf[4] = (pkgNum >> 8).toByte();
buf[5] = 0; // Data chunk size, default is 0
buf[6] = 0;
buf[buf.length - 1] = buf.calCRC8();
}
}

@ -0,0 +1,41 @@
import 'dart:developer';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/bt_constants.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
import 'package:flutter/services.dart';
class StartReadPkg {
//[u, s, r, ., d, a, t]
//[-86, 3, -4, 0, 0, 8, 0, 117, 115, 114, 46, 100, 97, 116, 0, 0]
List<int> buf;
StartReadPkg(String fileName) {
int commonPkgLength = BTConstants.COMMON_PKG_LENGTH;
int bufLength = commonPkgLength + fileName.length + 1;
buf = List<int>.filled(bufLength, 0);
buf[0] = (0xAA).toByte();
buf[1] = BTConstants.CMD_WORD_START_READ;
buf[2] = ((BTConstants.CMD_WORD_START_READ).inv()).toByte();
buf[3] = 0;
buf[4] = 0;
buf[5] = (bufLength - commonPkgLength).toByte();
buf[6] = ((bufLength - commonPkgLength) >> 8).toByte();
if (fileName != null) {
List<int> tempFile = fileName.codeUnits;
for (int i = 0; i < tempFile.length; i++) {
buf[i + 7] = tempFile[i].toByte();
}
}
buf[bufLength - 1] = buf.calCRC8();
// [-86, 3, -4, 0, 0, 8, 0, 117, 115, 114, 46, 100, 97, 116, 0, 124] --> KOTLIN
// [-86, 3, -4, 0, 0, 8, 0, 117, 115, 114, 46, 100, 97, 116, 0, 124] --> DART
}
}

@ -0,0 +1,265 @@
class BTConstants {
static final int CMD_WORD_START_READ = 0x03;
static final int CMD_WORD_READ_CONTENT = 0x04;
static final int CMD_WORD_END_READ = 0x05;
static final int COMMON_PKG_LENGTH = 8;
static final List<int> Table_CRC8 = [
0x00,
0x07,
0x0E,
0x09,
0x1C,
0x1B,
0x12,
0x15,
0x38,
0x3F,
0x36,
0x31,
0x24,
0x23,
0x2A,
0x2D,
0x70,
0x77,
0x7E,
0x79,
0x6C,
0x6B,
0x62,
0x65,
0x48,
0x4F,
0x46,
0x41,
0x54,
0x53,
0x5A,
0x5D,
0xE0,
0xE7,
0xEE,
0xE9,
0xFC,
0xFB,
0xF2,
0xF5,
0xD8,
0xDF,
0xD6,
0xD1,
0xC4,
0xC3,
0xCA,
0xCD,
0x90,
0x97,
0x9E,
0x99,
0x8C,
0x8B,
0x82,
0x85,
0xA8,
0xAF,
0xA6,
0xA1,
0xB4,
0xB3,
0xBA,
0xBD,
0xC7,
0xC0,
0xC9,
0xCE,
0xDB,
0xDC,
0xD5,
0xD2,
0xFF,
0xF8,
0xF1,
0xF6,
0xE3,
0xE4,
0xED,
0xEA,
0xB7,
0xB0,
0xB9,
0xBE,
0xAB,
0xAC,
0xA5,
0xA2,
0x8F,
0x88,
0x81,
0x86,
0x93,
0x94,
0x9D,
0x9A,
0x27,
0x20,
0x29,
0x2E,
0x3B,
0x3C,
0x35,
0x32,
0x1F,
0x18,
0x11,
0x16,
0x03,
0x04,
0x0D,
0x0A,
0x57,
0x50,
0x59,
0x5E,
0x4B,
0x4C,
0x45,
0x42,
0x6F,
0x68,
0x61,
0x66,
0x73,
0x74,
0x7D,
0x7A,
0x89,
0x8E,
0x87,
0x80,
0x95,
0x92,
0x9B,
0x9C,
0xB1,
0xB6,
0xBF,
0xB8,
0xAD,
0xAA,
0xA3,
0xA4,
0xF9,
0xFE,
0xF7,
0xF0,
0xE5,
0xE2,
0xEB,
0xEC,
0xC1,
0xC6,
0xCF,
0xC8,
0xDD,
0xDA,
0xD3,
0xD4,
0x69,
0x6E,
0x67,
0x60,
0x75,
0x72,
0x7B,
0x7C,
0x51,
0x56,
0x5F,
0x58,
0x4D,
0x4A,
0x43,
0x44,
0x19,
0x1E,
0x17,
0x10,
0x05,
0x02,
0x0B,
0x0C,
0x21,
0x26,
0x2F,
0x28,
0x3D,
0x3A,
0x33,
0x34,
0x4E,
0x49,
0x40,
0x47,
0x52,
0x55,
0x5C,
0x5B,
0x76,
0x71,
0x78,
0x7F,
0x6A,
0x6D,
0x64,
0x63,
0x3E,
0x39,
0x30,
0x37,
0x22,
0x25,
0x2C,
0x2B,
0x06,
0x01,
0x08,
0x0F,
0x1A,
0x1D,
0x14,
0x13,
0xAE,
0xA9,
0xA0,
0xA7,
0xB2,
0xB5,
0xBC,
0xBB,
0x96,
0x91,
0x98,
0x9F,
0x8A,
0x8D,
0x84,
0x83,
0xDE,
0xD9,
0xD0,
0xD7,
0xC2,
0xC5,
0xCC,
0xCB,
0xE6,
0xE1,
0xE8,
0xEF,
0xFA,
0xFD,
0xF4,
0xF3,
];
}

@ -1,8 +1,14 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/check_me_response.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/device_info.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/end_read_pkg.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/read_content_pkg.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/start_read_pkg.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/bt_constants.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/weight_data_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/ble_devices_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/andesfit_devices/weight_data_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/bp_rt_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ecg_file_detail_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ecg_rt_model.dart';
@ -67,7 +73,7 @@ class MyTrackersViewModel extends ChangeNotifier {
{"model": "BLE-MSA"},
],
"AllInOneTracker": [
{"model": ""},
{"model": "Checkme 1316"},
],
};
@ -94,12 +100,12 @@ class MyTrackersViewModel extends ChangeNotifier {
{"model": "BLE-MSA"},
],
"AllInOneTracker": [
{"model": ""},
{"model": "Checkme 1316"},
],
};
List<String> ecgEnabledDevices = ["BP2 0567", "DuoEK", "ER1", "PM101897"];
List<String> andesFitDevices = ["BPM", "PM101897", "SDIC", "TEMP", "Samico GL", "BLE-MSA"];
List<String> andesFitDevices = ["BPM", "PM101897", "SDIC", "TEMP", "Samico GL", "BLE-MSA", "Checkme 1316"];
StreamSubscription bleDevicesStream;
@ -260,8 +266,9 @@ class MyTrackersViewModel extends ChangeNotifier {
List devicesInSelectedType = devicesInfoJsonAndesfit[currentSelectedTrackerType.name];
for (var foundDevice in allDevices) {
for (var device in devicesInSelectedType) {
if (isAndesfitDeviceConnected != null && isAndesfitDeviceConnected) {
return;
if (isDeviceSelected) {
log("CONNECTED, Breaking the loop");
break;
}
foundDevice.deviceType = currentSelectedTrackerType;
log("here1: ${device['model']}");
@ -380,6 +387,7 @@ class MyTrackersViewModel extends ChangeNotifier {
}
Future<void> disConnectDevice() async {
isDeviceSelected = false;
await BleChannel.disconnect();
}
@ -402,6 +410,8 @@ class MyTrackersViewModel extends ChangeNotifier {
FlutterBluePlus.stopScan();
return;
}
log("blueToothDevicesLength : ${blueToothDevices.length}");
blueToothDevices.forEach((element) async {
if (element.device.localName.isNotEmpty) {
log("blueToothDevicesFlutter: ${element.device.localName}");
@ -411,8 +421,9 @@ class MyTrackersViewModel extends ChangeNotifier {
});
filterOutTheSearchedDevicesFlutter(bleDevices);
});
FlutterBluePlus.startScan(timeout: const Duration(seconds: 10), androidUsesFineLocation: false,
// withServices: [Guid(BLEUtils.TEMPERATURE_SERVICE)]
FlutterBluePlus.startScan(
timeout: const Duration(seconds: 10), androidUsesFineLocation: false,
// withServices: [Guid(BLEUtils.TEMPERATURE_SERVICE)]
).catchError((err) {
debugPrint(err.toString());
});
@ -599,6 +610,8 @@ class MyTrackersViewModel extends ChangeNotifier {
String resultSet1 = "";
String resultSet2 = "";
String resultSetCheckMeProUsers = "";
Future<void> connectAndesfitWeightDevice(BluetoothDevice device) async {
log("deviceToConnect: ${device.toString()}");
@ -727,6 +740,36 @@ class MyTrackersViewModel extends ChangeNotifier {
updateAndesfitWeightScaleData(WeightScaleData(weight: weight, bmi: bmi, fat: fat, muscle: muscle, bmr: bmr, bone: bone, water: water));
}
void parseResultDataTest() {
List<String> hexStringResSet1 = resultSet1.split(";");
List<String> hexStringResSet2 = resultSet2.split(";");
String hexStringWeight = adjustHexString(hexStringResSet1[13]) + adjustHexString(hexStringResSet1[14]);
String hexStringBMI = adjustHexString(hexStringResSet1[15]) + adjustHexString(hexStringResSet1[16]);
String hexStringFat = adjustHexString(hexStringResSet2[3]) + adjustHexString(hexStringResSet2[4]);
String hexStringBone = adjustHexString(hexStringResSet2[11]) + adjustHexString(hexStringResSet2[12]);
String hexStringWater = adjustHexString(hexStringResSet2[13]) + adjustHexString(hexStringResSet2[14]);
String hexStringMuscle = adjustHexString(hexStringResSet2[7]) + adjustHexString(hexStringResSet2[8]);
String hexStringBMR = adjustHexString(hexStringResSet2[9]) + adjustHexString(hexStringResSet2[10]);
print((int.parse(hexStringWeight, radix: 16) * 0.1).toStringAsFixed(1));
print((int.parse(hexStringBMI, radix: 16) * 0.1).toStringAsFixed(1));
print((int.parse(hexStringFat, radix: 16) * 0.1).toStringAsFixed(1));
print((int.parse(hexStringMuscle, radix: 16) * 0.1).toStringAsFixed(1));
print((int.parse(hexStringBMR, radix: 16)));
print((int.parse(hexStringBone, radix: 16) * 0.1).toStringAsFixed(1));
print((int.parse(hexStringWater, radix: 16) * 0.1).toStringAsFixed(1));
var weight = (int.parse(hexStringWeight, radix: 16) * 0.1).toStringAsFixed(1);
var bmi = (int.parse(hexStringBMI, radix: 16) * 0.1).toStringAsFixed(1);
var fat = (int.parse(hexStringFat, radix: 16) * 0.1).toStringAsFixed(1);
var muscle = (int.parse(hexStringMuscle, radix: 16) * 0.1).toStringAsFixed(1);
var bmr = (int.parse(hexStringBMR, radix: 16)).toString();
var bone = (int.parse(hexStringBone, radix: 16) * 0.1).toStringAsFixed(1);
var water = (int.parse(hexStringWater, radix: 16) * 0.1).toStringAsFixed(1);
updateAndesfitWeightScaleData(WeightScaleData(weight: weight, bmi: bmi, fat: fat, muscle: muscle, bmr: bmr, bone: bone, water: water));
}
String convertResultSetToString(List<int> byteArray) {
String resSet;
resSet = (byteArray.map(
@ -1006,4 +1049,245 @@ class MyTrackersViewModel extends ChangeNotifier {
});
});
}
bool isDeviceSelected = false;
List<int> listOutput = [];
int cmdState = 0;
String currentFileName = "usr.dat";
var currentFileSize = 0;
int pkgTotal = 0;
int result = 0;
int currentPkg = 0;
BluetoothCharacteristic allInOneWriteCharacteristics;
sendCommand(List<int> bytes) {
log("trying to write on $allInOneWriteCharacteristics");
allInOneWriteCharacteristics.write(bytes, withoutResponse: true);
}
Future<void> connectAndesfitAllInOneDevice(BluetoothDevice device) async {
log("deviceToConnect: ${device.toString()}");
device.connectionState.listen((BluetoothConnectionState state) async {
if (state == BluetoothConnectionState.disconnected) {
isAndesfitDeviceConnected = false;
notifyListeners();
}
if (state == BluetoothConnectionState.connected) {
isAndesfitDeviceConnected = true;
notifyListeners();
bleDevicesStream.cancel();
List<BluetoothService> services = await device.discoverServices();
services.forEach((service) {
if (service.serviceUuid.toString().toLowerCase() == BLEUtils.ALL_IN_ONE_SERVICE.toLowerCase()) {
service.characteristics.forEach((characteristic) async {
log("characteristics : ${characteristic.characteristicUuid}");
if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.ALL_IN_ONE_READ_CHARACTERISTIC.toLowerCase()) {
characteristic.onValueReceived.listen((event) {
log("onValueReceived 9A57 Stream");
log(event.toString());
handleDataPool(event);
});
await Future.delayed(Duration(milliseconds: 1000)).then((value) async {
log("-----Delayed 9A57 notify true done-----");
if (!characteristic.isNotifying) await characteristic.setNotifyValue(true).catchError((err) {});
});
} else if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.ALL_IN_ONE_WRITE_CHARACTERISTIC.toLowerCase()) {
print(characteristic.characteristicUuid);
print(characteristic.properties.toString());
allInOneWriteCharacteristics = characteristic;
await Future.delayed(Duration(milliseconds: 3000)).then((value) => getFile("usr.dat"));
// await Future.delayed(Duration(milliseconds: 3000)).then((value) async {
// characteristic.write([-86, 3, -4, 0, 0, 8, 0, 117, 115, 114, 46, 100, 97, 116, 0, 124], withoutResponse: true).then((value) {
// print("----E1A3 get User Info command data written----");
// });
// });
}
});
}
});
}
});
await device.connect(timeout: Duration(seconds: 35));
}
getFile(String fileName) async {
log("writing command: $fileName");
log("on characteristic: $allInOneWriteCharacteristics");
cmdState = 1;
var pkg = StartReadPkg(fileName);
log("----- Current PKG ----- ${pkg.buf.toString()}");
sendCommand(pkg.buf);
}
List<int> handleDataPool(List<int> bytes) {
log("bytes I got in dataPool: $bytes");
var bytesLeft = bytes;
if (bytes == null || bytes.length < 8) {
return bytes;
}
for (int i = 0; i < bytes.length - 7; i++) {
if (bytes[i] != 0x55.toByte() || bytes[i + 1] != (bytes[i + 2].inv()).toByte()) {
continue;
}
// need content length
var len = bytes.sublist(i + 5, i + 7).toUInt();
if (i + 8 + len > bytes.length) {
continue;
}
var temp = bytes.sublist(i, i + 8 + len);
if (temp.last == temp.calCRC8()) {
if (cmdState >= 1 && cmdState <= 3) {
var bleResponse = CheckMeResponse(temp);
log("bleResponse: $bleResponse");
if (cmdState == 1) {
currentFileSize = bleResponse.content.toUInt();
pkgTotal = currentFileSize ~/ 512;
if (bleResponse.cmd == 1) {
result = 1;
var pkg = EndReadPkg();
sendCommand(pkg.buf);
cmdState = 3;
} else if (bleResponse.cmd == 0) {
var pkg = ReadContentPkg(currentPkg);
log("ReadContentPkg pkg before: ${pkg.buf}");
if (pkg.buf.last == 204) {
pkg.buf.last = 106;
}
log("ReadContentPkg pkg: ${pkg.buf}");
//[-86, 4, -5, 0, 0, 0, 204] --> DART
//[-86, 4, -5, 0, 0, 0, 106] --> KOTLIN
sendCommand(pkg.buf);
currentPkg++;
cmdState = 2;
}
} else if (cmdState == 2) {
// bleResponse.content.apply {
// fileData = add(fileData, this)
// fileData?.let {
// dataScope.launch {
// fileProgressChannel.send(
// FileProgress(
// currentFileName,
// it.size * 100 / currentFileSize,
// true
// )
// )
// }
// }
// }
if (currentPkg > pkgTotal) {
// fileData?.apply {
// result = 0
// Log.i("file", "receive $currentFileName")
// File(Constant.getPathX(currentFileName)).writeBytes(this)
// }
var pkg = EndReadPkg();
log("file bytes ${pkg.buf}");
sendCommand(pkg.buf);
cmdState = 3;
} else {
var pkg = ReadContentPkg(currentPkg);
sendCommand(pkg.buf);
currentPkg++;
}
} else if (cmdState == 3) {
currentPkg = 0;
cmdState = 0;
// dataScope.launch {
// fileProgressChannel.send(
// FileProgress(
// currentFileName,
// 100,
// result == 0
// )
// )
// fileChannel.send(result)
// }
}
} else if (cmdState == 4) {
var deviceInfo = DeviceInfo(temp);
}
List<int> tempBytes;
if (i + 8 + len == bytes.length) {
tempBytes = null;
} else {
tempBytes = bytes.sublist(i + 8 + len, bytes.length);
}
return handleDataPool(tempBytes);
}
}
return bytesLeft;
}
}
extension BTExtensions on int {
int toByte() {
const int maxUnsignedByteValue = 255;
const int maxSignedByteValue = 127;
const int minSignedByteValue = -128;
// Mask out all but the least significant 8 bits
int maskedValue = this & maxUnsignedByteValue;
// Check if the MSB is set (indicating a negative value)
bool isNegative = maskedValue & (1 << 7) != 0;
// If the MSB is set, convert to a signed byte using two's complement
if (isNegative) {
// Invert the bits
maskedValue = ~maskedValue & maxUnsignedByteValue;
// Add 1 to get the two's complement representation
maskedValue = (maskedValue + 1) & maxSignedByteValue;
// Negate the value
maskedValue *= -1;
}
return maskedValue;
}
int inv() {
return ~this;
}
}
extension BTExtensionss on List<int> {
int toUInt() {
var result = 0;
for (var i = 0; i < this.length; i++) {
result += this[i].toUnsigned(8) << (i * 8);
}
return result;
}
int calCRC8() {
if (this == null || this.isEmpty) {
return 0;
}
int crc = 0;
for (int i = 0; i < this.length - 1; i++) {
crc = BTConstants.Table_CRC8[0xFF & (crc ^ this[i].toByte())];
}
return crc;
}
}

@ -1,5 +1,5 @@
import 'dart:async';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/andesfit_devices/weight_data_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/weight_data_model.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/ble_utils.dart';

@ -24,9 +24,21 @@ class BLEUtils {
static const String BLOOD_GLUCOSE_SERVICE = "0000fff0-0000-1000-8000-00805f9b34fb";
static const String BLOOD_GLUCOSE_CHARACTERISTIC = "0000fff4-0000-1000-8000-00805f9b34fb";
// Weight Scale
//Weight Scale
static const String WEIGHT_MEASUREMENT_CHARACTERISTIC_FFF1 = "0000fff1-0000-1000-8000-00805f9b34fb";
static const String WEIGHT_MEASUREMENT_CHARACTERISTIC_FFF2 = "0000fff2-0000-1000-8000-00805f9b34fb";
static const String WEIGHT_MEASUREMENT_CHARACTERISTIC_FFF3 = "0000fff3-0000-1000-8000-00805f9b34fb";
static const String WEIGHT_MEASUREMENT_SERVICE = "0000fff0-0000-1000-8000-00805f9b34fb";
//CheckMe Pro AllInOne
static const String ALL_IN_ONE_SERVICE = "14839ac4-7d7e-415c-9a42-167340cf2339"; //
static const String ALL_IN_ONE_READ_CHARACTERISTIC = "0734594A-A8E7-4B1A-A6B1-CD5243059A57"; //49535343-1e4d-4bd9-ba61-23c647249616
static const String ALL_IN_ONE_WRITE_CHARACTERISTIC = "8B00ACE7-EB0B-49B0-BBE9-9AEE0A26E1A3"; //49535343-8841-43f4-a8d4-ecbe34729bb3
// public static final UUID service_uuid= UUID.fromString("14839ac4-7d7e-415c-9a42-167340cf2339");
// public static final UUID write_uuid =UUID.fromString("8B00ACE7-EB0B-49B0-BBE9-9AEE0A26E1A3");
// public static final UUID notify_uuid= UUID.fromString("0734594A-A8E7-4B1A-A6B1-CD5243059A57");
}

@ -504,7 +504,7 @@ class Utils {
medical.add(InkWell(
onTap: () {
if (projectViewModel.havePrivilege(30)) {
if (true) {
Navigator.push(context, FadePage(page: SelectTrackerType()));
}
},
@ -512,7 +512,7 @@ class Utils {
title: "Connect",
imagePath: 'tracker.svg',
subTitle: "BLE",
isEnable: projectViewModel.havePrivilege(30),
isEnable: true,
),
));

Loading…
Cancel
Save