NE Context SDK Guide¶
NESDK is a utility that provides real-time contextual information about app users. It is intended to help apps become more context-aware of their users and change behaviour accordingly, such as automatically muting a message alert when the user is at work, and making a louder sound when outdoors.
NESDK provides a publish-subscribe style interface through its internal
Engine. All sensors publish to this central location, but sleep when there aren’t any subscribers listening to them.
To get started, you just need to initialise the service, which prepares the internal sensors:
stop() should be called when no longer needed, or
runInBackground(). This sets up the background service to either stop or remain alive respectively, and is usually done when the app is resumed and paused like so:
Once you have a service instance, you can call
ne.subscribe(topic, callback), which takes a topic and a callback:
Simple tasks can be performed directly with the
NE class, which is just a convenience interface for invoking the same methods on the
Engine subcomponent (e.g.
Now, every time the user’s activity changes, such as when they start running, a message will be printed in the debug console.
When subscribing, the subscription will last only while the variable is in scope. Hence, it is important to store it somewhere permanent if you want it to remain subscribed. For example:
The main methods of the
Engine interface are:
get(topic)manually retrieves the latest event on a topic. If no event has been published, the method will return
subscribe(topic, callback)as described above.
request(topic, callback)asks all sensors on the topic to produce an event immediately, if supported. Otherwise, the last known event is used. The callback will be called at-most once from the first sensor to honour the request. If no publisher exists on the given topic, a
NoPublishersexception is thrown.
publisherExists(topic)returns true if at least one publisher is active on the given topic.
The topics given to
subscribe(topic, callback) exist in a sort of hierarchy. For simplicity, we recommend that you use the topic constants defined within the
NE class. For example:
You can also provide a topic as a string sensor path. This allows you to listen to specific sensors, or a group of them. Here’s an example of how they are organised:
- "" # The 'root' topic. This receives everything. - "motion" # Receives motion-related events. - "motion/accelerometer" # Receives acceleration vectors. - "motion/accelerometer/0" # The primary accelerometer of the device. - "motion/accelerometer/1" # The secondary accelerometer. - "motion/gyroscope" # Receives angular velocity vectors. - "motion/gyroscope/0" # The primary gyroscope of the device. - "motion/device_movement" # Receives events related to physical device movement. - "motion/device_movement/significant" # Receives events when a device has moved a significant amount.
All data to and from the
Engine is encapsulated in an
Event. This class includes:
- The timestamp of when the event was created
- The name of the sensor that produced it
- One or more values along with confidence ratings
Most events have one value, but if there is uncertainty, a probability distribution is given. For example, if the activity sensor is unsure of the user’s current activity, it may emit an event like this:
- Event: - source: "ActivitySensor" - timestamp: "2018-04-27T17:15:30.325000Z" - values: - RUNNING: 0.7 - CYCLING: 0.2 - WALKING: 0.1
Event.values() retrieves all values as a list of pairs,
Event.value() retrieves the most likely value, and
Event.confidence() retrieves the most likely value’s confidence. This example will print out all of the values:
The values inside events conform to one of several datatypes. All datatypes inherit the
NEType class, which allows conversion to a string and a cloning method. By casting the value to its original datatype, you can get the raw data. Here are a list of currently supported data types:
|NEDouble||A floating-point number|
|NEIndoorOutdoor||An enumeration of indoor/outdoor states (
|NELocation||Latitude and longitude in decimal degrees, and a speed in metres per second|
|NELockStatus||An enumeration of phone lock states (
|NEMotion||An enumeration of motion states (
|NEReachability||An enumeration of device network reachability (
|NESignal||Information about the currently connected cellular base station, including signal strength in decibels, and an id as a concatenation of MCC, MNC, LAC/TAC, And CID/CI|
|NESituation||High level statements about a user’s current situation (
|NEVector3D||A 3D vector of floating-point numbers for representing points, lines, or fields in 3D space|
An event can only contain values of the same data type. If you disagree with this constraint, let us know!
Filters are a way of which events can notify your subscription callback. There are currently 3 filters: ‘type’, ‘dropout’, and ‘burst’. Filters can be specified as the second argument of
subscribe(topic, filter, callback),
get(topic, filter), and
request(topic, filter, callback) methods. These are given as strings and can be chained together in the following format:
If the filter syntax is incorrect, an
InvalidFilter exception will be thrown.
Because topic groups can receive data from multiple sensors, it’s useful to restrict subscriptions to a specific data type. The format for a type filter is:
TYPENAME is one of the types listed under Data Types.
Some sensors, such as the accelerometer, may produce events very quickly. To limit the rate at which events arrive, a dropout filter is used, specifying either a count or a timeout as follows:
dropout:9 receives every 10th event.
dropout:5s receives every 5 seconds. The following time suffixes can be given in the argument:
μs or us, ms, s, m, h for microseconds, milliseconds, seconds, minutes, and hours respectively.
If a dropout filter is too aggressive, and you still want high frequency data over certain periods, use a burst filter:
burst:3,100 receives the first 3 events for every 100 events.
burst:3s,1m receives the first 3 seconds of data every minute. The same time suffixes used in the Dropout Filter are used.
Times and counts can be mixed-and-matched, e.g.
Chained Filter Example¶
By default, NESDK requires only Internet permissions on Android, and permission to run in the background for iOS. Sensors that require extra permissions, such as location, are disabled until the host app grants that permission. This keeps the SDK lean, with a privacy-by-design philosophy. The following sensors require extra permissions:
|||(1, 2, 3, 4, 5, 6) All sensors that require |
|||(1, 2, 3, 4, 5, 6) To use location-based services in the background, you must also enable Location in Background permissions.|
These tables list the available sensors across each platform, along with their publishing topic and any permissions required to enable them.
Some sensors, such as ambient pressure, may not be available on all devices despite being supported by the platform. To see if a publisher exists, use
|Location Cluster ID||
|Bluetooth LE Devices||
|||iOS does not distinguish between GPS and low-power location sources.|