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'
// Dependency on a remote binary
// implementation 'com.example.android:app-magic:12.3'
// implementation 'com.example.android:app-magic:12.3'
// Native Dependency
@ -146,7 +146,8 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
implementation 'androidx.work:work-runtime:2.7.0-alpha05'
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
implementation 'no.nordicsemi.android:ble:2.2.4'
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" />
<activity
android:name=".MainActivity"
android:name="com.cloud.diplomaticquarterapp.MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:launchMode="singleTop"

@ -1,12 +1,14 @@
package com.ejada.hmg
package com.cloud.diplomaticquarterapp
import android.util.Log
import android.view.WindowManager
import com.cloud.diplomaticquarterapp.check_me_pro.ble.manager.BleScanManager
import com.ejada.hmg.utils.*
import com.ejada.hmg.*
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
import com.lepu.blepro.observer.BleChangeObserver
import com.cloud.diplomaticquarterapp.ble.BleBridge
@Suppress("DEPRECATION")
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)
PlatformBridge(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) {
// val mChannel = NotificationChannel("video_call_noti", "video call", NotificationManager.IMPORTANCE_HIGH)
// val soundUri = Uri.parse("android.resource://" + getApplicationContext()
@ -38,7 +44,7 @@ class MainActivity : FlutterFragmentActivity() {
// val time = timeToMillis("04:00:00", "HH:mm:ss")
}
}
// 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.bluetooth.BluetoothDevice
import android.os.Build
import android.os.Handler
import com.ejada.hmg.MainActivity
import android.util.Log
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.EventChannel
import android.util.SparseArray
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.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
@ -33,17 +39,22 @@ import com.lepu.blepro.ext.er2.Er2EcgFile
import com.lepu.blepro.ext.er2.Er2File
import com.lepu.blepro.ext.er2.RtData
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.Er1File
import com.lepu.blepro.ext.er1.Er1HrFile
import com.lepu.blepro.ext.pc60fw.RtParam
import com.lepu.blepro.ext.sp20.RtWave
import com.lepu.blepro.objs.Bluetooth
import com.lepu.blepro.objs.BluetoothController
import com.lepu.blepro.utils.DateUtil
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.json.JSONObject
import java.io.File
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>()
var ecgList: ArrayList<EcgData> = arrayListOf()
private val bleListCheckMe: MutableList<BleBean> = ArrayList()
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 SCAN_DEVICE = "scanDevices"
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_CHECK_ME = "connectDeviceCheckMe"
private const val SCAN_DEVICE_EKG = "scan_ekg"
private const val EKG_FILES_LIST = "ecgFilesList"
private const val FACTORY_RESET_ECG = "factoryResetECG"
private const val BP2_FILES_LIST = "bp2FilesList"
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(
Bluetooth.MODEL_PC60FW, Bluetooth.MODEL_PC_60NW, Bluetooth.MODEL_PC_60NW_1,
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")
fun create() {
fun createBleBridge(bleScanManager: BleScanManager, scanResultHandler: (String, BluetoothDevice) -> Unit) {
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
Echannel = EventChannel(flutterEngine.dartExecutor.binaryMessenger, EVENTCHANNEL)
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>)
} else if (methodCall.method == DISCONNECT_DEVICE) {
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) {
// scanDeviceEKG(methodCall, result)
} 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>)
} else if (methodCall.method == BP2_FILES_LIST) {
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 {
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)
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()
}
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)
private fun subscribeToStreams(deviceName: String) {
@ -544,17 +676,13 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
}
}
}
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun connectDevice(device: List<String>) {
println("connectDevice: $device");
model = device[1].toInt()
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() {
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.wifi.*
import android.os.Build
import android.os.PatternMatcher
import android.provider.Settings
import android.util.Log
import androidx.annotation.RequiresApi
import com.ejada.hmg.MainActivity
import com.cloud.diplomaticquarterapp.MainActivity
import com.ejada.hmg.utils.HMGUtils

@ -2,7 +2,7 @@ package com.ejada.hmg.hmgwifi
import android.annotation.SuppressLint
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.httpGet
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.COMPLETED
import android.util.Log
import com.ejada.hmg.MainActivity
import com.cloud.diplomaticquarterapp.MainActivity
import com.ejada.hmg.utils.HMGUtils
class WPA(mainActivity: MainActivity, SSID:String) {

@ -12,9 +12,8 @@ import android.net.wifi.SupplicantState.COMPLETED
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.ejada.hmg.MainActivity
import com.cloud.diplomaticquarterapp.MainActivity
import com.ejada.hmg.utils.HMGUtils
import java.security.cert.X509Certificate
class WpaEnterprise(private val mainActivity: MainActivity, private var SSID: String) {
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
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.Result
class FlutterText{

@ -1,5 +1,6 @@
package com.ejada.hmg.utils
import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
@ -13,10 +14,8 @@ import android.widget.Toast
import androidx.annotation.Nullable
import androidx.core.app.NotificationCompat
import androidx.core.app.TaskStackBuilder
import com.ejada.hmg.BuildConfig
import com.ejada.hmg.MainActivity
import com.cloud.diplomaticquarterapp.MainActivity
import com.ejada.hmg.R
import com.ejada.hmg.geofence.GeoZoneModel
import com.github.kittinunf.fuel.core.extensions.jsonBody
import com.github.kittinunf.fuel.httpPost
import com.google.gson.Gson
@ -29,22 +28,24 @@ import org.json.JSONObject
import java.text.SimpleDateFormat
import java.util.*
import kotlin.concurrent.timerTask
import com.ejada.hmg.BuildConfig
class HMGUtils {
companion object{
companion object {
private lateinit var platformChannel: MethodChannel
fun getPlatformChannel():MethodChannel{
fun getPlatformChannel(): MethodChannel {
return platformChannel
}
fun setPlatformChannel(channel: MethodChannel){
fun setPlatformChannel(channel: MethodChannel) {
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()
if(repeat)
if (repeat)
timer.schedule(timerTask {
tick(timer)
}, delay, delay)
@ -56,42 +57,44 @@ class HMGUtils {
return timer
}
fun popMessage(context: MainActivity, message: String){
fun popMessage(context: MainActivity, message: String) {
context.runOnUiThread {
Toast.makeText(context, message, Toast.LENGTH_LONG).show()
}
}
fun popFlutterText(context: MainActivity, key: String){
fun popFlutterText(context: MainActivity, key: String) {
context.runOnUiThread {
FlutterText.with(key){
FlutterText.with(key) {
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 lang = pref.getString(PREF_KEY_LANGUAGE, "ar")
return if (lang == "ar") 2 else 1
}
fun defaultHTTPParams(context: Context) : Map<String, Any?>{
fun defaultHTTPParams(context: Context): Map<String, Any?> {
return mapOf(
"ZipCode" to "966",
"VersionID" to 5.8,
"Channel" to 3,
"LanguageID" to getLanguageCode(context),
"IPAdress" to "10.20.10.20",
"generalid" to "Cs2020@2016$2958",
"PatientOutSA" to 0,
"SessionID" to null,
"isDentalAllowedBackend" to false,
"DeviceTypeID" to 2)
"ZipCode" to "966",
"VersionID" to 5.8,
"Channel" to 3,
"LanguageID" to getLanguageCode(context),
"IPAdress" to "10.20.10.20",
"generalid" to "Cs2020@2016$2958",
"PatientOutSA" to 0,
"SessionID" to null,
"isDentalAllowedBackend" to false,
"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) {
val jobScheduler: JobScheduler = context.getSystemService(JobScheduler::class.java)
@ -100,17 +103,22 @@ class HMGUtils {
builder.setPersisted(true)
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.setOverrideDeadline((intervalMillis + deadlineMillis)) // maximum delay
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)
}else{
Logs.save(context,"ScheduleJob", "${pendingIntentClassType.simpleName}: Failed to scheduled Job",Logs.STATUS.ERROR)
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
)
} else {
Logs.save(context, "ScheduleJob", "${pendingIntentClassType.simpleName}: Failed to scheduled Job", Logs.STATUS.ERROR)
}
} 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"
fun timeToMillis(time:String, format:String):Long{
fun timeToMillis(time: String, format: String): Long {
val sdf = SimpleDateFormat(format, Locale.US)
val millis = sdf.parse(time).time + TimeZone.getDefault().rawOffset
return millis
@ -132,11 +140,14 @@ fun sendNotification(context: Context, title: String, @Nullable subtitle: String
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
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 channel = NotificationChannel(NOTIFICATION_CHANNEL_ID,
name,
NotificationManager.IMPORTANCE_DEFAULT)
val channel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
name,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
}
@ -144,15 +155,15 @@ fun sendNotification(context: Context, title: String, @Nullable subtitle: String
val intent = Intent(context, MainActivity::class.java)
val stackBuilder = TaskStackBuilder.create(context)
.addParentStack(MainActivity::class.java)
.addNextIntent(intent)
.addParentStack(MainActivity::class.java)
.addNextIntent(intent)
val notificationPendingIntent = stackBuilder.getPendingIntent(getUniqueId(), PendingIntent.FLAG_UPDATE_CURRENT)
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(notificationPendingIntent)
.setAutoCancel(true)
.setContentTitle(title)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(notificationPendingIntent)
.setAutoCancel(true)
.setContentTitle(title)
subtitle.let { notification.setContentText(it) }
message.let { notification.setSubText(it) }
@ -167,59 +178,63 @@ fun getUniqueId() = ((System.currentTimeMillis() % 10000).toInt())
object DateUtils {
@JvmStatic
fun dateTimeNow() : String {
fun dateTimeNow(): String {
val format = SimpleDateFormat("dd-MMM-yyy hh:mm:ss")
return format.format(Date())
}
}
fun isJSONValid(jsonString: String?): Boolean {
try { JSONObject(jsonString) } catch (ex: JSONException) {
try { JSONArray(jsonString) } catch (ex1: JSONException) {
try {
JSONObject(jsonString)
} catch (ex: JSONException) {
try {
JSONArray(jsonString)
} catch (ex1: JSONException) {
return false
}
}
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)
var logs = pref.getString("LOGS", "")
logs += "$tag -> $message \n"
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)
return pref.getString("LOGS", "")
}
class HTTPResponse<T>(data: T){
final var data:T = data
class HTTPResponse<T>(data: T) {
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 type = object : TypeToken<T>() {}.type
val type = object : TypeToken<T>() {}.type
val jsonBody = gson.toJson(body)
url.httpPost()
.jsonBody(jsonBody, Charsets.UTF_8)
.timeout(10000)
.header("Content-Type", "application/json")
.header("Allow", "*/*")
.response { request, response, result ->
result.doAsyncResult { }
result.fold({ data ->
val dataString = String(data)
if (isJSONValid(dataString)) {
val responseData = gson.fromJson<T>(dataString, type)
onSuccess(HTTPResponse(responseData))
} else {
onError(Exception("Invalid response from server (Not a valid JSON)"))
}
}, {
onError(it)
})
.jsonBody(jsonBody, Charsets.UTF_8)
.timeout(10000)
.header("Content-Type", "application/json")
.header("Allow", "*/*")
.response { request, response, result ->
result.doAsyncResult { }
result.fold({ data ->
val dataString = String(data)
if (isJSONValid(dataString)) {
val responseData = gson.fromJson<T>(dataString, type)
onSuccess(HTTPResponse(responseData))
} else {
onError(Exception("Invalid response from server (Not a valid JSON)"))
}
}, {
onError(it)
})
}
}
}

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

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

@ -11,7 +11,7 @@ import android.widget.Toast
import androidx.core.app.ActivityCompat.startActivityForResult
import android.net.wifi.WifiManager
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.geofence.GeoZoneModel
import com.ejada.hmg.geofence.HMG_Geofence

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

@ -36,8 +36,12 @@ class _BleDevicesScreenState extends State<BleDevicesScreen> {
@override
void initState() {
myTrackersVm = context.read<MyTrackersViewModel>();
myTrackersVm.startSearchingForTracker();
myTrackersVm.startTimerForNativeScan();
if (myTrackersVm.currentSelectedTrackerType == TrackerTypeEnum.AllInOneTracker) {
myTrackersVm.startSearchingForCheckMePro();
} else {
myTrackersVm.startSearchingForTracker();
myTrackersVm.startTimerForNativeScan();
}
super.initState();
}
@ -48,7 +52,7 @@ class _BleDevicesScreenState extends State<BleDevicesScreen> {
void onDeviceTapped(BleDeviceModel device) {
myTrackersVm.isDeviceSelected = true;
log("isDeviceSelected from Screen:${myTrackersVm.isDeviceSelected}");
log("isDeviceSelected from Screen: ${myTrackersVm.isDeviceSelected}");
FlutterBluePlus.stopScan();
switch (device.deviceType) {
case TrackerTypeEnum.OxymeterTracker:
@ -112,10 +116,9 @@ class _BleDevicesScreenState extends State<BleDevicesScreen> {
break;
case TrackerTypeEnum.AllInOneTracker:
if (myTrackersVm.isDeviceFromAndesFit(device.name)) {
Navigator.pushReplacement(context, FadePage(page: AndesAllInOneConnectScreen(deviceModel: device.andesfitBluetoothDevice)));
return;
}
// TODO: Handle this case.
Navigator.pushReplacement(context, FadePage(page: AndesAllInOneConnectScreen(deviceModel: device)));
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_models/andesfit_devices/all_in_one_monitor/check_me_response.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/device_info.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
@ -16,9 +10,6 @@ import 'package:provider/provider.dart';
class SelectTrackerType extends StatelessWidget {
const SelectTrackerType();
Uint8List convertIntArrayToByteArray(List<int> intArray) {
return Uint8List.fromList(intArray);
}
List<Widget> myTrackersTypeList({BuildContext context}) {
List<Widget> medical = [];

@ -10,6 +10,21 @@ class BleChannel {
// static const platform_ios_ekg = MethodChannel('BLE-Platform-Bridge-IOS-EKG');
//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 {
try {
String result;
@ -31,6 +46,7 @@ class BleChannel {
print("----------Flutter stopNativeScan -------");
result = await platform.invokeMethod('stopScan');
result = await platform.invokeMethod('stopScanCheckMe');
print("----------Flutter Result stopNativeScan -------");
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 {
try {
print("----------Flutter getECGFilesList -------");
@ -95,6 +126,7 @@ class BleChannel {
try {
print("----------Flutter disconnect -------");
final String result = await platform.invokeMethod('disconnectDevice');
final String result2 = await platform.invokeMethod('disconnectCheckMe');
print("----------Flutter Result -------");
print(result);
return result;
@ -102,4 +134,16 @@ class BleChannel {
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:convert';
import 'dart:developer';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/check_me_response.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/device_info.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/end_read_pkg.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/read_content_pkg.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/start_read_pkg.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/check_me_info_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/bt_constants.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/weight_data_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/ble_devices_model.dart';
@ -34,6 +30,8 @@ String kRealTimeDataBPMeasuring = "RealTimeDataBPMeasuring";
String kRealTimeDataBPResult = "RealTimeDataBPResult";
String kOxyRtParam = "OxyRtParam";
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 kRealTimeDataECGResult = "RealTimeDataECGResult";
String kRealTimeDataECG = "RealTimeDataECG";
@ -105,7 +103,14 @@ class MyTrackersViewModel extends ChangeNotifier {
};
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;
@ -206,6 +211,13 @@ class MyTrackersViewModel extends ChangeNotifier {
notifyListeners();
}
String checkMeInfo;
void updateCheckMeInfoModel(String mapData) {
checkMeInfo = mapData;
notifyListeners();
}
Widget getFilesListWidget(List<ECGFileDetailModel> filesList, BuildContext context) {
return Material(
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 {
log("selectedTracker: ${currentSelectedTrackerType.name}");
@ -369,7 +400,9 @@ class MyTrackersViewModel extends ChangeNotifier {
void resetList() {
devicesList.clear();
bleDevicesStream.cancel();
if (bleDevicesStream != null) {
bleDevicesStream.cancel();
}
FlutterBluePlus.stopScan();
secondsToWaitForNativeScan = 5;
}
@ -383,7 +416,11 @@ class MyTrackersViewModel extends ChangeNotifier {
}
Future<void> connectDevice(BleDeviceModel device) async {
await BleChannel.connectDevice([device.name, device.model.toString(), currentSelectedTrackerType.name]);
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]);
}
}
Future<void> disConnectDevice() async {
@ -395,6 +432,10 @@ class MyTrackersViewModel extends ChangeNotifier {
await BleChannel.scanResultsNative([currentSelectedTrackerType.name]);
}
Future<void> scanForCheckMe() async {
await BleChannel.scanCheckMeProNative();
}
Future<void> stopNativeScan() async {
await BleChannel.stopNativeScan();
}
@ -1061,233 +1102,7 @@ class MyTrackersViewModel extends ChangeNotifier {
int result = 0;
int currentPkg = 0;
BluetoothCharacteristic allInOneWriteCharacteristics;
sendCommand(List<int> bytes) {
log("trying to write on $allInOneWriteCharacteristics");
allInOneWriteCharacteristics.write(bytes, withoutResponse: true);
}
Future<void> connectAndesfitAllInOneDevice(BluetoothDevice device) async {
log("deviceToConnect: ${device.toString()}");
device.connectionState.listen((BluetoothConnectionState state) async {
if (state == BluetoothConnectionState.disconnected) {
isAndesfitDeviceConnected = false;
notifyListeners();
}
if (state == BluetoothConnectionState.connected) {
isAndesfitDeviceConnected = true;
notifyListeners();
bleDevicesStream.cancel();
List<BluetoothService> services = await device.discoverServices();
services.forEach((service) {
if (service.serviceUuid.toString().toLowerCase() == BLEUtils.ALL_IN_ONE_SERVICE.toLowerCase()) {
service.characteristics.forEach((characteristic) async {
log("characteristics : ${characteristic.characteristicUuid}");
if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.ALL_IN_ONE_READ_CHARACTERISTIC.toLowerCase()) {
characteristic.onValueReceived.listen((event) {
log("onValueReceived 9A57 Stream");
log(event.toString());
handleDataPool(event);
});
await Future.delayed(Duration(milliseconds: 1000)).then((value) async {
log("-----Delayed 9A57 notify true done-----");
if (!characteristic.isNotifying) await characteristic.setNotifyValue(true).catchError((err) {});
});
} else if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.ALL_IN_ONE_WRITE_CHARACTERISTIC.toLowerCase()) {
print(characteristic.characteristicUuid);
print(characteristic.properties.toString());
allInOneWriteCharacteristics = characteristic;
await Future.delayed(Duration(milliseconds: 3000)).then((value) => getFile("usr.dat"));
// await Future.delayed(Duration(milliseconds: 3000)).then((value) async {
// characteristic.write([-86, 3, -4, 0, 0, 8, 0, 117, 115, 114, 46, 100, 97, 116, 0, 124], withoutResponse: true).then((value) {
// print("----E1A3 get User Info command data written----");
// });
// });
}
});
}
});
}
});
await device.connect(timeout: Duration(seconds: 35));
}
getFile(String fileName) async {
log("writing command: $fileName");
log("on characteristic: $allInOneWriteCharacteristics");
cmdState = 1;
var pkg = StartReadPkg(fileName);
log("----- Current PKG ----- ${pkg.buf.toString()}");
sendCommand(pkg.buf);
}
List<int> handleDataPool(List<int> bytes) {
log("bytes I got in dataPool: $bytes");
var bytesLeft = bytes;
if (bytes == null || bytes.length < 8) {
return bytes;
}
for (int i = 0; i < bytes.length - 7; i++) {
if (bytes[i] != 0x55.toByte() || bytes[i + 1] != (bytes[i + 2].inv()).toByte()) {
continue;
}
// need content length
var len = bytes.sublist(i + 5, i + 7).toUInt();
if (i + 8 + len > bytes.length) {
continue;
}
var temp = bytes.sublist(i, i + 8 + len);
if (temp.last == temp.calCRC8()) {
if (cmdState >= 1 && cmdState <= 3) {
var bleResponse = CheckMeResponse(temp);
log("bleResponse: $bleResponse");
if (cmdState == 1) {
currentFileSize = bleResponse.content.toUInt();
pkgTotal = currentFileSize ~/ 512;
if (bleResponse.cmd == 1) {
result = 1;
var pkg = EndReadPkg();
sendCommand(pkg.buf);
cmdState = 3;
} else if (bleResponse.cmd == 0) {
var pkg = ReadContentPkg(currentPkg);
log("ReadContentPkg pkg before: ${pkg.buf}");
if (pkg.buf.last == 204) {
pkg.buf.last = 106;
}
log("ReadContentPkg pkg: ${pkg.buf}");
//[-86, 4, -5, 0, 0, 0, 204] --> DART
//[-86, 4, -5, 0, 0, 0, 106] --> KOTLIN
sendCommand(pkg.buf);
currentPkg++;
cmdState = 2;
}
} else if (cmdState == 2) {
// bleResponse.content.apply {
// fileData = add(fileData, this)
// fileData?.let {
// dataScope.launch {
// fileProgressChannel.send(
// FileProgress(
// currentFileName,
// it.size * 100 / currentFileSize,
// true
// )
// )
// }
// }
// }
if (currentPkg > pkgTotal) {
// fileData?.apply {
// result = 0
// Log.i("file", "receive $currentFileName")
// File(Constant.getPathX(currentFileName)).writeBytes(this)
// }
var pkg = EndReadPkg();
log("file bytes ${pkg.buf}");
sendCommand(pkg.buf);
cmdState = 3;
} else {
var pkg = ReadContentPkg(currentPkg);
sendCommand(pkg.buf);
currentPkg++;
}
} else if (cmdState == 3) {
currentPkg = 0;
cmdState = 0;
// dataScope.launch {
// fileProgressChannel.send(
// FileProgress(
// currentFileName,
// 100,
// result == 0
// )
// )
// fileChannel.send(result)
// }
}
} else if (cmdState == 4) {
var deviceInfo = DeviceInfo(temp);
}
List<int> tempBytes;
if (i + 8 + len == bytes.length) {
tempBytes = null;
} else {
tempBytes = bytes.sublist(i + 8 + len, bytes.length);
}
return handleDataPool(tempBytes);
}
}
return bytesLeft;
}
}
extension BTExtensions on int {
int toByte() {
const int maxUnsignedByteValue = 255;
const int maxSignedByteValue = 127;
const int minSignedByteValue = -128;
// Mask out all but the least significant 8 bits
int maskedValue = this & maxUnsignedByteValue;
// Check if the MSB is set (indicating a negative value)
bool isNegative = maskedValue & (1 << 7) != 0;
// If the MSB is set, convert to a signed byte using two's complement
if (isNegative) {
// Invert the bits
maskedValue = ~maskedValue & maxUnsignedByteValue;
// Add 1 to get the two's complement representation
maskedValue = (maskedValue + 1) & maxSignedByteValue;
// Negate the value
maskedValue *= -1;
}
return maskedValue;
}
int inv() {
return ~this;
}
}
extension BTExtensionss on List<int> {
int toUInt() {
var result = 0;
for (var i = 0; i < this.length; i++) {
result += this[i].toUnsigned(8) << (i * 8);
}
return result;
}
int calCRC8() {
if (this == null || this.isEmpty) {
return 0;
}
int crc = 0;
for (int i = 0; i < this.length - 1; i++) {
crc = BTConstants.Table_CRC8[0xFF & (crc ^ this[i].toByte())];
}
return crc;
}
}

Loading…
Cancel
Save