Arduino Forum

International => Italiano => Software => Topic started by: giannilucia on Sep 11, 2012, 04:49 pm

Title: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 11, 2012, 04:49 pm
Salve a tutti,

come brevemente descritto nel titolo il mio problema consiste nell'inviare dei byte per chiedere la connessione ad un server tramite il protocollo MQTT, in pratica dopo aver stabilito la connessione TCP con il server di cosm, attraverso il metodo connectTCP della libreria InetGSM, dovrei inviare una richiesta di connect per questo protocollo, in pratica dovrei inviare questo:


    byte[] connectMessage = {0x10 //Connect
      , 0x0C + 0x04 //Remaining Length
      , 0x00 //0
      , 0x06 //6
      , 0x4d //M
      , 0x51 //Q
      , 0x49 //I
      , 0x73 //S
      , 0x64 //D
      , 0x70 //P
      , 0x03 //Protocol version = 3
      , 0x02 //Clean session only
      , 0x00 //Keepalive MSB
      , 0x3c //Keepaliave LSB = 60
      , 0x00 //String length MSB
      , 0x02 //String length LSB = 2
      , 0x4d //M
      , 0x70 //P .. Let's say client ID = MP
  };
     
  byte[] publishMessage = { 0x30 //Publish with QOS 0
      , 0x05 + 0x05 //Remaining length
      , 0x00 //MSB
      , 0x03 //3 bytes of topic
      , 0x61 //a
      , 0x2F ///
      , 0x62 //b (a/b) is the topic
      , 0x48, 0x45 , 0x4c , 0x4c, 0x4f //HELLO is the message 
  };

sono dei codici esadecimali che indicano al server che voglio instaurare una connessione con protocollo MQTT, esso mi dovrà rispondere con un'accettazione, che dovrò leggere, e poi effettuare il publisch, quindi inviare il secondo set di byte.
Utilizzo i byte perchè ho preso i valori direttamente dalla spiegazione di questo nuovo protocollo, ma se qualcuno mi può consigliare qualche altro metodo è sempre ben accetto.
In tutti i casi il problema principale è spedire questi dati al server.
Qualcuno può aiutarmi?
 
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 12, 2012, 03:06 pm
ciao, la libreria InetGSM è una astrazione della SIM900 che permette di creare facilmente richieste GET e POST col protocollo HTTP (che sta al di sopra del TCP)
Tu, che vuoi creare una libreria per il protocollo MQTT, quindi, dovrai usare i metodi forniti dalla libreria SIM900; la connect mi pare sia identica, ma essa ti mette a disposizione anche i metodi simpleWrite, WaitResp e read, che tra l'altro funzionano anche con array di byte come piace a te (di solito il problema non è con gli array di byte, ma con tutti gli altri tipi di dato in particolare numerici a virgola mobile e stringhe).
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 12, 2012, 05:19 pm
Ti voglio inanzi tutto ringraziare per la risposta, poi, dato che sono alle prime armi con l'uso dei protocolli volevo delle chiarificazioni, in pratica io dovrei prima instaurare una connessione TCP con il server (cosm), dopo di che mandare la richiesta di connect per specificare il tipo di protocollo che devo usare, quindi il fatto che io utilizzo la connectTCP della inetGsm dici che non va bene? poi come posso leggere se c'è una risposta da parte del server dopo aver fatto la connessione tcp?
Penso ci sia qualche cosa che mi sfugge...
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 12, 2012, 06:23 pm
no, tu instauri una comunicazione TCP con la connect, dopo di che parli direttamente con il protocollo.
In pratica ogni porta di un server fornisce un diverso "servizio", ed ogni servizio parla con il suo protocollo. Quindi la scelta di cosa e con che protocollo lo fai scegliendo la porta.

Il numero delle porte è standard (fino alla 1024), ma può essere facilmente cambiato dagli amministratori in base alle esigenze. Per esempio la porta 21 viene usata dai server FTP, ma anche dalle shell. La porta 80, la 8080 e la 8000 sono normalmente usate per fare l'HTTP (web), la 25 invio delle emalil (SMTP) e la 23 per la ricezione della posta (POP3), la 993 sia per l'invio che la ricezione delle mail ma con protocollo IMAP

da mqtt.org:
"Are there standard ports for MQTT to use?
Yes. TCP/IP port 1883 is reserved with IANA for use with MQTT. TCP/IP port 8883 is also registered, for using MQTT over SSL."

Quindi, visto che arduino non regge l'SSL, probabilmente dovrai usare la porta 1883

ora che sei connesso, invii la tua stringa di byte, attendi (se necessario) che si completi l'invio, e attendi (se necessario) la risposta.

nel tuo caso prima invii la connectMessage, attendi una risposta positiva (se no è inutile andare avanti), poi invii publishMessage per completare l'operazione
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 12, 2012, 10:07 pm
La tua risposta è  e stata perfetta e chiara  :), ho fatto tutto quello che mi hai detto, ho instaurato un collegamento TCP con cosm sulla porta 1883, il problema nasce quando cerco di inviare il connectMessage, io faccio:

gsm.SimpleWriteln(connectMessage);

ed ottengo un errore in compilazione e cioè:

call of overloadded SimpleWriteln(byte[18]) is ambiguous.

Prova_Protocollo_MQTT.cpp: In function 'void setup()':
Prova_Protocollo_MQTT:66: error: call of overloaded 'SimpleWriteln(byte [18])' is ambiguous
C:\Users\Gianni\Documents\arduino-1.0.1\libraries\GSMSHIELD/SIM900.h:34: note: candidates are: void SIMCOM900::SimpleWriteln(char*) <near match>
C:\Users\Gianni\Documents\arduino-1.0.1\libraries\GSMSHIELD/SIM900.h:36: note:                 void SIMCOM900::SimpleWriteln(const char*) <near match>
C:\Users\Gianni\Documents\arduino-1.0.1\libraries\GSMSHIELD/SIM900.h:38: note:                 void SIMCOM900::SimpleWriteln(int) <near match>

ti posto anche il codice del mio programma.


#include "SIM900.h"
#include <SoftwareSerial.h>
#include "inetGSM.h"
//#include "sms.h"
//#include "call.h"

//To change pins for Software Serial, use the two lines in GSM.cpp.

//GSM Shield for Arduino
//www.open-electronics.org
//this code is based on the example of Arduino Labs.

//Simple sketch to start a connection as client.

byte connectMessage[] = {0x10 //Connect
      , 0x0C + 0x04 //Remaining Length
      , 0x00 //0
      , 0x06 //6
      , 0x4d //M
      , 0x51 //Q
      , 0x49 //I
      , 0x73 //S
      , 0x64 //D
      , 0x70 //P
      , 0x03 //Protocol version = 3
      , 0x02 //Clean session only
      , 0x00 //Keepalive MSB
      , 0x3c //Keepaliave LSB = 60
      , 0x00 //String length MSB
      , 0x02 //String length LSB = 2
      , 0x4d //M
      , 0x70 //P .. Let's say client ID = MP
  };

InetGSM inet;

boolean started=false;

void setup()
{
  //Serial connection.
  Serial.begin(9600);
  Serial.println("GSM Shield testing.");
  //Start configuration of shield with baudrate.
  //For http uses is raccomanded to use 4800 or slower.
  if (gsm.begin(2400)){
    Serial.println("\nstatus=READY");
    started=true; 
  }
  else Serial.println("\nstatus=IDLE");
 
  if(started){
    //GPRS attach, put in order APN, username and password.
    //If no needed auth let them blank.
    if (inet.attachGPRS("internet.wind", "", ""))
      Serial.println("status=ATTACHED");
    else Serial.println("status=ERROR");
    delay(1000);
   
    //Read IP address.
    gsm.SimpleWriteln("AT+CIFSR");
    delay(5000);
    //Read until serial buffer is empty.
    gsm.WhileSimpleRead();
  if(inet.connectTCP("api.cosm.com",1883)){
  Serial.println("Connesso a Cosm");
  gsm.SimpleWriteln(connectMessage);
  }
  else Serial.println("Non Connesso");
   
  }
};

void loop()
{
 
};

Ti ringrazio nuovamente per il supporto, ne approfitto perchè si vede che sei una persona competente e in grado di spiegare le cose in maniera semplice, che è proprio quello che serve a me che mi sono appena avvicinato al mondo dei protocolli internet ed arduino. 



Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 12, 2012, 10:21 pm
sì, mi sono sbgliato, non vuole un array di byte ma un array di char. Dovrebbe bastare semplicemente cambiare il tipo di dato dell'array, da byte a char, senza alcun altro problema
comuque il compilatore ti suggerisce qualcosa:
SimpleWriteln(char*) array di char dinamico
SimpleWriteln(const char*) array di char
SimpleWriteln(int) un int
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: m_ri on Sep 12, 2012, 11:31 pm
noon penso basti fare il casting..vedi,se gli passi una stringa,lui si ferma al primo 0 che vede(significa terminatore di stringa)..ma un array di bytes  può contenere diversi zero(e quindi si fermerebba al primo 0) o non contenerne affatto..
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 12, 2012, 11:47 pm
hai ragione, vedendo che ai byte c'era affianco una lettera pensavo seguissero la tabella ascii.

Allora la soluzione "stupida" è raggrupare 2 a 2 i byte ed inviarli usando la SimpleWriteln(int) ma funziona solo se il numero di byte è pari (mi pare di sì nel caso dei tuoi messaggi)

per esempio
Code: [Select]

int i, mess;
for (i=0;i<lunghezzaArray;i+=2){
   mess = ((int)connectMessage[i])<<8+connectMessage[i+1];
    gsm.SimpleWriteln(mess);
}



la soluzione "difficile" è modificare la libreria per "magiarsi" anche gli array di byte (oppure sempre di char ma specificando la lunghezza, bypassando così il tappo delle stringhe)
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: m_ri on Sep 12, 2012, 11:49 pm
non ho quella libreria sottomano,ma direi che c'è un metodo simpleWrite che accetta due parametri,il vettore dy bytes,e la sua lunghezza...
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 12, 2012, 11:51 pm
non mi pare ci fosse, ma quella libreria a sua volta si poggiava su un'altra libreria(quindi alla fine erano 3 librerie una sopra l'altra), che essendo più "basso livello" dovrebbe avere il metodo, ora controllo

edit: come non detto, anche la libreria più a basso livello lavora con le stringhe, per via del fatto che sono comandi AT. però giaà nella libreria SIM900 si può notare un oggetto _cell, che poi sarebbe la seriale che è collegata con il modulo GSM (SoftwareSerial)...

quindi in SIM900.h aggiungi:

Code: [Select]

void SimpleWrite(byte *comm, int len);


e in SIM900.cpp
Code: [Select]

void SIMCOM900::SimpleWrite(byte *comm, int len)
{
        _cell.write(comm, len);
}


dopo di che potrei usare tranquillamente gli array byte così
gsm.SimpleWriteln(connectMessage, 18); //18 è il numero di byte da scrivere
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 13, 2012, 11:19 am
Ciao, allora ho provato a fare il tutto, risolto problema in compilazione, ma invio il messaggio di connect al server ma questo non mi risponde, allora ho fatto delle prove su un server di un mio amico e ho verificato che dopo aver avviato la connessione TCP, regolarmente accettata dal server, qualunque cosa invio al server questi non riceve nulla; Viceversa se il server manda qualcosa a me io la ricevo.
Ho provato anche a mandare una semplice stringa di caratteri tramite il comando SimpleWrietln ma nulla.
Ho fatto una prova con il metodo get della libreria inetGsm e in quel caso il server riceve le stringhe che si trovano nel metodo.
Non mi capacito quale sia la differenza e del perchè questo avvenga.
Potete illuminarmi!!!??? =(
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 13, 2012, 11:30 am
l'unica divverenza che noto è il carattere di "a capo" che viene aggiunto attraverso la println. Quindi dovresti modificare

Code: [Select]
void SIMCOM900::SimpleWrite(byte *comm, int len)
{
       _cell.write(comm, len);
}


in

Code: [Select]
void SIMCOM900::SimpleWrite(byte *comm, int len)
{
       _cell.write(comm, len);
       _cell.write('\n', 1); //aggiunge il carattere "a capo"
}


però a questo punto ho paura a cosa possa succedere se in mezzo al comando ci sia un valore che corrisponda all'a-capo.. tutto dipende da come interpreta i dati il chip GSM, bisognerebbe vedere che succede a basso livello (libreria gsm.h) però ora sono a lavoro.
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: m_ri on Sep 13, 2012, 02:17 pm
@lesto: sicuro di poter usare   _cell.write('\n', 1)  ?non so com'è fatta la libreria,ma ho paura che facendo così usi 13 o 10(valore asci dell'acapo) come indirizzo per cercarsi il vettore di array..
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 13, 2012, 02:24 pm
uff hai ragione ancora una volta, dovrebbe essere
char acapo = '\n';
_cell.write(&acapo, 1)

con le doppie virgolette, in questo modo lo forzi a a passare l'indirizzo

edit: chissà se si può fare
_cell.write(&'\n', 1)

o meglio
_cell.write("\n", 1)
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: m_ri on Sep 13, 2012, 02:48 pm
si,con il & dovrebbe andare..
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 13, 2012, 04:40 pm
Allora ho provato ha cambiare il metodo come mi avete consigliato, ma purtroppo non funziona mi dà errore in compilazione, quindi ho pensato di inserire nel codice del programma /n direttamente con il SimpleWrite, ho provato a inviare questo connectMessage a cosm, ma questi dopo aver accettato la connessione TCP non risponde nulla, invece secondo il protocollo MQTT dovrebbe rispondere con dei connectACK sia nel caso in cui accetti la richiesta sia nel caso in cui il connectMessage sia sbagliato, quindi mi sorge il dubbio che al server ancora non arriva nulla.
Come posso verificare se il server riceve i byte che gli mando?

Ragazzi veramente grazie per la pazienza e il supporto che mi state dando :P!!!
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 13, 2012, 05:47 pm
uhmm un analizzatore di rete lato server tipo wireshark o snuff
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 13, 2012, 06:18 pm
Ho scaricato il programma che mi hai detto hai idea di come posso fare l'analisi della connessione con il gsm di arduino?
Scusa se ti rompo, ma ho visto che sembra abbastanza complicato, quindi magari se tu avevi già esperienza potevi velocizzarmi un pò la cosa.
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 13, 2012, 06:28 pm
Cmq ottimo programma, stò analizzando il traffico del mio cpu ed è veramente perfetto per quello che serve a me, il problema è far analizzare il traffico sul gsm...
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 13, 2012, 06:30 pm
il traffico del tuo cpu?

non puoi analizzare il traffico sulla rete GSM, ma puoi analizzarlo una volta che sul cavo/wifi una volta che arriva al server
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 14, 2012, 09:22 am
Scusami, ma non ho ben capito come usare questo programma con arduino... :smiley-red:
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 14, 2012, 09:46 am
Ok, risolto!!!
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 14, 2012, 10:31 am
cosa e come hai risolto?
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 14, 2012, 11:00 am
Ciao, scusa hai ragione, sono stato un pò vago, in pratica sono riuscito finalmente ad inviare al mio server di prova una stringa, adesso stavo cercando di scrivere un metodo per farlo, è ho un errore in compilazione:


error: extra qualification 'InetGSM::' on member 'mqttConnect'

il metodo è il seguente:

int InetGSM::mqttConnect(const char* server, int port, char* msg,char* result, int resultlength)
{
  boolean connected=false;
  int n_of_at=0;
  int length_write;
  char end_c[2];
  end_c[0]=0x1a;
  end_c[1]='\0';

  while(n_of_at<3){
     if(!connectTCP(server, port)){
        #ifdef DEBUG_ON
         Serial.println("DB:NOT CONN");
      #endif   
          n_of_at++;
     }
     else{
      connected=true;
      n_of_at=3;
   }
  }

  if(!connected) return 0;
   
  gsm.SimpleWrite(msg);
 
  gsm.SimpleWrite("\n\n");
  gsm.SimpleWrite(end_c);

  switch(gsm.WaitResp(10000, 100, "SEND")){
   case RX_TMOUT_ERR:
      return 0;
   break;
   case RX_FINISHED_STR_NOT_RECV:
      return 0;
   break;
  }

     #ifdef DEBUG_ON
      Serial.println("DB:SENT");
   #endif   
  int res= gsm.read(result, resultlength);

 
  return res;
}
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 14, 2012, 11:11 am
L'errore che avevo era dovuto a una scrittura sbagliata del prototipo del metodo, adesso funziona e riesco ad inviare dati al server sotto forma di stringa, adesso provo con i byte e vedo che succede...
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 14, 2012, 11:20 am
ah, ma quindi per inviare la stringa andava bene il '\n'?
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 14, 2012, 03:25 pm
No, bisogna inserire un array di char ovvero:


char end_c[2];
  end_c[0]=0x1a;
  end_c[1]='\0';

e poi inviarlo a fine stringa, grazie a questo il server ha ricevuto la stringa.
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: lestofante on Sep 14, 2012, 03:36 pm
uhmm magari è il comando che avvisa il GSM che la stringa è terminata e va inviata
Title: Re: Inviare dei Byte ad Patchube(Cosm) tramite sim908
Post by: giannilucia on Sep 14, 2012, 04:41 pm
Ho pensato la stessa cosa, adesso stò cercando di inviare una richiesta di connessione con il protocollo MQTT, l'ho inviata sotto forma di byte a coms, che, da quanto leggo, mi dovrebbe rispondere con un codice che mi dice se accetta o meno la connessione, ma non mi risponde nulla...
non so se magari è possibile mandare delle stringhe, invece dei byte, per chiedere la connessione, secondo te?