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:
7:9409a72ab6c0
Parent:
5:fc8eefeb301b
Parent:
6:e57d6e9313f4
Child:
8:d4f705ba2ea5
--- a/plotly.cpp	Mon Jul 28 10:56:42 2014 +0000
+++ b/plotly.cpp	Tue Jul 29 13:30:31 2014 +0000
@@ -4,13 +4,13 @@
 #define plotlyURL "plot.ly"
 #define dataURL "arduino.plot.ly"
 
-plotly::plotly(char *username, char *api_key, char* stream_token, char *filename)
+plotly::plotly(const char *username, const char *api_key, const char** stream_tokens, const char *filename, int nTraces)
 {
     log_level = 3;  // 0 = Debugging, 1 = Informational, 2 = Status, 3 = Errors, 4 = Quiet (// Serial Off)
     dry_run = false;
     username_ = username;
     api_key_ = api_key;
-    stream_token_ = stream_token;
+    stream_tokens = stream_tokens;
     filename_ = filename;
     maxpoints = 30;
     world_readable = true;
@@ -18,22 +18,35 @@
     timezone = "America/Montreal";
     fileopt = "overwrite";
 
-    socket = NULL;
+    nTraces_ = nTraces;
 
+    sockets = (TCPSocketConnection **)malloc(sizeof(TCPSocketConnection *) * nTraces_);
+    for (int i = 0; i< nTraces_; i++) {
+        *(sockets+i) = NULL;
+    }
     initalised = false;
+
 }
 
 
 plotly::~plotly()
 {
-    closeStream();
-
+    closeStreams();
+    if (sockets)
+        free(sockets);
 }
 
 
 bool plotly::init()
 {
 
+    fprintf(stderr,"%d tokens\n",nTraces_);
+    wait(1);
+    for (int i = 0; i<nTraces_; i++) {
+        fprintf(stderr,"%s\n",*(stream_tokens_+i));
+        wait(1);
+    }
+
     //
     //  Create plot with a REST post to plotly
     //  See the clientresp section of https://plot.ly/rest/ for details
@@ -46,11 +59,13 @@
 
     if (!dry_run) {
         int pause = 1;
-        socket = new TCPSocketConnection();
-        while (socket->connect(plotlyURL, 80) < 0) {
+        *sockets = new TCPSocketConnection();
+        if (!*sockets)
+            return false;
+        while ((*sockets)->connect(plotlyURL, 80) < 0) {
             if (pause > 30) {
                 fprintf(stderr,"Failed to connect. :-(\n");
-                delete socket;
+                delete (*sockets);
                 return false;
             }
             fprintf(stderr,"... Couldn\'t connect to plotly's REST servers... trying again!\n");
@@ -67,18 +82,22 @@
     print_("Host: 107.21.214.199\r\n");
     print_("User-Agent: Arduino/0.5.1\r\n");
     print_("plotly-streamtoken: ");
-    print_(stream_token_);
+    for (int i = 0; i<nTraces_; i++) {
+        print_(stream_tokens_[i]);
+        if ( i < (nTraces_-1) )
+            print_(",");
+    }
     printNetTerminator_();
 
     print_("Content-Length: ");
 
-    // calculate the length of the packet payload and store it in the big buffer.
-    int lineLen = snprintf(buffer,k_bufferSize,"version=2.3&origin=plot&platform=arduino&un=%s&key=%s&args=[",username_,api_key_);
-    lineLen += snprintf((buffer+lineLen),k_bufferSize-lineLen,"{\"y\": [], \"x\": [], \"type\": \"scatter\", \"stream\": {\"token\": \"%s\", \"maxpoints\": %d}}",stream_token_,maxpoints);
+    unsigned long lineLen = snprintf(buffer,k_bufferSize,"version=2.3&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");
 
     print_(lineLen);
-
     printNetTerminator_();
     printNetTerminator_();
 
@@ -109,7 +128,7 @@
 
     if(!dry_run) {
         while(!proceed) {
-            int32_t dataIn = socket->receive(buffer,k_bufferSize -1);
+            int32_t dataIn = (*sockets)->receive(buffer,k_bufferSize -1);
             if (dataIn < 0) {
                 if(log_level < 3) fprintf(stderr,"error reading network socket\n");
                 break;
@@ -172,7 +191,7 @@
     }
 
     if(!dry_run && !proceed && log_level < 4) {
-        fprintf(stderr,"... Error initializing stream, aborting. Try again or get in touch with Chris at chris@plot.ly\n");
+        fprintf(stderr,"... Error initializing stream, aborting.\n");
     }
 
     if(!dry_run && proceed && log_level < 3) {
@@ -191,15 +210,33 @@
     if (proceed || dry_run) {
         initalised = true;
     }
-    if (socket) {
-        delete socket;
-        socket=NULL;
+    if (*sockets) {
+        delete *sockets;
+        *sockets=NULL;
     }
     return initalised;
 }
 
-bool plotly::openStream()
+void plotly::openStreams()
+{
+    for (int i = 0; i< nTraces_; i++) {
+        openStream(i);
+    }
+}
+
+void plotly::closeStreams()
 {
+    for (int i = 0; i< nTraces_; i++) {
+        closeStream(i);
+    }
+}
+
+
+bool plotly::openStream(int stream)
+{
+
+    if (stream >= nTraces_)
+        return false;
 
     if (!initalised)
         return false;
@@ -208,22 +245,20 @@
     // Start request to stream servers
     //
 
-    if (socket) {
-        delete socket;
-        socket = NULL;
+    if (*(sockets+stream) != NULL) {
+        delete *(sockets+stream);
+        *(sockets+stream) = NULL;
     }
 
-
     if(log_level < 3) fprintf(stderr,"... Connecting to plotly's streaming servers...\n");
 
-
     if (!dry_run) {
         int pause = 1;
-        socket = new TCPSocketConnection();
-        while (socket->connect(dataURL, 80) < 0) {
+        *(sockets + stream) = new TCPSocketConnection();
+        while ((*(sockets + stream))->connect(dataURL, 80) < 0) {
             if (pause > 30) {
                 fprintf(stderr,"Failed to connect. :-(\n");
-                delete socket;
+                delete *(sockets + stream);
                 return false;
             }
             fprintf(stderr,"... Couldn\'t connect to plotly's REST servers... trying again!\n");
@@ -233,139 +268,148 @@
     }
 
 
-    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 %d\n",stream);
 
-    print_("POST / HTTP/1.1\r\n");
-    print_("Host: arduino.plot.ly\r\n");
-    print_("User-Agent: Python\r\n");
-    print_("Transfer-Encoding: chunked\r\n");
-    print_("Connection: close\r\n");
-    print_("plotly-streamtoken: ");
-    print_(stream_token_);
-    printNetTerminator_();
+    print_("POST / HTTP/1.1\r\n",stream);
+    print_("Host: arduino.plot.ly\r\n",stream);
+    print_("User-Agent: Python\r\n",stream);
+    print_("Transfer-Encoding: chunked\r\n",stream);
+    print_("Connection: close\r\n",stream);
+    print_("plotly-streamtoken: ",stream);
+    print_(stream_tokens_[stream],stream);
+    printNetTerminator_(stream);
     if(convertTimestamp) {
-        print_("plotly-convertTimestamp: \"");
-        print_(timezone);
-        print_("\"");
-        printNetTerminator_();
+        print_("plotly-convertTimestamp: \"",stream);
+        print_(timezone,stream);
+        print_("\"",stream);
+        printNetTerminator_(stream);
     }
-    printNetTerminator_();
+    printNetTerminator_(stream);
 
     if(log_level < 3) fprintf(stderr,"... Done initializing, ready to stream!\n");
     return true;
 }
 
-void plotly::closeStream()
+void plotly::closeStream( int stream)
 {
-    if (socket) {
-        if (socket->is_connected()) {
-            print_("0\r\n\r\n");
-            socket->close();
+    if (stream >= nTraces_)
+        return;
+
+    if (*(sockets+stream) != NULL) {
+        if ((*(sockets+stream))->is_connected()) {
+            print_("0\r\n\r\n",stream);
+            (*(sockets+stream))->close();
         }
-        delete socket;
-        socket=NULL;
+        delete *(sockets+stream);
+        *(sockets+stream)=NULL;
     }
 }
 
-void plotly::reconnectStream()
+void plotly::reconnectStream(int number)
 {
-    while(!dry_run && (!socket || !socket->is_connected())) {
+    while(!dry_run && (!(*(sockets+number)) || !(*(sockets+number))->is_connected())) {
         if(log_level<4) fprintf(stderr,"... Disconnected from streaming servers\n");
-        closeStream();
-        openStream();
+        closeStream(number);
+        openStream(number);
     }
 }
 
-void plotly::plot(unsigned long x, int y)
+
+void plotly::plot(unsigned long x, int y, int stream)
 {
     if (!initalised)
         return;
 
-    reconnectStream();
+    reconnectStream(stream);
 
     // need to prefix with the length so print it once to get the content lenght and then a second time with the prefix.
     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);
+    sendFormatedText(buffer,len,stream);
 }
 
-void plotly::plot(unsigned long x, float y)
+void plotly::plot(unsigned long x, float y, int stream)
 {
     if (!initalised)
         return;
 
-    reconnectStream();
+    reconnectStream(stream);
 
     // need to prefix with the length so print it once to get the content lenght and then a second time with the prefix.
     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);
-    sendFormatedText(buffer,len);
+    sendFormatedText(buffer,len,stream);
 }
 
-void plotly::plot(float x, float y)
+void plotly::plot(float x, float y, int stream)
 {
     if (!initalised)
         return;
 
-    reconnectStream();
-
+    reconnectStream(stream);
     // need to prefix with the length so print it once to get the content lenght and then a second time with the prefix.
     int len = snprintf(buffer,k_bufferSize,"{\"x\": %.3f, \"y\": %.3f}\n", x,y);
     len = snprintf(buffer,k_bufferSize,"%x\r\n{\"x\": %.3f, \"y\": %.3f}\n\r\n",len, x,y);
-    sendFormatedText(buffer,len);
+    sendFormatedText(buffer,len,stream);
 }
 
 
-bool plotly::print_(int d)
+bool plotly::print_(int d, int stream)
 {
     char smallBuffer[10];
     int32_t len = snprintf(smallBuffer,10,"%d",d);
-    return sendFormatedText(smallBuffer,len);
+    return sendFormatedText(smallBuffer,len,stream);
 }
 
-bool plotly::print_(unsigned long d)
+bool plotly::print_(unsigned long d, int stream)
 {
     char smallBuffer[12];
     int32_t len = snprintf(smallBuffer,12,"%lu",d);
-    return sendFormatedText(smallBuffer,len);
+    return sendFormatedText(smallBuffer,len,stream);
 }
 
-bool plotly::print_(float d)
+bool plotly::print_(float d, int stream)
 {
     char smallBuffer[12];
     int32_t len = snprintf(smallBuffer,12,"%f",d);
-    return sendFormatedText(smallBuffer,len);
+    return sendFormatedText(smallBuffer,len,stream);
 }
 
-bool plotly::printNetTerminator_()
+bool plotly::printNetTerminator_(int stream)
 {
-    return sendFormatedText("\r\n",2);
+    return sendFormatedText("\r\n",2,stream);
 }
 
 
-bool plotly::print_(char *d) // strings could be long, use the big buffer
+
+bool plotly::print_(const char *d, int stream)// strings could be long, use the big buffer
 {
     int32_t len = snprintf(buffer,k_bufferSize,"%s",d);
-    return sendFormatedText(buffer,len);
+    return sendFormatedText(buffer,len,stream);
 }
 
+bool plotly::printHex_(uint16_t d, int stream)
+{
+    int32_t len = snprintf(buffer,k_bufferSize,"%X",d);
+    return sendFormatedText(buffer,len,stream);
+}
 
-bool plotly::sendFormatedText(char* data, int size)
+bool plotly::sendFormatedText(char* data, int size, int stream)
 {
     if(log_level < 2) {
         fprintf(stderr,"%s",data);
     }
     if(!dry_run) {
-        if (!socket) {
+        if (!*(sockets+stream)) {
             fprintf(stderr,"\nTX failed, No network socket exists\n");
             return false;
         }
-        if (!(socket->is_connected())) {
+        if (!((*(sockets+stream))->is_connected())) {
             fprintf(stderr,"\nTX failed, Network socket not connected\n");
             return false;
         }
 
-        int32_t sent = socket->send_all(data,size);
+        int32_t sent = (*(sockets+stream))->send_all(data,size);
         if (sent == size)
             return true;
         else {