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:
Fri Jan 03 11:55:17 2014 +0000
Revision:
8:bd39886d72fb
Parent:
6:e6d66d99dd6f
Child:
9:48b088e317aa
Update mbed library

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 6:e6d66d99dd6f 90 // etc. Note timestamps are optional, if a value does not havee timestamp,
citrusbyte 6:e6d66d99dd6f 91 // we can simply put NULL here, or we can put NULl for +ats+, meaning
citrusbyte 6:e6d66d99dd6f 92 // none of the values has a timestamp
citrusbyte 6:e6d66d99dd6f 93 // +values+ - Values to post. This works the same way as +ats+, the
citrusbyte 6:e6d66d99dd6f 94 // first +counts[0]+ number of items contain values to post to the first
citrusbyte 6:e6d66d99dd6f 95 // stream, the succeeding +counts[1]+ number of items contain values
citrusbyte 6:e6d66d99dd6f 96 // for the second stream, etc. The length of this array should be
citrusbyte 6:e6d66d99dd6f 97 // the sum of all values in +counts+ array.
citrusbyte 6:e6d66d99dd6f 98 template <class T>
citrusbyte 6:e6d66d99dd6f 99 int postMultiple(const char* feedId, int streamNum,
citrusbyte 6:e6d66d99dd6f 100 const char* names[], const int counts[],
citrusbyte 6:e6d66d99dd6f 101 const char* ats[], T values[]);
citrusbyte 6:e6d66d99dd6f 102
citrusbyte 6:e6d66d99dd6f 103 // Fetch values for a particular data stream. Since memory is
citrusbyte 5:ea68c8980ad8 104 // very limited on an Arduino, we cannot parse and get all the
citrusbyte 5:ea68c8980ad8 105 // data points in memory. Instead, we use callbacks here: whenever
citrusbyte 5:ea68c8980ad8 106 // a new data point is parsed, we call the callback using the values,
citrusbyte 5:ea68c8980ad8 107 // after that, the values will be thrown away to make space for new
citrusbyte 5:ea68c8980ad8 108 // values.
citrusbyte 5:ea68c8980ad8 109 // Note that you can also pass in a user-specified context in this
citrusbyte 5:ea68c8980ad8 110 // function, this context will be passed to the callback function
citrusbyte 5:ea68c8980ad8 111 // each time we get a data point.
citrusbyte 5:ea68c8980ad8 112 // For each data point, the callback will be called once. The HTTP
citrusbyte 5:ea68c8980ad8 113 // status code will be returned. And the content is only parsed when
citrusbyte 5:ea68c8980ad8 114 // the status code is 200.
citrusbyte 6:e6d66d99dd6f 115 int fetchValues(const char* feedId, const char* streamName,
citrusbyte 6:e6d66d99dd6f 116 stream_value_read_callback callback, void* context,
citrusbyte 6:e6d66d99dd6f 117 const char* startTime = NULL, const char* endTime = NULL,
citrusbyte 6:e6d66d99dd6f 118 const char* limit = NULL);
citrusbyte 5:ea68c8980ad8 119
citrusbyte 5:ea68c8980ad8 120 // Update datasource location
citrusbyte 5:ea68c8980ad8 121 // NOTE: On an Arduino Uno and other ATMEGA based boards, double has
citrusbyte 5:ea68c8980ad8 122 // 4-byte (32 bits) precision, which is the same as float. So there's
citrusbyte 5:ea68c8980ad8 123 // no natural double-precision floating number on these boards. With
citrusbyte 5:ea68c8980ad8 124 // a float value, we have a precision of roughly 7 digits, that means
citrusbyte 5:ea68c8980ad8 125 // either 5 or 6 digits after the floating point. According to wikipedia,
citrusbyte 5:ea68c8980ad8 126 // a difference of 0.00001 will give us ~1.1132m distance. If this
citrusbyte 5:ea68c8980ad8 127 // precision is good for you, you can use the double-version we provided
citrusbyte 5:ea68c8980ad8 128 // here. Otherwise, you may need to use the string-version and do the
citrusbyte 5:ea68c8980ad8 129 // actual conversion by yourselves.
citrusbyte 5:ea68c8980ad8 130 // However, with an Arduino Due board, double has 8-bytes (64 bits)
citrusbyte 5:ea68c8980ad8 131 // precision, which means you are free to use the double-version only
citrusbyte 5:ea68c8980ad8 132 // without any precision problems.
citrusbyte 5:ea68c8980ad8 133 // Returned value is the http status code.
citrusbyte 6:e6d66d99dd6f 134 template <class T>
citrusbyte 5:ea68c8980ad8 135 int updateLocation(const char* feedId, const char* name,
citrusbyte 6:e6d66d99dd6f 136 T latitude, T longitude, T elevation);
citrusbyte 5:ea68c8980ad8 137
citrusbyte 5:ea68c8980ad8 138 // Read location information for a feed. Also used callback to process
citrusbyte 5:ea68c8980ad8 139 // data points for memory reasons. The HTTP status code is returned,
citrusbyte 5:ea68c8980ad8 140 // response is only parsed when the HTTP status code is 200
citrusbyte 5:ea68c8980ad8 141 int readLocation(const char* feedId, location_read_callback callback,
citrusbyte 5:ea68c8980ad8 142 void* context);
citrusbyte 5:ea68c8980ad8 143 private:
citrusbyte 5:ea68c8980ad8 144 Client* _client;
citrusbyte 5:ea68c8980ad8 145 const char* _key;
citrusbyte 8:bd39886d72fb 146 int _case_insensitive;
citrusbyte 5:ea68c8980ad8 147 const char* _host;
citrusbyte 5:ea68c8980ad8 148 int _port;
citrusbyte 5:ea68c8980ad8 149 NullPrint _null_print;
citrusbyte 5:ea68c8980ad8 150
citrusbyte 5:ea68c8980ad8 151 // Writes the HTTP header part for updating a stream value
citrusbyte 6:e6d66d99dd6f 152 void writePostHeader(const char* feedId,
citrusbyte 5:ea68c8980ad8 153 const char* streamName,
citrusbyte 5:ea68c8980ad8 154 int contentLength);
citrusbyte 6:e6d66d99dd6f 155 // Writes HTTP header lines including M2X API Key, host, content
citrusbyte 5:ea68c8980ad8 156 // type and content length(if the body exists)
citrusbyte 5:ea68c8980ad8 157 void writeHttpHeader(int contentLength);
citrusbyte 5:ea68c8980ad8 158 // Parses HTTP response header and return the content length.
citrusbyte 5:ea68c8980ad8 159 // Note that this function does not parse all http headers, as long
citrusbyte 5:ea68c8980ad8 160 // as the content length is found, this function will return
citrusbyte 5:ea68c8980ad8 161 int readContentLength();
citrusbyte 5:ea68c8980ad8 162 // Skips all HTTP response header part. Return minus value in case
citrusbyte 5:ea68c8980ad8 163 // the connection is closed before we got all headers
citrusbyte 5:ea68c8980ad8 164 int skipHttpHeader();
citrusbyte 5:ea68c8980ad8 165 // Parses and returns the HTTP status code, note this function will
citrusbyte 5:ea68c8980ad8 166 // return immediately once it gets the status code
citrusbyte 5:ea68c8980ad8 167 int readStatusCode(bool closeClient);
citrusbyte 5:ea68c8980ad8 168 // Waits for a certain string pattern in the HTTP header, and returns
citrusbyte 5:ea68c8980ad8 169 // once the pattern is found. In the pattern, you can use '*' to denote
citrusbyte 5:ea68c8980ad8 170 // any character
citrusbyte 5:ea68c8980ad8 171 int waitForString(const char* str);
citrusbyte 5:ea68c8980ad8 172 // Closes the connection
citrusbyte 5:ea68c8980ad8 173 void close();
citrusbyte 5:ea68c8980ad8 174 // Parses JSON response of stream value API, and calls callback function
citrusbyte 5:ea68c8980ad8 175 // once we get a data point
citrusbyte 5:ea68c8980ad8 176 int readStreamValue(stream_value_read_callback callback, void* context);
citrusbyte 5:ea68c8980ad8 177 // Parses JSON response of location API, and calls callback function once
citrusbyte 5:ea68c8980ad8 178 // we get a data point
citrusbyte 5:ea68c8980ad8 179 int readLocation(location_read_callback callback, void* context);
citrusbyte 5:ea68c8980ad8 180 };
citrusbyte 5:ea68c8980ad8 181
citrusbyte 6:e6d66d99dd6f 182 #include "M2XStreamClient_template.h"
citrusbyte 6:e6d66d99dd6f 183
citrusbyte 5:ea68c8980ad8 184 #endif /* M2XStreamClient_h */
citrusbyte 5:ea68c8980ad8 185