plotly interface based on ardunio sample code

Dependents:   Plotly_HelloWorld

Library for plotting a simple x/y scatter chart on the plot.ly website.

See plotly_HelloWorld for sample usage.

Revision:
2:d53d74ed68ac
Parent:
1:d532e96fca12
Child:
3:967be3d46701
--- a/plotly.cpp	Wed Jul 02 10:13:24 2014 +0000
+++ b/plotly.cpp	Thu Jul 03 15:21:30 2014 +0000
@@ -1,7 +1,7 @@
 #include "plotly.h"
 #include "mbed.h"
 
-#define plotlyURL "plot.ly"
+#define plotlyURL "arduino.plot.ly"
 
 #define dataURL "arduino.plot.ly"
 
@@ -25,6 +25,7 @@
     timezone = "America/Montreal";
     fileopt = "overwrite";
 
+    socket = NULL;
     initalised = false;
 }
 
@@ -46,24 +47,26 @@
         fprintf(stderr,"... Attempting to connect to plotly's REST servers\n");
     }
 
-    socket.set_blocking(false);
-
-    do {
+//    socket.set_blocking(false);
 
-        socket.connect(plotlyURL, 80);
-        wait(10);
-        if(!(socket.is_connected()) && (log_level < 4)) {
+    if (!dry_run) {
+        socket = new TCPSocketConnection();
+        while (socket->connect(plotlyURL, 80) < 0) {
             fprintf(stderr,"... Couldn\'t connect to plotly's REST servers... trying again!\n");
+            wait(1);
         }
-    } while (!(socket.is_connected()));
+    }
 
     if(log_level < 3) fprintf(stderr,"... Connected to plotly's REST servers\n");
-    
+
     if(log_level < 3) fprintf(stderr,"... Sending HTTP Post to plotly\n");
-    
+
     print_("POST /clientresp HTTP/1.1\r\n");
     print_("Host: 107.21.214.199\r\n");
-    print_("User-Agent: Arduino/0.5.1\r\n");
+    print_("User-Agent: mBedAA0.01\r\n");
+    print_("plotly-streamtoken: ");
+    print_(stream_tokens_[0]);
+    print_("\r\n");
 
     print_("Content-Length: ");
     int contentLength = 126 + len_(username_) + len_(fileopt) + nTraces_*(87+len_(maxpoints)) + (nTraces_-1)*2 + len_(filename_);
@@ -72,7 +75,6 @@
     } else {
         contentLength += 5;
     }
-    print_(contentLength);
     // contentLength =
     //   44  // first part of querystring below
     // + len_(username)  // upper bound on username length
@@ -92,8 +94,33 @@
     // 126 + len_(username) + len_(fileopt) + nTraces*(86+len(maxpoints)) + (nTraces-1)*2 + len_(filename)
     //
     // Terminate headers with new lines
+
+
+// big buffer method to generate the string so that length can be measured directly.
+
+
+//    fprintf(stderr,"AutoVersion:\n");
+    int lineLen = snprintf(buffer,k_bufferSize,"version=2.2&origin=plot&platform=arduino&un=%s&key=%s&args=[",username_,api_key_);
+    for(int i=0; i<nTraces_; i++) {
+        lineLen += snprintf((buffer+lineLen),k_bufferSize-lineLen,"{\"y\": [], \"x\": [], \"type\": \"scatter\", \"stream\": {\"token\": \"%s\", \"maxpoints\": %d}}%s",stream_tokens_[i],maxpoints,((nTraces_ > 1) && (i != nTraces_-1))?", ":"");
+    }
+    lineLen += snprintf((buffer+lineLen),k_bufferSize-lineLen,"]&kwargs={\"fileopt\": \"%s\", \"filename\": \"%s\", \"world_readable\": %s}",fileopt,filename_,world_readable?"true":"false");
+
+//    fprintf(stderr,buffer);
+//    fprintf(stderr,"\nLen = %d",lineLen);
+
+    print_(lineLen);
     print_("\r\n\r\n");
-
+    
+    lineLen = snprintf(buffer,k_bufferSize,"version=2.2&origin=plot&platform=arduino&un=%s&key=%s&args=[",username_,api_key_);
+    for(int i=0; i<nTraces_; i++) {
+        lineLen += snprintf((buffer+lineLen),k_bufferSize-lineLen,"{\"y\": [], \"x\": [], \"type\": \"scatter\", \"stream\": {\"token\": \"%s\", \"maxpoints\": %d}}%s",stream_tokens_[i],maxpoints,((nTraces_ > 1) && (i != nTraces_-1))?", ":"");
+    }
+    lineLen += snprintf((buffer+lineLen),k_bufferSize-lineLen,"]&kwargs={\"fileopt\": \"%s\", \"filename\": \"%s\", \"world_readable\": %s}",fileopt,filename_,world_readable?"true":"false");
+    sendFormatedText(buffer,lineLen);
+    
+    print_("\r\n");
+/*            
     // Start printing querystring body
     print_("version=2.2&origin=plot&platform=arduino&un=");
     print_(username_);
@@ -124,12 +151,14 @@
     print_("}");
     // final newline to terminate the POST
     print_("\r\n");
+*/
 
     //
     // Wait for a response
     // Parse the response for the "All Streams Go!" and proceed to streaming
     // if we find it
     //
+
     char allStreamsGo[] = "All Streams Go!";
     int asgCnt = 0; // asg stands for All Streams Go
     char url[] = "\"url\": \"http://107.21.214.199/~";
@@ -147,18 +176,18 @@
 
     if(!dry_run) {
         while(!proceed) {
-            int32_t dataIn = socket.receive(rxBuffer,127);
+            int32_t dataIn = socket->receive(buffer,k_bufferSize -1);
             if (dataIn < 0) {
                 if(log_level < 3) fprintf(stderr,"error reading network socket\n");
                 break;
             }
             if(dataIn > 0) {
-                rxBuffer[dataIn]=0;
+                buffer[dataIn]=0;
 
-                if(log_level < 2) fprintf(stderr,rxBuffer);
+                if(log_level < 2) fprintf(stderr,buffer);
 
                 for (int i = 0; i<dataIn; i++) {
-                    c = rxBuffer[i];
+                    c = buffer[i];
                     //
                     // Attempt to read the "All streams go" msg if it exists
                     // by comparing characters as they roll in
@@ -225,8 +254,15 @@
             fprintf(stderr,"\n");
         }
     }
-    initalised = proceed || dry_run;
-    return proceed;
+
+    if (proceed || dry_run) {
+      initalised = true;
+    }
+    if (socket) {
+      delete socket;
+      socket=NULL;
+      }
+    return initalised;
 }
 
 void plotly::openStream()
@@ -237,56 +273,73 @@
     //
     // Start request to stream servers
     //
-    if(log_level < 3) {} fprintf(stderr,"... Connecting to plotly's streaming servers...\n");
-    char server[] = dataURL;
-    int port = 80;
-    while ( !socket.connect(server, port) ) {
-        if(log_level < 4) fprintf(stderr,"... Couldn\'t connect to servers... trying again!\n");
-        fibonacci_ += fibonacci_;
-        wait(10);
+
+    if (socket) {
+        delete socket;
+        socket = NULL;
+        }
+        
+
+    if(log_level < 3) fprintf(stderr,"... Connecting to plotly's streaming servers...\n");
+
+
+    if (!dry_run && !socket) {
+        socket = new TCPSocketConnection();
+        while (socket->connect(dataURL, 80) < 0) {
+            fprintf(stderr,"... Couldn\'t connect to servers... trying again!\n");
+            wait(10);
+        }
     }
-    fibonacci_ = 1;
-    if(log_level < 3) {} fprintf(stderr,"... Connected to plotly's streaming servers\n... Initializing stream\n");
+
+    if(log_level < 3) fprintf(stderr,"... Connected to plotly's streaming servers\n... Initializing stream\n");
 
     print_("POST / HTTP/1.1\r\n");
     print_("Host: 127.0.0.1\r\n");
-    print_("User-Agent: Python\r\n");
+    print_("User-Agent: mBedAA0.01\r\n");
     print_("Transfer-Encoding: chunked\r\n");
-    print_("Connection: close\r\n");
-    if(convertTimestamp) {
-        print_("plotly-convertTimestamp: \"");
-        print_(timezone);
-        print_("\"");
-    }
-    print_("\r\n\r\n");
+    print_("Connection: keep-alive\r\n");
+    print_("plotly-streamtoken: ");
+    print_(stream_tokens_[0]);
+    print_("\r\n");
+//    if(convertTimestamp) {
+//        print_("plotly-convertTimestamp: \"");
+//        print_(timezone);
+//        print_("\"");
+//        print_("\r\n");
+//    }
+    print_("\r\n");
 
     if(log_level < 3) fprintf(stderr,"... Done initializing, ready to stream!\n");
 }
 
 void plotly::closeStream()
 {
-    print_("0\r\n\r\n");
-    socket.close();
+    if (socket) {
+        if (socket->is_connected()) {
+          print_("0\r\n\r\n");
+          socket->close();
+        }
+        delete socket;
+    socket=NULL;
+    }
 }
 
 void plotly::reconnectStream()
 {
-    if (!initalised)
-        return;
-
-    while(!socket.is_connected()) {
+    while(!dry_run && (!socket || !socket->is_connected())) {
         if(log_level<4) fprintf(stderr,"... Disconnected from streaming servers\n");
         closeStream();
         openStream();
     }
 }
+
 void plotly::jsonStart(int i)
 {
     // Print the length of the message in hex:
     // 15 char for the json that wraps the data: {"x": , "y": }\n
     // + 23 char for the token: , "token": "abcdefghij"
     // = 38
-    printHex_(i+44);
+    printHex_(i+38);
     print_("\r\n{\"x\": ");
 }
 void plotly::jsonMiddle()
@@ -297,7 +350,8 @@
 {
     print_(", \"streamtoken\": \"");
     print_(token);
-    print_("\"}\n\r\n");
+    print_("\"");
+    print_("}\n\r\n");
 }
 
 int plotly::len_(int i)
@@ -334,107 +388,111 @@
 }
 void plotly::plot(unsigned long x, int y, char *token)
 {
+    if (!initalised)
+        return;
+
     reconnectStream();
-    jsonStart(len_(x)+len_(y));
-    print_(x);
-    jsonMiddle();
-    print_(y);
-    jsonEnd(token);
+
+//    int len = snprintf(buffer,k_bufferSize,"{\"x\": %lu, \"y\": %d, \"streamtoken\": \"%s\"}\n", x,y,token);
+//    len = snprintf(buffer,k_bufferSize,"%X\r\n{\"x\": %lu, \"y\": %d, \"streamtoken\": \"%s\"}\n\r\n",len, x,y,token);
+    int len = snprintf(buffer,k_bufferSize,"{\"x\": %lu, \"y\": %d}\n", x,y);
+    len = snprintf(buffer,k_bufferSize,"%x\r\n{\"x\": %lu, \"y\": %d}\n\r\n",len, x,y);
+    sendFormatedText(buffer,len);
 }
 
 void plotly::plot(unsigned long x, float y, char *token)
 {
+    if (!initalised)
+        return;
+
     reconnectStream();
 
-    char s_[15];
-    snprintf(s_,15,"%2.3lf",y);
-
-    jsonStart(len_(x)+len_(s_)-1);
-    print_(x);
-    jsonMiddle();
-    print_(y);
-    jsonEnd(token);
+    int len = snprintf(buffer,k_bufferSize,"{\"x\": %lu, \"y\": %.3f}\n", x,y);
+    len = snprintf(buffer,k_bufferSize,"%x\r\n{\"x\": %lu, \"y\": %.3f}\n\r\n",len, x,y);
+//    int len = snprintf(buffer,k_bufferSize,"{\"x\": %lu, \"y\": %.3f, \"streamtoken\": \"%s\"}\n", x,y,token);
+//    len = snprintf(buffer,k_bufferSize,"%X\r\n{\"x\": %lu, \"y\": %.3f, \"streamtoken\": \"%s\"}\n\r\n",len, x,y,token);
+    sendFormatedText(buffer,len);
 }
 
 bool plotly::print_(int d)
 {
-    int32_t len = snprintf(txBuffer,128,"%d",d);
-    if(log_level < 2)
-        fprintf(stderr,"%s",txBuffer);
-    if(!dry_run) {
-        int32_t sent = socket.send(txBuffer,len);
-        if (sent == len)
-            return true;
-        else {
-            fprintf(stderr,"\nTX failed to send _%s_ Sent %d of %d bytes\n",txBuffer,sent,len);
-            return false;
-        }
-    } else
-        return true;
+    int32_t len = snprintf(buffer,k_bufferSize,"%d",d);
+    return sendFormatedText(buffer,len);
+}
 
-}
 bool plotly::print_(unsigned long d)
 {
-    int32_t len = snprintf(txBuffer,128,"%lu",d);
-    if(log_level < 2)
-        fprintf(stderr,"%s",txBuffer);
+    int32_t len = snprintf(buffer,k_bufferSize,"%lu",d);
+    return sendFormatedText(buffer,len);
+}
+
+bool plotly::print_(float d)
+{
+    int32_t len = snprintf(buffer,k_bufferSize,"%f",d);
+    return sendFormatedText(buffer,len);
+}
+
+bool plotly::print_(char *d)
+{
+    int32_t len = snprintf(buffer,k_bufferSize,"%s",d);
+    return sendFormatedText(buffer,len);
+}
+
+bool plotly::printHex_(uint16_t d)
+{
+    int32_t len = snprintf(buffer,k_bufferSize,"%X",d);
+    return sendFormatedText(buffer,len);
+}
+
+bool plotly::sendFormatedText(char* data, int size)
+{
+    if(log_level < 2) {
+        fprintf(stderr,"%s",data);
+    }
     if(!dry_run) {
-        int32_t sent = socket.send(txBuffer,len);
-        if (sent == len)
+        if (!socket) {
+            fprintf(stderr,"\nTX failed, No network socket exists\n");
+            return false;
+            }
+        if (!(socket->is_connected())) {
+            fprintf(stderr,"\nTX failed, Network socket not connected\n");
+            return false;           
+            }
+        
+        int32_t sent = socket->send_all(data,size);
+        if (sent == size)
             return true;
         else {
-            fprintf(stderr,"\nTX failed to send _%s_ Sent %d of %d bytes\n",txBuffer,sent,len);
-            return false;
-        }
-    } else
-        return true;
-}
-bool plotly::print_(float d)
-{
-    int32_t len = snprintf(txBuffer,128,"%f",d);
-    if(log_level < 2)
-        fprintf(stderr,"%s",txBuffer);
-    if(!dry_run) {
-        int32_t sent = socket.send(txBuffer,len);
-        if (sent == len)
-            return true;
-        else {
-            fprintf(stderr,"\nTX failed to send _%s_ Sent %d of %d bytes\n",txBuffer,sent,len);
-            return false;
-        }
-    } else
-        return true;
-}
-bool plotly::print_(char *d)
-{
-    int32_t len = snprintf(txBuffer,128,"%s",d);
-    if(log_level < 2)
-        fprintf(stderr,"%s",txBuffer);
-    if(!dry_run) {
-        int32_t sent = socket.send(txBuffer,len);
-        if (sent == len)
-            return true;
-        else {
-            fprintf(stderr,"\nTX failed to send _%s_ Sent %d of %d bytes\n",txBuffer,sent,len);
+            fprintf(stderr,"\nTX failed to send _%s_ Sent %d of %d bytes\n",data,sent,size);
+            echoRxData();
             return false;
         }
     } else
         return true;
 }
 
-bool plotly::printHex_(uint16_t d)
+void plotly::echoRxData()
 {
-    int32_t len = snprintf(txBuffer,128,"%X",d);
-    if(log_level < 2)
-        fprintf(stderr,"%s",txBuffer);
-    if(!dry_run) {
-        int32_t sent = socket.send(txBuffer,len);
-        if (sent == len)
-            return true;
+
+    int32_t dataIn = socket->receive(buffer,k_bufferSize -1);
+    if (dataIn < 0) {
+        if (socket->is_connected()) {
+            fprintf(stderr,"error reading network socket. Closing it\n");
+            socket->close();
+            delete socket;
+            socket = NULL;
+            }
         else {
-            fprintf(stderr,"\nTX failed to send _%s_ Sent %d of %d bytes\n",txBuffer,sent,len);
-            return false;
-        }
-    } else
-        return true;
-}
+            fprintf(stderr,"error reading network socket, socket isn't connected\n");
+            delete socket;
+            socket = NULL;
+            }
+    }
+    if(dataIn > 0) {
+        buffer[dataIn]=0;
+        fprintf(stderr,"Rx Data __");
+        fprintf(stderr,buffer);
+        fprintf(stderr,"__\n");
+    }
+    
+}
\ No newline at end of file