Filter results by

ARTIK Cloud – via Arduino

Our previous tutorial installment provided a demonstration scenario for communicating with Samsung ARTIK Cloud. We used Node-RED to give you a familiar and interactive introduction.

In this article, we'll program the Samsung ARTIK module to send those same messages to ARTIK Cloud using the Arduino IDE to build a "sketch" and load it to the ARTIK module, just as you did with Blink an LED. You'll tie in actual sensor input: stand-in devices for the thermostat setting, inside temperature, and outside temperature.

We will be demonstrating both MQTT protocol and Web REST API protocol to give you a well-rounded education. After you've played with both, you can decide which one best suits your application.

Prerequisites

In preparation for this tutorial, you will need to:

  • Download and install updated Arduino IDE files and new libraries, as noted below.
  • Complete prior tutorials, paying particular attention to:
    – Writing and running a sketch in the Arduino IDE (Blink an LED)
    – Setting up the "Economy A/C Database" manifest (Publishing to ARTIK Cloud).
  • Log your ARTIK board in with dhclient wlan0 to the same Wi-Fi® network as you use on your Arduino IDE system. The sketch code does not include Wi-Fi login commands, which are not needed if you are connected to Wi-Fi beforehand.
  • Have a spare photoresistor and resistor on hand, similar to the ones you used for the Photon "sunshine detector" exercise.

The time for the three coding exercises in this installment, once the Arduino IDE and library code are installed, comes to less than 10 minutes each. Setting up the sensors and other preparation for the concluding exercise could take 10-30 minutes, depending on how much you still have set up from prior tutorials.

Installing Libraries

As always, Arduino makes life simpler with libraries. Here we use three: one for Wi-Fi, one to implement an MQTT client, and one to handle JSON-related formatting.

WiFiSSLClient

The latest Arduino IDE builds include a built-in WiFiSSLClient library that transparently replaces WiFiClient, yet in the background secures the link with SSL/TLS encryption.

WiFiClient and WiFiSSLClient bind to the HTTP or MQTT client through an IP stack. The choice of whether your calls are secured or not depends on the one you bind.

  • In our first MQTT example below, we use MQTT with SSL/TLS (bound to WiFiSSLClient) because ARTIK Cloud requires this encryption.
  • In our concluding example, we use MQTT with no encryption (bound to WiFiClient), instead communicating with ARTIK Cloud using secure Web protocols (bound to WiFiSSLClient).

Important: Install Arduino IDE 1.6.9 or later, and additionally update to ARTIK board version 0.3.6 or later through the Arduino IDE Board Manager.

MQTT Client Library

The MQTT client library handles the details of packet transfers so that you can subscribe and publish with minimal code.

  1. Install the Arduino MQTTClient library using Manage Libraries. (If you don't see the library, search online about deleting library_index.json to force the IDE to rebuild the library list.)
  2. Add #include <MQTTClient.h> to your sketch.

The author has provided useful information about this library here. Be sure to take note of the discussion on maximum packet size and consider it for your own application.

.JSON Formatting Library

We will need a simple way to structure data packets to match the .JSON format that ARTIK Cloud is expecting.

  1. Install the Arduino .JSON library.
  2. Add #include <ArduinoJson.h> to your sketch.

You'll find the author's very helpful write-up about this library here.

Coding for MQTT

Owing to the power of the ARTIK module with the Arduino IDE, here we can offer a surprisingly short exercise to demonstrate MQTT communication with ARTIK Cloud.

Basic MQTT Code

Load the Arduino IDE and start a new sketch. Our data this time will all be temperatures
(insTemp, desTemp, and outTemp).

  1. Copy in the code below. For clarity, we have left out error checking code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <WiFi.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>

// MQTT params  
char mqttCloudServer[]     = "api.artik.cloud";
int  mqttCloudPort         = 8883;
char mqttCloudClientName[] = "ARTIK-Arduino"; // or whatever you prefer
char mqttCloudUsername[]   = "_your_DEVICE_ID_goes_here_"; // FIX
char mqttCloudPassword[]   = "_your_DEVICE_TOKEN_goes_here_"; // FIX
char mqttCloudTopic[]      = "/v1.1/messages/_your_DEVICE_ID_goes_here_"; // FIX 
float insTemp, desTemp, outTemp;
char buf[100] = "\{\"insTemp\":19.3,  \"desTemp\":19.1, \"outTemp\":23.7 \}";

WiFiSSLClient ipCloudStack;
MQTTClient mqttCloudClient;
  
void setup() {
  mqttCloudClient.begin(mqttCloudServer, mqttCloudPort, ipCloudStack);
  mqttCloudClient.connect(mqttCloudClientName, mqttCloudUsername, mqttCloudPassword);
}
  
void loop() {
  mqttCloudClient.publish(mqttCloudTopic, buf);
  exit(0);   
} 

void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
} 
  1. Replace the ARTIK Cloud device placeholders with your own. As you will recall, they both come from My ARTIK Cloud (click on the 'gear').
    • Paste in Device ID (sdid) in two places.
    • Paste in Device Token (accessToken).
    • Close the Device Info window and go to ARTIK Cloud Charts.
  2. Take a moment to understand this compact code.
    • WiFiSSLClient sets up SSL/TLS network connectivity for MQTTClient; the two interact through ipCloudStack.
    • mqttCloudClient.connect makes the MQTT connection to ARTIK Cloud.
    • mqttCloudClient.publish publishes the data to the Device ID specified in Topic.
    • The MQTT params should already look familiar to you from previous tutorials.
  3. Load the sketch to the ARTIK module to run it.

You have just sent ARTIK Cloud a data message, and should see it at My ARTIK Cloud as always.

No data? Make sure you have the latest Arduino IDE and ARTIK board manager releases installed, as noted in Installing Libraries. Correct installation may require you to uninstall the Arduino IDE first.

Automating the JSON Formatting

Notice how we had to manually format our 'publish' data (in buf), using backslashes in front of the interior quotes and curly braces. It's not a pleasant task.

\{\"insTemp\":19.3, \"desTemp\":19.1, \"outTemp\":23.7"...

We'll automate this with the JSON library.

  1. Write a loadBuffer() routine to format data into .JSON. We want to create:

    • A reserved spot in memory to put our raw data
      StaticJsonBuffer<200> jsonBuffer;

    • A JSON object addressed at that spot, to be populated by data pairs
      JsonObject& dataPair = jsonBuffer.createObject();

    • Our data pairs (using variables this time)
      dataPair["insTemp"] = insTemp;
      dataPair["desTemp"] = desTemp;
      dataPair["outTemp"] = outTemp;

    • An operation to extract the data, one pair at a time, and "print" it JSON-formatted into the original buf that we used.
      dataPair.printTo(buf, sizeof(buf));

  2. Add in the completed JSON formatting routine at the end of your sketch.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     void loadBuffer(float insTemp, float desTemp, float outTemp) {  
       StaticJsonBuffer<200> jsonBuffer;  
       JsonObject& dataPair = jsonBuffer.createObject();  
    
       dataPair["insTemp"] = insTemp;  
       dataPair["desTemp"] = desTemp;  
       dataPair["outTemp"] = outTemp;  
    	
       dataPair.printTo(buf, sizeof(buf));  
     }
  3. Call the routine with some data (values of your choice) right after your loop() statement. You'll replace these hard-coded values with sensor input variables later.

    1
     loadBuffer(19.3,19.1,23.7);
  4. Load the sketch to the ARTIK module to run it.

The JSON-formatted data goes to ARTIK Cloud and shows up in My ARTIK Cloud.

You now have a simple formula to publish data to ARTIK Cloud over MQTT using the Arduino IDE. You can use Web protocols to do the same thing, as described below. Even if you do not plan to use Web protocols, you will need to understand them to complete the 'sensors' portion of this tutorial.

Coding for Web

Here we will duplicate in Web REST API protocols what we did using MQTT. As in the MQTT example, WiFiSSLClient takes care of all SSL/TLS issues in the background.

Basic Web REST API Code

This example creates a client object that connects and transfers data using a link encrypted by SSL/TLS.

  1. Copy in the code below. For clarity, we have left out error checking code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <WiFi.h>
#include <ArduinoJson.h>

// Web REST API params
char server[] = "api.artik.cloud";  
int port = 443; //(port 443 is default for HTTPS)

String AuthorizationData = "Authorization: Bearer _your_DEVICE_TOKEN_goes_here_";

float insTemp, desTemp, outTemp;
String PostData = "{\n  \"sdid\": \"_your_DEVICE_ID_goes_here_\",\n  \"type\": 	\"message\",\n  \"data\": \{\"insTemp\":19.3,  \"desTemp\":19.1, \"outTemp\":23.7 \}}";  

WiFiSSLClient client;

void setup() {
}
	
void loop() {
  client.connect(server, port);
  if (!client.connected()) { 
	; // service the error 
  } else {
      client.println("POST /v1.1/messages HTTP/1.1");
      client.println("Host: api.artik.cloud");
      client.println("Accept: */*");
      client.println("Content-Type: application/json");
      client.println(AuthorizationData);

      // POST data section
      client.print("Content-Length: ");
      client.println(PostData.length());
      client.println();
      client.println(PostData);
  }
  delay(500);
  exit(0);
}
  1. Replace the ARTIK Cloud device placeholders with your own. As you will recall, they both come from my ARTIK Cloud as described here.
    • Paste in Device ID (sdid).
    • Paste in Device Token (accessToken).
    • Close the Device Info window and go to ARTIK Cloud Charts.
  2. Load the sketch to the ARTIK module to run it.

You have just sent ARTIK Cloud a data message using Web REST API protocols.

Automating the JSON Formatting

For Web calls, formatting the data as JSON is trickier than for MQTT, because:

  • The data is "nested" within the Web REST API call data: element.
  • The Web REST API needs to know Content-Length. MQTT just uses the null (\0) at the end of the string.

So we need to create not only the JSON data pairs, but also a root data object, and bigger buffers (both within this call and for the global buf).

To upgrade the previous Web code to automated JSON formatting:

  1. Add in this completed JSON formatting routine at the bottom of your sketch.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     int loadBuffer(float insTemp, float desTemp, float outTemp) {  
       StaticJsonBuffer<200> jsonBuffer; // reserve spot in memory
    
       JsonObject& root = jsonBuffer.createObject(); // create root objects
         root["sdid"] = "_your_DEVICE_ID_goes_here_"; // FIX 
         root["type"] = "message";
    
       JsonObject& dataPair = root.createNestedObject("data"); // create nested objects
         dataPair["insTemp"] = insTemp;  
         dataPair["desTemp"] = desTemp;  
         dataPair["outTemp"] = outTemp;  
    
       root.printTo(buf, sizeof(buf)); // JSON-print to buffer
    
       return (root.measureLength()); // also return length
     }
  2. Copy your Device ID (in the PostData string) to the JSON code.

  3. Delete the String PostData... line and replace it with

    1
     char buf[200];
  4. Replace the POST data section with the following code.

    1
    2
    3
    4
    5
           // Automated POST data section
           client.print("Content-Length: ");
           client.println(loadBuffer(19.3,19.1,23.7)); // loads buf, returns length
           client.println();
           client.println(buf);
  5. Load and run the new sketch.

You should once again be seeing data on ARTIK Cloud.

Troubleshooting Tip. Pay attention to StaticJsonBuffer and buf sizes when creating data objects for your own application. If tight for space, remove sdid and type from the JSON routine and return them to client.println(...) functions (shrink buffer sizes accordingly).

Adding Controls and Sensors

In this section, we present implementation details of the system hardware that you might find useful as part of the complete demonstration scenario.

Because you may not have a full set of edge device controls and sensors available to play with (not to mention the refrigerator/freezer, A/C, and economizer units), we are going to simulate just a few inputs using what we have on-hand: our Particle Photon module and a couple of sensors from previous exercises. Here's how we plan to get data.

Temp Inputs ID  
Inside actual insTemp photoresistor connected locally to the ARTIK module
Inside desired desTemp our Web page 'green' slider control
Outdoor outTemp "sunshine detector" attached to Photon

MQTT plus Web

For educational purposes, we want to demonstrate how you can "mix and match" elements of both MQTT and Web protocols to your advantage. So, for this concluding exercise, you will set up the ARTIK module to:

  • Act as an SSL/TLS-secured Web client to ARTIK Cloud
  • Run Node-RED as host for your custom user interface Web page
  • Run Mosquitto as MQTT broker for two clients:
    – the Particle Photon module
    – the Node-RED MQTT 'color' output node.

Mosquitto can run as an SSL/TLS-secured broker, but the required setup (including certificate generation) is not trivial and best left to another tutorial. Moreover, the Particle Photon device does not currently support SSL/TLS. Here, we will leave all MQTT link communications in cleartext (only temperature values are being exchanged).

Data Source Preparation

Before we code the sketch, take a moment to set up your data input sources.

insTemp: Local Thermometer

For our first data input, let's try a quick test. We would like to start sending live insTemp (inside temperature) values to ARTIK Cloud. However, a temperature sensor is a very slow-reacting device. We want something where we can see changes immediately.

So instead of a temperature sensor, let's use a spare photoresistor – the same type you used on the Photon board. This time we will connect it directly to the ARTIK board on analog pin 0.

  1. Wire up the photoresistor and series resistor as shown. You'll find the 3.3V and GND connections on J25 and the A0 analog input connection on J24 (both are on the Interface board for the ARTIK 530/710 system).

  2. In the POST data section of your Web REST API code, change the buffer loading call to use the analogRead function for pin A0 in place of the hard-coded test value for insTemp.

    1
     client.println(loadBuffer(analogRead(0),19.1,23.7));
  3. Comment out the exit(0); statement and adjust delay() so that the program will run in a loop and send new values every 100ms.

  4. Load and run the new sketch.

    You should once again be seeing data on ARTIK Cloud. Wave your hand slowly over the photoresistor – ARTIK Cloud data should be following along (delayed by a few seconds).

    No data? Try it the "manual" way shown in the ADC Interface guide.

  5. When done, reset the ARTIK board. Remember, there are rate limits to the amount of data that ARTIK Cloud will accept, and they are lower for Web REST than for MQTT. Therefore, you don't want to leave a high-data-rate sketch running indefinitely.

In the real application, you would want to send data only when there has been a meaningful change of the temperature being sensed.

outTemp: Remote Thermometer

For our second data input, we will use the Photon module as you had it set up previously, with its attached photoresistor. We don't really need to change the code – we'll just use its "brightness" messages and pretend that they are outside temperature messages. However, let's adjust one thing.

  1. Open the Photon code editor the way you did here.
  2. Reduce the frequency of the Photon "brightness" messages to every 3-5 seconds by changing the delay(1000) value.
  3. While here, double-check your IP address to make sure it is still correct.

If we left the rate at one message every second, the terminal display would be so busy that you might not catch other error messages.

Make sure that your Photon is still working the way it was originally; repeat that tutorial if you have any doubts.

desTemp: Web Temp Slider

For our final data input, we will use the color slider that we implemented as Web page code using Node-RED. As with outTemp, we won't change anything from that code, so we will take its "color" messages and pretend that they are temperature setting request messages coming from the homeowner's thermostat or climate control console.

You must implement the slider code in your Node-RED page for this feature to work.

  1. Revisit the Web Window to MQTT tutorial.
  2. Set up and verify the slider code to be working before proceeding.

Our code below uses the middle two hex digits (of 6) sent by that code, representing 'g' of r-g-b, and converting them to a value of 0-255.

Procedure

You'll find below the full code for this exercise. You haven't had to use the Photon module, Mosquitto, or Node-RED in the current tutorial so far, but you'll use them all in this part.

  1. Have Node-RED prepared (with its flow coded and known-working) as noted above, but do not run it at this time.

  2. Have your Photon device prepared (programmed and known-working) as noted above, but do not power it up just yet.

  3. Start with your ARTIK board freshly powered up; log in, and connect to your Wi-Fi network (dhclient wlan0).

  4. Run Mosquitto as the local MQTT broker. Do not start Node-RED.

    Troubleshooting Tip. Invoke Mosquitto with mosquitto -v & as 'verbose' mode shows events like ConnAck and Publish taking place.

  5. Copy the complete code listed below to a blank sketch in the Arduino IDE. Its functionality is explained in the next section.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <WiFi.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>
#include <DebugSerial.h>
  
// MQTT params  
char mqttServer[]     = "192.168.1.232";
int  mqttPort         = 1883;
char mqttClientName[] = "ARTIK-Arduino"; // or whatever you prefer
float insTemp, desTemp, outTemp;
      
WiFiClient ipStack;
MQTTClient mqttClient;
  
// Web REST API params
char server[] = "api.artik.cloud";  
int httpsPort = 443; //(port 443 is default for HTTPS)
String AuthorizationData = "Authorization: Bearer _your_DEVICE_TOKEN_goes_here_";
char buf[128];

WiFiSSLClient client;
  
void setup() {
  DebugSerial.begin(9600);  
  mqttClient.begin(mqttServer, mqttPort, ipStack);
  mqttClient.connect(mqttClientName);
  delay(500);
  mqttClient.subscribe("#");
}
  
void loop() {
  mqttClient.loop();
  delay(1000);
}  
  
void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
  DebugSerial.print("Message arrived [");
  DebugSerial.print(topic);
  DebugSerial.println("] ");
      
  if (topic=="brightness") { // from Photon
    // convert payload to float
    String s = payload;
    float temp = s.toFloat();
    if (temp < 600) {
      if (temp > 200) { //expected range for photoresistor
        outTemp = temp;
      }  
    }
      DebugSerial.print("outTemp:");
      DebugSerial.println(outTemp);

  } 
  if (topic=="color") { // from Node-RED slider
      const char p[] = { payload[2], payload[3],'\0' };
      desTemp = strtol(p, NULL, 16);
      DebugSerial.print("desTemp:");
      DebugSerial.println(desTemp);
  }      
     
  insTemp = analogRead(0)/40; // from ARTIK photoresistor
      DebugSerial.print("insTemp:");
      DebugSerial.println(insTemp);
    
  // load current values into the buffer
  int bufLength = loadBuffer(insTemp,desTemp,outTemp);
  
  // send it out to ARTIK Cloud
  client.connect(server, httpsPort);
  delay(100);
  if (!client.connected()) { 
     DebugSerial.println("No connection to ARTIK Cloud!");
     ; // service the error 
   } 
   else {
     client.println("POST /v1.1/messages HTTP/1.1");
     client.println("Host: api.artik.cloud");
     client.println("Accept: */*");
     client.println("Content-Type: application/json");
     client.println(AuthorizationData);
     client.print("Content-Length: ");
    
     client.println(bufLength);
     client.println();
     client.println(buf);
   }
}
    
int loadBuffer(float insTemp, float desTemp, float outTemp) {  
  // Step 1: reserve memory space
  StaticJsonBuffer<200> jsonBuffer;
    
  // Step 2: Build object tree root in memory
  JsonObject& root = jsonBuffer.createObject(); 
  root["sdid"] = "_your_DEVICE_ID_goes_here_"; // FIX 
  root["type"] = "message";
    
  // Step 2A: Build nested object within root "data:" element  
  JsonObject& dataPair = root.createNestedObject("data");  
  dataPair["insTemp"] = insTemp;  
  dataPair["desTemp"] = desTemp;  
  dataPair["outTemp"] = outTemp;  
    
  // Step 3: "print" JSON-formatted info to the buffer
  root.printTo(buf, sizeof(buf));
  return (root.measureLength()+1);
}
  1. Replace the mqttServer address with your own localhost IP address.
  2. Update the Device information to use your ARTIK Cloud device.
    • Log in to My ARTIK Cloud, and click on the gear to your device.
    • Copy the information to two places: Device ID (near the bottom) and Device Token (near the top).
    • Close the Device Info screen and go to the ARTIK Cloud Charts page.
  3. Load the code to the ARTIK module to run it. Because you ran Mosquitto in verbose mode, you should see ConnAck and SubAck screen messages like these.

No data? To help troubleshoot, take advantage of the debug facilities:
#include <DebugSerial.h>
DebugSerial.begin(9600) within setup() {...}
– Add DebugSerial.println(xxx) as needed to print variables.

  1. Publish desTemp ('color') data from Node-RED.
    • Run Node-RED, set up the way you left off at the end of the Web Window to MQTT exercise (with the slider code added into your Web HTML template).
    • Look at the terminal window to verify connection. There should not be any Publish messages yet.
    • Move the "green" slider on the Node-RED Web page and look for Publish.
    • Watch for output on ARTIK Cloud.
  2. Publish outTemp ('brightness') data from Photon.
    • Power up the pre-programmed Photon module with its photoresistor connected.
    • Look at the terminal window to verify connection and publishing.
    • Watch for output on ARTIK Cloud.

Feel free to connect up the Photon and Node-RED in the reverse order. They are both just Mosquitto clients so it should work either way.

How It Works

The Web code is unchanged from the earlier exercise. Its main loop() code now resides in the messageReceived routine.

The MQTTClient code is used with the local broker (not ARTIK Cloud), and is only Subscribe code (no Publish activity is needed here). The Subscribe aspects are new.

  • The subscribe topic of # in mqttClient.subscribe("#") captures all messages. The messageReceived code then checks to see if the topic is:
    – 'color' (desTemp slider output from Node-RED user interface page)
    – 'brightness' (outTemp sensor message sent every few seconds by Photon).
  • If the topic matches, conversion of the incoming payload bytes is as follows.
    – For 'color', the middle two bytes represent 'g' of r-g-b as two hexadecimal digits.
    – For 'brightness', the string is decimal.
    In both cases, the data is converted to the float values expected by ARTIK Cloud.
  • The messageReceived routine is only executed on receipt of a message.
  • insTemp (the local analog input we tested in Web code) is only checked when in the messageReceived routine; otherwise, its value is not updated (change this if desired).

Summary

You now have working Arduino IDE code examples not only for MQTT transactions, but also for making general-purpose Web POST calls. At this point, you should have some pretty good ideas about how to adapt our elementary code to your own sophisticated design.

In our next installment, we will fill in more details of our ARTIK module and ARTIK Cloud sample scenario. We will introduce the concept of Actions that you can send from ARTIK Cloud, and act on when received from ARTIK Cloud, and will discuss the Rules you can write to generate these Actions.

Last updated on: