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