Pages: [1] 2   Go Down
Author Topic: Inviare dei Byte ad Patchube(Cosm) tramite sim908  (Read 1968 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 1
Posts: 68
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
 
Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10468
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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).
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Jr. Member
**
Karma: 1
Posts: 68
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...
Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10468
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Jr. Member
**
Karma: 1
Posts: 68
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

La tua risposta è  e stata perfetta e chiara  smiley, 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. 



Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10468
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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..
Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10468
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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)
« Last Edit: September 12, 2012, 04:49:59 pm by lesto » Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non ho quella libreria sottomano,ma direi che c'è un metodo simpleWrite che accetta due parametri,il vettore dy bytes,e la sua lunghezza...
Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10468
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
void SimpleWrite(byte *comm, int len);

e in SIM900.cpp
Code:
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
« Last Edit: September 12, 2012, 05:03:17 pm by lesto » Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Jr. Member
**
Karma: 1
Posts: 68
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!!!??? smiley-cry
Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10468
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

l'unica divverenza che noto è il carattere di "a capo" che viene aggiunto attraverso la println. Quindi dovresti modificare

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

in

Code:
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.
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@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..
Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10468
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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)
« Last Edit: September 13, 2012, 07:47:31 am by lesto » Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

si,con il & dovrebbe andare..
Logged

Pages: [1] 2   Go Up
Jump to: