BeaconPlus Android Software Development Kit Guide

  • Updating...

This SDK only support devices based on miniBeaconPlus firmware, it doesn't compatible with previous devices, such as iBeacon, eddystone and etc. BeaconSET+ SDK support more feature than BeaconSET SDK. We encountered some issues in the development process, So, please read the document carefully in order to help you get started as soon as possible. At the same time, this document will also inform the notes and issues.

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

BeaconSET+

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 18

Import to Project

  1. Copy the development kit MTBeaconPlus.jar file into the libs directory and add dependencies in build.gradle. As shown below:

    make jar

    add jar

    After the 20180502 version, the dfu function will use external dependencies. Please add under build.gradle

    // Add dependency library
     dependencies {
        implementation files('libs/MTBeaconPlus.jar')
        implementation 'no.nordicsemi.android:dfu:1.6.1'
     }
    
    1
    2
    3
    4
    5

    Otherwise it will crash when dfu.add code to proguard-rules.pro file:

     keep public class no.nordicsemi.android.**{*;}
    
    1
  2. Add 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"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
1
2
3
4
5
6
<service android:name="com.minew.beaconplus.sdk.ConnectService"/>
<service android:name="com.minew.beaconplus.sdk.services.DfuService"/>
<receiver android:name="com.minew.beaconplus.sdk.receivers.BluetoothChangedReceiver">
    <intent-filter> 
        <action android:name="android.bluetooth.adapter.action.STATE_CHANGED"/>
    </intent-filter>
</receiver>
1
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) {
  }
});
1
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.

/*
  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
            // all data frames of device(such as:iBeacon,UID,URL...)
            ArrayList<MinewFrame> advFrames = mtFrameHandler.getAdvFrames();
        }
    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

at the sometime, you can stop the scanning task in this way:

// stop scanning task.
mtCentralManager.stopScan();
1
2

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;
       default:
			break;  
    }
}
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

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.");
}
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

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 PASSWORDVALIDATING:
                        String password = "minew123";
                        getPasswordListener.getPassword(password);
                        break;    
                }
                
                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:
                        	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);
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

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();
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

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
VersionUndefined

// 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

// ideal value, support all features.
VersionMax = 1000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

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  
}
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

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);
         }
     }
 });
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

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();
1
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.

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
// !!!: the password string length must be 8, digits or letters;
// it will add password if device has no password, update password if device has a password
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!");
        }
    }
});
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

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.

  1. 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
    mtConnectionHandler.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
    mtConnectionHandler.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
    64
    /*
     *  mtConnectionHandler: a MTConnectionHandler instance
     */
    mtConnectionHandler.readSensorHistory(curTime, new MTSensorOperateCallback<SensorHTModel>() {
        @Override
        public void onReceiveHistoricalData(SensorHTModel sensorModel) {
            int date = sensorModel.getDate();// 此数据的Unix时间戳;
            float temperature = sensorModel.getTemperature();// 温度数据;
            float humidity = sensorModel.getHumidity();// 湿度数据;
        }
    
        @Override
        public void onNoHistoricalData() {
            Log.v("beaconplus","");
        }
    });
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    you can vividly display these data with the curve, table or other.

  2. 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;
        defaultbreak
    }
    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 HUMIDITY_BELOW_ALRM://Double click
            trigger.setTriggerType(BTN_DTAP_EVT);
            break;
        case HUMIDITY_BELOW_ALRM://Triple hit
            trigger.setTriggerType(BTN_TTAP_EVT);
            break;
    }

trigger.setCondition(10);//After reaching the trigger condition, broadcast duration: 10s
trigger.setAlwaysAdvertising(boolean alwaysAdvertising)//Whether to always broadcast
//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{
    TEMPERATURE_ABOVE_ALARM(1),//Temperature is higher than
    TEMPERATURE_BELOW_ALARM(2),//Temperature below
    HUMIDITY_ABOVE_ALRM(3),//Humidity is higher than
    HUMIDITY_BELOW_ALRM(4),//Humidity is below
    BTN_DTAP_EVT(9),//Double-trigger
    BTN_TTAP_EVT(10);//Three-shot trigger
}
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
 /**
     * 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";
*/
mMTConnectionHandler.setAlarmTime(startTime, endTime, 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.getVibrationSensitivity(mtSensorOperateCallback);
//query vibration status
mMTConnectionHandler.inquireVibrationsensorStatus(mtSensorOperateCallback);
//query the callback method of alarm time zone
mMTConnectionHandler.inquireVibrationTime(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 VibrationTimeModel) {
          VibrationTimeModel vibrationTimeModel = (VibrationTimeModel) mtSensorModel;
              
            }
        }
    };
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

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

  1. In Android-6.0 or later, Bluetooth scanning requires dynamic application for location permissions, as follows:

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,
                                          new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_COARSE_LOCATION);
    } 
    
    1
    2
    3
    4
    5
  2. Because 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

Not found: /home/minew/Platforms/Deploy/gitlab/mobile_sdk_website/repo/src/<<<< Updated upstream
  • 2020.10.27 v1.11 Added lastUpdate property for each broadcast frame
  • 2020.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
Last Updated:: 6/2/2021, 9:31:26 AM