Filter results by

SAMI and BLE Meet WebSockets

This blog post is obsoleted by Build an Android app with BLE and ARTIK Cloud.

Previously we’ve presented WebSockets as a tool for visualizing your data or plotting your location in real-time with SAMI. In this post we enhance the Android app we built in Introducing SAMI to Your Bluetooth Low Energy Devices. This new version sends sensor data to SAMI in real-time through WebSockets.

Introduction

Introducing SAMI to Your Bluetooth Low Energy Devices describes a typical use case where SAMI acts as back-end storage for Bluetooth low energy (BLE) devices. Once the data is in SAMI, you can use the platform’s data exchange capabilities to have devices talking and working together.

The SAMInBLE app we built in the previous article makes HTTP POST calls when sending data to SAMI. We observed that Polar H7 (the BLE device used in the demo) sends heart-rate data about once per second. Health and fitness sensors typically send data at such a high frequency. In these use cases, the overhead of sending data via HTTP protocols becomes overwhelming.

The good news is that we have options. Real-time data streaming with WebSockets is one of SAMI’s most important features. We believe that, in real-world scenario, BLE devices should send data to SAMI using WebSockets to achieve better streaming performance and lower latency. This article will discuss how to implement it.

Let’s call the updated app SAMInBLEws. All information in the previous article remains valid to SAMInBLEws, except the following sections: Prepare source files and libraries and Send heart-rate data to SAMI.

We do suggest you consult the previous article for background, including the demo section.

Installation and setup

I log into the Developer Portal to create an application and obtain the client ID. For specifics, refer to the Installation and setup for SAMInBLE.

Prepare source files and libraries

My prerequisites are:

I will test SAMInBLEws on a Nexus 5 phone with Android 5.0.1, and use a Polar H7 as the BLE device to collect heart-rate data.

  1. Get SAMInBLEws from GitHub.
  2. Download and build the SAMI Android SDK libraries. The library JAR files are generated under the target and target/lib directories of the SDK Maven project. Copy all library JAR files to Application/libs of SAMInBLEws.
  3. Download and build Java WebSockets. Copy java_websocket.jar to Application/libs of SAMInBLEws.
  4. Import SAMInBLEws as an existing Android Studio project in Android Studio IDE.
  5. Use the client ID (obtained above, when registering the app in the Developer Portal) to replace YOUR CLIENT APP ID in SAMISession.java.

Now build the project, and deploy the APK to an Android phone.

Implementation

At the high level, I will replace the HTTP POST calls in SAMInBLE with WebSocket API calls when sending heart rate to SAMI. Specifically, I implement the two new functionalities on top of SAMInBLE:

  • Establish a bi-directional WebSocket pipe.
  • Send heart-rate data to SAMI through the pipe.

I still need to use REST API calls to collect the information about the users and devices. Please consult the SAMInBLE Implementation for information.

Set up a WebSocket bi-directional pipe

SAMI supports two types of WebSockets: read-only and bi-directional pipes. Since SAMInBLEws will send heart-rate data to SAMI, I must use a bi-directional WebSocket.

Below is the WebSocket URL. By setting ack to true, I can get an ACK for each heart-rate message sent. Receiving ACKs is a convenient way for me to debug the app.

public static final String SAMI_WEBSOCKET_URL = "wss://api.samsungsami.io/v1.1/websocket?ack=true";

SAMISession now has the added responsibilty of handling the WebSocket. Method connectWebsocket() opens a WebSocket and then sends the message to SAMI to register the Heart Rate Tracker device to the socket. WebsocketEvents notifies SAMISession various events like onMessage and onClose. This sample app just prints logs when responding to the events. You could optionally implement the event notification mechanism that shows WebSocket events on UI.

 1 private void connectWebsocket() {
 2     if(mWebsocket == null) {
 3         mWebsocket = new Websocket();
 4     }
 5 
 6     if(!mWebsocket.isConnecting()) {
 7         mWebsocket.connect(SAMI_WEBSOCKET_URL, new WebsocketEvents() {
 8             @Override
 9             public void onOpen(ServerHandshake handshakedata) {
10                 final String message = getWSRegisterMessage();
11                 mWebsocket.send(message);
12             }
13 
14             @Override
15             public void onMessage(String message) {
16                 Log.d(TAG, "WebSocket: onMessage(" + message + ")");
17             }
18 
19             @Override
20             public void onClose(int code, String reason, boolean remote) {
21                 Log.d(TAG, "WebSocket: onClose() code = " + code + "; reason = " + reason + "; remote = " + remote);
22              }
23 
24             @Override
25             public void onError(Exception ex) {
26                 Log.d(TAG, "WebSocket: onError() errorMsg = " + ex.getMessage());
27             }
28         });
29     }
30 }

The app asks for ACKs for each heart rate message sent to SAMI. Callback method onMessage is invoked when an ACK is returned to the app by SAMI. The method prints message ID as follows:

{"data":{"mid":"sageaeg0b740deca7671dfd9"}

In addition, SAMISession provides method disconnectWebSocket to disconnect the WebSocket.

Send heart-rate data to SAMI in real-time

After the pipe is established, it is super-easy to send heart-rate data to SAMI, thanks to Java WebSockets.

Method sendHeartRateToSami in BluetoothLeService is called every time there is new sensor data from the BLE device. I modified that method to send data using the WebSocket in contrast to making HTTP POST calls:

1 private void sendHeartRateToSami() {
2         SAMISession.getInstance().onNewHeartRate(mHeartRateForSAMI, System.currentTimeMillis());
3 }

Eventually the data is sent out in method sendViaWebsocket of SAMISession:

 1 private void sendViaWebsocket(final int heartRate, final long ts) {
 2     final String message = getWSMessage(heartRate, ts);
 3     if (mWebsocket == null) {
 4         mWebsocket = new Websocket();
 5     }
 6     if (!mWebsocket.isConnected()) {
 7         setupWebsocket();
 8     }
 9     if (mWebsocket.isConnected()) {
10         mWebsocket.send(message);
11     }
12 }

The above utility method getWSMessage assembles WebSocket messages as follows:

1 {"sdid": "<HeartRateTrackerDeviceID>", "ts": "<millisecond when heart rate is received from BLE>", data":{"heart_rate": <integer>}}

Conclusion

It is straightforward to send/receive real-time data to/from SAMI using WebSockets. Development becomes even simpler by using the vast open-source WebSocket libraries for Objective-C, Java, Node.js, C++ and more. Apps that use this awesome feature have improved streaming performance and fewer rate limits than REST. Plot Your Location in Real-Time With SAMI is another good reference for implementing WebSockets on Android.

Stay tuned for more development blog posts by joining our mailing list at http://developer.samsungsami.io/.

Also read Introducing SAMI to Your Bluetooth Low Energy Devices.

Top image: Christian Senger

Get the ARTIK Newsletter

You like your news fresh! Sign up now and you will be the first to know about our latest software releases, coding tips, upcoming events, new blog posts and more!

By providing your contact information, you agree to our Privacy Policy and Terms of Use, confirm you are an adult 18 years or older, and authorize Samsung™ ARTIK to contact you by email with information about Samsung™ ARTIK products, events, and updates for Samsung IoT Solutions. You may unsubscribe at any time by clicking the link provided in our communications.