ARM mbed M2X API Client: The ARM mbed client library is used to send/receive data to/from AT&T's M2X service from mbed LPC1768 microcontrollers.

Dependents:   m2x-demo-all M2X_MTS_ACCEL_DEMO M2X_MTS_Accel M2X_K64F_ACCEL ... more

Committer:
citrusbyte
Date:
Wed Aug 13 01:56:18 2014 +0000
Revision:
9:48b088e317aa
Parent:
8:bd39886d72fb
Timestamp is now a required field

Who changed what in which revision?

UserRevisionLine numberNew contents of line
citrusbyte 5:ea68c8980ad8 1 #ifndef M2XStreamClient_h
citrusbyte 5:ea68c8980ad8 2 #define M2XStreamClient_h
citrusbyte 5:ea68c8980ad8 3
citrusbyte 5:ea68c8980ad8 4 #define MIN(a, b) (((a) > (b))?(b):(a))
citrusbyte 5:ea68c8980ad8 5
citrusbyte 6:e6d66d99dd6f 6 #define MBED_PLATFORM
citrusbyte 6:e6d66d99dd6f 7
citrusbyte 6:e6d66d99dd6f 8 #ifdef ARDUINO_PLATFORM
citrusbyte 6:e6d66d99dd6f 9 #include "Arduino.h"
citrusbyte 8:bd39886d72fb 10
citrusbyte 8:bd39886d72fb 11 #define USER_AGENT "User-Agent: M2X Arduino Client/0.1"
citrusbyte 6:e6d66d99dd6f 12 #endif
citrusbyte 6:e6d66d99dd6f 13
citrusbyte 6:e6d66d99dd6f 14 #ifdef MBED_PLATFORM
citrusbyte 5:ea68c8980ad8 15 #include "mbed.h"
citrusbyte 8:bd39886d72fb 16
citrusbyte 8:bd39886d72fb 17 #define USER_AGENT "User-Agent: M2X Mbed Client/0.1"
citrusbyte 6:e6d66d99dd6f 18 #endif
citrusbyte 6:e6d66d99dd6f 19
citrusbyte 5:ea68c8980ad8 20 #include "Client.h"
citrusbyte 6:e6d66d99dd6f 21 #include "NullPrint.h"
citrusbyte 6:e6d66d99dd6f 22
citrusbyte 6:e6d66d99dd6f 23 #ifdef DEBUG
citrusbyte 6:e6d66d99dd6f 24 #ifdef ARDUINO_PLATFORM
citrusbyte 6:e6d66d99dd6f 25 #define DBG(fmt_, data_) Serial.print(data_)
citrusbyte 6:e6d66d99dd6f 26 #define DBGLN(fmt_, data_) Serial.println(data_)
citrusbyte 6:e6d66d99dd6f 27 #define DBGLNEND Serial.println()
citrusbyte 6:e6d66d99dd6f 28 #endif // ARDUINO_PLATFORM
citrusbyte 5:ea68c8980ad8 29
citrusbyte 6:e6d66d99dd6f 30 #ifdef MBED_PLATFORM
citrusbyte 6:e6d66d99dd6f 31 #define DBG(fmt_, data_) printf((fmt_), (data_))
citrusbyte 6:e6d66d99dd6f 32 #define DBGLN(fmt_, data_) printf((fmt_), (data_)); printf("\n")
citrusbyte 6:e6d66d99dd6f 33 #define DBGLNEND printf("\n")
citrusbyte 6:e6d66d99dd6f 34 #endif // MBED_PLATFORM
citrusbyte 6:e6d66d99dd6f 35 #else
citrusbyte 6:e6d66d99dd6f 36 #define DBG(fmt_, data_)
citrusbyte 6:e6d66d99dd6f 37 #define DBGLN(fmt_, data_)
citrusbyte 6:e6d66d99dd6f 38 #define DBGLNEND
citrusbyte 6:e6d66d99dd6f 39 #endif // DEBUG
citrusbyte 6:e6d66d99dd6f 40
citrusbyte 6:e6d66d99dd6f 41 #define HEX(t_) ((char) (((t_) > 9) ? ((t_) - 10 + 'A') : ((t_) + '0')))
citrusbyte 6:e6d66d99dd6f 42 #define MAX_DOUBLE_DIGITS 7
citrusbyte 5:ea68c8980ad8 43
citrusbyte 5:ea68c8980ad8 44 static const int E_OK = 0;
citrusbyte 5:ea68c8980ad8 45 static const int E_NOCONNECTION = -1;
citrusbyte 5:ea68c8980ad8 46 static const int E_DISCONNECTED = -2;
citrusbyte 5:ea68c8980ad8 47 static const int E_NOTREACHABLE = -3;
citrusbyte 5:ea68c8980ad8 48 static const int E_INVALID = -4;
citrusbyte 5:ea68c8980ad8 49 static const int E_JSON_INVALID = -5;
citrusbyte 5:ea68c8980ad8 50
citrusbyte 5:ea68c8980ad8 51 typedef void (*stream_value_read_callback)(const char* at,
citrusbyte 5:ea68c8980ad8 52 const char* value,
citrusbyte 5:ea68c8980ad8 53 int index,
citrusbyte 5:ea68c8980ad8 54 void* context);
citrusbyte 5:ea68c8980ad8 55
citrusbyte 5:ea68c8980ad8 56 typedef void (*location_read_callback)(const char* name,
citrusbyte 5:ea68c8980ad8 57 double latitude,
citrusbyte 5:ea68c8980ad8 58 double longitude,
citrusbyte 5:ea68c8980ad8 59 double elevation,
citrusbyte 5:ea68c8980ad8 60 const char* timestamp,
citrusbyte 5:ea68c8980ad8 61 int index,
citrusbyte 5:ea68c8980ad8 62 void* context);
citrusbyte 5:ea68c8980ad8 63
citrusbyte 5:ea68c8980ad8 64 class M2XStreamClient {
citrusbyte 5:ea68c8980ad8 65 public:
citrusbyte 5:ea68c8980ad8 66 static const char* kDefaultM2XHost;
citrusbyte 5:ea68c8980ad8 67 static const int kDefaultM2XPort = 80;
citrusbyte 5:ea68c8980ad8 68
citrusbyte 5:ea68c8980ad8 69 M2XStreamClient(Client* client,
citrusbyte 5:ea68c8980ad8 70 const char* key,
citrusbyte 8:bd39886d72fb 71 int case_insensitive = 1,
citrusbyte 5:ea68c8980ad8 72 const char* host = kDefaultM2XHost,
citrusbyte 5:ea68c8980ad8 73 int port = kDefaultM2XPort);
citrusbyte 5:ea68c8980ad8 74
citrusbyte 6:e6d66d99dd6f 75 // Post data stream value, returns the HTTP status code
citrusbyte 6:e6d66d99dd6f 76 template <class T>
citrusbyte 6:e6d66d99dd6f 77 int post(const char* feedId, const char* streamName, T value);
citrusbyte 5:ea68c8980ad8 78
citrusbyte 6:e6d66d99dd6f 79 // Post multiple values to M2X all at once.
citrusbyte 6:e6d66d99dd6f 80 // +feedId+ - id of the feed to post values
citrusbyte 6:e6d66d99dd6f 81 // +streamNum+ - Number of streams to post
citrusbyte 6:e6d66d99dd6f 82 // +names+ - Array of stream names, the length of the array should
citrusbyte 6:e6d66d99dd6f 83 // be exactly +streamNum+
citrusbyte 6:e6d66d99dd6f 84 // +counts+ - Array of +streamNum+ length, each item in this array
citrusbyte 6:e6d66d99dd6f 85 // containing the number of values we want to post for each stream
citrusbyte 6:e6d66d99dd6f 86 // +ats+ - Timestamps for each value, the length of this array should
citrusbyte 6:e6d66d99dd6f 87 // be the some of all values in +counts+, for the first +counts[0]+
citrusbyte 6:e6d66d99dd6f 88 // items, the values belong to the first stream, for the following
citrusbyte 6:e6d66d99dd6f 89 // +counts[1]+ number of items, the values belong to the second stream,
citrusbyte 9:48b088e317aa 90 // etc. Notice that timestamps are required here: you must provide
citrusbyte 9:48b088e317aa 91 // a timestamp for each value posted.
citrusbyte 6:e6d66d99dd6f 92 // +values+ - Values to post. This works the same way as +ats+, the
citrusbyte 6:e6d66d99dd6f 93 // first +counts[0]+ number of items contain values to post to the first
citrusbyte 6:e6d66d99dd6f 94 // stream, the succeeding +counts[1]+ number of items contain values
citrusbyte 6:e6d66d99dd6f 95 // for the second stream, etc. The length of this array should be
citrusbyte 6:e6d66d99dd6f 96 // the sum of all values in +counts+ array.
citrusbyte 6:e6d66d99dd6f 97 template <class T>
citrusbyte 6:e6d66d99dd6f 98 int postMultiple(const char* feedId, int streamNum,
citrusbyte 6:e6d66d99dd6f 99 const char* names[], const int counts[],
citrusbyte 6:e6d66d99dd6f 100 const char* ats[], T values[]);
citrusbyte 6:e6d66d99dd6f 101
citrusbyte 6:e6d66d99dd6f 102 // Fetch values for a particular data stream. Since memory is
citrusbyte 5:ea68c8980ad8 103 // very limited on an Arduino, we cannot parse and get all the
citrusbyte 5:ea68c8980ad8 104 // data points in memory. Instead, we use callbacks here: whenever
citrusbyte 5:ea68c8980ad8 105 // a new data point is parsed, we call the callback using the values,
citrusbyte 5:ea68c8980ad8 106 // after that, the values will be thrown away to make space for new
citrusbyte 5:ea68c8980ad8 107 // values.
citrusbyte 5:ea68c8980ad8 108 // Note that you can also pass in a user-specified context in this
citrusbyte 5:ea68c8980ad8 109 // function, this context will be passed to the callback function
citrusbyte 5:ea68c8980ad8 110 // each time we get a data point.
citrusbyte 5:ea68c8980ad8 111 // For each data point, the callback will be called once. The HTTP
citrusbyte 5:ea68c8980ad8 112 // status code will be returned. And the content is only parsed when
citrusbyte 5:ea68c8980ad8 113 // the status code is 200.
citrusbyte 6:e6d66d99dd6f 114 int fetchValues(const char* feedId, const char* streamName,
citrusbyte 6:e6d66d99dd6f 115 stream_value_read_callback callback, void* context,
citrusbyte 6:e6d66d99dd6f 116 const char* startTime = NULL, const char* endTime = NULL,
citrusbyte 6:e6d66d99dd6f 117 const char* limit = NULL);
citrusbyte 5:ea68c8980ad8 118
citrusbyte 5:ea68c8980ad8 119 // Update datasource location
citrusbyte 5:ea68c8980ad8 120 // NOTE: On an Arduino Uno and other ATMEGA based boards, double has
citrusbyte 5:ea68c8980ad8 121 // 4-byte (32 bits) precision, which is the same as float. So there's
citrusbyte 5:ea68c8980ad8 122 // no natural double-precision floating number on these boards. With
citrusbyte 5:ea68c8980ad8 123 // a float value, we have a precision of roughly 7 digits, that means
citrusbyte 5:ea68c8980ad8 124 // either 5 or 6 digits after the floating point. According to wikipedia,
citrusbyte 5:ea68c8980ad8 125 // a difference of 0.00001 will give us ~1.1132m distance. If this
citrusbyte 5:ea68c8980ad8 126 // precision is good for you, you can use the double-version we provided
citrusbyte 5:ea68c8980ad8 127 // here. Otherwise, you may need to use the string-version and do the
citrusbyte 5:ea68c8980ad8 128 // actual conversion by yourselves.
citrusbyte 5:ea68c8980ad8 129 // However, with an Arduino Due board, double has 8-bytes (64 bits)
citrusbyte 5:ea68c8980ad8 130 // precision, which means you are free to use the double-version only
citrusbyte 5:ea68c8980ad8 131 // without any precision problems.
citrusbyte 5:ea68c8980ad8 132 // Returned value is the http status code.
citrusbyte 6:e6d66d99dd6f 133 template <class T>
citrusbyte 5:ea68c8980ad8 134 int updateLocation(const char* feedId, const char* name,
citrusbyte 6:e6d66d99dd6f 135 T latitude, T longitude, T elevation);
citrusbyte 5:ea68c8980ad8 136
citrusbyte 5:ea68c8980ad8 137 // Read location information for a feed. Also used callback to process
citrusbyte 5:ea68c8980ad8 138 // data points for memory reasons. The HTTP status code is returned,
citrusbyte 5:ea68c8980ad8 139 // response is only parsed when the HTTP status code is 200
citrusbyte 5:ea68c8980ad8 140 int readLocation(const char* feedId, location_read_callback callback,
citrusbyte 5:ea68c8980ad8 141 void* context);
citrusbyte 5:ea68c8980ad8 142 private:
citrusbyte 5:ea68c8980ad8 143 Client* _client;
citrusbyte 5:ea68c8980ad8 144 const char* _key;
citrusbyte 8:bd39886d72fb 145 int _case_insensitive;
citrusbyte 5:ea68c8980ad8 146 const char* _host;
citrusbyte 5:ea68c8980ad8 147 int _port;
citrusbyte 5:ea68c8980ad8 148 NullPrint _null_print;
citrusbyte 5:ea68c8980ad8 149
citrusbyte 5:ea68c8980ad8 150 // Writes the HTTP header part for updating a stream value
citrusbyte 6:e6d66d99dd6f 151 void writePostHeader(const char* feedId,
citrusbyte 5:ea68c8980ad8 152 const char* streamName,
citrusbyte 5:ea68c8980ad8 153 int contentLength);
citrusbyte 6:e6d66d99dd6f 154 // Writes HTTP header lines including M2X API Key, host, content
citrusbyte 5:ea68c8980ad8 155 // type and content length(if the body exists)
citrusbyte 5:ea68c8980ad8 156 void writeHttpHeader(int contentLength);
citrusbyte 5:ea68c8980ad8 157 // Parses HTTP response header and return the content length.
citrusbyte 5:ea68c8980ad8 158 // Note that this function does not parse all http headers, as long
citrusbyte 5:ea68c8980ad8 159 // as the content length is found, this function will return
citrusbyte 5:ea68c8980ad8 160 int readContentLength();
citrusbyte 5:ea68c8980ad8 161 // Skips all HTTP response header part. Return minus value in case
citrusbyte 5:ea68c8980ad8 162 // the connection is closed before we got all headers
citrusbyte 5:ea68c8980ad8 163 int skipHttpHeader();
citrusbyte 5:ea68c8980ad8 164 // Parses and returns the HTTP status code, note this function will
citrusbyte 5:ea68c8980ad8 165 // return immediately once it gets the status code
citrusbyte 5:ea68c8980ad8 166 int readStatusCode(bool closeClient);
citrusbyte 5:ea68c8980ad8 167 // Waits for a certain string pattern in the HTTP header, and returns
citrusbyte 5:ea68c8980ad8 168 // once the pattern is found. In the pattern, you can use '*' to denote
citrusbyte 5:ea68c8980ad8 169 // any character
citrusbyte 5:ea68c8980ad8 170 int waitForString(const char* str);
citrusbyte 5:ea68c8980ad8 171 // Closes the connection
citrusbyte 5:ea68c8980ad8 172 void close();
citrusbyte 5:ea68c8980ad8 173 // Parses JSON response of stream value API, and calls callback function
citrusbyte 5:ea68c8980ad8 174 // once we get a data point
citrusbyte 5:ea68c8980ad8 175 int readStreamValue(stream_value_read_callback callback, void* context);
citrusbyte 5:ea68c8980ad8 176 // Parses JSON response of location API, and calls callback function once
citrusbyte 5:ea68c8980ad8 177 // we get a data point
citrusbyte 5:ea68c8980ad8 178 int readLocation(location_read_callback callback, void* context);
citrusbyte 5:ea68c8980ad8 179 };
citrusbyte 5:ea68c8980ad8 180
citrusbyte 6:e6d66d99dd6f 181 #include "M2XStreamClient_template.h"
citrusbyte 6:e6d66d99dd6f 182
citrusbyte 5:ea68c8980ad8 183 #endif /* M2XStreamClient_h */
citrusbyte 5:ea68c8980ad8 184