Ciao a tutti dovrei gestire un time-out di 3 secondi in un collegamento Telnet tra due Arduino Uno uno Client e Uno Server. Sapete come farlo ? Ho trovato una mezza specie di soluzione ma non riesco ad uscire dal time-out
chiudo questo Topic ? ...semmai come si fa? :*
Posto il codice in questione
#include <SPI.h> // IMPORTA LIBRERIA SPI
#include <Ethernet.h> // IMPORTA LIBRERIA ETHERNET
byte LED [8] = { 9, 8, 7, 6, 5, 4, 3, 2 }; // DEFINIZIONE ARRAY DI LED
// PARAMETRI ETHERNET
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC ETHERNET SHIELD DEL SERVER
byte gateway[] = {
10, 10, 11, 1 }; // GATEWAY
byte subnet[] = {
255, 255, 255, 0 }; // SUBNET
EthernetServer server = EthernetServer(23); // TELNET 23
IPAddress ip( 10, 10, 11, 17 ); // IP ARDUINO SERVER
EthernetClient client = 0; // INIZIALIZZA IL CLIENT
// ALTRE VARIABILI
byte MSK[8]; // ARRAY DELLA MASCHERA
char CMD[7]; // ARRAY DI COMANDO
boolean statoConnessione = false; // USATA PER VERIFICARE LO STATO DELLA CONNESSIONE CLIENT TO SERVER
unsigned long tempoDaUltimaAzione; // TEMPO IN ms DALL'ULTIMA ATTIVITà
unsigned long timeOut = 3000; // TIMEOUT = 3s
int caratteriRicevuti = 0; // VARIABILE DI CONTEGGIO DEI CARATTERI RICEVUTI
void setup()
{
Ethernet.begin( mac, ip, gateway, gateway, subnet ); // INIZIALIZZA COLLEGAMENTO ETHERNET
server.begin(); // INIZIA AD ASCOLTARE I CLIENT
Serial.begin(9600); // INIZIALIZZA SERIALE
Serial.println(Ethernet.localIP());
for (int i = 0; i < 8; i++)
pinMode( LED[i] , OUTPUT ); // IMPOSTA I PIN DEFINITI IN LED[] COME OUTPUT
}
void loop()
{
// Serial.println(ip);
client = server.available();
if ( client && !statoConnessione ) { //****************************
statoConnessione = true; // STATO CONNESSIONE
client = server.available();
client.println("\nInvio Comandi Arduino Server");
client.println("\nDigitare la combinazione @1XXYY dove XX e' la MASK in notazione HEX e YY e' il comando in notazione HEX");
client.println("\nPremi Invio per inviare il comando ad Arduino Server");
Serial.println("888888");
stampaPrompt();
}
// VERIFICARE LA RICENZIONE DEL TESTO
else
if ( client.connected() && client.available() ) riceviComando();
// VERIFICARE SE LA CONNESSIONE è IN TIME OUT
// if (statoConnessione) verificaTimeoutConnessione();
// QUI RIENTRA IL CODICE PER FARE ALTRE COSE NEL LOOP
}
void verificaCMD(){
if ( CMD[0] == 'C' && CMD[1] == 'L' && CMD[2] == 'O' && CMD[3] == 'S' && CMD[4] == 'E' && CMD[5] == 0x0d ){
client.println();
Serial.println("\nCONNESSIONE CHIUSA !");
client.println("\nCONNESSIONE CHIUSA !");
client.stop();
statoConnessione = false;
}
}
void stampaMessaggioErrore()
{
client.println("\nCOMANDO SCONOSCIUTO !!! ");
}
in pratica il mio problema è il seguente se chiudo la connessione da Telnet come scritto nel codice tutto ok perchè statoConnessione torna false e ho messo client.stop();
se invece lo faccio inviando comandi da un altro Arduino Uno dovrei fare lo stesso ovviamente chiudere la connessione e reimpostare statoConnessione così facendo però eseguendo il loop entro una volta di troppo nella routine //**************************** e non mi accende immediatamente i led come invece dovrebbe fare. In soldoni vorrei che i led si continuassero ad accendersi e spegnersi andando su riceviComando come tutt'ora fa. Solo che quando entro da Telnet dopo aver premuto i bottoni vorrei avere il messaggio di benvenuto quello di //**************************** . Questo non è possibile perchè vengono stampati i caratteri di default del Telnet che vedo da seriale all'atto della connessione e il mio codice correttamente mi fa dire da Telnete COMANDO SCONOSCIUTO !!!
E' un sistema tutto tuo di fare una comunicazione, normalmente si chiude la connessione al termine della ricezione immediatamente, perchè devi decidere tu da linea di comando di chiudere? che senso ha?
Apri e chiudi ogni volta.. fine
questa linea?
if ( CMD[0] == 'C' && CMD[1] == 'L' && CMD[2] == 'O' && CMD[3] == 'S' && CMD[4] == 'E' && CMD[5] == 0x0d ){
è tremenda!!
if (client.available())
{
String readString;
int16_t c;
while ((c = client.read())>0)
{
readString += (char)c;
int cerca_comando = readString .indexOf("stringa da cercare");
if (cerca_comando !=-1) vai alla routine();
}
client.stop();
Poi fallo come meglio credi, ma andrebbe fatto su questo metodo,
Se c'è una richiesta APRI > leggi > esegui >rispondi > chiudi
ciao
Quella linea è se voglio chiudere a prescindere da Telnet...gli passo CLOSE + CR e mi chiude la connessione Telnet cioè tu come faresti ? io infatti l'ho sempre intesa come intendi tu apri leggi esegui chiudi ...
lo farei come si fa un webserver ne più ne meno, un esempio di telnet lo trovi nell'ide oppure http://arduino.cc/en/Tutorial/TelnetClient
si d'accordo ma questo è il client io dovrei fare il lato server...in pratica ho 8 led che dovrebbero essere comandati sia da Telnet che da un Arduino Uno che funge da client in pratica lo fa solo che quando accendo e spengo premendo i bottoni non ritorno nello stato del messaggio di benvenuto o se ci ritorno stando questo nel loop mi fa perdere una pressione di tasto ovvero non si accendono subito i LED bensì alla seconda pressione di pulsante in pratica non faccio una cosa tanto accettabile
il sistema che si usa è una funzione che accetta due stringhe, e le confronta usando un for. In questo modo puoi confrontare qualsiasi stringa.
anche perchè finchè confronti "CLOSE" è abbastaza facile come fai, ma se devi controllare che sia "supercalifragilistichespirlaidoso"... bhe auguri
allora però per ora abbamo visto regole per un codice leggibile, vediamo i problemi:
- stampaPrompt(), riceviComando() non vedo le funzioni..
- quando un client viene disconnesso (time out o altro) non mi pare che resetti tutte le variabili usate, in particolare dovresti cancellare CMD, o meglio azzerare il suo indice, e mettere statoConnessione = false
scusa x fare la stringa dovrei fare come mi ha suggerito paolo?
String readString;
char c;
while ((c = client.read())>0)
{
readString += (char)c;
così?
lesto:
il sistema che si usa è una funzione che accetta due stringhe, e le confronta usando un for. In questo modo puoi confrontare qualsiasi stringa.
anche perchè finchè confronti "CLOSE" è abbastaza facile come fai, ma se devi controllare che sia "supercalifragilistichespirlaidoso"... bhe auguriallora però per ora abbamo visto regole per un codice leggibile, vediamo i problemi:
- stampaPrompt(), riceviComando() non vedo le funzioni..
- quando un client viene disconnesso (time out o altro) non mi pare che resetti tutte le variabili usate, in particolare dovresti cancellare CMD, o meglio azzerare il suo indice, e mettere statoConnessione = false
void stampaPrompt()
{
tempoDaUltimaAzione = millis();
client.flush();
caratteriRicevuti = 0; // CONTA I CARATTERI RICEVUTI
client.println();
client.print("\n>");
Serial.println("PROMPT");
}
void riceviComando()
{
Serial.println("COMANDO RICEVUTO");
char c; // CARATTERE PER LA LETTURA
int caratteriInAttesa; // NUMERO DI CARATTERI IN ATTESA
// COPIA I CARATTERI IN ATTESA NEL BUFFER CMD
// FINO A QUANDO IL CMD è PIENO E NON è STATO RICEVUTO IL CR E NON CI SONO ALTRI CARATTERI DA LEGGERE
caratteriInAttesa = client.available();
do {
c = client.read();
CMD[caratteriRicevuti] = c;
Serial.println(CMD[caratteriRicevuti]);
caratteriRicevuti++;
caratteriInAttesa--;
}
while(caratteriRicevuti <= 7 && c != 0x0d && caratteriInAttesa > 0);
// SE è STATO RICEVUTO CR VAI A VERIFICARE IL COMANDO RICEVUTO ED ESEGUILO
if( c == 0x0d ) {
verificaCMD();
// DOPO AVER COMPLETATO IL COMANDO STAMPA UN NUOVO PROMPT
stampaPrompt();
// statoConnessione = false;
}
ok, per il primo caso on devi per forza passare dalla classe String; esiste la funzione strcmp() per confrontare 2 array di char (però devono finire con il carattere '\0', che è lo standard di fine stringa.
Ma per ora lasciamo stare la cosa.
all'inizio di riceviComando() non azzeri "caratteriRicevuti", quindi alla seconda connessione parti a scrivere nell'array dalla posizone 7 (array overflow), perchè entri almeno una volta nel do...while, che poi ti butta fuori subito.
ho capito che non vorresti azzerare "caratteriRicevuti" in modo da poter leggere un comando in più loop, ma in tal coaso devi azzerarlo appena ricevi un comando completo e quando disconnetti un client (altrimenti leggi mezzo comando da un client e mezzo dal successivo)
lesto:
ok, per il primo caso on devi per forza passare dalla classe String; esiste la funzione strcmp() per confrontare 2 array di char (però devono finire con il carattere '\0', che è lo standard di fine stringa.
Ma per ora lasciamo stare la cosa.all'inizio di riceviComando() non azzeri "caratteriRicevuti", quindi alla seconda connessione parti a scrivere nell'array dalla posizone 7 (array overflow), perchè entri almeno una volta nel do...while, che poi ti butta fuori subito.
ho capito che non vorresti azzerare "caratteriRicevuti" in modo da poter leggere un comando in più loop, ma in tal coaso devi azzerarlo appena ricevi un comando completo e quando disconnetti un client (altrimenti leggi mezzo comando da un client e mezzo dal successivo)
Scusa lesto non ti ho capito bene...mi puoi far vedere nel codice dove sbaglio ? grazie
void riceviComando()
{
Serial.println("COMANDO RICEVUTO");
char c; // CARATTERE PER LA LETTURA
int caratteriInAttesa; // NUMERO DI CARATTERI IN ATTESA
caratteriRicevuti = 0; // SE RIMETTO A 0 CARATTERI RICEVUTI NON SI ACCENDE PROPRIO + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// COPIA I CARATTERI IN ATTESA NEL BUFFER CMD
// FINO A QUANDO IL CMD è PIENO E NON è STATO RICEVUTO IL CR E NON CI SONO ALTRI CARATTERI DA LEGGERE
caratteriInAttesa = client.available();
do {
c = client.read();
CMD[caratteriRicevuti] = c;
Serial.println(CMD[caratteriRicevuti]);
caratteriRicevuti++;
caratteriInAttesa--;
}
while(caratteriRicevuti <= 7 && c != 0x0d && caratteriInAttesa > 0);
// SE è STATO RICEVUTO CR VAI A VERIFICARE IL COMANDO RICEVUTO ED ESEGUILO
if( c == 0x0d ) {
verificaCMD();
// DOPO AVER COMPLETATO IL COMANDO STAMPA UN NUOVO PROMPT
stampaPrompt();
// statoConnessione = false;
}
// SE IL BUFFER CMD E' PIENO SENZA AVERS RICEVUTO CR STAMPA UN MESSAGGIO DI ERRORE
if( caratteriRicevuti >= 7 ) {
client.println();
stampaMessaggioErrore();
stampaPrompt();
}
}
guarda ho messo caratteriRicevuti = 0; nel codice ma non funziona
sì, perchè all'inizio del mio messaggio pensavo che leggessi tutto il comando in un colpo solo, ma invece lo leggi in più loop... se leggi come finisce il mio messaggio dovresti capire come sistemare
ps. ma il resto del codice l'hai stritto tu?
lesto:
sì, perchè all'inizio del mio messaggio pensavo che leggessi tutto il comando in un colpo solo, ma invece lo leggi in più loop... se leggi come finisce il mio messaggio dovresti capire come sistemareps. ma il resto del codice l'hai stritto tu?
Si, quindi se il confronto lo faccio con quell'istruzione "strcmp" che mi hai detto tu su una stringa a quel punto ha senso azzerare di nuovo i caratteri? però mi sfugge come acquisire il comando senza fare client.available();
lascia stare il controllo sulla stringa, aggiungo solo problemi ai problemi. Qunado hai sistemato ci pensaimo.
mi sfugge come acquisire il comando senza fare client.available();
Quando avrei detto una cosa simile?
io ho detto:
ho capito che non vorresti azzerare "caratteriRicevuti" in modo da poter leggere un comando in più loop, ma in tal coaso devi azzerarlo appena ricevi un comando completo e quando disconnetti un client (altrimenti leggi mezzo comando da un client e mezzo dal successivo)
mi stavo proiettando nel caso in cui facevo il confronto con quell'istruzione che mi hai dato tu? ...cioè tu come mi consigli di acquisire il comando ??? x vedere semmai cosa bisogna fare ovvero come dovrei fare il metodo riceviComando ? Grazie mi dai un link x capire cosa fa strcmp ?? grazie
no, con quella istruzione il comando lo acquisisci uguale, solo che aggiungi in coda un \0, poi al posto nella if al posto di controllare lettera per lettera chiami strcmp passando l'array di char letto e la stringa da verificare, (cerca su google come funziona strcmp) e se ritorna 0 (se ricordo bene) allora le stringhe sono uguali.. insomma anzichè controllare lettera per lettera la strcmp fa tutto da sola.
mi consigli di cambiare il codice in questa maniera semmai? intanto cerco strcmp su internet però l'ho già fatto ma ho visto che lo menzionano sul forum inglese di arduino
Ciao, leggi il codice dell'ardupower li c'è la gestione della stringa comando ricevuta carattere a carattere e il timeout.
ciao ragazzi ho sempre il solito problema vorrei che quando mi connetto a Telnet e vengono stampati i caratteri di default quest'ultimi non vengano stampati altrimenti il mio sketch mi da il messaggio d'errore. Come posso evitare la stampa dei caratteri di default della connessione telnet? Grazie ora leggo Ardupower