dev_3.3_BLE
haroon amjad 2 years ago
parent ee5f90aba1
commit 992f7dd454

@ -1893,4 +1893,5 @@ const Map localizedValues = {
"sickLeaveAdmittedPatient": {"en": "You cannot activate this sick leave since you're an admitted patient.", "ar": "لا يمكنك تفعيل هذه الإجازة المرضية لأنك مريض مقبل."},
"dischargeDate": {"en": "Discharge Date", "ar": "تاريخ التفريغ"},
"selectAdmissionText": {"en": "Please select one of the admissions from below to view medical reports:", "ar": "يرجى تحديد أحد حالات القبول من الأسفل لعرض التقارير الطبية:"},
"spirometer": {"en": "Spirometer", "ar": "مقياس التنفس"},
};

@ -0,0 +1,146 @@
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/ble_utils.dart';
import 'package:diplomaticquarterapp/uitl/bluetooth_off.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:permission_handler/permission_handler.dart';
class ECG_BLE extends StatefulWidget {
@override
State<ECG_BLE> createState() => _ECG_BLEState();
}
class _ECG_BLEState extends State<ECG_BLE> {
String connectionStatus = "disconnected";
BluetoothDevice currentConnectedDevice;
BluetoothCharacteristic ecgWriteCharacteristic;
@override
void dispose() {
super.dispose();
if (currentConnectedDevice != null) currentConnectedDevice.disconnect();
}
@override
void initState() {
super.initState();
FlutterBluePlus.setLogLevel(LogLevel.verbose, color:false);
}
@override
Widget build(BuildContext context) {
return AppScaffold(
appBarTitle: "ECG",
showNewAppBar: true,
isShowDecPage: true,
showNewAppBarTitle: true,
backgroundColor: Color(0xffF8F8F8),
body: SingleChildScrollView(
child: StreamBuilder<BluetoothAdapterState>(
stream: FlutterBluePlus.adapterState,
initialData: BluetoothAdapterState.unknown,
builder: (c, snapshot) {
final adapterState = snapshot.data;
if (adapterState == BluetoothAdapterState.on) {
return Container(
margin: EdgeInsets.only(top: 200.0, left: 50.0, right: 50.0),
child: Column(
children: [
Center(
child: DefaultButton(
TranslationBase.of(context).start.toUpperCase(),
() {
checkBLEPermissions();
},
color: CustomColors.green,
),
),
SizedBox(
height: 50.0,
),
Text("Connection state: $connectionStatus"),
SizedBox(
height: 50.0,
),
// Text("Current Temp: $currentTempInCelsius"),
],
),
);
} else {
FlutterBluePlus.stopScan();
return SizedBox(height: 300.0, child: BluetoothOffScreen(adapterState: adapterState));
}
}),
),
);
}
void checkBLEPermissions() {
[Permission.location, Permission.storage, Permission.bluetooth, Permission.bluetoothConnect, Permission.bluetoothScan].request().then((status) {
startBLEConnection();
});
}
void startBLEConnection() {
if (FlutterBluePlus.isScanningNow == false) {
setState(() {
connectionStatus = "Connecting...";
});
FlutterBluePlus.startScan(timeout: const Duration(seconds: 5), androidUsesFineLocation: false).then((value) {
List<ScanResult> blueToothDevices = value;
blueToothDevices.forEach((element) async {
if (element.device.localName.isNotEmpty) {
if (element.device.localName.toLowerCase() == "pm101897") {
element.device.connectionState.listen((BluetoothConnectionState state) async {
if(mounted) {
setState(() {
connectionStatus = state.toString();
});
}
if (state == BluetoothConnectionState.disconnected) {
// typically, start a periodic timer that tries to periodically reconnect.
// Note: you must always re-discover services after disconnection!
}
if (state == BluetoothConnectionState.connected) {
currentConnectedDevice = element.device;
List<BluetoothService> services = await element.device.discoverServices();
services.forEach((service) {
if (service.serviceUuid.toString().toLowerCase() == BLEUtils.ECG_SERVICE) {
print(service.serviceUuid);
service.characteristics.forEach((characteristic) async {
if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.ECG_READ_CHARACTERISTIC) {
print(characteristic.characteristicUuid);
characteristic.onValueReceived.listen((event) {
print("onValueReceived Stream");
print(event);
});
await characteristic.setNotifyValue(true);
}
if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.ECG_WRITE_CHARACTERISTIC) {
print(characteristic.characteristicUuid);
ecgWriteCharacteristic = characteristic;
ecgWriteCharacteristic.write([0x90], allowLongWrite: true);
}
});
return true;
}
});
}
});
await element.device.connect(timeout: Duration(seconds: 35));
return true;
}
}
});
});
}
}
}

@ -2,6 +2,8 @@ import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/Weight/WeightHomePage.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/blood_pressure/BloodPressureBLE.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/blood_suger/blood_sugar_home_page.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ecg_ble.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/spirometer.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/temperature.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart';
@ -27,12 +29,12 @@ class MyTrackers extends StatelessWidget {
],
body: SingleChildScrollView(
child: Container(
child: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 2 / 2, crossAxisSpacing: 12, mainAxisSpacing: 12),
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(21),
shrinkWrap: true,
children: [
child: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 2 / 2, crossAxisSpacing: 12, mainAxisSpacing: 12),
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(21),
shrinkWrap: true,
children: [
InkWell(
onTap: () {
Navigator.push(context, FadePage(page: BloodSugarHomePage()));
@ -85,20 +87,48 @@ class MyTrackers extends StatelessWidget {
height: 45.0,
),
),
InkWell(
onTap: () {
Navigator.push(context, FadePage(page: BloodPressureBLE()));
},
child: MedicalProfileItem(
title: TranslationBase.of(context).bloodPressure + " BLE",
imagePath: 'assets/tracker/blood-pressure.png',
subTitle: null,
isPngImage: true,
width: 45.0,
height: 45.0,
),
),
])),
InkWell(
onTap: () {
Navigator.push(context, FadePage(page: BloodPressureBLE()));
},
child: MedicalProfileItem(
title: TranslationBase.of(context).bloodPressure + " BLE",
imagePath: 'assets/tracker/blood-pressure.png',
subTitle: null,
isPngImage: true,
width: 45.0,
height: 45.0,
),
),
InkWell(
onTap: () {
Navigator.push(context, FadePage(page: SpirometerBLE()));
},
child: MedicalProfileItem(
title: TranslationBase.of(context).spirometer + " BLE",
imagePath: 'assets/tracker/blood-pressure.png',
subTitle: null,
isPngImage: true,
width: 45.0,
height: 45.0,
),
),
InkWell(
onTap: () {
Navigator.push(context, FadePage(page: ECG_BLE()));
},
child: MedicalProfileItem(
title: "ECG BLE",
imagePath: 'assets/tracker/blood-pressure.png',
subTitle: null,
isPngImage: true,
width: 45.0,
height: 45.0,
),
),
],
),
),
),
);
}

@ -0,0 +1,205 @@
import 'dart:async';
import 'dart:io';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/ble_utils.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:permission_handler/permission_handler.dart';
class SpirometerBLE extends StatefulWidget {
@override
State<SpirometerBLE> createState() => _SpirometerBLEState();
}
class _SpirometerBLEState extends State<SpirometerBLE> {
String connectionStatus = "disconnected";
BluetoothDevice currentConnectedDevice;
Timer _timer;
Timer _timerRead;
@override
void dispose() {
super.dispose();
if (currentConnectedDevice != null) currentConnectedDevice.disconnect();
if (_timer != null && _timer.isActive) _timer.cancel();
if (_timerRead != null && _timerRead.isActive) _timerRead.cancel();
}
@override
Widget build(BuildContext context) {
return AppScaffold(
appBarTitle: TranslationBase.of(context).spirometer,
showNewAppBar: true,
isShowDecPage: true,
showNewAppBarTitle: true,
backgroundColor: Color(0xffF8F8F8),
body: SingleChildScrollView(
child: StreamBuilder<BluetoothAdapterState>(
stream: FlutterBluePlus.adapterState,
initialData: BluetoothAdapterState.unknown,
builder: (c, snapshot) {
final adapterState = snapshot.data;
if (adapterState == BluetoothAdapterState.on) {
return Container(
margin: EdgeInsets.only(top: 200.0, left: 50.0, right: 50.0),
child: Column(
children: [
Center(
child: DefaultButton(
TranslationBase.of(context).start.toUpperCase(),
() {
checkBLEPermissions();
},
color: CustomColors.green,
),
),
SizedBox(
height: 50.0,
),
Text("Connection state: $connectionStatus"),
SizedBox(
height: 50.0,
),
// Text("Current Temp: $currentTempInCelsius"),
],
),
);
} else {
FlutterBluePlus.stopScan();
return SizedBox(height: 300.0, child: BluetoothOffScreen(adapterState: adapterState));
}
}),
),
);
}
void checkBLEPermissions() {
[Permission.location, Permission.storage, Permission.bluetooth, Permission.bluetoothConnect, Permission.bluetoothScan].request().then((status) {
startBLEConnection();
});
}
void startBLEConnection() {
if (FlutterBluePlus.isScanningNow == false) {
setState(() {
connectionStatus = "Connecting...";
});
FlutterBluePlus.startScan(timeout: const Duration(seconds: 5), androidUsesFineLocation: false).then((value) {
List<ScanResult> blueToothDevices = value;
blueToothDevices.forEach((element) async {
if (element.device.localName.isNotEmpty) {
if (element.device.localName.toLowerCase() == "ble-msa") {
element.device.connectionState.listen((BluetoothConnectionState state) async {
setState(() {
connectionStatus = state.toString();
});
if (state == BluetoothConnectionState.disconnected) {
// typically, start a periodic timer that tries to periodically reconnect.
// Note: you must always re-discover services after disconnection!
if (_timer != null && _timer.isActive) _timer.cancel();
if (_timerRead != null && _timerRead.isActive) _timerRead.cancel();
}
if (state == BluetoothConnectionState.connected) {
currentConnectedDevice = element.device;
List<int> BLEToMSAWriteCharacters = [];
BLEToMSAWriteCharacters.add(int.parse("5506", radix: 16));
List<BluetoothService> services = await element.device.discoverServices();
services.forEach((service) {
if (service.serviceUuid.toString().toLowerCase() == BLEUtils.BLE_TO_MSA100_SERVICE) {
print(service.serviceUuid);
service.characteristics.forEach((characteristic) async {
if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.BLE_TO_MSA100_CHARACTERISTIC) {
print(characteristic.characteristicUuid);
_timer = Timer.periodic(Duration(seconds: 2), (Timer timer) {
characteristic.write(BLEToMSAWriteCharacters).then((value) {
print("Characteristic response:");
}).catchError((err) {});
});
}
if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.MSA100_TO_BLE_CHARACTERISTIC) {
print(characteristic.characteristicUuid);
_timerRead = Timer.periodic(Duration(seconds: 2), (Timer timer) {
characteristic.read().then((value) {
print("Characteristic Read value: ");
print(value);
});
});
// characteristic.onValueReceived.listen((event) {
// print("onValueReceived Stream");
// print(event);
// setState(() {
// currentTempInCelsius = convertIntListToHex(event);
// String currentTempInFahrenheit = ((num.parse(currentTempInCelsius) * 1.8) + 32).toStringAsFixed(1);
// currentTempInCelsius = currentTempInCelsius + "\u2103" + " / " + currentTempInFahrenheit + "\u2109";
// });
// });
// await characteristic.setNotifyValue(true);
}
});
return true;
}
});
}
});
await element.device.connect(timeout: Duration(seconds: 35));
return true;
}
}
});
});
}
}
}
class BluetoothOffScreen extends StatelessWidget {
const BluetoothOffScreen({Key key, this.adapterState}) : super(key: key);
final BluetoothAdapterState adapterState;
@override
Widget build(BuildContext context) {
return ScaffoldMessenger(
child: Scaffold(
backgroundColor: Colors.lightBlue,
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Icon(
Icons.bluetooth_disabled,
size: 200.0,
color: Colors.white54,
),
Text(
'Bluetooth Adapter is ${adapterState != null ? adapterState.toString().split(".").last + ", Please turn on your bluetooth to continue." : 'not available'}.',
textAlign: TextAlign.center,
style: Theme.of(context).primaryTextTheme.titleSmall?.copyWith(color: Colors.white),
),
if (Platform.isAndroid)
ElevatedButton(
child: const Text('TURN ON'),
onPressed: () async {
try {
if (Platform.isAndroid) {
await FlutterBluePlus.turnOn();
}
} catch (e) {}
},
),
],
),
),
),
);
}
}

@ -2,6 +2,7 @@ import 'dart:io';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/ble_utils.dart';
import 'package:diplomaticquarterapp/uitl/bluetooth_off.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
@ -149,46 +150,3 @@ class _TemperatureHomePageState extends State<TemperatureHomePage> {
return (number * 0.01).toStringAsFixed(1);
}
}
class BluetoothOffScreen extends StatelessWidget {
const BluetoothOffScreen({Key key, this.adapterState}) : super(key: key);
final BluetoothAdapterState adapterState;
@override
Widget build(BuildContext context) {
return ScaffoldMessenger(
child: Scaffold(
backgroundColor: Colors.lightBlue,
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Icon(
Icons.bluetooth_disabled,
size: 200.0,
color: Colors.white54,
),
Text(
'Bluetooth Adapter is ${adapterState != null ? adapterState.toString().split(".").last + ", Please turn on your bluetooth to continue." : 'not available'}.',
textAlign: TextAlign.center,
style: Theme.of(context).primaryTextTheme.titleSmall?.copyWith(color: Colors.white),
),
if (Platform.isAndroid)
ElevatedButton(
child: const Text('TURN ON'),
onPressed: () async {
try {
if (Platform.isAndroid) {
await FlutterBluePlus.turnOn();
}
} catch (e) {}
},
),
],
),
),
),
);
}
}

@ -6,4 +6,17 @@ class BLEUtils {
//Temperature
static const String TEMPERATURE_SERVICE = "00001809-0000-1000-8000-00805f9b34fb";
static const String TEMPERATURE_CHARACTERISTIC = "00002a1c-0000-1000-8000-00805f9b34fb";
}
//Spirometer
static const String BLE_TO_MSA100_SERVICE = "0000fff0-0000-1000-8000-00805f9b34fb";
static const String BLE_TO_MSA100_CHARACTERISTIC = "0000ff0b-0000-1000-8000-00805f9b34fb";
static const String MSA100_TO_BLE_SERVICE = "0000fff0-0000-1000-8000-00805f9b34fb";
static const String MSA100_TO_BLE_CHARACTERISTIC = "0000ff0a-0000-1000-8000-00805f9b34fb";
//ECG
static const String ECG_SERVICE = "49535343-fe7d-4ae5-8fa9-9fafd205e455"; //
static const String ECG_READ_CHARACTERISTIC = "49535343-1e4d-4bd9-ba61-23c647249616"; //49535343-1e4d-4bd9-ba61-23c647249616
static const String ECG_WRITE_CHARACTERISTIC = "49535343-8841-43f4-a8d4-ecbe34729bb3"; //49535343-8841-43f4-a8d4-ecbe34729bb3
}

@ -0,0 +1,47 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
class BluetoothOffScreen extends StatelessWidget {
const BluetoothOffScreen({Key key, this.adapterState}) : super(key: key);
final BluetoothAdapterState adapterState;
@override
Widget build(BuildContext context) {
return ScaffoldMessenger(
child: Scaffold(
backgroundColor: Colors.lightBlue,
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Icon(
Icons.bluetooth_disabled,
size: 200.0,
color: Colors.white54,
),
Text(
'Bluetooth Adapter is ${adapterState != null ? adapterState.toString().split(".").last + ", Please turn on your bluetooth to continue." : 'not available'}.',
textAlign: TextAlign.center,
style: Theme.of(context).primaryTextTheme.titleSmall?.copyWith(color: Colors.white),
),
if (Platform.isAndroid)
ElevatedButton(
child: const Text('TURN ON'),
onPressed: () async {
try {
if (Platform.isAndroid) {
await FlutterBluePlus.turnOn();
}
} catch (e) {}
},
),
],
),
),
),
);
}
}

@ -2902,6 +2902,7 @@ class TranslationBase {
String get sickLeaveAdmittedPatient => localizedValues["sickLeaveAdmittedPatient"][locale.languageCode];
String get dischargeDate => localizedValues["dischargeDate"][locale.languageCode];
String get selectAdmissionText => localizedValues["selectAdmissionText"][locale.languageCode];
String get spirometer => localizedValues["spirometer"][locale.languageCode];
}

Loading…
Cancel
Save