Invio Comandi tra Client e Server

uil tuo codice:

while ( server.available() && client.connected() ) {                 //  Client-To-Serve                                                                                               
    char c = client.read();                                            //  Legge i Byte su Client
    comando[0] = c;
    comando[1] = c;
    comando[2] = c;
  }

La mia correzzione

Prima di tutto la read() restituisce il primo carattere disponibile o -1 se non ci sono dati. Quindi devi assicurarti di avere ALMENO 3 caratteri dsponibili.

while ( client.connected() && server.available() >= 3 ) {                 //  Client-To-Serve                                                                                               
    char c = client.read();                                            //  Legge i Byte su Client
    comando[0] = c;
    comando[1] = c;
    comando[2] = c;
  }
}

poi: c è una variabile che contoiene l'ultimo carattere letto; tu stai prendendo quetrso carattere e copiandolo 3 volte nell'array comando. Invece vuoi leggere i 3 caratteri;

while ( client.connected() && server.available() >= 3 ) {                 //  Client-To-Serve                                                                                               
    char c = client.read();                                            //  Legge i Byte su Client
    comando[0] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[1] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[2] = c;
  }
}

Infine nel caso della stringa "ON", essendo di soli 2 caratteri non renderebbe mai "server.available() >= 3 " vero; quindi lato client puoi fare client.print("ON "); (notare lo spazio finale)

e ovviamente quel "0x0d" che non ha senso va cambiato in ' ' (notare lo spazio)

#include <SPI.h>                               //  Importa Libreria SPI
#include <Ethernet.h>                          //  Importa Libreria 
//  Ethernet

#define LED 7                                  //  Porta digitale 7 LED

char comando[3] ;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };        //  MAC Ethernet Shield del Server

byte ip[] = { 10, 10, 11, 17 };                             //  IP Arduino Server

EthernetServer server = EthernetServer(23);    //  Telnet porta 23
EthernetClient client = 0;                     //  Inizializza il Client

void setup()
{
  pinMode( LED, OUTPUT );                      //  Imposta LED OUTPUT
  Ethernet.begin(mac, ip);                     //  Inizializza Ethernet
  server.begin();
}
void loop()
{ 
  while ( client.connected() && server.available() >= 3 ) {                 //  Client-To-Serve                                                                                               
    char c = client.read();                                            //  Legge i Byte su Client
    comando[0] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[1] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[2] = c;
  }
  if ( comando[0] == 'O' && comando[1] == 'N' && comando[3] == ' ' ) 
    digitalWrite( LED, HIGH );
  if ( comando[0] == 'O' && comando[1] == 'F' && comando[3] == 'F' ) 
    digitalWrite( LED, LOW );
}

scusa ma non mi funziona così dove sbaglio

sul lato client ho scritto

client.print("ON ");

e

client.print("OFF");

dovrei stampare un carattere alla volta nel lato client?

comando[0] == 'O' && comando[1] == 'N' && comando[3]

gli array partono a contare da 0, quindi un array da 3 elementi ha indici 0, 1 e 2...

edit: lo stesso vale per OFF

si giusto ma non credo cambi granchè ...è stato un errore di distrazione cmq grazie Lesto

in che senso non credi che cambi ganchè? con comando[3] stai andando a leggere una zona di memoria al di fuori del tuo array (array overflow, se il sistema operativo, che arduino non ha, rileva una baggianata del genere ti uccide il programma con un errore di Segmentation Fault, uno degli errori più difficili da correggere individuare e più sensibili lato sicurezza!) , per quel che ne sai lì dentro potrebbe esserci la prima lettera della dichiarazione di indipendenza in giapponese :smiley:

Arduino Lato Client

#include <SPI.h>

#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>
#include <util.h>
#include <WebServer.h>

#define BUTTONON  7                 //  PIN7 INPUT = BUTTON  
#define BUTTONOFF 6                 //  PIN7 INPUT = BUTTON  

int ts1st  = HIGH;                  //  ts1st LEGGE E MEMORIZZA IL LIVELLO DI BUTTON  
int stato1 = HIGH;                  //  stato1 MANTIENE LO STATO DI BUTTON
int ts2st  = HIGH;                  //  ts2st LEGGE E MEMORIZZA IL LIVELLO DI BUTTON  
int stato2 = HIGH;                  //  stato2 MANTIENE LO STATO DI BUTTON
int i = 0;                          //  i CONTA LE VOLTE DI BUTTON ON PUSH
int j = 0;                          //  j CONTA LE VOLTE DI BUTTON OFF PUSH

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x47 };          //  MAC ETHERNET SHIELD
byte ip[] = { 10, 10, 11, 16 };                               //  IP CLIENT 
byte server[] = { 10, 10, 11, 45 };                           //  IP SERVER
byte gateway[] = { 10, 10, 11, 1 };                           //  INDIRIZZO ROUTER GATEWAY
byte subnet[] = { 255, 255, 255, 0 };                         //  SUBNET

EthernetClient client;

void setup() {  

  Ethernet.begin(mac, ip, gateway, subnet);                 //  INIZIALIZZA ETHERNET
  Serial.begin(9600);                                       //  INIZIALIZZA LA SERIALE
  pinMode(BUTTONON, INPUT);                                 //  IMPOSTA IL BUTTONON COME INPUT
  pinMode(BUTTONOFF, INPUT);                                //  IMPOSTA IL BUTTONOFF COME INPUT
  delay(150);                                               //  RITARDO DI 150ms

}  

void loop() {  

  ts1st = digitalRead(BUTTONON);                            //  LEGGE E MEMORIZZA IL VALORE DI BUTTONON
  ts2st = digitalRead(BUTTONOFF);                           //  LEGGE E MEMORIZZA IL VALORE DI BUTTONOFF

    if ( ts1st == HIGH && stato1 == HIGH );
  else{
    if ( ts1st == LOW && stato1 == HIGH ){                    //  PULSANTE PUSH FASE ON
      stato1 = LOW;                                           //  IMPOSTA IL NUOVO STATO = LOW
      delay(150);                                             //  RITARDO 150ms
      i++;                                                    //  INCREMENTA CONTEGGIO PUSH
      Serial.print(" IL BOTTONE ON E' STATO PREMUTO ");       //  STAMPA IL NUMERO DI PUSH EFFETTUATI
      Serial.print(i);
      Serial.print(" VOLTE");
      Serial.println();
      if (client.connect(server, 23)){
        client.print("ON ");      
        client.stop();
      }
      else{
        Serial.println("Connessione ON fallita");  //  Altrimenti
        //  Stampa su COM3 Connessione ON fallita
        client.stop();                 //  Chiudi connessione
      }
    }
    if ( ts1st == HIGH && stato1 == LOW )                   //  POSIZIONE DI RIPOSO FASE OFF
      stato1 = HIGH;                                        //  AGGIORNA IL NUOVO STATO DI BUTTONON = HIGH
  }

  if ( ts2st == HIGH && stato2 == HIGH );
  else{
    if ( ts2st == LOW && stato2 == HIGH ){                    //  PULSANTE PUSH FASE ON
      stato2 = LOW;                                           //  IMPOSTA IL NUOVO STATO = LOW
      delay(150);                                             //  RITARDO 150ms
      j++;                                                    //  INCREMENTA CONTEGGIO PUSH
      Serial.print(" IL BOTTONE OFF E' STATO PREMUTO ");      //  STAMPA IL NUMERO DI PUSH EFFETTUATI
      Serial.print(j);
      Serial.print(" VOLTE");
      Serial.println();
      if (client.connect(server, 23)){
        client.print("OFF");      
        client.stop();
      }
      else{
        Serial.println("Connessione OFF fallita");    //  Altrimenti
                                                     //  Stampa su COM3 Connessione ON fallita
        client.stop();                               //  Chiudi connessione
      }
    }
    if ( ts2st == HIGH && stato2 == LOW )                     //  POSIZIONE DI RIPOSO FASE OFF
      stato2 = HIGH;                                          //  AGGIORNA IL NUOVO STATO DI BUTTON = HIGH     
  }
}

Arduino Lato Server

#include <SPI.h>                               //  Importa Libreria SPI
#include <Ethernet.h>                          //  Importa Libreria 
//  Ethernet

#define LED 7                                  //  Porta digitale 7 LED

char comando[3] ;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };        //  MAC Ethernet Shield del Server

byte ip[] = { 10, 10, 11, 17 };                             //  IP Arduino Server

EthernetServer server = EthernetServer(23);    //  Telnet porta 23
EthernetClient client = 0;                     //  Inizializza il Client

void setup()
{
  pinMode( LED, OUTPUT );                      //  Imposta LED OUTPUT
  Ethernet.begin(mac, ip);                     //  Inizializza Ethernet
  server.begin();
}
void loop()
{ 
  while ( client.connected() && server.available() >= 3 ) {                 //  Client-To-Serve                                                                                               
    char c = client.read();                                            //  Legge i Byte su Client
    comando[0] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[1] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[2] = c;
  }
  if ( comando[0] == 'O' && comando[1] == 'N' && comando[2] == ' ' ) 
    digitalWrite( LED, HIGH );
  if ( comando[0] == 'O' && comando[1] == 'F' && comando[2] == 'F' ) 
    digitalWrite( LED, LOW );
}

Si Lesto non volevo dire che avevo fatto una cosa azzeccata anzi una sciocchezza enorme ho fatto, ma continua a non accendermi il LED messo sul PIN 7 del mio arduino Server
Grazie

collegati via telent al server, e invia i comandi tu stesso (non serve premere invio, telnet invia i caratteri mentre li digiti, quindi se sbagli a digitare in realtà il tasto cancella non funziona, anche se SEMBRA farlo)

Lesto capisco cosa intendi, però questo problema che mi è stato assegnato è di fare una rete in cui ci sono N Client ( N Arduino Uno ) e N server (altri N Arduino Uno ) ognuno ha un ip in pratica gli N client hanno connesse delle pulsantiere touch e vanno a comandare in maniera confusionaria (IP) gli altri server che hanno invece collegati dei Relay quindi i comandi glieli devo passare in questo modo altrimenti risulta complicato . Dovrebbe in soldoni premi un bottone sul lato client accendi una luce o lo scaldabagno di uno dei tanti server.

si ma per fare i test devi andare per gradi, prima fai funzionare il server con telnet, poi lo fai funzionare con il client.
Altrimenti impazzisci a cercare nel server un errore del client.

Lesto ho fatto come dici tu sono andato su Telnet all'indirizzo IP specificato x il server se faccio 1 e 0 se li digito il led si accende e si spegne se digito "ON " oppure "OFF" con il codice di ON e OFF del server non va guarda il codice sarebbe questo

#include <SPI.h>                               //  Importa Libreria SPI
#include <Ethernet.h>                          //  Importa Libreria 
//  Ethernet

#define LED 7                                  //  Porta digitale 7 LED

char comando[3] ;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };        //  MAC Ethernet Shield del Server

byte ip[] = { 10, 10, 11, 17 };                             //  IP Arduino Server

EthernetServer server = EthernetServer(23);    //  Telnet porta 23
EthernetClient client = 0;                     //  Inizializza il Client

void setup()
{
  pinMode( LED, OUTPUT );                      //  Imposta LED OUTPUT
  Ethernet.begin(mac, ip);                     //  Inizializza Ethernet
  server.begin();
}
void loop()
{ 
  while ( client.connected() && server.available() >= 3 ) {                 //  Client-To-Serve                                                                                               
    char c = client.read();                                            //  Legge i Byte su Client
    comando[0] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[1] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[2] = c;
  }
  if ( comando[0] == 'O' && comando[1] == 'N' && comando[2] == ' ' ) 
    digitalWrite( LED, HIGH );
  if ( comando[0] == 'O' && comando[1] == 'F' && comando[2] == 'F' ) 
    digitalWrite( LED, LOW );
}

Sicuramente è xchè client.read legge un carattere alla volta :slight_smile: però come faccio a fargli leggere i 3 caratteri??? Grazie sempre con telnet dal lato server

il fatto di leggere 3 caratteri lo stai già facendo, e si fa esattamente così, si legge un carattere alla volta e si riscostruisce.

se faccio 1 e 0 se li digito il led si accende e si spegne se digito "ON " oppure "OFF" con il codice di ON e OFF del server non va

se non hai ricaricato il codice sul server con le modifiche che abbiamo fatto fin'ora per legger 3 lettere ci credo che non funziona. Se avessi caricato il codice 1 e 0 non dovrebbero più funzionare.

Lesto come dicevo prima

ho caricato questo sketch su un arduino uno

#include <SPI.h>                               //  Importa Libreria SPI
#include <Ethernet.h>                          //  Importa Libreria 
//  Ethernet

#define LED 7                                  //  Porta digitale 7 LED

char comando[3] ;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };        //  MAC Ethernet Shield del Server

byte ip[] = { 10, 10, 11, 17 };                             //  IP Arduino Server

EthernetServer server = EthernetServer(23);    //  Telnet porta 23
EthernetClient client = 0;                     //  Inizializza il Client

void setup()
{
  pinMode( LED, OUTPUT );                      //  Imposta LED OUTPUT
  Ethernet.begin(mac, ip);                     //  Inizializza Ethernet
  server.begin();
}
void loop()
{ 
  while ( client.connected() && server.available() >= 3 ) {                 //  Client-To-Serve                                                                                               
    char c = client.read();                                            //  Legge i Byte su Client
    comando[0] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[1] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[2] = c;
  }
  if ( comando[0] == 'O' && comando[1] == 'N' && comando[2] == ' ' ) 
    digitalWrite( LED, HIGH );
  if ( comando[0] == 'O' && comando[1] == 'F' && comando[2] == 'F' ) 
    digitalWrite( LED, LOW );
}

poi sono andato su putty ho aperto la pagina telnet dell ip 10.10.11.17 ok ? e se faccio 1 e 0 ok il led si accende e si spegne se scrivo ON oppure OFF non succede nulla :slight_smile: dove sbaglio?

sbagli che NON hai caricato il codice sull'arduino, altrimenti 1 e 0 NON funzionerebbero.
Poi magari on funzionerebbero nemmeno "ON" e "OFF" (ma dubito), ma sicuramente 0 e 1 non devono funizonare..

cioè mi spieghi se hai veramente caricato quel codice come mai si accende quando scrivi 0 e 1? arduino non se lo inventa certo dal nulla :slight_smile:

l'unica spiegazione è che sia rimasto sopra il vecchio codice.

Suggerimento: quando carichi il codice togli l'ethernet shield, se il problema persiste fai il reset a mano

se carico questo codice su arduino

#include <SPI.h>                                              //  IMPORTA LIBRERIA SPI
#include <Ethernet.h>                                         //  IMPORTA LIBRERIA ETHERNET 

#define LED 7                                                 //  PORTA DIGITALE 7 LED

//  PARAMETRI ETHERNET

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };          //  MAC ETHERNET SHIELD DEL SERVER 
byte ip[] = { 10, 10, 11, 17 };                               //  IP ARDUINO SERVER
byte gateway[] = { 10, 10, 11, 1 };
byte subnet[] = { 255, 255, 255, 0 };                             

//  ALTRE VARIABILI

#define dimCmd 8      //  LUNGHEZZA DEL PIù LUNGO COMANDO
int cmd[dimCmd];      //  ARRAY DI COMANDO
int bitRicevuti = 0;  //  NUMERO DI BIT RICEVUTI

boolean connectState = false;                  //  USATA PER VERIFICARE CONNESSIONE CLIENT TO SERVER

unsigned long tempoDaUltimaAzione;             //  TEMPO IN ms DALL'ULTIMA ATTIVITà
unsigned long tempoMassimoPermesso = 300000;   //  5 MINUTI

EthernetServer server = EthernetServer(23);    //  Telnet porta 23
EthernetClient client = 0;                     //  Inizializza il Client

void setup()
{
  pinMode( LED, OUTPUT );                      //  Imposta LED OUTPUT
  Ethernet.begin(mac, ip);                     //  Inizializza Ethernet
  server.begin();
  delay(150);
}
void loop()
{ 
  if (server.available() && client.connected()) {  //  BYTE SUL SERVER & CONNECTED

    char c = client.read();                        //  LEGGE I BYTE SU CLIENT

    if ( c == '1' )                                //  SE BYTE = 1 LED ON
      digitalWrite( LED, HIGH );
    else
      if ( c == '0' )                              //  SE BYE = 0 LED OFF
        digitalWrite( LED, LOW );
  }
}

vado su tera term e digito 1 poi 0 il led si accende e si spegne

se carico l'altro quello del messaggio precedente con ON E OFF e provo da tera term a digitare ON O OFF IL LED non si accende...vorrei capire perchè

a me sembra stano che entrambi i codici funzionino, visto che non inizializzi mai la variabile client... ti manca un pezzo!
Fai più attenzione al codice che posti e alla descrizione degli errori...

il pezzo che manca:

client = server.available();

il pezzo errato

while  (server.available() >3 && client.connected()) {

diventa

while (client.available() < 3 && client.connected()) {

infatti server.available() ritorna l'istanza ad un EthernetClient connesso, una volta che abbiamo il client vogliamo sapere il numero di caratteri che ci ha spedito che s ottiene con client.available()

quindi diventa:

void loop()
{ 
  client = server.available();
  if (client){  //se si è connesso qualcuno
    while ( client.connected() && client.available() < 3 ) {                 //  Client-To-Serve                                                                                               
       //aspetta senza far nulla che il client si disconnetta o invii almeno 3 lettere
    }

    if (client.available() < 3) { //il client si è disconnesso, ma non ha inviato 3 lettere
      client.close(); //chiudiamo comunque la comunicazione in modo pulito, e rilasciamo eventuali risorse della classe
      return; //non vogliamo fare altro, ternima questo loop() immediatamente (e quindi passiamo al prossimo loop da capo)
    }
    char c = client.read();                                            //  Legge i Byte su Client
    comando[0] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[1] = c;
    c = client.read();                                            //  Legge i Byte su Client
    comando[2] = c;
    if ( comando[0] == 'O' && comando[1] == 'N' && comando[2] == ' ' ) 
      digitalWrite( LED, HIGH );
    if ( comando[0] == 'O' && comando[1] == 'F' && comando[2] == 'F' ) 
      digitalWrite( LED, LOW );
 }
}

Grande Lesto mo funziona alla grande cerco pure di capire come hai fatto :wink: ...ma tipo io un client posso connetterlo ad N server facendo semplicemente client.connect(server,23); dove ovviamente server è l'IP del server a cui voglio connetterlo giusto ? :smiley: penso che sto ragionamento non faccia una piega ma per inviare un numero ? basta fare client.print(010101, BIN); x dirgli che è binario ? ...grazie mille ancora !

dipende. Un'oggetto client può essere connesso ad un solo server per volta (se non come fai a dirgli da chi leggere/scrivere?). Ma nulla vieta di avere uno più (magari un array) di oggetti client, ognuno connesso al suo server, e magari anche più di uno connesso allo stesso server.

Mi pare che però l'ethernet shield al massimo gestica 5 connessioni simultanee... Quindi esitono dei limiti, che sono aggirabili in certe condizioni

credo siano 4 le connessioni contemporanee... una cosa sullo sketch di prima a me client.close() non me lo prendeva io c'ho messo client.stop() diceva che close non era specificato nella libreria ethernet o cmq che non era un comando da applicare a client perchè? cmq con client.stop al posto di client.close va alla grande

perchè mi son sbagliato io, close non esite, ma vedo che hai risolto il bug da solo :grin:

finchè è così semplice ci arrivo anche io :roll_eyes: Grazie ancora...ma per scambiare questi comandi tra client e server mi basta studiare i comandi della libreria Ethernet sia lato server che lato client giusto x intenderci qui Ethernet - Arduino Reference giusto?