# MinewKit document
This SDK only supports the Bluetooth sensor devices from Minew. The SDK helps developers to handle everything between the phone and the Devices, including: scanning the device, broadcasting data, connecting to the device, writing data to the device, receiving data from the device, etc.
# Preliminary work
Overall framework:MBT02ConnectableAssetTagBleManager
is the device management class, which is always a single instance when the app is running. MBT02ConnectableAssetTagEntity
is the device instance class, this suite generates an instance for each device, which is used after scanning and connecting, and contains device broadcast data inside, which will be updated during scanning as the device keeps broadcasting.
MBT02ConnectableAssetTagBleManager
:Device management class that scans the surrounding Tags devices and can connect them, verify them, etc.;
MBT02ConnectableAssetTagEntity
:Example of an Tag device acquired during scanning, inherited fromBaseBleDeviceEntity
;
# Import to project
Development Environment
The minimum sdk support is Android 5.0, corresponding to API Level 21. set
minSdkVersion
to 21 or above inbuild.gradle
of the module.android { defaultConfig { applicationId "com.xxx.xxx" minSdkVersion 21 } }
1
2
3
4
5
6
7Add jar to the module's libs folder and add the following statement to the
build.gradle
of themodule
(add the dependency directly)implementation files('libs/base_ble_library.jar') implementation files('libs/minew_mbt02_connectable_asset_tag.jar') implementation 'org.lucee:bcprov-jdk15on:1.52.0'
1
2
3Or right-click the jar file and select
Add as Library
to add it to the current module.Add the configuration to the.so library file in the App directory build.gradle
android { defaultConfig { ndk { abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64' } } sourceSets { main { jniLibs.srcDirs = ['libs'] } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14The following permissions are required in
AndroidManifest.xml
, and iftargetSdkVersion
is greater than 23, you need to do permission management to get the permissions.<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" tools:node="replace" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" tools:node="replace" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/> <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED"/> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <!-- Required to maintain app compatibility. --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Use
The sdk is divided into three phases: scanning, connecting, and reading and writing.
# Scanning section
# Start scannin
For Android 6.0 and above systems, when performing BLE scanning, you need to apply for Bluetooth permission and turn on the positioning switch before proceeding.
To enable Bluetooth scanning, you need to turn on Bluetooth first. If you scan without turning on Bluetooth, the APP will crash. You can use BLETool.checkBluetooth(this) to determine whether Bluetooth is turned on. If it is not turned on, you can turn on Bluetooth first.
val mBleManager = MBT02ConnectableAssetTagBleManager.getInstance()
when (BLETool.checkBluetooth(this@MainActivity)) {
BluetoothState.BLE_NOT_SUPPORT -> {
Toast.makeText(this@MainActivity, "Not Support BLE", Toast.LENGTH_SHORT).show()
}
BluetoothState.BLUETOOTH_OFF -> {
val enableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
launcherActivityResultForBle.launch(enableIntent)
}
BluetoothState.BLUETOOTH_ON -> {
manager.startScan(App.getApplication().mApplication, 5*60*1000,object : OnScanDevicesResultListener<MBT02ConnectableAssetTagEntity> {
override fun onScanResult(scanList: MutableList<MBT02ConnectableAssetTagEntity>?) {
}
override fun onStopScan(scanList: MutableList<MBT02ConnectableAssetTagEntity>?) {
}
})
}
else -> {
}
}
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
The SDK does not process the Bluetooth scanning duration internally, but scanning is a power-consuming operation. The SDK stops scanning after 5 minutes by default. If you still need to continue scanning, you can provide a timer or refresh operation to continue calling the scanning method to continue scanning the device.。
# Retrieve data
During the scan, the APP is able to get a part of the current data of the device through the sdk. The data of the device is obtained throughMBT02ConnectableAssetTagEntity
as shown below, which is stored in the broadcast frame object.
The sdk providesBaseBleDeviceEntity
as the base class ofMBT02ConnectableAssetTagEntity
to store the public data of the sensor device as shown in the following table.
Name | Type | Description |
---|---|---|
macAddress | String | device mac |
name | String | Device name |
rssi | int | Signal strength |
The BaseBleDeviceEntity
also keeps a Map, which is used internally to store the device broadcast data frames it acquires during a scan, and can be retrieved as follows
val module:MBT02ConnectableAssetTagEntity
val deviceStaticInfoFrame : DeviceStaticInfoFrame? = module.getMinewFrame(FrameType.DEVICE_INFORMATION_FRAME)?.let {
it as DeviceStaticInfoFrame
}
if (deviceInforFrame != null) {
//Device mac address
String macAddress = deviceInforFrame.macAddress
//Percentage of power
val battery = deviceInforFrame.battery
//firmware version
val firmwareVersion = deviceInforFrame.firmwareVersion
}
2
3
4
5
6
7
8
9
10
11
12
There are some of adv frames for Connectable Asset Tag device
Device static information frame
DeviceStaticInfoFrame
Name Type Description frameVersion int device type firmwareVersion String Firmware Version batteryLevel int Battery Level Percentage macAddress String firmware mac peripheralSupportInfo PeripheralSupportInfo Description of peripheral support
other
# Connections
It is usually necessary to stop scanning before connecting. sdk provides methods to connect and disconnect.。
val manager = MBT02ConnectableAssetTagBleManager.getInstance()
//stop scanning
manager.stopScan(context)
//Setting the device secret key
val key="3141592653589793"
manager.setSecretKey(key)
//Connection, module for the device to be connected
val module:MBT02ConnectableAssetTagEntity
manager.connect(context,module)
//Disconnect. macAddress is the device mac
manager.disConnect(macAddress)
2
3
4
5
6
7
8
9
10
11
12
Note: Before connecting the device, please confirm whether the device is scanned, if no device broadcast is scanned and the connection method is called, the connection will fail.
After calling connect()
, there will be a status listener in sdk for the connection process.
val manager = MBT02ConnectableAssetTagBleManager.getInstance()
manager.setOnConnStateListener { macAddress, bleConnectionState ->
when (it) {
BleConnectionState.Connecting -> {
//This state will be called back after calling connect()
Log.d("connectionListener", "Connecting")
}
BleConnectionState.Connected -> {
//The initial connection was successful, as a transition phase, but not really successful at this point.
Log.d("connectionListener", "Connected")
}
BleConnectionState.AuthenticateSuccess ->{
//Key verification successful.
Log.d("connectionListener", "AuthenticateSuccess")
}
BleConnectionState.AuthenticateFail ->{
//Key verification failed.
Log.d("connectionListener", "AuthenticateFail")
}
BleConnectionState.ConnectComplete -> {
//Connection is complete, the device is now ready for read and write operations.
Log.d("connectionListener", "ConnectComplete")
}
BleConnectionState.Disconnect -> {
//Connection failure or device disconnection will be called back, active disconnection will not call back the .
Log.d("connectionListener", "Disconnect")
}
else -> {}
}
}
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
During the connection process, sdk will return multiple connection states to the app, which the app needs to handle properly.
- BleConnectionState.Connecting,BleConnectionState.Connected: Connecting the device in, do not do time-consuming operations in this state, because at this time in the connected device discovery service, and send authentication data, etc.
- BleConnectionState.ConnectComplete: The device is successfully connected at this point, and can perform read and write operations, such as configuring advparameters, sensor configuration, reading historical data, etc.
- BleConnectionState.AuthenticateFail:The secret key is verified during the authentication process. If the entered secret key is incorrect, this state will be called back and the device will actively disconnect.
- BleConnectionState.AuthenticateSuccess:The secret key is verified during the authentication process. If the entered secret key is correct, this status will be called back.
- BleConnectionState.Disconnect: The callback will be made if the connection fails or the device is disconnected.
# Reading and writing
The read and write APIs are as follows.:
/**
*Set device key
* @param macAddress device mac
* @param secretKey secret key key
* @param listener
*/
public void setSecretKey(String macAddress, String secretKey);
/**
* Query device version information
* @param macAddress device mac
* @param listener listener
*/
public void getFirmwareVersion(String macAddress, OnQueryResultListener<FirmwareVersionModel> listener);
/**
* Firmware upgrade
*
* @param macAddress device mac
* @param isLinkUpgrade true url upgrade, false firmware package upgrade. The default value is false, and the url upgrade * method is not supported.
* @param dfuTarget isLinkUpgrade =true, dfuTarget = 0
* @param upgradeData upgrade package data
* @param listener listener
*/
public void firmwareUpgrade(String macAddress,boolean isLinkUpgrade,int dfuTarget,byte[] upgradeData, OnFirmwareUpgradeListener listener);
/**
* Restore factory settings
*
* @param macAddress device mac
* @param listener listener
*/
public void reset(String macAddress, OnModifyConfigurationListener listener);
/**
* Shutdown
* @param macAddress device mac
* @param listener listener
*/
public void powerOff(String macAddress, OnModifyConfigurationListener listener);
/**
* Verify the OTA upgrade file
* @param zipFilePath ota file path
* @return true=upgrade file ,false= unusable
*/
boolean verifyOtaFile(@NonNull String zipFilePath);
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
45
46
47
48
49
Some methods are supplemented:
Set the device key. This method must be called before the connect() method.
val manager = MBT02ConnectableAssetTagBleManager.getInstance() val secretKey = "3141592653589793" manager.setSecretKey(mAddress,secretKey)
1
2
3
4Query device version information。
suspend fun queryFirmwareInfo(): FirmwareVersionModel? = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext null } return@withContext suspendCancellableCoroutine<FirmwareVersionModel?> { continuation -> manager.queryDeviceFirmwareInfo(connectMacAddress!!) { isSuccessful, version -> continuation.resume( when (isSuccessful) { true -> version else -> null }, null ) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15Set device LED
suspend fun setLEDConfig( color: Int, workTotalTime: Int, singleCycleLightingTime: Int, singleCycleLightOffTime: Int, brightness: Int ): Boolean = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext false } return@withContext suspendCancellableCoroutine<Boolean> { continuation -> manager.setLEDConfiguration( connectMacAddress!!, color, workTotalTime, singleCycleLightingTime, singleCycleLightOffTime, brightness ) { isSuccess -> continuation.resume(isSuccess, null) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24Set device buzzer
suspend fun setBuzzerConfig( workingCyclesTime: Int, singleCycleWorkTime: Int, singleCycleIdleTime: Int, gear: Int ): Boolean = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext false } return@withContext suspendCancellableCoroutine<Boolean> { continuation -> manager.setBuzzerConfiguration( connectMacAddress!!, workingCyclesTime, singleCycleWorkTime, singleCycleIdleTime, gear ) { isSuccess -> continuation.resume(isSuccess, null) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22Firmware upgrade.
private fun firmwareUpgrade( fileByte: ByteArray, dfuTarget: Int ) { mConnectViewModel.firmwareUpgrade(dfuTarget, fileByte, progressCallBack = { progress -> WaitDialog.show(getString(R.string.common_upgrading), (progress / 100f)) binding.progressBarSimpleCustom.progress = progress.toFloat() }, successCallBack = { WaitDialog.dismiss() ToastUtils.showShort(R.string.common_firmware_upgrade_successfully) finishPageForResult() }, failCallBack = { WaitDialog.dismiss() ToastUtils.showShort(R.string.common_firmware_upgrade_failure2) } ) } fun firmwareUpgrade( dfuTarget: Int, fileByte: ByteArray, progressCallBack:(progress:Int) -> Unit, successCallBack:() -> Unit, failCallBack:() -> Unit, ){ manager.firmwareUpgrade(connectMacAddress!!,false,dfuTarget,fileByte, object : OnFirmwareUpgradeListener { override fun updateProgress(progress: Int) { progressCallBack(progress) } override fun upgradeSuccess() { successCallBack() } override fun upgradeFailed() { failCallBack() } }) }
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
37
38
39
40
41
42
43
44
45Restore the factory settings.
suspend fun reset(): Boolean = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext false } return@withContext suspendCancellableCoroutine<Boolean> { continuation -> manager.reset(connectMacAddress!!) { continuation.resume(it, null) } } }
1
2
3
4
5
6
7
8
9
10Shutdown.
suspend fun shutdown(): Boolean = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext false } return@withContext suspendCancellableCoroutine<Boolean> { continuation -> manager.powerOff(connectMacAddress!!) { continuation.resume(it, null) } } }
1
2
3
4
5
6
7
8
9
10
# History
- **2024/10/30 edit;