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

Files at this revision

API Documentation at this revision

Comitter:
citrusbyte
Date:
Wed Sep 10 13:07:34 2014 +0000
Parent:
4:ba0d02be2835
Child:
11:a11af0c81cfa
Commit message:
Sync changes with github repo

Changed in this revision

M2XStreamClient.cpp Show annotated file Show diff for this revision Revisions of this file
M2XStreamClient.h Show annotated file Show diff for this revision Revisions of this file
M2XStreamClient_template.h Show annotated file Show diff for this revision Revisions of this file
StreamParseFunctions.h Show annotated file Show diff for this revision Revisions of this file
--- a/M2XStreamClient.cpp	Sun Sep 07 17:56:18 2014 +0000
+++ b/M2XStreamClient.cpp	Wed Sep 10 13:07:34 2014 +0000
@@ -7,6 +7,7 @@
 
 const char* M2XStreamClient::kDefaultM2XHost = "api-m2x.att.com";
 
+static int write_delete_values(Print* print, const char* from, const char* end);
 int print_encoded_string(Print* print, const char* str);
 int tolower(int ch);
 
@@ -105,6 +106,32 @@
   return status;
 }
 
+int M2XStreamClient::deleteValues(const char* feedId, const char* streamName,
+                                  const char* from, const char* end) {
+  if (_client->connect(_host, _port)) {
+    DBGLN("%s", "Connected to M2X server!");
+    int length = write_delete_values(&_null_print, from, end);
+    writeDeleteHeader(feedId, streamName, length);
+    write_delete_values(_client, from, end);
+  } else {
+    DBGLN("%s", "ERROR: Cannot connect to M2X server!");
+    return E_NOCONNECTION;
+  }
+
+  return readStatusCode(true);
+}
+
+static int write_delete_values(Print* print, const char* from,
+                               const char* end) {
+  int bytes = 0;
+  bytes += print->print("{\"from\":\"");
+  bytes += print->print(from);
+  bytes += print->print("\",\"end\":\"");
+  bytes += print->print(end);
+  bytes += print->print("\"}");
+  return bytes;
+}
+
 // Encodes and prints string using Percent-encoding specified
 // in RFC 1738, Section 2.2
 int print_encoded_string(Print* print, const char* str) {
@@ -126,9 +153,9 @@
   return bytes;
 }
 
-void M2XStreamClient::writePostHeader(const char* feedId,
-                                      const char* streamName,
-                                      int contentLength) {
+void M2XStreamClient::writePutHeader(const char* feedId,
+                                     const char* streamName,
+                                     int contentLength) {
   _client->print("PUT /v1/feeds/");
   print_encoded_string(_client, feedId);
   _client->print("/streams/");
@@ -138,6 +165,19 @@
   writeHttpHeader(contentLength);
 }
 
+void M2XStreamClient::writeDeleteHeader(const char* feedId,
+                                        const char* streamName,
+                                        int contentLength) {
+  _client->print("DELETE /v1/feeds/");
+  print_encoded_string(_client, feedId);
+  _client->print("/streams/");
+  print_encoded_string(_client, streamName);
+  _client->print("/values");
+  _client->println(" HTTP/1.0");
+
+  writeHttpHeader(contentLength);
+}
+
 void M2XStreamClient::writeHttpHeader(int contentLength) {
   _client->println(USER_AGENT);
   _client->print("X-M2X-KEY: ");
@@ -310,8 +350,8 @@
 
   jsonlite_parser_callbacks cbs = jsonlite_default_callbacks;
   cbs.key_found = on_stream_key_found;
+  cbs.number_found = on_stream_number_found;
   cbs.string_found = on_stream_string_found;
-  cbs.number_found = on_stream_string_found;
   cbs.context.client_state = &state;
 
   jsonlite_parser p = jsonlite_parser_init(jsonlite_parser_estimate_size(5));
@@ -320,6 +360,7 @@
   jsonlite_result result = jsonlite_result_unknown;
   while (index < length) {
     int i = 0;
+
     DBG("%s", "Received Data: ");
     while ((i < BUF_LEN) && _client->available()) {
       buf[i++] = _client->read();
@@ -342,7 +383,7 @@
       close();
       return E_JSON_INVALID;
     }
-    
+
     index += i;
   }
 
--- a/M2XStreamClient.h	Sun Sep 07 17:56:18 2014 +0000
+++ b/M2XStreamClient.h	Wed Sep 10 13:07:34 2014 +0000
@@ -48,10 +48,18 @@
 static const int E_INVALID = -4;
 static const int E_JSON_INVALID = -5;
 
+/*
+ * +type+ indicates the value type: 1 for string, 2 for number
+ * NOTE that the value type here only contains a hint on how
+ * you can use the value. Even though 2 is returned, the value
+ * is still stored in (const char *), and atoi/atof is needed to
+ * get the actual value
+ */
 typedef void (*stream_value_read_callback)(const char* at,
                                            const char* value,
                                            int index,
-                                           void* context);
+                                           void* context,
+                                           int type);
 
 typedef void (*location_read_callback)(const char* name,
                                        double latitude,
@@ -72,9 +80,9 @@
                   const char* host = kDefaultM2XHost,
                   int port = kDefaultM2XPort);
 
-  // Post data stream value, returns the HTTP status code
+  // Push data stream value using PUT request, returns the HTTP status code
   template <class T>
-  int post(const char* feedId, const char* streamName, T value);
+  int put(const char* feedId, const char* streamName, T value);
 
   // Post multiple values to M2X all at once.
   // +feedId+ - id of the feed to post values
@@ -87,9 +95,8 @@
   // be the some of all values in +counts+, for the first +counts[0]+
   // items, the values belong to the first stream, for the following
   // +counts[1]+ number of items, the values belong to the second stream,
-  // etc. Note timestamps are optional, if a value does not havee timestamp,
-  // we can simply put NULL here, or we can put NULl for +ats+, meaning
-  // none of the values has a timestamp
+  // etc. Notice that timestamps are required here: you must provide
+  // a timestamp for each value posted.
   // +values+ - Values to post. This works the same way as +ats+, the
   // first +counts[0]+ number of items contain values to post to the first
   // stream, the succeeding +counts[1]+ number of items contain values
@@ -140,6 +147,23 @@
   // response is only parsed when the HTTP status code is 200
   int readLocation(const char* feedId, location_read_callback callback,
                    void* context);
+
+  // Delete values from a data stream
+  // You will need to provide from and end date/time strings in the ISO8601
+  // format "yyyy-mm-ddTHH:MM:SS.SSSZ" where
+  //   yyyy: the year
+  //   mm: the month
+  //   dd: the day
+  //   HH: the hour (24 hour format)
+  //   MM: the minute
+  //   SS.SSS: the seconds (to the millisecond)
+  // NOTE: the time is given in Zulu (GMT)
+  // M2X will delete all values within the from to end date/time range.
+  // The status code is 204 on success and 400 on a bad request (e.g. the
+  // timestamp is not in ISO8601 format or the from timestamp is not less than
+  // or equal to the end timestamp.
+  int deleteValues(const char* feedId, const char* streamName,
+                   const char* from, const char* end);
 private:
   Client* _client;
   const char* _key;
@@ -149,9 +173,13 @@
   NullPrint _null_print;
 
   // Writes the HTTP header part for updating a stream value
-  void writePostHeader(const char* feedId,
-                       const char* streamName,
-                       int contentLength);
+  void writePutHeader(const char* feedId,
+                      const char* streamName,
+                      int contentLength);
+  // Writes the HTTP header part for deleting stream values
+  void writeDeleteHeader(const char* feedId,
+                         const char* streamName,
+                         int contentLength);
   // Writes HTTP header lines including M2X API Key, host, content
   // type and content length(if the body exists)
   void writeHttpHeader(int contentLength);
--- a/M2XStreamClient_template.h	Sun Sep 07 17:56:18 2014 +0000
+++ b/M2XStreamClient_template.h	Wed Sep 10 13:07:34 2014 +0000
@@ -6,12 +6,12 @@
 int print_encoded_string(Print* print, const char* str);
 
 template <class T>
-int M2XStreamClient::post(const char* feedId, const char* streamName, T value) {
+int M2XStreamClient::put(const char* feedId, const char* streamName, T value) {
   if (_client->connect(_host, _port)) {
     DBGLN("%s", "Connected to M2X server!");
-    writePostHeader(feedId, streamName,
-                    //  for {"value": and }
-                    _null_print.print(value) + 10);
+    writePutHeader(feedId, streamName,
+                   //  for {"value": and }
+                   _null_print.print(value) + 10);
     _client->print("{\"value\":");
     _client->print(value);
     _client->print("}");
@@ -34,13 +34,9 @@
     bytes += print->print(names[i]);
     bytes += print->print("\":[");
     for (int j = 0; j < counts[i]; j++) {
-      bytes += print->print("{");
-      if (ats && ats[value_index]) {
-        bytes += print->print("\"at\": \"");
-        bytes += print->print(ats[value_index]);
-        bytes += print->print("\",");
-      }
-      bytes += print->print("\"value\": \"");
+      bytes += print->print("{\"at\": \"");
+      bytes += print->print(ats[value_index]);
+      bytes += print->print("\", \"value\": \"");
       bytes += print->print(values[value_index]);
       bytes += print->print("\"}");
       if (j < counts[i] - 1) { bytes += print->print(","); }
--- a/StreamParseFunctions.h	Sun Sep 07 17:56:18 2014 +0000
+++ b/StreamParseFunctions.h	Wed Sep 10 13:07:34 2014 +0000
@@ -3,7 +3,7 @@
 
 // Data structures and functions used to parse stream values
 
-#define STREAM_BUF_LEN 64
+#define STREAM_BUF_LEN 32
 
 typedef struct {
   uint8_t state;
@@ -40,11 +40,13 @@
   }
 }
 
-static void on_stream_string_found(jsonlite_callback_context* context,
-                                   jsonlite_token* token)
+static void on_stream_value_found(jsonlite_callback_context* context,
+                                  jsonlite_token* token,
+                                  int type)
 {
   stream_parsing_context_state* state =
       (stream_parsing_context_state*) context->client_state;
+
   if (TEST_IS_AT(state->state)) {
     strncpy(state->at_str, (const char*) token->start,
             MIN(token->end - token->start, STREAM_BUF_LEN));
@@ -59,9 +61,21 @@
 
   if (TEST_GOT_STREAM(state->state)) {
     state->callback(state->at_str, state->value_str,
-                    state->index++, state->context);
+                    state->index++, state->context, type);
     state->state = 0;
   }
 }
 
+static void on_stream_string_found(jsonlite_callback_context* context,
+                                   jsonlite_token* token)
+{
+  on_stream_value_found(context, token, 1);
+}
+
+static void on_stream_number_found(jsonlite_callback_context* context,
+                                   jsonlite_token* token)
+{
+  on_stream_value_found(context, token, 2);
+}
+
 #endif  /* StreamParseFunctions_h */