Compare commits
79 Commits
dev_v3.13.
...
dev_v3.13.
| Author | SHA1 | Date |
|---|---|---|
|
|
66a9afa6f3 | 2 years ago |
|
|
34e47421a3 | 2 years ago |
|
|
336536df4a | 2 years ago |
|
|
c10fb7f1a9 | 2 years ago |
|
|
6f2392bee3 | 2 years ago |
|
|
6e96f9c0d0 | 2 years ago |
|
|
0830b4d248 | 2 years ago |
|
|
b136f63e40 | 2 years ago |
|
|
c1751c05db | 2 years ago |
|
|
be294ae264 | 2 years ago |
|
|
6cd410e2d9 | 2 years ago |
|
|
6fd429c883 | 2 years ago |
|
|
2922f74e9b | 2 years ago |
|
|
518785323e | 2 years ago |
|
|
55b93feda3 | 2 years ago |
|
|
4ec93e8609 | 2 years ago |
|
|
6cd1e29998 | 2 years ago |
|
|
cd3783d9f6 | 2 years ago |
|
|
4d74d2143f | 2 years ago |
|
|
32b32e34fd | 2 years ago |
|
|
322d0a8b5d | 2 years ago |
|
|
1bf0f7558d | 2 years ago |
|
|
e0a54798ba | 2 years ago |
|
|
52e2e15b4d | 2 years ago |
|
|
b212fe6bbb | 2 years ago |
|
|
275fa5ca3a | 2 years ago |
|
|
fd79b10f41 | 2 years ago |
|
|
0967e45752 | 2 years ago |
|
|
a494f454cb | 2 years ago |
|
|
4893a1f3af | 2 years ago |
|
|
43f149d940 | 2 years ago |
|
|
5dc0f571c8 | 2 years ago |
|
|
c73333d164 | 2 years ago |
|
|
1cc77e7d32 | 2 years ago |
|
|
8611903db0 | 2 years ago |
|
|
70ca4071fc | 2 years ago |
|
|
a271e700c7 | 2 years ago |
|
|
33b0900b37 | 2 years ago |
|
|
be53844c58 | 2 years ago |
|
|
c9994b8269 | 2 years ago |
|
|
0a700270f4 | 2 years ago |
|
|
c3ce151a79 | 2 years ago |
|
|
6e97f8556f | 2 years ago |
|
|
6aea29e06a | 2 years ago |
|
|
83b681981d | 2 years ago |
|
|
7e49dac7bd | 2 years ago |
|
|
886677d97e | 2 years ago |
|
|
3d1d61066f | 2 years ago |
|
|
7d023cdb35 | 2 years ago |
|
|
6e6c4fef1a | 2 years ago |
|
|
6ee64b923e | 2 years ago |
|
|
6fd40305b4 | 2 years ago |
|
|
1fd978e0c2 | 2 years ago |
|
|
68b83e5f98 | 2 years ago |
|
|
b137f4b09a | 2 years ago |
|
|
433616c7b6 | 2 years ago |
|
|
b6a3ae2380 | 2 years ago |
|
|
28cd6769ec | 2 years ago |
|
|
e52e75aefd | 2 years ago |
|
|
2500441832 | 2 years ago |
|
|
9361d058fc | 2 years ago |
|
|
e59734ce43 | 2 years ago |
|
|
55b447926e | 2 years ago |
|
|
1b39b1a5a8 | 2 years ago |
|
|
448740a854 | 2 years ago |
|
|
767f81c8cf | 2 years ago |
|
|
e282d73dcf | 2 years ago |
|
|
b183518a19 | 2 years ago |
|
|
efba7faa78 | 2 years ago |
|
|
22d6a415c7 | 2 years ago |
|
|
3f2452c8fd | 2 years ago |
|
|
5b7cde43d1 | 2 years ago |
|
|
3f767f738a | 2 years ago |
|
|
aad249297c | 2 years ago |
|
|
382ff07a89 | 2 years ago |
|
|
992f7dd454 | 2 years ago |
|
|
ee5f90aba1 | 2 years ago |
|
|
336c0f17b6 | 2 years ago |
|
|
23ab0483e0 | 2 years ago |
Binary file not shown.
@ -0,0 +1,17 @@
|
||||
package com.cloud.diplomaticquarterapp.ble;
|
||||
|
||||
public class BPModelMeasuring {
|
||||
|
||||
public int pressure;
|
||||
public int pr;
|
||||
public boolean deflate;
|
||||
public boolean pulse;
|
||||
|
||||
public BPModelMeasuring(int pressure, int pr, boolean deflate, boolean pulse) {
|
||||
this.pressure = pressure;
|
||||
this.pr = pr;
|
||||
this.deflate = deflate;
|
||||
this.pulse = pulse;
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.cloud.diplomaticquarterapp.ble;
|
||||
|
||||
public class BPModelResult {
|
||||
|
||||
public boolean deflate;
|
||||
public int dia;
|
||||
public int mean;
|
||||
public int pr;
|
||||
public int pressure;
|
||||
public int result;
|
||||
public int sys;
|
||||
|
||||
public BPModelResult(boolean deflate, int dia, int mean, int pr, int pressure, int result, int sys) {
|
||||
this.deflate = deflate;
|
||||
this.dia = dia;
|
||||
this.mean = mean;
|
||||
this.pr = pr;
|
||||
this.pressure = pressure;
|
||||
this.result = result;
|
||||
this.sys = sys;
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,22 @@
|
||||
package com.cloud.diplomaticquarterapp.ble;
|
||||
|
||||
public class OxymeterModel {
|
||||
|
||||
public int spo2;
|
||||
public int pr;
|
||||
public float pi;
|
||||
public boolean isProbeOff;
|
||||
public boolean isPulseSearching;
|
||||
public boolean isCheckProbe;
|
||||
public int battery;
|
||||
|
||||
public OxymeterModel(int spo2, int pr, float pi, boolean isProbeOff, boolean isPulseSearching, boolean isCheckProbe, int battery) {
|
||||
this.spo2 = spo2;
|
||||
this.pr = pr;
|
||||
this.pi = pi;
|
||||
this.isProbeOff = isProbeOff;
|
||||
this.isPulseSearching = isPulseSearching;
|
||||
this.isCheckProbe = isCheckProbe;
|
||||
this.battery = battery;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.cloud.diplomaticquarterapp.ble.utils;
|
||||
|
||||
public class AlgorithmUtil {
|
||||
public static native double[] filter(double var0, boolean var2);
|
||||
|
||||
public static native short[] shortFilter(short[] var0);
|
||||
|
||||
static {
|
||||
System.loadLibrary("online-lib");
|
||||
System.loadLibrary("offline-lib");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package com.cloud.diplomaticquarterapp.ble.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class EcgData {
|
||||
|
||||
private long startTime; // 时间戳s
|
||||
private int duration;
|
||||
private String fileName;
|
||||
private byte[] data;
|
||||
private short[] shortData;
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(long startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(int duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public short[] getShortData() {
|
||||
return shortData;
|
||||
}
|
||||
|
||||
public void setShortData(short[] shortData) {
|
||||
this.shortData = shortData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" + "startTime:" + startTime + ", duration:" + duration + ", fileName:'" + fileName + '\'' + ", data:" + Arrays.toString(data) + ", shortData:" + Arrays.toString(shortData) + '}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
//package com.cloud.diplomaticquarterapp.ble.utils;
|
||||
//
|
||||
////
|
||||
//// Source code recreated from a .class file by IntelliJ IDEA
|
||||
//// (powered by FernFlower decompiler)
|
||||
////
|
||||
//
|
||||
//
|
||||
//import doac.doba;
|
||||
//import doac.dobn;
|
||||
//import doac.docn;
|
||||
//
|
||||
//public class FilterUtil {
|
||||
// public FilterUtil() {
|
||||
// }
|
||||
//
|
||||
// public static short[] getEcgFileFilterData(int var0, byte[] var1) {
|
||||
// if (var0 != 7 && var0 != 8) {
|
||||
// if (var0 == 19) {
|
||||
// return AlgorithmUtil.shortFilter((new doba(var1)).doan());
|
||||
// }
|
||||
//
|
||||
// if (var0 == 52) {
|
||||
// return AlgorithmUtil.shortFilter((new docn("", var1, "")).doah());
|
||||
// }
|
||||
//
|
||||
// if (var0 != 77 && var0 != 127) {
|
||||
// if (var0 == 32) {
|
||||
// return AlgorithmUtil.shortFilter((new doba(var1)).doan());
|
||||
// }
|
||||
//
|
||||
// if (var0 != 33 && var0 != 74 && var0 != 75) {
|
||||
// switch (var0) {
|
||||
// case 145:
|
||||
// case 146:
|
||||
// case 147:
|
||||
// case 148:
|
||||
// case 149:
|
||||
// break;
|
||||
// default:
|
||||
// return new short[0];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return AlgorithmUtil.shortFilter(DecompressUtil.er1Decompress((new dobn(var1)).doad()));
|
||||
// }
|
||||
//}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.cloud.diplomaticquarterapp.ble.utils;
|
||||
|
||||
//
|
||||
// Source code recreated from a .class file by IntelliJ IDEA
|
||||
// (powered by FernFlower decompiler)
|
||||
//
|
||||
|
||||
public class HexString {
|
||||
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
|
||||
|
||||
private HexString() {
|
||||
}
|
||||
|
||||
public static String bytesToHex(byte[] var0) {
|
||||
char[] var1 = new char[var0.length * 2];
|
||||
|
||||
for(int var2 = 0; var2 < var0.length; ++var2) {
|
||||
int var3 = var0[var2] & 255;
|
||||
int var4 = var2 * 2;
|
||||
char[] var5;
|
||||
char[] var10001 = var5 = HEX_ARRAY;
|
||||
int var10002 = var3;
|
||||
var1[var4] = var5[var3 >>> 4];
|
||||
var3 = var4 + 1;
|
||||
var1[var3] = var10001[var10002 & 15];
|
||||
}
|
||||
|
||||
return new String(var1);
|
||||
}
|
||||
|
||||
public static byte[] hexToBytes(String var0) {
|
||||
if (var0.length() % 2 == 1) {
|
||||
throw new IllegalArgumentException("hexToBytes requires an even-length String parameter");
|
||||
} else {
|
||||
int var1;
|
||||
byte[] var2 = new byte[(var1 = var0.length()) / 2];
|
||||
|
||||
for(int var3 = 0; var3 < var1; var3 += 2) {
|
||||
int var4 = var3 / 2;
|
||||
var2[var4] = (byte)((Character.digit(var0.charAt(var3), 16) << 4) + Character.digit(var0.charAt(var3 + 1), 16));
|
||||
}
|
||||
|
||||
return var2;
|
||||
}
|
||||
}
|
||||
|
||||
public static String trimStr(String var0) {
|
||||
return var0.trim();
|
||||
}
|
||||
}
|
||||
@ -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,19 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.bean
|
||||
|
||||
import com.google.gson.Gson
|
||||
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
|
||||
)
|
||||
|
||||
fun UserBean.toJson(): String {
|
||||
return Gson().toJson(this)
|
||||
}
|
||||
@ -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,56 @@
|
||||
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()
|
||||
|
||||
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,64 @@
|
||||
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
|
||||
import com.cloud.diplomaticquarterapp.utils.Constant
|
||||
|
||||
|
||||
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,224 @@
|
||||
package com.cloud.diplomaticquarterapp.check_me_pro.ble.worker
|
||||
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.content.Context
|
||||
import android.os.Environment
|
||||
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.format.UserInfo
|
||||
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)} "
|
||||
}
|
||||
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 {
|
||||
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.buf.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,235 @@
|
||||
package com.cloud.diplomaticquarterapp.smart_ring_2301
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Service
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.bluetooth.le.ScanSettings
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.text.TextUtils
|
||||
import com.jstyle.blesdk2301.callback.BleConnectionListener
|
||||
import com.jstyle.blesdk2301.callback.OnScanResults
|
||||
import com.jstyle.blesdk2301.model.Device
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* 蓝牙管理类 Bluetooth management class
|
||||
*/
|
||||
@SuppressLint("MissingPermission")
|
||||
class BleManager private constructor(var context: Context) {
|
||||
private var address: String? = null
|
||||
private var bleService: BleService? = null
|
||||
private val serviceConnection: ServiceConnection = object : ServiceConnection {
|
||||
override fun onServiceDisconnected(name: ComponentName) { // TODO Auto-generated method stub
|
||||
bleService = null
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||
bleService = (service as BleService.LocalBinder).service
|
||||
if (!TextUtils.isEmpty(address)) {
|
||||
bleService!!.initBluetoothDevice(address, context, NeedReconnect1, bleConnectionListener1)
|
||||
}
|
||||
}
|
||||
}
|
||||
private var serviceIntent: Intent? = null
|
||||
var bluetoothAdapter: BluetoothAdapter?
|
||||
val isBleEnable: Boolean
|
||||
get() = bluetoothAdapter!!.enable()
|
||||
|
||||
/**
|
||||
* 连接蓝牙设备
|
||||
* Connect Bluetooth device
|
||||
*
|
||||
* @param address
|
||||
*/
|
||||
protected var NeedReconnect1 = true
|
||||
protected var bleConnectionListener1: BleConnectionListener? = null
|
||||
fun connectDevice(address: String?, NeedReconnect: Boolean, bleConnectionListener: BleConnectionListener?) {
|
||||
NeedReconnect1 = NeedReconnect
|
||||
bleConnectionListener1 = bleConnectionListener
|
||||
if (!bluetoothAdapter!!.isEnabled || TextUtils.isEmpty(address) || isConnected) return
|
||||
if (bleService == null) {
|
||||
this.address = address
|
||||
} else {
|
||||
bleService!!.initBluetoothDevice(address, context, NeedReconnect, bleConnectionListener)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭蓝牙服务通知
|
||||
* Turn off Bluetooth service notification
|
||||
*/
|
||||
fun enableNotifaction() {
|
||||
if (bleService == null) return
|
||||
bleService!!.setCharacteristicNotification(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入指令到蓝牙设备
|
||||
* Write command to Bluetooth device
|
||||
*/
|
||||
fun writeValue(value: ByteArray?) {
|
||||
if (bleService == null || instance == null) return
|
||||
bleService!!.writeValue(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 多条指令同时添加后发送到设备
|
||||
* Multiple instructions are added at the same time and sent to the device
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
fun offerValue(data: ByteArray?) {
|
||||
if (bleService == null) return
|
||||
if (data != null) {
|
||||
bleService!!.offerValue(data)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入指令到蓝牙设备
|
||||
* Write command to Bluetooth device
|
||||
*/
|
||||
fun writeValue() {
|
||||
if (bleService == null) return
|
||||
bleService!!.nextQueue()
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开设备 Disconnect the device
|
||||
*/
|
||||
fun disconnectDevice() {
|
||||
if (bleService == null) return
|
||||
bleService!!.disconnect()
|
||||
}
|
||||
|
||||
val isConnected: Boolean
|
||||
/**
|
||||
* 查询设备是否已经连接
|
||||
* Query whether the device is connected
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
get() = if (bleService == null) false else bleService!!.isConnected
|
||||
|
||||
/**
|
||||
* 取消扫描设备
|
||||
* Cancel scanning device
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
fun StopDeviceScan() {
|
||||
isinScan = false
|
||||
if (null != bluetoothAdapter && null != bluetoothAdapter!!.bluetoothLeScanner) {
|
||||
bluetoothAdapter!!.bluetoothLeScanner.stopScan(scanCallback)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描蓝牙设备,用于开始绑定设备
|
||||
* Scan Bluetooth device to start binding device
|
||||
*/
|
||||
private var DevicesName: Array<String>? = null
|
||||
private var onScanResult: OnScanResults? = null
|
||||
private var isinScan = false
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
fun DeviceScanResults(Devicesname: Array<String>, onScanResults: OnScanResults) {
|
||||
if (!isinScan && instance!!.isBleEnable) { //如果蓝牙开关是开启的就进行扫描
|
||||
isinScan = true
|
||||
DevicesName = Devicesname
|
||||
onScanResult = onScanResults
|
||||
//返回已配对设备
|
||||
//获得已配对的远程蓝牙设备的集合
|
||||
val devices = bluetoothAdapter!!.bondedDevices
|
||||
if (devices.size > 0) {
|
||||
for (bluetoothDevice in devices) {
|
||||
if (Canctians(bluetoothDevice.name.lowercase(Locale.getDefault()))) {
|
||||
val device = Device()
|
||||
device.bluetoothDevice = bluetoothDevice
|
||||
device.isIsconted = false
|
||||
device.isPaired = true
|
||||
device.isIsdfu = bluetoothDevice.name.lowercase(Locale.getDefault()).contains("dfu")
|
||||
device.name = bluetoothDevice.name
|
||||
device.mac = bluetoothDevice.address
|
||||
onScanResult!!.Success(device)
|
||||
}
|
||||
}
|
||||
}
|
||||
bluetoothAdapter!!.bluetoothLeScanner.startScan(null, ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(), scanCallback)
|
||||
}
|
||||
}
|
||||
|
||||
private val scanCallback: ScanCallback = object : ScanCallback() {
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||
super.onScanResult(callbackType, result)
|
||||
val deviceName = result.device.name
|
||||
if (isinScan && !TextUtils.isEmpty(deviceName) && Canctians(deviceName.lowercase(Locale.getDefault()).trim { it <= ' ' })) {
|
||||
val device = Device()
|
||||
device.bluetoothDevice = result.device
|
||||
device.isIsconted = false
|
||||
device.isPaired = false
|
||||
device.isIsdfu = deviceName.lowercase(Locale.getDefault()).contains("dfu")
|
||||
device.name = result.device.name
|
||||
device.mac = result.device.address
|
||||
device.riss = result.rssi
|
||||
onScanResult!!.Success(device)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBatchScanResults(results: List<ScanResult>) {
|
||||
super.onBatchScanResults(results)
|
||||
}
|
||||
|
||||
override fun onScanFailed(errorCode: Int) {
|
||||
super.onScanFailed(errorCode)
|
||||
onScanResult!!.Fail(errorCode)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
if (serviceIntent == null) {
|
||||
serviceIntent = Intent(context, BleService::class.java)
|
||||
context.bindService(serviceIntent!!, serviceConnection, Service.BIND_AUTO_CREATE)
|
||||
}
|
||||
val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
||||
bluetoothAdapter = bluetoothManager.adapter
|
||||
}
|
||||
|
||||
private fun Canctians(name: String): Boolean {
|
||||
var catian = false
|
||||
if (null == DevicesName || DevicesName!!.size == 0) {
|
||||
return false
|
||||
} else {
|
||||
for (devicesname in DevicesName!!) {
|
||||
if (name.lowercase(Locale.getDefault()).contains(devicesname.lowercase(Locale.getDefault()))) {
|
||||
catian = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return catian
|
||||
}
|
||||
|
||||
companion object {
|
||||
var instance: BleManager? = null
|
||||
private set
|
||||
|
||||
fun init(context: Context) {
|
||||
if (instance != null) {
|
||||
return
|
||||
}
|
||||
synchronized(BleManager::class.java) {
|
||||
if (instance == null) {
|
||||
instance = BleManager(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,11 @@
|
||||
package com.cloud.diplomaticquarterapp.smart_ring_2301.Util
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2017/4/11.
|
||||
*/
|
||||
class BleData {
|
||||
|
||||
var value: ByteArray? = null
|
||||
var action: String? = null
|
||||
var data: String? = null
|
||||
}
|
||||
@ -0,0 +1,137 @@
|
||||
package com.cloud.diplomaticquarterapp.smart_ring_2301.Util
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* 计时器
|
||||
*/
|
||||
class CustomCountDownTimer(
|
||||
//Millis since epoch when alarm should stop.
|
||||
private var millisInFuture: Long, countDownInterval: Long,
|
||||
tickListener: TimerTickListener
|
||||
) {
|
||||
//thread on which the callbacks will be called
|
||||
private val mainThreadHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
//listener interface which is to be implemented by the users of the count down timer
|
||||
interface TimerTickListener {
|
||||
/**
|
||||
* Callback on each tick
|
||||
*
|
||||
* @param millisLeft time left in millisec for the timer to shutdown
|
||||
*/
|
||||
fun onTick(millisLeft: Long)
|
||||
|
||||
/**
|
||||
* Callback to be invokded when timer's time finishes
|
||||
*/
|
||||
fun onFinish()
|
||||
|
||||
/**
|
||||
* Callback to be invokded when timer is canceled
|
||||
*/
|
||||
fun onCancel()
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class which delegates the events to callbacks provided in the TimerTickListener
|
||||
*/
|
||||
private inner class TimerRunnable : Runnable {
|
||||
override fun run() {
|
||||
if (isCancelled) {
|
||||
scheduler.shutdown()
|
||||
mainThreadHandler.post { tickListener.onCancel() }
|
||||
} else if (isPaused) {
|
||||
} else {
|
||||
stopTimeInFuture = stopTimeInFuture - countdownInterval
|
||||
mainThreadHandler.post(object : Runnable {
|
||||
val millisLeft = stopTimeInFuture
|
||||
override fun run() {
|
||||
if (millisLeft <= 0) {
|
||||
tickListener.onFinish()
|
||||
scheduler.shutdown()
|
||||
} else {
|
||||
tickListener.onTick(millisLeft)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//The interval in millis that the user receives callbacks
|
||||
private val countdownInterval: Long
|
||||
|
||||
//the time at which timer is to stop
|
||||
private var stopTimeInFuture: Long
|
||||
|
||||
//boolean representing if the timer was cancelled
|
||||
var isCancelled = false
|
||||
|
||||
//boolean representing if the timer was paused
|
||||
private var isPaused = false
|
||||
|
||||
//listener which listens to the timer events
|
||||
private val tickListener: TimerTickListener
|
||||
|
||||
//scheduler which provides the thread to create timer
|
||||
private val scheduler: ScheduledExecutorService
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param millisInFuture time in millisec for which timer is to run
|
||||
* @param countDownInterval interval frequency in millisec at which the callback will be invoked
|
||||
* @param tickListener implementation of TimerTickListener which provides callbacks code
|
||||
*/
|
||||
init {
|
||||
stopTimeInFuture = millisInFuture
|
||||
countdownInterval = countDownInterval
|
||||
this.tickListener = tickListener
|
||||
scheduler = Executors.newSingleThreadScheduledExecutor()
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the countdown.
|
||||
*/
|
||||
@Synchronized
|
||||
fun start() {
|
||||
isCancelled = false
|
||||
isPaused = false
|
||||
scheduler.scheduleWithFixedDelay(
|
||||
TimerRunnable(), countdownInterval, countdownInterval,
|
||||
TimeUnit.MILLISECONDS
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the countdown timer
|
||||
*/
|
||||
@Synchronized
|
||||
fun cancel() {
|
||||
isCancelled = true
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun pause() {
|
||||
isPaused = true
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun resume() {
|
||||
isPaused = false
|
||||
}
|
||||
|
||||
fun extendTime(delta: Long) {
|
||||
stopTimeInFuture = stopTimeInFuture + delta
|
||||
millisInFuture = millisInFuture + delta
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "CustomCountDownTimer"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,248 @@
|
||||
package com.cloud.diplomaticquarterapp.smart_ring_2301.Util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.content.ContentResolver
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.provider.DocumentsContract
|
||||
import android.provider.MediaStore
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import java.io.UnsupportedEncodingException
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2017/4/6.
|
||||
*/
|
||||
object ResolveData {
|
||||
private const val TAG = "ResolveData"
|
||||
private const val SHORTENED_LOCAL_NAME = 0x08
|
||||
private const val COMPLETE_LOCAL_NAME = 0x09
|
||||
private const val oneMinMillis = 60 * 1000L
|
||||
var startString = " 12:00:00"
|
||||
fun getBcd(value: String): Int {
|
||||
return value.toInt(16)
|
||||
}
|
||||
|
||||
fun decodeDeviceName(data: ByteArray): String? {
|
||||
var name: String? = null
|
||||
var fieldLength: Int
|
||||
var fieldName: Int
|
||||
val packetLength = data.size
|
||||
var index = 0
|
||||
while (index < packetLength) {
|
||||
fieldLength = data[index].toInt()
|
||||
if (fieldLength <= 0) break
|
||||
fieldName = data[++index].toInt()
|
||||
if (fieldName == COMPLETE_LOCAL_NAME
|
||||
|| fieldName == SHORTENED_LOCAL_NAME
|
||||
) {
|
||||
name = decodeLocalName(data, index + 1, fieldLength - 1)
|
||||
break
|
||||
}
|
||||
index += fieldLength - 1
|
||||
index++
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@JvmStatic
|
||||
fun decodeDeviceName(bluetoothDevice: BluetoothDevice, data: ByteArray): String? {
|
||||
var name = bluetoothDevice.name
|
||||
if (!TextUtils.isEmpty(name)) return name
|
||||
var fieldLength: Int
|
||||
var fieldName: Int
|
||||
val packetLength = data.size
|
||||
var index = 0
|
||||
while (index < packetLength) {
|
||||
fieldLength = data[index].toInt()
|
||||
if (fieldLength <= 0) break
|
||||
fieldName = data[++index].toInt()
|
||||
if (fieldName == COMPLETE_LOCAL_NAME
|
||||
|| fieldName == SHORTENED_LOCAL_NAME
|
||||
) {
|
||||
name = decodeLocalName(data, index + 1, fieldLength - 1)
|
||||
break
|
||||
}
|
||||
index += fieldLength - 1
|
||||
index++
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the local name
|
||||
*/
|
||||
fun decodeLocalName(
|
||||
data: ByteArray?, start: Int,
|
||||
length: Int
|
||||
): String? {
|
||||
return try {
|
||||
kotlin.String()
|
||||
} catch (e: UnsupportedEncodingException) {
|
||||
Log.e(
|
||||
"scan", "Unable to convert the complete local name to UTF-8",
|
||||
e
|
||||
)
|
||||
null
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
Log.e("scan", "Error when reading complete local name", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转十六进制字符串
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
@JvmStatic
|
||||
fun byte2Hex(data: ByteArray?): String {
|
||||
if (data != null && data.size > 0) {
|
||||
val sb = StringBuilder(data.size)
|
||||
for (tmp in data) {
|
||||
sb.append(String.format("%02X ", tmp))
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
return "no data"
|
||||
}
|
||||
|
||||
fun getRealFilePath(context: Context, uri: Uri?): String? {
|
||||
if (null == uri) return null
|
||||
val scheme = uri.scheme
|
||||
var data: String? = null
|
||||
if (scheme == null) data = uri.path else if (ContentResolver.SCHEME_FILE == scheme) {
|
||||
data = uri.path
|
||||
} else if (ContentResolver.SCHEME_CONTENT == scheme) {
|
||||
val cursor = context.contentResolver.query(uri, arrayOf(MediaStore.Images.ImageColumns.DATA), null, null, null)
|
||||
if (null != cursor) {
|
||||
if (cursor.moveToFirst()) {
|
||||
val index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)
|
||||
if (index > -1) {
|
||||
data = cursor.getString(index)
|
||||
}
|
||||
}
|
||||
cursor.close()
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* 专为Android4.4设计的从Uri获取文件绝对路径
|
||||
*/
|
||||
fun getPath(context: Context, uri: Uri): String? {
|
||||
|
||||
|
||||
// DocumentProvider
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
|
||||
// ExternalStorageProvider
|
||||
if (isExternalStorageDocument(uri)) {
|
||||
val docId = DocumentsContract.getDocumentId(uri)
|
||||
val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
val type = split[0]
|
||||
if ("primary".equals(type, ignoreCase = true)) {
|
||||
return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
|
||||
}
|
||||
|
||||
// TODO handle non-primary volumes
|
||||
} else if (isDownloadsDocument(uri)) {
|
||||
val id = DocumentsContract.getDocumentId(uri)
|
||||
val contentUri = ContentUris.withAppendedId(
|
||||
Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id)
|
||||
)
|
||||
return getDataColumn(context, contentUri, null, null)
|
||||
} else if (isMediaDocument(uri)) {
|
||||
val docId = DocumentsContract.getDocumentId(uri)
|
||||
val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
val type = split[0]
|
||||
var contentUri: Uri? = null
|
||||
if ("image" == type) {
|
||||
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||
} else if ("video" == type) {
|
||||
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||
} else if ("audio" == type) {
|
||||
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
|
||||
}
|
||||
val selection = "_id=?"
|
||||
val selectionArgs = arrayOf(split[1])
|
||||
return getDataColumn(context, contentUri, selection, selectionArgs)
|
||||
}
|
||||
} else if ("content".equals(uri.scheme, ignoreCase = true)) {
|
||||
return getDataColumn(context, uri, null, null)
|
||||
} else if ("file".equals(uri.scheme, ignoreCase = true)) {
|
||||
return uri.path
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the data column for this Uri. This is useful for
|
||||
* MediaStore Uris, and other file-based ContentProviders.
|
||||
*
|
||||
* @param context
|
||||
* The context.
|
||||
* @param uri
|
||||
* The Uri to query.
|
||||
* @param selection
|
||||
* (Optional) Filter used in the query.
|
||||
* @param selectionArgs
|
||||
* (Optional) Selection arguments used in the query.
|
||||
* @return The value of the _data column, which is typically a file path.
|
||||
*/
|
||||
fun getDataColumn(
|
||||
context: Context, uri: Uri?, selection: String?,
|
||||
selectionArgs: Array<String>?
|
||||
): String? {
|
||||
var cursor: Cursor? = null
|
||||
val column = "_data"
|
||||
val projection = arrayOf(column)
|
||||
try {
|
||||
cursor = context.contentResolver.query(
|
||||
uri!!, projection, selection, selectionArgs,
|
||||
null
|
||||
)
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
val column_index = cursor.getColumnIndexOrThrow(column)
|
||||
return cursor.getString(column_index)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uri
|
||||
* The Uri to check.
|
||||
* @return Whether the Uri authority is ExternalStorageProvider.
|
||||
*/
|
||||
fun isExternalStorageDocument(uri: Uri): Boolean {
|
||||
return "com.android.externalstorage.documents" == uri.authority
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uri
|
||||
* The Uri to check.
|
||||
* @return Whether the Uri authority is DownloadsProvider.
|
||||
*/
|
||||
fun isDownloadsDocument(uri: Uri): Boolean {
|
||||
return "com.android.providers.downloads.documents" == uri.authority
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uri
|
||||
* The Uri to check.
|
||||
* @return Whether the Uri authority is MediaProvider.
|
||||
*/
|
||||
fun isMediaDocument(uri: Uri): Boolean {
|
||||
return "com.android.providers.media.documents" == uri.authority
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.cloud.diplomaticquarterapp.smart_ring_2301.Util
|
||||
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.processors.FlowableProcessor
|
||||
import io.reactivex.rxjava3.processors.PublishProcessor
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import io.reactivex.rxjava3.subjects.Subject
|
||||
|
||||
|
||||
/**
|
||||
* Created by zhuge on 2017/1/19 0019.
|
||||
*/
|
||||
class RxBus private constructor() {
|
||||
private val bus: Subject<Any>
|
||||
private val mBus: FlowableProcessor<Any>
|
||||
|
||||
init {
|
||||
mBus = PublishProcessor.create<Any>().toSerialized()
|
||||
bus = PublishSubject.create<Any>().toSerialized()
|
||||
}
|
||||
|
||||
fun post(`object`: Any) {
|
||||
bus.onNext(`object`)
|
||||
}
|
||||
|
||||
fun <T : Any> toObservable(eventType: Class<T>): Observable<T> {
|
||||
return bus.ofType(eventType)
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
val instance = RxBus()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.cloud.diplomaticquarterapp.smart_ring_2301.Util
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.ObservableTransformer
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2017/4/26.
|
||||
*/
|
||||
object SchedulersTransformer {
|
||||
private const val TAG = "SchedulersTransformer"
|
||||
fun <T : Any> io2MainObservable(): ObservableTransformer<T, T> {
|
||||
return ObservableTransformer { upstream -> upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) }
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package com.cloud.diplomaticquarterapp.smart_ring_2301.Util
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
|
||||
object SharedPreferenceUtils {
|
||||
const val KEY_REMIND_PSD = "REMIND_PSD"
|
||||
const val KEY_account_type = "KEY_account_type"
|
||||
const val KEY_countryCode = "KEY_countryCode"
|
||||
const val KEY_TimeZone = "KEY_TimeZone"
|
||||
const val KEY_DFU_ADDRESS = "KEY_DFU_ADDRESS"
|
||||
const val KEY_Exercise_Mode = "KEY_Exercise_Mode"
|
||||
const val KEY_Enable_ActivityClock = "KEY_Enable_ActivityClock"
|
||||
const val KEY_UNIT_WEIGHT = "KEY_UNIT_WEIGHT"
|
||||
const val KEY_UNIT_HEIGHT = "KEY_UNIT_HEIGHT"
|
||||
const val KEY_RES_FILEPATH = "KEY_RES_FILEPATH"
|
||||
const val KEY_Is_First = "KEY_Is_First"
|
||||
const val KEY_From_Login = "KEY_From_Login"
|
||||
const val KEY_PHONE = "PHONE"
|
||||
const val KEY_UID = "uid"
|
||||
const val KEY_PSD = "PSD"
|
||||
const val KEY_ADDRESS = "ADDRESS"
|
||||
const val KEY_Language = "Language"
|
||||
const val KEY_LOGIN = "lOGIN"
|
||||
const val KEY_NICKNAME = "nickname"
|
||||
private const val spName = "jstyle_sleep"
|
||||
const val KEY_AUTH_USERID = "KEY_AUTH_USERID"
|
||||
const val KEY_highHeart = "highHeart"
|
||||
const val KEY_highBrEATH = "highBrEATH"
|
||||
const val KEY_lowHeart = "lowHeart"
|
||||
const val KEY_lowBreath = "lowBreath"
|
||||
const val KEY_deviceName = "deviceName"
|
||||
const val KEY_PLAN_ON = "PLAN_ON"
|
||||
const val KEY_PLAN_first = "PLAN_first"
|
||||
const val KEY_Sleep_goal = "KEY_Sleep_goal"
|
||||
const val KEY_Step_goal = "KEY_Step_goal"
|
||||
const val KEY_deviceType = "KEY_deviceType"
|
||||
var sharedPreferences: SharedPreferences? = null
|
||||
private set
|
||||
const val DefaultCountryCode = "0086-"
|
||||
fun init(context: Context) {
|
||||
sharedPreferences = context.getSharedPreferences(spName, Activity.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
fun setSpBoolean(name: String?, bool: Boolean) {
|
||||
sharedPreferences!!.edit().putBoolean(name, bool).commit()
|
||||
}
|
||||
|
||||
fun getSpBoolean(name: String?): Boolean {
|
||||
return sharedPreferences!!.getBoolean(name, false)
|
||||
}
|
||||
|
||||
fun getBoolean(name: String?, defaultValue: Boolean): Boolean {
|
||||
return sharedPreferences!!.getBoolean(name, defaultValue)
|
||||
}
|
||||
|
||||
fun setSpString(name: String?, value: String?) {
|
||||
sharedPreferences!!.edit().putString(name, value).commit()
|
||||
}
|
||||
|
||||
fun getSpString(name: String?): String? {
|
||||
return getString(name, null)
|
||||
}
|
||||
|
||||
fun getString(name: String?, defaultValue: String?): String? {
|
||||
return sharedPreferences!!.getString(name, defaultValue)
|
||||
}
|
||||
|
||||
fun setSpInteger(name: String?, value: Int) {
|
||||
sharedPreferences!!.edit().putInt(name, value).commit()
|
||||
}
|
||||
|
||||
fun getInteger(name: String?, defaultValue: Int): Int {
|
||||
return sharedPreferences!!.getInt(name, defaultValue)
|
||||
}
|
||||
|
||||
fun getSpInteger(name: String?): Int {
|
||||
return getInteger(name, -1)
|
||||
}
|
||||
|
||||
fun setSpFloat(name: String?, value: Float) {
|
||||
sharedPreferences!!.edit().putFloat(name, value).commit()
|
||||
}
|
||||
|
||||
fun getSpFloat(name: String?): Float {
|
||||
return getFloat(name, 0.0f)
|
||||
}
|
||||
|
||||
fun getFloat(name: String?, defaultValue: Float): Float {
|
||||
return sharedPreferences!!.getFloat(name, defaultValue)
|
||||
}
|
||||
}
|
||||
@ -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,7 @@
|
||||
package com.cloud.diplomaticquarterapp.utils
|
||||
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
|
||||
object UiChannel {
|
||||
val progressChannel = Channel<Int>(Channel.CONFLATED)
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'org.jetbrains.kotlin.android'
|
||||
|
||||
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
|
||||
lintOptions{
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
|
||||
minSdkVersion 18
|
||||
targetSdkVersion 33
|
||||
versionCode 3
|
||||
versionName "3.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
task makejar(type: Jar) {
|
||||
from file('build/intermediates/javac/debug/classes')
|
||||
archiveName = '2301sdk' + defaultConfig.versionName + '.jar'
|
||||
destinationDir = file('build/libs')
|
||||
include "com/jstyle/blesdk2301/**"
|
||||
|
||||
|
||||
}
|
||||
makejar.dependsOn(build)
|
||||
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'androidx.core:core-ktx:+'
|
||||
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +1,26 @@
|
||||
package com.jstyle.blesdk2301;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.jstyle.blesdk.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.jstyle.blesdk2301.callback
|
||||
|
||||
interface BleConnectionListener {
|
||||
fun BleStatus(status: Int, newState: Int) //蓝牙4.0连接状态 Bluetooth 4.0 connection status
|
||||
fun ConnectionSucceeded() //连接设备成功 Successfully connected the device
|
||||
fun Connecting() //设备连接中 Device is connected
|
||||
fun ConnectionFailed() //设备连接失败 Device connection failed
|
||||
fun OnReconnect() //重新连接中 Reconnecting
|
||||
fun BluetoothSwitchIsTurnedOff() //蓝牙开关被关闭 Bluetooth switch is turned off
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.jstyle.blesdk2301.callback
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/4/10.
|
||||
*/
|
||||
interface DataListener2301 {
|
||||
fun dataCallback(maps: Map<String?, Any?>?)
|
||||
fun dataCallback(value: ByteArray?)
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package com.jstyle.blesdk2301.callback
|
||||
|
||||
import com.jstyle.blesdk2301.model.Device
|
||||
|
||||
interface OnScanResults {
|
||||
fun Success(date: Device?)
|
||||
fun Fail(code: Int)
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.jstyle.blesdk2301.cmdenum
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
class YhDeviceData : Serializable {
|
||||
var dataType = 0 // is index
|
||||
var data: String? = "" //data object
|
||||
var isDataEnd = false //Is it over?
|
||||
fun srgetDeviceData(): String {
|
||||
return if (data == null) "" else data!!
|
||||
}
|
||||
|
||||
fun srsetData(data: String?) {
|
||||
this.data = data
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "YhDeviceData{" +
|
||||
"dataType=" + dataType +
|
||||
", data=" + data +
|
||||
", dataEnd=" + isDataEnd +
|
||||
'}'
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,128 @@
|
||||
package com.jstyle.blesdk2301.constant
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2020/4/9.
|
||||
*/
|
||||
object BleConst {
|
||||
const val GetDeviceTime = "0"
|
||||
const val SetDeviceTime = "1"
|
||||
const val GetPersonalInfo = "2"
|
||||
const val SetPersonalInfo = "3"
|
||||
const val GetDeviceInfo = "4"
|
||||
const val SetDeviceInfo = "5" //设置手环基本参数
|
||||
const val CMD_Set_Mac = "6"
|
||||
const val GetStepGoal = "7"
|
||||
const val SetStepGoal = "8"
|
||||
const val GetDeviceBatteryLevel = "9"
|
||||
const val GetDeviceMacAddress = "10"
|
||||
const val GetDeviceVersion = "11"
|
||||
const val CMD_Reset = "12"
|
||||
const val CMD_MCUReset = "13"
|
||||
const val SetMotorVibrationWithTimes = "14"
|
||||
const val GetDeviceName = "15"
|
||||
const val GetAutomatic = "16"
|
||||
const val SetAutomatic = "17"
|
||||
const val GetAlarmClock = "18"
|
||||
const val SetAlarmClockWithAllClock = "19"
|
||||
const val Notify = "20"
|
||||
const val GetSedentaryReminder = "21"
|
||||
const val SetSedentaryReminder = "22"
|
||||
const val RealTimeStep = "23"
|
||||
const val GetTotalActivityData = "24"
|
||||
const val GetDetailActivityData = "25"
|
||||
const val GetDetailSleepData = "26"
|
||||
const val GetDynamicHR = "27"
|
||||
const val GetStaticHR = "28"
|
||||
const val GetActivityModeData = "29"
|
||||
const val EnterActivityMode = "30"
|
||||
const val DeviceSendDataToAPP = "31"
|
||||
const val BackHomeView = "35"
|
||||
const val GetTempHistoryData = "36"
|
||||
const val ECGDATA = "37"
|
||||
const val EcgppGstatus = "38"
|
||||
const val EcgppG = "39"
|
||||
const val GPSControlCommand = "40"
|
||||
const val Gps = "41" //手环发送给app
|
||||
const val GetHRVData = "42"
|
||||
const val CMD_Set_TemperatureCorrection = "43"
|
||||
const val Weather = "44"
|
||||
const val Braceletdial = "45"
|
||||
const val Braceletdialok = "46"
|
||||
const val SportMode = "47"
|
||||
const val GetSportMode = "48"
|
||||
const val CMD_Set_WorkOutReminder = "49"
|
||||
const val CMD_Get_WorkOutReminder = "50"
|
||||
const val ReadSerialNumber = "51"
|
||||
const val ECG = "53"
|
||||
const val Clear_Bracelet_data = "54"
|
||||
const val Blood_oxygen = "55"
|
||||
const val SocialdistanceGetting = "56"
|
||||
const val SocialdistanceSetting = "57"
|
||||
const val Sos = "58"
|
||||
const val Temperature_history = "59"
|
||||
const val SetDialinterface = "60"
|
||||
const val HeartBeatpacket = "61"
|
||||
const val GetAxillaryTemperatureDataWithMode = "62"
|
||||
const val GetMAC = "63"
|
||||
const val Getppg = "64"
|
||||
const val CloseECGPPG = "65"
|
||||
const val GetEcgPpgStatus = "66"
|
||||
const val ECGdata = "67"
|
||||
const val GetAutomaticSpo2Monitoring = "68"
|
||||
const val SetSpo2 = "69"
|
||||
const val GEtSpo2 = "70"
|
||||
const val DeleteECGdata = "71"
|
||||
const val DeleteHrv = "72"
|
||||
const val MeasurementHrvCallback = "73"
|
||||
const val MeasurementHeartCallback = "74"
|
||||
const val MeasurementOxygenCallback = "75"
|
||||
const val StopMeasurementHrvCallback = "76"
|
||||
const val StopMeasurementHeartCallback = "77"
|
||||
const val StopMeasurementOxygenCallback = "78"
|
||||
const val ExitQRcode = "79"
|
||||
const val EnterQRcode = "80"
|
||||
const val QRcodebandBack = "81"
|
||||
const val SportData = "82"
|
||||
const val Delete_Obtain_The_data_of_manual_blood_oxygen_test = "83"
|
||||
const val Delete_Blood_oxygen = "84"
|
||||
const val Delete_GetTotalActivityData = "85"
|
||||
const val Delete_AlarmClock = "87"
|
||||
const val Delete_ActivityModeData = "88"
|
||||
const val Delete_GetStaticHR = "89"
|
||||
const val Delete_GetDynamicHR = "90"
|
||||
const val deleteGetTemperature_historyDataWithMode = "91"
|
||||
const val deleteGetAxillaryTemperatureDataWithMode = "92"
|
||||
const val deleteGetDetailActivityDataWithMode = "93"
|
||||
const val Delete_GetDetailSleepData = "94"
|
||||
const val Enter_photo_mode = "95"
|
||||
const val openRRInterval = "96"
|
||||
const val closeRRInterval = "97"
|
||||
const val realtimeRRIntervalData = "98"
|
||||
const val realtimePPGData = "99"
|
||||
const val realtimePPIData = "100"
|
||||
const val ppgWithMode = "101"
|
||||
const val ppgStartSucessed = "102"
|
||||
const val ppgStartFailed = "103"
|
||||
const val ppgStop = "104"
|
||||
const val ppgQuit = "105"
|
||||
const val ppgMeasurementProgress = "106"
|
||||
const val ppgResult = "107"
|
||||
const val SetBloodpressure_calibration = "108"
|
||||
const val GetBloodpressure_calibration = "109"
|
||||
const val SetWomenHealth = "110"
|
||||
const val GetWomenHealth = "111"
|
||||
const val SetPregnancyCycle = "112"
|
||||
const val GetPregnancyCycle = "113"
|
||||
const val Getpeisu = "114"
|
||||
const val GetpeisuER = "115"
|
||||
const val CMD_Set_Name = "116"
|
||||
const val CMD_Get_Name = "117"
|
||||
const val Blood_glucose_status = "118"
|
||||
const val Blood_glucose_data = "119"
|
||||
const val FindActivityMode = "120"
|
||||
const val FindMobilePhoneMode = "FindMobilePhoneMode"
|
||||
const val RejectTelMode = "RejectTelMode"
|
||||
const val TelMode = "TelMode"
|
||||
const val ECGResult = "ECGResult"
|
||||
const val ENTERECG = "ENTERECG"
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.jstyle.blesdk2301.constant
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/1/17.
|
||||
*/
|
||||
object DeviceConst {
|
||||
const val CMD_SET_TIME = 0x01.toByte()
|
||||
const val CMD_GET_TIME = 0x41.toByte()
|
||||
const val CMD_Set_UseInfo = 0x02.toByte()
|
||||
const val CMD_GET_USERINFO = 0x42.toByte()
|
||||
const val CMD_Set_DeviceID = 0x05.toByte()
|
||||
const val CMD_Enable_Activity = 0x09.toByte() //
|
||||
const val CMD_Get_BatteryLevel = 0x13.toByte() //
|
||||
const val CMD_Get_Address = 0x22.toByte()
|
||||
const val CMD_Get_Version = 0x27.toByte()
|
||||
const val CMD_Reset = 0x12.toByte()
|
||||
const val CMD_Mcu_Reset = 0x2e.toByte()
|
||||
const val CMD_Set_Auto = 0x2a.toByte()
|
||||
const val CMD_Get_Auto = 0x2b.toByte()
|
||||
const val CMD_Get_TotalData = 0x51.toByte() //
|
||||
const val CMD_Get_DetailData = 0x52.toByte()
|
||||
const val CMD_Get_SleepData = 0x53.toByte()
|
||||
const val CMD_Get_HeartData = 0x54.toByte()
|
||||
const val CMD_Get_OnceHeartData = 0x55.toByte()
|
||||
const val CMD_Get_HrvTestData = 0x56.toByte() //
|
||||
const val ReadTempHisrory = 0x62.toByte()
|
||||
const val MeasurementWithType = 0x28.toByte()
|
||||
const val Oxygen_data = 0x66.toByte()
|
||||
const val CMD_Start_EXERCISE = 0x19.toByte()
|
||||
const val CMD_heart_package = 0x17.toByte()
|
||||
const val CMD_HeartPackageFromDevice = 0x18.toByte() //
|
||||
const val CMD_Set_Name = 0x3d.toByte()
|
||||
const val CMD_Get_Name = 0x3e.toByte()
|
||||
const val CMD_Get_SPORTData = 0x5C.toByte()
|
||||
const val CMD_Get_Bloodsugar = 0x78.toByte()
|
||||
const val Bloodsugar_data = 0x3a.toByte() //血糖数据
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
enum class AutoMode {
|
||||
AutoHeartRate, AutoSpo2, AutoTemp, AutoHrv
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
enum class AutoTestMode {
|
||||
AutoHeartRate, AutoSpo2
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/1/16.
|
||||
*/
|
||||
class Clock : SendData(), Serializable {
|
||||
var number = 0
|
||||
var type = 0
|
||||
var hour = 0
|
||||
var minute = 0
|
||||
var week: Byte = 0
|
||||
var content: String? = null
|
||||
var isEnable = false
|
||||
fun srgetWeek(): Int {
|
||||
return week.toInt()
|
||||
}
|
||||
|
||||
fun srsetWeek(week: Byte) {
|
||||
this.week = week
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Clock{" +
|
||||
"number=" + number +
|
||||
", type=" + type +
|
||||
", hour=" + hour +
|
||||
", minute=" + minute +
|
||||
", week=" + week +
|
||||
", content='" + content + '\'' +
|
||||
", enable=" + isEnable +
|
||||
'}'
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import java.io.Serializable
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor
|
||||
|
||||
class Device : Serializable {
|
||||
var name: String? = null //设备名字
|
||||
var mac: String? = null //设备的mac
|
||||
var productID = 0 //产品id,预留
|
||||
var bluetoothDevice: BluetoothDevice? = null //蓝牙
|
||||
var isIsconted = false //蓝牙是否连接
|
||||
var isPaired = false //是否是配对设备
|
||||
var isIsdfu = false //是否直接升级
|
||||
var riss = 100
|
||||
var time: ScheduledThreadPoolExecutor? = null //每一个设备轮询器
|
||||
fun srsetIsdfu(isdfu: Boolean) {
|
||||
isIsdfu = isdfu
|
||||
}
|
||||
|
||||
fun srsetIsconted(isconted: Boolean) {
|
||||
isIsconted = isconted
|
||||
}
|
||||
|
||||
fun srgetName(): String {
|
||||
return if (name == null) "" else name!!
|
||||
}
|
||||
|
||||
fun srsetName(name: String?) {
|
||||
this.name = name
|
||||
}
|
||||
|
||||
fun srgetMac(): String {
|
||||
return if (mac == null) "" else mac!!
|
||||
}
|
||||
|
||||
fun srsetMac(mac: String?) {
|
||||
this.mac = mac
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Device{" +
|
||||
"name='" + name + '\'' +
|
||||
", mac='" + mac + '\'' +
|
||||
", productID=" + productID +
|
||||
", getBluetoothDevice=" + bluetoothDevice +
|
||||
", isconted=" + isIsconted +
|
||||
'}'
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/4/28.
|
||||
*/
|
||||
class DeviceBean {
|
||||
var dataList: List<Map<String, String>>? = null
|
||||
var isFinish = false
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/4/9.
|
||||
*/
|
||||
class DeviceName : SendData() {
|
||||
var name: String? = null
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/8/2.
|
||||
*/
|
||||
class ExerciseMode : SendData() {
|
||||
var exerciseMode = 0
|
||||
var enableStatus = 0
|
||||
fun getExerciseMode(position: Int): Int {
|
||||
return modes[position]
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val Status_START = 1
|
||||
const val Status_PAUSE = 2
|
||||
const val Status_CONTUINE = 3
|
||||
const val Status_FINISH = 4
|
||||
const val Mode_RUN = 0
|
||||
const val Mode_CYCLING = 1
|
||||
const val Mode_BADMINTON = 2
|
||||
const val Mode_FOOTBALL = 3
|
||||
const val Mode_TENNIS = 4
|
||||
const val Mode_YOGA = 5
|
||||
const val Mode_BREATH = 6
|
||||
const val Mode_DANCE = 7
|
||||
const val Mode_BASKETBALL = 8
|
||||
const val Mode_Walk = 9
|
||||
const val Mode_workout = 10
|
||||
const val Mode_Cricket = 11
|
||||
const val Mode_Hiking = 12
|
||||
const val Mode_Aerobics = 13
|
||||
const val Mode_PingPong = 14
|
||||
const val Mode_RopeJump = 15
|
||||
const val Mode_Situps = 16
|
||||
const val Volleyball = 17
|
||||
var modes = intArrayOf(
|
||||
Mode_RUN, Mode_CYCLING, Mode_BADMINTON, Mode_FOOTBALL,
|
||||
Mode_TENNIS, Mode_YOGA, Mode_BREATH, Mode_DANCE, Mode_BASKETBALL, Mode_Walk, Mode_workout, Mode_Cricket, Mode_Hiking, Mode_Aerobics, Mode_PingPong, Mode_RopeJump, Mode_Situps, Volleyball
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
import android.bluetooth.BluetoothDevice
|
||||
|
||||
class ExtendedBluetoothDevice {
|
||||
val device: BluetoothDevice
|
||||
|
||||
/** The name is not parsed by some Android devices, f.e. Sony Xperia Z1 with Android 4.3 (C6903). It needs to be parsed manually. */
|
||||
var name: String
|
||||
var rssi: Int
|
||||
|
||||
constructor(device: BluetoothDevice, name: String, rssi: Int) {
|
||||
this.device = device
|
||||
this.name = name
|
||||
this.rssi = rssi
|
||||
}
|
||||
|
||||
constructor(device: BluetoothDevice) {
|
||||
this.device = device
|
||||
name = device.name
|
||||
rssi = NO_RSSI
|
||||
}
|
||||
|
||||
fun matches(mdevice: BluetoothDevice): Boolean {
|
||||
return device.address == mdevice.address
|
||||
}
|
||||
|
||||
companion object {
|
||||
/* package */
|
||||
const val NO_RSSI = -1000
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/1/16.
|
||||
*/
|
||||
class MyAutomaticHRMonitoring : SendData() {
|
||||
var open = 0 //1 开启整个时间段都测量 2时间段内间隔测量 0关闭
|
||||
|
||||
// 1. Enable measurement throughout the entire time period 2. Measure intervals within the time period 0. Close
|
||||
var startHour = 0 //开始小时 Starting hours
|
||||
var startMinute = 0 //开始分钟 Start minute
|
||||
var endHour = 0 //结束小时 End Hour
|
||||
var endMinute = 0 //结束分钟 End minute
|
||||
var week = 0 //星期一到星期日 开启选择 Monday to Sunday open selection
|
||||
var time = 0 //多少时间测试一次,单位是分钟。 How many times does it take to test, in minutes.
|
||||
override fun toString(): String {
|
||||
return "MyAutomaticHRMonitoring{" +
|
||||
"open=" + open +
|
||||
", startHour=" + startHour +
|
||||
", startMinute=" + startMinute +
|
||||
", endHour=" + endHour +
|
||||
", endMinute=" + endMinute +
|
||||
", week=" + week +
|
||||
", time=" + time +
|
||||
'}'
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
import java.util.Calendar
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/1/16.
|
||||
*/
|
||||
class MyDeviceTime : SendData() {
|
||||
var year: Int
|
||||
var month: Int
|
||||
var day: Int
|
||||
var hour: Int
|
||||
var minute: Int
|
||||
var second: Int
|
||||
|
||||
init {
|
||||
val calendar = Calendar.getInstance()
|
||||
year = calendar[Calendar.YEAR]
|
||||
month = calendar[Calendar.MONTH] + 1
|
||||
day = calendar[Calendar.DAY_OF_MONTH]
|
||||
hour = calendar[Calendar.HOUR_OF_DAY]
|
||||
minute = calendar[Calendar.MINUTE]
|
||||
second = calendar[Calendar.SECOND]
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "MyDeviceTime{" +
|
||||
"year=" + year +
|
||||
", month=" + month +
|
||||
", day=" + day +
|
||||
", hour=" + hour +
|
||||
", minute=" + minute +
|
||||
", second=" + second +
|
||||
'}'
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/1/16.
|
||||
*/
|
||||
class MyPersonalInfo : SendData() {
|
||||
var sex = 0 //1 male,0female
|
||||
var age = 0
|
||||
var height = 0
|
||||
var weight = 0
|
||||
var stepLength = 70
|
||||
override fun toString(): String {
|
||||
return "MyPersonalInfo{" +
|
||||
"sex=" + sex +
|
||||
", age=" + age +
|
||||
", height=" + height +
|
||||
", weight=" + weight +
|
||||
", stepLength=" + stepLength +
|
||||
'}'
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/1/16.
|
||||
*/
|
||||
class MySedentaryReminder : SendData() {
|
||||
var startHour = 0
|
||||
var startMinute = 0
|
||||
var endHour = 0
|
||||
var endMinute = 0
|
||||
var week = 0
|
||||
var intervalTime = 0
|
||||
var leastStep = 0
|
||||
var isEnable = false
|
||||
override fun toString(): String {
|
||||
return "MySedentaryReminder{" +
|
||||
"startHour=" + startHour +
|
||||
", startMinute=" + startMinute +
|
||||
", endHour=" + endHour +
|
||||
", endMinute=" + endMinute +
|
||||
", week=" + week +
|
||||
", intervalTime=" + intervalTime +
|
||||
", leastStep=" + leastStep +
|
||||
", enable=" + isEnable +
|
||||
'}'
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/1/16.
|
||||
*/
|
||||
class Notifier : SendData() {
|
||||
var type = 0
|
||||
var info = ""
|
||||
var title = ""
|
||||
override fun toString(): String {
|
||||
return "Notifier{" +
|
||||
"type=" + type +
|
||||
", info='" + info + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
'}'
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val Data_Tel = 0
|
||||
const val Data_Sms = 1
|
||||
const val Data_WeChat = 2
|
||||
const val Data_Facebook = 3
|
||||
const val Data_Instagram = 4
|
||||
const val Data_Skype = 5
|
||||
const val Data_Telegram = 6
|
||||
const val Data_Twitter = 7
|
||||
const val Data_Vkclient = 8
|
||||
const val Data_WhatApp = 9
|
||||
const val Data_QQ = 10
|
||||
const val Data_IN = 11
|
||||
const val Data_Stop_Tel = 0xff
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/4/8.
|
||||
*/
|
||||
open class SendData
|
||||
@ -0,0 +1,16 @@
|
||||
package com.jstyle.blesdk2301.model
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/1/16.
|
||||
*/
|
||||
class SportPeriod : SendData() {
|
||||
var startHour = 0
|
||||
var startMinute = 0
|
||||
var endHour = 0
|
||||
var endMinute = 0
|
||||
var week = 0
|
||||
var days = 0
|
||||
var intervalTime = 0
|
||||
var leastStep = 0
|
||||
var isEnable = false
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue