diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro index 67361ef5..35c451f0 100644 --- a/android/app/proguard-rules.pro +++ b/android/app/proguard-rules.pro @@ -38,4 +38,6 @@ -keep class org.otwebrtc.** { *; } -dontwarn com.opentok.android.** --dontwarn com.opentok.otc.** \ No newline at end of file +-dontwarn com.opentok.otc.** + +-keep class com.boskokg.flutter_blue_plus.* { *; } \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 42fc0237..036443f3 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,10 +7,7 @@ additional functionality it is fine to subclass or reimplement FlutterApplication and put your custom class here. --> - - - @@ -41,6 +38,23 @@ + + + + + + + + + + + + + + + diff --git a/lib/models/ble_devices/ble_scan_response.dart b/lib/models/ble_devices/ble_scan_response.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/pages/medical/my_trackers/my_trackers.dart b/lib/pages/medical/my_trackers/my_trackers.dart index 7f0ac95f..8f9fe10a 100644 --- a/lib/pages/medical/my_trackers/my_trackers.dart +++ b/lib/pages/medical/my_trackers/my_trackers.dart @@ -1,6 +1,7 @@ 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_suger/blood_sugar_home_page.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'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -70,6 +71,19 @@ class MyTrackers extends StatelessWidget { height: 45.0, ), ), + InkWell( + onTap: () { + Navigator.push(context, FadePage(page: TemperatureHomePage())); + }, + child: MedicalProfileItem( + title: TranslationBase.of(context).temperature, + imagePath: 'assets/tracker/weight.png', + subTitle: null, + isPngImage: true, + width: 45.0, + height: 45.0, + ), + ), ])), ), ); diff --git a/lib/pages/medical/my_trackers/temperature.dart b/lib/pages/medical/my_trackers/temperature.dart new file mode 100644 index 00000000..8884fe99 --- /dev/null +++ b/lib/pages/medical/my_trackers/temperature.dart @@ -0,0 +1,181 @@ +import 'dart:io'; + +import 'package:diplomaticquarterapp/theme/colors.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 TemperatureHomePage extends StatefulWidget { + @override + State createState() => _TemperatureHomePageState(); +} + +class _TemperatureHomePageState extends State { + String connectionStatus = "disconnected"; + String currentTempInCelsius = "0.0"; + + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).temperature, + showNewAppBar: true, + isShowDecPage: true, + showNewAppBarTitle: true, + backgroundColor: Color(0xffF8F8F8), + body: SingleChildScrollView( + child: StreamBuilder( + 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" + "\u2103"), + ], + ), + ); + } 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 blueToothDevices = value; + blueToothDevices.forEach((element) async { + if (element.device.localName.isNotEmpty) { + if (element.device.localName.toLowerCase() == "temp") { + 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 (state == BluetoothConnectionState.connected) { + List services = await element.device.discoverServices(); + services.forEach((service) { + if (service.serviceUuid.toString().contains("1809")) { + print(service.serviceUuid); + service.characteristics.forEach((characteristic) async { + if (characteristic.characteristicUuid.toString().toLowerCase().contains("2a1c")) { + print(characteristic.characteristicUuid); + characteristic.onValueReceived.listen((event) { + print("onValueReceived Stream"); + print(event); + setState(() { + currentTempInCelsius = convertIntListToHex(event); + }); + }); + await characteristic.setNotifyValue(true); + } + }); + return true; + } + }); + } + }); + await element.device.connect(timeout: Duration(seconds: 35)); + return true; + } + } + }); + }); + } + } + + String convertIntListToHex(List byteArray) { + String b = (byteArray.map((x) { + return x.toRadixString(16); + })).join(";"); + List hexString = b.split(";"); + print("HexString: $hexString"); + String returnString = hexString[3] + hexString[2] + hexString[1]; + print("Temp Hex String: $returnString"); + final number = int.parse(returnString, radix: 16); + print("Temp Number: ${number * 0.01}"); + + 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: [ + 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) {} + }, + ), + ], + ), + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 9f3755da..861e6c4d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -210,6 +210,7 @@ dependencies: # open_file: ^3.2.1 open_filex: ^4.3.2 path_provider: ^2.0.8 + flutter_blue_plus: ^1.14.11 # flutter_callkit_incoming: ^1.0.3+3 # firebase_core: 1.12.0