plotly interface based on ardunio sample code
Library for plotting a simple x/y scatter chart on the plot.ly website.
See plotly_HelloWorld for sample usage.
Diff: plotly.cpp
- 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