Pubnub demo for AT&T IoT Starter Kit. Functionally similar to the Flow demo.

Dependencies:   FXOS8700CQ MODSERIAL mbed

http://pubnub.github.io/slides/workshop/pictures/broadcast.png

Pubnub demo for AT&T IoT Starter Kit

This demo is functionally similar to the Flow demo, so you can find general information here: https://developer.mbed.org/users/JMF/code/Avnet_ATT_Cellular_IOT/.

The only difference is that we use Pubnub to publish the measurements and subscribe to receiving the instructions to set the LED.

Settings

Pubnub related settings are:

Pubnub settings in `config_me.h`

PUBNUB_SUBSCRIBE_KEY
PUBNUB_PUBLISH_KEY
PUBNUB_CHANNEL

All are documented in their respective comments.

Pubnub context class

Similar to Pubnub SDKs, we provide a Pubnub context class. It is defined in pubnub.h header file and implemented in pubnub.cpp.

It provides only the fundamental "publish" and "subscribe" methods. They are documented in the header file.

This class is reusable in other code (it is not specific to this demo), it has a very narrow interface to the AT&T IoT cellular modem code. For example of use, you can look at the main() (in main.c).

Sample of published data

Published message w/measurement data

{"serial":"vstarterkit001","temp":89.61,"humidity":35,"accelX":0.97,"accelY":0.013,"accelZ":-0.038}

Don't worry, nobody got burnt, the temperature is in degrees Fahrenheit. :)

Publish a message (from, say, the Pubnub console http://pubnub.com/console) of the form {"LED":<name-of-the-color>} on the channel that this demo listens to (default is hello_world) to turn the LED to that color on the Starter Kit:

Turn LED to red

{"LED":"Red"}

Turn LED to green

{"LED":"Green"}

Turn LED to blue

{"LED":"Blue"}
Committer:
sveljko
Date:
Fri Sep 02 17:44:55 2016 +0000
Revision:
81:a5df87708b9a
First version that works, forked from official AT&T IoT starter kit repository.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sveljko 81:a5df87708b9a 1 #include "pubnub.h"
sveljko 81:a5df87708b9a 2
sveljko 81:a5df87708b9a 3 #include "mbed.h"
sveljko 81:a5df87708b9a 4 #include <string>
sveljko 81:a5df87708b9a 5 #include "wnc_control.h"
sveljko 81:a5df87708b9a 6
sveljko 81:a5df87708b9a 7 #include <stdio.h>
sveljko 81:a5df87708b9a 8
sveljko 81:a5df87708b9a 9
sveljko 81:a5df87708b9a 10 pubnub_ctx::pubnub_ctx(char const* pub_key, char const *key_sub)
sveljko 81:a5df87708b9a 11 : d_pub_key(pub_key)
sveljko 81:a5df87708b9a 12 , d_key_sub(key_sub)
sveljko 81:a5df87708b9a 13 , d_token("0")
sveljko 81:a5df87708b9a 14 {
sveljko 81:a5df87708b9a 15 }
sveljko 81:a5df87708b9a 16
sveljko 81:a5df87708b9a 17
sveljko 81:a5df87708b9a 18 pubnub_ctx::~pubnub_ctx()
sveljko 81:a5df87708b9a 19 {
sveljko 81:a5df87708b9a 20 }
sveljko 81:a5df87708b9a 21
sveljko 81:a5df87708b9a 22
sveljko 81:a5df87708b9a 23 static void append_epilogue(std::string &s, std::string const& uuid, std::string const& auth)
sveljko 81:a5df87708b9a 24 {
sveljko 81:a5df87708b9a 25 s += "?pnsdk=AvnetATTmbed";
sveljko 81:a5df87708b9a 26 if (!uuid.empty()) {
sveljko 81:a5df87708b9a 27 s += "&uuid=";
sveljko 81:a5df87708b9a 28 s += uuid;
sveljko 81:a5df87708b9a 29 }
sveljko 81:a5df87708b9a 30 if (!auth.empty()) {
sveljko 81:a5df87708b9a 31 s += "&auth=";
sveljko 81:a5df87708b9a 32 s += auth;
sveljko 81:a5df87708b9a 33 }
sveljko 81:a5df87708b9a 34 s += " HTTP/1.1\r\nHost: pubsub.pubnub.com\r\n\r\n";
sveljko 81:a5df87708b9a 35 }
sveljko 81:a5df87708b9a 36
sveljko 81:a5df87708b9a 37
sveljko 81:a5df87708b9a 38 pubnub_ctx::result pubnub_ctx::publish(char const* channel, char const* message)
sveljko 81:a5df87708b9a 39 {
sveljko 81:a5df87708b9a 40 char const *pmessage = message;
sveljko 81:a5df87708b9a 41 std::string s("GET /publish/");
sveljko 81:a5df87708b9a 42 s += d_pub_key; s += "/";
sveljko 81:a5df87708b9a 43 s += d_key_sub; s += "/0/";
sveljko 81:a5df87708b9a 44 s += channel; s += "/0/";
sveljko 81:a5df87708b9a 45
sveljko 81:a5df87708b9a 46 while (pmessage[0]) {
sveljko 81:a5df87708b9a 47 /* RFC 3986 Unreserved characters plus few
sveljko 81:a5df87708b9a 48 * safe reserved ones. */
sveljko 81:a5df87708b9a 49 size_t okspan = strspn(pmessage, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~" ",=:;@[]");
sveljko 81:a5df87708b9a 50 if (okspan > 0) {
sveljko 81:a5df87708b9a 51 s.append(pmessage, okspan);
sveljko 81:a5df87708b9a 52 pmessage += okspan;
sveljko 81:a5df87708b9a 53 }
sveljko 81:a5df87708b9a 54 if (pmessage[0]) {
sveljko 81:a5df87708b9a 55 /* %-encode a non-ok character. */
sveljko 81:a5df87708b9a 56 s.append(1, '%');
sveljko 81:a5df87708b9a 57 s.append(1, "0123456789ABCDEF"[pmessage[0] / 16]);
sveljko 81:a5df87708b9a 58 s.append(1, "0123456789ABCDEF"[pmessage[0] % 16]);
sveljko 81:a5df87708b9a 59 ++pmessage;
sveljko 81:a5df87708b9a 60 }
sveljko 81:a5df87708b9a 61 }
sveljko 81:a5df87708b9a 62
sveljko 81:a5df87708b9a 63 append_epilogue(s, d_uuid, d_auth);
sveljko 81:a5df87708b9a 64
sveljko 81:a5df87708b9a 65 sockwrite_mdm(s.c_str());
sveljko 81:a5df87708b9a 66 string response;
sveljko 81:a5df87708b9a 67 unsigned read = sockread_mdm(&response, 1024, 50);
sveljko 81:a5df87708b9a 68
sveljko 81:a5df87708b9a 69 if (read < 5) {
sveljko 81:a5df87708b9a 70 extern Serial pc;
sveljko 81:a5df87708b9a 71 pc.printf("read = %d\r\n", read);
sveljko 81:a5df87708b9a 72 return response_too_short;
sveljko 81:a5df87708b9a 73 }
sveljko 81:a5df87708b9a 74 char const* start = strchr(response.data(), '[');
sveljko 81:a5df87708b9a 75 if (NULL == start) {
sveljko 81:a5df87708b9a 76 return missing_open_bracket;
sveljko 81:a5df87708b9a 77 }
sveljko 81:a5df87708b9a 78 if (NULL == strrchr(response.data() + response.size() - 1, ']')) {
sveljko 81:a5df87708b9a 79 return missing_close_bracket;
sveljko 81:a5df87708b9a 80 }
sveljko 81:a5df87708b9a 81
sveljko 81:a5df87708b9a 82 if (1 != strtol(start + 1, NULL, 10)) {
sveljko 81:a5df87708b9a 83 return publish_failed;
sveljko 81:a5df87708b9a 84 }
sveljko 81:a5df87708b9a 85
sveljko 81:a5df87708b9a 86 return ok;
sveljko 81:a5df87708b9a 87 }
sveljko 81:a5df87708b9a 88
sveljko 81:a5df87708b9a 89 pubnub_ctx::result pubnub_ctx::subscribe(char const* channel, std::vector<std::string>& messages)
sveljko 81:a5df87708b9a 90 {
sveljko 81:a5df87708b9a 91 std::string s("GET /subscribe/");
sveljko 81:a5df87708b9a 92 s += d_key_sub; s += "/";
sveljko 81:a5df87708b9a 93 s += channel; s += "/0/";
sveljko 81:a5df87708b9a 94 s += d_token;;
sveljko 81:a5df87708b9a 95 append_epilogue(s, d_uuid, d_auth);
sveljko 81:a5df87708b9a 96
sveljko 81:a5df87708b9a 97 sockwrite_mdm(s.c_str());
sveljko 81:a5df87708b9a 98 string response;
sveljko 81:a5df87708b9a 99 unsigned read = sockread_mdm(&response, 1024, 50);
sveljko 81:a5df87708b9a 100
sveljko 81:a5df87708b9a 101 if (read < 10) {
sveljko 81:a5df87708b9a 102 return response_too_short;
sveljko 81:a5df87708b9a 103 }
sveljko 81:a5df87708b9a 104 char const* start = strchr(response.c_str(), '[');
sveljko 81:a5df87708b9a 105 if (NULL == start) {
sveljko 81:a5df87708b9a 106 return missing_open_bracket;
sveljko 81:a5df87708b9a 107 }
sveljko 81:a5df87708b9a 108 if (start[1] != '[') {
sveljko 81:a5df87708b9a 109 return missing_open_bracket;
sveljko 81:a5df87708b9a 110 }
sveljko 81:a5df87708b9a 111 enum {
sveljko 81:a5df87708b9a 112 idle,
sveljko 81:a5df87708b9a 113 in_string,
sveljko 81:a5df87708b9a 114 escape,
sveljko 81:a5df87708b9a 115 done
sveljko 81:a5df87708b9a 116 } state = idle;
sveljko 81:a5df87708b9a 117 start += 2;
sveljko 81:a5df87708b9a 118 char const* end;
sveljko 81:a5df87708b9a 119 int bracket_level = 1;
sveljko 81:a5df87708b9a 120 for (end = start; (*end != '\0') && (state != done); ++end) {
sveljko 81:a5df87708b9a 121 char c = *end;
sveljko 81:a5df87708b9a 122 switch (state) {
sveljko 81:a5df87708b9a 123 case idle:
sveljko 81:a5df87708b9a 124 switch (c) {
sveljko 81:a5df87708b9a 125 case '"':
sveljko 81:a5df87708b9a 126 state = in_string;
sveljko 81:a5df87708b9a 127 break;
sveljko 81:a5df87708b9a 128 case ',':
sveljko 81:a5df87708b9a 129 if (bracket_level == 1) {
sveljko 81:a5df87708b9a 130 messages.push_back(std::string(start, end-start));
sveljko 81:a5df87708b9a 131 start = end + 1;
sveljko 81:a5df87708b9a 132 }
sveljko 81:a5df87708b9a 133 break;
sveljko 81:a5df87708b9a 134 case '{':
sveljko 81:a5df87708b9a 135 case '[':
sveljko 81:a5df87708b9a 136 ++bracket_level;
sveljko 81:a5df87708b9a 137 break;
sveljko 81:a5df87708b9a 138 case '}':
sveljko 81:a5df87708b9a 139 --bracket_level;
sveljko 81:a5df87708b9a 140 break;
sveljko 81:a5df87708b9a 141 case ']':
sveljko 81:a5df87708b9a 142 if (--bracket_level <= 0) {
sveljko 81:a5df87708b9a 143 if (end-start-1 > 0) {
sveljko 81:a5df87708b9a 144 messages.push_back(std::string(start, end-start));
sveljko 81:a5df87708b9a 145 }
sveljko 81:a5df87708b9a 146 state = done;
sveljko 81:a5df87708b9a 147 }
sveljko 81:a5df87708b9a 148 break;
sveljko 81:a5df87708b9a 149 }
sveljko 81:a5df87708b9a 150 break;
sveljko 81:a5df87708b9a 151 case in_string:
sveljko 81:a5df87708b9a 152 switch (c) {
sveljko 81:a5df87708b9a 153 case '"':
sveljko 81:a5df87708b9a 154 state = idle;
sveljko 81:a5df87708b9a 155 break;
sveljko 81:a5df87708b9a 156 case '\\':
sveljko 81:a5df87708b9a 157 state = escape;
sveljko 81:a5df87708b9a 158 break;
sveljko 81:a5df87708b9a 159 }
sveljko 81:a5df87708b9a 160 break;
sveljko 81:a5df87708b9a 161 case escape:
sveljko 81:a5df87708b9a 162 state = in_string;
sveljko 81:a5df87708b9a 163 break;
sveljko 81:a5df87708b9a 164 default:
sveljko 81:a5df87708b9a 165 state = done;
sveljko 81:a5df87708b9a 166 break;
sveljko 81:a5df87708b9a 167 }
sveljko 81:a5df87708b9a 168 }
sveljko 81:a5df87708b9a 169 if (state != done) {
sveljko 81:a5df87708b9a 170 return format_error;
sveljko 81:a5df87708b9a 171 }
sveljko 81:a5df87708b9a 172 if ((end[0] != ',') && (end[1] != '"')) {
sveljko 81:a5df87708b9a 173 return missing_time_token;
sveljko 81:a5df87708b9a 174 }
sveljko 81:a5df87708b9a 175 start = end + 2;
sveljko 81:a5df87708b9a 176 end = strchr(start, '"');
sveljko 81:a5df87708b9a 177 if (NULL == end) {
sveljko 81:a5df87708b9a 178 return bad_time_token;
sveljko 81:a5df87708b9a 179 }
sveljko 81:a5df87708b9a 180 d_token.assign(start, end-start);
sveljko 81:a5df87708b9a 181
sveljko 81:a5df87708b9a 182 return ok;
sveljko 81:a5df87708b9a 183 }