Integrate IoT Devices into the SmartThings Ecosystem


Objective

Learn how to create your own IoT device using SmartThings SDK for Direct Connected Devices.

Overview

The SmartThings SDK for Direct Connected Devices is provided to ease the development of devices which operate with SmartThings Cloud and mobile application. It is small enough to work on resource limited embedded devices.

In this Code Lab, you will learn how to create your own IoT device profile at SmartThings cloud and how to implement on your test device. It is explained into three parts. The first explains how you can register and deploy to test your own IoT device profile in SmartThings using the Developer Workspace.

Then, it demonstrates how to create your own IoT device application with SmartThings SDK.

The last part shows how to onboard and control instances of your device with SmartThings mobile application.

Set up your environment

You will need the following:

  • Host PC

    This Code Lab is based on Ubuntu Linux (x64)

  • Toolchain and Board Support Package (BSP) for Micro-Controller Unit (MCU) board

    You will use the ESP32-C3-DevKitC board. You may set up the environment by referring to this GitHub repository.


  • GitHub repositories for the library and references or samples of SmartThings SDK for Direct Connected Devices for C

    $ git clone https://github.com/SmartThingsCommunity/st-device-sdk-c-ref.git
    $ cd st-cevice-sdk-c-ref
    
    $ python3 setup.py esp32
    
  • SmartThings mobile application

Sample Code

Here is a sample code for you to start coding in this Code Lab. Download it and start your learning experience!

SmartThings SDK Sample Code
(2.60 KB)

Register and deploy to test your device

Using the Developer Workspace, create a device profile and customize the instructions for onboarding the device on the SmartThings mobile app, and deploy devices to be tested. These configurations can be edited up until the point you submit the device for publication in the production of the SmartThings ecosystem.

Sign in to SmartThings Developers

Sign in to SmartThings Developer Workspace using your Samsung account.

Create new project

You need to create an integration project for a direct connected device. Create a new device project for device integration. Select Device Integration, then Direct-connected. Afterwards, name your project respectively.

Add a device profile

Define your device’s functionalities with SmartThings capability. First, navigate and select Define Device Profile and then click Create Device Profile. Fill the required fields with respective values. Afterwards, select a capability for your device.

You can get more information about the capabilities available here.

Add device onboarding

The device onboarding guides device owners when their device is first registering and connecting to SmartThings. You can customize the screens presented by adding a device onboarding profile. The ownership validation type is also defined at this stage.

You may customize the screens displayed when the device onboards via the SmartThings mobile app, or just use the default values.

Add a product info

The product info defines how this device is shown at SmartThings mobile app catalog. You can define device’s category and its regional availability.

Deploy your device to test

You can start testing by deploying your device to test. There are two ways to do this:

Via Overview menu

Via Test > Test Devices

You will be able to see your device in the SmartThings mobile app when in Developer mode only after it has been deployed for testing.

Register test devices

You can add the identity of device for authenticating it to the SmartThings cloud. This requires device information like serial number and device public key (ED25519). Since the maximum number of test device is limited per user, once you’ve reached it, you should remove the existing one.

This example shows how to create ED25519 key pair with SDK tools. You can get device_info.json file as a result from tools/keygen/linux/output_{ serialNumber}.

Linux version of key generator (keygen) utility is located at st-iot-device-sdk-c-reference/iot-core/tools/keygen/ or st-device-sdk-c/tools/keygen/.

Serial number for testing device would be randomly generated by this tool which has STDK + 12-digit alphanumeric format:


$ cd ~/Workspace/st-device-sdk-c-ref/iot-core/tools/keygen/
$ python3 stdk-keygen.py –firmware switch_example_001
Use following serial number and public key
for the identity of your device in Developer Workspace.

Serial Number:
STDK**E90W***uCX

Public Key:
nFN5x***uQusQ****ZHoBSFaAoP9***kNdLnjDJRew=

Copy STDK**E90W***uCX from keygen output and paste it into Serial Number field of Register A Test Device page.
Copy public key string from keygen output (nFN5x***uQusQ****ZHoBSFaAoP9***kNdLnjDJRew= in this example) and paste it into Public Key field.

Generate device QR code

Using the device QR code could be helpful while device onboarding. QR code should have format like below. Refer here for more details.

{Your mnId}: 4-digit alphanumeric mnId of your account

{Device onboardingId}: 3-digit number Onboarding ID, you can find it from your developer workspace project Device Onboarding > Other Info page

{Device serialNumber}: device serial number which is registered at your developer workspace project

You can simply generate QR code with using below Python script:


import qrcode

mnid = 'FFFF' # "FFFF" is an example. you should replace it with yours
onboardingId = '111' # "111" is an example. you should replace it with yours
serialNumber = 'STDKtest0001' # "STDKtest0001" is an exmaple. you should replace it with yours
qrUrl = 'https://qr.samsungiots.com/?m=' + mnid + '&s=' + onboardingId + '&r=' + serialNumber
img = qrcode.make(qrUrl)
img.save(serialNumber + '.png')
qrcode.QRCode(box_size=10, border=4)

Write device application

Open and edit sample device app

Currently, you are doing the Code Lab example, which is located at apps/esp32/code_lab_example directory in the GitHub repository.

  • Download onboarding_profile.json from the Overview of your device in Developer Workspace.

  • Copy onboarding_profile.json file into your application directory, apps/esp32/code_lab_example/main:

    $ cd ~/Workspace/st-device-sdk-c-ref/apps/esp32/code_lab_example/main/
    $ cp ~/Downloads/onboarding_config.json
    
  • Copy device_info.json from tools/keygen/linux/output_{serialNumber} which contains your device specific information to application directory, apps/esp32/code_lab_example/main:

    $ cd ~/Workspace/st-device-sdk-c-ref/iot-core/tools/keygen/
    $ cp output_{serialNumber}/device_info.json ~/Workspace/st-device-sdk-c-ref/apps/esp32/code_lab_example/main/
    

    firmwareVersion: version string

    privateKey: base64 encoded ED25519 private key. This value should be paired with what you registered to Developer Workspace.

    publicKey: base64 encoded ED25519 public key. This value should be same with what you registered to Developer Workspace.

    serialNumber: This value should be same with what you registered to Developer Workspace

    {
        "deviceInfo": {
            "firmwareVersion": "switch_example_001",
            "privateKey": "dH**JKMRD5X****BaV+fGoXa3qZfNW3V****jHXOmd0=",
            "publicKey": "nFN5x***uQusQ****ZHoBSFaAoP9***kNdLnjDJRew=",
            "serialNumber": "STDK**E90W***uCX"
        }
    }
    
    
  • Open sample application source code

    • Browse in apps/esp32/code_lab_example/main/ directory.

    • Open main.c file.

  • Write your device application code

    • This example already has cloud connection functionality using SmartThings SDK APIs.

      
      void app_main(void)
      	{
      		/**
      		  Easily integrate your Direct Connected Device using the Direct Connected Devices SDK.
      		  The SDK manages all MQTT topics and onboarding requirements,
      		  freeing you to focus on the Capabilities of your device.
      		  That is, you can simply develop a basic application
      		  by just calling the APIs provided by st_iot_core layer like below.
      		  // create a iot context
      		  1. st_conn_init();
      		  // create a handle to process capability
      		  2. st_cap_handle_init(); (called in function 'capability_init')
      		  // register a callback function to process capability command when it comes from the SmartThings Server.
      		  3. st_cap_cmd_set_cb(); (called in function 'capability_init')
      		  // process on-boarding procedure. There is nothing more to do on the app side than call the API.
      		  4. st_conn_start();
      		 */
      
      		unsigned char *onboarding_config = (unsigned char *) onboarding_config_start;
      		unsigned int onboarding_config_len = onboarding_config_end - onboarding_config_start;
      		unsigned char *device_info = (unsigned char *) device_info_start;
      		unsigned int device_info_len = device_info_end - device_info_start;
      
      		int err;
      
      		iot_gpio_init();
      		xTaskCreate(app_main_task, "app_main_task", 4096, NULL, 10, NULL);
      
      		//create a iot context
      		iot_ctx = st_conn_init(onboarding_config, onboarding_config_len, device_info, device_info_len);
      		if (iot_ctx != NULL) {
      			err = st_conn_set_noti_cb(iot_ctx, iot_noti_cb, NULL);
      			if (err)
      				printf("fail to set notification callback function\n");
      		} else {
      			printf("fail to create the iot_context\n");
      		}
      
      		//create a handle to process capability and initialize capability info
      		capability_init();
      
      		//connect to server
      		err = st_conn_start(iot_ctx, (st_status_cb)&iot_status_cb, IOT_STATUS_ALL, NULL, NULL);
      		if (err) {
      			printf("fail to start connection. err:%d\n", err);
      		}
      
      	}
      
      
    • Complete your command callback function for each capability. The command callback function should contain your device control upon each command such as LED on or off control. Capability example for each capability would be helpful to handle attribute command for each capability. You can find it at apps/capability_example/main.

      static void update_switch_state(int switch_state)
      {
      	const char* switch_value;
      
      	if (switch_state == SWITCH_ON) {
      		switch_value = caps_helper_switch.attr_switch.value_on;
      	} else {
      		switch_value = caps_helper_switch.attr_switch.value_off;
      	}
      
      	//TODO: Set switch attribute value and send
      	//
      	// Example
      	//===============================================================================
      	// cap_switch_data->set_switch_value(cap_switch_data, switch_value);
      	// cap_switch_data->attr_switch_send(cap_switch_data);
      	//===============================================================================
      }
      
      static int get_switch_state(void)
      {
      	const char* switch_value;
      	int switch_state = SWITCH_OFF;
      
      	//TODO: Get switch attribute value
      	//
      	// Example
      	//===============================================================================
      	// switch_value = cap_switch_data->get_switch_value(cap_switch_data);
      	//
      	// if (!strcmp(switch_value, caps_helper_switch.attr_switch.value_on)) {
      	//     switch_state = SWITCH_ON;
      	// } else if (!strcmp(switch_value, caps_helper_switch.attr_switch.value_off)) {
      	//     switch_state = SWITCH_OFF;
      	// }
      	//===============================================================================
      	return switch_state;
      }
      
      static void cap_switch_cmd_cb(struct caps_switch_data *caps_data)
      {
      	int switch_state = get_switch_state();
      	set_led_mode(switch_state);
      }
      
      static void capability_init()
      {
      	//TODO: initialize switch capability with using capability sample's initializae function
      	//
      	// Example
      	// //===============================================================================
      	// cap_switch_data = caps_switch_initialize(iot_ctx, "main", NULL, NULL);
      	// if (cap_switch_data) {
      	//     const char *switch_init_value = caps_helper_switch.attr_switch.value_on;
      	//
      	//     cap_switch_data->cmd_on_usr_cb = cap_switch_cmd_cb;
      	//     cap_switch_data->cmd_off_usr_cb = cap_switch_cmd_cb;
      	//
      	//     cap_switch_data->set_switch_value(cap_switch_data, switch_init_value);
      	// }
      	//===============================================================================
      }
      
      

Build, flash, and monitor

You can build, flash, and monitor in the console with the following:


$ cd ~/Workspace/st-device-sdk-c-ref
$ python3 build.py apps/esp32/code_lab_example
$ python3 build.py apps/esp32/code_lab_example flash
$ python3 build.py apps/esp32/code_lab_example monitor
Or
$ cd ~/Workspace/st-device-sdk-c-ref
$ python3 build.py apps/esp32/code_lab_example flash monitor


Onboard and control the device via SmartThings app

Onboarding

a. Enable developer mode

Developer mode should be enabled on SmartThings mobile application.

Launch the SmartThings app, go to Dashboard > Settings. Long-press About SmartThings for 20 seconds. Enable the Developer mode, then restart the SmartThings app.

You can find out more information here.

b. Add a new device

Go to Add device and click My Testing Devices or Scan QR code. You can now see and add your self-published devices.

Control by SmartThings application

a. Device control from dashboard

You can turn your device’s LED on or off by clicking the button in the SmartThings app.

b. Device control from plugin

You can control various attributes and get more detailed information from the device plugin user interface.

You're done!

Congratulations! You have successfully achieved the goal of this Code Lab. Now, you can control your IoT devices using the SmartThings app all by yourself! If you're having trouble, you may download this file:

SmartThings Device SDK Complete Code
(2.49 KB)