Building a Frivolous Internet Connected Display with ESP32
I am obsessed with numbers, are you? Examples in the demo are frivolous but the objective is to display that numbers that matter on a tiny OLED from all over the internet(sort of)!
We will be using services like IFTTT (which did not work well), Zapier (trial plan) etc to
fetch numbers from numerous services out there and show them on a tiny display. We will be using
the hornbill ESP32 Minima to connect to the internet (AWS IOT). We will expose a webhook
on our server to receive the trigger and then publish the message to display. Confused? Looking at
the image below might help.
This may not be the best appoach to do this, but this is what I could come up with you. If you can think
of anything better, please do comment!
Contents
[hide]The Parts
- Hornbill ESP32 Minima
- OLED 128x64
- Wires
- Plastic enclosure
- LiPo Battery
The Build
Measure the OLED size, mark it on the enclosure and make a cut out. We did it with a bench top drill. Start out by drilling small holes along side the marking.
File the rough edges to make a smooth cut out.
We plan to power it up with the LiPo battery. If you plan to use a USB charger, you might want to make one more cut out for it.
The Hornbill Minima comes with the LiPo battery connector. Only 4 connections are to be made for the display.
OLED Pin | ESP32 Pin | Description |
---|---|---|
SDA | 21 | Yellow wire |
SCL | 22 | White wire |
VCC | 3.3V | Red Wire |
GND | GND | Black wire |
Start with with soldering the wires on OLED first.
Then solder the wires on the Hornbill Minima Pads.
Now make appropriate changes in the firmware code. Download from the "code for FICD section"
Now, its is time to mount the display inside the case. We did this with the help of tape. You might design and print a tiny 3D printed case as well.
Now the display is ready for action. It will display hard-coded numbers from the firmware. In the next section we will look at using services like IFTTT and Zapier, to display numbers that matter.
Let us look at the data will flow throughout the example.
Attribute | Example Value | Description |
---|---|---|
service | Name of the service, this should match in the Arduino code | |
serviceTag | followers | This will be displayed in small font. It could be anything that describes the next attribute. |
value | 231 | The value shown in big font on the display. It can be a formatted number or string. |
Setting up the trigger Services
These services all triggers to be set up from various other services online. We tried IFTTT and Zapier in this tutorial. The IFTTT maker channel did not work well. Zapier did work well. You may try these or any other similar services as well. Note that the free plan for Zapier is limited. Opening an account and setting up a trigger is pretty straightforward and for that reason I'll skip those steps.
With all these services we will set up a HTTP POST request to be made whenever the event occurs. In the example below I configure a POST action if a new twitter search appear with a certain name.
You can get creative with the trigger part, it could be email, Instagram, Stocks, Time, Weather etc., I will cover the action part in detail. The end goal of the action part is to take the configured values and publish them on the display. However there is no direct way to do that. The trigger services use HTTP and our devices on Hornbill IO/ AWS IOT speak MQTT. Hence we need to write a small script to handle the post and publish the message to the display. I will cover this in the next section. Let us look at the action part now.
The URL handles the POST request with the fields described in the table above. The code for handling the post and publishing the message to device is described in the next section. The URL used in the example is disabled and you'll have to make one if needed. Also note that the triggers if not set properly can publish millions of messages which will cost a lot of money. So be sure to set them up properly.
Code on Web Server
In this section we will look at handling the POST data from the previous step and publishing the payload to the device. We use a node server with AWS IOT library to achieve this. You may as well use service like AWS lambda to achieve the same.
var express = require('express'); | |
var router = express.Router(); | |
var awsIot = require('aws-iot-device-sdk'); | |
router.post('/', function (req, res) { | |
var thingShadows = awsIot.thingShadow({ | |
keyPath: '<path to private key>', | |
certPath: '<path to certificate>', | |
caPath: '<path to root Ca>', | |
clientId: Math.random().toString(36).substring(7), | |
region: '<aws-region>' | |
}); | |
var payload={"state":{"desired": null }}; | |
var service_name = req.body.service; | |
var service_tag = req.body.serviceTag; | |
var service_value = req.body.value; | |
payload.state.desired = { service: service_name, | |
serviceTag: service_tag, | |
value: service_value | |
}; | |
var clientTokenUpdate; | |
thingShadows.on('connect', function () { | |
thingShadows.register('<thing name>', true, function () { | |
clientTokenUpdate = thingShadows.update('<thing name>', payload); | |
if (clientTokenUpdate === null) { | |
res.json({ status: 400, 'data': 'Error while publishing to device' }); | |
} else { | |
res.json({ status: 200, 'data': 'Published : ' + JSON.stringify(payload) }); | |
} | |
}); | |
}); | |
}); | |
module.exports = router; |
Code on the ESP32 Hardware
The code requires several configurations to work. Check the tutorials listed in the beginning of the code for details on setting up AWS IOT and using it with simpler examples first.
With this code you'll have to first set up the AWS Configuration
- /************************************************************************
- AWS Configuration
- /************************************************************************/
- char WIFI_SSID[]="your Wifi SSID";
- char WIFI_PASSWORD[]="Wifi Password";
- char HOST_ADDRESS[]="AWS host address";
- char CLIENT_ID[]= "client id";
- char TOPIC_NAME[]= "your thing/topic name";
- /***********************************************************************/
Also the services to be displayed need to configured.
- typedef enum{
- SERVICE_TWITTER,
- SERVICE_FACEBOOK,
- SERVICE_TIME,
- SERVICE_TEMPERATURE,
- SERVICE_MAX_OPTIONS
- };
Lastly, the bitmaps for the logs will also have to updated according to the service used.
The complete source code is listed below.
/* | |
* For detailed tutorial on building the project visit: | |
* https://exploreembedded.com/wiki/Building_a_Frivolous_Internet_Connected_Display_with_ESP32 | |
* Install the libraries listed in the tutorial before compiling the code. | |
* Reference links: | |
https://exploreembedded.com/wiki/Secure_IOT_with_AWS_and_Hornbill_ESP32 | |
https://exploreembedded.com/wiki/AWS_IOT_with_Arduino_ESP32 | |
* Library Links: | |
https://github.com/ExploreEmbedded/Hornbill-Examples/tree/master/arduino-esp32/AWS_IOT/examples | |
https://github.com/adafruit/Adafruit_SSD1306 | |
https://github.com/adafruit/Adafruit-GFX-Library | |
*/ | |
#include <Wire.h> | |
#include <WiFi.h> | |
#include <Adafruit_GFX.h> | |
#include <Adafruit_SSD1306.h> | |
#include <jsonParser.h> | |
#include <AWS_IOT.h> | |
AWS_IOT AWS_CLIENT; | |
/************************************************************************ | |
AWS Configuration | |
/************************************************************************/ | |
char WIFI_SSID[]="your Wifi SSID"; | |
char WIFI_PASSWORD[]="Wifi Password"; | |
char HOST_ADDRESS[]="AWS host address"; | |
char CLIENT_ID[]= "client id"; | |
char TOPIC_NAME[]= "your thing/topic name"; | |
/***********************************************************************/ | |
/************************************************************************* | |
OLED | |
*************************************************************************/ | |
#define OLED_RESET 0xFF | |
Adafruit_SSD1306 display(OLED_RESET); | |
#if (SSD1306_LCDHEIGHT != 64) | |
#error("Height incorrect, please fix Adafruit_SSD1306.h!"); | |
#endif | |
/************************************************************************/ | |
/********************************************************************************************************** | |
32x32 Horizontal Logos | |
***********************************************************************************************************/ | |
const uint8_t logoTwitter PROGMEM []= { | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, | |
0x00, 0x00, 0x3F, 0xCE, 0x30, 0x00, 0x7F, 0xFC, 0x38, 0x00, 0xFF, 0xF8, 0x7C, 0x00, 0xFF, 0xFE, | |
0x3E, 0x00, 0xFF, 0xFC, 0x3F, 0x80, 0xFF, 0xF8, 0x3F, 0xF0, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF8, | |
0x2F, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, | |
0x1F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xC0, | |
0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFE, 0x00, | |
0x00, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0x80, 0x00, | |
0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
}; | |
const uint8_t logoFacebook PROGMEM [] = { | |
0x0F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xF8, 0x1E, | |
0xFF, 0xFF, 0xF0, 0x1E, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, | |
0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0x00, 0x1F, | |
0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x1F, | |
0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, | |
0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, | |
0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0x7F, 0xFF, 0xC1, 0xFE, 0x7F, 0xFF, 0xC1, 0xFE, | |
0x3F, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00 | |
}; | |
const uint8_t logoTime PROGMEM [] = { | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x01, 0x00, 0x60, 0x00, 0x04, 0x08, 0x10, 0x00, | |
0x08, 0x00, 0x08, 0x00, 0x10, 0x08, 0x04, 0x00, 0x00, 0x08, 0x02, 0x00, 0x20, 0x08, 0x00, 0x00, | |
0x00, 0x08, 0x01, 0x00, 0x40, 0x08, 0x01, 0x80, 0x40, 0x08, 0x00, 0x80, 0x40, 0x08, 0x00, 0x80, | |
0x42, 0x0F, 0xF2, 0x80, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, | |
0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x03, 0x80, 0x10, 0x08, 0x02, 0x80, | |
0x08, 0x00, 0x04, 0x80, 0x04, 0x00, 0x3C, 0x78, 0x02, 0x00, 0x20, 0x08, 0x00, 0x80, 0x10, 0x10, | |
0x00, 0x3E, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x11, 0x20, 0x00, 0x00, 0x14, 0xE0, | |
0x00, 0x00, 0x18, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
}; | |
const uint8_t logoTemperature PROGMEM [] = { | |
0x06, 0x00, 0x0F, 0x00, 0x06, 0x00, 0x1F, 0x80, 0x1F, 0x87, 0xD9, 0x80, 0x1F, 0x80, 0x19, 0x80, | |
0x06, 0x00, 0x19, 0x80, 0x06, 0x01, 0xD9, 0x80, 0x00, 0x00, 0x19, 0x80, 0x00, 0x07, 0xF9, 0x80, | |
0x00, 0x00, 0x19, 0x80, 0x00, 0x01, 0xD9, 0x80, 0x00, 0x01, 0xDF, 0x80, 0x00, 0x00, 0x1F, 0x80, | |
0x00, 0x07, 0xFF, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x01, 0xDF, 0x80, 0x00, 0x00, 0x1F, 0x80, | |
0x1F, 0x80, 0x1F, 0x80, 0x1F, 0x87, 0xDF, 0x80, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x76, 0xE0, | |
0x00, 0x00, 0xE6, 0xF0, 0x00, 0x01, 0xDF, 0xB8, 0x00, 0x01, 0xBF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, | |
0x00, 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xBF, 0xD8, 0x00, 0x01, 0xBF, 0xD8, | |
0x00, 0x00, 0xDF, 0xB0, 0x00, 0x00, 0xE0, 0x70, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x1F, 0x80 | |
}; | |
const uint8_t logoHornbill PROGMEM [] = { | |
0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, | |
0xFC, 0xFC, 0x0F, 0xF0, 0x00, 0xC0, 0x31, 0xC6, 0x78, 0x70, 0x03, 0xE0, 0x01, 0xC0, 0x33, 0xCE, | |
0x30, 0x30, 0x01, 0xC0, 0x00, 0xC0, 0x01, 0xC6, 0x30, 0x30, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC6, | |
0x30, 0x31, 0xFD, 0xFF, 0xFC, 0xFE, 0x71, 0xC6, 0x3F, 0xF1, 0x8C, 0xED, 0x8C, 0xE7, 0x31, 0xC6, | |
0x30, 0x73, 0x0E, 0xE1, 0x8C, 0xC3, 0x31, 0xC6, 0x30, 0x33, 0x06, 0xE1, 0x8C, 0xC3, 0x31, 0xC6, | |
0x30, 0x33, 0x86, 0xE1, 0x8C, 0xC3, 0x31, 0xC6, 0x30, 0x33, 0x8C, 0xE1, 0x8C, 0xC3, 0x31, 0xC6, | |
0x78, 0x79, 0xDC, 0xE3, 0x9C, 0xEE, 0x39, 0xCE, 0x00, 0x08, 0x70, 0x00, 0x00, 0x38, 0x00, 0x00, | |
0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x7F, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x01, 0xDF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x07, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x1F, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x3D, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
}; | |
/*******************************************************************************************************/ | |
typedef enum{ | |
SERVICE_TWITTER, | |
SERVICE_FACEBOOK, | |
SERVICE_TIME, | |
SERVICE_TEMPERATURE, | |
SERVICE_MAX_OPTIONS | |
}; | |
jsmntok_t token[512]; | |
char rcvdPayload[512]; | |
char msgReceived=0; | |
int serviceNum = 0; | |
char supportedServices[SERVICE_MAX_OPTIONS][20]= | |
{ | |
"twitter", | |
"facebook", | |
"time", | |
"temperature" | |
}; | |
typedef enum{ | |
VALUE_NUM, | |
VALUE_FLOAT, | |
VALUE_STRING | |
}valueType_t; | |
typedef struct{ | |
char Tag[20]; | |
char value[20]; | |
const uint8_t *logo; | |
}serviceData_t; | |
serviceData_t service[SERVICE_MAX_OPTIONS]={ | |
/*serviceTag value LogoArray */ | |
{"tweets", "12345", logoTwitter}, | |
{"likes", "5678", logoFacebook}, | |
{"Time", "9:30", logoTime}, | |
{"Temp", "35", logoTemperature} | |
}; | |
void processReceivedMsg(); | |
void wifiInit(); | |
void connectToAWS(); | |
void mySubCallBackHandler (char *topicName, int payloadLen, char *payLoad) | |
{ | |
if(msgReceived==0) | |
{ | |
strncpy(rcvdPayload,payLoad,payloadLen); | |
rcvdPayload[payloadLen] = 0; | |
msgReceived = 1; | |
} | |
} | |
void setup() { | |
Serial.begin(115200); | |
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64) | |
wifiInit(); | |
connectToAWS(); | |
} | |
void loop() { | |
display.clearDisplay(); | |
if(service[serviceNum].logo != 0); // Display Logo if available | |
display.drawBitmap(0,0, service[serviceNum].logo, 32, 32, WHITE); // Display the Logo | |
display.setTextColor(WHITE); | |
display.setTextSize(2); | |
display.setCursor(36,0); | |
display.print(service[serviceNum].Tag); | |
display.setTextSize(3); | |
display.setCursor(32,32); | |
display.print(service[serviceNum].value); | |
display.setTextSize(1); | |
display.setCursor(64-(SERVICE_MAX_OPTIONS*3),56); | |
for(int i=0;i<=SERVICE_MAX_OPTIONS;i++) | |
{ | |
if(i==serviceNum) | |
{ | |
int x0,y0,x1,y1,x2,y2; | |
x0 = display.getCursorX()+3; | |
y0 = display.getCursorY()+3; | |
display.fillCircle(x0,y0,3,WHITE); | |
} | |
else | |
{ | |
display.write('.'); | |
} | |
} | |
if(serviceNum<(SERVICE_MAX_OPTIONS-1)) // Ensure the state machine is within the limits | |
{ | |
serviceNum++; // Go to next state | |
} | |
else | |
{ | |
serviceNum = 0; | |
} | |
display.display(); | |
if(msgReceived == 1) | |
{ | |
processReceivedMsg(); | |
msgReceived = 0; | |
} | |
if (WiFi.status() != WL_CONNECTED) | |
{ | |
hornbillInitMsgs("Wifi Disconnected, Reconnecting after 1sec"); | |
vTaskDelay(1000/portTICK_PERIOD_MS); | |
wifiInit(); | |
connectToAWS(); | |
} | |
vTaskDelay(2000/portTICK_PERIOD_MS); | |
} | |
void hornbillInitMsgs(char *msg) | |
{ | |
display.clearDisplay(); | |
display.setTextColor(WHITE); | |
display.drawBitmap(0,0, logoHornbill, 64, 32, WHITE); | |
display.setTextSize(1); | |
display.setCursor(0,40); | |
display.print(msg); | |
display.display(); | |
} | |
void wifiInit() | |
{ | |
int status = WL_IDLE_STATUS; | |
while (status != WL_CONNECTED) | |
{ | |
sprintf(rcvdPayload,"Reconnicting to SSID:%s",WIFI_SSID); | |
hornbillInitMsgs(rcvdPayload); | |
// Connect to WPA/WPA2 network. Change this line if using open or WEP network: | |
status = WiFi.begin(WIFI_SSID, WIFI_PASSWORD); | |
// wait 5 seconds for connection: | |
vTaskDelay(2000/portTICK_PERIOD_MS); | |
} | |
} | |
void connectToAWS() | |
{ | |
int rc,reconnectCnt=0; | |
hornbillInitMsgs("Connected to wifi"); | |
if(AWS_CLIENT.connect(HOST_ADDRESS,CLIENT_ID)== 0) | |
{ | |
hornbillInitMsgs("Connected to AWS"); | |
vTaskDelay(1000/portTICK_PERIOD_MS); | |
do{ | |
rc = AWS_CLIENT.subscribe(TOPIC_NAME,mySubCallBackHandler); | |
if(rc == 0) | |
{ | |
hornbillInitMsgs("Subscribe Successfull"); | |
vTaskDelay(1000/portTICK_PERIOD_MS); | |
} | |
else if(reconnectCnt++>5) | |
{ | |
hornbillInitMsgs("Subscribe Failed, Check the Thing Name and Certificates"); | |
while(1); | |
} | |
}while(rc != 0); | |
} | |
else | |
{ | |
hornbillInitMsgs("AWS connection failed, Check the HOST Address"); | |
while(1); | |
} | |
} | |
char ser[20], serTag[20],serVal[20]; | |
void processReceivedMsg() | |
{ | |
int i,r,index; | |
jsmn_parser_t tokenParser; | |
jsmn.Init(&tokenParser); | |
r = jsmn.parse(&tokenParser, rcvdPayload, strlen(rcvdPayload), token, sizeof(token)/sizeof(token[0])); | |
if (r < 0) { | |
return;// HORNBILL_IO_REQUEST_JSON_INVALID; | |
} | |
/* Assume the top-level element is an object */ | |
if (r < 1 || token[0].type != JSMN_OBJECT) { | |
return;// HORNBILL_IO_REQUEST_JSON_INVALID; | |
} | |
/* Loop over all keys of the root object */ | |
for (i = 1; i < r; i++) { | |
if (jsmn.equate(rcvdPayload, &token[i], "reported") == 0) { | |
/* We may use strndup() to fetch string value */ | |
return ; | |
}else if (jsmn.equate(rcvdPayload, &token[i], "desired") == 0) { | |
/* We may use strndup() to fetch string value */ | |
i++; | |
}else if (jsmn.equate(rcvdPayload, &token[i], "service") == 0) { | |
/* We may use strndup() to fetch string value */ | |
sprintf(ser,"%.*s", token[i+1].end-token[i+1].start,rcvdPayload + token[i+1].start); | |
i++; | |
} else if (jsmn.equate(rcvdPayload, &token[i], "serviceTag") == 0) { | |
/* We may want to do strtol() here to get numeric value */ | |
sprintf(serTag,"%.*s", token[i+1].end-token[i+1].start,rcvdPayload + token[i+1].start); | |
i++; | |
} else if (jsmn.equate(rcvdPayload, &token[i], "value") == 0) { | |
/* We may use strndup() to fetch string value */ | |
sprintf(serVal,"%.*s", token[i+1].end-token[i+1].start,rcvdPayload + token[i+1].start); | |
i++; | |
for(index=0;index<SERVICE_MAX_OPTIONS;index++) | |
{ | |
if(strcmp(ser,supportedServices[index])==0) | |
{ | |
strcpy(service[index].Tag,serTag); | |
strcpy(service[index].value,serVal); | |
break; | |
} | |
} | |
} | |
else { | |
// printf("Unexpected key: %.*s\n", token[i].end-token[i].start,rcvdPayload + token[i].start); | |
} | |
} | |
} |
Although this looks pretty straight forward. It needs understanding of several technologies. It would help being patient in pulling this off. I took substantial help of my team mates to make this happen. In fact I did nothing more than thinking of idea and writing the tutorial. If you need help in any of the steps do not hesitate to comment!