BP tracker Integration Completed

dev_3.3_BLE
Faiz Hashmi 2 years ago
parent 886677d97e
commit 6e97f8556f

@ -1,25 +1,16 @@
package com.ejada.hmg package com.ejada.hmg
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.ContentResolver
import android.media.AudioAttributes
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.os.Build
import android.view.WindowManager import android.view.WindowManager
import androidx.annotation.NonNull;
import com.ejada.hmg.utils.* import com.ejada.hmg.utils.*
import com.ejada.hmg.* import com.ejada.hmg.*
import io.flutter.embedding.android.FlutterFragmentActivity import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant import io.flutter.plugins.GeneratedPluginRegistrant
import com.lepu.blepro.observer.BleChangeObserver import com.lepu.blepro.observer.BleChangeObserver
class MainActivity : FlutterFragmentActivity(), BleChangeObserver { @Suppress("DEPRECATION")
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { class MainActivity : FlutterFragmentActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine); GeneratedPluginRegistrant.registerWith(flutterEngine);
@ -50,11 +41,11 @@ class MainActivity : FlutterFragmentActivity(), BleChangeObserver {
} }
override fun onBleStateChanged(model: Int, state: Int) { // override fun onBleStateChanged(model: Int, state: Int) {
//println( "model $model, state: $state") // println("onBleStateChanged")
// _bleState.value = state == Ble.State.CONNECTED // println("model $model, state: $state")
// Log.d(TAG, "bleState $bleState") //
} // }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()

@ -1,17 +1,8 @@
package com.ejada.hmg.utils package com.ejada.hmg.utils
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.Intent.getIntent
import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.provider.Settings
import android.util.Log
import android.widget.Toast
import androidx.core.app.ActivityCompat.startActivityForResult
import com.ejada.hmg.MainActivity import com.ejada.hmg.MainActivity
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
@ -20,13 +11,11 @@ import io.flutter.plugin.common.EventChannel
import android.util.SparseArray import android.util.SparseArray
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import com.cloud.diplomaticquarterapp.ble.utils.EcgData import com.cloud.diplomaticquarterapp.ble.utils.EcgData
import com.cloud.diplomaticquarterapp.ble.utils.RTBP2Data
import com.google.gson.Gson import com.google.gson.Gson
//Ble //Ble
import com.jeremyliao.liveeventbus.LiveEventBus import com.jeremyliao.liveeventbus.LiveEventBus
import com.lepu.blepro.constants.Ble
import com.lepu.blepro.event.EventMsgConst import com.lepu.blepro.event.EventMsgConst
import com.lepu.blepro.event.EventMsgConst.Ble.* import com.lepu.blepro.event.EventMsgConst.Ble.*
import com.lepu.blepro.event.InterfaceEvent import com.lepu.blepro.event.InterfaceEvent
@ -39,18 +28,15 @@ import com.lepu.blepro.ext.er2.DeviceInfo
import com.lepu.blepro.ext.er2.Er2EcgFile import com.lepu.blepro.ext.er2.Er2EcgFile
import com.lepu.blepro.ext.er2.Er2File import com.lepu.blepro.ext.er2.Er2File
import com.lepu.blepro.ext.er2.RtData import com.lepu.blepro.ext.er2.RtData
import com.lepu.blepro.ext.bp2.*
import com.lepu.blepro.ext.pc60fw.RtParam import com.lepu.blepro.ext.pc60fw.RtParam
import com.lepu.blepro.objs.Bluetooth import com.lepu.blepro.objs.Bluetooth
import com.lepu.blepro.objs.BluetoothController import com.lepu.blepro.objs.BluetoothController
import com.lepu.blepro.observer.BleChangeObserver
import com.lepu.blepro.utils.DateUtil import com.lepu.blepro.utils.DateUtil
import com.lepu.blepro.utils.Er1Decompress import com.lepu.blepro.utils.Er1Decompress
import io.flutter.plugin.common.EventChannel.EventSink import kotlin.reflect.KFunction2
import no.nordicsemi.android.ble.observer.ConnectionObserver
class BleBridge( class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivity: MainActivity) {
private var flutterEngine: FlutterEngine, private var mainActivity: MainActivity
) {
private lateinit var channel: MethodChannel private lateinit var channel: MethodChannel
private lateinit var Echannel: EventChannel private lateinit var Echannel: EventChannel
@ -196,14 +182,16 @@ class BleBridge(
result.notImplemented() result.notImplemented()
} }
} }
Echannel.setStreamHandler(object : EventChannel.StreamHandler { Echannel.setStreamHandler(
object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, eventSink: EventChannel.EventSink?) { override fun onListen(arguments: Any?, eventSink: EventChannel.EventSink?) {
this@BleBridge.eventSink = eventSink this@BleBridge.eventSink = eventSink
} }
override fun onCancel(arguments: Any?) { override fun onCancel(arguments: Any?) {
} }
}) },
)
} }
@ -214,8 +202,17 @@ class BleBridge(
BleServiceHelper.BleServiceHelper.disconnect(false) BleServiceHelper.BleServiceHelper.disconnect(false)
} }
private fun scanDevice(methodCall: MethodCall, result: MethodChannel.Result) { private fun scanDevice(methodCall: MethodCall, result: MethodChannel.Result) {
println("This is Test of Scanning")
LiveEventBus.get<Boolean>(EventMsgConst.Ble.EventServiceConnectedAndInterfaceInit).observe(this.mainActivity) {
// BleService init success
println("EventServiceConnectedAndInterfaceInit---------")
BleServiceHelper.BleServiceHelper.startScan(models)
println("EventServiceConnectedAndInterfaceInit")
}
LiveEventBus.get<Boolean>(EventMsgConst.Ble.EventServiceConnectedAndInterfaceInit).observe(this.mainActivity) { LiveEventBus.get<Boolean>(EventMsgConst.Ble.EventServiceConnectedAndInterfaceInit).observe(this.mainActivity) {
// BleService init success // BleService init success
println("EventServiceConnectedAndInterfaceInit---------") println("EventServiceConnectedAndInterfaceInit---------")
@ -225,11 +222,13 @@ class BleBridge(
LiveEventBus.get<Bluetooth>(EventMsgConst.Discovery.EventDeviceFound).observe(this.mainActivity) { LiveEventBus.get<Bluetooth>(EventMsgConst.Discovery.EventDeviceFound).observe(this.mainActivity) {
var deviceName: String = "" var deviceName: String = ""
for (b in BluetoothController.getDevices()) { for (b in BluetoothController.getDevices()) {
// println(b.name) println(b.name)
//TODO: UNCOMMENT THIS
// if (b.name.contains("POD-1_SN8187", true) || b.name.contains( // if (b.name.contains("POD-1_SN8187", true) || b.name.contains(
// "O2M 1670", true // "O2M 1670", true
// ) || b.name.contains("DuoEK", true) || b.name.contains("BP2", true) // ) || b.name.contains("DuoEK", true) || b.name.contains("BP2", true)
// // ) {
if (b.name.contains("BP2", true)) { if (b.name.contains("BP2", true)) {
println("connecting bp2") println("connecting bp2")
@ -241,6 +240,7 @@ class BleBridge(
BleServiceHelper.BleServiceHelper.connect( BleServiceHelper.BleServiceHelper.connect(
this.mainActivity.applicationContext, b.model, b.device this.mainActivity.applicationContext, b.model, b.device
) )
} }
} }
@ -260,6 +260,7 @@ class BleBridge(
val data = it.data as DeviceInfo val data = it.data as DeviceInfo
println("DuoEK INFO DATA: $data") println("DuoEK INFO DATA: $data")
val returnData = mapOf("type" to "infoData", "data" to data.toString()) val returnData = mapOf("type" to "infoData", "data" to data.toString())
eventSink?.success(returnData) eventSink?.success(returnData)
} }
LiveEventBus.get<InterfaceEvent>(InterfaceEvent.ER2.EventEr2FileList).observe(this.mainActivity) { LiveEventBus.get<InterfaceEvent>(InterfaceEvent.ER2.EventEr2FileList).observe(this.mainActivity) {
@ -357,7 +358,7 @@ class BleBridge(
LiveEventBus.get<InterfaceEvent>(InterfaceEvent.BP2.EventBp2Info).observe(this.mainActivity) { LiveEventBus.get<InterfaceEvent>(InterfaceEvent.BP2.EventBp2Info).observe(this.mainActivity) {
val data = it.data as com.lepu.blepro.ext.bp2.DeviceInfo val data = it.data as com.lepu.blepro.ext.bp2.DeviceInfo
println("BP2 INFO DATA: $data") println("BP2 INFO DATA: $data")
val returnData = mapOf("type" to "infoData", "data" to data.toString()) val returnData = mapOf("type" to "infoData", "data" to data.toString(), "deviceName" to deviceName)
eventSink?.success(returnData) eventSink?.success(returnData)
BleServiceHelper.BleServiceHelper.startRtTask(model) BleServiceHelper.BleServiceHelper.startRtTask(model)
} }
@ -414,7 +415,7 @@ class BleBridge(
} }
LiveEventBus.get<InterfaceEvent>(InterfaceEvent.BP2.EventBp2RtData).observe(this.mainActivity) { LiveEventBus.get<InterfaceEvent>(InterfaceEvent.BP2.EventBp2RtData).observe(this.mainActivity) {
val data = it.data as RTBP2Data val data = it.data as com.lepu.blepro.ext.bp2.RtData
// data.status: RtStatus // data.status: RtStatus
// data.status.deviceStatus: 0(STATUS_SLEEP), 1(STATUS_MEMERY), 2(STATUS_CHARGE), 3(STATUS_READY), // data.status.deviceStatus: 0(STATUS_SLEEP), 1(STATUS_MEMERY), 2(STATUS_CHARGE), 3(STATUS_READY),
// 4(STATUS_BP_MEASURING), 5(STATUS_BP_MEASURE_END), // 4(STATUS_BP_MEASURING), 5(STATUS_BP_MEASURE_END),
@ -424,10 +425,27 @@ class BleBridge(
// data.param: RtParam // data.param: RtParam
// data.param.paramDataType: 0(Bp measuring), 1(Bp end), 2(Ecg measuring), 3(Ecg end) // data.param.paramDataType: 0(Bp measuring), 1(Bp end), 2(Ecg measuring), 3(Ecg end)
println("EventBp2RtData FOR BP : $data") when (data.param.paramDataType) {
val returnData = mapOf("type" to "RealTimeDataBP2", "data" to gson.toJson(data)) 0 -> {
println(returnData) val bpIng = RtBpIng(data.param.paramData)
val returnData = mapOf("type" to "RealTimeDataBP2Measuring", "data" to gson.toJson(bpIng))
eventSink?.success(returnData)
}
1 -> {
val bpResult = RtBpResult(data.param.paramData)
val returnData = mapOf("type" to "RealTimeDataBP2Result", "data" to gson.toJson(bpResult))
println("RealTimeDataBP2Result FOR BP : $returnData")
eventSink?.success(returnData) eventSink?.success(returnData)
}
}
} }
} }

@ -1,34 +0,0 @@
package com.cloud.diplomaticquarterapp.ble.utils;
import com.lepu.blepro.ext.bp2.RtParam;
import com.lepu.blepro.ext.bp2.RtStatus;
public class RTBP2Data {
private RtStatus status;
private RtParam param;
public RTBP2Data() {
}
public RtStatus getStatus() {
return this.status;
}
public void setStatus(RtStatus var1) {
this.status = var1;
}
public RtParam getParam() {
return this.param;
}
public void setParam(RtParam var1) {
this.param = var1;
}
public String toString() {
return "RtData{status=" + this.status + ", param=" + this.param + '}';
}
}

@ -0,0 +1,24 @@
class BpRtDataMeasuringModel {
bool deflate;
int pr;
int pressure;
bool pulse;
BpRtDataMeasuringModel({this.deflate, this.pr, this.pressure, this.pulse});
BpRtDataMeasuringModel.fromJson(Map<String, dynamic> json) {
deflate = json['deflate'];
pr = json['pr'];
pressure = json['pressure'];
pulse = json['pulse'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['deflate'] = this.deflate;
data['pr'] = this.pr;
data['pressure'] = this.pressure;
data['pulse'] = this.pulse;
return data;
}
}

@ -0,0 +1,33 @@
class BpRtDataResultModel {
bool deflate;
int dia;
int mean;
int pr;
int pressure;
int result;
int sys;
BpRtDataResultModel({this.deflate, this.dia, this.mean, this.pr, this.pressure, this.result, this.sys});
BpRtDataResultModel.fromJson(Map<String, dynamic> json) {
deflate = json['deflate'];
dia = json['dia'];
mean = json['mean'];
pr = json['pr'];
pressure = json['pressure'];
result = json['result'];
sys = json['sys'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['deflate'] = this.deflate;
data['dia'] = this.dia;
data['mean'] = this.mean;
data['pr'] = this.pr;
data['pressure'] = this.pressure;
data['result'] = this.result;
data['sys'] = this.sys;
return data;
}
}

@ -1,5 +1,8 @@
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:diplomaticquarterapp/models/ble_devices/viatom_devices/bp_rt_data_measuring_model.dart';
import 'package:diplomaticquarterapp/models/ble_devices/viatom_devices/bp_rt_data_result_model.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart'; import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/viatom_ble/ble_connect.dart'; import 'package:diplomaticquarterapp/viatom_ble/ble_connect.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
@ -15,16 +18,18 @@ class BpTrackerBLE extends StatefulWidget {
class _BpTrackerBLEState extends State<BpTrackerBLE> { class _BpTrackerBLEState extends State<BpTrackerBLE> {
EventChannel eventChannel = EventChannel('BLE-Platform-Bridge-Event'); EventChannel eventChannel = EventChannel('BLE-Platform-Bridge-Event');
String receivedData = '';
final bpDataNotifier = ValueNotifier<String>("start"); final bpDataNotifierMeasuring = ValueNotifier<BpRtDataMeasuringModel>(BpRtDataMeasuringModel());
final bpDataNotifierResult = ValueNotifier<BpRtDataResultModel>(BpRtDataResultModel());
// String deviceName = "CheckMeO2"; final bpStatusNotifier = ValueNotifier<String>("status");
final bpDeviceDataNotifier = ValueNotifier<String>("");
String deviceName = "BP2"; String deviceName = "BP2";
@override @override
void dispose() { void dispose() {
bpDataNotifier.dispose(); bpDataNotifierMeasuring.dispose();
bpDataNotifierResult.dispose();
bpStatusNotifier.dispose();
super.dispose(); super.dispose();
BleChannel.disconnect(); BleChannel.disconnect();
} }
@ -43,50 +48,157 @@ class _BpTrackerBLEState extends State<BpTrackerBLE> {
isShowDecPage: false, isShowDecPage: false,
showNewAppBarTitle: true, showNewAppBarTitle: true,
backgroundColor: Color(0xffF8F8F8), backgroundColor: Color(0xffF8F8F8),
body: SingleChildScrollView( body: Padding(
child: Padding(
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: ListView(
children: [
ValueListenableBuilder(
valueListenable: bpDeviceDataNotifier,
builder: (context, value, _) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
value == null || value.isEmpty ? "" : "Connected",
style: TextStyle(fontSize: 18),
),
Text(
"$value",
style: TextStyle(fontSize: 18),
),
],
);
},
),
ValueListenableBuilder(
valueListenable: bpStatusNotifier,
builder: (context, value, _) {
if (value == "RealTimeDataBP2Measuring") {
return ValueListenableBuilder(
valueListenable: bpDataNotifierMeasuring,
builder: (context, BpRtDataMeasuringModel bpRtDataMeasuringModel, _) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
mHeight(24.0),
Column(
children: [
Text(bpRtDataMeasuringModel.pressure.toString(), style: TextStyle(fontSize: 100, fontWeight: FontWeight.bold)),
Text("Pressure", style: TextStyle(fontSize: 20)),
],
),
mHeight(24.0),
],
);
},
);
} else if (value == "RealTimeDataBP2Result") {
return ValueListenableBuilder(
valueListenable: bpDataNotifierResult,
builder: (context, BpRtDataResultModel bpRtDataResultModel, _) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
mHeight(24.0),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Text("Dia", style: TextStyle(fontSize: 20)),
Text(bpRtDataResultModel.dia.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("mmHg", style: TextStyle(fontSize: 10)),
],
),
Column(
children: [
Text("Sys", style: TextStyle(fontSize: 20)),
Text(bpRtDataResultModel.sys.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("mmHg", style: TextStyle(fontSize: 10)),
],
),
Column(
children: [
Text("♥︎", style: TextStyle(fontSize: 20)),
Text(bpRtDataResultModel.pr.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("/min", style: TextStyle(fontSize: 10)),
],
),
],
),
mHeight(24.0),
],
);
},
);
}
return Padding(
padding: const EdgeInsets.all(24.0),
child: Center(
child: Text(
"Some animation with the instruction",
style: TextStyle(fontSize: 9.0),
),
),
);
},
),
],
),
),
ValueListenableBuilder(
valueListenable: bpDeviceDataNotifier,
builder: (context, value, _) {
if (value == null || value.isEmpty) {
return Row(
children: [ children: [
Expanded( Expanded(
child: DefaultButton( child: DefaultButton(
"Get Info", "Start Scan",
() async { () async {
checkBLEPermissions(); checkBLEPermissions();
}, },
textColor: Colors.white, textColor: Colors.white,
color: Colors.green,
), ),
), ),
mWidth(16.0), ],
);
}
return Row(
children: [
Expanded( Expanded(
child: DefaultButton( child: DefaultButton(
"Get Files List", "Disconnect with $value",
() async { () async {
await BleChannel.getBP2FilesList(["bloodpressure", "BP2"]); bpDataNotifierMeasuring.dispose();
bpDataNotifierResult.dispose();
bpStatusNotifier.dispose();
BleChannel.disconnect();
}, },
textColor: Colors.white, textColor: Colors.white,
), ),
), ),
], ],
), );
mHeight(20.0), return Row(
// _buildLiveLineChart() mainAxisAlignment: MainAxisAlignment.spaceEvenly,
ValueListenableBuilder(
valueListenable: bpDataNotifier,
builder: (context, value, _) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
value, value != null || value.isEmpty ? "" : "Connected",
style: TextStyle(fontSize: 9.0), style: TextStyle(fontSize: 18),
),
Text(
"$value",
style: TextStyle(fontSize: 18),
), ),
mHeight(24.0),
getFilesListWidget(),
mHeight(20.0),
], ],
); );
}, },
@ -94,7 +206,6 @@ class _BpTrackerBLEState extends State<BpTrackerBLE> {
], ],
), ),
), ),
),
); );
} }
@ -125,7 +236,8 @@ class _BpTrackerBLEState extends State<BpTrackerBLE> {
print('Received event---: $event'); print('Received event---: $event');
print(event['type']); print(event['type']);
if (event['type'] == "infoData") { if (event['type'] == "infoData") {
bpDataNotifier.value = event['data']; bpStatusNotifier.value = "infoData";
bpDeviceDataNotifier.value = event['deviceName'];
} }
if (event['type'] == "fileList") { if (event['type'] == "fileList") {
// parseEKGFilesList(event['data']); // parseEKGFilesList(event['data']);
@ -133,49 +245,25 @@ class _BpTrackerBLEState extends State<BpTrackerBLE> {
if (event['type'] == 'fileDetail') { if (event['type'] == 'fileDetail') {
print("Received file data ---:"); print("Received file data ---:");
print(event['data']); print(event['data']);
// parseEKGFileDetailObject(event['data']);
} }
if (event['type'] == "RealTimeDataBP2") { if (event['type'] == "RealTimeDataBP2Measuring") {
bpDataNotifier.value = event['data']; parseBpRtMeasuringObject(event['data']);
// parseEKGRealTimeDataObject(event['data']); bpStatusNotifier.value = "RealTimeDataBP2Measuring";
}
if (event['type'] == "RealTimeDataBP2Result") {
parseBpRtResultObject(event['data']);
bpStatusNotifier.value = "RealTimeDataBP2Result";
} }
}); });
await BleChannel.getScanningResult(["bloodpressure", "BP2"]); await BleChannel.getScanningResult(["bloodpressure", "BP2"]);
}); });
} }
String getSPO2(String value) { void parseBpRtMeasuringObject(dynamic returnData) {
return "SpO2: " + value.split(",")[0].replaceAll("{spo2=", ""); bpDataNotifierMeasuring.value = BpRtDataMeasuringModel.fromJson(json.decode(returnData));
}
String getPR(String value) {
return "Pulse Rate: " + value.split(",")[1].replaceAll("pr=", "");
} }
String getPI(String value) { void parseBpRtResultObject(dynamic returnData) {
return "Perfusion Index: " + value.split(",")[2].replaceAll("pi=", "") + "%"; bpDataNotifierResult.value = BpRtDataResultModel.fromJson(json.decode(returnData));
} }
String getSPO2iOS(String value) {
return "SpO2: " + value.split(",")[0];
}
String getPRiOS(String value) {
return "Pulse Rate: " + value.split(",")[1];
}
// List<String> setResult(String value) {
// List<String> values = value.split(",");
//
// print(values[0].replaceAll("{spo2=", ""));
// print(values[1].replaceAll("pr=", ""));
// print(values[2].replaceAll("pi=", ""));
//
// values.clear();
// values.add(values[0].replaceAll("{spo2=", ""));
// values.add(values[1].replaceAll("pr=", ""));
// values.add(values[2].replaceAll("pi=", ""));
//
// return values;
// }
} }

@ -5,7 +5,6 @@ class BleChannel {
static const platform_ios_ekg = MethodChannel('BLE-Platform-Bridge-IOS-EKG'); static const platform_ios_ekg = MethodChannel('BLE-Platform-Bridge-IOS-EKG');
//BLE-Platform-Bridge //BLE-Platform-Bridge
static Future<String> getScanningResult(List<String> deviceType) async { static Future<String> getScanningResult(List<String> deviceType) async {
try { try {
@ -66,5 +65,4 @@ class BleChannel {
return "Error: $e"; return "Error: $e";
} }
} }
} }

Loading…
Cancel
Save