[Risolto] Pachube e Content-Length (was: Pachube int ed unsigned long, problema)

Ho messo su un codice per inviare 8 datastream in una singola chiamata PUT.
Ma solo 6 di questi dati vengono ricevuti e loggati.
I dati che non passano sono un int ed un unsigned long.
Tutti gli altri sono float e arrivano perfettamente.

Le float le ho convertite con dtostrf, l’int con itoa e il long con ltoa.

Quello che faccio è questo:
creo dei buffer per le variabili
converto le variabili e le alloco nei buffer
costruisco una stringa e ne calcolo la lunghezza per il content lenght.
inizio la chiamata put secondo lo schema

 PUT /v2/feeds/18842.csv HTTP/1.1
 Host: api.pachube.com  
 X-PachubeApiKey: ENTER_YOUR_PACHUBE_API_KEY_HERE
 Content-Length: 28
 Connection: close
 
 0,value1
 1,value2
 2,value3

e con dei client.print invio i dati formattandoli riga per riga.

client.print("0,");
client.println(buffer1);
ecc

La mia sensazione è che le variabili int e long non vengano convertite come è necessario, penso a questo perché tutto il resto viene ricevuto senza problemi.
Suggerimenti? Sbaglio ad usare itoa ed ltoa? C’è un altro modo di convertirle?

Grazie

codice completo a seguire

 /*----- Pachube -----*/

    // buffer per la conversione delle variabili
    char charbuffertout[5]; // t_out
    char charbufferhout[5]; // h_out
    char charbuffertin[5]; // t_in
    char charbufferhin[5]; // h_in
    char charbufferT1[5]; // T1 h20
    char charbufferT2[5]; // T2 Heat
    char charbufferluce[7]; //luce
    char charbufferssr[2]; // SSR

    // conversione delle variabili in ASCII
    dtostrf(mydata.toutES,4,1,charbuffertout); // conversione float dtostrf(floatVar, minStringWidthIncDecimalPoint, numVarsAfterDecimal, charBuf);
    dtostrf(mydata.houtES,4,1,charbufferhout);
    dtostrf(mydata.tinES,4,1,charbuffertin);
    dtostrf(mydata.hinES,4,1,charbufferhin);
    dtostrf(mydata.T2ES,4,1,charbufferT2);
    dtostrf(mydata.T1ES,4,1,charbufferT1);
    
    ltoa(mydata.mediaHzES,charbufferluce,10); // conversione long
    itoa(mydata.statusSSRES,charbufferssr,10); // conversione int

    //composizione della stringa per il calcolo del Content-Length:
    char stringaTs[100] = "t_out,";  // Field 1 t_out
    strcat(stringaTs, charbuffertout);
    strcat(stringaTs, "rh_out,");   // Field 2 h_out
    strcat(stringaTs, charbufferhout);
    strcat(stringaTs, "t_in,");   // Field 3 t_in
    strcat(stringaTs, charbuffertin);
    strcat(stringaTs, "rh_in,");   // Field 4 h_in
    strcat(stringaTs, charbufferhin);
    strcat(stringaTs, "t_h2o,");   // Field 5 T1 H20
    strcat(stringaTs, charbufferT1);
    strcat(stringaTs, "t_heat,");  // Field 6 T2 Heat
    strcat(stringaTs, charbufferT2);
    strcat(stringaTs, "hz,");
    strcat(stringaTs, charbufferluce); // Field 7 MediaLuce
    strcat(stringaTs, "ssr,"); 
    strcat(stringaTs, charbufferssr); // Field 8 SSR 

    PgmPrint("StringaTs Contenuto: ");
    Serial.println(stringaTs);  
    PgmPrint("StringaTs lunghezza: ");
    Serial.println( strlen(stringaTs) ); // Lunghezza della stringa

    // invio dati a pachube
    // if there's a successful connection:
    if (client.connect()) {
      PgmPrintln("connecting to Pachube...");
      // send the HTTP PUT request. 

[cutttt]

      // here's the actual content of the PUT request:
      client.print("t_out,"); 
      client.println(charbuffertout);// t_out <------ questo funziona
      client.print("rh_out,"); 
      client.println(charbufferhout); // h_out <------ questo funziona
      client.print("t_in,"); 
      client.println(charbuffertin); // t_in <------ questo funziona
      client.print("rh_in,"); 
      client.println(charbufferhin); // h_in <------ questo funziona 
      client.print("t_h2o,"); 
      client.println(charbufferT1); // T1 h20 <------ questo funziona
      client.print("t_heat,"); 
      client.println(charbufferT2); // T2 Heat <------ questo funziona
      client.print("hz,"); 
      client.println(charbufferluce); //luce <------ questo NON funziona
      client.print("ssr,"); 
      client.println(charbufferssr); // SSR <------ questo NON funziona

      PgmPrintln("Connection Done... Maybe");
      client.stop();
      delay (500);
    } 
    else {
      // if you couldn't make a connection:
      PgmPrintln("connection failed");
    }

ciao

prova a stampare anche su seriale il pacchetto che invii a Pachube o - in alternativa - a "sniffare" il pacchetto da un PC in rete usando Wireshark così vediamo cosa non va...

Da seriale tutto mi appare come dovrebbe essere. Non vedo errori, la formattazione, l'output, il content lenght sono tutti corretti.

Whireshark l'ho scaricato ed ho provato a catturare un pacchetto, dovrei esserci riuscita ma ovviamente non ci capisco niente.

Ciao

vedi qualche pacchetto di risposta provenire da Pachube? Wireshark ha la funzione "follow tcp stream" che - se evidenzi il pacchetto di "andata" ti filtra tutta la conversazione e ti mostra anche le risposte

x iscrizione

Luca, whireshark è una figata. Per la prima volta ho visto esattamente cosa mando fuori... ancora non ci siamo, ma almeno ho potuto sistemare un po' l'impaginazione. Ecco lo stream. Come vedete l'invio sembra andare a buon fine... ma solo i primi sei datastream vengono aggiornati. Il datastreams 7 ed 8 non vengono aggiornati.

PUT /v2/feeds/xxxxxxx.csv HTTP/1.1 Host: api.pachube.com X-PachubeApiKey: xxxxxxxxxxxxxxxxx Content-Length: 44 Connection: close

1,25.7 2,27.2 3,25.6 4,28.0 5,24.6 6,24.5 7,682 8,0

HTTP/1.1 200 OK

Date: Sat, 11 Feb 2012 20:37:41 GMT

Content-Type: text/plain; charset=utf-8

Connection: close

X-Pachube-Logging-Key: logging.xxxx

X-PachubeRequestId: xxxx

Cache-Control: max-age=0

Content-Length: 1

Age: 0

Vary: Accept-Encoding

L'unica differenza che esiste è che i datastream da 1 a 6 sono tutti float convertiti con dtostrf (e.g.) dtostrf(mydata.houtES,4,1,charbufferhout); mentre il 7 e l'8 sono rispettivamente un unsigned long ed un int convertiti con

char charbufferluce[7]; //luce
char charbufferssr[2]; // SSR

ltoa(mydata.mediaHzES,charbufferluce,10); // conversione long
itoa(mydata.statusSSRES,charbufferssr,10); // conversione int

sarà mica il charset? Ogni aiuto sarà prezioso, mi mancano solo questi due stream porca pupazzola!

ma se stampi a seriale il risultato di itoa ed ltoa cosa appare?

secondo me è il problema è proprio quì, sotto il naso:

char charbufferluce[7]; //luce
char charbufferssr[2]; // SSR

ltoa(mydata.mediaHzES,charbufferluce,10); // conversione long
itoa(mydata.statusSSRES,charbufferssr,10); // conversione int

dici ad ltoa e itoa che i due buffer son lunghi dieci, ma li dichiari lunghi 7 e 2…

ps. ma come hai scoperto il formato della put per patchube? con wireshark? ma soprattutto riesci ad usarlo? not bad

lesto: ma se stampi a seriale il risultato di itoa ed ltoa cosa appare?

Appare ciò che deve apparire, ovvero i valori che vorrei inviare... Da seriale e da whireshark sembra tutto in ordine.

secondo me è il problema è proprio quì, sotto il naso:

char charbufferluce[7]; //luce
char charbufferssr[2]; // SSR

ltoa(mydata.mediaHzES,charbufferluce,10); // conversione long itoa(mydata.statusSSRES,charbufferssr,10); // conversione int




dici ad ltoa e itoa che i due buffer son lunghi dieci, ma li dichiari lunghi 7 e 2...

Lesto, non ti capisco. il 10 di itoa e ltoa dovrebbe essere la base, decimale. Sbaglio?

ps. ma come hai scoperto il formato della put per patchube? con wireshark? ma soprattutto riesci ad usarlo? not bad

uot? O_o Io whireshark manco sapevo aprirlo fino a due minuti fa, la put di pachube è chiaramente indicata sul sito, alla sezione quickstart... sono partita da quella :) Per ora uppo 6 valori su 8. E' un risultato discreto, ma poco utile fin quando non completo tutto.

ciao

mi viene da pensare.. il datastream 8 non si aggiorna anche se provi con valori fittizi diversi da zero?

scusa hai ragione, ho interpretato male il reference. sei sicura di aver dimensionato gli array in modo da contenere tutte le cifre +1? se stampi la put cosa ottieni? puoi postare?

non ho guardato la sezione quick start :-)

sarebbe utile postare il contenuto di charbufferluce, charbufferssr, e della put completa. per quanto riguarda la decodifica, dovrebbe essere unicode, che è un'estensione dell'ansi quindi retrocompatibile

Prova ad analizzare quello che viene inviato con un software tipo fiddler (se sei su windows) oppure http://www.charlesproxy.com/ Prova a diminuire il numero di feed (togli i primi due), e vedi se ti legge gli ultimi. Non è che c'è qualche tipo di limite (lato server) sul numero dei sensori aggiornabili per stream? Non è che c'è qualche tipo di limite nella lunghezza del messaggio inviabile al server?

Ho risolto. Io quelli di pachube li sego in due se mi capitano sotto tiro. Domani vi posto la soluzione, ora tanto stanca :)

Io quelli di pachube li sego in due se mi capitano sotto tiro.

hi hi hi hi hi hi, spezzaci le gambine ]:D

Ciao.

nell'attesa io voto per un limite del numero di datastream

Testato: nell'attesa io voto per un limite del numero di datastream

Idem con patate!

@danielaES: ma thingspeak? Non stavi utilizzando quello? qual'è meglio? pachube o thingspeak?

io voto per il passaggio di integer a 4 byte, oppure per il passaggio di integer in esadecimale

And the winner is... nessuno! Abbiamo tutti cannato egregiamente, io in primis :) Possiamo però dire che buona parte del disguido deriva dalla carente documentazione messa a disposizione da pachube. Si sono concentrati sulla creazione di una libreria ufficiale per arduino ma hanno documentato poco come inviare i dati, scrivendo il codice in proprio.

Btw. Le variabili vengono convertite senza problemi con itoa e ltoa, non è un problema di buffer od altro. Il problema stava nel Content-Length che deve includere: i dati inviati ma anche le newlines ("/n"). Ogni newline conta 1, sebbene printata in due caratteri "/n". Paradossalmente se al posto della newline si usa un client.println... questo non influenza il Content-Length.

Una volta intuito ciò è stato semplice, è bastato creare una variabile a cui aggiungere oltre la stringa dati anche le newline (nel mio caso sette) e printare questa come Content-Length.

int contentlength = (strlen(dati) + 7);

Dimensionato correttamente il Content-Length, tutti i dati sono apparsi. Prima non venivano ricevuti perché la stringa veniva tagliata anticipatamente. Notare che comunque pachube ritorna "OK" anche se il Content-Length è sbagliato, semplicemente tronca i dati ricevuti.

@Andre. Ho lasciato perdere thingspeak perché non è un sito di datalogging! Poi scriverò la recensione Thingspeak vs Pachube. Al momento pachube è la cosa meno peggio che si trova in rete, fortunatamente sono riuscita ad far funzionare l'invio di datastream multipli senza il polling/roundrobin. Quindi andre... Si può fare! :D aggiorna blog! Puoi mettere quanti datastreams vuoi in una singola put :D Questo è un grosso vantaggio perché ti eviti il delay di 15 sec tra un invio e l'altro.

DanielaES: Ogni newline conta 1, sebbene printata in due caratteri "/n".

:) in realtà "\n" è un friendly code del compilatore... quello che effettivamente è "new line" è un singolo carattere ASCII (tranne nella codifica txt dos dove sono due: CRLF)

DanielaES: @Andre. Ho lasciato perdere thingspeak perché non è un sito di datalogging!

Come no? E che è allora!? :)

DanielaES: Poi scriverò la recensione Thingspeak vs Pachube.

attendo!

DanielaES: fortunatamente sono riuscita ad far funzionare l'invio di datastream multipli senza il polling/roundrobin. Quindi andre... Si può fare! :D aggiorna blog! Puoi mettere quanti datastreams vuoi in una singola put :D Questo è un grosso vantaggio perché ti eviti il delay di 15 sec tra un invio e l'altro.

Questo sai perchè? La documentazione che fa pena! Appena puoi, posta il codice con la multi-single-put :)

Il delay lo misi perchè qualche mese fa era ancora più limitativo pachube, c'era un limite di quattro put al minuto (mi pare) e allora misi il delay tra una put e l'altra per rientrare nel minuto.

btw brava così!

int contentlength = (strlen(dati) + 7);

moolto strano, dovrebbe contare anche i \n… magari i \n (CR) vengono convertiti in \n\r (CRLF) dal modulo ethernet, quindi prova a usare \n\r al posto di \n (probabilmente la println usa \n\r, ecco perchè non ti da problemi)

cmq il “” significa “carattere di escape”, e non occupa byte perchè semplicemente indica che vuoi inserire un carattere speciale, e il carattere successivo indica QUALE carattere speciale. Se vuoi semplicemente scrivere “”, ti toccherà scrivere “\”!