# BeaconSET Plus Android Software Development Kit Guide
- Updating...
This set of SDK only supports devices based on miniBeaconPlus firmware and no longer supports products produced by other companies. Compared with the previous single-channel device SDK, the current set of BeaconSET Plus SDK supports more features. Of course, we also encountered many problems during the development process. We will explain the design reasons and precautions in this document. So, please read this document carefully to get started with project development as soon as possible.
Please read the part of this document which you need, part 1 we will explain the architecture of this SDK, part 2 will help developers to get started, part 3 will explain notes in your developing progress, part 4 you can get error codes and descriptions.
# Design instructions
We divide the communications between SDK and devices into two stages: Scanning stage, Connection stage. For ease of understanding, let's take a look at the related classes and the relationships between them.
MTCentralManager: global manager, check system's bluetooth status, listen status changes, the most important is scan and connect to devices;
MTPeripheral: instance of devices, MTCentralManager will create an MTPeripheral instance while it found a physical device, a device corresponds to an instance. every MTPeripheral instance has a MTFrameHandler property and a MTConnectionHandler property(These two properties are explained below);
MTFrameHandler: Advertisement frame analysis, it can analyze all frames from advertisement data of a device. in other words, it's the core of the scanning stage;
MTConnectionHandler: connection Operator. this class control all the operation of device in connection stage.
MTSensorHandler: sensor Operator, this class control all the sensor operation of device in connection stage.
**MinewFrame:**data frame, every minewframe(or subclass) instance corresponds to a data frame, usually created by "MTFrameHandler", if a device advertises mutiple data frames(such as iBeacon, UID, URL) "MTFrameHandler" will create multiple corresponding MinewFrame instances.
MTOTAManager: OTA, use this class for update device's firmware only.
# Overall structure
# Advertisement Stage
in this stage, MTCentralManager will scan and analyze the advertisement data of miniBeaconPlus devices, MTCentralManager will create "MTPeripheral" instance for every physical devices, developers can get all advertisement data by its MTFrameHandler property.
# Connection Stage
After a MTPeripheral connected, developer can make some changes of the device by MTConnectionHandler(a Property of MTPeripheral instance).
# OTA Operations
In general, OTA operations is complicated, so we encapsulates the MTOTAManager to perform firmware update operations, please note developer can update devices only in connection status.
# Get Started
# Prepare
# Development environment:
- Android Studio
- minSdkVersion 24
# Import to Project
Copy the development kit MTBeaconPlus.aar file into the libs directory and add dependencies in build.gradle. As shown below:
Please add under build.gradle
// Add dependency library dependencies { implementation files('libs\\MTBeaconPlus.aar') }
1
2
3
4Add the Bluetooth permissions and the corresponding component registration under the AndroidManifest.xml file. As follows:
<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"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
tools:targetApi="s" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
2
3
4
5
6
7
8
9
<service android:name="com.minew.beaconplus.sdk.ConnectService"/>
<receiver android:name="com.minew.beaconplus.sdk.receivers.BluetoothChangedReceiver">
<intent-filter>
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED"/>
</intent-filter>
</receiver>
2
3
4
5
6
7
# Start Developing
# Get sharedInstance of Manager
First of all, the developer should get the sharedInstance of Manager:
// get sharedInstance
MTCentralManager mtCentralManager = MTCentralManager.getInstance(this);
// listen the change of iPhone bluetooth
// *** also get from "bluetoothstate" property.
// *** this SDK will work normally only while state == PowerStatePoweredOn!
mtCentralManager.setBluetoothChangedListener(new OnBluetoothStateChangedListener() {
@Override
public void onStateChanged(BluetoothState state) {
}
});
2
3
4
5
6
7
8
9
10
11
# Scan devices
start scanning task to find devices around you, then you can get their advertisement content, connect to device and change parameters.
Attempting to start scanning while already in scanning mode, Return "Operation Failed: Currently in scanning mode, no need to restart scanning."
/*
mtCentralManager: sharedInstance of MTCentralManager
*/
// start scanning task
mtCentralManager.startScan();
// Traverse the List,get instance of every device.
// ** you can also display them on views.
mtCentralManager.setMTCentralManagerListener(new MTCentralManagerListener() {
@Override
public void onScanedPeripheral(final List<MTPeripheral> peripherals) {
for (MTPeripheral mtPeripheral : peripherals) {
// get FrameHandler of a device.
MTFrameHandler mtFrameHandler = mtPeripheral.mMTFrameHandler;
String mac = mtFrameHandler.getMac(); //mac address of device
String name = mtFrameHandler.getName(); // name of device
int battery = mtFrameHandler.getBattery(); //battery
int rssi = mtFrameHandler.getRssi(); //rssi
long lastUpdate = mtFrameHandler.getLastUpdate(); //last updated time
// all data frames of device(such as:iBeacon,UID,URL...)
ArrayList<MinewFrame> advFrames = mtFrameHandler.getAdvFrames();
for (MinewFrame minewFrame : advFrames) {
//Last updated time of each frame
Log.v("beaconplus", "lastUpdate:" + minewFrame.getLastUpdate());
}
}
}
});
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
at the sometime, you can stop the scanning task in this way.
Attempting to stop scanning when not in scanning mode,Return "Operation Failed: Currently not in scanning mode, no need to stop scanning."
// stop scanning task.
mtCentralManager.stopScan();
2
Get scan status
//true: scanning, false: not scanning
mtCentralManager.isScanning();
2
The SDK will cache all scanned devices and return them. If you need to clear the cache, you need to stop scanning first and then clear the cache.
When trying to clear the cache while currently scanning, it returns "Operation failed: Currently in scanning state, the cache cannot be cleared, please stop scanning first."
Code example for pull-down refresh:
// Stop scanning
mtCentralManager.stopScan();
// Clear cache
mtCentralManager.clear();
// Start scanning
mtCentralManager.startScan();
2
3
4
5
6
now the developer can get all advertisement data of device in this way. Next, we will talk about how to get frame data, such as iBeacon, URL, UID and etc...
Please refer to the code example below.
/*
mtFrameHandler: a MTFrameHandler instance.
*/
ArrayList<MinewFrame> advFrames = mtFrameHandler.getAdvFrames();
for (MinewFrame minewFrame : advFrames) {
FrameType frameType = minewFrame.getFrameType();
switch (frameType) {
case FrameiBeacon://iBeacon
IBeaconFrame iBeaconFrame = (IBeaconFrame) minewFrame;
Log.v("beaconplus", iBeaconFrame.getUuid() + iBeaconFrame.getMajor() + iBeaconFrame.getMinor());
break;
case FrameUID://uid
UidFrame uidFrame = (UidFrame) minewFrame;
Log.v("beaconplus", uidFrame.getNamespaceId() + uidFrame.getInstanceId());
break;
case FrameAccSensor:
AccFrame accFrame = (AccFrame) minewFrame;//acc
Log.v("beaconplus", accFrame.getXAxis() + accFrame.getYAxis() + accFrame.getZAxis());
break;
case FrameHTSensor:
HTFrame htFrame = (HTFrame) minewFrame;//ht
Log.v("beaconplus", htFrame.getTemperature() + htFrame.getHumidity());
break;
case FrameTLM:
TlmFrame tlmFrame = (TlmFrame) minewFrame;//tlm
Log.v("beaconplus", tlmFrame.getTemperature() + tlmFrame.getBatteryVol() + tlmFrame.getSecCount() + tlmFrame.getAdvCount());
break;
case FrameURL:
UrlFrame urlFrame = (UrlFrame) minewFrame;//url
Log.v("beaconplus", "Link:" + urlFrame.getUrlString() + "Rssi @ 0m:" + urlFrame.getTxPower());
break;
case FrameLightSensor:
LightFrame lightFrame = (LightFrame) minewFrame;//light
Log.v("beaconplus", "battery:" + lightFrame.getBattery() + "%" + lightFrame.getLuxValue());
break;
case FrameForceSensor:
ForceFrame forceFrame = ((ForceFrame) minewFrame);//force
Log.v("beaconplus", "battery:" + forceFrame.getBattery() + "%" + "force:" + forceFrame.getForce() + "gram");
break;
case FramePIRSensor:
PIRFrame pirFrame = ((PIRFrame) minewFrame);//pir
Log.v("beaconplus", "battery:" + pirFrame.getBattery() + "%" + "PIR:", pirFrame.getValue());
break;
case FrameTempSensor://temp
TemperatureFrame temperatureFrame = (TemperatureFrame) minewFrame;
Log.v("beaconplus", "battery:" + temperatureFrame.getBattery() + "%,temperature:" + String.format("%.2f", temperatureFrame.getValue()) + "°C");
break;
case FrameTVOCSensor://tvoc
TvocFrame tvocFrame = (TvocFrame) minewFrame;
Log.v("beaconplus", "battery:" + tvocFrame.getBattery() + ",TVOC:" tvocFrame.getValue() + "ppb," + "battery:" +tvocFrame.getBattery() + "mV");
break;
case FrameLineBeacon://FrameLineBeacon
FrameLineBeacon lineBeacon = ((FrameLineBeacon) minewFrame);
Log.v("beaconplus", "Hwid:" + lineBeacon.getHwid()
+ ",Rssi@1m:", lineBeacon.getTxPower()
+ ",authentication:"lineBeacon.getAuthentication()
+ ",timesTamp:" + lineBeacon.getTimesTamp());
break;
case FrameTamperProof://TamperProofFrame
TamperProofFrame tamperProofFrame = ((TamperProofFrame) minewFrame);//
Log.v("beaconplus", "battery:" + tamperProofFrame.getBattery());
break;
case FrameInfo://InfoFrame
InfoFrame infoFrame = ((InfoFrame) minewFrame);//
Log.v("beaconplus", infoFrame.getMajor() + infoFrame.getMinor() + infoFrame.getBatteryVoltage());
break;
case FrameGInfo://GInfoFrame
GInfoFrame GinfoFrame = ((GInfoFrame) minewFrame);//
Log.v("beaconplus", GinfoFrame.getMac() + GinfoFrame.getBattery() + GinfoFrame.getUuid());
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
Important: for all types of sensor value, if it equals to Double.MIN_VALUE OR Integer.MIN_VALUE, it means that this value is not available.
Please refer to the code example below:
/*
* htFrame: HTFrame
* lightFrame:LightFrame
* accFrame:AccFrame
* forceFrame:ForceFrame
* pirFrame:PIRFrame
*/
if (htFrame.getTemperature == Double.MIN_VALUE) {
Log.v("tag",this value is not available.");
}
if (lightFrame.getLuxValue == Integer.MIN_VALUE) {
Log.v("tag",this value is not available.");
}
if (accFrame.getXAxis() == Double.MIN_VALUE) {
Log.v("tag",this value is not available.");
}
if (forceFrame.getXAxis() == Double.MIN_VALUE) {
Log.v("tag",this value is not available.");
}
if (pirFrame.getXAxis() == Double.MIN_VALUE) {
Log.v("tag",this value is not available.");
}
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
# Connect to device
Connect to the device in order to do more operations(change parameter, OTA). you will find that when connect to device password may need, so ,Please note that callback status PASSWORDVALIDATING:
Please refer to the code example below.
/*
mtCentralManager: a MTCentralManager sharedInstance
mtPeripheral: a MTPeripheral instance
*/
mtCentralManager.connect(mtPeripheral, connectionStatueListener);
/*
there is mutiple state when connect to the device,
only "status == StatusCompleted" means connection operations success.
if exception appears, error will not be NULL
*/
private ConnectionStatueListener connectionStatueListener = new ConnectionStatueListener() {
@Override
public void onUpdateConnectionStatus(final ConnectionStatus connectionStatus, final GetPasswordListener getPasswordListener) {
runOnUiThread(new Runnable() {
@Override
public void run() {
switch (connectionStatus) {
case CONNECTING:
Log.e("minew_tag", ": CONNECTING")
break;
case CONNECTED:
Log.e("minew_tag", ": CONNECTED")
break;
case CONNECTED:
Log.e("minew_tag", ": CONNECTED")
break;
case READINGINFO:
//Advanced exercise can be notified when reading firmware information
Log.e("minew_tag", ": Read device firmware information")
break;
case DEVICEVALIDATING://After successfully verifying the device, write the verification key to the device
LogUtils.e("DEVICEVALIDATING");
break;
//If you need the connect password, will call back this state.
// !!!:Warnning: passwordRequire must not be NULL!!!
// the length of password string must be 8.
case PASSWORDVALIDATING:
// (Warning/Note)!!!: the password string length must be 8, digits or letters,Otherwise, it may cause the device firmware to malfunction
String password = "minew123";
getPasswordListener.getPassword(password);
break;
case SYNCHRONIZINGTIME://Password verification completed
Log.e("minew_tag", ": SYNCHRONIZINGTIME")
break;
case READINGCONNECTABLE:
Log.e("minew_tag", ": Read device firmware information")
LogUtils.e("READINGCONNECTABLE");
break;
case READINGFEATURE:
LogUtils.e("READINGFEATURE");
break;
case READINGFRAMES:
LogUtils.e("READINGFRAMES");
break;
case READINGTRIGGERS:
LogUtils.e("READINGTRIGGERS");
break;
case READINGSENSORS:
LogUtils.e("READINGSENSORS");
break;
case COMPLETED:
//At this point the connection is successful and the parameters are written to the device
break;
}
});
}
@Override
public void onError(MTException mtException) {
}
};
// disconnec from the device.
mtCentralManager.disconnect(mtPeripheral);
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# Get base information
the developer can get device information and modify parameters when a device connected.
the code example below let the developer get the base data of the device.
/*
* mtPeripheral:a MTPeripheral instance
*/
MTConnectionHandler mtConnectionHandler = mtPeripheral.mMTConnectionHandler;
// current connection status
ConnectState connectState = mtConnectionHandler.getConnectState();
// password require or not. None, Require
PasswordState passwordState = mtConnectionHandler.getPasswordState();
// device info, such as:(Firmware Version: 0.9.1);
HashMap<String, String> systeminfos = mtConnectionHandler.systeminfos;
String manufacturer = systeminfos.get(Constants.manufacturer);
String modlenumber = systeminfos.get(Constants.modlenumber);
String macAddress = systeminfos.get(Constants.serialnumber);
String hardware = systeminfos.get(Constants.hardware);
String firmware = systeminfos.get(Constants.firmware);
String software = systeminfos.get(Constants.software);
// device features
MTConnectionFeature mtConnectionFeature = mtConnectionHandler.mTConnectionFeature;
// atitude of slot(s),
int slotAtitude = mtConnectionFeature.getSlotAtitude();
// parameters can be modified:none,adv,txpower,adv/txpower
FeatureSupported featureSupported = mtConnectionFeature.getFeatureSupported();
// // frames supported(multiple)
List<FrameType> supportedSlots = mtConnectionFeature.getSupportedSlots();
// Txpower supported(multiple)
byte[] supportedTxpowers = mtConnectionFeature.getSupportedTxpowers();
// trigger supported(multiple)
ArrayList<TriggerType> supportTriggers = mtConnectionFeature.supportTriggers;
// Version of firmware;
Version version = mtConnectionFeature.getVersion();
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
PS: MTConnectionHandler’s Version property.
The version value comes form firmware version, check the version value to find out functions the device support:
// init value
UNDEFIND
// base version, base function only.
VersionBase
// this version or above support custom connection password and device info frame.
Version0_9_8
// this version or above support remote shut down.
Version0_9_9
// this version or above support triggers.
Version2_0_0
// this version or above support triggers with adv configs.
Version2_2_60
//The difference between Bluetooth 4.2 and 5.0
VERSION2_5_X
//new version
VERSION2_NEW
// ideal value, support all features.
VersionMax = 1000
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
# Get data of each Slot
Next, let talk about the parameter data of every slot, the reason why we speak about this is because all the content of changing parameters is here.
Slot :Before read the code, let's talk about slot, you can think slot as a advertisement tool, it advertise the content of advertisement data even "don't know" what the content is. such as the 6 slots may like this:
Slot Number | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
Adv content | iBeacon | TLM | UID | URL | HTSensor | None |
Adv interval(ms) | 1000 | 2000 | 500 | 900 | 3000 | 0 |
RSSI@0/1m(dbm) | -1 | 0 | -4 | -10 | -3 | 0 |
Txpower(dbm) | 4 | 0 | -4 | 4 | 0 | 0 |
By meaning of the table, the No.0 slot will advertise iBeacon data, the No.1 slot will advertise TLM data, …, the No.5 slot will not advertise any data. each of them have their own advertising interval, Txpower and Calibration RSSI. They are independent of each other.
PS: Calibration RSSI(RSSI@0/1m) is the RSSI when device @ 0/1m(iBeacon is 1, others 0).
How to get the slot advertisement data? please refer to the code example below.
/*
* mtConnectionHandler: a MTConnectionHandler instance
*/
// each slot has a frame of current device.
// atitude of this List is equals to slot atitude(feature.slotAtitude)
//
// In strict accordance with the order of the slot,such as:0. -> MinewiBeacon,1. -> MinewUID ...
ArrayList<MinewFrame> allFrames = mtConnectionHandler.allFrames;
/*
We assume the No.3 slot has iBeacon data, the No.4 slot has UID data.
let's try to analyze the data of No.3 slot.
*/
// due to the defualt object is MinewFrame(the superclass of MinewiBeacon), so we need make a conversion.
// get the frame of No.3 slot
MinewFrame minewFrame = allFrames.get(2);
// check this slot has iBeacon data or not,
// *You can not check if you confirm its type.
if(minewFrame.getFrameType()==FrameType.FrameiBeacon){
IBeaconFrame iBeaconFrame = (IBeaconFrame) minewFrame;
// iBeacon data
String uuid = iBeaconFrame.getUuid(); //uuid
int major = iBeaconFrame.getMajor(); //major
int minor = iBeaconFrame.getMinor(); //minor
// the other parameters of this slot
int curSlot = iBeaconFrame.getCurSlot();// number of the slot
int advInterval = iBeaconFrame.getAdvInterval();// advertisement interval
int advtxPower = iBeaconFrame.getAdvtxPower();// RSSI@0/1m
int radiotxPower = iBeaconFrame.getRadiotxPower();// radio Txpower
}
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
You can analyze the data of other slots in the same way, it's worth noting that when frameType == FrameNone means the slot has no data: From another perspective it means this slot is closed.
# Change slot data
The developer can modify advertisement and parameters of every slot freely via our APi.
We divide the data frame into static frames and dynamic frames:
- Static frame: advertisement data will not change when it was advertise, such as iBeacon, UID, URL
- Dynamic frame: advertisement data will change while it was advertise, such as TLM, Sensor
Please refer to the code example below:
/*
mtConnectionHandler: a MTConnectionHandler instance
*/
// create a uid instance
UidFrame uidFrame = new UidFrame();
uidFrame.setFrameType(FrameType.FrameUID);
// set "namespaceId" and "instanceId" of UID
uidFrame.setNamespaceId("0123456789abdcdcba12");
uidFrame.setInstanceId("0123456789dc");
// the other parameters of slot
uidFrame.setRadiotxPower(4); // Radio txpower.
uidFrame.setAdvInterval(600);// advertisement interval
uidFrame.setAdvtxPower(-3); // RSSI@0m
// write to device.
// detail: 1.let No.1 slot advertise UID data, namespaceId:0123456789abdcdcba12 instanceId:0123456789dc
// 2.set No.1 slot advertisement interval to 600ms, RSSI@0m to -3dbm, radio txpower to 4dbm
//The second parameter is the curSlot number
mtConnectionHandler.writeSlotFrame(uidFrame, 1, new MTCOperationCallback() {
@Override
public void onOperation(boolean success, MTException mtException) {
if(success){
Log.v("beaconplus","Success!");
}else{
Log.v("beaconplus",mtException.getMessage);
}
}
});
//set LineaBeaconFrame
LineBeaconFrame lineBeaconFrame = new LineBeaconFrame();
lineBeaconFrame.setFrameType(FrameType.FrameLineBeacon);
String hwid = "123456abfc";//Hwid长度为 10,包含 a-f/A-F/0-9
String vendorKey = "123456ad";//VendorKey长度为 8,包含 a-f/A-F/0-9
Stirng lotKey = "123456";//LotKey长度为 16 包含 a-f/A-F/0-9
lineBeaconFrame.setHwid(hwid);
lineBeaconFrame.setVendorKey(vendorKey);
lineBeaconFrame.setLotKey(lotKey);
// The second parameter is the channel number
mtConnectionHandler.writeSlotFrame(lineBeaconFrame, 1, new MTCOperationCallback() {
@Override
public void onOperation(boolean success, MTException mtException) {
if(success){
Log.v("beaconplus","Success!");
}else{
Log.v("beaconplus",mtException.getMessage);
}
}
});
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
50
51
Becareful, the slot parameter has ranges:
- Advertisement interval: 100 - 5000 (ms)
- RSSI@0m: -127 - 0 (dbm)
The most important: Radio txpower is not a range, it's grade, such as: -8, -4, 0, 4. you can get all supported Radio Txpowers from the feature property of the "MTConnectionHandler"
/*
mtConnectionFeature: a property of MTConnectionHandler.
*/
// get all supported Radio txpower of current device.
byte[] supportedTxpowers = mtConnectionFeature.getSupportedTxpowers();
2
3
4
5
6
OK, you can modify any slot in the way above, if you want to close a slot, only need to create a MinewFrame instance and make its frameType property to FrameNone, then write this frame to device. oh don't forget to set a slotnumber for the slot which you want to close.
# special frame data
Modify the Bluetooth broadcast method: Bluetooth 5.0 125Kbps
/** * set broadcast rate * @param mCurrentSlot: The currently selected channel value * @param templateBroadcastRate: 1mbps is set to 0, 125kbps is set to 1 * @return broadCastRate */ int broadCastRate = mtConnectionHandler.calculateBroadCastRate(int mCurrentSlot, int templateBroadcastRate); mtConnectionHandler.setBroadcastRate(int broadCastRate, MTCOperationCallback mtcOperationCallback);// set broadcast rate
1
2
3
4
5
6
7
8Set Acc Frame Parameters:int odr, int wakeupThreshold, int wakeupDuration
//Get Acc source parameters::int odr, int wakeupThreshold, int wakeupDuration List<AccParamsModel> list = mtConnectionHandler.getSetAccParamsValue(); for(AccParamsModel paramsModel : list) { Pair<String, Integer> ordvalues = paramsModel.getOrdsVelues(); Integer odr= ordvalues.second; int[] wakeupTimeValues = paramsModel.getWakeupTimeValues();//Indicates the wake-up threshold range int wakeupTime_min = wakeupTimeValuesp[0];//Wake Threshold Minimum int wakeupTime_max = wakeupTimeValuesp[1];//Wake Threshold Max int[] wakeupDurationValues = paramsModel.getWakeupDurationValues();//wakeup duration range int wakeupDuration_min = wakeupTimeValuesp[0];//Wakeup Duration Minimum int wakeupDuration_max = wakeupTimeValuesp[1];//Wakeup Duration Max } /* Set parameters for Acc:wakeupThreshold Take values in the range of int[]wakeupTimeValues,wakeupDuration takes values in the range of int[] wakeupDurationValues */ mtConnectionHandler.setAccValue(MTCOperationCallback mtcOperationCallback, int odr, int wakeupThreshold, int wakeupDuration);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Change global parameter
Global parameter of device is a device level feature, such as connectable, password require, reset to default and etc.
Please refer to the code example below.
/*
mtConnectionHandler: a MTConnectionHandler instance
*/
// reset the device
mtConnectionHandler.resetFactorySetting(new MTCOperationCallback() {
@Override
public void onOperation(boolean success, MTException mtException) {
if (success) {
Log.v("beaconplus","Success!");
} else {
Log.v("beaconplus","Failed!");
}
}
});
// update connectable settings
// CONNECTABLE_YES: app can connect to the device, CONNECTABLE_NO app can't connect to the device.
// if you set CONNECTABLE_NO, you can connect to device by press the button on device maybe next time.
// DANGER!!!:if there is no button on device and set CONNECTABLE_NO, the app can't connect to device even forever.
mtConnectionHandler.updateConnectable(CONNECTABLE_NO, new MTCOperationCallback() {
@Override
public void onOperation(final boolean success, final MTException mtException) {
if (success) {
Log.v("beaconplus","Success!");
} else {
Log.v("beaconplus","Failed!");
}
}
});
// Modify/Add password,it will add password if device has no password, update password if device has a password
// (Warning/Note)!!!: the password string length must be 8, digits or letters,Otherwise, it may cause the device firmware to malfunction
mtConnectionHandler.modifyPassword("minew123", new MTCOperationCallback() {
@Override
public void onOperation(final boolean success, MTException mtException) {
if (success) {
Log.v("beaconplus","Success!");
} else {
Log.v("beaconplus","Failed!");
}
}
});
// remove password
mtConnectionHandler.removePassword(new MTCOperationCallback() {
@Override
public void onOperation(final boolean success, MTException mtException) {
if (success) {
Log.v("beaconplus","Success!");
} else {
Log.v("beaconplus","Failed!");
}
}
});
/**
* remote shut down the device.
* DANGER!!!: please make sure there a button on device, otherwise it may not boot again.
*
* (New) Note: If the model name is Beacon Plus-BL and the device does not support shutdown, an UnsupportedOperationException will be thrown directly.
* Need to pre-determine the value of model name
*
* Get the value of model name via MTConnectionHandler.systeminfos.get(Constants.modlenumber)
*/
mtConnectionHandler.powerOff(new MTCOperationCallback() {
@Override
public void onOperation(boolean success, MTException mtException) {
if (success) {
Log.v("beaconplus","Success!");
} else {
Log.v("beaconplus","Failed!");
}
}
});
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# Sensor data
BeaconPlus devices integrated a variety of sensors: HT(Temperature and Humidity ), Light, Acceleration and etc, currently we provide APi for read HT History data and API for PRI.
Please note: On January 9, 2019, we provided a new interface to obtain temperature and humidity data. If you are using a new interface provided after this date, Please refer to the code example below.
read Sensor data
Please make sure the device has HT Sensor, otherwise you can't get data correctly. Please refer to the code example below.
/* * mtConnectionHandler: MTConnectionHandler实例 * * long longtime = System.currentTimeMillis(); * int time = (int) (longtime / 1000); * byte[] curTime = Tools.intToBytes(time) */ // Read temperature and humidity data from the device mMTConnectionHandler.getMtSensorHandler().readSensorHistory(curTime, new MTSensorOperateCallback<SensorHTModel>() { @Override public void onResult(SensorHTModel sensorHTModel) { int date = sensorModel.getDate();// The Unix timestamp of this data; float temperature = sensorModel.getTemperature();// Temperature data; float humidity = sensorModel.getHumidity();// Humidity data; } @Override public void onNoHistoricalData() { Log.v("beaconplus",""); } }); // Read temperature data from the device mMTConnectionHandler.getMtSensorHandler().readTempSensorHistory(curTime, new MTSensorOperateCallback<SensorTempModel>() { @Override public void onResult(SensorTempModel sensorTempModel) { int date = sensorTempModel.getDate();// Unix timestamp of this data; float temperature = sensorModel.getTemperature();// Temperature data } }); // Six-axis sensor data from the device mMTConnectionHandler.getMtSensorHandler().readLSMHistory(Tools.intToBytes(time), new MTSensorOperateCallback<SensorSixAxisModel>() { @Override public void onResult(SensorSixAxisModel sensorSixAxisModel) { int date = sensorSixAxisModel.getDate();// Unix timestamp of this data; double A_XAxis = sensorSixAxisModel.getA_XAxis(); double A_YAxis = sensorSixAxisModel.getA_YAxis(); double A_ZAxis = sensorSixAxisModel.getA_ZAxis(); double D_XAxis = sensorSixAxisModel.getD_XAxis(); double D_YAxis = sensorSixAxisModel.getD_YAxis(); double D_ZAxis = sensorSixAxisModel.getD_ZAxis(); } }); // Sensor data from the magnetometer on the device mMTConnectionHandler.getMtSensorHandler().readLISHistory(Tools.intToBytes(time), new MTSensorOperateCallback<SensorMAGModel>() { @Override public void onResult(SensorMAGModel sensorMAGModel) { int date = sensorMAGModel.getDate();// Unix timestamp of this data; double A_XAxis = sensorMAGModel.getA_XAxis(); double A_YAxis = sensorMAGModel.getA_YAxis(); double A_ZAxis = sensorMAGModel.getA_ZAxis(); } }); // From the atmospheric pressure sensor data on the device mMTConnectionHandler.getMtSensorHandler().readDPSHistory(Tools.intToBytes(time), new MTSensorOperateCallback<SensorAPModel>() { @Override public void onResult(SensorAPModel sensorAPModel) { int date = sensorAPModel.getDate();// Unix timestamp of this data; double pressure = sensorAPModel.getPressure(); } });
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64you can vividly display these data with the curve, table or other.
PIR sensor data
Please make sure the device has PIR Sensor, otherwise you can't get data correctly. Please refer to the code example below.
//mMtConnectionHandler: a MTConnectionHandler instance MTSensorHandler mtSensorHandler = mMtConnectionHandler.getMtSensorHandler(); Map<String, MTSensorModel> sensorMap = mtSensorHandler.getSensorMap(); SensorPIRModel sensorPIRModel = (SensorPIRModel) sensorMap.get(FrameType.FramePIRSensor.name()); //trigger time, the infrared sensor can be triggered again after the trigger time int time = sensorPIRModel.getTime(); //a bool,whether to allow repeated triggers boolean repeatTrigger = sensorPIRModel.isRepeatTrigger();
1
2
3
4
5
6
7
8
# Set triggers
BeaconPlus device has triggers, you can set triggers for every slot, the device will advertise the corresponding slot only when the trigger condition is met.
Please refer to the code example below.
/*
mtConnectionHandler: a MTConnectionHandler instance
*/
Trigger trigger = new Trigger();
trigger.setCurSlot(2);// Target slot:2
trigger.setTriggerType(TEMPERATURE_ABOVE_ALARM);// Triggering condition:temperature above
trigger.setCondition(10);// value:10
mMTConnectionHandler.setTriggerCondition(trigger,new SetTriggerListener() {
@Override
public void onSetTrigger(boolean success, MTException mtException) {
if (success) {
Log.v("beaconplus","Success!");
} else {
Log.v("beaconplus","Failed!");
}
}
});
//Set up the channel
private void SetPassage(int slot){
Trigger trigger = new Trigger();//Instantiate a trigger
//There are usually 6 channels
swith(slot) {
case 0://Channel 1
trigger.setCurSlot(0);
break;
case 1://Channel 2
trigger.setCurSlot(1);
break;
case 2://Channel 3
trigger.setCurSlot(2);
break;
case 3://Channel 4
trigger.setCurSlot(3);
break;
case 4://Channel 5
trigger.setCurSlot(4);
break;
case 5://Channel 6
trigger.setCurSlot(5);
break;
default:
break
}
switch(TriggerType triggerType) {//The argument here is an enum
case TEMPERATURE_ABOVE_ALARM://Temperature is higher than
//Trigger condition: temperature is higher than
trigger.setTriggerType(TEMPERATURE_ABOVE_ALARM);
break;
case TEMPERATURE_BELOW_ALARM://Temperature below
trigger.setTriggerType(TEMPERATURE_BELOW_ALARM);
break;
case HUMIDITY_ABOVE_ALRM://Humidity is higher than
trigger.setTriggerType(HUMIDITY_ABOVE_ALRM);
break;
case HUMIDITY_BELOW_ALRM://Humidity is below
trigger.setTriggerType(HUMIDITY_BELOW_ALRM);
break;
case BTN_DTAP_EVT://Double click
trigger.setTriggerType(BTN_DTAP_EVT);
break;
case BTN_TTAP_EVT://Triple hit
trigger.setTriggerType(BTN_TTAP_EVT);
break;
}
int mTemCondition= 10;//After reaching the trigger condition, broadcast duration: 10s
switch (triggerType) {
case TEMPERATURE_ABOVE_ALARM://Temperature is higher than
case TEMPERATURE_BELOW_ALARM://Temperature below
case HUMIDITY_ABOVE_ALRM://Humidity is higher than
case HUMIDITY_BELOW_ALRM://Humidity is below
case LIGHT_ABOVE_ALRM://Light perception is higher than
case LIGHT_BELOW_ALARM://Light sensitivity is lower than
case FORCE_ABOVE_ALRM://The pressure sensitivity is greater than
case FORCE_BELOW_ALRM://The pressure sensitivity is lower than
case TVOC_ABOVE_ALARM://TVOC is greater than
case TVOC_BELOW_ALARM://TVOC is lower than
trigger.setCondition(mTemCondition);
break;
default:
trigger.setCondition(mTemCondition * 1000);
}
trigger.setAlwaysAdvertising(boolean alwaysAdvertising)//Set whether to enable basic parameter broadcast. true: on, false: off.
trigger.setTriggerType(TriggerType.TRIGGER_SRC_NONE)//Set whether to enable trigger broadcast. It is turned off when the value is TRIGGER_SRC_NONE and turned on when it is other values.
//Broadcast conditions: time interval, the maximum is 5000ms
trigger.setAdvInterval(int advInterval)
//Broadcast conditions: broadcast signal strength, the maximum is 4, generally this is a negative value
trigger.setRadioTxpower(int radioTxpower)
mMTConnectionHandler.setTriggerCondition(trigger,new SetTriggerListener() {
@Override
public void onSetTrigger(boolean success, MTException mtException) {
if (success) {
Log.v("beaconplus","Success!");
} else {
Log.v("beaconplus","Failed!");
}
}
});
}
public enum TriggerType{
MOTION_DETECT(0),//Acceleration
TEMPERATURE_ABOVE_ALARM(1),//The temperature is higher than
TEMPERATURE_BELOW_ALARM(2),//The temperature is lower than
HUMIDITY_ABOVE_ALRM(3),//Humidity is higher than
HUMIDITY_BELOW_ALRM(4),//The humidity is lower than
LIGHT_ABOVE_ALRM(5),//Light perception is higher than
BTN_PUSH_EVT(6),//Press the button
BTN_RELEASE_EVT(7),//Button pop-up
BTN_STAP_EVT(8),//Click the button
BTN_DTAP_EVT(9),//Double-click the button
BTN_TTAP_EVT(10),//Three clicks on the button
LIGHT_BELOW_ALARM(11),//Light sensitivity is lower than
FORCE_ABOVE_ALRM(12),//The pressure sensitivity is greater than
FORCE_BELOW_ALRM(13),//The pressure sensitivity is lower than
PIR_DETECT(14),//infrared
TVOC_ABOVE_ALARM(15),//TVOC is greater than
TVOC_BELOW_ALARM(16),//TVOC is lower than
VIBRATION_DETECT(17),//Vibration trigger
LEAKAGE_ALARM(18),//Leak alarm
TRIGGER_SRC_NONE(-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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# Vibration sensor related operations
/**
* Set the sensitivity of the vibration sensor
* Super high:0x00, high:0x01,middle:0x02,low:0x03,Ultra low:0x04
*/
byte[] bytes = new byte[]{0x00};
mMTConnectionHandler.setVibrationSensitivity(bytes, new MTCOperationCallback() {
@Override
public void onOperation(boolean success, MTException mtException) {
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
});
/**
* Set alarm time zone
* String startTime = "19:00"
* String endTime = "21:00"
* int switch_status = 0 // 0: off, 1: on
*/
mMTConnectionHandler.setAlarmTime(startTime1,endTime1,switch_status1,
startTime2,endTime2,switch_status2,
startTime3,endTime3,switch_status3,
mtcOperationCallback);
//Callback method for setting alarm time zone
MTCOperationCallback mtcOperationCallback = new MTCOperationCallback() {
@Override
public void onOperation(boolean success, MTException mtException) {
runOnUiThread(new Runnable() {
@Override
public void run() {
}
}
});
}
};
/**
* Set the vibration function switch
* 0x01:open,0x00: off
* byte[] statusByte = new byte[]{0x00}; off
* byte[] statusByte = new byte[]{0x01}; open
*/
statusByte = new byte[]{0x00};
mMTConnectionHandler.setVibrationsensorStatus(statusByte, new MTCOperationCallback() {
@Override
public void onOperation(boolean success, MTException mtException) {
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
});
//Get vibration sensitivity
mMTConnectionHandler.inquireVibrationSensitivity(mtSensorOperateCallback);
//query vibration status
mMTConnectionHandler.inquireVibrationsensorStatus(mtSensorOperateCallback);
//query the callback method of alarm time zone
mMTConnectionHandler.inquireAlarmTime(mtSensorOperateCallback);
/**
* Get vibration sensitivity, query vibration status, query the callback method of alarm * time zone
*/
MTSensorOperateCallback mtSensorOperateCallback = new MTSensorOperateCallback() {
@Override
public void onResult(MTSensorModel mtSensorModel) {
if (mtSensorModel instanceof VibrationSensorModel) {
VibrationSensorModel vibrationSensorModel = (VibrationSensorModel) mtSensorModel;
} else if (mtSensorModel instanceof VibrationStatusModel) {
VibrationStatusModel vibrationStatusModel = (VibrationStatusModel) mtSensorModel;
} else if (mtSensorModel instanceof SensorTimeModel) {
SensorTimeModel sensorTimeModel = (SensorTimeModel) mtSensorModel;
switch (sensorTimeModel.getTimeInterval()) {
case 1:
startTime1 = sensorTimeModel.getStartTime();
endTime1 = sensorTimeModel.getEndTime();
timeSwitch1 = sensorTimeModel.getTimeSwitch() ? 1 : 0;
break;
case 2:
startTime2 = sensorTimeModel.getStartTime();
endTime2 = sensorTimeModel.getEndTime();
timeSwitch2 = sensorTimeModel.getTimeSwitch() ? 1 : 0;
break;
case 3:
startTime3 = sensorTimeModel.getStartTime();
endTime3 = sensorTimeModel.getEndTime();
timeSwitch3 = sensorTimeModel.getTimeSwitch() ? 1 : 0;
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
At the end of this part, you can refer all code above to develop. Of course we made a note for every APi in the SDK, if there is something new, we will update this document.
# Notes
In Android-6.0 or later, Bluetooth scanning requires dynamic application for location permissions, as follows:
String[] requestPermissions; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { requestPermissions = new String[]{ Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }; } else { requestPermissions = new String[]{ Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }; } ActivityCompat.requestPermissions(this, requestPermissions, PERMISSION_CODE);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18Because the connection process of the device is in the service, it is recommended to call the following method after the app starts to open the service, otherwise the connection function will not be used. details as follows:
/* * mtCentralManager:a MTConnectionHandler instance */ MTCentralManager mtCentralManager = MTCentralManager.getInstance(this); mtCentralManager.startService(); //stop ConnectService mtCentralManager.stopService();
1
2
3
4
5
6
7
8
# Change log
2020.10.27 v1.11 Added
lastUpdate
property for each broadcast frame2020.3.25 v1.10 Add information display and data setting supporting linebeacon frame
2019.12.04 v1.3 Modified the problem that some phones in Android 9.0 can't scan when the screen is closed, and added filtering conditions;
2019.7.11 v1.2 change the
powerOff
;2019.1.9 v1.1 second version;
Stashed changes
- 2017.10.13 v1.0 first version;
- 2019.1.9 v1.1 second version;
- 2019.7.11 v1.2 change the
powerOff
; - 2019.12.04 v1.3 Modified the problem that some phones in Android 9.0 can't scan when the screen is closed, and added filtering conditions;
- 2020.3.25 v1.10 Add information display and data setting supporting linebeacon frame
- 2020.10.27 v1.10.2 Added lastUpdate property for every broadcast frame
- 2021.4.21 v1.11.0 added six-axis/magnetometer/atmospheric pressure sensor
- 2021.4.28 v1.11.1 added vibration sensor
- 2022.2.23 V1.15.1 Added TamperProofFrame ,fix the problem that the optimized SDK cannot connect to the device;
- 2022.5.9 Added InfoFrame;
- 2022.5.10 Special frame data: support Bluetooth 5.0 125kbps rate, support parameter modification of ACC frame;
- 2022.5.23 Added parsing and parameter modification of GInfo broadcast frames;
- 2024.1.2 Added comments for setting basic parameter broadcast and trigger broadcast switches, and added TriggerType type, add instructions on how to obtain the latest update time of the device and frame;
- 2024.1.16 Add instructions for clearing cache methods, and correct the use and instructions of some methods;