NAV Navbar
JavaScript Node.JS Python Java (Android)

Introduction

Welcome to the Sensum Empathic AI Developer Platform.

The SensumAPI and SensumSDK enable you to build products & services that respond to emotional events in real time.

Glossary of Terms

Term Description
SensumAPI The SensumAPI is the RESTful API that is used either directly or through the SensumSDK
SensumSDK SensumSDK refers to the Android SDK

SensumAPI

Introduction

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

SensumAPI enables you to access our Empathic AI Platform, which processes data (eg. from sensors) into human-state values. Our API is designed to be RESTful, responding to HTTP requests with bodies in JSON format. All requests require that the Content-Type: application/json header be specified. SensumAPI is also cross-origin resource sharing ready.

SensumSDK handles many of these requests and responses natively. It can however be useful to use the SensumAPI directly.

URI Structure

SensumAPI uses URI resources to provide access to its services. To use a RESTful API, your application will use HTTP Methods(GET, POST, etc.) to request and parse a response. SensumAPI uses JSON for communication between your application and the server.

An example URI: https://api.sensum.co/v0/testdata

Authorization

SensumAPI uses a combination of an API Key and request signing to authorize access. You can register a new API Key by contacting us.

SensumAPI expects each call to contain the following headers to gain access:

To calculate the value for the Authorization header you must calculate a hash of your request, add extra information, then add the AWS secret key in order to create a signing key and then use this to sign the request. To learn more about generating the Signature please read the AWS Documentation on Signature v4

When using the SDK, the signature will be automatically generated when making API calls through it.

Available Metrics

Below are the metrics that SensumAPI can analyse and the units that the data is posted in

Metric Name Unit
heartrate bpm
breathingrate bpm
temperature oC, assumed to be ambient/external
skintemperature oC
gsr microsiemens*
location_latitude deg
location_longitude deg
location_altitude m
location_accuracy or location_accuracy_horizontal/vertical if available
location_speed m/s
acceleration linear acceleration in m/s2**
acceleration_x m/s2
acceleration_y m/s2
acceleration_z m/s2

* The GSR (galvanic skin response) unit of skin conductance ‘microsiemens’ is the inverse of the skin resistance; some devices return GSR as resistance in Ohms and this must be converted before upload, i.e. if a device returns values in x kOhms, the conversion is 1/(1000*x)

** All acceleration values should exclude gravity and be in m/s2

SensumAPI Analysis Responses

Input Metric(s) Generated Events Generated Records Generated Stats
any Events for that Metric Stats for that event
heartrate arousal arousal (See Fuzzy Class Stats)
gsr engagement engagement (See Fuzzy Class Stats)
acceleration_[x,y,z] activity activity (See Fuzzy Class Stats)

Events

Event Fields Type Meaning
time UTC Timestamp (ms) Time of event
value String: One of [‘normal’, ‘rising’, ‘falling’, ‘max’, ‘min’] Type of event (normal is not currently used)
severity                               Float Relative severity of the event, i.e. how much of value change between forward/backward events with respect to the average value

Stats

Stats Field Type Meaning
avg Float average (mean) value
duration Float (seconds) time between first and last analysed records
max Float max value
min Float min value
std Float standard deviation of the record
percentiles Object(dict) 10th, 50th, and 90th percentile values

Fuzzy Class Stats

For “fuzzy” classification outputs such as arousal, engagement and activity, an additional stats structure is used containing 3 fields:

Field Type Meaning
value Float [0-1] activation value
dominant string label of the dominant classification category
sectors Object(dict) per-category-label activivation i.e {label:value,...}

Current Sector Labels (highest to lowest activation value):

Send text data to analyse emoji and text sentiment

This endpoint allows users to send strings of text to our service for emotional sentiment analysis.

The service will return a JSON object that contains Positivity, Negativity and Emotionality values for emojis and text.

HTTP Request

POST https://api.sensum.co/v0/sentiment

Glossary

Term Description
positivity The level of positive emotion expressed in an input(Scale: 0 to +1)
negativity The level of negative emotion expressed in an input(Scale: 0 to +1)
emotionality The overall strength of emotion contained in an input(Scale: -1 to +1)*

Code samples

var headers = {
  'Content-Type':'application/json',
  'Authorization' : 'AWS Sig v4 Key',
  'x-api-key' : 'PublicDemoKeyForDocumentation'

};

var data = {
  "text":"👌👌👌"
};

$.ajax({
  url: 'https://api.sensum.co/v0/sentiment',
  method: 'post',
  data: JSON.stringify(data);
  headers: headers,
  success: function(data) {
    console.log(JSON.stringify(data));
  }
})
const request = require('node-fetch');

const headers = {
  'Content-Type':'application/json',
  'Authorization' : 'AWS Sig v4 Key',
  'x-api-key' : 'PublicDemoKeyForDocumentation'

};

var data = {
  "text":"👌👌👌"
};


fetch('https://api.sensum.co/v0/sentiment',
{
  method: 'POST',
  body : body,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
import requests
headers = {
  'Content-Type':'application/json',
  'Authorization' : 'AWS Sig v4 Key',
  'x-api-key' : 'PublicDemoKeyForDocumentation'
}


data = {
  "text":"👌👌👌"
}

r = requests.post('https://api.sensum.co/v0/sentiment', data=data, headers = headers)

print r.json()

Responses

Status Meaning Description
200 OK 200 response

Examples

Please refer to the code samples for request and response examples

Text Only - Unemotional

Request

{
  "text": "This is nothing"
}

Response

{
  "emoji_sentiment": null,
  "text_sentiment": {
    "emotionality": 0.0, //Aggregate Emotionality Score from -1,+1
    "negativity": 0.0, // Negativity Score from 0 to +1
    "positivity": 0.0  // Positivity Score from 0 to +1
   }
}

Text Only - Emotional

Request

{
  "text": "This was a very good test"
}

Response

{
  "emoji_sentiment": null,
  "text_sentiment": {
    "positivity": 0.444,
    "negativity": 0.0,
    "emotionality": 0.4927
  }
}

Emoji

Request

{
  "text":"👌👌👌"
}

Response

{
  "text_sentiment": {
    "negativity": 0.0,
    "positivity": 0.0,
    "emotionality": 0.0
  },
  "emoji_sentiment": {
    "positivity": 0.6575529733,
    "negativity": 0.0936431989,
    "emotionality": 0.4236068641
  }
}

Send data for events analysis

This endpoint allows the user to send data to the Empathic AI service for analysis. The response will return a series of significant events.

An event is triggered when there is a statistically significant timeseries change detected in an incoming data stream, whether that is from a Bluetooth sensor or internal sensor such as Accelerometer. Depending on the data stream applied, this can indicate a shift or change in emotional or activity state.

The severity of an event is dependent on

HTTP Request

POST https://api.sensum.co/v0/events

Code samples

var headers = {
  'Content-Type':'application/json',
  'Authorization': 'AWS_Sig v4 Key',
  'x-api-key': 'Public'

};

var data = {
    "records": {
      "heartrate": [
        {
          "time": 1502807187332,
          "value": 111.77347523527911
        },
        {
          "time": 1502807188332,
          "value": 112.89604978090439
        },
        {
          "time": 1502807189332,
          "value": 112.37719504311998
        },
        {
          "time": 1502807190332,
          "value": 113.68469103590627
        },
        {
          "time": 1502807191332,
          "value": 113.67799449012763
        },
        {
          "time": 1502807192332,
          "value": 112.71988545819869
        },
        {
          "time": 1502807193332,
          "value": 113.05775062793727
        },
        {
          "time": 1502807194332,
          "value": 114.53499763344529
        },
        {
          "time": 1502807195332,
          "value": 115.4964191594706
        },
        {
          "time": 1502807196332,
          "value": 115.31744641217797
        }
      ]
    }
  };

$.ajax({
  url: 'https://api.sensum.co/v0/events',
  method: 'post',
  data: JSON.stringify(data),
  headers: headers,
  success: function(data) {
    console.log(JSON.stringify(data));
  }
})
const request = require('node-fetch');
const inputBody = '{
    "records": {
      "heartrate": [
        {
          "time": 1502807187332,
          "value": 111.77347523527911
        },
        {
          "time": 1502807188332,
          "value": 112.89604978090439
        },
        {
          "time": 1502807189332,
          "value": 112.37719504311998
        },
        {
          "time": 1502807190332,
          "value": 113.68469103590627
        },
        {
          "time": 1502807191332,
          "value": 113.67799449012763
        },
        {
          "time": 1502807192332,
          "value": 112.71988545819869
        },
        {
          "time": 1502807193332,
          "value": 113.05775062793727
        },
        {
          "time": 1502807194332,
          "value": 114.53499763344529
        },
        {
          "time": 1502807195332,
          "value": 115.4964191594706
        },
        {
          "time": 1502807196332,
          "value": 115.31744641217797
        }
      ]
    }
  }
';
const headers = {
  'Content-Type':'application/json',
  'Authorization' : 'AWS Sig v4 Key',
  'x-api-key' : 'PublicDemoKeyForDocumentation'

};

fetch('https://api.sensum.co/v0/events',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
import requests
headers = {
  'Content-Type':'application/json',,
  'Authorization' : 'AWS Sig v4 Key',
  'x-api-key' : 'PublicDemoKeyForDocumentation'
}

data = {
    "records": {
      "heartrate": [
        {
          "time": 1502807187332,
          "value": 111.77347523527911
        },
        {
          "time": 1502807188332,
          "value": 112.89604978090439
        },
        {
          "time": 1502807189332,
          "value": 112.37719504311998
        },
        {
          "time": 1502807190332,
          "value": 113.68469103590627
        },
        {
          "time": 1502807191332,
          "value": 113.67799449012763
        },
        {
          "time": 1502807192332,
          "value": 112.71988545819869
        },
        {
          "time": 1502807193332,
          "value": 113.05775062793727
        },
        {
          "time": 1502807194332,
          "value": 114.53499763344529
        },
        {
          "time": 1502807195332,
          "value": 115.4964191594706
        },
        {
          "time": 1502807196332,
          "value": 115.31744641217797
        }
      ]
    }
  }


r = requests.post('https://api.sensum.co/v0/events', params = data, headers = headers)

print r.json()

Body parameter

{
    "records": {
      "heartrate": [
        {
          "time": 1502807187332,
          "value": 111.77347523527911
        },
        {
          "time": 1502807188332,
          "value": 112.89604978090439
        },
        {
          "time": 1502807189332,
          "value": 112.37719504311998
        },
        {
          "time": 1502807190332,
          "value": 113.68469103590627
        },
        {
          "time": 1502807191332,
          "value": 113.67799449012763
        },
        {
          "time": 1502807192332,
          "value": 112.71988545819869
        },
        {
          "time": 1502807193332,
          "value": 113.05775062793727
        },
        {
          "time": 1502807194332,
          "value": 114.53499763344529
        },
        {
          "time": 1502807195332,
          "value": 115.4964191594706
        },
        {
          "time": 1502807196332,
          "value": 115.31744641217797
        }
      ]
    }
  }

Responses

Status Meaning Description
200 OK Successful request

Response Headers

Status Header Type Format Description
200 Access-Control-Allow-Origin string

Example responses

{
    "events":{
        "heartrate":[
            {"time":1502807187000,"value":"min","severity":0.03176537181134584},
            {"time":1502807196000,"value":"max","severity":0.03176537181134584}
        ]
    },
    "stats":{
        "heartrate":{
            "avg":113.55359048765672,
            "duration":9,
            "max":115.4964191594706,
            "min":111.77347523527911,
            "std":1.175057115344551,
            "percentiles":{"10":112.3168230623359,"50":113.36787255903245,"90":115.33534368690724}}
    },
    "records":{
        "arousal":[
            {"time":1502807187332,"value":5.359549491038813e-15},
            {"time":1502807188332,"value":0.052921639437207874},
            {"time":1502807189332,"value":0.028461220785887004},
            {"time":1502807190332,"value":0.09010062973692541},
            {"time":1502807191332,"value":0.08978493383721622},
            {"time":1502807192332,"value":0.044616707881203976},
            {"time":1502807193332,"value":0.06054471797280525},
            {"time":1502807194332,"value":0.13018671519236316},
            {"time":1502807195332,"value":0.17551110237516387},
            {"time":1502807196332,"value":0.16707377298958567}
        ]
    },
    "exec_time":0.12196207046508789
}

Errors

SensumAPI uses the following error codes:

Error Code Meaning
400 Bad Request - Your Request may have caused an error
401 Unauthorized - This error will likely occur if the Cognito Authorization Header (AWS Signature v4) is either missing or invalid.
403 Forbidden -This error will likely occur if the API Key Header is either invalid or missing.
405 Method Not Allowed - You have attempted to make a request using a HTTP Method that is invalid for the requested resource.
429 Too Many Requests - You have made more requests than is allowed under the usage plan.
500 Internal Server Error - There is an error with our service
503 Service Unavailable - Our service is down for maintenance. Please try again later.

SensumSDK - Android

Android Device Compatibility

The Android version of SensumSDK can be installed on devices with 6.0 (Marshmallow) up to 8.0 (Oreo).

We recommend the Samsung S6, S7, S8, OnePlus X and above or the Google Pixel as suitable devices for reliable Bluetooth functionality.

Bluetooth Device Compatibility

Note: This document is regularly updated with new devices. Please contact us for integration details. GSR data is only accessible from Shimmer devices at present.

Accepted Biometric Data Inputs

The Android SensumSDK can accept the following metrics:

Service Constants

These constants can be used to construct message bundles that are then relayed to the Empathic AI service to send and retrieve data.

One example of a call to the service would be to send credentials in order to authenticate a user. See “Submit Credentials to service for authorization” for an example in how these bundles are constructed.

API Base URL

public static final String API_BASEURL = "api-baseurl"

This is used to pass the base url for API to the SensumSDK service which is used for setting up communication with the SensumAPI.

API Key

public static final String API_KEY = "api-key"

This is used to pass the API key to the SensumSDK service which is used for setting up communication with the SensumAPI.

Google Id Token

public static final String GOOGLE_ID_TOKEN = "google-id-token"

This is used to pass the Google id token to the SensumSDK service which is used for setting up communication with the SensumAPI.

Google Web Client Id

public static final String GOOGLE_WEB_CLIENT_ID = "google-web-client-id"

This is used to pass the Google web client id to the SensumSDK service which is used for setting up communication with the SensumAPI.

Google Login

public static final int GOOGLE_LOGIN = 126

This is used to pass a google login message to the SensumSDK service.

Login Filter

public static final String LOGIN_FILTER = "login-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for the user login.

Identity Pool Id

public static final String IDENTITY_POOL_ID = "identity-poolid"

This is used to pass the AWS identity pool id to the SensumSDK service which is used for user authentication.

Heart Rate Filter

public static final String HR_FILTER = "hr-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving the heart rate value.

Heart Rate Event Filter

public static final String HR_EVENT_FILTER = "hr-event-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving the heart rate events from the SensumAPI.

Heart Rate Arousal Filter

public static final String AROUSAL_FILTER = "arousal-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving the heart rate arousal from the SensumAPI.

GPS Filter

public static final String GPS_FILTER = "gps-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving the GPS values.

Speed Value

public static final String SPEED_VALUE = "speed-value"

This is used to pass the captured GPS speed value.

Latitude Value

public static final String LATITUDE_VALUE = "latitude-value"

This is used to pass the captured GPS latitude value.

Longitude Value

public static final String LONGITUDE_VALUE = "longtitude-value"

This is used to pass the captured GPS longitude value.

Altitude Value

public static final String ALTITUDE_VALUE = "altitude-value"

This is used to pass the captured GPS altitude value.

Bearing Value

public static final String BEARING_VALUE = "bearing-value"

This is used to pass the captured GPS bearing value

Accuracy Value

public static final String ACCURACY_VALUE = "accuracy-value"

This is used to pass the captured GPS accuracy value.

GPS Event Filter

public static final String GPS_EVENT_FILTER = "gps-event-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving the GPS events from the SensumAPI.

Accelerometer Filter

public static final String ACC_FILTER = "acc-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving the accelerometer values.

X Value

public static final String X_VALUE = "x-value"

This is used to pass the captured accelerometer x value.

Y Value

public static final String Y_VALUE = "y-value"

This is used to pass the captured accelerometer y value

Z Value

public static final String Z_VALUE = "z-value"

This is used to pass the captured accelerometer z value.

Accelerometer Event Filter

public static final String ACC_EVENT_FILTER = "acc-event-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving the accelerometer events from the SensumAPI.

Accelerometer Registration

public static final String ACC_FAILED_REGISTERED = "accelerometer-registration"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for checking accelerometer registration.

GSR Filter

public static final String GSR_FILTER = "gsr-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving the GSR values.

GSR Event Filter

public static final String GSR_EVENT_FILTER = "gsr-event-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving the GSR events from the SensumAPI.

Extra Data

public static final String EXTRA_DATA = "extra-data"

This is used to bundle up extra data to the intents.

Acceleration Capture

public static final String ACCELERATION_CAPTURE = "acceleration-capture"

This is used to enable/disable capturing of accelerometer data that is sent to the SensumAPI.

GPS Capture

public static final String GPS_CAPTURE = "gps-capture"

This is used to enable/disable capturing of GPS data that is sent to the SensumAPI.

HR Capture

public static final String HR_CAPTURE = "heartrate-capture"

This is used to enable/disable capturing of heart rate data that is sent to the SensumAPI.

Input Capture

public static final String INPUT_CAPTURE = "input-capture"

This is used to enable/disable capturing of text/emoji data that is sent to the SensumAPI.

GSR Capture

public static final String GSR_CAPTURE = "gsr-capture"

This is used to enable/disable capturing of GSR data that is sent to the SensumAPI.

Data Rate Send

public static final String DATA_RATE_SEND = "send-rate"

This is used to pass the interval rate (in milliseconds) for the data to be sent to the SensumAPI.

API Response

public static final String API_RESPONSE = "api-response"

This is used to pass message from the SensumSDK service for the SensumAPI response.

Toast Message

public static final String TOAST_MESSAGE = "toast-message"

This is used to pass informative toast message from the SensumSDK service.

Input Sentiment Text

public static final int INPUT_SENTIMENT_TEXT = 128

This is used to filter/pass text & emoji message for sentiment analysis to the SensumSDK service.

Emoji Sentiment Filter

public static final String EMOJI_SENTIMENT_FILTER = "emoji-sentiment-filter"

This is used to pass Emoji value to the SensumSDK service which is passed to the API for Sentiment analysis.

Text Sentiment Filter

public static final String TEXT_SENTIMENT_FILTER = "text-sentiment-filter"

This is used to pass Text value to the SensumSDK service which is passed to the API for Sentiment analysis.

Emotionality

public static final String EMOTIONALITY = "emotionality"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving Emotionality value (Sentiment Analysis) from the SensumAPI

Positivity

public static final String POSITIVITY = "positivity"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving Positivity value (Sentiment Analysis) from the SensumAPI

Negativity

public static final String NEGATIVITY = "negativity"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for receiving Negativity value (Sentiment Analysis) from the SensumAPI

Cancel Capture

public static final int CANCEL_CAPTURE = 112

This is used to cancel sending of the captured data to the SensumAPI

Start Capture

public static final int START_CAPTURE = 113

This is used to start sending of the captured data to the SensumAPI

Hello

public static final int HELLO = 127

This is used for the initial communication between developer and frontend to demo how it works

Hello Filter

public static final String HELLO_FILTER = "hello-filter"

This is used to filter for hello at the front end

Device Name

public static final String DEVICE_NAME = "device-name"

This is used to get the connected device name

Device Address

public static final String DEVICE_ADDRESS = "device-address"

This is used to get the connected device address

Connection

public static final String CONNECTION = "connection"

This is used to pass a connection message from the SensumSDK service to the front end

BLE Scan

public static final int BLE_SCAN = 102

This is used to pass a BLE scan message to the SensumSDK service

Connect BLE Device

public static final int CONNECT_BLE = 101

This is used to pass a connect BLE device message to the SensumSDK service

BLE Connection Filter

public static final String BLE_CONNECTION_FILTER = "ble-connected-filter"

This is used to pass a BLE connection message from the SensumSDK service which is used as an intent filter at the front end

BLE Device Filter

public static final String BLE_DEVICE_FILTER = "ble-filter"

This is used to pass a message from the SensumSDK service which is used as an intent filter at the front end for the connected ble device

BLE Device Name

public static final String BLE_DEVICE_NAME = "ble-device-name"

This is used to pass the BLE device name from the SensumSDK service

Disconnect BLE Device

public static final int DISCONNECT_BLE = 134

This is used to disconnect a BLE device

BLE Connectivity

public static final String BLE_CONNECTIVITY = "ble-connectivity"

This is used to pass a BLE connectivity message from the SensumSDK service to the front end

Connected Devices

public static final int CONNECTED_DEVICES = 136

This is used to pass a message to the SensumSDK to get the connected device names

Connected Devices Filter

public static final String CONNECTED_DEVICES_FILTER = "connected-devices-filter"

This is used to filter for the connected devices

Bluetooth Device Name

public static final String BLUETOOTH_DEVICE_NAME = "bluetooth-device-name"

This is used to pass the bluetooth device name from the SensumSDK service

Bluetooth Scan

public static final int BLUETOOTH_SCAN = 107

This is used to pass a bluetooth scan message to the SensumSDK service

Disconnect Bluetooth Device

public static final int DISCONNECT_BLUETOOTH = 135

This is used to disconnect a bluetooth device

Connect Bluetooth Device

public static final int CONNECT_BLUETOOTH_DEVICE = 108

This is used to pass a connect bluetooth device message to the SensumSDK service

Bluetooth Connectivity

public static final String BT_CONNECTIVITY = "bt-connectivity"

This is used to pass a bluetooth connectivity message from the SensumSDK service to the front end

Bluetooth Connection Filter

public static final String BLUETOOTH_CONNECTION_FILTER = "bluetooth-connected-filter"

This is used to filter for bluetooth connection at the front end

Bluetooth Device Filter

public static final String BLUETOOTH_DEVICE_FILTER = "bluetooth-device-filter"

This is used to filter for bluetooth device at the front end

Device Disconnected

public static final String DEVICE_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED"

This is used to pass a message from the SensumSDK service in case of any device disconnection

Realm Response

public static final String REALM_RESPONSE = "realm-response"

This is used to pass message from the SensumSDK service for data manipulation in realm for a session

Example Methods

Examples available in the ‘Android’ tab.

Initiate connection to service

      // class fields
    Messenger mServiceMessenger;
    SdkService mService;
    boolean mIsBound;

    private final ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            SdkService.LocalBinder binder = (SdkService.LocalBinder) iBinder;
            mService = binder.getService();
            mServiceMessenger = mService.mServiceMessenger;
            if (!mIsBound) {
                mIsBound = true;
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            // handle disconnect
        }
    };

private final ServiceConnection mConnection = new ServiceConnection()

Connection made to the service. Once bound to the service, the binder object is passed through to messenger to set it up.

Submit Credentials to service for authorization (Google Sign-In)

    void submit() {
        Bundle bundle = new Bundle();
        bundle.putString(API_BASEURL, apiBaseUrl);
        bundle.putString(API_KEY, apiKey);
        bundle.putString(IDENTITY_POOL_ID, identityPoolId);
        bundle.putString(GOOGLE_ID_TOKEN, googleIdToken);
        bundle.putString(GOOGLE_WEB_CLIENT_ID, googleWebClientId);
        sendToService(bundle, GOOGLE_LOGIN);
    }

Follow Google’s instructions to add Google Sign-In to your application.

Once successfully implemented you must send the Google Id token for the Google Sign-In application to us to authenticate access. You can contact us at hello@sensum.co.

void submit()

Sets up the credential bundle to be sent to the SensumSDK service this needs to be sent first to the SensumSDK service as only authenticated users can use the service.

Send a data message to the service

    public void sendToService(Bundle bundle, int argValue) {
        Message message = Message.obtain();
        message.arg1 = argValue;
        message.setData(bundle);
        try {
            mServiceMessenger.send(message);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

public void sendToService(Bundle bundle, int argValue)

Send message to the service.

Create New Broadcast Receiver Object

     private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {

                case HELLO_FILTER:
                    Toast.makeText(MainActivity.this, intent.getStringExtra(EXTRA_DATA), Toast.LENGTH_LONG).show();
                    break;
                case GPS_FILTER:
                    Bundle gpsBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case ACC_FILTER:
                    Bundle accBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case HR_FILTER:
                    String hrValue = intent.getStringExtra(EXTRA_DATA);
                    break;
                case GSR_FILTER:
                    String gsrValue = intent.getStringExtra(EXTRA_DATA);
                    break;
                case API_RESPONSE:
                    String apiResponse = intent.getStringExtra(EXTRA_DATA);
                    break;
                case TOAST_MESSAGE:
                    String toastMessage = intent.getStringExtra(EXTRA_DATA);
                    break;
                case EMOJI_SENTIMENT_FILTER:
                    Bundle emojiSentimentBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case TEXT_SENTIMENT_FILTER:
                    Bundle textSentimentBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case CONNECTED_DEVICES_FILTER:
                    String btDeviceName = intent.getStringExtra(ServiceConstants.BLUETOOTH_DEVICE_NAME);
                    break;
                case BLE_DEVICE_FILTER:
                    ArrayList<BluetoothDevice> bledeviceList = intent.getParcelableArrayListExtra
                            (EXTRA_DATA);
                    for (BluetoothDevice bleDevice: bledeviceList) {
                        Log.d("BleDevice", bleDevice.getName() + " " + bleDevice.getAddress());
                    }
                    break;
                case BLUETOOTH_DEVICE_FILTER:
                    ArrayList<BluetoothDevice> bluetoothDevices = intent.getParcelableArrayListExtra(EXTRA_DATA);
                    for (BluetoothDevice bluetoothDevice : bluetoothDevices) {
                        Log.d("BluetoothDevice", bluetoothDevice.getName() + " " + bluetoothDevice
                                .getAddress());
                    }
                    break;
            }
        }
    };

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver()

Broadcast receiver with the list of registered filters.

Update IntentFilter with new Actions

    private IntentFilter updateIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();

        intentFilter.addAction(HELLO_FILTER);
        intentFilter.addAction(GPS_FILTER);
        intentFilter.addAction(ACC_FILTER);
        intentFilter.addAction(HR_FILTER);
        intentFilter.addAction(GSR_FILTER);
        intentFilter.addAction(API_RESPONSE);
        intentFilter.addAction(TOAST_MESSAGE);
        intentFilter.addAction(HR_EVENT_FILTER);
        intentFilter.addAction(AROUSAL_FILTER);
        intentFilter.addAction(GSR_EVENT_FILTER);
        intentFilter.addAction(EMOJI_SENTIMENT_FILTER);
        intentFilter.addAction(TEXT_SENTIMENT_FILTER);
        intentFilter.addAction(CONNECTED_DEVICES_FILTER);
        return intentFilter;
    }

private IntentFilter updateIntentFilter()

Start Biometric Data Capture

    private void startCaptureSetUp() {
        sendToService(getCaptureBundle(), START_CAPTURE);
    }

private void startCaptureSetUp()

Starts capturing of biometric/contextual data.

Get Capture Bundle

    private Bundle getCaptureBundle() {
        Bundle bundle = new Bundle();
        bundle.putBoolean(ACCELERATION_CAPTURE, true);
        bundle.putBoolean(HR_CAPTURE, true); 
        bundle.putBoolean(GPS_CAPTURE, true); 
        bundle.putBoolean(GSR_CAPTURE, true); 
        bundle.putBoolean(INPUT_CAPTURE, true);
        bundle.putLong(DATA_RATE_SEND, 20 * 1000);
        return bundle;
    }

private Bundle getCaptureBundle()

Sets up the bundle data for capture using the service constants.

Stop Biometric Data Capture

    private void stopCaptureSetUp() {
        sendToService(getCaptureBundle(), CANCEL_CAPTURE);
    }

private void stopCaptureSetUp()

Stops capturing of biometric/contextual data.

Tutorial - Android SDK

Introduction

This tutorial is designed to assist Android Developers working with the SensumSDK and SensumAPI.

It is intended to provide a detailed guide to using the Sensum Emotion AI toolkit, providing code examples and guidelines for use.

Have fun and enjoy!

Requirements

Getting Started

Figure 1 - Start a new Android Studio project

Figure 1 - Start New Project


Figure 2 - Create New Project

Figure 2 - Create New Project


Figure 3 - Select Platforms

Figure 3 - Select Platforms


Figure 4 - Add Activity

Figure 4 - Add Activity


Figure 5 - Customize the Activity

Figure 5 - Customize the Activity


Managing Module Dependencies

 Figure 6 - New Module

Figure 6 - Creating A New Module


 Figure 7 - Import .JAR/.AAR Package

Figure 7 - Import .JAR/.AAR Package


 Figure 8 - Create New Module

Figure 8 - Create New Module


Figure 9 - Project Structure

Figure 9 - Project Structure


Figure 10 - Module Dependency

Figure 10 - Module Dependency


Figure 11 - Choose Modules

Figure 11 - Choose Modules


Implementing the Shimmer library for GSR values

Including Permissions

Code Snippet 1

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

Creating a Service

Code Snippet 2

    // class fields
    Messenger mServiceMessenger;
    SdkService mService;
    boolean mIsBound;

    private final ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            SdkService.LocalBinder binder = (SdkService.LocalBinder) iBinder;
            mService = binder.getService();
            mServiceMessenger = mService.mServiceMessenger;
            if (!mIsBound) {
                mIsBound = true;
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            // handle disconnect
        }
    };

Code Snippet 3

        <service android:name="co.sensum.sensumservice.SDK.SdkService"/>
        <service android:name="co.sensum.sensumservice.SDK.BLE.BluetoothLeService"/>
    </application>

Binding and Unbinding the Service

Code Snippet 4

@Override
protected void onStart() {
    super.onStart();
    Intent intent = new Intent(this, SdkService.class);
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

Code Snippet 5

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mIsBound) {
        unbindService(mConnection);
        mIsBound = false;
    }
}

Using a Broadcast Receiver

Table 1: Broadcast Receiver Filters

Action Description IntentExtras
BLE_DEVICE_FILTER Filters for BLE devices ArrayList<BluetoothDevice>
HR_FILTER Filters for heart rate value String
GPS_FILTER Filters for GPS values Bundle
ACC_FILTER Filters for acceleration values Bundle
DEVICE_DISCONNECTED Filters for a device disconnected value null
API_RESPONSE Filters for responses from the SensumAPI String
TOAST_MESSAGE Filters for messages from the Service String
BLE_CONNECTION_FILTER Filters for connection BLE messages String
BLUETOOTH_CONNECTION_FILTER Filters for bluetooth connection messages String
BLUETOOTH_DEVICE_FILTER Filters for bluetooth devices ArrayList<BluetoothDevice>
GSR_FILTER Filters for GSR values String
ACC_FAILED_REGISTERED Filters for acceleration failure from unsupported devices null
HELLO_FILTER Filters for hello message String
HR_EVENT_FILTER Filters for heart rate events from the SensumAPI String
AROUSAL_FILTER Filters for heart rate arousals from the SensumAPI String
GSR_EVENT_FILTER Filters for GSR events from the SensumAPI String
EMOJI_SENTIMENT_FILTER Filters for emoji sentiment from the SensumAPI String
TEXT_SENTIMENT_FILTER Filters for text sentiment from the SensumAPI String
CONNECTED_DEVICES_FILTER Filters for connected devices String

Setting up the Broadcast Receiver

Code Snippet 6

    private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case HELLO_FILTER:
                    Toast.makeText(MainActivity.this, intent.getStringExtra(EXTRA_DATA), Toast.LENGTH_LONG).show();
                    break;
                case GPS_FILTER:
                    Bundle gpsBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case ACC_FILTER:
                    Bundle accBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case HR_FILTER:
                    String hrValue = intent.getStringExtra(EXTRA_DATA);
                    break;
                case GSR_FILTER:
                    String gsrValue = intent.getStringExtra(EXTRA_DATA);
                    break;
                case API_RESPONSE:
                    String apiResponse = intent.getStringExtra(EXTRA_DATA);
                    break;
                case TOAST_MESSAGE:
                    String toastMessage = intent.getStringExtra(EXTRA_DATA);
                    break;
                case EMOJI_SENTIMENT_FILTER:
                    Bundle emojiSentimentBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case TEXT_SENTIMENT_FILTER:
                    Bundle textSentimentBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case CONNECTED_DEVICES_FILTER:
                    String btDeviceName = intent.getStringExtra(ServiceConstants.BLUETOOTH_DEVICE_NAME);
                    break;
                case BLE_DEVICE_FILTER:
                    ArrayList<BluetoothDevice> bledeviceList = intent.getParcelableArrayListExtra
                            (EXTRA_DATA);
                    for (BluetoothDevice bleDevice: bledeviceList) {
                        Log.d("BleDevice", bleDevice.getName() + " " + bleDevice.getAddress());
                    }
                    break;
                case BLUETOOTH_DEVICE_FILTER:
                    ArrayList<BluetoothDevice> bluetoothDevices = intent.getParcelableArrayListExtra(EXTRA_DATA);
                    for (BluetoothDevice bluetoothDevice : bluetoothDevices) {
                        Log.d("BluetoothDevice", bluetoothDevice.getName() + " " + bluetoothDevice
                                .getAddress());
                    }
                    break;
            }
        }
    };

Code Snippet 7

 @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(mMessageReceiver, getUpdateIntentFilter());
    }

Code Snippet 8

  private IntentFilter getUpdateIntentFilter() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(HELLO_FILTER);
        filter.addAction(GPS_FILTER);
        filter.addAction(ACC_FILTER);
        filter.addAction(HR_FILTER);
        filter.addAction(GSR_FILTER);
        filter.addAction(API_RESPONSE);
        filter.addAction(TOAST_MESSAGE);
        filter.addAction(HR_EVENT_FILTER);
        filter.addAction(AROUSAL_FILTER);
        filter.addAction(GSR_EVENT_FILTER);
        filter.addAction(EMOJI_SENTIMENT_FILTER);
        filter.addAction(TEXT_SENTIMENT_FILTER);
        filter.addAction(CONNECTED_DEVICES_FILTER);
        filter.addAction(BLE_DEVICE_FILTER);
        filter.addAction(BLE_CONNECTION_FILTER);
        filter.addAction(BLUETOOTH_DEVICE_FILTER);
        return filter;
    }

Code Snippet 9

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mIsBound){
            unbindService(mConnection);
            mIsBound = false;
            unregisterReceiver(mMessageReceiver);
        }
    }

Communicating with the Service

Table 2: Send to Service Commands

Constants (of type ‘Int’) Required Bundle Data
CONNECT_BLE String DEVICE_NAME,
String DEVICE_ADDRESS
BLE_SCAN null
START_CAPTURE boolean ACCELERATION_CAPTURE,
boolean HR_CAPTURE,
boolean GPS_CAPTURE,
boolean GSR_CAPTURE,
boolean INPUT_CAPTURE,
int DATA_RATE_SEND
CANCEL_CAPTURE boolean ACCELERATION_CAPTURE,
boolean HR_CAPTURE,
boolean GPS_CAPTURE,
boolean GSR_CAPTURE,
boolean INPUT_CAPTURE
GOOGLE_LOGIN String API_BASEURL,
String API_KEY,
String IDENTITY_POOL_ID,
String GOOGLE_ID_TOKEN,
String GOOGLE_WEB_CLIENT_ID
BLUETOOTH_SCAN null
CONNECT_BLUETOOTH_DEVICE String DEVICE_NAME,
String DEVICE_ADDRESS
HELLO null
INPUT_SENTIMENT_TEXT String TEXT_MESSAGE
DISCONNECT_BLE null
DISCONNECT_BLUETOOTH null
CONNECTED_DEVICES null

Code Snippet 10

   public void sendToService(Bundle bundle, int argValue){
        Message message = Message.obtain();
        message.arg1 = argValue;
        message.setData(bundle);
        try {
            mServiceMessenger.send(message);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

Interacting with the Service

Code Snippet 11

  private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case HELLO_FILTER:
                    Toast.makeText(MainActivity.this, intent.getStringExtra(EXTRA_DATA), Toast.LENGTH_LONG).show();
                    break;
                case GPS_FILTER:
                    Bundle gpsBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case ACC_FILTER:
                    Bundle accBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case HR_FILTER:
                    String hrValue = intent.getStringExtra(EXTRA_DATA);
                    break;
                case GSR_FILTER:
                    String gsrValue = intent.getStringExtra(EXTRA_DATA);
                    break;
                case API_RESPONSE:
                    String apiResponse = intent.getStringExtra(EXTRA_DATA);
                    break;
                case TOAST_MESSAGE:
                    String toastMessage = intent.getStringExtra(EXTRA_DATA);
                    break;
                case EMOJI_SENTIMENT_FILTER:
                    Bundle emojiSentimentBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case TEXT_SENTIMENT_FILTER:
                    Bundle textSentimentBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case CONNECTED_DEVICES_FILTER:
                    String btDeviceName = intent.getStringExtra(ServiceConstants.BLUETOOTH_DEVICE_NAME);
                    break;
                case BLE_DEVICE_FILTER:
                    ArrayList<BluetoothDevice> bledeviceList = intent.getParcelableArrayListExtra
                            (EXTRA_DATA);
                    Log.d(TAG, "onReceive: " + bledeviceList.size());
                    for (BluetoothDevice bleDevice: bledeviceList) {
                        Log.d("BleDevice", bleDevice.getName() + " " + bleDevice.getAddress());
                    }
                    break;
               case BLUETOOTH_DEVICE_FILTER:
                    ArrayList<BluetoothDevice> bluetoothDevices = intent.getParcelableArrayListExtra(EXTRA_DATA);
                    for (BluetoothDevice bluetoothDevice : bluetoothDevices) {
                        Log.d("BluetoothDevice", bluetoothDevice.getName() + " " + bluetoothDevice
                                .getAddress());
                    }
                    break;
            }
        }
    };

Code Snippet 12

Button button = (Button) findViewById(R.id.hello_button);
button.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
       sendToService(null, HELLO);
   }
});

Setting up BLE

Code Snippet 13

Button button = (Button) findViewById(R.id.scanButton);
button.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
       sendToService(null, BLE_SCAN);
   }
});

Receiving BLE Devices

Connecting a BLE Device

Code Snippet 14

Bundle bundle =  new Bundle();
bundle.putString(DEVICE_NAME, deviceName);
bundle.putString(DEVICE_ADDRESS, deviceAddress);
sendToService(bundle, CONNECT_BLE);

Receiving Values

Setting up Bluetooth

Receiving GPS and Acceleration Values

Table 3: Broadcast Receiver Filter Examples

Filter Bundle Constants Example Method Call
GPS Filter Float speed SPEED_VALUE gpsBundle.getFloat(SPEED_VALUE)
Double latitude LATITUDE_VALUE gpsBundle.getFloat(LATITUDE_VALUE)
Double longitude LONGITUDE_VALUE gpsBundle.getFloat(LONGITUDE_VALUE)
Double altitude ALTITUDE_VALUE gpsBundle.getFloat(ALTITUDE_VALUE)
Float bearing BEARING_VALUE gpsBundle.getFloat(BEARING_VALUE)
Float accuracy ACCURACY_VALUE gpsBundle.getFloat(ACCURACY_VALUE)
ACC_FILTER Float x X_VALUE accBundle.getFloat(X_VALUE)
Float y Y_VALUE accBundle.getFloat(Y_VALUE)
Float z Z_VALUE accBundle.getFloat(Z_VALUE)

Capturing Data

Code Snippet 15

public Bundle getCaptureBundle() {
        Bundle bundle = new Bundle();
        bundle.putBoolean(ServiceConstants.ACCELERATION_CAPTURE, true);
        bundle.putBoolean(ServiceConstants.HR_CAPTURE, true);
        bundle.putBoolean(ServiceConstants.GPS_CAPTURE, true);
        bundle.putBoolean(ServiceConstants.GSR_CAPTURE, true);
        bundle.putBoolean(ServiceConstants.INPUT_CAPTURE, true);
        bundle.putLong(ServiceConstants.DATA_RATE_SEND, 1000);
        return bundle;
    }
}

Code Snippet 16

sendToService(getCaptureBundle(), START_CAPTURE);
...
sendToService(getCaptureBundle(), CANCEL_CAPTURE);

Receiving Values from SensumAPI

Table 4: Additional Broadcast Receiver Filters

Action (description) Intent Extras
HR_EVENT_FILTER Filters for heart rate events null
ACC_EVENT_FILTER Filters for acceleration events null
AROUSAL_FILTER Filters for arousal events null
GPS_EVENT_FILTER Filters for GPS events null
GSR_EVENT_FILTER Filters for GSR events null
EMOJI_SENTIMENT_FILTER Filters for Emoji Sentiment values Bundle
TEXT_SENTIMENT_FILTER Filters for Text Sentiment values Bundle

Code Snippet 17

private IntentFilter getUpdateIntentFilter() {
      IntentFilter filter = new IntentFilter();
        filter.addAction(HELLO_FILTER);
        filter.addAction(GPS_FILTER);
        filter.addAction(ACC_FILTER);
        filter.addAction(HR_FILTER);
        filter.addAction(GSR_FILTER);
        filter.addAction(API_RESPONSE);
        filter.addAction(TOAST_MESSAGE);
        filter.addAction(HR_EVENT_FILTER);
        filter.addAction(AROUSAL_FILTER);
        filter.addAction(GSR_EVENT_FILTER);
        filter.addAction(EMOJI_SENTIMENT_FILTER);
        filter.addAction(TEXT_SENTIMENT_FILTER);
      return filter;
  }

Realm Queries

Code Snippet 18

private void queryRealmForArousalStats() {
   try {
       Realm.init(this);
       Realm realm = Realm.getDefaultInstance().getDefaultInstance();
       RealmResults<ArousalStats> realmResults = realm.where(ArousalStats.class).findAll();
       realmResults.load();
       if (!realmResults.isEmpty()) {
           for (ArousalStats realmRecords : realmResults) {
               updateArousalStats(realmRecords);
           }
       } else {
           Log.d(TAG, "No arousal stats data found in the database");
       }
   } catch (Throwable e) {
       Log.d(TAG, "Unable to get arousal stats data from the database " + e.toString());
   }
}

private void updateArousalStats(ArousalStats arousalStats) {
   ArousalSectors arousalSectors = arousalStats.getArousalSectors();
   double activated = arousalSectors.getActivated();
   double calm = arousalSectors.getCalm();
   double excited = arousalSectors.getExcited();
   double passive = arousalSectors.getPassive();
   double relaxed = arousalSectors.getRelaxed();
}

Table 5: Example Event Realm Object

Object Associated Methods Method Type Description
ResHeartRate Events associated with Heart Rate getValue() String Retrieves a value associated with the event event - min, max, normal, rising, falling
getTime() long Event time
getSeverity() double How much of value change between forward/backward events with respect to the average value

Table 6: SensumSDK Realm Objects

Objects
ResAccelerometerX
ResAccelerometerY
ResAccelerometerZ
ResGpsAccuracy
ResGpsAltitude
ResGpsBearing
ResGpsLatitude
ResGpsLongitude
ResGpsSpeed
ResGSR
ResHeartRateTestData

Table 7: Example Statistics Object

Object Associated Methods Method Type Description
HeartRateStats getAvg() Double Returns an average value
getDuration() Double Returns duration value
getMax() Double Returns max value
getMin() double Returns min value
getPercentiles() Percentiles Returns a percentile object (see Table 9)
getStd() Double Returns a standard deviation value

Table 8: SensumSDK Statistics Objects

Objects
AccelerometerXStats
AccelerometerYStats
AccelerometerZStats
GpsAccuracyStats
GpsAltitudeStats
GpsBearingStats
GpsLatitudeStats
GpsLongitudeStats
GpsSpeedStats
GsrStats

Table 9: SensumSDK Percentiles Object

Object Associated Methods Type Description
Percentiles get10() double Returns 10th percentile value
get50() double Returns 50th percentile value
get90() double Returns 90th percentile value

Table 10: ArousalStats Realm Object

Object Associated Methods Type Description
ArousalStats getValue() double Returns an activation value
getDominant() String Label of the dominant classification category
getSectors() ArousalSectors Returns the sectors associated with the arousal stats object (Table 11)

Table 11: ArousalSectors Realm Object

Object Associated Methods Type Description
ArousalSectors getExcited() double Returns a value associated with excitement
getActivated() double Returns a value associated with activity
getCalm() double Returns a value associated with calmness
getPassive() double Returns a value associated with passiveness
getRelaxed() double Returns a value associated with relaxation

Table 12: EngagementStats Realm Object

Object Associated Methods Type Description
EngagementStats getValue() double Returns an activation value
getDominant() String Label of the dominant classification category
getSectors() EngagementSectors Returns the sectors associated with the engagement stats object (Table 13)

Table 13: EngagmentSectors Realm Object

Object Associated Methods Type Description
EngagmentSectors getHighlyEngaged() double Returns a value associated with highly engaged
getEngaged() double Returns a value associated with engaged
getActivated() double Returns a value associated with activiated
getNeutral() double Returns a value associated with neutral

Table 14: Sentiment Filter Data

Object Type Description
EMOTIONALITY double Returns a value associated with emotionality
POSITIVITY double Returns a value associated with positivity
NEGATIVITY double Returns a value associated with negativity

Table 15: ActivityStats Realm Object

Object Associated Methods Type Description
ActivityStats getValue() double Returns an activation value
getDominant() String Label of the dominant classification category
getSectors() ActivitySectors Returns the sectors associated with the activity stats object (Table 16)

Table 16: ActivitySectors Realm Object

Object Associated Methods Type Description
ActivitySectors getActive() double Returns a value associated with active
getInactive() double Returns a value associated with inactive

Google Sign-In

Code Snippet 19

implementation 'com.google.android.gms:play-services-auth:11.0.4'

Code Snippet 20

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
       .requestEmail()
       .requestProfile()
       .requestIdToken(googleWebClientId)
       .requestServerAuthCode(googleWebClientId)
       .requestId()
       .build();

GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
       .enableAutoManage(this, this )
       .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
       .build();

Code Snippet 21

Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient);
this.startActivityForResult(signInIntent, RC_SIGN_IN);

Bundle Parameters

Parameter Type Description
apiBaseUrl String This is the base url for the API, currently this is http://emotionai.sensum.co/v0
apiKey String This is the API Key that will be required to access the SensumAPI(For trial usage use PublicDemoKeyForDocumentation)
identityPoolId String The CognitoIdentityPoolId required to successfully authenticate with the SensumAPI. We will provide you with this.
googleIdToken String This is the google id token returned when successfully logged in with a valid Google account
googleWebClientId                                                            String This is the web client id that was created when you set up sign-in with Google. It can be found in the Credentials page under 'APIs and Service’ in the Google Cloud Platform page

Code Snippet 22

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);
   if (requestCode == RC_SIGN_IN) {
       GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
       GoogleSignInAccount acct = result.getSignInAccount();
       String googleIdToken = acct.getIdToken();
       Bundle bundle = new Bundle();
       bundle.putString(API_BASEURL, apiBaseUrl);
       bundle.putString(API_KEY, apiKey);
       bundle.putString(IDENTITY_POOL_ID, identityPoolId);
       bundle.putString(GOOGLE_ID_TOKEN, googleIdToken);
       bundle.putString(GOOGLE_WEB_CLIENT_ID, googleWebClientId);
       sendToService(bundle, GOOGLE_LOGIN);
   }
}

Gradle Dependencies

Code Snippet 23

    classpath "io.realm:realm-gradle-plugin:4.2.0"
    allprojects {
    repositories {
        maven { url  "http://dl.bintray.com/shimmerengineering/Shimmer" }
        google()
    }
}

Code Snippet 24

    compile 'com.amazonaws:aws-android-sdk-core:2.6.18'
    compile 'com.amazonaws:aws-android-sdk-s3:2.6.18'
    compile 'com.amazonaws:aws-android-sdk-cognito:2.6.18'
    compile 'com.amazonaws:aws-android-sdk-ddb:2.6.18'
    compile 'com.amazonaws:aws-android-sdk-cognitoidentityprovider:2.6.18'
    compile 'com.squareup.retrofit2:retrofit:2.4.0'
    compile 'com.squareup.retrofit2:converter-moshi:2.4.0'
    compile 'com.squareup.moshi:moshi:1.5.0'
    compile 'com.squareup.okhttp3:okhttp:3.10.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.10.0'
    compile 'com.google.code.gson:gson:2.8.0'
    compile 'com.google.guava:guava:19.0'
    compile 'com.shimmerresearch.managers.bluetoothmanager:ShimmerBluetoothManager:0.9.33beta'
    compile 'com.shimmerresearch.driver:ShimmerDriver:0.9.120beta'

Summary Guide

API Control

Setting Data Sending Request Rate to the API

Android

When using the sendToService method ensure that you send the integer parameters DATA_RATE_SEND as part of your bundle.

Listen for API events

Android

Use a Broadcast Receiver

Table 1

Action Description IntentExtras
BLE_DEVICE_FILTER Filters for BLE devices ArrayList<BluetoothDevice>
HR_FILTER Filters for heart rate value String
GPS_FILTER Filters for GPS values Bundle
ACC_FILTER Filters for acceleration values Bundle
DEVICE_DISCONNECTED Filters for a device disconnected value null
API_RESPONSE Filters for responses from the API String
TOAST_MESSAGE Filters for messages from the Service String
BLE_CONNECTION_FILTER Filters for connection BLE messages String
BLUETOOTH_CONNECTION_FILTER Filters for bluetooth connection messages String
BLUETOOTH_DEVICE_FILTER Filters for bluetooth devices ArrayList<BluetoothDevice>
GSR_FILTER Filters for GSR values String
ACC_FAILED_REGISTERED Filters for acceleration failure from unsupported devices null
HELLO_FILTER Filters for hello message String
HR_EVENT_FILTER Filters for heart rate events from the API String
AROUSAL_FILTER Filters for heart rate arousals from the API String
GSR_EVENT_FILTER Filters for GSR events from the API String
EMOJI_SENTIMENT_FILTER Filters for emoji sentiment from the API String
TEXT_SENTIMENT_FILTER Filters for text sentiment from the API String

Setting up the Broadcast Receiver

Code Snippet 1

    private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action){
                case HELLO_FILTER:
                    Toast.makeText(MainActivity.this, intent.getStringExtra(EXTRA_DATA), Toast.LENGTH_LONG).show();
                    break;
                case GPS_FILTER:
                    Bundle gpsBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case ACC_FILTER:
                    Bundle accBundle = intent.getBundleExtra(EXTRA_DATA);
                    break;
                case HR_FILTER:
                    String hrValue = intent.getStringExtra(EXTRA_DATA);
                    break;
                case GSR_FILTER:
                    String gsrValue = intent.getStringExtra(EXTRA_DATA);
                    break;
                case API_RESPONSE:
                    String apiResponse = intent.getStringExtra(EXTRA_DATA);
                    break;
                case TOAST_MESSAGE:
                    String toastMessage = intent.getStringExtra(EXTRA_DATA);
                    break;
               case HR_EVENT_FILTER:
                   Break;
               case AROUSAL_FILTER:
                   break;
               case GSR_EVENT_FILTER:
                   break;
               case EMOJI_SENTIMENT_FILTER:
                   Bundle emojiSentimentBundle = intent.getBundleExtra(EXTRA_DATA);
                   break;
               case TEXT_SENTIMENT_FILTER:
                   Bundle textSentimentBundle = intent.getBundleExtra(EXTRA_DATA);
                   break;
            }
        }
    };

Code Snippet 5

 @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(mMessageReceiver, getUpdateIntentFilter());
    }

Code Snippet 3

  private IntentFilter getUpdateIntentFilter() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(HELLO_FILTER);
        filter.addAction(GPS_FILTER);
        filter.addAction(ACC_FILTER);
        filter.addAction(HR_FILTER);
        filter.addAction(GSR_FILTER);
        filter.addAction(API_RESPONSE);
        filter.addAction(TOAST_MESSAGE);
        filter.addAction(HR_EVENT_FILTER);
        filter.addAction(AROUSAL_FILTER);
        filter.addAction(GSR_EVENT_FILTER);
        filter.addAction(EMOJI_SENTIMENT_FILTER);
        filter.addAction(TEXT_SENTIMENT_FILTER);
        return filter;
    }

Code Snippet 4

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mIsBound){
            unbindService(mConnection);
            mIsBound = false;
            unregisterReceiver(mMessageReceiver);
        }
    }

Accelerometer Control

Start Recording

Android

Use the sendToService method the the boolean ACCELERATION_CAPTURE = true with the constant START_CAPTURE to the background service.

Stop Recording

Android

Use the sendToService method the the boolean ACCELERATION_CAPTURE = true with the constant CANCEL_CAPTURE to the background service.

Check API Sending status

Android

Assign Listener

Android

Set Read Frequency

Android

Location Control

Start Recording

Android

Use the sendToService method the the boolean GPS_CAPTURE = true with the constant START_CAPTURE to the background service.

Stop Recording

Android

Use the sendToService method the the boolean GPS_CAPTURE = true with the constant CANCEL_CAPTURE to the background service.

Check API Sending status

Android

Assign Listener

Android

Set Read Frequency

Android

Tag Control

Start Recording

Android

Use the sendToService method the the boolean INPUT_CAPTURE = true with the constant START_CAPTURE to the background service.

Stop Recording

Android

Use the sendToService method the the boolean INPUT_CAPTURE = true with the constant CANCEL_CAPTURE to the background service.

Check API Sending status

Android

Assign Listener

Android

Create Tag

Android

Bluetooth Control

Start Recording

Android

Use the sendToService method the the boolean HR_CAPTURE = true with the constant START_CAPTURE to the background service.

Stop Recording

Android

Use the sendToService method the the boolean HR_CAPTURE = true with the constant CANCEL_CAPTURE to the background service.

Check API Sending status

Android

Assign Listener

Android

Scan for Devices

Android

Connect to Device

Android

Disconnect From Device

Android