Filter results by

Develop an Android app to manage SAMI Rules

Note: This tutorial has been updated for ARTIK Cloud. Read it here.

Today we’re developing an Android app that can create and manage Rules for the user. With these Rules, a user’s flame detector can turn on/off the user’s smart LED light. The system in this article includes the fire detector and smart LED light we discussed in our two previous blogs about building a DIY smart home with SAMI. This article focuses on building the Android app that accompanies the fire detector and smart lights. You will learn how to use the SAMI Rules APIs to programmatically create and manage Rules for users within the app. This means users will not need to create their own Rules in the SAMI User Portal.

The big picture

The diagram below shows the high-level architecture of the whole system:

SAMI Rules and Android architecture diagram

The system works as follows:

  1. The Android app can create, get, or delete a pair of SAMI Rules. The “TURN ON” Rule turns on the smart light if the fire detector detects the flame. The “TURN OFF” Rule does the opposite. Using these Rules, the fire detector can control the LED. The following will happen once the pair of Rules has been created.
  2. The fire detector sends “onFire” data to SAMI. SAMI sends the corresponding Actions to the smart light based on the value of “onFire”.
  3. The smart light sends back the latest state (ON/OFF) to SAMI after receiving an Action.
  4. The Android app monitors and displays the latest states of the flame detector and the light.

We will develop the Android application on the left side of the diagram. You can check out the code at GitHub. Refer to our previous articles to learn how to:

In this article, we use the Device Simulator as an alternative way to test the application.

Android app demo

Let’s first show what the app looks like before discussing the implementation:

  • Start the Android app SAMIRules.

    SAMI Rules

  • Click “LOGIN” and enter your SAMI credentials.
  • Click “Allow” when the app asks you to give it permission to access data from two device types on SAMI. This screen appears when you use the app for the first time.
  • After you finish the authentication flow, you will see the information screen:

    SAMI Rules

    This screen has four regions, which show buttons for managing Rules; the status of the WebSocket connection; the status of the fire detector; and the status of the smart light.

  • Once you have created the Rules, you should see that the status of the light (fourth region) changes according to the status of the fire detector (third region), as follows:

    SAMI Rules

The main goal of this article is to teach development with SAMI Rules APIs rather than Android application development. To avoid cluttering the code due to the complex UI, the application enforces the following restrictions to avoid handling more than two Rules:

  • Before creating or deleting Rules, first click the button to GET Rules.
  • If there are no Rules, enable the CREATE button and disable the DELETE button. Create a pair of Rules (TURN ON and TURN OFF) once the CREATE button is clicked. Then disable the CREATE button and enable the DELETE button.
  • If there are Rules, enable the DELETE button and disable the CREATE button. Delete a pair of Rules once the DELETE button is clicked. Then disable the DELETE button and enable the CREATE button.

Installation and setup

Now let’s set up your system and build the app so that you can play with it.

Create the application in the Developer Portal

Log into the Developer Portal to register your Android application on SAMI. To properly test the application in this tutorial, we have used two separate Samsung accounts with different email addresses:

  1. Our official developer account. This is the account we use to log into the Developer Portal and register our application.
  2. A simulated user account. This is the account we used in the above demo to log into SAMI and the User Portal.

Follow these instructions to create an application. For this Android app, select the following:

  • Set “AUTHORIZATION METHODS” to “Client Credentials, auth code, implicit”.
  • Set “AUTH REDIRECT URL” to android-app://redirect.
  • Under “Permissions”, check “Read” for “Profile”.
  • Click the “Add Device Type” button. Choose “SAMI Example IoT DIY Sensor” as the device type. Check “Read” permissions for this device type.
  • Repeat these steps to add “SAMI Example Simple Smart Light” with “Read” and “Write” permissions. The permission screen will look like this:

    SAMI Rules

In order to create a Rule to control the smart light, your app must request “Read” and “Write” permissions for the smart light. The user will be prompted to grant these permissions when first running the app. Make a note of the client ID. This is the unique application ID, which will be used in the Android source file later.

Connect two devices in the User Portal

  • Use your SAMI user account to log into the User Portal.
  • Connect a device with type “SAMI Example IoT DIY Sensor” to your SAMI user account. Give it a name like “Fire Detector”.
  • On the devices dashbaord, lick the Settings icon next to this device. Copy the device ID from the “Device Info” pop-up. You will use it in the Android code.

    Fire detector

  • Repeat these steps to connect a device with type “SAMI Example Simple Smart Light” and copy its device ID to use in the Android code.

Note that these two devices could be programmatically created for the user within the app, rather than with the User Portal. We did not implement device creation in this sample app in order to avoid complicating the code. Refer to this post to learn how to programmatically add a SAMI device within an application.

Prepare source files and libraries

  1. Check out the source code on GitHub.
  2. Download and build SAMI’s Java/Android SDK libraries. The library JAR files are generated under the target and target/lib directories of the SDK Maven project.
  3. Copy all library JAR files to sample-android-SAMIRules/Application/libs under the Android directory.
  4. Start Android Studio and import the project at the directory sample-android-SAMIRules.
  5. Use the client ID (obtained previously in the Developer Portal) and the device IDs (obtained previously in the User Portal) to replace the corresponding placeholders in SAMISession.java:
// Copy them from the corresponding application in the Developer Portal
public static final String CLIENT_ID = "<YOUR CLIENT ID>";

// Copy them from the Device Info screen in the User Portal
public final static String SMART_LIGHT_DEVICE_ID = "<YOUR SMART LIGHT DEVICE ID>";
public final static String FIRE_DETECTOR_DEVICE_ID = "<YOUR FIRE DETECTOR DEVICE ID>";

Now build the project and deploy the APK to an Android phone. You should be able to play with the app like in the above demo.

Implementation

We are finally ready to talk about the implementation. We implement the following functionalities:

  1. Authenticate a user using the OAuth 2.0 workflow.
  2. Get the user ID needed for Rules API calls.
  3. Call SAMI Rules APIs to get/create/delete rules
  4. Establish connections to WebSocket /live endpoint for the app to receive the latest states from the two devices.

The rest of the section focuses on item No. 3. All other items have been discussed in detail in the above linked articles. As another reminder: To avoid complicating the code of the sample app, we did not implement device creation in the app. As a result, you have to connect the two devices in the User Portal and then copy their device IDs to the Android code. Please refer to this post for instructions on programmatically adding a SAMI device within an app.

Rules API wrapper

The wrapper provides an easy way to make REST API calls to create, delete, or get the Rules. We need to implement the wrapper here since the SAMI Android SDK does not yet support the Rules APIs (this is forthcoming, and will make the wrapper unnecessary). You can find wrappers for other APIs here. RulesApi class exposes three methods that will be called by RuleActivity in background threads. The code snippet below also gives the implementation of postRule(). This method files a HTTP request to create a rule and returns the HTTP response. The other two methods have similar implementations.

 1 public class RulesApi {
 2   ...
 3   ApiInvoker apiInvoker = ApiInvoker.getInstance();
 4 
 5   public String postRule(Rule rule) throws ApiException {
 6     Object postBody = rule;
 7 
 8     // create path and map variables
 9     String path = "/rules".replaceAll("\\{format\\}","json");
10 
11     // query params
12     Map<String, String> queryParams = new HashMap<>();
13     Map<String, String> headerParams = new HashMap<>();
14 
15     String contentType = "application/json";
16 
17     try {
18       String response = apiInvoker.invokeAPI(basePath, path, "POST", queryParams, postBody, headerParams, contentType);
19       return response;
20     } catch (ApiException ex) {
21       if(ex.getCode() == 404) {
22         return null;
23       }
24       else {
25         throw ex;
26       }
27     }
28   }
29 
30   public String getRules() throws ApiException {
31     ...
32   }
33 
34   public String deleteRule(String ruleId) throws ApiException {
35     ...
36   }
37   ...
38 }

Get, create, and delete rules

When the “GET” Rules button is clicked, the following line of the code in RulesActivity triggers a REST call to get the Rules created by this application for the user.

new GetRulesInBackground().execute();

GetRulesInBackground calls getRules() of the wrapper in the background and then parses the HTTP response to present the UI.

 1 class GetRulesInBackground extends AsyncTask<Void, Void, String> {
 2   final static String TAG = "GetRulesInBackground";
 3   @Override
 4   protected String doInBackground(Void... params) {
 5     String retVal = null;
 6     try {
 7       retVal = SAMISession.getInstance().getRulesApi().getRules();
 8     } catch (Exception e) {
 9       ...
10     }
11     return retVal;
12   }
13 
14   @Override
15   protected void onPostExecute(String result) {
16     Log.v(TAG, "::response after getting rules: " + result);
17     try {
18       String displayInfo = result;
19       JSONObject jsonObject = new JSONObject(result);
20       int receivedRules = jsonObject.getInt("count");
21       mRuleIdx = 0;
22       if (jsonObject.getInt("count") <= 0) {
23         mRuleIds = null;
24       } else {
25         JSONArray rulesObj = jsonObject.getJSONArray("data");
26         /* parse the rules and fill in the information to display
27          */
28         ...
29       }
30       handleBtnsEnable();
31       displayRulesApiCallResponse(TAG + " rules:\n" + displayInfo);
32     } catch (Exception e) {
33       ....
34     }
35   }
36 }

Following the same logic, implement and execute CreateRuleInBackground and DeleteRuleInBackground in RulesActivity.

Play with the app

There are a few ways to try this app and verify it works as expected. Specifically, let’s verify the following two functionalities:

If you have developed the fire detector and smart light, you can follow the architecture diagram to play with the Android app alongside the two devices. Here we’ll focus on verification using a SAMI tool—the Device Simulator.

Verify that Rules are working

Make sure that you have already created the Rules using the Android app. Let’s now verify that the Rules work properly. We use two Device Simulators. The first simulates the smart light that receives Actions from SAMI via WebSocket. The second simulates the fire detector, which sends data to SAMI every five seconds using a WebSocket. The value of “onFire” is randomly set to “true” or “false”. We want to verify that each of these random values triggers the correct Action to be received by the first simulator. Please follow the steps to start the two Simulators. You will need an access token. We suggest using the API Console to get an access token after logging in with your simulated user account. In the first Simulator’s console, run the command lw and pass in the device ID (did) of the smart light. The command sets up a WebSocket connection between SAMI and the smart light simulated in the Device Simulator. The console output indicates that the WebSocket is established.

$ lw 713f4xxxx
Using this token to connect: xxxx
WS -> Connected to wss://api.samsungsami.io/v1.1/websocket?ack=true
Register {"Authorization":"bearer xxxx","sdid":"713f4xxxx","type":"register","cid":1432935445622}
$ WS -> {"data":{"message":"OK","code":"200","cid":"1432935445622"}}

In the second Simulator’s console, run the command gs to generate a simulation scenario. Replace the contents of the generated scenario file, e.g. fire_detector_sim.json, with the following (also replacing the placeholder, of course!):

 1 {
 2   "sdid": "<YOUR FIRE DETECTOR DEVICE ID>",
 3   "deviceToken": "",
 4   "data": {
 5     "onFire": false,
 6   },
 7   "config": {
 8     "onFire": {
 9       "type": "Boolean",
10       "function": "random"
11     },
12   },
13   "api": "WS",
14   "period": 5000
15 }

Then run the command rs to start the simulation of the fire detector, which sends data to SAMI every five seconds as follows:

$ rs 45176xxxx fire_detector_sim
Loading scenario from /home/someuser/device-simulator/target/45176xxxx/fire_detector_sim.json

$ Using this token to send the messages: xxxx
WS -> Connected to wss://api.samsungsami.io/v1.1/websocket?ack=true
Register {"Authorization":"bearer xxxx","sdid":"45176xxxx","type":"register","cid":1455663141297}
WS -> {"data":{"code":"200","message":"OK","cid":"1455663141297"}}
Send #0 (+1ms. Elapsed: 1ms) {"onFire":false}
WS -> {"data":{"mid":"0d71d590bc5d43868e2e0ec0bc893e7e","cid":"1455663141299"}}
Send #1 (+4999ms. Elapsed: 5000ms) {"onFire":true}
WS -> {"data":{"mid":"87e3f4b1ca354120b374233b92bfc237","cid":"1455663146299"}}

At the same time, you should see that the simulated smart light receives the correct Actions triggered by the Rules in the first Simulator’s console:

WS -> {"type":"action","cts":1455662918009,"ts":1455662918009,"mid":"c14222fe966745c794066b0374e2bb6e","ddid":"0f8b470c6e214a76b914bc864e2c2b6b","data":{"actions":[{"name":"setOff","parameters":{}}]},"sdid":"45176xxxx","pmid":"0d71d590bc5d43868e2e0ec0bc893e7e","ddtid":"dtf263ae9dd8244490bd171d1c2693c663","uid":"xxxx","mv":1}
WS -> {"type":"action","cts":1455662922802,"ts":1455662922802,"mid":"5be5781f46704a4a9c75f479fff2b426","ddid":"0f8b470c6e214a76b914bc864e2c2b6b","data":{"actions":[{"name":"setOn","parameters":{}}]},"sdid":"45176xxxx","pmid":"87e3f4b1ca354120b374233b92bfc237","ddtid":"dtf263ae9dd8244490bd171d1c2693c663","uid":"xxxx","mv":1}

So far, we have seen that the pair of Rules work properly. When “onFire” is true, the smart light receives a “setOn” Action. Otherwise, it receives a “setOff” Action. Similarly, you can verify the Rule deletion functionality. In the first Simulator, press s followed by the “Enter” key to stop sending messages. Type slw in the second Simulator to stop receiving Actions.

Verify that monitoring is working

In the experiment above, you should have seen that the app correctly monitors the states of the fire detector. We now only need to focus on the light state monitoring functionality. A real smart light should send back its latest state after acting on an Action. You can use one of the above Simulators to emulate sending light states to SAMI, and then check if the Android app receives the latest state properly. Run the gs command to generate the Simulation scenario. In this case, the scenario file is good to use as-is. Then, run the command rs to start the simulation. Now the Simulator sends one message to SAMI every one second, and each message has a random state value (“true” or “false”). The commands and the output of the Simulator are given below. The second parameter in the commands is the device ID of the smart light.

$ gs fde8715961 sendingLightStateSim
Scenario saved to /home/someuser/device-simulator/fde8715961/sendingLightStateSim.json
$
$ rs fde8715961 sendingLightStateSim
Loading scenario from /home/someuser/device-simulator/fde8715961/sendingLightStateSim.json
Using this token to send the messages: 06192752a09041f8b7c2878fa460fedc
Send #0 {"state":true}
Got MID: 8532a9ff8b814ed8b68d82f95e1d903a

Once the Simulator sends a message, you should see this new message in the fourth region of the screen in your Android app. This verifies that the app’s monitoring functionality works as expected. In the simulator, press s followed by the “Enter” key to stop sending messages to SAMI. If you developed the fire detector and smart light from our previous articles, you can easily do end-to-end testing without using the Device Simulator. Read Monitor Fire and Temperature Using SAMI, Open-Source IoT Hardware and Android and An IoT remote control.

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.