MTWristbandKit 说明文档
本套SDK仅支持Minew公司出品的蓝牙手环设备。通过SDK可以帮助开发者处理手机和手环之间的一切工作,包括:扫描设备,广播数据、连接设备,向设备写入数据,从设备接收数据等。
前期工作
整体框架:MinewWristbandManager
为设备管理类,在APP运行时始终是单例。WristbandModule
是设备实例类,此套件会为每一个设备生成一个实例,在扫描和连接后都会使用,内部包含设备广播数据,该数据会随着设备不停广播而更新
MinewWristbandManager
:设备管理类,可以扫描周围的手环设备,并且可以连接它们,校验它们等。
WristbandModule
:扫描时获取到的设备实例,对应手环设备,在扫描和连接后都会使用
StaticInfoFrame
:静态信息帧
ConfigFrame
:配置帧
CombinedFrame
:组合帧
TemperatureHistory
:温度历史数据实体类
WristbandHistory
:接触历史数据实体类
手环并不是会一直在广播状态。内部置有加速度传感器,有移动才会广播一段时间,期间可以通过sdk去扫描设备。需要注意的是,手环在广播阶段不能立即连接,需要判断是已经唤醒后才能去连接。
导入到工程
开发环境
sdk最低支持Android 5.0,对应API Level为21。在module的
build.gradle
中设置minSdkVersion
为21或21以上android { defaultConfig { applicationId "com.xxx.xxx" minSdkVersion 21 } }
1
2
3
4
5
6
7将
MinewWristbandKit.jar
添加到module的libs文件夹下,并在该module
的build.gradle
中添加如下语句(直接添加依赖):implementation files('libs/MinewWristbandKit.jar') implementation 'org.lucee:bcprov-jdk15on:1.52.0'
1
2或者右键该jar文件,选择
Add as Library
,添加到当前module在
AndroidManifest.xml
需要以下权限,如果targetSdkVersion
大于23,则需要做权限管理以获取权限<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
1
2
3
4
使用
sdk分为扫描、唤醒和连接三个阶段
扫描
开始扫描
Android6.0系统以上,进行BLE扫描,需要申请到定位权限后才可以进行,并且需要打开定位开关!
MinewWristbandManager manager = MinewWristbandManager.getInstance(getApplicationContext());
manager.startScan(new OnScanWristbandResultListener() {
@Override
public void onScanWristbandResult(ArrayList<WristbandModule> result) {
//scan result
}
});
2
3
4
5
6
7
sdk内部并没有对蓝牙扫描时长进行处理,但是扫描是耗电操作,一般90秒就可以停止扫描了,如果还需要继续扫描,可以提供刷新等操作以便继续扫描。
取出数据
在扫描期间,sdk获取到的广播数据存储在广播帧里,部分数据会在连接后需要用到。当前需要用到的帧类型是:StaticInfoFrame
和ConfigFrame
。
StaticInfoFrame:
名称 | 类型 | 描述 |
---|---|---|
power | int | 电量百分比 |
firmwareVersion | String | 固件版本 |
ConfigFrame:
名称 | 类型 | 描述 |
---|---|---|
openStorage | boolean | 是否已经打开存储开关,false为关,否则已经打开 |
recordNum | int | 历史记录条数 |
versionCode | int | 固件版本号。 当扫描到ConfigFrame后,可能的值为2或3。 具体将在表格下方单独说明 |
hasTemperatureSensor | boolean | 手环是否带有温度传感器,true表示有温度传感器,否则没有 |
temperatureRecordNum | int | 温度告警记录条数,仅当versionCode 为3且hasTemperatureSensor 为true,该值才有效 |
说明:在ConfigFrame中,新增versionCode
属性,表示固件版本号,当扫描到ConfigFrame后,可能的值为2或3。
- 如果为2,表示当前手环仅有:关机、存储开关关闭或打开、固件升级功能;
- 如果为3,进一步细分是否有温度传感器(根据hasTemperatureSensor属性来判断)
- 无温度传感器:在为2的基础功能上,增加恢复出厂设置功能
- 有温度传感器:拥有以上所有功能,再添加:告警距离读写、报警温度读写、测温间隔时间读写等功能
CombinedFrame
名称 | 类型 | 描述 |
---|---|---|
temperature | float | 温度,当前温度,按下按键后会广播当前温度 |
要想取出内部数据,首先需要先获得对应的广播帧对象,在获取固件版本等。注意,由于是存在广播帧对象中,而在扫描时,不能保证立即就能接收到指定广播帧,所以需要做非空判断!
StaticInfoFrame staticInfoFrame = (StaticInfoFrame) getMinewFrame(ScanRecordFrameType.Static_Info_Frame);
if (staticInfoFrame != null) {
//获取固件版本
String version = staticInfoFrame.getFirmwareVersion();
//获取电量百分比
int power = staticInfoFrame.getPower();
}
ConfigFrame configFrame = (ConfigFrame) getMinewFrame(ScanRecordFrameType.Config_Frame);
if (configFrame != null) {
//历史记录条数
int recordNum = configFrame.getRecordNum();
//是否已经开启存储开关
boolean isOpenStorage = configFrame.isOpenStorage();
//温度告警历史记录条数
int tempRecordNum = configFrame.getTemperatureRecordNum();
//是否带有温度传感器
boolean hasTemperatureSensor = configFrame.hasTemperatureSensor()();
//版本号
int versionCode = configFrame.getVersionCode();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sdk提供了更简洁的方式来获取设备信息,但是在未接收到广播帧时,获取到的值为"Unknown"或"-1"或“false”,具体是什么值,取决于它们的类型。
//获取固件版本
String version = wristbandModule.getFirmwareVersion();
//获取电量百分比
int power = wristbandModule.getPower();
//获取历史记录条数
int recordNum = wristbandModule.getTotalRecord();
//是否已经开启存储开关
boolean isOpenStorage = wristbandModule.isOpenStorage();
//获取温度告警历史记录条数
int tempRecordNum = wristbandModule.getTotalTemperatureRecord();
//获取设备的实时温度
float temperature = wristbandModule.getTemperature();
//手环是否带有温度传感器
boolean hasTemperaturSensor = wristbandModule.hasTemperatureSensor();
//设备版本号。这个值的作用请看扫描——取出数据——ConfigFrame部分
int versionCode = wristbandModule.getFirmwareVersionCode();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
唤醒
设备在扫描到手环设备后,需要去唤醒后才能去连接。唤醒后,一分钟以内,可以去连接;过了一分钟,需要重新唤醒。可通过WristbandModule.isAwakened()
来判断指定手环是否已经被唤醒。
//当前手机系统是否支持唤醒手环,如果为false,就不去唤醒
boolean isSupport = manager.isSupportAdvertisement();
//activateState为true表示手环已唤醒,否则为未唤醒
boolean activateState = wristbandModule.isAwakened();
if (isSupport && !activateState) {
//手机支持唤醒手环,且当前手环未被唤醒,就去唤醒手环
manager.startAwaken(macAddress);
}
2
3
4
5
6
7
8
需要注意:
- 在被唤醒前,不能停止扫描。否则将无法获取到唤醒状态!
- 在激活-未激活状态转变。唤醒后如果1分钟以内没有去连接导致变为未激活状态,那么只能通过重新启动扫描。
SDK通过startAwaken(String macAddress)
来唤醒指定设备,现在增加主动停止唤醒设备的机制,这与以前不同,以前是直到唤醒成功后才会自动停止,现在是在开始唤醒后,设置唤醒时长,在唤醒时长过后就会自动停止唤醒,且停止唤醒不会发出通知。
SDK增加了设置唤醒时长的方法:setAwakenTime(long timeMillis)
,默认是10秒,可设置范围是5秒到15秒。由于SDK缺少在唤醒时长范围内主动停止唤醒的功能,所以APP需要自己在发现设备已经被唤醒的情况下停止唤醒,即stopAwaken()
。
连接
连接前一般需要先停止扫描
if (!device.isAwakened()) {
//设备未唤醒不可连接
Toast.makeText(this,"not_activate",Toast.LENGTH_SHORT).show();
return
}
//停止扫描
manager.stopScan();
//连接
manager.connect(context, module);
//断开连接
manager.disConnect(macAddress);
2
3
4
5
6
7
8
9
10
11
sdk中会对连接过程和设备断开连接等方式会有状态监听
manager.setOnConnStateListener(new OnConnStateListener() {
/*
* 连接过程中的状态回调
*
* @param macAddress 设备mac
* @param connectionState 状态
*/
@Override
public void onUpdateConnState(String address, ConnectionState connectionState) {
switch (connectionState) {
case Disconnect:
//连接失败或者设备断开连接会回调,主动断开不会回调该状态
break;
case Power_Off:
//关机,设备发送关机指令,成功后会回调该状态,不会回调Disconnect状态
break;
case Inactivated:
//未被唤醒状态。如上文所示,如果未检测设备已经唤醒就去连接,会回调该状态
break;
case Verify_Password:
//密码验证,回调该状态后,设备需要写入密码,通过sendPassword写入
manager.sendPassword(address, "minew123")
break;
case PasswordError:
//密码错误,设备会断开连接,并且不会回调Disconnect状态
break;
case Firmware_Upgrade_Successfully:
//固件升级成功,不会回调Disconnect状态
break;
case Connect_Complete:
//连接完成,此时设备可进行读写操作
break;
case Reset_Device:
//恢复出厂设置,成功后会回调该状态,不会回调Disconnect状态
break;
default:
break;
}
}
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
在连接过程中,sdk会返回多个连接状态到app中,app需要做好处理
- ConnectionState.Inactivated: 如果在连接前后去判断手环是否已经激活,一般不会回调该状态。但是手环激活时间只有一分钟,一分钟后如果才连接,这时候sdk虽然返回是已经激活状态,但实际上激活状态不会再更新。需要重新开始扫描才会变化;
- ConnectionState.Verify_Password: 手环连接需要验证密码,一旦回调该状态,那么就需要通过
manager.sendPassword(address, "minew123")
来写入密码。注意,密码长度为8位; - ConnectionState.PasswordError: 密码错误,手环会断开连接,并且不会返回ConnectionState.Disconnect状态;
- ConnectionState.Connect_Complete: 返回这个状态,说明手环已经连接成功,可以进行读写操作,比如读取历史数据等;
- ConnectionState.Power_Off: 关机。通过关机指令可使手环关机,并回调该状态。另外,连接也会断开,且不会回调ConnectionState.Disconnect状态;
- ConnectionState.Firmware_Upgrade_Successfully: 进行固件升级,sdk会给出另一个回调方法,并且升级成功后会回调该状态,连接会断开,且不会回调ConnectionState.Disconnect状态;
- ConnectionState.Disconnect: 连接失败或者设备断开连接会回调,主动断开不会回调该状态。即调用
manager.disConnect(macAddress);
不会回调该状态。注意:升级失败是会回调该状态的; - ConnectionState.Reset_Device: 恢复出厂设置成功,并回调该状态。另外,连接也会断开,且不会回调ConnectionState.Disconnect状态。
API汇总
连接前
startScan(): 开始扫描。每次开始扫描都会清除上一次扫描的所有结果
stopScan(): 停止扫描
setAwakenTime(long timeMillis): 设置唤醒时长,默认是10秒,在
startAwaken(String macAddress)
调用前设置才会生效getAwakenTime(): 获取此前设置的唤醒时长
startAwaken(String macAddress): 开始唤醒设备
stopAwaken(): 停止去唤醒
isAwakened(): 是否在唤醒设备
connect(Context context, WristbandModule module): 连接设备
disConnect(String macAddress): 断开连接
setOnConnStateListener(OnConnStateListener listener): 设置连接状态,这是必须调用的
sendPassword(String macAddress, String password): 写入密码
//macAddress为手环mac,password为要写入的密码 manager.sendPassword(macAddress, password);
1
2
连接后
注意:连接后,在连接期间,对于同一设备,不管是读取还是写入,都需要等到上一操作完成,才能继续下一操作,否则程序会出现问题。 比如手环有20000条历史记录,读取需要几分钟时间,这时候又去关闭存储开关,就会导致程序出现问题,可能是数据错乱,或者更严重点程序闪退。
另外还请注意:读取历史记录,在通信过程中可能会丢包!如果对历史数据较为敏感,那么可以在读取到历史数据后对其条数进行判断,如果与预期结果条数不一致,可重新读取。
连接后可用方法如下:
读取历史数据;
读取历史数据是通过索引来读取的,索引从0开始,如读取前七条,则传入0和6。需要注意的是每次读取不能超过7条。如果传入0和25,默认读取0到6,即读取前7条。
//分别传入手环对象,开始索引和结束索引以及监听器 manager.readHistoryData(module, 0, 6, new OnReadHistoryDataListener<WristbandHistory>() { /** * mac为设备mac * data为这次读取操作得到的历史数据 */ @Override public void receiverDataCompletely(String macAddress, ArrayList<WristbandHistory> list) { } });
1
2
3
4
5
6
7
8
9
10
11
12
13读取全部历史数据;
manager.readAllHistoryData(module, new OnReadAllHistoryDataListener<WristbandHistory>() { /** * mac为设备mac * process为读取全部历史数据的进度 */ @Override public void receiverDataProgress(String macAddress, float process) { } /** * mac为设备mac * data为这次读取操作得到的历史数据 */ @Override public void receiverDataCompletely(String macAddress, ArrayList<WristbandHistory> allData) { } });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22读取温度告警历史数据;
读取温度告警历史数据是通过索引来读取的,索引从0开始,如读取前七条,则传入0和6。需要注意的是每次读取不能超过14条。如果传入0和25,默认读取0到13,即读取前14条。
//分别传入手环对象,开始索引和结束索引以及监听器 manager.readTemperatureHistory(module, 0, 6, new OnReadHistoryDataListener<TemperatureHistory>() { /** * mac为设备mac * data为这次读取操作得到的历史数据 */ @Override public void receiverDataCompletely(String macAddress, ArrayList<TemperatureHistory> allData) { } });
1
2
3
4
5
6
7
8
9
10
11
12
13读取全部温度告警历史数据;
manager.readAllTemperatureHistory( module, new OnReadAllHistoryDataListener<TemperatureHistory>() { @Override public void receiverDataProgress(String macAddress, float process) { } @Override public void receiverDataCompletely(String macAddress, ArrayList<TemperatureHistory> allData) { } });
1
2
3
4
5
6
7
8
9
10
11
12
13
14存储开关设置;
/** * 存储开关设置 * * @param macAddress 设备mac * @param isOpen 是否要打开 * @param listener 监听器 */ manager.storageSwitch(mac, true, new OnChangeListener() { @Override public void onModifyResult(boolean b) { } });
1
2
3
4
5
6
7
8
9
10
11
12
13关机;
/** * 关机 * * @param macAddress 设备mac */ manager.powerOff(mac, new OnChangeListener() { @Override public void onModifyResult(boolean b) { } });
1
2
3
4
5
6
7
8
9
10
11固件升级;
/** * 固件升级 * * @param macAddress 设备mac * @param upgradeData 升级包数据 * @param listener 监听器 */ manager.firmwareUpgrade(mac, upgradeData, new OnFirmwareUpgradeListener() { /** * 升级包数据写入进度 */ @Override public void updateProgress(int progress) { } /** * 升级成功会触发OnConnStateListener回调,返回 * ConnectionState.Firmware_Upgrade_Successfully状态 */ @Override public void upgradeSuccess() { } /** * 升级失败。升级失败会断开连接,会触发OnConnStateListener回调,返回 * ConnectionState.Disconnect状态 */ @Override public void upgradeFailed() { } });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36恢复出厂设置。在 ConfigFrame.versionCode 为3的情况下可使用;
manager.resetDevice(module, new OnChangeListener() { @Override public void onModifyResult(boolean value) { } });
1
2
3
4
5
6读取温度测量间隔。在 ConfigFrame.versionCode 为3且WristbandModule.hasTemperatureSensor() 返回true的情况下可使用。读取到的测量间隔范围在0到7200秒,注意,单位是秒;
manager.readTempeMeasureInterval(module, new OnReadValueListener<Integer>() { @Override public void onReadValue(Integer value) { } });
1
2
3
4
5
6设置温度测量间隔。在 ConfigFrame.versionCode 为3且WristbandModule.hasTemperatureSensor() 返回true的情况下可使用。手环支持的测量间隔范围在0到7200秒,注意,单位是秒;
manager.setTempMeasureInterval(module, 8, new OnChangeListener() { @Override public void onModifyResult(boolean result) { } });
1
2
3
4
5
6读取温度告警值。在 ConfigFrame.versionCode 为3且WristbandModule.hasTemperatureSensor() 返回true的情况下可使用。读取到的值范围在设置范围应在
30.0℃
~42.0℃
之间;manager.readTempAlarmValue(module, new OnReadValueListener<Float>() { @Override public void onReadValue(Float value) { } });
1
2
3
4
5
6设置温度告警值。在 ConfigFrame.versionCode 为3且WristbandModule.hasTemperatureSensor() 返回true的情况下可使用。写入的值范围在设置范围应在
30.0℃
~42.0℃
之间;manager.setTempAlarmValue(module, 20, new OnChangeListener() { @Override public void onModifyResult(boolean result) { } });
1
2
3
4
5
6读取告警距离档位。在 WristbandModule.getFirmwareVersionCode() 返回3的情况下可使用。读取到的值为0到4;
manager.readAlarmGear(module, new OnReadValueListener<Integer>() { @Override public void onReadValue(Integer value) { } });
1
2
3
4
5
6写入告警距离档位。在 WristbandModule.getFirmwareVersionCode() 返回3的情况下可使用。写入的值为0到4。
manager.setAlarmGear(module, 2, new OnChangeListener() { @Override public void onModifyResult(boolean result) { } });
1
2
3
4
5
6读取温度报警振动值。写入的值范围在设置范围应在
30.0℃
~42.0℃
之间。需满足以下条件才可使用:- 在 WristbandModule.getFirmwareVersionCode() 返回3
- WristbandModule.hasTemperatureSensor() 返回true
- 固件版本是3.2.5及以上。
manager.readAlarmVibrationValue(module, new OnReadValueListener<Integer>() { @Override public void onReadValue(Integer value) { } });
1
2
3
4
5
6设置温度报警振动值,写入的值范围在设置范围应在
30.0℃
~42.0℃
之间。需满足以下条件才可使用:- 在 WristbandModule.getFirmwareVersionCode() 返回3
- WristbandModule.hasTemperatureSensor() 返回true
- 固件版本是3.2.5及以上。
manager.setAlarmVibrationValue(module, 33F, new OnChangeListener() { @Override public void onModifyResult(boolean result) { } });
1
2
3
4
5
6读取温度报警振动开关值,需满足以下条件才可使用:
- 在 WristbandModule.getFirmwareVersionCode() 返回3
- WristbandModule.hasTemperatureSensor() 返回true
- 固件版本是3.2.5及以上。
manager.readVibrationSwitch(module, new OnReadValueListener<Boolean>() { @Override public void onReadValue(Boolean value) { } });
1
2
3
4
5
6设置温度报警振动开关值。需满足以下条件才可使用:
- 在 WristbandModule.getFirmwareVersionCode() 返回3
- WristbandModule.hasTemperatureSensor() 返回true
- 固件版本是3.2.5及以上。
manager.setVibrationSwitch(module, true, new OnChangeListener() { @Override public void onModifyResult(boolean result) { } });
1
2
3
4
5
6读取近距离报警震动开关值。需满足以下条件才可使用:
- 在 WristbandModule.getFirmwareVersionCode() 返回2或3
- 固件版本是3.2.5及以上。
manager.readCrAlarmVibrationSwitch(module, new OnReadValueListener<Boolean>() { @Override public void onReadValue(Boolean value) { } });
1
2
3
4
5
6设置近距离报警震动开关值。需满足以下条件才可使用:
- 在 WristbandModule.getFirmwareVersionCode() 返回2或3
- 固件版本是3.2.5及以上。
manager.setCrAlarmVibrationSwitch(module, true, new OnChangeListener() { @Override public void onModifyResult(boolean result) { } });
1
2
3
4
5
6
附表
在这里对一些类的属性进行说明。
TemperatureHistory(温度历史数据实体类):
名称 | 类型 | 描述 |
---|---|---|
macAddress | String | 当前设备mac |
time | long | 时间戳,表示记录时间 |
temperature | float | 温度 |
WristbandHistory(接触历史数据实体类):
名称 | 类型 | 描述 |
---|---|---|
macAddress | String | 设备mac |
time | long | 时间戳,表示记录时间 |
rssi | float | 信号强度 |
更新历史
2020/07/06
- 增加sdk支持系统版本说明;
- 增加读取历史数据中,单次读取长度不能超过7,索引从0开始。
2020/08/11
- 修改sdk支持最低版本为21,唤醒手环增加
isSupportAdvertisement()
方法判断系统是否支持唤醒手环; - 增加
resetDevice()
、readTempeMeasureInterval()
、setTempMeasureInterval()
、readTempAlarmValue()
、setTempAlarmValue()
、readAlarmGear()
、setAlarmGear()
等方法。由于sdk兼容以前的手环设备,所以在调用这些方法时需要做些判断。具体查看本文档。
2020/08/26
- 修改设置档位为0到4;
- 增加如下方法:
- setAwakenTime()
- getAwakenTime()
2020/09/01
修改单次最多读取温度历史数据条数从7改为14,影响到方法为:readTemperatureHistory()
。
2020/09/16
设置和读取温度告警值范围修改为30.0℃
~ 42.0℃
;
2020/10/10
- 新增对TemperatureHistory和WristbandHistory属性的说明;
- 在读取历史数据过程中(接触数据和温度数据),可能会产生丢包。如果对历史数据较为敏感,那么可以在读取到历史数据后对其条数进行判断,如果与预期结果条数不一致,可重新读取。
2021/04/02
增加读取和写入数据功能,这些功能位于连接后功能列表的第15至第20条。另外,请务必注意,部分新功能是在新固件上增加,在使用这些功能之前,需要满足固件和硬件的基础上使用。 具体看demo。
另外,在连接后的功能列表,补充了这些功能可以在哪些版本下可用的条件判断