Finally Got the CheckMePro Device Info
parent
322d0a8b5d
commit
4d74d2143f
@ -0,0 +1,7 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro
|
||||
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
|
||||
object UiChannel {
|
||||
val progressChannel = Channel<Int>(Channel.CONFLATED)
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import android.bluetooth.BluetoothDevice
|
||||
|
||||
data class BleBean(var name: String, var bluetoothDevice: BluetoothDevice)
|
||||
@ -0,0 +1,11 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import java.util.*
|
||||
|
||||
data class BpBean(
|
||||
var date: Date = Date(),
|
||||
var timeString: String = "",
|
||||
var sys: Int = 0,
|
||||
var dia: Int=0,
|
||||
var pr: Int = 0
|
||||
)
|
||||
@ -0,0 +1,17 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import java.util.*
|
||||
|
||||
data class DlcBean(
|
||||
var date: Date = Date(),
|
||||
var timeString: String = "",
|
||||
var hr: Int = 0,
|
||||
var eface: Int = 0,
|
||||
var oxy: Int = 0,
|
||||
var pi: Int = 0,
|
||||
var oface: Int = 0,
|
||||
var prFlag: Int = 0,
|
||||
var pr: Int = 0,
|
||||
var bpiFace: Int = 0,
|
||||
var voice: Int = 0
|
||||
)
|
||||
@ -0,0 +1,11 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import java.util.*
|
||||
|
||||
data class EcgBean(
|
||||
var date: Date = Date(),
|
||||
var timeString: String = "",
|
||||
var way: Int = 0,
|
||||
var face: Int = 0,
|
||||
var voice: Int = 0
|
||||
)
|
||||
@ -0,0 +1,10 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import java.util.*
|
||||
|
||||
data class GluBean(
|
||||
var date: Date = Date(),
|
||||
var timeString: String = "",
|
||||
var glu:Float=0f,
|
||||
var note:String=""
|
||||
)
|
||||
@ -0,0 +1,13 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import java.util.*
|
||||
|
||||
data class OxyBean(
|
||||
var date: Date = Date(),
|
||||
var timeString: String = "",
|
||||
var way: Int = 0,
|
||||
var oxy: Int = 0,
|
||||
var pr: Int = 0,
|
||||
var pi: Int = 0,
|
||||
var face: Int = 0
|
||||
)
|
||||
@ -0,0 +1,52 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import java.util.*
|
||||
|
||||
data class PedBean(
|
||||
var date: Date = Date(),
|
||||
var timeString: String? = "",
|
||||
var step: Int = 0,
|
||||
var dis: Float = 0f,
|
||||
var speed: Float = 0f,
|
||||
var cal: Float = 0f,
|
||||
var fat: Float = 0f,
|
||||
var time: Int = 0
|
||||
) : Parcelable {
|
||||
constructor(parcel: Parcel) : this(
|
||||
TODO("date"),
|
||||
parcel.readString(),
|
||||
parcel.readInt(),
|
||||
parcel.readFloat(),
|
||||
parcel.readFloat(),
|
||||
parcel.readFloat(),
|
||||
parcel.readFloat(),
|
||||
parcel.readInt()
|
||||
) {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(timeString)
|
||||
parcel.writeInt(step)
|
||||
parcel.writeFloat(dis)
|
||||
parcel.writeFloat(speed)
|
||||
parcel.writeFloat(cal)
|
||||
parcel.writeFloat(fat)
|
||||
parcel.writeInt(time)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<PedBean> {
|
||||
override fun createFromParcel(parcel: Parcel): PedBean {
|
||||
return PedBean(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<PedBean?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import java.util.*
|
||||
|
||||
data class SlpBean(
|
||||
var date: Date = Date(),
|
||||
var timeString: String = "",
|
||||
var time: Int = 0,
|
||||
var lowTime: Int = 0,
|
||||
var lowCount: Int = 0,
|
||||
var minO2: Int = 0,
|
||||
var meanO2: Int = 0,
|
||||
var face: Int = 0
|
||||
|
||||
)
|
||||
@ -0,0 +1,11 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import java.util.*
|
||||
|
||||
data class TmpBean(
|
||||
var date: Date = Date(),
|
||||
var timeString: String = "",
|
||||
var way: Int = 0,
|
||||
var tmp: Float = 0f,
|
||||
var face: Int = 0
|
||||
)
|
||||
@ -0,0 +1,14 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import java.util.*
|
||||
|
||||
data class UserBean(
|
||||
var id: String = "",
|
||||
var name: String = "",
|
||||
var ico: Int = 0,
|
||||
var sex: Int = 0,
|
||||
var birthday: Date = Date(),
|
||||
var weight: Int = 0,
|
||||
var height: Int = 0,
|
||||
var color: Int = 0
|
||||
)
|
||||
@ -0,0 +1,40 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.constant;
|
||||
|
||||
public class BTConstant {
|
||||
|
||||
// Bluetooth Command length
|
||||
public final static int WRITE_CONTENT_PKG_DATA_LENGTH = 1024;
|
||||
public final static int READ_CONTENT_ACK_DATA_LENGTH = 1024;
|
||||
public final static int COMMON_PKG_LENGTH = 8;
|
||||
public final static int COMMON_ACK_PKG_LENGTH = 12;
|
||||
public final static int READ_CONTENT_ACK_PKG_FRONT_LENGTH = 8;
|
||||
public final static int GET_INFO_ACK_PKG_LENGTH = 8 + 256;
|
||||
|
||||
public final static byte ACK_CMD_OK = 0;
|
||||
public final static byte ACK_CMD_BAD = 1;
|
||||
|
||||
// Bluetooth Max file name length
|
||||
public final static byte BT_WRITE_FILE_NAME_MAX_LENGTH = 30;
|
||||
public final static byte BT_READ_FILE_NAME_MAX_LENGTH = 30;
|
||||
|
||||
// Bluetooth Command word
|
||||
public final static byte CMD_WORD_START_WRITE = 0x00;
|
||||
public final static byte CMD_WORD_WRITE_CONTENT = 0x01;
|
||||
public final static byte CMD_WORD_END_WRITE = 0x02;
|
||||
public final static byte CMD_WORD_START_READ = 0x03;
|
||||
public final static byte CMD_WORD_READ_CONTENT = 0x04;
|
||||
public final static byte CMD_WORD_END_READ = 0x05;
|
||||
public final static byte CMD_WORD_DEL_FILE = 0x06;
|
||||
public final static byte CMD_WORD_LIST_START = 0x07;
|
||||
public final static byte CMD_WORD_LIST_DATA = 0x08;
|
||||
public final static byte CMD_WORD_LIST_END = 0x09;
|
||||
public final static byte CMD_WORD_LANG_UPDATE_START = 0x0A;
|
||||
public final static byte CMD_WORD_LANG_UPDATE_DATA = 0x0B;
|
||||
public final static byte CMD_WORD_LANG_UPDATE_END = 0x0C;
|
||||
public final static byte CMD_WORD_APP_UPDATE_START = 0x0D;
|
||||
public final static byte CMD_WORD_APP_UPDATE_DATA = 0x0E;
|
||||
public final static byte CMD_WORD_APP_UPDATE_END = 0x0F;
|
||||
public final static byte CMD_WORD_GET_INFO = 0x14;
|
||||
public final static byte CMD_WORD_PING = 0x15;
|
||||
public final static byte CMD_WORD_PARA_SYNC = 0x16;
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.bean.BpBean
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import java.util.*
|
||||
|
||||
|
||||
class BpInfo constructor(var bytes: ByteArray) {
|
||||
var size: Int = bytes.size/11
|
||||
var Bp: ArrayList<BpBean> = arrayListOf<BpBean>()
|
||||
|
||||
|
||||
init {
|
||||
|
||||
var start: Int
|
||||
for (k in 0 until size) {
|
||||
start = k * 11
|
||||
val year: Int = toUInt(setRange(start, 2))
|
||||
val month: Int = toUInt(setRange(start + 2, 1)) - 1
|
||||
val date: Int = toUInt(setRange(start + 3, 1))
|
||||
val hour: Int = toUInt(setRange(start + 4, 1))
|
||||
val minute: Int = toUInt(setRange(start + 5, 1))
|
||||
val second: Int = toUInt(setRange(start + 6, 1))
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar[Calendar.YEAR] = year
|
||||
calendar[Calendar.MONTH] = month
|
||||
calendar[Calendar.DATE] = date
|
||||
calendar[Calendar.HOUR] = hour
|
||||
calendar[Calendar.MINUTE] = minute
|
||||
calendar[Calendar.SECOND] = second
|
||||
Bp.add(BpBean())
|
||||
Bp[k].apply {
|
||||
this.date = calendar.time
|
||||
timeString = String.format(
|
||||
"%04d%02d%02d%02d%02d%02d",
|
||||
year,
|
||||
month + 1,
|
||||
date,
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
)
|
||||
sys = toUInt(setRange(start + 7, 2))
|
||||
dia = toUInt(setRange(start + 9, 1))
|
||||
pr = toUInt(setRange(start + 10, 1))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun setRange(start: Int, len: Int): ByteArray {
|
||||
return bytes.copyOfRange(start, start + len)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import com.cloud.diplomaticquarterapp.utils.unsigned
|
||||
|
||||
|
||||
class CheckMeResponse(var bytes: ByteArray) {
|
||||
var cmd: Int = bytes[1].unsigned()
|
||||
var pkgNo: Int = toUInt(bytes.copyOfRange(3, 5))
|
||||
var len: Int = toUInt(bytes.copyOfRange(5, 7))
|
||||
var content: ByteArray = bytes.copyOfRange(7, 7 + len)
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import android.util.Log
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import org.json.JSONObject
|
||||
|
||||
class DeviceInfo(buf: ByteArray) {
|
||||
var len: Int = toUInt(buf.copyOfRange(5, 7))
|
||||
var content: ByteArray = buf.copyOfRange(7, 7 + len)
|
||||
var deviceStr: String = String(content)
|
||||
var json: JSONObject
|
||||
|
||||
init {
|
||||
Log.i("byteSize", buf.decodeToString())
|
||||
Log.i("len::", len.toString())
|
||||
deviceStr = deviceStr.substring(0, deviceStr.indexOf("}") + 1)
|
||||
json = JSONObject(deviceStr)
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.bean.DlcBean
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import java.util.*
|
||||
|
||||
|
||||
class DlcInfo(var bytes: ByteArray) {
|
||||
var size: Int = bytes.size / 17
|
||||
var dlc: ArrayList<DlcBean> = arrayListOf<DlcBean>()
|
||||
|
||||
|
||||
init {
|
||||
|
||||
var start: Int
|
||||
for (k in 0 until size) {
|
||||
start = k * 17
|
||||
val year: Int = toUInt(setRange(start, 2))
|
||||
val month: Int = toUInt(setRange(start + 2, 1))
|
||||
val date: Int = toUInt(setRange(start + 3, 1))
|
||||
val hour: Int = toUInt(setRange(start + 4, 1))
|
||||
val minute: Int = toUInt(setRange(start + 5, 1))
|
||||
val second: Int = toUInt(setRange(start + 6, 1))
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar[Calendar.YEAR] = year
|
||||
calendar[Calendar.MONTH] = month - 1
|
||||
calendar[Calendar.DATE] = date
|
||||
calendar[Calendar.HOUR] = hour
|
||||
calendar[Calendar.MINUTE] = minute
|
||||
calendar[Calendar.SECOND] = second
|
||||
dlc.add(DlcBean())
|
||||
dlc[k].apply {
|
||||
this.date = calendar.time
|
||||
timeString = String.format(
|
||||
"%04d%02d%02d%02d%02d%02d",
|
||||
year,
|
||||
month,
|
||||
date,
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
)
|
||||
hr = toUInt(setRange(start + 7, 2))
|
||||
eface = toUInt(setRange(start + 9, 1))
|
||||
if (eface > 2) eface = 2
|
||||
oxy = toUInt(setRange(start + 10, 1))
|
||||
pi = toUInt(setRange(start + 11, 1))
|
||||
oface = toUInt(setRange(start + 12, 1))
|
||||
if (oface > 2) oface = 2
|
||||
prFlag = toUInt(setRange(start + 13, 1))
|
||||
pr = toUInt(setRange(start + 14, 1))
|
||||
bpiFace = toUInt(setRange(start + 15, 1))
|
||||
if (bpiFace > 2) bpiFace = 2
|
||||
voice = toUInt(setRange(start + 16, 1))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun setRange(start: Int, len: Int): ByteArray {
|
||||
return bytes.copyOfRange(start, start + len)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.bean.EcgBean
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import java.util.*
|
||||
|
||||
|
||||
class EcgInfo(var bytes: ByteArray) {
|
||||
var size: Int = bytes.size / 10
|
||||
var ecg: ArrayList<EcgBean> = arrayListOf<EcgBean>()
|
||||
|
||||
|
||||
init {
|
||||
var start: Int
|
||||
for (k in 0 until size) {
|
||||
start = k * 10
|
||||
val year: Int = toUInt(setRange(start, 2))
|
||||
val month: Int = toUInt(setRange(start + 2, 1)) - 1
|
||||
val date: Int = toUInt(setRange(start + 3, 1))
|
||||
val hour: Int = toUInt(setRange(start + 4, 1))
|
||||
val minute: Int = toUInt(setRange(start + 5, 1))
|
||||
val second: Int = toUInt(setRange(start + 6, 1))
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar[Calendar.YEAR] = year
|
||||
calendar[Calendar.MONTH] = month
|
||||
calendar[Calendar.DATE] = date
|
||||
calendar[Calendar.HOUR] = hour
|
||||
calendar[Calendar.MINUTE] = minute
|
||||
calendar[Calendar.SECOND] = second
|
||||
ecg.add(EcgBean())
|
||||
ecg[k].apply {
|
||||
this.date = calendar.time
|
||||
timeString = String.format(
|
||||
"%04d%02d%02d%02d%02d%02d",
|
||||
year,
|
||||
month + 1,
|
||||
date,
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
)
|
||||
way = toUInt(setRange(start + 7, 1))
|
||||
face = toUInt(setRange(start + 8, 1))
|
||||
if (face > 2) face = 2
|
||||
voice = toUInt(setRange(start + 9, 1))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun setRange(start: Int, len: Int): ByteArray {
|
||||
return bytes.copyOfRange(start, start + len)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
|
||||
|
||||
class EcgWaveInfo constructor(var bytes: ByteArray) {
|
||||
|
||||
var hrSize: Int = toUInt(bytes.copyOfRange(0, 2))
|
||||
var waveSize: Int = toUInt(bytes.copyOfRange(2, 6)) - 4
|
||||
var hr: Int = toUInt(bytes.copyOfRange(6, 8))
|
||||
var st: Int = toUInt(bytes.copyOfRange(8, 10))
|
||||
var qrs: Int = toUInt(bytes.copyOfRange(10, 12))
|
||||
var pvcs: Int = toUInt(bytes.copyOfRange(12, 14))
|
||||
var qtc: Int = toUInt(bytes.copyOfRange(14, 16))
|
||||
var result: Int = toUInt(bytes.copyOfRange(16, 17))
|
||||
var qt: Int = toUInt(bytes.copyOfRange(19, 21))
|
||||
var hrList: IntArray = IntArray(hrSize / 2)
|
||||
var waveList: IntArray = IntArray(waveSize / 2)
|
||||
var waveIntSize = waveSize / 2
|
||||
val total = 2500
|
||||
var waveViewSize = waveIntSize / total
|
||||
|
||||
|
||||
init {
|
||||
|
||||
for (index in 0 until hrSize / 2) {
|
||||
hrList[index] = toUInt(setRange(index * 2 + 22, 2))
|
||||
}
|
||||
// for (index in 0 until waveSize / 2) {
|
||||
|
||||
// waveList[index] =
|
||||
// bytes[23 + index * 2 + hrSize].toInt() * 256 + bytes[22 + index * 2 + hrSize].toInt()
|
||||
// }
|
||||
|
||||
|
||||
// waveList= ECGInnerItem(bytes).ecgData
|
||||
waveIntSize=waveList.size
|
||||
waveViewSize=waveIntSize/total
|
||||
if (waveViewSize * total < waveIntSize) {
|
||||
waveViewSize++
|
||||
}
|
||||
}
|
||||
|
||||
private fun setRange(start: Int, len: Int): ByteArray {
|
||||
return bytes.copyOfRange(start, start + len)
|
||||
}
|
||||
|
||||
|
||||
fun getWave(index: Int): IntArray {
|
||||
val result = IntArray(total)
|
||||
for (k in 0 until total) {
|
||||
result[k] = if (k + index * total < waveList.size) {
|
||||
waveList[k + index * total]
|
||||
} else {
|
||||
1000000
|
||||
}
|
||||
|
||||
}
|
||||
return result
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.bean.GluBean
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import java.util.*
|
||||
|
||||
|
||||
class GluInfo constructor(var bytes: ByteArray) {
|
||||
var size: Int = bytes.size / 32
|
||||
var Glu: ArrayList<GluBean> = arrayListOf<GluBean>()
|
||||
|
||||
|
||||
init {
|
||||
|
||||
var start: Int
|
||||
for (k in 0 until size) {
|
||||
start = k * 32
|
||||
val year: Int = toUInt(setRange(start, 2))
|
||||
val month: Int = toUInt(setRange(start + 2, 1)) - 1
|
||||
val date: Int = toUInt(setRange(start + 3, 1))
|
||||
val hour: Int = toUInt(setRange(start + 4, 1))
|
||||
val minute: Int = toUInt(setRange(start + 5, 1))
|
||||
val second: Int = toUInt(setRange(start + 6, 1))
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar[Calendar.YEAR] = year
|
||||
calendar[Calendar.MONTH] = month
|
||||
calendar[Calendar.DATE] = date
|
||||
calendar[Calendar.HOUR] = hour
|
||||
calendar[Calendar.MINUTE] = minute
|
||||
calendar[Calendar.SECOND] = second
|
||||
Glu.add(GluBean())
|
||||
Glu[k].apply {
|
||||
this.date = calendar.time
|
||||
timeString = String.format(
|
||||
"%04d%02d%02d%02d%02d%02d",
|
||||
year,
|
||||
month + 1,
|
||||
date,
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
)
|
||||
glu= toUInt(setRange(start+7,2)).toFloat()/10f
|
||||
note=String(setRange(start+12,20))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun setRange(start: Int, len: Int): ByteArray {
|
||||
return bytes.copyOfRange(start, start + len)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.bean.OxyBean
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import java.util.*
|
||||
|
||||
|
||||
class OxyInfo constructor(var bytes: ByteArray) {
|
||||
var size: Int = bytes.size / 12
|
||||
var Oxy: ArrayList<OxyBean> = arrayListOf<OxyBean>()
|
||||
|
||||
|
||||
init {
|
||||
|
||||
var start: Int
|
||||
for (k in 0 until size) {
|
||||
start = k * 12
|
||||
val year: Int = toUInt(setRange(start, 2))
|
||||
val month: Int = toUInt(setRange(start + 2, 1)) - 1
|
||||
val date: Int = toUInt(setRange(start + 3, 1))
|
||||
val hour: Int = toUInt(setRange(start + 4, 1))
|
||||
val minute: Int = toUInt(setRange(start + 5, 1))
|
||||
val second: Int = toUInt(setRange(start + 6, 1))
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar[Calendar.YEAR] = year
|
||||
calendar[Calendar.MONTH] = month
|
||||
calendar[Calendar.DATE] = date
|
||||
calendar[Calendar.HOUR] = hour
|
||||
calendar[Calendar.MINUTE] = minute
|
||||
calendar[Calendar.SECOND] = second
|
||||
Oxy.add(OxyBean())
|
||||
Oxy[k].apply {
|
||||
this.date = calendar.time
|
||||
timeString = String.format(
|
||||
"%04d%02d%02d%02d%02d%02d",
|
||||
year,
|
||||
month + 1,
|
||||
date,
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
)
|
||||
way = toUInt(setRange(start + 7, 1))
|
||||
if (way > 2) way = 2
|
||||
oxy = toUInt(setRange(start + 8, 1))
|
||||
pr = toUInt(setRange(start + 9, 1))
|
||||
pi = toUInt(setRange(start + 10, 1))
|
||||
face = toUInt(setRange(start + 11, 1))
|
||||
if (face > 2) face = 2
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun setRange(start: Int, len: Int): ByteArray {
|
||||
return bytes.copyOfRange(start, start + len)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import com.cloud.diplomaticquarterapp.utils.unsigned
|
||||
|
||||
|
||||
class OxyWaveInfo constructor(var bytes: ByteArray) {
|
||||
val size1: Int = toUInt(bytes.copyOfRange(0, 2))
|
||||
val size2: Int = toUInt(bytes.copyOfRange(2, 6))
|
||||
val o2Array = IntArray(size1 / 3)
|
||||
val pulseArray = IntArray(size1 / 3)
|
||||
val waveArray = IntArray(size2)
|
||||
|
||||
|
||||
init {
|
||||
for (k in 0 until size1 / 3) {
|
||||
o2Array[k] = bytes[k * 3 + 6].unsigned()
|
||||
pulseArray[k] =
|
||||
bytes[k * 3 + 7].unsigned() + bytes[k * 3 + 8].unsigned() * 256
|
||||
}
|
||||
for (k in 0 until size2) {
|
||||
waveArray[k] = bytes[k + 6 + size1].unsigned()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import android.util.Log
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.bean.PedBean
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import java.util.*
|
||||
|
||||
|
||||
class PedInfo constructor(var bytes: ByteArray) {
|
||||
var size: Int = bytes.size / 29
|
||||
var Ped: ArrayList<PedBean> = arrayListOf<PedBean>()
|
||||
|
||||
|
||||
init {
|
||||
Log.i("pedoSize",bytes.size.toString())
|
||||
|
||||
var start: Int
|
||||
for (k in 0 until size) {
|
||||
start = k * 29
|
||||
val year: Int = toUInt(setRange(start, 2))
|
||||
val month: Int = toUInt(setRange(start + 2, 1)) - 1
|
||||
val date: Int = toUInt(setRange(start + 3, 1))
|
||||
val hour: Int = toUInt(setRange(start + 4, 1))
|
||||
val minute: Int = toUInt(setRange(start + 5, 1))
|
||||
val second: Int = toUInt(setRange(start + 6, 1))
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar[Calendar.YEAR] = year
|
||||
calendar[Calendar.MONTH] = month
|
||||
calendar[Calendar.DATE] = date
|
||||
calendar[Calendar.HOUR] = hour
|
||||
calendar[Calendar.MINUTE] = minute
|
||||
calendar[Calendar.SECOND] = second
|
||||
Ped.add(PedBean())
|
||||
Ped[k].apply {
|
||||
this.date = calendar.time
|
||||
timeString = String.format(
|
||||
"%04d%02d%02d%02d%02d%02d",
|
||||
year,
|
||||
month + 1,
|
||||
date,
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
)
|
||||
step = toUInt(setRange(start + 7, 4))
|
||||
dis = toUInt(setRange(start + 11, 4)).toFloat() / 100f
|
||||
speed = toUInt(setRange(start + 15, 4)).toFloat() / 10f
|
||||
cal = toUInt(setRange(start + 19, 4)).toFloat() / 100f
|
||||
fat = toUInt(setRange(start + 23, 2)).toFloat() / 100f
|
||||
time = toUInt(setRange(start + 25, 2))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun setRange(start: Int, len: Int): ByteArray {
|
||||
return bytes.copyOfRange(start, start + len)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import android.util.Log
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.bean.SlpBean
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import java.util.*
|
||||
|
||||
|
||||
class SlpInfo constructor(var bytes: ByteArray) {
|
||||
var size: Int = bytes.size / 18
|
||||
var Slp: ArrayList<SlpBean> = arrayListOf<SlpBean>()
|
||||
fun byteArray2String(byteArray: ByteArray): String {
|
||||
var fuc = ""
|
||||
for (b in byteArray) {
|
||||
val st = String.format("%02X", b)
|
||||
fuc += ("$st ");
|
||||
}
|
||||
return fuc
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
Log.e("sleepSIze",byteArray2String(bytes))
|
||||
var start: Int
|
||||
for (k in 0 until size) {
|
||||
start = k *18
|
||||
val year: Int = toUInt(setRange(start, 2))
|
||||
val month: Int = toUInt(setRange(start + 2, 1)) - 1
|
||||
val date: Int = toUInt(setRange(start + 3, 1))
|
||||
val hour: Int = toUInt(setRange(start + 4, 1))
|
||||
val minute: Int = toUInt(setRange(start + 5, 1))
|
||||
val second: Int = toUInt(setRange(start + 6, 1))
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar[Calendar.YEAR] = year
|
||||
calendar[Calendar.MONTH] = month
|
||||
calendar[Calendar.DATE] = date
|
||||
calendar[Calendar.HOUR] = hour
|
||||
calendar[Calendar.MINUTE] = minute
|
||||
calendar[Calendar.SECOND] = second
|
||||
Slp.add(SlpBean())
|
||||
Slp[k].apply {
|
||||
this.date = calendar.time
|
||||
timeString = String.format(
|
||||
"%04d%02d%02d%02d%02d%02d",
|
||||
year,
|
||||
month + 1,
|
||||
date,
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
)
|
||||
time = toUInt(setRange(start + 7, 4))
|
||||
lowTime = toUInt(setRange(start + 11, 2))
|
||||
lowCount = toUInt(setRange(start + 13, 2))
|
||||
minO2 = toUInt(setRange(start + 15, 1))
|
||||
meanO2 = toUInt(setRange(start + 16, 1))
|
||||
face = toUInt(setRange(start + 17, 1))
|
||||
if (face > 2) face = 2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun setRange(start: Int, len: Int): ByteArray {
|
||||
return bytes.copyOfRange(start, start + len)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.bean.TmpBean
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import java.util.*
|
||||
|
||||
|
||||
class TmpInfo constructor(var bytes: ByteArray) {
|
||||
var size: Int = bytes.size / 11
|
||||
var Tmp: ArrayList<TmpBean> = arrayListOf<TmpBean>()
|
||||
|
||||
|
||||
init {
|
||||
|
||||
var start: Int
|
||||
for (k in 0 until size) {
|
||||
start = k * 11
|
||||
val year: Int = toUInt(setRange(start, 2))
|
||||
val month: Int = toUInt(setRange(start + 2, 1)) - 1
|
||||
val date: Int = toUInt(setRange(start + 3, 1))
|
||||
val hour: Int = toUInt(setRange(start + 4, 1))
|
||||
val minute: Int = toUInt(setRange(start + 5, 1))
|
||||
val second: Int = toUInt(setRange(start + 6, 1))
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar[Calendar.YEAR] = year
|
||||
calendar[Calendar.MONTH] = month
|
||||
calendar[Calendar.DATE] = date
|
||||
calendar[Calendar.HOUR] = hour
|
||||
calendar[Calendar.MINUTE] = minute
|
||||
calendar[Calendar.SECOND] = second
|
||||
Tmp.add(TmpBean())
|
||||
Tmp[k].apply {
|
||||
this.date = calendar.time
|
||||
timeString = String.format(
|
||||
"%04d%02d%02d%02d%02d%02d",
|
||||
year,
|
||||
month + 1,
|
||||
date,
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
)
|
||||
way = toUInt(setRange(start + 7, 1))
|
||||
if (way > 2) way = 2
|
||||
tmp = toUInt(setRange(start + 8, 2)).toFloat() / 10f
|
||||
face = toUInt(setRange(start + 10, 1))
|
||||
if (face > 2) face = 2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun setRange(start: Int, len: Int): ByteArray {
|
||||
return bytes.copyOfRange(start, start + len)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.format
|
||||
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.bean.UserBean
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import com.cloud.diplomaticquarterapp.utils.unsigned
|
||||
import java.util.*
|
||||
|
||||
|
||||
class UserInfo constructor(var bytes: ByteArray) {
|
||||
var size: Int = bytes.size / 27
|
||||
var user: Array<UserBean> = Array(size) {
|
||||
UserBean()
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
var start: Int
|
||||
for (k in 0 until size) {
|
||||
start = k * 27
|
||||
user[k].id = bytes[start].unsigned().toString()
|
||||
user[k].name = String(setRange(start + 1, 16))
|
||||
user[k].ico = bytes[start + 17].unsigned()
|
||||
user[k].sex = bytes[start + 18].unsigned()
|
||||
val year: Int = toUInt(setRange(start + 19, 2))
|
||||
val month: Int = toUInt(setRange(start + 21, 1)) - 1
|
||||
val date: Int = toUInt(setRange(start + 22, 1))
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar[Calendar.YEAR] = year
|
||||
calendar[Calendar.MONTH] = month
|
||||
calendar[Calendar.DATE] = date
|
||||
user[k].birthday = calendar.time
|
||||
user[k].weight = toUInt(setRange(start + 23, 2)) /10
|
||||
user[k].height = toUInt(setRange(start + 25, 2))
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun setRange(start: Int, len: Int): ByteArray {
|
||||
return bytes.copyOfRange(start, start + len)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,111 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.manager;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.bluetooth.BluetoothGattService;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.ble.BleManager;
|
||||
import no.nordicsemi.android.ble.data.Data;
|
||||
|
||||
public class BleDataManager extends BleManager {
|
||||
private BluetoothGattCharacteristic write_char;
|
||||
private BluetoothGattCharacteristic notify_char;
|
||||
private OnNotifyListener listener;
|
||||
|
||||
public BleDataManager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void setNotifyListener(OnNotifyListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BleManagerGattCallback getGattCallback() {
|
||||
return new MyManagerGattCallback();
|
||||
}
|
||||
|
||||
public void sendCmd(byte[] bytes) {
|
||||
// Log.i("----- Current Write Command -----", "");
|
||||
writeCharacteristic(write_char, bytes)
|
||||
.split()
|
||||
.done(device -> {
|
||||
})
|
||||
.enqueue();
|
||||
}
|
||||
|
||||
|
||||
public interface OnNotifyListener {
|
||||
void onNotify(BluetoothDevice device, Data data);
|
||||
}
|
||||
|
||||
private class MyManagerGattCallback extends BleManagerGattCallback {
|
||||
@Override
|
||||
public boolean isRequiredServiceSupported(BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(service_uuid);
|
||||
|
||||
|
||||
if (service != null) {
|
||||
write_char = service.getCharacteristic(write_uuid);
|
||||
notify_char = service.getCharacteristic(notify_uuid);
|
||||
}
|
||||
|
||||
boolean notify = false;
|
||||
if (notify_char != null) {
|
||||
final int properties = notify_char.getProperties();
|
||||
notify = (properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0;
|
||||
}
|
||||
boolean writeRequest = false;
|
||||
if (write_char != null) {
|
||||
final int properties = write_char.getProperties();
|
||||
int writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT;
|
||||
if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0) {
|
||||
writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE;
|
||||
}
|
||||
write_char.setWriteType(writeType);
|
||||
writeRequest = (properties & BluetoothGattCharacteristic.PROPERTY_WRITE) != 0 || (properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0;
|
||||
/// LepuBleLog.d(TAG, "writeChar writeRequest == " + writeRequest);
|
||||
|
||||
}
|
||||
// Return true if all required services have been found
|
||||
return write_char != null && notify_char != null
|
||||
&& notify && writeRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptionalServiceSupported(BluetoothGatt gatt) {
|
||||
return super.isOptionalServiceSupported(gatt);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
beginAtomicRequestQueue()
|
||||
.add(requestMtu(23) // Remember, GATT needs 3 bytes extra. This will allow packet size of 244 bytes.
|
||||
.with((device, mtu) -> Log.d("TAG", "MTU set to " + mtu))
|
||||
.fail((device, status) -> log(Log.WARN, "Requested MTU not supported: " + status)))
|
||||
.add(enableNotifications(notify_char))
|
||||
.done(device -> Log.d("TAG", "Target initialized"))
|
||||
.enqueue();
|
||||
setNotificationCallback(notify_char)
|
||||
.with((device, data) -> {
|
||||
listener.onNotify(device, data);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected() {
|
||||
write_char = null;
|
||||
notify_char = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final UUID service_uuid = UUID.fromString("14839ac4-7d7e-415c-9a42-167340cf2339");
|
||||
public static final UUID write_uuid = UUID.fromString("8B00ACE7-EB0B-49B0-BBE9-9AEE0A26E1A3");
|
||||
public static final UUID notify_uuid = UUID.fromString("0734594A-A8E7-4B1A-A6B1-CD5243059A57");
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.manager
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.le.BluetoothLeScanner
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.bluetooth.le.ScanSettings
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
|
||||
|
||||
class BleScanManager {
|
||||
interface Scan {
|
||||
fun scanReturn(name: String, bluetoothDevice: BluetoothDevice)
|
||||
}
|
||||
|
||||
private var bluetoothAdapter: BluetoothAdapter? = null
|
||||
private lateinit var leScanner: BluetoothLeScanner
|
||||
private var scan: Scan? = null
|
||||
private val leScanCallback: ScanCallback = object : ScanCallback() {
|
||||
@SuppressLint("MissingPermission")
|
||||
override fun onScanResult(
|
||||
callbackType: Int, result: ScanResult
|
||||
) {
|
||||
super.onScanResult(callbackType, result)
|
||||
val device = result.device
|
||||
if (device?.name == null) return;
|
||||
scan?.apply {
|
||||
scanReturn(device.name, device)
|
||||
}
|
||||
Log.i("scanned ble", " ${device.name}")
|
||||
}
|
||||
|
||||
override fun onBatchScanResults(results: List<ScanResult>) {}
|
||||
override fun onScanFailed(errorCode: Int) {}
|
||||
}
|
||||
|
||||
fun setCallBack(scan: Scan) {
|
||||
this.scan = scan
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@RequiresApi(Build.VERSION_CODES.M)
|
||||
fun initScan(context: Context) {
|
||||
context.apply {
|
||||
val settings: ScanSettings = ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build()
|
||||
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
||||
bluetoothAdapter = bluetoothManager.adapter
|
||||
leScanner = bluetoothAdapter!!.bluetoothLeScanner
|
||||
leScanner.startScan(null, settings, leScanCallback)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun stopScan() {
|
||||
leScanner.stopScan(leScanCallback)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg
|
||||
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.constant.BTConstant
|
||||
import com.cloud.diplomaticquarterapp.utils.CRCUtils
|
||||
import kotlin.experimental.inv
|
||||
|
||||
class EndReadPkg {
|
||||
var buf: ByteArray = ByteArray(BTConstant.COMMON_PKG_LENGTH)
|
||||
|
||||
init {
|
||||
// TODO Auto-generated constructor stub
|
||||
buf[0] = 0xAA.toByte()
|
||||
buf[1] = BTConstant.CMD_WORD_END_READ
|
||||
buf[2] = BTConstant.CMD_WORD_END_READ.inv()
|
||||
buf[3] = 0 //Package number, the default is 0
|
||||
buf[4] = 0
|
||||
buf[5] = 0 //data chunk size, the default is 0
|
||||
buf[6] = 0
|
||||
buf[buf.size - 1] = CRCUtils.calCRC8(buf)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg
|
||||
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.constant.BTConstant
|
||||
import com.cloud.diplomaticquarterapp.utils.CRCUtils
|
||||
import kotlin.experimental.inv
|
||||
|
||||
|
||||
class GetDeviceInfoPkg() {
|
||||
val buf: ByteArray = ByteArray(BTConstant.COMMON_PKG_LENGTH)
|
||||
|
||||
init {
|
||||
buf[0] = 0xAA.toByte()
|
||||
buf[1] = BTConstant.CMD_WORD_GET_INFO
|
||||
buf[2] = BTConstant.CMD_WORD_GET_INFO.inv()
|
||||
buf[3] = 0.toByte() //Package number
|
||||
buf[4] = 0.toByte()
|
||||
buf[5] = 0.toByte()
|
||||
buf[6] = 0.toByte()
|
||||
buf[buf.size - 1] = CRCUtils.calCRC8(buf)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.constant.BTConstant
|
||||
import com.cloud.diplomaticquarterapp.utils.CRCUtils
|
||||
import kotlin.experimental.inv
|
||||
|
||||
class ReadContentPkg(pkgNum: Int) {
|
||||
val buf: ByteArray = ByteArray(BTConstant.COMMON_PKG_LENGTH)
|
||||
|
||||
init {
|
||||
buf[0] = 0xAA.toByte()
|
||||
buf[1] = BTConstant.CMD_WORD_READ_CONTENT
|
||||
buf[2] = BTConstant.CMD_WORD_READ_CONTENT.inv()
|
||||
buf[3] = pkgNum.toByte() //Package number
|
||||
buf[4] = (pkgNum shr 8).toByte()
|
||||
buf[5] = 0 //data chunk size, the default is 0
|
||||
buf[6] = 0
|
||||
buf[buf.size - 1] = CRCUtils.calCRC8(buf)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.constant.BTConstant
|
||||
import com.cloud.diplomaticquarterapp.utils.CRCUtils
|
||||
import kotlin.experimental.inv
|
||||
|
||||
class StartReadPkg(fileName: String?) {
|
||||
val buf: ByteArray = ByteArray(BTConstant.COMMON_PKG_LENGTH + fileName!!.length + 1)
|
||||
|
||||
init {
|
||||
buf[0] = (0xAA).toByte()
|
||||
buf[1] = BTConstant.CMD_WORD_START_READ
|
||||
buf[2] = BTConstant.CMD_WORD_START_READ.inv()
|
||||
buf[3] = 0 //Package number, the default is 0
|
||||
buf[4] = 0
|
||||
buf[5] = (buf.size - BTConstant.COMMON_PKG_LENGTH).toByte() //data chunk size
|
||||
buf[6] = (buf.size - BTConstant.COMMON_PKG_LENGTH shr 8).toByte()
|
||||
val tempFileName = fileName!!.toCharArray()
|
||||
for (i in tempFileName.indices) {
|
||||
buf[i + 7] = tempFileName[i].toByte()
|
||||
}
|
||||
buf[buf.size - 1] = CRCUtils.calCRC8(buf)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,222 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.worker
|
||||
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.format.CheckMeResponse
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.format.DeviceInfo
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.manager.BleDataManager
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg.EndReadPkg
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg.GetDeviceInfoPkg
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg.ReadContentPkg
|
||||
import com.cloud.diplomaticquarterapp.check_me_pro.ble.pkg.StartReadPkg
|
||||
import com.cloud.diplomaticquarterapp.utils.CRCUtils
|
||||
import com.cloud.diplomaticquarterapp.utils.Constant
|
||||
import com.cloud.diplomaticquarterapp.utils.add
|
||||
import com.cloud.diplomaticquarterapp.utils.toUInt
|
||||
import com.google.gson.Gson
|
||||
import io.flutter.plugin.common.EventChannel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import no.nordicsemi.android.ble.data.Data
|
||||
import java.io.File
|
||||
import kotlin.experimental.inv
|
||||
|
||||
class BleDataWorker(private val updateEventSink: (Map<String, Any>) -> Unit) {
|
||||
private var pool: ByteArray? = null
|
||||
private val deviceChannel = Channel<DeviceInfo>(Channel.CONFLATED)
|
||||
private val fileChannel = Channel<Int>(Channel.CONFLATED)
|
||||
private val connectChannel = Channel<String>(Channel.CONFLATED)
|
||||
private var myBleDataManager: BleDataManager? = null
|
||||
private val dataScope = CoroutineScope(Dispatchers.IO)
|
||||
private val mutex = Mutex()
|
||||
|
||||
private var cmdState = 0;
|
||||
var pkgTotal = 0;
|
||||
var currentPkg = 0;
|
||||
var fileData: ByteArray? = null
|
||||
var currentFileName = ""
|
||||
var result = 1;
|
||||
var currentFileSize = 0
|
||||
|
||||
|
||||
companion object {
|
||||
val fileProgressChannel = Channel<FileProgress>(Channel.CONFLATED)
|
||||
}
|
||||
|
||||
data class FileProgress(
|
||||
var name: String = "", var progress: Int = 0, var success: Boolean = false
|
||||
)
|
||||
|
||||
private val comeData = object : BleDataManager.OnNotifyListener {
|
||||
override fun onNotify(device: BluetoothDevice?, data: Data?) {
|
||||
data?.value?.apply {
|
||||
pool = add(pool, this)
|
||||
}
|
||||
pool?.apply {
|
||||
pool = handleDataPool(pool)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val gson = Gson()
|
||||
|
||||
|
||||
private fun handleDataPool(bytes: ByteArray?): ByteArray? {
|
||||
val bytesLeft: ByteArray? = bytes
|
||||
|
||||
if (bytes == null || bytes.size < 8) {
|
||||
return bytes
|
||||
}
|
||||
loop@ for (i in 0 until bytes.size - 7) {
|
||||
if (bytes[i] != 0x55.toByte() || bytes[i + 1] != bytes[i + 2].inv()) {
|
||||
continue@loop
|
||||
}
|
||||
|
||||
// need content length
|
||||
val len = toUInt(bytes.copyOfRange(i + 5, i + 7))
|
||||
if (i + 8 + len > bytes.size) {
|
||||
continue@loop
|
||||
}
|
||||
|
||||
val temp: ByteArray = bytes.copyOfRange(i, i + 8 + len)
|
||||
if (temp.last() == CRCUtils.calCRC8(temp)) {
|
||||
|
||||
if (cmdState in 1..3) {
|
||||
val bleResponse = CheckMeResponse(temp)
|
||||
if (cmdState == 1) {
|
||||
currentFileSize = toUInt(bleResponse.content)
|
||||
pkgTotal = currentFileSize / 512
|
||||
if (bleResponse.cmd == 1) {
|
||||
result = 1
|
||||
val pkg = EndReadPkg()
|
||||
sendCmd(pkg.buf)
|
||||
cmdState = 3
|
||||
} else if (bleResponse.cmd == 0) {
|
||||
val pkg = ReadContentPkg(currentPkg)
|
||||
sendCmd(pkg.buf)
|
||||
currentPkg++
|
||||
cmdState = 2;
|
||||
}
|
||||
|
||||
|
||||
} else if (cmdState == 2) {
|
||||
bleResponse.content.apply {
|
||||
fileData = add(fileData, this)
|
||||
fileData?.let {
|
||||
dataScope.launch {
|
||||
fileProgressChannel.send(
|
||||
FileProgress(
|
||||
currentFileName, it.size * 100 / currentFileSize, true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentPkg > pkgTotal) {
|
||||
fileData?.apply {
|
||||
result = 0
|
||||
Log.i("file", "receive $currentFileName")
|
||||
File(Constant.getPathX(currentFileName)).writeBytes(this)
|
||||
}
|
||||
val pkg = EndReadPkg()
|
||||
Log.i("file", "bytes ${pkg.buf}")
|
||||
sendCmd(pkg.buf)
|
||||
cmdState = 3
|
||||
} else {
|
||||
val pkg = ReadContentPkg(currentPkg)
|
||||
sendCmd(pkg.buf)
|
||||
currentPkg++
|
||||
}
|
||||
|
||||
} else if (cmdState == 3) {
|
||||
fileData = null
|
||||
currentPkg = 0
|
||||
cmdState = 0
|
||||
dataScope.launch {
|
||||
fileProgressChannel.send(
|
||||
FileProgress(
|
||||
currentFileName, 100, result == 0
|
||||
)
|
||||
)
|
||||
fileChannel.send(result)
|
||||
}
|
||||
}
|
||||
} else if (cmdState == 4) {
|
||||
val deviceInfo = DeviceInfo(temp)
|
||||
|
||||
val json = deviceInfo.json
|
||||
var s: String = ""
|
||||
for (k in json.keys()) {
|
||||
s += "$k: "
|
||||
s += "${json.get(k)} "
|
||||
}
|
||||
Log.d("DeviceInfoFaiz", "This is the DeviceInfo: ${gson.toJson(json)}");
|
||||
val returnData = mapOf("type" to "infoDataCheckMe", "data" to gson.toJson(json))
|
||||
updateEventSink(returnData)
|
||||
}
|
||||
|
||||
|
||||
val tempBytes: ByteArray? = if (i + 8 + len == bytes.size) null else bytes.copyOfRange(
|
||||
i + 8 + len, bytes.size
|
||||
)
|
||||
|
||||
return handleDataPool(tempBytes)
|
||||
}
|
||||
}
|
||||
|
||||
return bytesLeft
|
||||
}
|
||||
|
||||
private fun sendCmd(bs: ByteArray) {
|
||||
myBleDataManager?.sendCmd(bs)
|
||||
}
|
||||
|
||||
|
||||
fun initWorker(context: Context, bluetoothDevice: BluetoothDevice?) {
|
||||
myBleDataManager = BleDataManager(context)
|
||||
myBleDataManager?.setNotifyListener(comeData)
|
||||
bluetoothDevice?.let {
|
||||
myBleDataManager?.connect(it)?.useAutoConnect(false)?.retry(150, 100)?.done {
|
||||
Log.i("BLE", "连接成功了.>>.....>>>>")
|
||||
getDeviceInfo();
|
||||
dataScope.launch {
|
||||
connectChannel.send("yes")
|
||||
}
|
||||
}?.enqueue()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun waitConnect() {
|
||||
connectChannel.receive()
|
||||
}
|
||||
|
||||
suspend fun getFile(name: String): Int {
|
||||
mutex.withLock {
|
||||
this.currentFileName = name
|
||||
cmdState = 1
|
||||
val pkg = StartReadPkg(name)
|
||||
Log.i("----- Current PKG -----", pkg.toString());
|
||||
sendCmd(pkg.buf)
|
||||
return fileChannel.receive()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDeviceInfo() {
|
||||
cmdState = 4
|
||||
val pkg = GetDeviceInfoPkg()
|
||||
sendCmd(pkg.buf)
|
||||
|
||||
}
|
||||
|
||||
fun disconnect() {
|
||||
myBleDataManager?.disconnect()?.enqueue()
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.cloud.diplomaticquarterapp.utils
|
||||
|
||||
|
||||
fun add(ori: ByteArray?, add: ByteArray): ByteArray {
|
||||
if (ori == null) {
|
||||
return add
|
||||
}
|
||||
|
||||
val new: ByteArray = ByteArray(ori.size + add.size)
|
||||
for ((index, value) in ori.withIndex()) {
|
||||
new[index] = value
|
||||
}
|
||||
|
||||
for ((index, value) in add.withIndex()) {
|
||||
new[index + ori.size] = value
|
||||
}
|
||||
|
||||
return new
|
||||
}
|
||||
|
||||
|
||||
fun toUInt(bytes: ByteArray): Int {
|
||||
var result = 0
|
||||
for ((i, v) in bytes.withIndex()) {
|
||||
result += v.unsigned().shl(i * 8)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
fun Byte.unsigned(): Int = when {
|
||||
(toInt() < 0) -> 255 + toInt() + 1
|
||||
else -> toInt()
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.cloud.diplomaticquarterapp.utils;
|
||||
|
||||
|
||||
/**
|
||||
* Tools used to generate CRC8 code
|
||||
*
|
||||
* @author zouhao
|
||||
*/
|
||||
public class CRCUtils {
|
||||
|
||||
/**
|
||||
* CRC8 code table
|
||||
*/
|
||||
private static final char[] Table_CRC8 = {0x00, 0x07, 0x0E, 0x09, 0x1C,
|
||||
0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
|
||||
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46,
|
||||
0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB,
|
||||
0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, 0x90,
|
||||
0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1,
|
||||
0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5,
|
||||
0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0,
|
||||
0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93,
|
||||
0x94, 0x9D, 0x9A, 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
|
||||
0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59,
|
||||
0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74,
|
||||
0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1,
|
||||
0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, 0xF9, 0xFE, 0xF7, 0xF0,
|
||||
0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3,
|
||||
0xD4, 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56,
|
||||
0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10, 0x05,
|
||||
0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
|
||||
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78,
|
||||
0x7F, 0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25,
|
||||
0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE,
|
||||
0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F,
|
||||
0x8A, 0x8D, 0x84, 0x83, 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC,
|
||||
0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3};
|
||||
|
||||
/**
|
||||
* Generate CRC8 code
|
||||
*
|
||||
* @param buf Data buffer
|
||||
* @return CRC8 code, return 0 when the parameter is error
|
||||
*/
|
||||
public static byte calCRC8(byte[] buf) {
|
||||
if (buf == null || buf.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte crc = 0;
|
||||
|
||||
for (int i = 0; i < buf.length - 1; i++) {
|
||||
crc = (byte) Table_CRC8[0x00ff & (crc ^ (buf[i]))];
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.cloud.diplomaticquarterapp.utils;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class Constant {
|
||||
public final static String[] EcgWay = {"Hand-Hand", "Hand-Chest", "1-Lead", "2-Lead"};
|
||||
public final static String[] OxyWay = {"Internal", "External", ""};
|
||||
public final static String[] TmpWay = {"Body", "Thing", ""};
|
||||
public static String filePath;
|
||||
|
||||
public static String getPathX(String s) {
|
||||
return filePath + s;
|
||||
}
|
||||
|
||||
public static void initVar(Context context) {
|
||||
File[] fs = context.getExternalFilesDirs(null);
|
||||
if (fs != null && fs.length >= 1) {
|
||||
filePath = fs[0].getAbsolutePath() + "/";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
class CheckMeInfoModel {
|
||||
String region;
|
||||
String model;
|
||||
String hardwareVer;
|
||||
String softwareVer;
|
||||
String languageVer;
|
||||
String curLanguage;
|
||||
String fileVer;
|
||||
String sPCPVer;
|
||||
String application;
|
||||
String sN;
|
||||
String branchCode;
|
||||
|
||||
CheckMeInfoModel(
|
||||
{this.region,
|
||||
this.model,
|
||||
this.hardwareVer,
|
||||
this.softwareVer,
|
||||
this.languageVer,
|
||||
this.curLanguage,
|
||||
this.fileVer,
|
||||
this.sPCPVer,
|
||||
this.application,
|
||||
this.sN,
|
||||
this.branchCode});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CheckMeInfoModel{region: $region, model: $model, hardwareVer: $hardwareVer, softwareVer: $softwareVer, languageVer: $languageVer, curLanguage: $curLanguage, fileVer: $fileVer, sPCPVer: $sPCPVer, application: $application, sN: $sN, branchCode: $branchCode}';
|
||||
}
|
||||
|
||||
CheckMeInfoModel.fromJson(Map<String, dynamic> json) {
|
||||
region = json['Region'];
|
||||
model = json['Model'];
|
||||
hardwareVer = json['HardwareVer'];
|
||||
softwareVer = json['SoftwareVer'];
|
||||
languageVer = json['LanguageVer'];
|
||||
curLanguage = json['CurLanguage'];
|
||||
fileVer = json['FileVer'];
|
||||
sPCPVer = json['SPCPVer'];
|
||||
application = json['Application'];
|
||||
sN = json['SN'];
|
||||
branchCode = json['BranchCode'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['Region'] = this.region;
|
||||
data['Model'] = this.model;
|
||||
data['HardwareVer'] = this.hardwareVer;
|
||||
data['SoftwareVer'] = this.softwareVer;
|
||||
data['LanguageVer'] = this.languageVer;
|
||||
data['CurLanguage'] = this.curLanguage;
|
||||
data['FileVer'] = this.fileVer;
|
||||
data['SPCPVer'] = this.sPCPVer;
|
||||
data['Application'] = this.application;
|
||||
data['SN'] = this.sN;
|
||||
data['BranchCode'] = this.branchCode;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
|
||||
|
||||
class CheckMeResponse {
|
||||
List<int> bytes;
|
||||
int cmd;
|
||||
int pkgNo;
|
||||
int len;
|
||||
List<int> content;
|
||||
|
||||
CheckMeResponse(List<int> bytes) {
|
||||
this.bytes = bytes;
|
||||
this.cmd = bytes[1];
|
||||
this.pkgNo = bytes.sublist(3, 5).toUInt();
|
||||
this.len = bytes.sublist(5, 7).toUInt();
|
||||
this.content = bytes.sublist(7, 7 + len);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CheckMeResponse{bytes: $bytes, cmd: $cmd, pkgNo: $pkgNo, len: $len, content: $content}';
|
||||
}
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class DeviceInfo {
|
||||
int len;
|
||||
List<int> content;
|
||||
String deviceStr;
|
||||
Map<String, dynamic> json;
|
||||
|
||||
DeviceInfo(List<int> buf) {
|
||||
len = _toUInt(buf.sublist(5, 7));
|
||||
content = buf.sublist(7, 7 + len);
|
||||
deviceStr = utf8.decode(content);
|
||||
deviceStr = deviceStr.substring(0, deviceStr.indexOf("}") + 1);
|
||||
json = jsonDecode(deviceStr);
|
||||
}
|
||||
|
||||
int _toUInt(List<int> bytes) {
|
||||
var result = 0;
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
result += bytes[i].toUnsigned(8) << (i * 8);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/bt_constants.dart';
|
||||
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class EndReadPkg {
|
||||
Uint8List buf;
|
||||
|
||||
EndReadPkg() {
|
||||
int commonPkgLength = BTConstants.COMMON_PKG_LENGTH; // Assuming BTConstant.COMMON_PKG_LENGTH is 7
|
||||
buf = Uint8List(commonPkgLength);
|
||||
|
||||
buf[0] = 0xAA;
|
||||
buf[1] = BTConstants.CMD_WORD_END_READ; // Assuming BTConstant.CMD_WORD_END_READ is defined elsewhere
|
||||
buf[2] = ~BTConstants.CMD_WORD_END_READ; // Assuming BTConstant.CMD_WORD_END_READ is defined elsewhere
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
buf[5] = 0;
|
||||
buf[6] = 0;
|
||||
|
||||
buf[buf.length - 1] = buf.calCRC8();
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/bt_constants.dart';
|
||||
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
|
||||
|
||||
class ReadContentPkg {
|
||||
List<int> buf;
|
||||
|
||||
ReadContentPkg(int pkgNum) {
|
||||
buf = List<int>.filled(7, 0);
|
||||
buf[0] = 0xAA.toByte();
|
||||
buf[1] = BTConstants.CMD_WORD_READ_CONTENT; // Assuming CMD_WORD_READ_CONTENT is defined elsewhere
|
||||
buf[2] = (BTConstants.CMD_WORD_READ_CONTENT.inv()).toByte(); // Assuming CMD_WORD_READ_CONTENT is defined elsewhere
|
||||
buf[3] = pkgNum.toByte(); // Package number
|
||||
buf[4] = (pkgNum >> 8).toByte();
|
||||
buf[5] = 0; // Data chunk size, default is 0
|
||||
buf[6] = 0;
|
||||
buf[buf.length - 1] = buf.calCRC8();
|
||||
}
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/andesfit_devices/bt_constants.dart';
|
||||
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class StartReadPkg {
|
||||
//[u, s, r, ., d, a, t]
|
||||
|
||||
//[-86, 3, -4, 0, 0, 8, 0, 117, 115, 114, 46, 100, 97, 116, 0, 0]
|
||||
|
||||
List<int> buf;
|
||||
|
||||
StartReadPkg(String fileName) {
|
||||
int commonPkgLength = BTConstants.COMMON_PKG_LENGTH;
|
||||
|
||||
int bufLength = commonPkgLength + fileName.length + 1;
|
||||
buf = List<int>.filled(bufLength, 0);
|
||||
|
||||
buf[0] = (0xAA).toByte();
|
||||
buf[1] = BTConstants.CMD_WORD_START_READ;
|
||||
buf[2] = ((BTConstants.CMD_WORD_START_READ).inv()).toByte();
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
buf[5] = (bufLength - commonPkgLength).toByte();
|
||||
buf[6] = ((bufLength - commonPkgLength) >> 8).toByte();
|
||||
|
||||
if (fileName != null) {
|
||||
List<int> tempFile = fileName.codeUnits;
|
||||
|
||||
for (int i = 0; i < tempFile.length; i++) {
|
||||
buf[i + 7] = tempFile[i].toByte();
|
||||
}
|
||||
}
|
||||
|
||||
buf[bufLength - 1] = buf.calCRC8();
|
||||
|
||||
// [-86, 3, -4, 0, 0, 8, 0, 117, 115, 114, 46, 100, 97, 116, 0, 124] --> KOTLIN
|
||||
// [-86, 3, -4, 0, 0, 8, 0, 117, 115, 114, 46, 100, 97, 116, 0, 124] --> DART
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue