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 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 ARTIK 053 "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 toWiFiSSLClient
).
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.
- 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.) - 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.
- Install the Arduino .JSON library.
- 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
).
- 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) { } |
- Replace the ARTIK Cloud device placeholders with your own. As you will recall, they both come from My ARTIK Cloud.
-
Paste in Device ID (
sdid
) in two places. -
Paste in Device Token (
accessToken
). - Close the Device Info window and go to ARTIK Cloud Charts.
-
Take a moment to understand this compact code.
-
WiFiSSLClient
sets up SSL/TLS network connectivity forMQTTClient
; the two interact throughipCloudStack
. -
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.
-
- 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.
-
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));
-
-
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)); }
-
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);
-
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.
- 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); } |
-
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.
-
Paste in Device ID (
- 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:
-
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 }
-
Copy your Device ID (in the
PostData
string) to the JSON code. -
Delete the
String PostData...
line and replace it with1
char buf[200];
-
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);
-
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 ARTIK 053 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 ARTIK 053 module |
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 ARTIK 053 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. 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 ARTIK 053 board. This time we will connect it directly to the ARTIK 5/7/10 board on analog pin 0.
-
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).
-
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 forinsTemp
.1
client.println(loadBuffer(analogRead(0),19.1,23.7));
-
Comment out the
exit(0);
statement and adjustdelay()
so that the program will run in a loop and send new values every 100ms. -
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.
-
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 ARTIK 053 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.
Make sure that your ARTIK 053 module 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.
- Revisit the Web Window to MQTT tutorial.
- 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 ARTIK 053 module, Mosquitto, or Node-RED in the current tutorial so far, but you'll use them all in this part.
-
Have Node-RED prepared (with its flow coded and known-working) as noted above, but do not run it at this time.
-
Have your ARTIK 053 device prepared (programmed and known-working) as noted above, but do not power it up just yet.
-
Start with your ARTIK board freshly powered up; log in, and connect to your Wi-Fi network.
-
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. -
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") { // 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); } |
-
Replace the
mqttServer
address with your ownlocalhost
IP address. -
Update the Device information to use your ARTIK Cloud device.
- Log in to My ARTIK Cloud, and click on 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.
- 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.
-
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.
-
Publish
outTemp
('brightness') data from ARTIK 053 module.- Power up the pre-programmed ARTIK 053 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 ARTIK 053 module 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
#
inmqttClient.subscribe("#")
captures all messages. ThemessageReceived
code then checks to see if the topic is:
– 'color' (desTemp
slider output from Node-RED user interface page)
– 'brightness' (outTemp
sensor message sent by the ARTIK 053 module). - 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 thefloat
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 themessageReceived
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.