diff --git a/android/app/build.gradle b/android/app/build.gradle index 774ae2fb..f911635e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -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') diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 036443f3..359c2843 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -71,7 +71,7 @@ + // 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() - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/BleBridge.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/BleBridge.kt index b4686dce..84bd9eb7 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/BleBridge.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/BleBridge.kt @@ -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() var ecgList: ArrayList = arrayListOf() + private val bleListCheckMe: MutableList = 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 = java.util.ArrayList() + + + private val userChannel = Channel(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) } 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) + } 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) } 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) { - 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) { + 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) { diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/UiChannel.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/UiChannel.kt new file mode 100644 index 00000000..5f4c18d4 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/UiChannel.kt @@ -0,0 +1,7 @@ +package com.cloud.diplomaticquarterapp.check_me_pro + +import kotlinx.coroutines.channels.Channel + +object UiChannel { + val progressChannel = Channel(Channel.CONFLATED) +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/BleBean.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/BleBean.kt new file mode 100644 index 00000000..8833f420 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/BleBean.kt @@ -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) diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/BpBean.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/BpBean.kt new file mode 100644 index 00000000..12fc1eac --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/BpBean.kt @@ -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 +) diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/DlcBean.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/DlcBean.kt new file mode 100644 index 00000000..29a84374 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/DlcBean.kt @@ -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 +) diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/EcgBean.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/EcgBean.kt new file mode 100644 index 00000000..50ed81c5 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/EcgBean.kt @@ -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 +) diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/GluBean.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/GluBean.kt new file mode 100644 index 00000000..0a61f3b6 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/GluBean.kt @@ -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="" +) diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/OxyBean.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/OxyBean.kt new file mode 100644 index 00000000..b12829e3 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/OxyBean.kt @@ -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 +) diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/PedBean.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/PedBean.kt new file mode 100644 index 00000000..36e6aa09 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/PedBean.kt @@ -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 { + override fun createFromParcel(parcel: Parcel): PedBean { + return PedBean(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } +} diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/SlpBean.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/SlpBean.kt new file mode 100644 index 00000000..d2a06abe --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/SlpBean.kt @@ -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 + +) diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/TmpBean.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/TmpBean.kt new file mode 100644 index 00000000..5128c569 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/TmpBean.kt @@ -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 +) diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/UserBean.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/UserBean.kt new file mode 100644 index 00000000..009c7856 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/bean/UserBean.kt @@ -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 +) diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/constant/BTConstant.java b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/constant/BTConstant.java new file mode 100644 index 00000000..627df162 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/constant/BTConstant.java @@ -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; +} diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/BpInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/BpInfo.kt new file mode 100644 index 00000000..a8b89cff --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/BpInfo.kt @@ -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 = arrayListOf() + + + 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) + } + + +} + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/CheckMeResponse.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/CheckMeResponse.kt new file mode 100644 index 00000000..5b3af112 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/CheckMeResponse.kt @@ -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) +} + + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/DeviceInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/DeviceInfo.kt new file mode 100644 index 00000000..229942d1 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/DeviceInfo.kt @@ -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) + + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/DlcInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/DlcInfo.kt new file mode 100644 index 00000000..b0175118 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/DlcInfo.kt @@ -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 = arrayListOf() + + + 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) + } + + +} + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/EcgInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/EcgInfo.kt new file mode 100644 index 00000000..1aa8332e --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/EcgInfo.kt @@ -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 = arrayListOf() + + + 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) + } + + +} + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/EcgWaveInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/EcgWaveInfo.kt new file mode 100644 index 00000000..bfacff86 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/EcgWaveInfo.kt @@ -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 + + } + + +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/GluInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/GluInfo.kt new file mode 100644 index 00000000..35b6ffd6 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/GluInfo.kt @@ -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 = arrayListOf() + + + 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) + } + + +} + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/OxyInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/OxyInfo.kt new file mode 100644 index 00000000..08ddc44f --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/OxyInfo.kt @@ -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 = arrayListOf() + + + 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) + } + + +} + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/OxyWaveInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/OxyWaveInfo.kt new file mode 100644 index 00000000..7c3b6f55 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/OxyWaveInfo.kt @@ -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() + } + } + + +} + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/PedInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/PedInfo.kt new file mode 100644 index 00000000..58f74688 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/PedInfo.kt @@ -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 = arrayListOf() + + + 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) + } + + +} + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/SlpInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/SlpInfo.kt new file mode 100644 index 00000000..e3f396e5 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/SlpInfo.kt @@ -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 = arrayListOf() + 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) + } + + +} + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/TmpInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/TmpInfo.kt new file mode 100644 index 00000000..2f9f23d6 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/TmpInfo.kt @@ -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 = arrayListOf() + + + 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) + } + + +} + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/UserInfo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/UserInfo.kt new file mode 100644 index 00000000..ddc2ed85 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/format/UserInfo.kt @@ -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 = 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) + } + + +} + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/manager/BleDataManager.java b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/manager/BleDataManager.java new file mode 100644 index 00000000..d0122096 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/manager/BleDataManager.java @@ -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"); +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/manager/BleScanManager.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/manager/BleScanManager.kt new file mode 100644 index 00000000..cff89423 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/manager/BleScanManager.kt @@ -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) {} + 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) + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/EndReadPkg.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/EndReadPkg.kt new file mode 100644 index 00000000..ce4a0a91 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/EndReadPkg.kt @@ -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) + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/GetDeviceInfoPkg.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/GetDeviceInfoPkg.kt new file mode 100644 index 00000000..e5e7c720 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/GetDeviceInfoPkg.kt @@ -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) + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/ReadContentPkg.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/ReadContentPkg.kt new file mode 100644 index 00000000..57ec69c4 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/ReadContentPkg.kt @@ -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) + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/StartReadPkg.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/StartReadPkg.kt new file mode 100644 index 00000000..e71003aa --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/pkg/StartReadPkg.kt @@ -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) + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/worker/BleDataWorker.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/worker/BleDataWorker.kt new file mode 100644 index 00000000..e81554b7 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/check_me_pro/ble/worker/BleDataWorker.kt @@ -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) -> Unit) { + private var pool: ByteArray? = null + private val deviceChannel = Channel(Channel.CONFLATED) + private val fileChannel = Channel(Channel.CONFLATED) + private val connectChannel = Channel(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(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() + } + +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Guest.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Guest.kt index 7b3cc2d1..e92070b5 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Guest.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Guest.kt @@ -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 diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Internet.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Internet.kt index dcfa5488..8641d37a 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Internet.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Internet.kt @@ -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 diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WPA.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WPA.kt index 61cc4f9f..6a8a2590 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WPA.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WPA.kt @@ -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) { diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WpaEnterprise.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WpaEnterprise.kt index e8e39344..9e0605f7 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WpaEnterprise.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WpaEnterprise.kt @@ -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" diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/ByteArray.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/ByteArray.kt new file mode 100644 index 00000000..2a8225eb --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/ByteArray.kt @@ -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() +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/CRCUtils.java b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/CRCUtils.java new file mode 100644 index 00000000..981c48fb --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/CRCUtils.java @@ -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; + } + +} diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/Constant.java b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/Constant.java new file mode 100644 index 00000000..0a92c478 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/Constant.java @@ -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() + "/"; + } + } +} diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/FlutterText.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/FlutterText.kt index 1a650074..977defbb 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/FlutterText.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/FlutterText.kt @@ -1,7 +1,6 @@ package com.ejada.hmg.utils import io.flutter.plugin.common.MethodChannel -import io.flutter.plugin.common.MethodChannel.Result class FlutterText{ diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt index 7fbf859a..9b6f5b79 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt @@ -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{ + fun defaultHTTPParams(context: Context): Map { 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 scheduleJob(context: Context, pendingIntentClassType:Class, jobId:Int, intervalDuration:String, deadlineMillis:Long = (30 * 1000)) { // default deadline: 30 Seconds + @SuppressLint("MissingPermission") + fun scheduleJob(context: Context, pendingIntentClassType: Class, 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(data: T){ - final var data:T = data +class HTTPResponse(data: T) { + final var data: T = data } -fun httpPost(url: String, body: Map, onSuccess: (response: HTTPResponse) -> Unit, onError: (error: Exception) -> Unit){ +fun httpPost(url: String, body: Map, onSuccess: (response: HTTPResponse) -> Unit, onError: (error: Exception) -> Unit) { val gson = Gson() - val type = object : TypeToken() {}.type + val type = object : TypeToken() {}.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(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(dataString, type) + onSuccess(HTTPResponse(responseData)) + } else { + onError(Exception("Invalid response from server (Not a valid JSON)")) + } + }, { + onError(it) + }) - } + } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/Logs.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/Logs.kt index d9dc209e..db4f911a 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/Logs.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/Logs.kt @@ -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{ - return Logs.Common.list(context,"GeofenceEvent", tag, status) + fun list(context: Context, tag: String? = null, status: Logs.STATUS? = null): List { + 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{ - return Logs.Common.list(context,"RegisterGeofence", tag, status) + fun list(context: Context, tag: String? = null, status: Logs.STATUS? = null): List { + 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{ - return Logs.Common.list(context,"Logs", tag, status) + fun list(context: Context, tag: String? = null, status: Logs.STATUS? = null): List { + 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(string,LogsContainerModel::class.java) + val string = pref.getString(key, "{}") + val json = gson.fromJson(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{ + fun list(context: Context, key: String, tag: String? = null, status: Logs.STATUS? = null): List { val pref = Logs.storage(context) - val string = pref.getString(key,"{}") - val json = gson.fromJson(string,LogsContainerModel::class.java) - if(tag == null && status == null) { + val string = pref.getString(key, "{}") + val json = gson.fromJson(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() - fun add(log:LogModel){ + fun add(log: LogModel) { LOGS.add(log) } } diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/OpenTokPlatformBridge.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/OpenTokPlatformBridge.kt index ebb04456..84e27e29 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/OpenTokPlatformBridge.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/OpenTokPlatformBridge.kt @@ -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 diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/PlatformBridge.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/PlatformBridge.kt index 9a66f4b3..c6b2476d 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/PlatformBridge.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/PlatformBridge.kt @@ -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 diff --git a/lib/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_all_in-one_connect_screen.dart b/lib/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_all_in-one_connect_screen.dart index 8b0ca498..02f3c0ad 100644 --- a/lib/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_all_in-one_connect_screen.dart +++ b/lib/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_all_in-one_connect_screen.dart @@ -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 @override void initState() { myTrackersVm = context.read(); - 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 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 @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 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, diff --git a/lib/pages/medical/my_trackers/ble_device_type_screens/ble_devices_screen.dart b/lib/pages/medical/my_trackers/ble_device_type_screens/ble_devices_screen.dart index 88993f14..da3470a9 100644 --- a/lib/pages/medical/my_trackers/ble_device_type_screens/ble_devices_screen.dart +++ b/lib/pages/medical/my_trackers/ble_device_type_screens/ble_devices_screen.dart @@ -36,8 +36,12 @@ class _BleDevicesScreenState extends State { @override void initState() { myTrackersVm = context.read(); - 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 { 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 { 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; } } diff --git a/lib/pages/medical/my_trackers/ble_device_type_screens/select_tracker_type.dart b/lib/pages/medical/my_trackers/ble_device_type_screens/select_tracker_type.dart index 05fb6694..471090d0 100644 --- a/lib/pages/medical/my_trackers/ble_device_type_screens/select_tracker_type.dart +++ b/lib/pages/medical/my_trackers/ble_device_type_screens/select_tracker_type.dart @@ -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 intArray) { - return Uint8List.fromList(intArray); - } List myTrackersTypeList({BuildContext context}) { List medical = []; diff --git a/lib/pages/medical/my_trackers/ble_helpers/ble_connect_helper.dart b/lib/pages/medical/my_trackers/ble_helpers/ble_connect_helper.dart index 9d5d7f46..1e92c67f 100644 --- a/lib/pages/medical/my_trackers/ble_helpers/ble_connect_helper.dart +++ b/lib/pages/medical/my_trackers/ble_helpers/ble_connect_helper.dart @@ -10,6 +10,21 @@ class BleChannel { // static const platform_ios_ekg = MethodChannel('BLE-Platform-Bridge-IOS-EKG'); //BLE-Platform-Bridge + static Future 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 scanResultsNative(List 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 connectDeviceCheckMe(List 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 getECGFilesList(List 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 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"; + } + } } diff --git a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/check_me_info_model.dart b/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/check_me_info_model.dart new file mode 100644 index 00000000..6d625ff1 --- /dev/null +++ b/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/check_me_info_model.dart @@ -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 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 toJson() { + final Map data = new Map(); + 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; + } +} diff --git a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/check_me_response.dart b/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/check_me_response.dart deleted file mode 100644 index 6ab90fc0..00000000 --- a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/check_me_response.dart +++ /dev/null @@ -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 bytes; - int cmd; - int pkgNo; - int len; - List content; - - CheckMeResponse(List 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}'; - } -} diff --git a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/device_info.dart b/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/device_info.dart deleted file mode 100644 index 971114ac..00000000 --- a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/device_info.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'dart:convert'; - -class DeviceInfo { - int len; - List content; - String deviceStr; - Map json; - - DeviceInfo(List 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 bytes) { - var result = 0; - for (var i = 0; i < bytes.length; i++) { - result += bytes[i].toUnsigned(8) << (i * 8); - } - return result; - } -} \ No newline at end of file diff --git a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/end_read_pkg.dart b/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/end_read_pkg.dart deleted file mode 100644 index 9fae7334..00000000 --- a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/end_read_pkg.dart +++ /dev/null @@ -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(); - } -} diff --git a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/read_content_pkg.dart b/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/read_content_pkg.dart deleted file mode 100644 index cb49f55b..00000000 --- a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/read_content_pkg.dart +++ /dev/null @@ -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 buf; - - ReadContentPkg(int pkgNum) { - buf = List.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(); - } -} diff --git a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/start_read_pkg.dart b/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/start_read_pkg.dart deleted file mode 100644 index 980f972d..00000000 --- a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/start_read_pkg.dart +++ /dev/null @@ -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 buf; - - StartReadPkg(String fileName) { - int commonPkgLength = BTConstants.COMMON_PKG_LENGTH; - - int bufLength = commonPkgLength + fileName.length + 1; - buf = List.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 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 - } -} diff --git a/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/temperature_info.dart b/lib/pages/medical/my_trackers/ble_models/andesfit_devices/all_in_one_monitor/temperature_info.dart deleted file mode 100644 index e69de29b..00000000 diff --git a/lib/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart b/lib/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart index 69569e73..5f6cd5cf 100644 --- a/lib/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart +++ b/lib/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.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 ecgEnabledDevices = ["BP2 0567", "DuoEK", "ER1", "PM101897"]; - List andesFitDevices = ["BPM", "PM101897", "SDIC", "TEMP", "Samico GL", "BLE-MSA", "Checkme 1316"]; + List 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 filesList, BuildContext context) { return Material( child: SizedBox( @@ -300,6 +312,25 @@ class MyTrackersViewModel extends ChangeNotifier { }); } + Future 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 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 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 disConnectDevice() async { @@ -395,6 +432,10 @@ class MyTrackersViewModel extends ChangeNotifier { await BleChannel.scanResultsNative([currentSelectedTrackerType.name]); } + Future scanForCheckMe() async { + await BleChannel.scanCheckMeProNative(); + } + Future stopNativeScan() async { await BleChannel.stopNativeScan(); } @@ -1061,233 +1102,7 @@ class MyTrackersViewModel extends ChangeNotifier { int result = 0; int currentPkg = 0; - BluetoothCharacteristic allInOneWriteCharacteristics; - - sendCommand(List bytes) { - log("trying to write on $allInOneWriteCharacteristics"); - allInOneWriteCharacteristics.write(bytes, withoutResponse: true); - } - Future 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 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 handleDataPool(List 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 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 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; } }