Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

ElcoMaster Android SDK Getting Started

The ElcoMaster Android SDK will allow you to integrate a range of Elcometer gauges into your
Android applications. The current SDK supports the following Bluetooth gauges:

 Elcometer 456C (Standard and Top Models)


 Elcometer 224C (Top Model)
 Elcometer 510 (Top Model)
 Elcometer 480 (Top Models)
 Elcometer MTG6/MTG8
 Elcometer PTG8
 Elcometer 311C (Top Model)
 Elcometer 415C (Top Model)
 Elcometer 130 (Profiler and Top Models)
 Elcometer 500
 Elcometer 319

This getting started guide will give an overview of how to connect, download batches and live
measurements from these gauges.

Within the SDK zip there is a demo project, it requires Android Studio 3.X or greater.
Installation & Requirements
The SDK library is supplied as an aar library.

To install the library file into your Android application, copy the sdklib.aar into the libs folder in your
application.

Modify the build.gradle for your application to include the SDK project, e.g. add the following to your
dependencies:
implementation files('libs/sdklib.aar')

e.g.
Permissions
Android needs specific permissions for enumerating and connecting to Bluetooth devices.
Specifically BLUEOOTH, BLUETOOTH_ADMIN and ACCESS_COARSE_LOCATION permissions, these
will be added automatically to your APK manifest when you include the SDK library.

For Android 6.0+ the AccessCoarseLocation permission will also need to be dynamically requested
using the standard Android activity APIs CheckSelfPermission and RequestPermission. Check the
demo project for more information.

For Android 11.0 and above you will also require ACCESS_FINE_LOCATION to be placed in both the
manifest and dynamical requested.
Initialisation
The SDK requires the application context be passed to it before any other action is taken. The best
location to place this is in a custom Application class, e.g..
package com.elcometer.sdkdemo;

import android.app.Application;
import com.elcometer.sdklib.ElcoMasterSDK;

public class SDKDemoApplication extends Application {


@Override
public void onCreate() {
super.onCreate();

// initialise SDK - it requires the application context


ElcoMasterSDK.initialise(getApplicationContext());
}
}

Remember to update your AndroidManifest.xml file with the name of your Application object, e.g.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.elcometer.sdkdemo">

<application
android:name="com.elcometer.sdkdemo.SDKDemoApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Connecting to a Gauge
Connections can either be initiated by a built in gauge picker dialog or by manually passing the
required Bluetooth information.

The gauge picker dialog can be shown using the following:


ElcoMasterSDK.showPicker(this, "Select Bluetooth Device", "", null);

The first parameter being the current activity, second parameter the title to show on the picker, the
third parameter being a filter that will only display gauges containing the specified text, and finally
the forth parameter being a callback which is triggered when a gauge is selected (can be left null if
not required).

Notification of gauge connection and disconnection events can also be registered using the
GaugeConnectionManager singleton, using the setConnectionListener method, e.g.

GaugeConnectionManager.getInstance().setConnectionListener(new GaugeConnectionManager.ConnectionListener() {
@Override
public void onConnection(GaugeConnection connection) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// update ui for connected gauge
}
});
}

@Override
public void onDisconnection(GaugeConnection connection) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// update ui for disconnected gauge
}
});
}
});

Manual connections to Bluetooth gauges can be opened by creating a GaugeConnectionInfo class


with the Bluetooth address string (formatted in MAC address format, e.g. AB:12:AB:12:AB) and its
Bluetooth name. Pass this GaugeConnectionInfo to the open method of the
GaugeConnectionManager singleton and it will return a GaugeConnection object if sucesssfull.
Download Live Measurements
Live measurements require a dummy live batch object to be created. This can be done by calling the
createDefaultLiveBatch() method of the gauge connection live readings are to be collected from, e.g.
mBatch = mGauge.createDefaultLiveBatch();

Where above mGauge is the connected GaugeConnection object.

Once the batch is created, a listener can be setup which will be triggered when readings are added
to the batch, e.g.

// setup listener to get live readings


mBatch.setBatchListener(new Batch.BatchListener() {
@Override
public void onNewReading(NativeReading reading) {
// *NOTE* we will not be in the UI thread here.
// process live reading here
}
});

To link the dummy batch to the connection we call setLiveBatch on the gauge connection and pass in
the created batch object, e.g.
mGauge.setLiveBatch(mBatch);

Finally we tell the connection to begin live measurements.


mGauge.queueCommand(new GaugeConnection.IdleReadingCommand(null));

As readings are measured they will trigger the listener callback.


Downloading Batches
Batches are collections of measurements stored on a gauge, these can be downloaded by the SDK.
The first step is to put the gauge into a mode where batches can be retrieved, this can be achieved
by telling the connection to enter batch communications mode, e.g.
mGauge.queueCommand(new GaugeConnection.CommsModeCommand(mHandler));

A handler object (mHandler) is passed into the command, a message will be sent to the handler
when the command completes.

A typical handler would look like follows:


private Handler mHandler = new CommsMessageHandler(this);
private static class CommsMessageHandler extends Handler {
private final WeakReference<BatchesActivity> mBatchesActivityWeakReference;

CommsMessageHandler(BatchesActivity myClassInstance) {
mBatchesActivityWeakReference = new WeakReference<>(myClassInstance);
}

@Override
public void handleMessage(Message msg) {
BatchesActivity batchesActivity = mBatchesActivityWeakReference.get();
if (batchesActivity != null) {
if (msg.obj instanceof GaugeConnection.CommsModeCommand) {
// we have entered comms mode - so if the gauge supports batching download the batch list
GaugeConnection.CommsModeCommand command = (GaugeConnection.CommsModeCommand) msg.obj;

if (command.isSuccess() && command.getDetails() != null && command.getDetails().isSupportsBatching()) {


// now we are connected - request list of batches
batchesActivity.mGauge.queueCommand(new GaugeConnection.BatchListCommand(this));
}
}
}
}
}

When the message object is a CommsModeCommand and it has completed, and the gauge supports
batching it requests a list of batches by doing the following:
batchesActivity.mGauge.queueCommand(new GaugeConnection.BatchListCommand(this));

Again the same handler object is passed to the command, so the handleMessage callback can be
extended as follows:
public void handleMessage(Message msg) {
BatchesActivity batchesActivity = mBatchesActivityWeakReference.get();
if (batchesActivity != null) {
if (msg.obj instanceof GaugeConnection.CommsModeCommand) {
// we have entered comms mode - so if the gauge supports batching download the batch list
GaugeConnection.CommsModeCommand command = (GaugeConnection.CommsModeCommand) msg.obj;

if (command.isSuccess() && command.getDetails() != null && command.getDetails().isSupportsBatching()) {


// now we are connected - request list of batches
batchesActivity.mGauge.queueCommand(new GaugeConnection.BatchListCommand(this));
}
} else if (msg.obj instanceof GaugeConnection.BatchListCommand) {
// we have the batch list so show it on the ui
GaugeConnection.BatchListCommand command = (GaugeConnection.BatchListCommand) msg.obj;

if (command.isSuccess()) {
for (GaugeConnectionBatch batch : command.getBatches()) {
batchesActivity.mBatches.add(new BatchListItem(batch));
}
batchesActivity.mBatches.notifyDataSetChanged();
}
}
}
}

Now when the message object is a BatchListCommand an listview adapter (mBatches) is updated
with the list of GaugeConnectionBatch objects retrieved (command.getBatches())
Finally we want to download the batch, this can be achieved by doing the following:
mGauge.queueCommand(new GaugeConnection.BatchDownloadCommand(mHandler, batches));

Where the second parameter (batches) passed are the GaugeConnectionBatch objects we wish to
fully download.

Again in the handler we can process the response.


public void handleMessage(Message msg) {
BatchesActivity batchesActivity = mBatchesActivityWeakReference.get();
if (batchesActivity != null) {
if (msg.obj instanceof GaugeConnection.CommsModeCommand) {
// we have entered comms mode - so if the gauge supports batching download the batch list
GaugeConnection.CommsModeCommand command = (GaugeConnection.CommsModeCommand) msg.obj;

if (command.isSuccess() && command.getDetails() != null && command.getDetails().isSupportsBatching()) {


// now we are connected - request list of batches
batchesActivity.mGauge.queueCommand(new GaugeConnection.BatchListCommand(this));
}

} else if (msg.obj instanceof GaugeConnection.BatchListCommand) {


// we have the batch list so show it on the ui
GaugeConnection.BatchListCommand command = (GaugeConnection.BatchListCommand) msg.obj;

if (command.isSuccess()) {
for (GaugeConnectionBatch batch : command.getBatches()) {
batchesActivity.mBatches.add(new BatchListItem(batch));
}
batchesActivity.mBatches.notifyDataSetChanged();
}
} else if (msg.obj instanceof GaugeConnection.BatchDownloadCommand) {
// batch has been downloaded
GaugeConnection.BatchDownloadCommand command = (GaugeConnection.BatchDownloadCommand) msg.obj;

StringBuilder info = new StringBuilder();

// format the batch info into a string


for (Batch batch : command.getDownloadedBatches()) {
info.append(String.format(Locale.getDefault(), "Batch: %s\n", batch.getOriginalID()));
info.append(String.format(Locale.getDefault(), "Readings: %d\n", batch.getValidCount()));
info.append("\n");

NativeReading reading = batch.allocateReading();

for (int i = 0; i < batch.getRowCount(); i++) {


batch.getReading(i, reading);

if ((reading.getFlags() & NativeReading.READING_MASK_INCLUDED) != 0) {


StringBuilder readingRow = new StringBuilder();

for (int j = 0; j < batch.getColumnCount(); j++) {


if (readingRow.length() != 0) {
readingRow.append(", ");
}

readingRow.append(reading.toDisplayString(j));
}

info.append(String.format(Locale.getDefault(), "%d: %s\n", reading.getId() + 1,


readingRow.toString()));
}
}
}

// show batch details


Intent activity = new Intent(batchesActivity, BatchInfoActivity.class);
activity.putExtra("BatchInfo", info.toString());
batchesActivity.startActivity(activity);
}
}
}

In the above example when the message object is a BatchDownloadCommand we iterate over the
downloaded batches (command.getDownloadedBatches()) and for each one we iterate over the
readings in the batch and convert all the reading values into text.

You might also like