Filter results by

Developing With SAMI: Give Your App a Brain

We add a data analysis backend server to the iOS app built in the Developing with SAMI series. This post shows how SAMI enables third-party applications to perform effective analytics on data from diverse sources and users.

This article reads from top to bottom, but you can also skip to your preferred section:

Introduction

A real-world user will own different types of smart devices from different vendors. Currently, however, the IoT market is highly segmented. One reason is that many devices silo the user’s data into their own applications.

The ability to combine and analyze data from multiple devices would therefore allow the creation of highly relevant services for users. SAMI, as an agnostic data broker and an open platform, is addressing the challenge of interoperability among different device types and vertical markets.

In my previous series of Developing with SAMI articles, I built an iOS app called SAMIHMonitor. This calorie tracker allows a user to record and store their calories in SAMI, and later view historical data from both their calorie tracker and another smart device, their Withings scale connected to SAMI.

But aggregating data from disparate sources is only the first step. Data is useless without generating insights. Therefore, data analysis is the next step.

We believe that data analysis is the “brain” of an application. In a real-world scenario, the size of the data to be analyzed could be very large. So the data analysis is very likely to reside out of the mobile app.

In this post, I am going to bring SAMIHMonitor closer to the real-world case. Specifically, I will add a backend server to SAMIHMonitor. This gives SAMIHMonitor two components: an iOS app and a backend server. The backend server reads health data from all users and then generates a rank for each user. The iOS app built in Part 3 is enhanced to show the rank. I refer to this whole system as SAMIHMonitor in this post.

With this development adventure, I hope to answer the following questions in my mind:

  • How easily does SAMI allow a third party to build such a system that contains multiple components?
  • How easily can different application components access user data while still satisfying SAMI permission models?

High-level system view

The diagram below shows the high-level architecture that involves SAMI, Withings devices, the SAMIHMonitor iOS app and SAMIHMonitor backend server in a multiple-user scenario.

SAMIHMonitor system overview

This diagram shows devices/apps belonging to two users. Each user stores three types of data in SAMI:

  • Caloric intake from the calorie tracker on the iPhone,
  • Weight data from the Withings scale connected to SAMI,
  • Health ranks from the SAMIHMonitor backend server.

The health monitor server reads each user’s weight and calories from SAMI, generates ranks, and then sends the ranks back to SAMI. The iOS app reads the authenticated user’s rank from SAMI and displays it to the user.

All API calls to SAMI require an access token. There are three types of access tokens and multiple ways to obtain a token. In this post, we will learn how the backend server obtains an appropriate token to accomplish its mission.

Demo: Generate and view your health rank

The backend server triggers the rank calculation periodically. Below is an example of the console output:

$ node algorithm_engine
------------------------
Trigger health rank calculation

Collect user weight data...
Obtained application token: e559c526226a4fe285fa036e2eac0323
[240bc34cf61348e6a3255fe5d8539484]:47.1 47 47 
[650a7c8b6ca44730b077ce849af64e90]:60 65 62

Collect user calorie data...
Obtained application token: 089a6bde4c804b5dbb0e3e04b8b93abb
[650a7c8b6ca44730b077ce849af64e90]:300 350 
[240bc34cf61348e6a3255fe5d8539484]:1800 2000 1800 

Calculate and send health ranks...
Obtained application token: 12283821a8d649d3967b9cf212a4ce88
uid=[240bc34cf61348e6a3255fe5d8539484]: rank = 13
uid=[650a7c8b6ca44730b077ce849af64e90]: rank = 56
uid=[240bc34cf61348e6a3255fe5d8539484]: rank is sent to SAMI
uid=[650a7c8b6ca44730b077ce849af64e90]: rank is sent to SAMI

The SAMIHMonitor iOS app works similarly as version two. The sole enhancement is that the app now shows health ranks.

After you finish the authentication flow on the iOS app, you will see a user information screen: SAMIHMonitor V2 Click the “Show Health Rank” button. You will then see the data screen, which lists the ranks as follows: SAMIHMonitor V2

Installation and setup

Get the source code of the iOS app and backend server at GitHub. The backend server is developed using Node.js.

Register your app

Follow Developing With SAMI: Let’s Bring Your Data Together to set up the iOS app. Now I need to perform one extra step in order to use this newer version of the app:

I log into the Developer Portal using my developer account. Click “SAMIHealthMonitor APP” and then “Edit App Info” to open the application editor. Under “Permissions”, click the “+ Add Device Type” button. Select “SAMI Example HRank” as the device type. Check “Read” and “Write” permissions for this device type and save my changes.

What I have done is to request new permissions for this application in order to write and read the rank data to and from SAMI. Please also note the client ID and client secret on this screen, since you will use them to configure the source code.

Setup source files

See Developing With SAMI: Let’s Bring Your Data Together to prepare Objective-C source files and libraries for the SAMIHMonitor iOS app.

Perform the following steps to configure the source file of the backend server.

  • Change to backend directory.
  • Fill in the following information in source file algorithm_engine.js.
 1 var clientID = "YOUR CLIENT APP ID";
 2 var clientSecret = "YOUR CLIENT APP SECRET";
 3 
 4 // A data structure hosting the information of the user that has granted permission to the application
 5 var user_1 = {uid:"",  // user id
 6               calorieTrackerSdid:"", // calorie tracker device id 
 7               withingsSdid:"", // Withings device id
 8               hRankSdid:""  // HRank device id
 9               };
10 var user_2 = {uid:"",  // user id
11               calorieTrackerSdid:"", // calorie tracker device id 
12               withingsSdid:"", // Withings device id
13               hRankSdid:"" // HRank device id
14               }; 
15 // Collection of all users
16 var users = [user_1, user_2];

The above code block only lists two users for illustration purposes. You can add more users in algorithm_engine.js. For a real-world production-level application, the backend server should communicate with its iOS app and record each user ID that has granted permissions to SAMIHMonitor, and the user’s device IDs. For this sample application, we do not implement this functionality to avoid cluttering the app.

Our focus is to explain how the backend server communicates with SAMI to get data across multiple users. We use the following workaround to record the users and devices. To get the user ID and device IDs of a user, start the SAMIHMonitor iOS app in Xcode and then log into SAMI as that user. You can get the information of that user from the printout on the Xcode console, and then copy the information into the above code block. Perform these steps for all users whose health rank you want to calculate.

  • Run the following commands to install necessary node modules.
$ npm install node-rest-client
$ npm install periodic-task
  • Finally, bring the server up.
$ node algorithm_engine

Then you will see the server console output, similar to the demo. Meanwhile, on the iOS app, you will see the updated rank by refreshing the rank data screen shortly after the backend server finishes recalculating the ranks.

Implementation

Let’s dive into the implementation of the backend server. To learn about the implementation of the iOS app, please consult the previous post. The diagram below illustrates the high-level logic of the backend server.
SAMIHMonitor V3 The data analysis here is a toy algorithm and does not make any sense in a real-world scenario. The key point here is to show you how to get the right access tokens in order to get and send data from and to SAMI across multiple users.

Create HRank device type on the Developer Portal

I use the Simple Manifest to create this device type. Each SAMIHMonitor user will have such a device on SAMI. This device records the user’s health ranks generated by the backend server.

{
    "overall_rank":47,
    "comments":"put comments here if needed"
}

I give my device type the name “SAMI Example HRank” and a unique name com.samsungsami.hrank. I go to the Developer Portal and click “SAMI Example HRank” and then “Status”, and finally the “Publish” button. From now on, this device type is visible to other users and developers on the User Portal and Developer Portal, and can be used by any application.

The SAMIHMonitor iOS app is enhanced to create a device of HRank type on SAMI for each user, and to read and display the rank data from SAMI to the user.

Obtain application tokens

The first time a user opens the SAMHIMonitor iOS app, they are prompted to give SAMHIMonitor the following permissions:

  • Read and write for the “SAMI Example Calorie Tracker” device type,
  • Read for the “Withings Device” device type,
  • Read and write for the “SAMI Example HRank” device type.

After the user grants the requested permissions, all application components (the iOS app and the backend server) can access the user’s data according to the above permissions.

According to the documentation on token types, the backend server should use an application token to access the data of all users that have granted permissions. Note that the SAMHIMonitor iOS app cannot access all users’ data since it uses a user token, which can only be used to access the data of the user currently logged into the app.

The Client Credentials method is the only way to generate an application token. The code below illustrates the implementation of the Client Credentials method in Node.js. After the token is obtained, the callback passed in getAppToken is called.

 1 function getAppToken (callback) {
 2     // Compose the http request
 3     var body = "client_id=" + clientID + "&client_secret=" + clientSecret 
 4     + "&grant_type=" + grantType + "&scope=" + scope;
 5     var requestArgs = {
 6         headers: {
 7             "Content-Type": "application/x-www-form-urlencoded"
 8         },
 9         data: body
10     };
11     
12     c.post(samiAuthUrl, requestArgs, function(data, response) {            
13         var jsonData = JSON.parse(data);
14         appToken = jsonData.access_token;
15         console.log("Obtained application token: " + appToken);
16         callback();
17     });     
18 }

Make API calls

We can use the application token obtained above to make API calls to achieve the following:

  • Get calorie data of all users from SAMI.
  • Get weight data of all users from SAMI.
  • Send health ranks of all users back to SAMI.

The implementation of the above three functionalities is quite similar. The following code block shows how to get all users’ weight data.

 1 getAppToken (getAllUserWeight);
 2 
 3 function getAllUserWeight() {
 4     users.forEach(getWeightData);
 5 }
 6 
 7 function getWeightData(user) {
 8     var requestArgs = buildArgs();
 9     
10     var url = samiMsgApiUrl + "/last?count=" + msgCount + "&sdids=" + user.withingsSdid;
11     c.get(url, requestArgs, function(data, response) {
12         var messages = data.data;
13         ++countWeightColl;
14         if (finishWeightCollection()) {
15             handleRank();   
16         }
17     });
18 }

Since the application token is short-lived, I request an application token before making API calls to get all users’ weight data. This is illustrated in the above code block.

What comes next?

To provide a service that is relevant to individuals, a real-world application needs to be capable of accessing data across multiple device types and across multiple users. Normally the data analysis component resides outside of the mobile app. This post shows how SAMI enables different components of a third-party application to easily access data.

As I mentioned in Setup source files, the backend server in this post uses a hack to get the information of all users that have granted permissions to the app. In the future, we plan to improve the SAMIHMonitor server by adding the capability to communicate with the iOS app to get user information.

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

Top image: Charis Tsevis

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, blog posts, datasheet updates, and more.

* By checking either box, you may receive notifications by phone, email, text, and/or other electronic means from Samsung Semiconductor, Inc. and its affiliates. If you choose to receive partner notifications, we may forward your contact information to our partners. You may unsubscribe from these services at any time by clicking on the unsubscribe link in our communications or by submitting a request here. Please see our Privacy Policy and Terms of Use for more information about how your data is stored and used.