Finally Got the CheckMePro Device Info

dev_3.3_BLE
Faiz Hashmi 2 years ago
parent 322d0a8b5d
commit 4d74d2143f

@ -129,7 +129,7 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.code.gson:gson:2.8.6'
// Dependency on a remote binary // Dependency on a remote binary
// implementation 'com.example.android:app-magic:12.3' // implementation 'com.example.android:app-magic:12.3'
// Native Dependency // Native Dependency
@ -146,7 +146,8 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
implementation 'androidx.work:work-runtime:2.7.0-alpha05' implementation 'androidx.work:work-runtime:2.7.0-alpha05'
androidTestImplementation "androidx.test:core:1.4.0" androidTestImplementation "androidx.test:core:1.4.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2"
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2'
// Lepu Libraries // Lepu Libraries
implementation 'no.nordicsemi.android:ble:2.2.4' implementation 'no.nordicsemi.android:ble:2.2.4'
implementation(name: 'lepu-blepro-1.0.1', ext: 'aar') implementation(name: 'lepu-blepro-1.0.1', ext: 'aar')

@ -71,7 +71,7 @@
<meta-data android:name="push_kit_auto_init_enabled" android:value="true" /> <meta-data android:name="push_kit_auto_init_enabled" android:value="true" />
<activity <activity
android:name=".MainActivity" android:name="com.cloud.diplomaticquarterapp.MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:launchMode="singleTop" android:launchMode="singleTop"

@ -1,12 +1,14 @@
package com.ejada.hmg package com.cloud.diplomaticquarterapp
import android.util.Log
import android.view.WindowManager import android.view.WindowManager
import com.cloud.diplomaticquarterapp.check_me_pro.ble.manager.BleScanManager
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.plugins.GeneratedPluginRegistrant import io.flutter.plugins.GeneratedPluginRegistrant
import com.lepu.blepro.observer.BleChangeObserver import com.cloud.diplomaticquarterapp.ble.BleBridge
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
class MainActivity : FlutterFragmentActivity() { class MainActivity : FlutterFragmentActivity() {
@ -18,7 +20,11 @@ class MainActivity : FlutterFragmentActivity() {
this.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) this.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON)
PlatformBridge(flutterEngine, this).create() PlatformBridge(flutterEngine, this).create()
OpenTokPlatformBridge(flutterEngine, this).create() OpenTokPlatformBridge(flutterEngine, this).create()
BleBridge(flutterEngine, this).create() BleBridge(flutterEngine, this).createBleBridge(BleScanManager()) { name, bluetoothDevice ->
// Handle the scan result here
Log.d("MainActivity", "Received scan result: $name, $bluetoothDevice")
}
}
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// val mChannel = NotificationChannel("video_call_noti", "video call", NotificationManager.IMPORTANCE_HIGH) // val mChannel = NotificationChannel("video_call_noti", "video call", NotificationManager.IMPORTANCE_HIGH)
// val soundUri = Uri.parse("android.resource://" + getApplicationContext() // val soundUri = Uri.parse("android.resource://" + getApplicationContext()
@ -38,7 +44,7 @@ class MainActivity : FlutterFragmentActivity() {
// val time = timeToMillis("04:00:00", "HH:mm:ss") // val time = timeToMillis("04:00:00", "HH:mm:ss")
} }
// override fun onBleStateChanged(model: Int, state: Int) { // override fun onBleStateChanged(model: Int, state: Int) {
@ -47,7 +53,3 @@ class MainActivity : FlutterFragmentActivity() {
// //
// } // }
override fun onResume() {
super.onResume()
}
}

@ -1,20 +1,26 @@
package com.ejada.hmg.utils package com.cloud.diplomaticquarterapp.ble
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice
import android.os.Build import android.os.Build
import android.os.Handler import android.os.Handler
import com.ejada.hmg.MainActivity import android.util.Log
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.EventChannel 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.BPModelMeasuring
import com.cloud.diplomaticquarterapp.ble.BPModelResult
import com.cloud.diplomaticquarterapp.ble.OxymeterModel
import com.cloud.diplomaticquarterapp.ble.utils.EcgData import com.cloud.diplomaticquarterapp.ble.utils.EcgData
import com.cloud.diplomaticquarterapp.ble.utils.HexString import com.cloud.diplomaticquarterapp.ble.utils.HexString
import com.cloud.diplomaticquarterapp.check_me_pro.UiChannel
import com.cloud.diplomaticquarterapp.check_me_pro.bean.BleBean
import com.cloud.diplomaticquarterapp.check_me_pro.bean.UserBean
import com.cloud.diplomaticquarterapp.check_me_pro.ble.format.UserInfo
import com.cloud.diplomaticquarterapp.check_me_pro.ble.manager.BleScanManager
import com.cloud.diplomaticquarterapp.check_me_pro.ble.worker.BleDataWorker
import com.cloud.diplomaticquarterapp.utils.Constant
import com.cloud.diplomaticquarterapp.MainActivity
import com.google.gson.Gson import com.google.gson.Gson
@ -33,17 +39,22 @@ 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.bp2.*
import com.lepu.blepro.ext.er1.Er1Config
import com.lepu.blepro.ext.er1.Er1EcgFile import com.lepu.blepro.ext.er1.Er1EcgFile
import com.lepu.blepro.ext.er1.Er1File import com.lepu.blepro.ext.er1.Er1File
import com.lepu.blepro.ext.er1.Er1HrFile
import com.lepu.blepro.ext.pc60fw.RtParam import com.lepu.blepro.ext.pc60fw.RtParam
import com.lepu.blepro.ext.sp20.RtWave import com.lepu.blepro.ext.sp20.RtWave
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.utils.DateUtil import com.lepu.blepro.utils.DateUtil
import com.lepu.blepro.utils.Er1Decompress import com.lepu.blepro.utils.Er1Decompress
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeoutOrNull
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import org.json.JSONObject
import java.io.File import java.io.File
class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivity: MainActivity) { class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivity: MainActivity) {
@ -54,6 +65,7 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
private var ecgFileNames = arrayListOf<String>() private var ecgFileNames = arrayListOf<String>()
var ecgList: ArrayList<EcgData> = arrayListOf() var ecgList: ArrayList<EcgData> = arrayListOf()
private val bleListCheckMe: MutableList<BleBean> = ArrayList()
val gson = Gson() val gson = Gson()
@ -63,15 +75,52 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
private const val EVENTCHANNEL = "BLE-Platform-Bridge-Event" private const val EVENTCHANNEL = "BLE-Platform-Bridge-Event"
private const val SCAN_DEVICE = "scanDevices" private const val SCAN_DEVICE = "scanDevices"
private const val STOP_SCAN = "stopScan" private const val STOP_SCAN = "stopScan"
private const val STOP_SCAN_CHECK_ME = "stopScanCheckMe"
private const val CONNECT_DEVICE = "connectDevice" private const val CONNECT_DEVICE = "connectDevice"
private const val CONNECT_DEVICE_CHECK_ME = "connectDeviceCheckMe"
private const val SCAN_DEVICE_EKG = "scan_ekg" private const val SCAN_DEVICE_EKG = "scan_ekg"
private const val EKG_FILES_LIST = "ecgFilesList" private const val EKG_FILES_LIST = "ecgFilesList"
private const val FACTORY_RESET_ECG = "factoryResetECG" private const val FACTORY_RESET_ECG = "factoryResetECG"
private const val BP2_FILES_LIST = "bp2FilesList" private const val BP2_FILES_LIST = "bp2FilesList"
private const val DISCONNECT_DEVICE = "disconnectDevice" private const val DISCONNECT_DEVICE = "disconnectDevice"
private const val DISCONNECT_CHECK_ME = "disconnectCheckMe"
private const val READ_USER_CHECK_ME_PRO = "readUserCheckMePro"
private const val GET_DEVICE_INFO_CHECK_ME_PRO = "getDeviceInfoCheckMePro"
private const val SCAN_FOR_CHECK_ME_PRO = "scanForCheckMePro"
val scan = BleScanManager()
val dataScope = CoroutineScope(Dispatchers.IO)
val uiScope = CoroutineScope(Dispatchers.Main)
}
private val bleWorker = BleDataWorker { deviceInfoString ->
// Update eventSink in BleBridge
eventSink?.success(deviceInfoString)
} }
var mUserData: MutableList<UserBean> = java.util.ArrayList()
private val userChannel = Channel<Int>(Channel.CONFLATED)
private var userFileName = arrayOf(
"dlc.dat", "ped.dat", "nibp.dat", "glu.dat"
)
private var commonFileName = arrayOf(
"bpcal.dat",
"ecg.dat",
"oxi.dat",
"tmp.dat",
"slm.dat",
)
var currentUser = 0
lateinit var userInfo: UserInfo
private val models = intArrayOf( private val models = intArrayOf(
Bluetooth.MODEL_PC60FW, Bluetooth.MODEL_PC_60NW, Bluetooth.MODEL_PC_60NW_1, Bluetooth.MODEL_PC60FW, Bluetooth.MODEL_PC_60NW, Bluetooth.MODEL_PC_60NW_1,
Bluetooth.MODEL_PC66B, Bluetooth.MODEL_PF_10, Bluetooth.MODEL_PF_20, Bluetooth.MODEL_PC66B, Bluetooth.MODEL_PF_10, Bluetooth.MODEL_PF_20,
@ -171,7 +220,7 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
@SuppressLint("NewApi") @SuppressLint("NewApi")
fun create() { fun createBleBridge(bleScanManager: BleScanManager, scanResultHandler: (String, BluetoothDevice) -> Unit) {
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
Echannel = EventChannel(flutterEngine.dartExecutor.binaryMessenger, EVENTCHANNEL) Echannel = EventChannel(flutterEngine.dartExecutor.binaryMessenger, EVENTCHANNEL)
channel.setMethodCallHandler { methodCall: MethodCall, result: MethodChannel.Result -> channel.setMethodCallHandler { methodCall: MethodCall, result: MethodChannel.Result ->
@ -184,6 +233,12 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
connectDevice(methodCall.arguments as List<String>) connectDevice(methodCall.arguments as List<String>)
} else if (methodCall.method == DISCONNECT_DEVICE) { } else if (methodCall.method == DISCONNECT_DEVICE) {
disconnectDevice(methodCall, result) disconnectDevice(methodCall, result)
} else if (methodCall.method == STOP_SCAN_CHECK_ME) {
stopScanForCheckMePro()
} else if (methodCall.method == CONNECT_DEVICE_CHECK_ME) {
connectDeviceCheckMe(methodCall.arguments as List<String>)
} else if (methodCall.method == DISCONNECT_CHECK_ME) {
disConnectDeviceCheckMe()
} else if (methodCall.method == SCAN_DEVICE_EKG) { } else if (methodCall.method == SCAN_DEVICE_EKG) {
// scanDeviceEKG(methodCall, result) // scanDeviceEKG(methodCall, result)
} else if (methodCall.method == EKG_FILES_LIST) { } else if (methodCall.method == EKG_FILES_LIST) {
@ -192,6 +247,12 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
factoryResetECG(methodCall.arguments as List<String>) factoryResetECG(methodCall.arguments as List<String>)
} else if (methodCall.method == BP2_FILES_LIST) { } else if (methodCall.method == BP2_FILES_LIST) {
getBP2FilesList() getBP2FilesList()
} else if (methodCall.method == SCAN_FOR_CHECK_ME_PRO) {
scanForCheckMePro(bleScanManager, scanResultHandler)
} else if (methodCall.method == READ_USER_CHECK_ME_PRO) {
} else if (methodCall.method == GET_DEVICE_INFO_CHECK_ME_PRO) {
} else { } else {
result.notImplemented() result.notImplemented()
} }
@ -210,6 +271,10 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
} }
private fun stopScanForCheckMePro() {
scan.stopScan();
}
@RequiresApi(Build.VERSION_CODES.Q) @RequiresApi(Build.VERSION_CODES.Q)
fun disconnectDevice(methodCall: MethodCall, result: MethodChannel.Result) { fun disconnectDevice(methodCall: MethodCall, result: MethodChannel.Result) {
@ -244,13 +309,80 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
} }
} }
@RequiresApi(Build.VERSION_CODES.M)
private fun scanForCheckMePro(bleScanManager: BleScanManager, scanResultHandler: (String, BluetoothDevice) -> Unit) {
bleScanManager.initScan(this.mainActivity)
bleScanManager.setCallBack(object : BleScanManager.Scan {
override fun scanReturn(name: String, bluetoothDevice: BluetoothDevice) {
onScanResult(name, bluetoothDevice)
}
})
}
private fun stopScan() {
@SuppressLint("MissingPermission")
fun onScanResult(name: String, bluetoothDevice: BluetoothDevice) {
if (!(name.contains("Checkme"))) return;
var z: Int = 0;
for (ble in bleListCheckMe) run {
if (ble.name == bluetoothDevice.name) {
z = 1
}
}
if (z == 0) {
bleListCheckMe.add(BleBean(name, bluetoothDevice))
Log.d("CheckMeProDeviceFound", "This is the Device Name: $name")
val bluetoothDeviceJson = JSONObject().apply {
put("name", bluetoothDevice.name ?: "")
put("macAddr", bluetoothDevice.address ?: "")
put("type", bluetoothDevice.type)
// Add more properties as needed
}
println("EventDeviceFound : ${bluetoothDeviceJson.toString()}")
val returnData = mapOf("type" to "DevicesListCheckMe", "data" to bluetoothDeviceJson.toString())
eventSink?.success(returnData)
println(name)
}
}
private fun stopScan() {
BleServiceHelper.BleServiceHelper.stopScan() BleServiceHelper.BleServiceHelper.stopScan()
} }
private suspend fun readUserFromCheckMePro() {
userChannel.receive()
val userTemp = File(Constant.getPathX("usr.dat")).readBytes()
userTemp.apply {
userInfo = UserInfo(this)
val total = userInfo.user.size * 2 + 6 + 1
var tIndex = 1
UiChannel.progressChannel.send(tIndex * 100 / total)
for (user in userInfo.user) {
for (f in userFileName) {
bleWorker.getFile(user.id + f)
tIndex++
UiChannel.progressChannel.send(tIndex * 100 / total)
}
}
for (f in commonFileName) {
bleWorker.getFile(f)
tIndex++
UiChannel.progressChannel.send(tIndex * 100 / total)
}
delay(300)
UiChannel.progressChannel.close()
}
}
@RequiresApi(Build.VERSION_CODES.Q) @RequiresApi(Build.VERSION_CODES.Q)
private fun subscribeToStreams(deviceName: String) { private fun subscribeToStreams(deviceName: String) {
@ -544,17 +676,13 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
} }
} }
} }
} }
@RequiresApi(Build.VERSION_CODES.Q) @RequiresApi(Build.VERSION_CODES.Q)
private fun connectDevice(device: List<String>) { private fun connectDevice(device: List<String>) {
println("connectDevice: $device"); println("connectDevice: $device");
model = device[1].toInt() model = device[1].toInt()
val deviceName = device[0] val deviceName = device[0]
@ -572,9 +700,41 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
} }
}
private fun connectDeviceCheckMe(device: List<String>) {
val currentBluetoothDevice = bleListCheckMe.first { bleBean ->
bleBean.name == device[0]
}
Log.d("DeviceFound", "This is the Device i have : ${currentBluetoothDevice.name}")
// stopScanForCheckMePro()
bleWorker.initWorker(this.mainActivity, currentBluetoothDevice.bluetoothDevice)
uiScope.launch {
val a = withTimeoutOrNull(10000) {
bleWorker.waitConnect()
}
// a?.let {
// val b = withTimeoutOrNull(10000) {
// bleWorker.getFile("usr.dat")
// }
// b?.let {
// userChannel.send(1)
// }
// }
}
// uiScope.launch {
//// readUserFromCheckMePro()
// getCheckMeProDeviceInfo()
// }
} }
private fun disConnectDeviceCheckMe() {}
private fun readFileForEr2() { private fun readFileForEr2() {
if (ecgFileNames.size == 0) { if (ecgFileNames.size == 0) {

@ -0,0 +1,7 @@
package com.cloud.diplomaticquarterapp.check_me_pro
import kotlinx.coroutines.channels.Channel
object UiChannel {
val progressChannel = Channel<Int>(Channel.CONFLATED)
}

@ -0,0 +1,5 @@
package com.cloud.diplomaticquarterapp.check_me_pro.bean
import android.bluetooth.BluetoothDevice
data class BleBean(var name: String, var bluetoothDevice: BluetoothDevice)

@ -0,0 +1,11 @@
package com.cloud.diplomaticquarterapp.check_me_pro.bean
import java.util.*
data class BpBean(
var date: Date = Date(),
var timeString: String = "",
var sys: Int = 0,
var dia: Int=0,
var pr: Int = 0
)

@ -0,0 +1,17 @@
package com.cloud.diplomaticquarterapp.check_me_pro.bean
import java.util.*
data class DlcBean(
var date: Date = Date(),
var timeString: String = "",
var hr: Int = 0,
var eface: Int = 0,
var oxy: Int = 0,
var pi: Int = 0,
var oface: Int = 0,
var prFlag: Int = 0,
var pr: Int = 0,
var bpiFace: Int = 0,
var voice: Int = 0
)

@ -0,0 +1,11 @@
package com.cloud.diplomaticquarterapp.check_me_pro.bean
import java.util.*
data class EcgBean(
var date: Date = Date(),
var timeString: String = "",
var way: Int = 0,
var face: Int = 0,
var voice: Int = 0
)

@ -0,0 +1,10 @@
package com.cloud.diplomaticquarterapp.check_me_pro.bean
import java.util.*
data class GluBean(
var date: Date = Date(),
var timeString: String = "",
var glu:Float=0f,
var note:String=""
)

@ -0,0 +1,13 @@
package com.cloud.diplomaticquarterapp.check_me_pro.bean
import java.util.*
data class OxyBean(
var date: Date = Date(),
var timeString: String = "",
var way: Int = 0,
var oxy: Int = 0,
var pr: Int = 0,
var pi: Int = 0,
var face: Int = 0
)

@ -0,0 +1,52 @@
package com.cloud.diplomaticquarterapp.check_me_pro.bean
import android.os.Parcel
import android.os.Parcelable
import java.util.*
data class PedBean(
var date: Date = Date(),
var timeString: String? = "",
var step: Int = 0,
var dis: Float = 0f,
var speed: Float = 0f,
var cal: Float = 0f,
var fat: Float = 0f,
var time: Int = 0
) : Parcelable {
constructor(parcel: Parcel) : this(
TODO("date"),
parcel.readString(),
parcel.readInt(),
parcel.readFloat(),
parcel.readFloat(),
parcel.readFloat(),
parcel.readFloat(),
parcel.readInt()
) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(timeString)
parcel.writeInt(step)
parcel.writeFloat(dis)
parcel.writeFloat(speed)
parcel.writeFloat(cal)
parcel.writeFloat(fat)
parcel.writeInt(time)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<PedBean> {
override fun createFromParcel(parcel: Parcel): PedBean {
return PedBean(parcel)
}
override fun newArray(size: Int): Array<PedBean?> {
return arrayOfNulls(size)
}
}
}

@ -0,0 +1,15 @@
package com.cloud.diplomaticquarterapp.check_me_pro.bean
import java.util.*
data class SlpBean(
var date: Date = Date(),
var timeString: String = "",
var time: Int = 0,
var lowTime: Int = 0,
var lowCount: Int = 0,
var minO2: Int = 0,
var meanO2: Int = 0,
var face: Int = 0
)

@ -0,0 +1,11 @@
package com.cloud.diplomaticquarterapp.check_me_pro.bean
import java.util.*
data class TmpBean(
var date: Date = Date(),
var timeString: String = "",
var way: Int = 0,
var tmp: Float = 0f,
var face: Int = 0
)

@ -0,0 +1,14 @@
package com.cloud.diplomaticquarterapp.check_me_pro.bean
import java.util.*
data class UserBean(
var id: String = "",
var name: String = "",
var ico: Int = 0,
var sex: Int = 0,
var birthday: Date = Date(),
var weight: Int = 0,
var height: Int = 0,
var color: Int = 0
)

@ -0,0 +1,40 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.constant;
public class BTConstant {
// Bluetooth Command length
public final static int WRITE_CONTENT_PKG_DATA_LENGTH = 1024;
public final static int READ_CONTENT_ACK_DATA_LENGTH = 1024;
public final static int COMMON_PKG_LENGTH = 8;
public final static int COMMON_ACK_PKG_LENGTH = 12;
public final static int READ_CONTENT_ACK_PKG_FRONT_LENGTH = 8;
public final static int GET_INFO_ACK_PKG_LENGTH = 8 + 256;
public final static byte ACK_CMD_OK = 0;
public final static byte ACK_CMD_BAD = 1;
// Bluetooth Max file name length
public final static byte BT_WRITE_FILE_NAME_MAX_LENGTH = 30;
public final static byte BT_READ_FILE_NAME_MAX_LENGTH = 30;
// Bluetooth Command word
public final static byte CMD_WORD_START_WRITE = 0x00;
public final static byte CMD_WORD_WRITE_CONTENT = 0x01;
public final static byte CMD_WORD_END_WRITE = 0x02;
public final static byte CMD_WORD_START_READ = 0x03;
public final static byte CMD_WORD_READ_CONTENT = 0x04;
public final static byte CMD_WORD_END_READ = 0x05;
public final static byte CMD_WORD_DEL_FILE = 0x06;
public final static byte CMD_WORD_LIST_START = 0x07;
public final static byte CMD_WORD_LIST_DATA = 0x08;
public final static byte CMD_WORD_LIST_END = 0x09;
public final static byte CMD_WORD_LANG_UPDATE_START = 0x0A;
public final static byte CMD_WORD_LANG_UPDATE_DATA = 0x0B;
public final static byte CMD_WORD_LANG_UPDATE_END = 0x0C;
public final static byte CMD_WORD_APP_UPDATE_START = 0x0D;
public final static byte CMD_WORD_APP_UPDATE_DATA = 0x0E;
public final static byte CMD_WORD_APP_UPDATE_END = 0x0F;
public final static byte CMD_WORD_GET_INFO = 0x14;
public final static byte CMD_WORD_PING = 0x15;
public final static byte CMD_WORD_PARA_SYNC = 0x16;
}

@ -0,0 +1,58 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import com.cloud.diplomaticquarterapp.check_me_pro.bean.BpBean
import com.cloud.diplomaticquarterapp.utils.toUInt
import java.util.*
class BpInfo constructor(var bytes: ByteArray) {
var size: Int = bytes.size/11
var Bp: ArrayList<BpBean> = arrayListOf<BpBean>()
init {
var start: Int
for (k in 0 until size) {
start = k * 11
val year: Int = toUInt(setRange(start, 2))
val month: Int = toUInt(setRange(start + 2, 1)) - 1
val date: Int = toUInt(setRange(start + 3, 1))
val hour: Int = toUInt(setRange(start + 4, 1))
val minute: Int = toUInt(setRange(start + 5, 1))
val second: Int = toUInt(setRange(start + 6, 1))
val calendar = Calendar.getInstance()
calendar[Calendar.YEAR] = year
calendar[Calendar.MONTH] = month
calendar[Calendar.DATE] = date
calendar[Calendar.HOUR] = hour
calendar[Calendar.MINUTE] = minute
calendar[Calendar.SECOND] = second
Bp.add(BpBean())
Bp[k].apply {
this.date = calendar.time
timeString = String.format(
"%04d%02d%02d%02d%02d%02d",
year,
month + 1,
date,
hour,
minute,
second
)
sys = toUInt(setRange(start + 7, 2))
dia = toUInt(setRange(start + 9, 1))
pr = toUInt(setRange(start + 10, 1))
}
}
}
private fun setRange(start: Int, len: Int): ByteArray {
return bytes.copyOfRange(start, start + len)
}
}

@ -0,0 +1,14 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import com.cloud.diplomaticquarterapp.utils.toUInt
import com.cloud.diplomaticquarterapp.utils.unsigned
class CheckMeResponse(var bytes: ByteArray) {
var cmd: Int = bytes[1].unsigned()
var pkgNo: Int = toUInt(bytes.copyOfRange(3, 5))
var len: Int = toUInt(bytes.copyOfRange(5, 7))
var content: ByteArray = bytes.copyOfRange(7, 7 + len)
}

@ -0,0 +1,20 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import android.util.Log
import com.cloud.diplomaticquarterapp.utils.toUInt
import org.json.JSONObject
class DeviceInfo(buf: ByteArray) {
var len: Int = toUInt(buf.copyOfRange(5, 7))
var content: ByteArray = buf.copyOfRange(7, 7 + len)
var deviceStr: String = String(content)
var json: JSONObject
init {
Log.i("byteSize", buf.decodeToString())
Log.i("len::", len.toString())
deviceStr = deviceStr.substring(0, deviceStr.indexOf("}") + 1)
json = JSONObject(deviceStr)
}
}

@ -0,0 +1,69 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import com.cloud.diplomaticquarterapp.check_me_pro.bean.DlcBean
import com.cloud.diplomaticquarterapp.utils.toUInt
import java.util.*
class DlcInfo(var bytes: ByteArray) {
var size: Int = bytes.size / 17
var dlc: ArrayList<DlcBean> = arrayListOf<DlcBean>()
init {
var start: Int
for (k in 0 until size) {
start = k * 17
val year: Int = toUInt(setRange(start, 2))
val month: Int = toUInt(setRange(start + 2, 1))
val date: Int = toUInt(setRange(start + 3, 1))
val hour: Int = toUInt(setRange(start + 4, 1))
val minute: Int = toUInt(setRange(start + 5, 1))
val second: Int = toUInt(setRange(start + 6, 1))
val calendar = Calendar.getInstance()
calendar[Calendar.YEAR] = year
calendar[Calendar.MONTH] = month - 1
calendar[Calendar.DATE] = date
calendar[Calendar.HOUR] = hour
calendar[Calendar.MINUTE] = minute
calendar[Calendar.SECOND] = second
dlc.add(DlcBean())
dlc[k].apply {
this.date = calendar.time
timeString = String.format(
"%04d%02d%02d%02d%02d%02d",
year,
month,
date,
hour,
minute,
second
)
hr = toUInt(setRange(start + 7, 2))
eface = toUInt(setRange(start + 9, 1))
if (eface > 2) eface = 2
oxy = toUInt(setRange(start + 10, 1))
pi = toUInt(setRange(start + 11, 1))
oface = toUInt(setRange(start + 12, 1))
if (oface > 2) oface = 2
prFlag = toUInt(setRange(start + 13, 1))
pr = toUInt(setRange(start + 14, 1))
bpiFace = toUInt(setRange(start + 15, 1))
if (bpiFace > 2) bpiFace = 2
voice = toUInt(setRange(start + 16, 1))
}
}
}
private fun setRange(start: Int, len: Int): ByteArray {
return bytes.copyOfRange(start, start + len)
}
}

@ -0,0 +1,60 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import com.cloud.diplomaticquarterapp.check_me_pro.bean.EcgBean
import com.cloud.diplomaticquarterapp.utils.toUInt
import java.util.*
class EcgInfo(var bytes: ByteArray) {
var size: Int = bytes.size / 10
var ecg: ArrayList<EcgBean> = arrayListOf<EcgBean>()
init {
var start: Int
for (k in 0 until size) {
start = k * 10
val year: Int = toUInt(setRange(start, 2))
val month: Int = toUInt(setRange(start + 2, 1)) - 1
val date: Int = toUInt(setRange(start + 3, 1))
val hour: Int = toUInt(setRange(start + 4, 1))
val minute: Int = toUInt(setRange(start + 5, 1))
val second: Int = toUInt(setRange(start + 6, 1))
val calendar = Calendar.getInstance()
calendar[Calendar.YEAR] = year
calendar[Calendar.MONTH] = month
calendar[Calendar.DATE] = date
calendar[Calendar.HOUR] = hour
calendar[Calendar.MINUTE] = minute
calendar[Calendar.SECOND] = second
ecg.add(EcgBean())
ecg[k].apply {
this.date = calendar.time
timeString = String.format(
"%04d%02d%02d%02d%02d%02d",
year,
month + 1,
date,
hour,
minute,
second
)
way = toUInt(setRange(start + 7, 1))
face = toUInt(setRange(start + 8, 1))
if (face > 2) face = 2
voice = toUInt(setRange(start + 9, 1))
}
}
}
private fun setRange(start: Int, len: Int): ByteArray {
return bytes.copyOfRange(start, start + len)
}
}

@ -0,0 +1,64 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import com.cloud.diplomaticquarterapp.utils.toUInt
class EcgWaveInfo constructor(var bytes: ByteArray) {
var hrSize: Int = toUInt(bytes.copyOfRange(0, 2))
var waveSize: Int = toUInt(bytes.copyOfRange(2, 6)) - 4
var hr: Int = toUInt(bytes.copyOfRange(6, 8))
var st: Int = toUInt(bytes.copyOfRange(8, 10))
var qrs: Int = toUInt(bytes.copyOfRange(10, 12))
var pvcs: Int = toUInt(bytes.copyOfRange(12, 14))
var qtc: Int = toUInt(bytes.copyOfRange(14, 16))
var result: Int = toUInt(bytes.copyOfRange(16, 17))
var qt: Int = toUInt(bytes.copyOfRange(19, 21))
var hrList: IntArray = IntArray(hrSize / 2)
var waveList: IntArray = IntArray(waveSize / 2)
var waveIntSize = waveSize / 2
val total = 2500
var waveViewSize = waveIntSize / total
init {
for (index in 0 until hrSize / 2) {
hrList[index] = toUInt(setRange(index * 2 + 22, 2))
}
// for (index in 0 until waveSize / 2) {
// waveList[index] =
// bytes[23 + index * 2 + hrSize].toInt() * 256 + bytes[22 + index * 2 + hrSize].toInt()
// }
// waveList= ECGInnerItem(bytes).ecgData
waveIntSize=waveList.size
waveViewSize=waveIntSize/total
if (waveViewSize * total < waveIntSize) {
waveViewSize++
}
}
private fun setRange(start: Int, len: Int): ByteArray {
return bytes.copyOfRange(start, start + len)
}
fun getWave(index: Int): IntArray {
val result = IntArray(total)
for (k in 0 until total) {
result[k] = if (k + index * total < waveList.size) {
waveList[k + index * total]
} else {
1000000
}
}
return result
}
}

@ -0,0 +1,57 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import com.cloud.diplomaticquarterapp.check_me_pro.bean.GluBean
import com.cloud.diplomaticquarterapp.utils.toUInt
import java.util.*
class GluInfo constructor(var bytes: ByteArray) {
var size: Int = bytes.size / 32
var Glu: ArrayList<GluBean> = arrayListOf<GluBean>()
init {
var start: Int
for (k in 0 until size) {
start = k * 32
val year: Int = toUInt(setRange(start, 2))
val month: Int = toUInt(setRange(start + 2, 1)) - 1
val date: Int = toUInt(setRange(start + 3, 1))
val hour: Int = toUInt(setRange(start + 4, 1))
val minute: Int = toUInt(setRange(start + 5, 1))
val second: Int = toUInt(setRange(start + 6, 1))
val calendar = Calendar.getInstance()
calendar[Calendar.YEAR] = year
calendar[Calendar.MONTH] = month
calendar[Calendar.DATE] = date
calendar[Calendar.HOUR] = hour
calendar[Calendar.MINUTE] = minute
calendar[Calendar.SECOND] = second
Glu.add(GluBean())
Glu[k].apply {
this.date = calendar.time
timeString = String.format(
"%04d%02d%02d%02d%02d%02d",
year,
month + 1,
date,
hour,
minute,
second
)
glu= toUInt(setRange(start+7,2)).toFloat()/10f
note=String(setRange(start+12,20))
}
}
}
private fun setRange(start: Int, len: Int): ByteArray {
return bytes.copyOfRange(start, start + len)
}
}

@ -0,0 +1,64 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import com.cloud.diplomaticquarterapp.check_me_pro.bean.OxyBean
import com.cloud.diplomaticquarterapp.utils.toUInt
import java.util.*
class OxyInfo constructor(var bytes: ByteArray) {
var size: Int = bytes.size / 12
var Oxy: ArrayList<OxyBean> = arrayListOf<OxyBean>()
init {
var start: Int
for (k in 0 until size) {
start = k * 12
val year: Int = toUInt(setRange(start, 2))
val month: Int = toUInt(setRange(start + 2, 1)) - 1
val date: Int = toUInt(setRange(start + 3, 1))
val hour: Int = toUInt(setRange(start + 4, 1))
val minute: Int = toUInt(setRange(start + 5, 1))
val second: Int = toUInt(setRange(start + 6, 1))
val calendar = Calendar.getInstance()
calendar[Calendar.YEAR] = year
calendar[Calendar.MONTH] = month
calendar[Calendar.DATE] = date
calendar[Calendar.HOUR] = hour
calendar[Calendar.MINUTE] = minute
calendar[Calendar.SECOND] = second
Oxy.add(OxyBean())
Oxy[k].apply {
this.date = calendar.time
timeString = String.format(
"%04d%02d%02d%02d%02d%02d",
year,
month + 1,
date,
hour,
minute,
second
)
way = toUInt(setRange(start + 7, 1))
if (way > 2) way = 2
oxy = toUInt(setRange(start + 8, 1))
pr = toUInt(setRange(start + 9, 1))
pi = toUInt(setRange(start + 10, 1))
face = toUInt(setRange(start + 11, 1))
if (face > 2) face = 2
}
}
}
private fun setRange(start: Int, len: Int): ByteArray {
return bytes.copyOfRange(start, start + len)
}
}

@ -0,0 +1,28 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import com.cloud.diplomaticquarterapp.utils.toUInt
import com.cloud.diplomaticquarterapp.utils.unsigned
class OxyWaveInfo constructor(var bytes: ByteArray) {
val size1: Int = toUInt(bytes.copyOfRange(0, 2))
val size2: Int = toUInt(bytes.copyOfRange(2, 6))
val o2Array = IntArray(size1 / 3)
val pulseArray = IntArray(size1 / 3)
val waveArray = IntArray(size2)
init {
for (k in 0 until size1 / 3) {
o2Array[k] = bytes[k * 3 + 6].unsigned()
pulseArray[k] =
bytes[k * 3 + 7].unsigned() + bytes[k * 3 + 8].unsigned() * 256
}
for (k in 0 until size2) {
waveArray[k] = bytes[k + 6 + size1].unsigned()
}
}
}

@ -0,0 +1,63 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import android.util.Log
import com.cloud.diplomaticquarterapp.check_me_pro.bean.PedBean
import com.cloud.diplomaticquarterapp.utils.toUInt
import java.util.*
class PedInfo constructor(var bytes: ByteArray) {
var size: Int = bytes.size / 29
var Ped: ArrayList<PedBean> = arrayListOf<PedBean>()
init {
Log.i("pedoSize",bytes.size.toString())
var start: Int
for (k in 0 until size) {
start = k * 29
val year: Int = toUInt(setRange(start, 2))
val month: Int = toUInt(setRange(start + 2, 1)) - 1
val date: Int = toUInt(setRange(start + 3, 1))
val hour: Int = toUInt(setRange(start + 4, 1))
val minute: Int = toUInt(setRange(start + 5, 1))
val second: Int = toUInt(setRange(start + 6, 1))
val calendar = Calendar.getInstance()
calendar[Calendar.YEAR] = year
calendar[Calendar.MONTH] = month
calendar[Calendar.DATE] = date
calendar[Calendar.HOUR] = hour
calendar[Calendar.MINUTE] = minute
calendar[Calendar.SECOND] = second
Ped.add(PedBean())
Ped[k].apply {
this.date = calendar.time
timeString = String.format(
"%04d%02d%02d%02d%02d%02d",
year,
month + 1,
date,
hour,
minute,
second
)
step = toUInt(setRange(start + 7, 4))
dis = toUInt(setRange(start + 11, 4)).toFloat() / 100f
speed = toUInt(setRange(start + 15, 4)).toFloat() / 10f
cal = toUInt(setRange(start + 19, 4)).toFloat() / 100f
fat = toUInt(setRange(start + 23, 2)).toFloat() / 100f
time = toUInt(setRange(start + 25, 2))
}
}
}
private fun setRange(start: Int, len: Int): ByteArray {
return bytes.copyOfRange(start, start + len)
}
}

@ -0,0 +1,71 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import android.util.Log
import com.cloud.diplomaticquarterapp.check_me_pro.bean.SlpBean
import com.cloud.diplomaticquarterapp.utils.toUInt
import java.util.*
class SlpInfo constructor(var bytes: ByteArray) {
var size: Int = bytes.size / 18
var Slp: ArrayList<SlpBean> = arrayListOf<SlpBean>()
fun byteArray2String(byteArray: ByteArray): String {
var fuc = ""
for (b in byteArray) {
val st = String.format("%02X", b)
fuc += ("$st ");
}
return fuc
}
init {
Log.e("sleepSIze",byteArray2String(bytes))
var start: Int
for (k in 0 until size) {
start = k *18
val year: Int = toUInt(setRange(start, 2))
val month: Int = toUInt(setRange(start + 2, 1)) - 1
val date: Int = toUInt(setRange(start + 3, 1))
val hour: Int = toUInt(setRange(start + 4, 1))
val minute: Int = toUInt(setRange(start + 5, 1))
val second: Int = toUInt(setRange(start + 6, 1))
val calendar = Calendar.getInstance()
calendar[Calendar.YEAR] = year
calendar[Calendar.MONTH] = month
calendar[Calendar.DATE] = date
calendar[Calendar.HOUR] = hour
calendar[Calendar.MINUTE] = minute
calendar[Calendar.SECOND] = second
Slp.add(SlpBean())
Slp[k].apply {
this.date = calendar.time
timeString = String.format(
"%04d%02d%02d%02d%02d%02d",
year,
month + 1,
date,
hour,
minute,
second
)
time = toUInt(setRange(start + 7, 4))
lowTime = toUInt(setRange(start + 11, 2))
lowCount = toUInt(setRange(start + 13, 2))
minO2 = toUInt(setRange(start + 15, 1))
meanO2 = toUInt(setRange(start + 16, 1))
face = toUInt(setRange(start + 17, 1))
if (face > 2) face = 2
}
}
}
private fun setRange(start: Int, len: Int): ByteArray {
return bytes.copyOfRange(start, start + len)
}
}

@ -0,0 +1,59 @@
import com.cloud.diplomaticquarterapp.check_me_pro.bean.TmpBean
import com.cloud.diplomaticquarterapp.utils.toUInt
import java.util.*
class TmpInfo constructor(var bytes: ByteArray) {
var size: Int = bytes.size / 11
var Tmp: ArrayList<TmpBean> = arrayListOf<TmpBean>()
init {
var start: Int
for (k in 0 until size) {
start = k * 11
val year: Int = toUInt(setRange(start, 2))
val month: Int = toUInt(setRange(start + 2, 1)) - 1
val date: Int = toUInt(setRange(start + 3, 1))
val hour: Int = toUInt(setRange(start + 4, 1))
val minute: Int = toUInt(setRange(start + 5, 1))
val second: Int = toUInt(setRange(start + 6, 1))
val calendar = Calendar.getInstance()
calendar[Calendar.YEAR] = year
calendar[Calendar.MONTH] = month
calendar[Calendar.DATE] = date
calendar[Calendar.HOUR] = hour
calendar[Calendar.MINUTE] = minute
calendar[Calendar.SECOND] = second
Tmp.add(TmpBean())
Tmp[k].apply {
this.date = calendar.time
timeString = String.format(
"%04d%02d%02d%02d%02d%02d",
year,
month + 1,
date,
hour,
minute,
second
)
way = toUInt(setRange(start + 7, 1))
if (way > 2) way = 2
tmp = toUInt(setRange(start + 8, 2)).toFloat() / 10f
face = toUInt(setRange(start + 10, 1))
if (face > 2) face = 2
}
}
}
private fun setRange(start: Int, len: Int): ByteArray {
return bytes.copyOfRange(start, start + len)
}
}

@ -0,0 +1,46 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
import com.cloud.diplomaticquarterapp.check_me_pro.bean.UserBean
import com.cloud.diplomaticquarterapp.utils.toUInt
import com.cloud.diplomaticquarterapp.utils.unsigned
import java.util.*
class UserInfo constructor(var bytes: ByteArray) {
var size: Int = bytes.size / 27
var user: Array<UserBean> = Array(size) {
UserBean()
}
init {
var start: Int
for (k in 0 until size) {
start = k * 27
user[k].id = bytes[start].unsigned().toString()
user[k].name = String(setRange(start + 1, 16))
user[k].ico = bytes[start + 17].unsigned()
user[k].sex = bytes[start + 18].unsigned()
val year: Int = toUInt(setRange(start + 19, 2))
val month: Int = toUInt(setRange(start + 21, 1)) - 1
val date: Int = toUInt(setRange(start + 22, 1))
val calendar = Calendar.getInstance()
calendar[Calendar.YEAR] = year
calendar[Calendar.MONTH] = month
calendar[Calendar.DATE] = date
user[k].birthday = calendar.time
user[k].weight = toUInt(setRange(start + 23, 2)) /10
user[k].height = toUInt(setRange(start + 25, 2))
}
}
private fun setRange(start: Int, len: Int): ByteArray {
return bytes.copyOfRange(start, start + len)
}
}

@ -0,0 +1,111 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.manager;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.util.Log;
import java.util.Arrays;
import java.util.UUID;
import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.ble.data.Data;
public class BleDataManager extends BleManager {
private BluetoothGattCharacteristic write_char;
private BluetoothGattCharacteristic notify_char;
private OnNotifyListener listener;
public BleDataManager(Context context) {
super(context);
}
public void setNotifyListener(OnNotifyListener listener) {
this.listener = listener;
}
@Override
protected BleManagerGattCallback getGattCallback() {
return new MyManagerGattCallback();
}
public void sendCmd(byte[] bytes) {
// Log.i("----- Current Write Command -----", "");
writeCharacteristic(write_char, bytes)
.split()
.done(device -> {
})
.enqueue();
}
public interface OnNotifyListener {
void onNotify(BluetoothDevice device, Data data);
}
private class MyManagerGattCallback extends BleManagerGattCallback {
@Override
public boolean isRequiredServiceSupported(BluetoothGatt gatt) {
final BluetoothGattService service = gatt.getService(service_uuid);
if (service != null) {
write_char = service.getCharacteristic(write_uuid);
notify_char = service.getCharacteristic(notify_uuid);
}
boolean notify = false;
if (notify_char != null) {
final int properties = notify_char.getProperties();
notify = (properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0;
}
boolean writeRequest = false;
if (write_char != null) {
final int properties = write_char.getProperties();
int writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT;
if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0) {
writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE;
}
write_char.setWriteType(writeType);
writeRequest = (properties & BluetoothGattCharacteristic.PROPERTY_WRITE) != 0 || (properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0;
/// LepuBleLog.d(TAG, "writeChar writeRequest == " + writeRequest);
}
// Return true if all required services have been found
return write_char != null && notify_char != null
&& notify && writeRequest;
}
@Override
public boolean isOptionalServiceSupported(BluetoothGatt gatt) {
return super.isOptionalServiceSupported(gatt);
}
@Override
protected void initialize() {
beginAtomicRequestQueue()
.add(requestMtu(23) // Remember, GATT needs 3 bytes extra. This will allow packet size of 244 bytes.
.with((device, mtu) -> Log.d("TAG", "MTU set to " + mtu))
.fail((device, status) -> log(Log.WARN, "Requested MTU not supported: " + status)))
.add(enableNotifications(notify_char))
.done(device -> Log.d("TAG", "Target initialized"))
.enqueue();
setNotificationCallback(notify_char)
.with((device, data) -> {
listener.onNotify(device, data);
});
}
@Override
public void onDeviceDisconnected() {
write_char = null;
notify_char = null;
}
}
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");
}

@ -0,0 +1,63 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.manager
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.bluetooth.le.BluetoothLeScanner
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.Context
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
class BleScanManager {
interface Scan {
fun scanReturn(name: String, bluetoothDevice: BluetoothDevice)
}
private var bluetoothAdapter: BluetoothAdapter? = null
private lateinit var leScanner: BluetoothLeScanner
private var scan: Scan? = null
private val leScanCallback: ScanCallback = object : ScanCallback() {
@SuppressLint("MissingPermission")
override fun onScanResult(
callbackType: Int, result: ScanResult
) {
super.onScanResult(callbackType, result)
val device = result.device
if (device?.name == null) return;
scan?.apply {
scanReturn(device.name, device)
}
Log.i("scanned ble", " ${device.name}")
}
override fun onBatchScanResults(results: List<ScanResult>) {}
override fun onScanFailed(errorCode: Int) {}
}
fun setCallBack(scan: Scan) {
this.scan = scan
}
@SuppressLint("MissingPermission")
@RequiresApi(Build.VERSION_CODES.M)
fun initScan(context: Context) {
context.apply {
val settings: ScanSettings = ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build()
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
bluetoothAdapter = bluetoothManager.adapter
leScanner = bluetoothAdapter!!.bluetoothLeScanner
leScanner.startScan(null, settings, leScanCallback)
}
}
@SuppressLint("MissingPermission")
fun stopScan() {
leScanner.stopScan(leScanCallback)
}
}

@ -0,0 +1,21 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg
import com.cloud.diplomaticquarterapp.check_me_pro.ble.constant.BTConstant
import com.cloud.diplomaticquarterapp.utils.CRCUtils
import kotlin.experimental.inv
class EndReadPkg {
var buf: ByteArray = ByteArray(BTConstant.COMMON_PKG_LENGTH)
init {
// TODO Auto-generated constructor stub
buf[0] = 0xAA.toByte()
buf[1] = BTConstant.CMD_WORD_END_READ
buf[2] = BTConstant.CMD_WORD_END_READ.inv()
buf[3] = 0 //Package number, the default is 0
buf[4] = 0
buf[5] = 0 //data chunk size, the default is 0
buf[6] = 0
buf[buf.size - 1] = CRCUtils.calCRC8(buf)
}
}

@ -0,0 +1,21 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg
import com.cloud.diplomaticquarterapp.check_me_pro.ble.constant.BTConstant
import com.cloud.diplomaticquarterapp.utils.CRCUtils
import kotlin.experimental.inv
class GetDeviceInfoPkg() {
val buf: ByteArray = ByteArray(BTConstant.COMMON_PKG_LENGTH)
init {
buf[0] = 0xAA.toByte()
buf[1] = BTConstant.CMD_WORD_GET_INFO
buf[2] = BTConstant.CMD_WORD_GET_INFO.inv()
buf[3] = 0.toByte() //Package number
buf[4] = 0.toByte()
buf[5] = 0.toByte()
buf[6] = 0.toByte()
buf[buf.size - 1] = CRCUtils.calCRC8(buf)
}
}

@ -0,0 +1,19 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg
import com.cloud.diplomaticquarterapp.check_me_pro.ble.constant.BTConstant
import com.cloud.diplomaticquarterapp.utils.CRCUtils
import kotlin.experimental.inv
class ReadContentPkg(pkgNum: Int) {
val buf: ByteArray = ByteArray(BTConstant.COMMON_PKG_LENGTH)
init {
buf[0] = 0xAA.toByte()
buf[1] = BTConstant.CMD_WORD_READ_CONTENT
buf[2] = BTConstant.CMD_WORD_READ_CONTENT.inv()
buf[3] = pkgNum.toByte() //Package number
buf[4] = (pkgNum shr 8).toByte()
buf[5] = 0 //data chunk size, the default is 0
buf[6] = 0
buf[buf.size - 1] = CRCUtils.calCRC8(buf)
}
}

@ -0,0 +1,23 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg
import com.cloud.diplomaticquarterapp.check_me_pro.ble.constant.BTConstant
import com.cloud.diplomaticquarterapp.utils.CRCUtils
import kotlin.experimental.inv
class StartReadPkg(fileName: String?) {
val buf: ByteArray = ByteArray(BTConstant.COMMON_PKG_LENGTH + fileName!!.length + 1)
init {
buf[0] = (0xAA).toByte()
buf[1] = BTConstant.CMD_WORD_START_READ
buf[2] = BTConstant.CMD_WORD_START_READ.inv()
buf[3] = 0 //Package number, the default is 0
buf[4] = 0
buf[5] = (buf.size - BTConstant.COMMON_PKG_LENGTH).toByte() //data chunk size
buf[6] = (buf.size - BTConstant.COMMON_PKG_LENGTH shr 8).toByte()
val tempFileName = fileName!!.toCharArray()
for (i in tempFileName.indices) {
buf[i + 7] = tempFileName[i].toByte()
}
buf[buf.size - 1] = CRCUtils.calCRC8(buf)
}
}

@ -0,0 +1,222 @@
package com.cloud.diplomaticquarterapp.check_me_pro.ble.worker
import android.bluetooth.BluetoothDevice
import android.content.Context
import android.util.Log
import com.cloud.diplomaticquarterapp.check_me_pro.ble.format.CheckMeResponse
import com.cloud.diplomaticquarterapp.check_me_pro.ble.format.DeviceInfo
import com.cloud.diplomaticquarterapp.check_me_pro.ble.manager.BleDataManager
import com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg.EndReadPkg
import com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg.GetDeviceInfoPkg
import com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg.ReadContentPkg
import com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg.StartReadPkg
import com.cloud.diplomaticquarterapp.utils.CRCUtils
import com.cloud.diplomaticquarterapp.utils.Constant
import com.cloud.diplomaticquarterapp.utils.add
import com.cloud.diplomaticquarterapp.utils.toUInt
import com.google.gson.Gson
import io.flutter.plugin.common.EventChannel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import no.nordicsemi.android.ble.data.Data
import java.io.File
import kotlin.experimental.inv
class BleDataWorker(private val updateEventSink: (Map<String, Any>) -> Unit) {
private var pool: ByteArray? = null
private val deviceChannel = Channel<DeviceInfo>(Channel.CONFLATED)
private val fileChannel = Channel<Int>(Channel.CONFLATED)
private val connectChannel = Channel<String>(Channel.CONFLATED)
private var myBleDataManager: BleDataManager? = null
private val dataScope = CoroutineScope(Dispatchers.IO)
private val mutex = Mutex()
private var cmdState = 0;
var pkgTotal = 0;
var currentPkg = 0;
var fileData: ByteArray? = null
var currentFileName = ""
var result = 1;
var currentFileSize = 0
companion object {
val fileProgressChannel = Channel<FileProgress>(Channel.CONFLATED)
}
data class FileProgress(
var name: String = "", var progress: Int = 0, var success: Boolean = false
)
private val comeData = object : BleDataManager.OnNotifyListener {
override fun onNotify(device: BluetoothDevice?, data: Data?) {
data?.value?.apply {
pool = add(pool, this)
}
pool?.apply {
pool = handleDataPool(pool)
}
}
}
val gson = Gson()
private fun handleDataPool(bytes: ByteArray?): ByteArray? {
val bytesLeft: ByteArray? = bytes
if (bytes == null || bytes.size < 8) {
return bytes
}
loop@ for (i in 0 until bytes.size - 7) {
if (bytes[i] != 0x55.toByte() || bytes[i + 1] != bytes[i + 2].inv()) {
continue@loop
}
// need content length
val len = toUInt(bytes.copyOfRange(i + 5, i + 7))
if (i + 8 + len > bytes.size) {
continue@loop
}
val temp: ByteArray = bytes.copyOfRange(i, i + 8 + len)
if (temp.last() == CRCUtils.calCRC8(temp)) {
if (cmdState in 1..3) {
val bleResponse = CheckMeResponse(temp)
if (cmdState == 1) {
currentFileSize = toUInt(bleResponse.content)
pkgTotal = currentFileSize / 512
if (bleResponse.cmd == 1) {
result = 1
val pkg = EndReadPkg()
sendCmd(pkg.buf)
cmdState = 3
} else if (bleResponse.cmd == 0) {
val pkg = ReadContentPkg(currentPkg)
sendCmd(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)
}
val pkg = EndReadPkg()
Log.i("file", "bytes ${pkg.buf}")
sendCmd(pkg.buf)
cmdState = 3
} else {
val pkg = ReadContentPkg(currentPkg)
sendCmd(pkg.buf)
currentPkg++
}
} else if (cmdState == 3) {
fileData = null
currentPkg = 0
cmdState = 0
dataScope.launch {
fileProgressChannel.send(
FileProgress(
currentFileName, 100, result == 0
)
)
fileChannel.send(result)
}
}
} else if (cmdState == 4) {
val deviceInfo = DeviceInfo(temp)
val json = deviceInfo.json
var s: String = ""
for (k in json.keys()) {
s += "$k: "
s += "${json.get(k)} "
}
Log.d("DeviceInfoFaiz", "This is the DeviceInfo: ${gson.toJson(json)}");
val returnData = mapOf("type" to "infoDataCheckMe", "data" to gson.toJson(json))
updateEventSink(returnData)
}
val tempBytes: ByteArray? = if (i + 8 + len == bytes.size) null else bytes.copyOfRange(
i + 8 + len, bytes.size
)
return handleDataPool(tempBytes)
}
}
return bytesLeft
}
private fun sendCmd(bs: ByteArray) {
myBleDataManager?.sendCmd(bs)
}
fun initWorker(context: Context, bluetoothDevice: BluetoothDevice?) {
myBleDataManager = BleDataManager(context)
myBleDataManager?.setNotifyListener(comeData)
bluetoothDevice?.let {
myBleDataManager?.connect(it)?.useAutoConnect(false)?.retry(150, 100)?.done {
Log.i("BLE", "连接成功了.>>.....>>>>")
getDeviceInfo();
dataScope.launch {
connectChannel.send("yes")
}
}?.enqueue()
}
}
suspend fun waitConnect() {
connectChannel.receive()
}
suspend fun getFile(name: String): Int {
mutex.withLock {
this.currentFileName = name
cmdState = 1
val pkg = StartReadPkg(name)
Log.i("----- Current PKG -----", pkg.toString());
sendCmd(pkg.buf)
return fileChannel.receive()
}
}
private fun getDeviceInfo() {
cmdState = 4
val pkg = GetDeviceInfoPkg()
sendCmd(pkg.buf)
}
fun disconnect() {
myBleDataManager?.disconnect()?.enqueue()
}
}

@ -6,11 +6,10 @@ import android.content.Intent
import android.net.* import android.net.*
import android.net.wifi.* import android.net.wifi.*
import android.os.Build import android.os.Build
import android.os.PatternMatcher
import android.provider.Settings import android.provider.Settings
import android.util.Log import android.util.Log
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import com.ejada.hmg.MainActivity import com.cloud.diplomaticquarterapp.MainActivity
import com.ejada.hmg.utils.HMGUtils import com.ejada.hmg.utils.HMGUtils

@ -2,7 +2,7 @@ package com.ejada.hmg.hmgwifi
import android.annotation.SuppressLint import android.annotation.SuppressLint
import com.ejada.hmg.utils.API import com.ejada.hmg.utils.API
import com.ejada.hmg.MainActivity import com.cloud.diplomaticquarterapp.MainActivity
import com.github.kittinunf.fuel.core.extensions.jsonBody import com.github.kittinunf.fuel.core.extensions.jsonBody
import com.github.kittinunf.fuel.httpGet import com.github.kittinunf.fuel.httpGet
import com.github.kittinunf.fuel.httpPost import com.github.kittinunf.fuel.httpPost

@ -7,7 +7,7 @@ import android.net.wifi.*
import android.net.wifi.SupplicantState.ASSOCIATED import android.net.wifi.SupplicantState.ASSOCIATED
import android.net.wifi.SupplicantState.COMPLETED import android.net.wifi.SupplicantState.COMPLETED
import android.util.Log import android.util.Log
import com.ejada.hmg.MainActivity import com.cloud.diplomaticquarterapp.MainActivity
import com.ejada.hmg.utils.HMGUtils import com.ejada.hmg.utils.HMGUtils
class WPA(mainActivity: MainActivity, SSID:String) { class WPA(mainActivity: MainActivity, SSID:String) {

@ -12,9 +12,8 @@ import android.net.wifi.SupplicantState.COMPLETED
import android.os.Build import android.os.Build
import android.util.Log import android.util.Log
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import com.ejada.hmg.MainActivity import com.cloud.diplomaticquarterapp.MainActivity
import com.ejada.hmg.utils.HMGUtils import com.ejada.hmg.utils.HMGUtils
import java.security.cert.X509Certificate
class WpaEnterprise(private val mainActivity: MainActivity, private var SSID: String) { class WpaEnterprise(private val mainActivity: MainActivity, private var SSID: String) {
private var TAG = "WpaEnterprise" private var TAG = "WpaEnterprise"

@ -0,0 +1,34 @@
package com.cloud.diplomaticquarterapp.utils
fun add(ori: ByteArray?, add: ByteArray): ByteArray {
if (ori == null) {
return add
}
val new: ByteArray = ByteArray(ori.size + add.size)
for ((index, value) in ori.withIndex()) {
new[index] = value
}
for ((index, value) in add.withIndex()) {
new[index + ori.size] = value
}
return new
}
fun toUInt(bytes: ByteArray): Int {
var result = 0
for ((i, v) in bytes.withIndex()) {
result += v.unsigned().shl(i * 8)
}
return result
}
fun Byte.unsigned(): Int = when {
(toInt() < 0) -> 255 + toInt() + 1
else -> toInt()
}

@ -0,0 +1,58 @@
package com.cloud.diplomaticquarterapp.utils;
/**
* Tools used to generate CRC8 code
*
* @author zouhao
*/
public class CRCUtils {
/**
* CRC8 code table
*/
private static final char[] 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};
/**
* Generate CRC8 code
*
* @param buf Data buffer
* @return CRC8 code, return 0 when the parameter is error
*/
public static byte calCRC8(byte[] buf) {
if (buf == null || buf.length == 0) {
return 0;
}
byte crc = 0;
for (int i = 0; i < buf.length - 1; i++) {
crc = (byte) Table_CRC8[0x00ff & (crc ^ (buf[i]))];
}
return crc;
}
}

@ -0,0 +1,23 @@
package com.cloud.diplomaticquarterapp.utils;
import android.content.Context;
import java.io.File;
public class Constant {
public final static String[] EcgWay = {"Hand-Hand", "Hand-Chest", "1-Lead", "2-Lead"};
public final static String[] OxyWay = {"Internal", "External", ""};
public final static String[] TmpWay = {"Body", "Thing", ""};
public static String filePath;
public static String getPathX(String s) {
return filePath + s;
}
public static void initVar(Context context) {
File[] fs = context.getExternalFilesDirs(null);
if (fs != null && fs.length >= 1) {
filePath = fs[0].getAbsolutePath() + "/";
}
}
}

@ -1,7 +1,6 @@
package com.ejada.hmg.utils package com.ejada.hmg.utils
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.Result
class FlutterText{ class FlutterText{

@ -1,5 +1,6 @@
package com.ejada.hmg.utils package com.ejada.hmg.utils
import android.annotation.SuppressLint
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
@ -13,10 +14,8 @@ import android.widget.Toast
import androidx.annotation.Nullable import androidx.annotation.Nullable
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.TaskStackBuilder import androidx.core.app.TaskStackBuilder
import com.ejada.hmg.BuildConfig import com.cloud.diplomaticquarterapp.MainActivity
import com.ejada.hmg.MainActivity
import com.ejada.hmg.R import com.ejada.hmg.R
import com.ejada.hmg.geofence.GeoZoneModel
import com.github.kittinunf.fuel.core.extensions.jsonBody import com.github.kittinunf.fuel.core.extensions.jsonBody
import com.github.kittinunf.fuel.httpPost import com.github.kittinunf.fuel.httpPost
import com.google.gson.Gson import com.google.gson.Gson
@ -29,22 +28,24 @@ import org.json.JSONObject
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import kotlin.concurrent.timerTask import kotlin.concurrent.timerTask
import com.ejada.hmg.BuildConfig
class HMGUtils { class HMGUtils {
companion object{ companion object {
private lateinit var platformChannel: MethodChannel private lateinit var platformChannel: MethodChannel
fun getPlatformChannel():MethodChannel{ fun getPlatformChannel(): MethodChannel {
return platformChannel return platformChannel
} }
fun setPlatformChannel(channel: MethodChannel){
fun setPlatformChannel(channel: MethodChannel) {
platformChannel = channel platformChannel = channel
} }
fun timer(delay: Long, repeat: Boolean, tick: (Timer) -> Unit) : Timer{ fun timer(delay: Long, repeat: Boolean, tick: (Timer) -> Unit): Timer {
val timer = Timer() val timer = Timer()
if(repeat) if (repeat)
timer.schedule(timerTask { timer.schedule(timerTask {
tick(timer) tick(timer)
}, delay, delay) }, delay, delay)
@ -56,27 +57,27 @@ class HMGUtils {
return timer return timer
} }
fun popMessage(context: MainActivity, message: String){ fun popMessage(context: MainActivity, message: String) {
context.runOnUiThread { context.runOnUiThread {
Toast.makeText(context, message, Toast.LENGTH_LONG).show() Toast.makeText(context, message, Toast.LENGTH_LONG).show()
} }
} }
fun popFlutterText(context: MainActivity, key: String){ fun popFlutterText(context: MainActivity, key: String) {
context.runOnUiThread { context.runOnUiThread {
FlutterText.with(key){ FlutterText.with(key) {
Toast.makeText(context, it, Toast.LENGTH_LONG).show() Toast.makeText(context, it, Toast.LENGTH_LONG).show()
} }
} }
} }
fun getLanguageCode(context: Context) : Int { fun getLanguageCode(context: Context): Int {
val pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE) val pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE)
val lang = pref.getString(PREF_KEY_LANGUAGE, "ar") val lang = pref.getString(PREF_KEY_LANGUAGE, "ar")
return if (lang == "ar") 2 else 1 return if (lang == "ar") 2 else 1
} }
fun defaultHTTPParams(context: Context) : Map<String, Any?>{ fun defaultHTTPParams(context: Context): Map<String, Any?> {
return mapOf( return mapOf(
"ZipCode" to "966", "ZipCode" to "966",
"VersionID" to 5.8, "VersionID" to 5.8,
@ -87,11 +88,13 @@ class HMGUtils {
"PatientOutSA" to 0, "PatientOutSA" to 0,
"SessionID" to null, "SessionID" to null,
"isDentalAllowedBackend" to false, "isDentalAllowedBackend" to false,
"DeviceTypeID" to 2) "DeviceTypeID" to 2
)
} }
fun <T>scheduleJob(context: Context, pendingIntentClassType:Class<T>, jobId:Int, intervalDuration:String, deadlineMillis:Long = (30 * 1000)) { // default deadline: 30 Seconds @SuppressLint("MissingPermission")
fun <T> scheduleJob(context: Context, pendingIntentClassType: Class<T>, jobId: Int, intervalDuration: String, deadlineMillis: Long = (30 * 1000)) { // default deadline: 30 Seconds
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
val jobScheduler: JobScheduler = context.getSystemService(JobScheduler::class.java) val jobScheduler: JobScheduler = context.getSystemService(JobScheduler::class.java)
@ -100,17 +103,22 @@ class HMGUtils {
builder.setPersisted(true) builder.setPersisted(true)
builder.setBackoffCriteria(30000, JobInfo.BACKOFF_POLICY_LINEAR) builder.setBackoffCriteria(30000, JobInfo.BACKOFF_POLICY_LINEAR)
val intervalMillis = timeToMillis(intervalDuration,"HH:mm:ss") val intervalMillis = timeToMillis(intervalDuration, "HH:mm:ss")
builder.setMinimumLatency(intervalMillis) // wait at least builder.setMinimumLatency(intervalMillis) // wait at least
builder.setOverrideDeadline((intervalMillis + deadlineMillis)) // maximum delay builder.setOverrideDeadline((intervalMillis + deadlineMillis)) // maximum delay
if (jobScheduler.schedule(builder.build()) == JobScheduler.RESULT_SUCCESS){ if (jobScheduler.schedule(builder.build()) == JobScheduler.RESULT_SUCCESS) {
Logs.save(context,"ScheduleJob", "${pendingIntentClassType.simpleName}: Job scheduled to trigger after duration $intervalDuration >> HH:mm:ss --('MinimumLatency:$intervalMillis Deadline:${(intervalMillis + deadlineMillis)}')--",Logs.STATUS.SUCCESS) Logs.save(
}else{ context,
Logs.save(context,"ScheduleJob", "${pendingIntentClassType.simpleName}: Failed to scheduled Job",Logs.STATUS.ERROR) "ScheduleJob",
"${pendingIntentClassType.simpleName}: Job scheduled to trigger after duration $intervalDuration >> HH:mm:ss --('MinimumLatency:$intervalMillis Deadline:${(intervalMillis + deadlineMillis)}')--",
Logs.STATUS.SUCCESS
)
} else {
Logs.save(context, "ScheduleJob", "${pendingIntentClassType.simpleName}: Failed to scheduled Job", Logs.STATUS.ERROR)
} }
} else { } else {
Logs.save(context,"ScheduleJob", "${pendingIntentClassType.simpleName}: Failed to scheduled Job on VERSION.SDK_INT < ${android.os.Build.VERSION_CODES.M}",Logs.STATUS.ERROR) Logs.save(context, "ScheduleJob", "${pendingIntentClassType.simpleName}: Failed to scheduled Job on VERSION.SDK_INT < ${android.os.Build.VERSION_CODES.M}", Logs.STATUS.ERROR)
} }
} }
@ -122,7 +130,7 @@ class HMGUtils {
private const val NOTIFICATION_CHANNEL_ID = BuildConfig.APPLICATION_ID + ".channel" private const val NOTIFICATION_CHANNEL_ID = BuildConfig.APPLICATION_ID + ".channel"
fun timeToMillis(time:String, format:String):Long{ fun timeToMillis(time: String, format: String): Long {
val sdf = SimpleDateFormat(format, Locale.US) val sdf = SimpleDateFormat(format, Locale.US)
val millis = sdf.parse(time).time + TimeZone.getDefault().rawOffset val millis = sdf.parse(time).time + TimeZone.getDefault().rawOffset
return millis return millis
@ -132,11 +140,14 @@ fun sendNotification(context: Context, title: String, @Nullable subtitle: String
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID) == null) { && notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID) == null
) {
val name = context.getString(R.string.app_name) val name = context.getString(R.string.app_name)
val channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, val channel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
name, name,
NotificationManager.IMPORTANCE_DEFAULT) NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel) notificationManager.createNotificationChannel(channel)
} }
@ -167,38 +178,42 @@ fun getUniqueId() = ((System.currentTimeMillis() % 10000).toInt())
object DateUtils { object DateUtils {
@JvmStatic @JvmStatic
fun dateTimeNow() : String { fun dateTimeNow(): String {
val format = SimpleDateFormat("dd-MMM-yyy hh:mm:ss") val format = SimpleDateFormat("dd-MMM-yyy hh:mm:ss")
return format.format(Date()) return format.format(Date())
} }
} }
fun isJSONValid(jsonString: String?): Boolean { fun isJSONValid(jsonString: String?): Boolean {
try { JSONObject(jsonString) } catch (ex: JSONException) { try {
try { JSONArray(jsonString) } catch (ex1: JSONException) { JSONObject(jsonString)
} catch (ex: JSONException) {
try {
JSONArray(jsonString)
} catch (ex1: JSONException) {
return false return false
} }
} }
return true return true
} }
fun saveLog(context: Context, tag: String, message: String){ fun saveLog(context: Context, tag: String, message: String) {
val pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE) val pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE)
var logs = pref.getString("LOGS", "") var logs = pref.getString("LOGS", "")
logs += "$tag -> $message \n" logs += "$tag -> $message \n"
pref.edit().putString("LOGS", logs).apply(); pref.edit().putString("LOGS", logs).apply();
} }
fun getLogs(context: Context) : String?{ fun getLogs(context: Context): String? {
val pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE) val pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE)
return pref.getString("LOGS", "") return pref.getString("LOGS", "")
} }
class HTTPResponse<T>(data: T){ class HTTPResponse<T>(data: T) {
final var data:T = data final var data: T = data
} }
fun <T>httpPost(url: String, body: Map<String, Any?>, onSuccess: (response: HTTPResponse<T>) -> Unit, onError: (error: Exception) -> Unit){ fun <T> httpPost(url: String, body: Map<String, Any?>, onSuccess: (response: HTTPResponse<T>) -> Unit, onError: (error: Exception) -> Unit) {
val gson = Gson() val gson = Gson()
val type = object : TypeToken<T>() {}.type val type = object : TypeToken<T>() {}.type
val jsonBody = gson.toJson(body) val jsonBody = gson.toJson(body)

@ -2,83 +2,83 @@ package com.ejada.hmg.utils
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Build
import com.ejada.hmg.BuildConfig import com.ejada.hmg.BuildConfig
import com.google.gson.Gson import com.google.gson.Gson
class Logs { class Logs {
enum class STATUS{ enum class STATUS {
SUCCESS, SUCCESS,
ERROR; ERROR;
} }
class GeofenceEvent{
companion object{ class GeofenceEvent {
fun save(context: Context, tag:String, message:String, status:Logs.STATUS = STATUS.SUCCESS){ companion object {
Logs.Common.save(context,"GeofenceEvent", tag, message, status) fun save(context: Context, tag: String, message: String, status: Logs.STATUS = STATUS.SUCCESS) {
Logs.Common.save(context, "GeofenceEvent", tag, message, status)
} }
fun list(context: Context, tag:String? = null, status:Logs.STATUS? = null):List<LogModel>{ fun list(context: Context, tag: String? = null, status: Logs.STATUS? = null): List<LogModel> {
return Logs.Common.list(context,"GeofenceEvent", tag, status) return Logs.Common.list(context, "GeofenceEvent", tag, status)
} }
fun raw(context: Context):String{ fun raw(context: Context): String {
return Logs.Common.raw(context,"GeofenceEvent") return Logs.Common.raw(context, "GeofenceEvent")
} }
} }
} }
class RegisterGeofence{ class RegisterGeofence {
companion object{ companion object {
fun save(context: Context, tag:String, message:String, status:Logs.STATUS = STATUS.SUCCESS){ fun save(context: Context, tag: String, message: String, status: Logs.STATUS = STATUS.SUCCESS) {
Logs.Common.save(context,"RegisterGeofence", tag, message, status) Logs.Common.save(context, "RegisterGeofence", tag, message, status)
} }
fun list(context: Context, tag:String? = null, status:Logs.STATUS? = null):List<LogModel>{ fun list(context: Context, tag: String? = null, status: Logs.STATUS? = null): List<LogModel> {
return Logs.Common.list(context,"RegisterGeofence", tag, status) return Logs.Common.list(context, "RegisterGeofence", tag, status)
} }
fun raw(context: Context):String{ fun raw(context: Context): String {
return Logs.Common.raw(context,"RegisterGeofence"); return Logs.Common.raw(context, "RegisterGeofence");
} }
} }
} }
companion object{ companion object {
private var pref:SharedPreferences? = null private var pref: SharedPreferences? = null
fun save(context: Context, tag:String, message:String, status:Logs.STATUS = STATUS.SUCCESS){ fun save(context: Context, tag: String, message: String, status: Logs.STATUS = STATUS.SUCCESS) {
Logs.Common.save(context,"Logs", tag, message, status) Logs.Common.save(context, "Logs", tag, message, status)
} }
fun list(context: Context, tag:String? = null, status:Logs.STATUS? = null):List<LogModel>{ fun list(context: Context, tag: String? = null, status: Logs.STATUS? = null): List<LogModel> {
return Logs.Common.list(context,"Logs", tag, status) return Logs.Common.list(context, "Logs", tag, status)
} }
fun raw(context: Context):String{ fun raw(context: Context): String {
return Logs.Common.raw(context,"Logs"); return Logs.Common.raw(context, "Logs");
} }
private fun storage(context: Context):SharedPreferences{ private fun storage(context: Context): SharedPreferences {
if(pref == null) { if (pref == null) {
pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE) pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE)
} }
return pref!! return pref!!
} }
} }
private class Common{ private class Common {
companion object{ companion object {
private val gson = Gson() private val gson = Gson()
fun save(context: Context, key:String, tag:String, message:String, status:Logs.STATUS = STATUS.SUCCESS){ fun save(context: Context, key: String, tag: String, message: String, status: Logs.STATUS = STATUS.SUCCESS) {
if(!BuildConfig.DEBUG) if (!BuildConfig.DEBUG)
return return
val pref = Logs.storage(context) val pref = Logs.storage(context)
val string = pref.getString(key,"{}") val string = pref.getString(key, "{}")
val json = gson.fromJson<LogsContainerModel>(string,LogsContainerModel::class.java) val json = gson.fromJson<LogsContainerModel>(string, LogsContainerModel::class.java)
json.add( json.add(
LogModel().apply { LogModel().apply {
this.TAG = tag this.TAG = tag
@ -88,42 +88,42 @@ class Logs {
} }
) )
pref.edit().putString(key,gson.toJson(json)).apply() pref.edit().putString(key, gson.toJson(json)).apply()
} }
fun list(context: Context, key:String, tag:String? = null, status:Logs.STATUS? = null):List<LogModel>{ fun list(context: Context, key: String, tag: String? = null, status: Logs.STATUS? = null): List<LogModel> {
val pref = Logs.storage(context) val pref = Logs.storage(context)
val string = pref.getString(key,"{}") val string = pref.getString(key, "{}")
val json = gson.fromJson<LogsContainerModel>(string,LogsContainerModel::class.java) val json = gson.fromJson<LogsContainerModel>(string, LogsContainerModel::class.java)
if(tag == null && status == null) { if (tag == null && status == null) {
return json.LOGS return json.LOGS
}else if(tag != null && status != null){ } else if (tag != null && status != null) {
return json.LOGS.filter { (it.TAG == tag && it.STATUS == status.name) } return json.LOGS.filter { (it.TAG == tag && it.STATUS == status.name) }
}else if(tag != null){ } else if (tag != null) {
return json.LOGS.filter { (it.TAG == tag) } return json.LOGS.filter { (it.TAG == tag) }
}else if(status != null){ } else if (status != null) {
return json.LOGS.filter { (it.STATUS == status.name) } return json.LOGS.filter { (it.STATUS == status.name) }
} }
return listOf() return listOf()
} }
fun raw(context: Context, key:String):String{ fun raw(context: Context, key: String): String {
val pref = Logs.storage(context) val pref = Logs.storage(context)
val string = pref.getString(key,"{}") val string = pref.getString(key, "{}")
return string!! return string!!
} }
} }
} }
class LogModel{ class LogModel {
lateinit var TAG:String lateinit var TAG: String
lateinit var MESSAGE:String lateinit var MESSAGE: String
lateinit var STATUS:String lateinit var STATUS: String
lateinit var DATE:String lateinit var DATE: String
companion object{ companion object {
fun with(tag:String, message:String, status:String):LogModel{ fun with(tag: String, message: String, status: String): LogModel {
return LogModel().apply { return LogModel().apply {
this.TAG = tag this.TAG = tag
this.MESSAGE = message this.MESSAGE = message
@ -134,9 +134,9 @@ class Logs {
} }
} }
class LogsContainerModel{ class LogsContainerModel {
var LOGS = mutableListOf<LogModel>() var LOGS = mutableListOf<LogModel>()
fun add(log:LogModel){ fun add(log: LogModel) {
LOGS.add(log) LOGS.add(log)
} }
} }

@ -1,6 +1,6 @@
package com.ejada.hmg.utils package com.ejada.hmg.utils
import com.ejada.hmg.MainActivity import com.cloud.diplomaticquarterapp.MainActivity
import com.ejada.hmg.opentok.OpenTok import com.ejada.hmg.opentok.OpenTok
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall

@ -11,7 +11,7 @@ import android.widget.Toast
import androidx.core.app.ActivityCompat.startActivityForResult import androidx.core.app.ActivityCompat.startActivityForResult
import android.net.wifi.WifiManager import android.net.wifi.WifiManager
import android.util.Log import android.util.Log
import com.ejada.hmg.MainActivity import com.cloud.diplomaticquarterapp.MainActivity
import com.ejada.hmg.hmgwifi.HMG_Guest import com.ejada.hmg.hmgwifi.HMG_Guest
import com.ejada.hmg.geofence.GeoZoneModel import com.ejada.hmg.geofence.GeoZoneModel
import com.ejada.hmg.geofence.HMG_Geofence import com.ejada.hmg.geofence.HMG_Geofence

@ -1,5 +1,4 @@
import 'package:diplomaticquarterapp/extensions/string_extensions.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/ble_devices_model.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/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart'; import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
@ -8,7 +7,7 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class AndesAllInOneConnectScreen extends StatefulWidget { class AndesAllInOneConnectScreen extends StatefulWidget {
final BluetoothDevice deviceModel; final BleDeviceModel deviceModel;
const AndesAllInOneConnectScreen({this.deviceModel}); const AndesAllInOneConnectScreen({this.deviceModel});
@ -22,13 +21,13 @@ class _AndesAllInOneConnectScreenState extends State<AndesAllInOneConnectScreen>
@override @override
void initState() { void initState() {
myTrackersVm = context.read<MyTrackersViewModel>(); myTrackersVm = context.read<MyTrackersViewModel>();
myTrackersVm.connectAndesfitAllInOneDevice(widget.deviceModel); myTrackersVm.connectDevice(widget.deviceModel);
super.initState(); super.initState();
} }
@override @override
void dispose() { void dispose() {
myTrackersVm.disConnectAndesfitDevice(widget.deviceModel); myTrackersVm.disConnectDevice();
super.dispose(); super.dispose();
} }
@ -36,32 +35,27 @@ class _AndesAllInOneConnectScreenState extends State<AndesAllInOneConnectScreen>
return Expanded( return Expanded(
child: ListView( child: ListView(
children: [ children: [
if (myTrackersViewModel.andesfitWeightScaleData == null && (myTrackersViewModel.isAndesfitDeviceConnected != null && myTrackersViewModel.isAndesfitDeviceConnected)) ...[ if (myTrackersViewModel.checkMeInfo == null) ...[
Row( Padding(
mainAxisAlignment: MainAxisAlignment.center, padding: const EdgeInsets.all(24.0),
children: [ child: Center(
mHeight(24.0), child: Text(
Column( "Some animation with the instruction",
children: [ style: TextStyle(fontSize: 9.0),
Text("Please Wait", style: TextStyle(fontSize: 20)),
],
), ),
mHeight(24.0),
],
), ),
] else if (false) ...[ )
// Add the UI here for All In One Monitor
] else ...[ ] else ...[
Padding( Padding(
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
child: Center( child: Center(
child: Text( child: Text(
"Some animation with the instruction", "${myTrackersViewModel.checkMeInfo.toString()}",
style: TextStyle(fontSize: 9.0), style: TextStyle(fontSize: 9.0),
), ),
), ),
) )
], ]
], ],
), ),
); );
@ -70,7 +64,7 @@ class _AndesAllInOneConnectScreenState extends State<AndesAllInOneConnectScreen>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AppScaffold( return AppScaffold(
appBarTitle: "${widget.deviceModel.localName}", appBarTitle: "${widget.deviceModel.name}",
showNewAppBar: true, showNewAppBar: true,
isShowDecPage: false, isShowDecPage: false,
showNewAppBarTitle: true, showNewAppBarTitle: true,
@ -89,9 +83,9 @@ class _AndesAllInOneConnectScreenState extends State<AndesAllInOneConnectScreen>
children: [ children: [
Expanded( Expanded(
child: DefaultButton( child: DefaultButton(
"Disconnect with ${widget.deviceModel.localName}", "Disconnect with ${widget.deviceModel.name}",
() async { () async {
myTrackersVm.disConnectAndesfitDevice(widget.deviceModel); myTrackersVm.disConnectDevice();
Navigator.pop(context); Navigator.pop(context);
}, },
textColor: Colors.white, textColor: Colors.white,

@ -36,8 +36,12 @@ class _BleDevicesScreenState extends State<BleDevicesScreen> {
@override @override
void initState() { void initState() {
myTrackersVm = context.read<MyTrackersViewModel>(); myTrackersVm = context.read<MyTrackersViewModel>();
if (myTrackersVm.currentSelectedTrackerType == TrackerTypeEnum.AllInOneTracker) {
myTrackersVm.startSearchingForCheckMePro();
} else {
myTrackersVm.startSearchingForTracker(); myTrackersVm.startSearchingForTracker();
myTrackersVm.startTimerForNativeScan(); myTrackersVm.startTimerForNativeScan();
}
super.initState(); super.initState();
} }
@ -48,7 +52,7 @@ class _BleDevicesScreenState extends State<BleDevicesScreen> {
void onDeviceTapped(BleDeviceModel device) { void onDeviceTapped(BleDeviceModel device) {
myTrackersVm.isDeviceSelected = true; myTrackersVm.isDeviceSelected = true;
log("isDeviceSelected from Screen:${myTrackersVm.isDeviceSelected}"); log("isDeviceSelected from Screen: ${myTrackersVm.isDeviceSelected}");
FlutterBluePlus.stopScan(); FlutterBluePlus.stopScan();
switch (device.deviceType) { switch (device.deviceType) {
case TrackerTypeEnum.OxymeterTracker: case TrackerTypeEnum.OxymeterTracker:
@ -112,10 +116,9 @@ class _BleDevicesScreenState extends State<BleDevicesScreen> {
break; break;
case TrackerTypeEnum.AllInOneTracker: case TrackerTypeEnum.AllInOneTracker:
if (myTrackersVm.isDeviceFromAndesFit(device.name)) { if (myTrackersVm.isDeviceFromAndesFit(device.name)) {
Navigator.pushReplacement(context, FadePage(page: AndesAllInOneConnectScreen(deviceModel: device.andesfitBluetoothDevice)));
return; return;
} }
// TODO: Handle this case. Navigator.pushReplacement(context, FadePage(page: AndesAllInOneConnectScreen(deviceModel: device)));
break; break;
} }
} }

@ -1,11 +1,5 @@
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_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/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/data_display/medical/medical_profile_item.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
@ -16,9 +10,6 @@ import 'package:provider/provider.dart';
class SelectTrackerType extends StatelessWidget { class SelectTrackerType extends StatelessWidget {
const SelectTrackerType(); const SelectTrackerType();
Uint8List convertIntArrayToByteArray(List<int> intArray) {
return Uint8List.fromList(intArray);
}
List<Widget> myTrackersTypeList({BuildContext context}) { List<Widget> myTrackersTypeList({BuildContext context}) {
List<Widget> medical = []; List<Widget> medical = [];

@ -10,6 +10,21 @@ 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> scanCheckMeProNative() async {
try {
String result;
print("----------Flutter scanCheckMeProNative -------");
result = await platform.invokeMethod('scanForCheckMePro');
print("----------Flutter scanCheckMeProNative Result -------");
print(result);
return result;
} catch (e) {
return "Error: $e";
}
}
static Future<String> scanResultsNative(List<String> deviceType) async { static Future<String> scanResultsNative(List<String> deviceType) async {
try { try {
String result; String result;
@ -31,6 +46,7 @@ class BleChannel {
print("----------Flutter stopNativeScan -------"); print("----------Flutter stopNativeScan -------");
result = await platform.invokeMethod('stopScan'); result = await platform.invokeMethod('stopScan');
result = await platform.invokeMethod('stopScanCheckMe');
print("----------Flutter Result stopNativeScan -------"); print("----------Flutter Result stopNativeScan -------");
print(result); print(result);
@ -55,6 +71,21 @@ class BleChannel {
} }
} }
static Future<String> connectDeviceCheckMe(List<String> device) async {
try {
String result;
print("----------Flutter init connectDeviceCheckMe -------");
result = await platform.invokeMethod('connectDeviceCheckMe', device);
print("----------Flutter Result connectDeviceCheckMe -------");
print(result);
return result;
} catch (e) {
return "Error: $e";
}
}
static Future<String> getECGFilesList(List<String> device) async { static Future<String> getECGFilesList(List<String> device) async {
try { try {
print("----------Flutter getECGFilesList -------"); print("----------Flutter getECGFilesList -------");
@ -95,6 +126,7 @@ class BleChannel {
try { try {
print("----------Flutter disconnect -------"); print("----------Flutter disconnect -------");
final String result = await platform.invokeMethod('disconnectDevice'); final String result = await platform.invokeMethod('disconnectDevice');
final String result2 = await platform.invokeMethod('disconnectCheckMe');
print("----------Flutter Result -------"); print("----------Flutter Result -------");
print(result); print(result);
return result; return result;
@ -102,4 +134,16 @@ class BleChannel {
return "Error: $e"; return "Error: $e";
} }
} }
static Future<String> getDeviceInfoCheckMePro() async {
try {
print("----------Flutter getDeviceInfoCheckMePro -------");
final String result = await platform.invokeMethod('getDeviceInfoCheckMePro');
print("----------Flutter getDeviceInfoCheckMePro result -------");
print(result);
return result;
} catch (e) {
return "Error: $e";
}
}
} }

@ -0,0 +1,61 @@
class CheckMeInfoModel {
String region;
String model;
String hardwareVer;
String softwareVer;
String languageVer;
String curLanguage;
String fileVer;
String sPCPVer;
String application;
String sN;
String branchCode;
CheckMeInfoModel(
{this.region,
this.model,
this.hardwareVer,
this.softwareVer,
this.languageVer,
this.curLanguage,
this.fileVer,
this.sPCPVer,
this.application,
this.sN,
this.branchCode});
@override
String toString() {
return 'CheckMeInfoModel{region: $region, model: $model, hardwareVer: $hardwareVer, softwareVer: $softwareVer, languageVer: $languageVer, curLanguage: $curLanguage, fileVer: $fileVer, sPCPVer: $sPCPVer, application: $application, sN: $sN, branchCode: $branchCode}';
}
CheckMeInfoModel.fromJson(Map<String, dynamic> json) {
region = json['Region'];
model = json['Model'];
hardwareVer = json['HardwareVer'];
softwareVer = json['SoftwareVer'];
languageVer = json['LanguageVer'];
curLanguage = json['CurLanguage'];
fileVer = json['FileVer'];
sPCPVer = json['SPCPVer'];
application = json['Application'];
sN = json['SN'];
branchCode = json['BranchCode'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['Region'] = this.region;
data['Model'] = this.model;
data['HardwareVer'] = this.hardwareVer;
data['SoftwareVer'] = this.softwareVer;
data['LanguageVer'] = this.languageVer;
data['CurLanguage'] = this.curLanguage;
data['FileVer'] = this.fileVer;
data['SPCPVer'] = this.sPCPVer;
data['Application'] = this.application;
data['SN'] = this.sN;
data['BranchCode'] = this.branchCode;
return data;
}
}

@ -1,24 +0,0 @@
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}';
}
}

@ -1,24 +0,0 @@
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;
}
}

@ -1,22 +0,0 @@
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();
}
}

@ -1,20 +0,0 @@
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();
}
}

@ -1,41 +0,0 @@
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
}
}

@ -1,11 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:developer'; 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/check_me_info_model.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/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/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/ble_devices_model.dart';
@ -34,6 +30,8 @@ String kRealTimeDataBPMeasuring = "RealTimeDataBPMeasuring";
String kRealTimeDataBPResult = "RealTimeDataBPResult"; String kRealTimeDataBPResult = "RealTimeDataBPResult";
String kOxyRtParam = "OxyRtParam"; String kOxyRtParam = "OxyRtParam";
String kDevicesList = "DevicesList"; String kDevicesList = "DevicesList";
String kDevicesListCheckMe = "DevicesListCheckMe";
String kInfoDataCheckMe = "infoDataCheckMe";
String kRealTimeDataECGMeasuring = "RealTimeDataECGMeasuring"; // This is for the device that measures BP and ECG also Like BP2 0567 String kRealTimeDataECGMeasuring = "RealTimeDataECGMeasuring"; // This is for the device that measures BP and ECG also Like BP2 0567
String kRealTimeDataECGResult = "RealTimeDataECGResult"; String kRealTimeDataECGResult = "RealTimeDataECGResult";
String kRealTimeDataECG = "RealTimeDataECG"; String kRealTimeDataECG = "RealTimeDataECG";
@ -105,7 +103,14 @@ class MyTrackersViewModel extends ChangeNotifier {
}; };
List<String> ecgEnabledDevices = ["BP2 0567", "DuoEK", "ER1", "PM101897"]; List<String> ecgEnabledDevices = ["BP2 0567", "DuoEK", "ER1", "PM101897"];
List<String> andesFitDevices = ["BPM", "PM101897", "SDIC", "TEMP", "Samico GL", "BLE-MSA", "Checkme 1316"]; List<String> andesFitDevices = [
"BPM",
"PM101897",
"SDIC",
"TEMP",
"Samico GL",
"BLE-MSA",
];
StreamSubscription bleDevicesStream; StreamSubscription bleDevicesStream;
@ -206,6 +211,13 @@ class MyTrackersViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
String checkMeInfo;
void updateCheckMeInfoModel(String mapData) {
checkMeInfo = mapData;
notifyListeners();
}
Widget getFilesListWidget(List<ECGFileDetailModel> filesList, BuildContext context) { Widget getFilesListWidget(List<ECGFileDetailModel> filesList, BuildContext context) {
return Material( return Material(
child: SizedBox( child: SizedBox(
@ -300,6 +312,25 @@ class MyTrackersViewModel extends ChangeNotifier {
}); });
} }
Future<void> startSearchingForCheckMePro() async {
log("selectedTracker in startSearchingForCheckMePro: ${currentSelectedTrackerType.name}");
await checkBLEPermissions();
eventChannel.receiveBroadcastStream().listen((event) {
print('Received event---: $event');
print(event['type']);
if (event['type'] == kDevicesListCheckMe) {
List list = [json.decode(event['data'])];
parsesDevicesList(list);
}
if (event['type'] == kInfoDataCheckMe) {
updateCheckMeInfoModel(event['data'].toString());
}
});
await scanForCheckMe();
}
Future<void> startSearchingForTracker() async { Future<void> startSearchingForTracker() async {
log("selectedTracker: ${currentSelectedTrackerType.name}"); log("selectedTracker: ${currentSelectedTrackerType.name}");
@ -369,7 +400,9 @@ class MyTrackersViewModel extends ChangeNotifier {
void resetList() { void resetList() {
devicesList.clear(); devicesList.clear();
if (bleDevicesStream != null) {
bleDevicesStream.cancel(); bleDevicesStream.cancel();
}
FlutterBluePlus.stopScan(); FlutterBluePlus.stopScan();
secondsToWaitForNativeScan = 5; secondsToWaitForNativeScan = 5;
} }
@ -383,8 +416,12 @@ class MyTrackersViewModel extends ChangeNotifier {
} }
Future<void> connectDevice(BleDeviceModel device) async { Future<void> connectDevice(BleDeviceModel device) async {
if (currentSelectedTrackerType == TrackerTypeEnum.AllInOneTracker) {
await BleChannel.connectDeviceCheckMe([device.name, device.model.toString(), currentSelectedTrackerType.name]);
} else {
await BleChannel.connectDevice([device.name, device.model.toString(), currentSelectedTrackerType.name]); await BleChannel.connectDevice([device.name, device.model.toString(), currentSelectedTrackerType.name]);
} }
}
Future<void> disConnectDevice() async { Future<void> disConnectDevice() async {
isDeviceSelected = false; isDeviceSelected = false;
@ -395,6 +432,10 @@ class MyTrackersViewModel extends ChangeNotifier {
await BleChannel.scanResultsNative([currentSelectedTrackerType.name]); await BleChannel.scanResultsNative([currentSelectedTrackerType.name]);
} }
Future<void> scanForCheckMe() async {
await BleChannel.scanCheckMeProNative();
}
Future<void> stopNativeScan() async { Future<void> stopNativeScan() async {
await BleChannel.stopNativeScan(); await BleChannel.stopNativeScan();
} }
@ -1061,233 +1102,7 @@ class MyTrackersViewModel extends ChangeNotifier {
int result = 0; int result = 0;
int currentPkg = 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 { Future<void> connectAndesfitAllInOneDevice(BluetoothDevice device) async {
log("deviceToConnect: ${device.toString()}"); 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;
} }
} }

Loading…
Cancel
Save