Modified M2XStreamClient

Fork of M2XStreamClient-JMF by Jim Flynn

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?

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 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