plotly interface based on ardunio sample code
Embed:
(wiki syntax)
Show/hide line numbers
plotly.cpp
00001 #include "plotly.h" 00002 #include "mbed.h" 00003 00004 #define plotlyURL "plot.ly" 00005 #define dataURL "arduino.plot.ly" 00006 00007 plotly::plotly (const char *username, const char *api_key, const char* stream_tokens[], const char *filename, int nTraces) 00008 { 00009 log_level = 3; // 0 = Debugging, 1 = Informational, 2 = Status, 3 = Errors, 4 = Quiet (// Serial Off) 00010 dry_run = false; 00011 username_ = username; 00012 api_key_ = api_key; 00013 stream_tokens_ = stream_tokens; 00014 filename_ = filename; 00015 maxpoints = 30; 00016 world_readable = true; 00017 convertTimestamp = false; 00018 timezone = "America/Montreal"; 00019 fileopt = "overwrite"; 00020 00021 nTraces_ = nTraces; 00022 00023 sockets = (TCPSocketConnection **)malloc(sizeof(TCPSocketConnection *) * nTraces_); 00024 for (int i = 0; i< nTraces_; i++) { 00025 *(sockets+i) = NULL; 00026 } 00027 initalised = false; 00028 00029 } 00030 00031 00032 plotly::~plotly() 00033 { 00034 closeStreams(); 00035 if (sockets) 00036 free(sockets); 00037 } 00038 00039 00040 bool plotly::init() 00041 { 00042 // 00043 // Create plot with a REST post to plotly 00044 // See the clientresp section of https://plot.ly/rest/ for details 00045 // 00046 if(dry_run && log_level < 3) { 00047 fprintf(stderr,"... This is a dry run, we are not connecting to plotly's servers...\n"); 00048 } else if(log_level < 3) { 00049 fprintf(stderr,"... Attempting to connect to plotly's REST servers\n"); 00050 } 00051 00052 if (!dry_run) { 00053 int pause = 1; 00054 *sockets = new TCPSocketConnection(); 00055 if (!*sockets) 00056 return false; 00057 while ((*sockets)->connect(plotlyURL, 80) < 0) { 00058 if (pause > 30) { 00059 fprintf(stderr,"Failed to connect. :-(\n"); 00060 delete (*sockets); 00061 return false; 00062 } 00063 fprintf(stderr,"... Couldn\'t connect to plotly's REST servers... trying again!\n"); 00064 wait(pause); 00065 pause *= 2; 00066 } 00067 } 00068 00069 if(log_level < 3) fprintf(stderr,"... Connected to plotly's REST servers\n"); 00070 00071 if(log_level < 3) fprintf(stderr,"... Sending HTTP Post to plotly\n"); 00072 00073 print_("POST /clientresp HTTP/1.1\r\n"); 00074 print_("Host: 107.21.214.199\r\n"); 00075 print_("User-Agent: Arduino/0.5.1\r\n"); 00076 print_("plotly-streamtoken: "); 00077 for (int i = 0; i<nTraces_; i++) { 00078 print_(stream_tokens_[i]); 00079 if ( i < (nTraces_-1) ) 00080 print_(","); 00081 } 00082 printNetTerminator_(); 00083 00084 print_("Content-Length: "); 00085 00086 unsigned long lineLen = snprintf(buffer,k_bufferSize,"version=2.3&origin=plot&platform=arduino&un=%s&key=%s&args=[",username_,api_key_); 00087 for(int i=0; i<nTraces_; i++) { 00088 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))?", ":""); 00089 } 00090 lineLen += snprintf((buffer+lineLen),k_bufferSize-lineLen,"]&kwargs={\"fileopt\": \"%s\", \"filename\": \"%s\", \"world_readable\": %s}",fileopt,filename_,world_readable?"true":"false"); 00091 00092 print_(lineLen); 00093 printNetTerminator_(); 00094 printNetTerminator_(); 00095 00096 sendFormatedText(buffer,lineLen); 00097 00098 printNetTerminator_(); 00099 00100 // 00101 // Wait for a response 00102 // Parse the response for the "All Streams Go!" and proceed to streaming 00103 // if we find it 00104 // 00105 00106 char allStreamsGo[] = "All Streams Go!"; 00107 int asgCnt = 0; // asg stands for All Streams Go 00108 char url[] = "\"url\": \"http://107.21.214.199/~"; 00109 char fid[4]; 00110 int fidCnt = 0; 00111 int urlCnt = 0; 00112 int usernameCnt = 0; 00113 bool proceed = false; 00114 bool fidMatched = false; 00115 char c; 00116 00117 if(log_level < 2) { 00118 fprintf(stderr,"... Sent message, waiting for plotly's response...\n"); 00119 } 00120 00121 if(!dry_run) { 00122 while(!proceed) { 00123 int32_t dataIn = (*sockets)->receive(buffer,k_bufferSize -1); 00124 if (dataIn < 0) { 00125 if(log_level < 3) fprintf(stderr,"error reading network socket\n"); 00126 break; 00127 } 00128 if(dataIn > 0) { 00129 buffer[dataIn]=0; 00130 00131 if(log_level < 2) fprintf(stderr,buffer); 00132 00133 for (int i = 0; i<dataIn; i++) { 00134 c = buffer[i]; 00135 // 00136 // Attempt to read the "All streams go" msg if it exists 00137 // by comparing characters as they roll in 00138 // 00139 00140 if(asgCnt == strlen(allStreamsGo) && !proceed) { 00141 proceed = true; 00142 } else if(allStreamsGo[asgCnt]==c) { 00143 asgCnt += 1; 00144 } else if(asgCnt > 0) { 00145 // reset counter 00146 asgCnt = 0; 00147 } 00148 00149 // 00150 // Extract the last bit of the URL from the response 00151 // The url is in the form http://107.21.214.199/~USERNAME/FID 00152 // We'll character-count up through char url[] and through username_, then start 00153 // filling in characters into fid 00154 // 00155 00156 if(log_level < 3) { 00157 if(url[urlCnt]==c && urlCnt < strlen(url)) { 00158 urlCnt += 1; 00159 } else if(urlCnt > 0 && urlCnt < strlen(url)) { 00160 // Reset counter 00161 urlCnt = 0; 00162 } 00163 if(urlCnt == strlen(url) && fidCnt < 4 && !fidMatched) { 00164 // We've counted through the url, start counting through the username 00165 if(usernameCnt < strlen(username_)+2) { 00166 usernameCnt += 1; 00167 } else { 00168 // the url ends with " 00169 if(c != '"') { 00170 fid[fidCnt] = c; 00171 fidCnt += 1; 00172 } else if(fidCnt>0) { 00173 fidMatched = true; 00174 } 00175 00176 } 00177 } 00178 } 00179 } 00180 } 00181 wait(0.1); 00182 } 00183 } 00184 00185 if(!dry_run && !proceed && log_level < 4) { 00186 fprintf(stderr,"... Error initializing stream, aborting.\n"); 00187 } 00188 00189 if(!dry_run && proceed && log_level < 3) { 00190 fprintf(stderr,"... A-ok from plotly, All Streams Go!\n"); 00191 if(fidMatched) { 00192 fprintf(stderr,"... View your streaming plot here: https://plot.ly/~"); 00193 fprintf(stderr,username_); 00194 fprintf(stderr,"/"); 00195 for(int i=0; i<fidCnt; i++) { 00196 fprintf(stderr,"%c",fid[i]); 00197 } 00198 fprintf(stderr,"\n"); 00199 } 00200 } 00201 00202 if (proceed || dry_run) { 00203 initalised = true; 00204 } 00205 if (*sockets) { 00206 delete *sockets; 00207 *sockets=NULL; 00208 } 00209 return initalised; 00210 } 00211 00212 void plotly::openStreams() 00213 { 00214 for (int i = 0; i< nTraces_; i++) { 00215 openStream(i); 00216 } 00217 } 00218 00219 void plotly::closeStreams() 00220 { 00221 for (int i = 0; i< nTraces_; i++) { 00222 closeStream(i); 00223 } 00224 } 00225 00226 00227 bool plotly::openStream(int stream) 00228 { 00229 00230 if (stream >= nTraces_) 00231 return false; 00232 00233 if (!initalised) 00234 return false; 00235 00236 // 00237 // Start request to stream servers 00238 // 00239 00240 if (*(sockets+stream) != NULL) { 00241 delete *(sockets+stream); 00242 *(sockets+stream) = NULL; 00243 } 00244 00245 if(log_level < 3) fprintf(stderr,"... Connecting to plotly's streaming servers...\n"); 00246 00247 if (!dry_run) { 00248 int pause = 1; 00249 *(sockets + stream) = new TCPSocketConnection(); 00250 while ((*(sockets + stream))->connect(dataURL, 80) < 0) { 00251 if (pause > 30) { 00252 fprintf(stderr,"Failed to connect. :-(\n"); 00253 delete *(sockets + stream); 00254 return false; 00255 } 00256 fprintf(stderr,"... Couldn\'t connect to plotly's REST servers... trying again!\n"); 00257 wait(pause); 00258 pause *= 2; 00259 } 00260 } 00261 00262 00263 if(log_level < 3) fprintf(stderr,"... Connected to plotly's streaming servers\n... Initializing stream %d\n",stream); 00264 00265 print_("POST / HTTP/1.1\r\n",stream); 00266 print_("Host: arduino.plot.ly\r\n",stream); 00267 print_("User-Agent: Python\r\n",stream); 00268 print_("Transfer-Encoding: chunked\r\n",stream); 00269 print_("Connection: close\r\n",stream); 00270 print_("plotly-streamtoken: ",stream); 00271 print_(stream_tokens_[stream],stream); 00272 printNetTerminator_(stream); 00273 if(convertTimestamp) { 00274 print_("plotly-convertTimestamp: \"",stream); 00275 print_(timezone,stream); 00276 print_("\"",stream); 00277 printNetTerminator_(stream); 00278 } 00279 printNetTerminator_(stream); 00280 00281 if(log_level < 3) fprintf(stderr,"... Done initializing, ready to stream!\n"); 00282 return true; 00283 } 00284 00285 void plotly::closeStream( int stream) 00286 { 00287 if (stream >= nTraces_) 00288 return; 00289 00290 if (*(sockets+stream) != NULL) { 00291 if ((*(sockets+stream))->is_connected()) { 00292 print_("0\r\n\r\n",stream); 00293 (*(sockets+stream))->close(); 00294 } 00295 delete *(sockets+stream); 00296 *(sockets+stream)=NULL; 00297 } 00298 } 00299 00300 void plotly::reconnectStream(int number) 00301 { 00302 while(!dry_run && (!(*(sockets+number)) || !(*(sockets+number))->is_connected())) { 00303 if(log_level<4) fprintf(stderr,"... Disconnected from streaming servers\n"); 00304 closeStream(number); 00305 openStream(number); 00306 } 00307 } 00308 00309 00310 void plotly::plot(unsigned long x, int y, int stream) 00311 { 00312 if (!initalised) 00313 return; 00314 00315 reconnectStream(stream); 00316 00317 // need to prefix with the length so print it once to get the content lenght and then a second time with the prefix. 00318 int len = snprintf(buffer,k_bufferSize,"{\"x\": %lu, \"y\": %d}\n", x,y); 00319 len = snprintf(buffer,k_bufferSize,"%x\r\n{\"x\": %lu, \"y\": %d}\n\r\n",len, x,y); 00320 sendFormatedText(buffer,len,stream); 00321 } 00322 00323 void plotly::plot(unsigned long x, float y, int stream) 00324 { 00325 if (!initalised) 00326 return; 00327 00328 reconnectStream(stream); 00329 00330 // need to prefix with the length so print it once to get the content lenght and then a second time with the prefix. 00331 int len = snprintf(buffer,k_bufferSize,"{\"x\": %lu, \"y\": %.3f}\n", x,y); 00332 len = snprintf(buffer,k_bufferSize,"%x\r\n{\"x\": %lu, \"y\": %.3f}\n\r\n",len, x,y); 00333 sendFormatedText(buffer,len,stream); 00334 } 00335 00336 void plotly::plot(float x, float y, int stream) 00337 { 00338 if (!initalised) 00339 return; 00340 00341 reconnectStream(stream); 00342 // need to prefix with the length so print it once to get the content lenght and then a second time with the prefix. 00343 int len = snprintf(buffer,k_bufferSize,"{\"x\": %.3f, \"y\": %.3f}\n", x,y); 00344 len = snprintf(buffer,k_bufferSize,"%x\r\n{\"x\": %.3f, \"y\": %.3f}\n\r\n",len, x,y); 00345 sendFormatedText(buffer,len,stream); 00346 } 00347 00348 00349 bool plotly::print_(int d, int stream) 00350 { 00351 char smallBuffer[10]; 00352 int32_t len = snprintf(smallBuffer,10,"%d",d); 00353 return sendFormatedText(smallBuffer,len,stream); 00354 } 00355 00356 bool plotly::print_(unsigned long d, int stream) 00357 { 00358 char smallBuffer[12]; 00359 int32_t len = snprintf(smallBuffer,12,"%lu",d); 00360 return sendFormatedText(smallBuffer,len,stream); 00361 } 00362 00363 bool plotly::print_(float d, int stream) 00364 { 00365 char smallBuffer[12]; 00366 int32_t len = snprintf(smallBuffer,12,"%f",d); 00367 return sendFormatedText(smallBuffer,len,stream); 00368 } 00369 00370 bool plotly::printNetTerminator_(int stream) 00371 { 00372 return sendFormatedText("\r\n",2,stream); 00373 } 00374 00375 00376 00377 bool plotly::print_(const char *d, int stream)// strings could be long, use the big buffer 00378 { 00379 int32_t len = snprintf(buffer,k_bufferSize,"%s",d); 00380 return sendFormatedText(buffer,len,stream); 00381 } 00382 00383 bool plotly::printHex_(uint16_t d, int stream) 00384 { 00385 int32_t len = snprintf(buffer,k_bufferSize,"%X",d); 00386 return sendFormatedText(buffer,len,stream); 00387 } 00388 00389 bool plotly::sendFormatedText(char* data, int size, int stream) 00390 { 00391 if(log_level < 2) { 00392 fprintf(stderr,"%s",data); 00393 } 00394 if(!dry_run) { 00395 if (!*(sockets+stream)) { 00396 fprintf(stderr,"\nTX failed, No network socket exists\n"); 00397 return false; 00398 } 00399 if (!((*(sockets+stream))->is_connected())) { 00400 fprintf(stderr,"\nTX failed, Network socket not connected\n"); 00401 return false; 00402 } 00403 00404 int32_t sent = (*(sockets+stream))->send_all(data,size); 00405 if (sent == size) 00406 return true; 00407 else { 00408 fprintf(stderr,"\nTX failed to send _%s_ Sent %d of %d bytes\n",data,sent,size); 00409 return false; 00410 } 00411 } else 00412 return true; 00413 } 00414
Generated on Thu Jul 14 2022 22:40:21 by 1.7.2