Gestione stringhe dettaglio indexOf

Ciao ragazzi questo è il mio primo post, e non sono riuscito a risolvere un mio piccolo problema.
Senza che vi posto l'intero codice perchè vorrei un aiuto su alcune semplici righe.
Sto ottimizzando il codice del mio sketch. Avendo ad esempio le seguenti righe:

cmd1 = msg.indexOf("1=ON");
cmd2 = msg.indexOf("2=ON");
cmd3 = msg.indexOf("3=ON");

Vorrei semplicemente utilizzare un vettore e fare una cosa del genere:

for(i=1; i<10; i++){
   cmd[i]=msg.indexOf("%d=ON",i);
}

Peccato che penso che una cosa del genere non sia possibile, non so se mi avete capito, vorrei fare una cosa tipo la printf del C ovvero:

printf("%d=ON",i)

Sapreste per favore aiutarmi? Grazie in anticipo :slight_smile:

Non dici cosa vuoi fare ... prova a spiegare meglio

allora tu hai una stringa msg che ti arriva penso da un httt get e voi interpretare se c'è un 1 e un on, un 2 e un on oppure off ecc ecc
questo cmd1 sarebbe quello che arduino deve commutare?

ah, forse cerchi la sprint? è come la printf, però stampa in un array di char invece che nello standard output

http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/

Per semplicità vi posto l'intero codice.

//Librerie impiegate per il progetto
#include <SPI.h>
#include <Ethernet.h>

//Creao un array di byte per specificare il mac address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//creo un array di byte per specificare l'indirizzo ip
byte ip[] = {192, 168, 1, 110}; //modificate questo valore in base alla vostra rete

char Data_RX;

String msg = "";
String app1 = "";
String app2 = "";
boolean LEDON[10] = { false };
//Stringa Form 
int cmd1[10] = { 0 };
int cmd2[10] = { 0 };

//indice per cicli
int i = 0;

//creao un oggetto server che rimane in ascolto sulla porta
//specificata
EthernetServer ArduinoServer(80);

void setup(){
  Serial.begin(14400);
  //inizializza lo shield con il mac e l'ip  
  Ethernet.begin(mac, ip);
  //inizializza l'oggetto server
  ArduinoServer.begin();
  
  //definisco i pin come uscite
  for(i=0; i<10; i++){
     pinMode(i, OUTPUT);
  }
}

void loop(){
    //IMPORTANTE pulisco la variabile msg  
    msg = "";
    
    EthernetClient pc_client = ArduinoServer.available();

    //controllo se pc_client è true
    if (pc_client != false){
        //controllo continuamente che il client sia connesso
        while (pc_client.connected()){
            //Controllo se ci sono byte disponibili per la lettura
            if (pc_client.available()){
                //leggo i byte disponibili
                //provenienti dal client
                Data_RX = pc_client.read();
                
                //ricostruisco la stringa ricevuta concatenando i singoli byte
                msg += Data_RX;
                
                //Attendo che tutti i byte siano letti
                //quando Data_RX contiene il carattere
                //di nuova line capisco tutti i byte sono
                //stati letti
                if (Data_RX == '\n'){
                    //cerco all'interno della stringa il parametro che mi interessa
                    for(i=1; i<10; i++){
                      cmd[i]=msg.indexOf("%d=ON",i);
                    }

                    
                    //Invio la risposta al client
                    //invio lo status code
                    pc_client.println("HTTP/1.1 200 OK");
                    //imposto il data type
                    pc_client.println("Content-Type: text/html");
                    pc_client.println();
                    //invio codice html

                    
                    //Piloto l'uscita e invio lo stato al browser
                    for(i = 1; i < 10; i++){
                       if(cmd[i] > 0){
                          digitalWrite(i, HIGH);
                          LEDON[i] = true;
                          //pc_client.print("<p>PIN %d ATTIVO </p>");
                       }else{
                          digitalWrite(i, LOW);
                          LEDON[i] = false;
                          //pc_client.print("<p>PIN %d ATTIVO </p>");
                       }
                    }
                    

                    pc_client.print("<html><head>");    
                    pc_client.print("<meta http-equiv=\"refresh\" content=\"0; url=http://localhost/domotic/riservata/loggato.php\"/>"); 
                    pc_client.print("</head></html>");               
                    //aspetto 1 ms affinche la risposta giunga al browser del client
                    delay(1);
                    //esco dal ciclo while una volta completato l'invio della risposta
                    break;
                }
            }
        }
        //chiudo la connessione
        pc_client.stop();
    }
}

Ora stavo pensando che una soluzione potesse essere anche questa di seguito, ma non mi funziona sapreste dirmi il perchè?

                    for(i = 1; i < 10; i ++){
                       app = i + "=ON";
                       cmd[i] = msg.indexOf(app1);
                    }

Dove app è una stringa d'appoggio che utilizzo per concatenare il numero del pin (int i) e la stringa "=ON", così da ottenere 1=ON, 2=ON etc etc...così con cmd*=indexOf(app1) ottengo un vettore cmd1 contenente un valore intero che mi dice se il led è acceso o meno (perchè se cmd > 0 è su ON, mentre se = 0 è OFF). Ovviamente all'inizio ho dichiarato app1 nel seguente modo String app1 = "";.*
Provando questo script mi rimane fisso il led 1, e non posso fare nient'altro.

la soluzione più facile è

pc_client.print("<p>PIN ");
pc_client.print(i);
pc_client.print(" ATTIVO </p>");

poi se vuoi possiamo complicarci la vita, eh :grin:

Ciao tuxj,
se non ho capito male quello che vuoi fare è estrarti da 'msg' il numero del pin da mettere HIGH? Giusto? Se è così ti conviene usare la funzione String.substring che come parametro prende il risultato della funzione String.indexof('='). String.indexOf ti restituisce la posizione del carattere '=' e String.substring ti estrae la stringa compresa dalla posizione 0 fino al '=' escluso. Occhio al valore di ritorno se indexOf non trova il carattere ricercato :).

Altra cosa, se metti un secondo parametro alla funzione String.indexOf questa inizierà a cercare la stringa rappresentata dal primo paramentro a partire dalla posizione i-esima ossia dal secondo parametro.

for(i=1; i<10; i++){

cmd[i]=msg.indexOf("%d=ON",i);
        }

Dai occhio alla documentazione di String e in particolare http://arduino.cc/en/Reference/StringSubstring e http://arduino.cc/en/Reference/StringIndexOf

Ciao

Innanzitutto grazie a tutti delle risposte siete stati gentilissimi e utilissimi.

lesto:
la soluzione più facile è

pc_client.print("<p>PIN ");

pc_client.print(i);
pc_client.print(" ATTIVO

");



poi se vuoi possiamo complicarci la vita, eh :grin:

Questa non è una soluzione che fa al caso mio perchè gli stati dei led li gestisco attraverso una query al database. Voglio limitare arduino a spegnere e accendere.
Vi posto il codice di arduino che utilizzo tuttora, che funziona per tutti i led, ma è troppo lungo come codice a mio avviso.

//Librerie impiegate per il progetto
#include <SPI.h>
#include <Ethernet.h>

//Creao un array di byte per specificare il mac address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//creo un array di byte per specificare l'indirizzo ip
byte ip[] = {192, 168, 1, 110}; //modificate questo valore in base alla vostra rete

char Data_RX;

String msg = "";
String app = "";
int cmd1 = 0;
int cmd2 = 0;
int cmd3 = 0;
int cmd4 = 0;
int cmd5 = 0;
int cmd6 = 0;
int cmd7 = 0;
int cmd8 = 0;
int cmd9 = 0;

boolean LEDON[10] = { false };
//creao un oggetto server che rimane in ascolto sulla porta
//specificata
EthernetServer ArduinoServer(80);

void setup()
{
  //inizializza lo shield con il mac e l'ip  
  Ethernet.begin(mac, ip);
  //inizializza l'oggetto server
  ArduinoServer.begin();
  
  //definisco i pin2 e pin3 come uscite
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
}

void loop()
{
    //IMPORTANTE pulisco la variabile msg  
    msg = "";
    
    EthernetClient pc_client = ArduinoServer.available();

    //controllo se pc_client è true
    if (pc_client != false)
    {
        //controllo continuamente che il client sia connesso
        while (pc_client.connected())
        {
            //Controllo se ci sono byte disponibili per la lettura
            if (pc_client.available())
            {
                //leggo i byte disponibili
                //provenienti dal client
                Data_RX = pc_client.read();
                
                //ricostruisco la stringa ricevuta concatenando i singoli byte
                msg += Data_RX;
                
                //Attendo che tutti i byte siano letti
                //quando Data_RX contiene il carattere
                //di nuova line capisco tutti i byte sono
                //stati letti
                if (Data_RX == '\n')
                {
                    //cerco all'interno della stringa il parametro che mi interessa
                    cmd1 = msg.indexOf("1=ON");                                       
                    cmd2 = msg.indexOf("2=ON");
                    cmd3 = msg.indexOf("3=ON");
                    cmd4 = msg.indexOf("4=ON");
                    cmd5 = msg.indexOf("5=ON");
                    cmd6 = msg.indexOf("6=ON");
                    cmd7 = msg.indexOf("7=ON");
                    cmd8 = msg.indexOf("8=ON");
                    cmd9 = msg.indexOf("9=ON");
                    
                    //Invio la risposta al client
                    //invio lo status code
                    pc_client.println("HTTP/1.1 200 OK");
                    //imposto il data type
                    pc_client.println("Content-Type: text/html");
                    pc_client.println();
                    
                    //Piloto l'uscita e invio lo stato al browser 2
                    if (cmd1 > 0){                      
                      digitalWrite(1, HIGH);
                      LEDON[1] = true;
                      app = "1=ON";
                      
                    }else{                     
                      digitalWrite(1, LOW);
                      LEDON[1] = false;
                      app = "1=OFF";
                    }

                    //Pilota l'uscita e invio lo stato al browser del led 4
                    if (cmd2 > 0)                    {                      
                      digitalWrite(2, HIGH);
                      LEDON[2] = true;
                      app = app + "&2=ON";
                    }else{                      
                      digitalWrite(2, LOW);
                      LEDON[2] = false;
                      app = app + "&2=OFF";
                    }

                    //Piloto l'uscita e invio lo stato al browser 5
                    if (cmd3 > 0){                      
                      digitalWrite(3, HIGH);
                      LEDON[3] = true;
                      app = app + "&3=ON";
                    }else{                      
                      digitalWrite(3, LOW);
                      LEDON[3] = false;
                      app = app + "&3=OFF";
                    }                        

                    //Piloto l'uscita e invio lo stato al browser 5
                    if (cmd4 > 0){                      
                      digitalWrite(4, HIGH);
                      LEDON[4] = true;
                      app = app + "&4=ON";
                    }else{                      
                      digitalWrite(4, LOW);
                      LEDON[4] = false;
                      app = app + "&4=OFF";
                    }  
                    
                    //Piloto l'uscita e invio lo stato al browser 5
                    if (cmd5 > 0){                      
                      digitalWrite(5, HIGH);
                      LEDON[5] = true;
                      app = app + "&5=ON";
                    }else{                      
                      digitalWrite(5, LOW);
                      LEDON[5] = false;
                      app = app + "&5=OFF";
                    }   
 
                     
                    //Piloto l'uscita e invio lo stato al browser 2
                    if (cmd6 > 0){                      
                      digitalWrite(6, HIGH);
                      LEDON[6] = true;
                      app = app + "&6=ON";
                    }else{                      
                      digitalWrite(6, LOW);
                      LEDON[6] = false;
                      app = app + "&6=OFF";
                    }

                    //Pilota l'uscita e invio lo stato al browser del led 4
                    if (cmd7 > 0){                      
                      digitalWrite(7, HIGH);
                      LEDON[7] = true;
                      app = app + "&7=ON";
                    }else{                      
                      digitalWrite(7, LOW);
                      LEDON[7] = false;
                      app = app + "&7=OFF";
                    }

                    //Piloto l'uscita e invio lo stato al browser 5
                    if (cmd8 > 0){                      
                      digitalWrite(8, HIGH);
                      LEDON[8] = true;
                      app = app + "&8=ON";
                    }else{                      
                      digitalWrite(8, LOW);
                      LEDON[8] = false;
                      app = app + "&8=OFF";
                    }                             

                    //Piloto l'uscita e invio lo stato al browser 5
                    if (cmd9 > 0){                      
                      digitalWrite(9, HIGH);
                      LEDON[9] = true;
                      app = app + "&9=ON";
                    }else{                      
                      digitalWrite(9, LOW);
                      LEDON[9] = false;
                      app = app + "&9=OFF";
                    }                             
                    pc_client.print("<html><head>");    
                    pc_client.print("<meta http-equiv=\"refresh\" content=\"0; url=http://localhost/domotic/riservata/update.php?"); 
                    pc_client.print(app);
                    pc_client.print("\"> ");
                    pc_client.print("</head></html>");                      
                    //aspetto 1 ms affinche la risposta giunga al browser del client
                    delay(1);
                    //esco dal ciclo while una volta completato l'invio della risposta
                    break;
                }
            }
        }
        //chiudo la connessione
        pc_client.stop();
    }
}

Il codice di arduino rimanda ad una pagina update.php che sarebbe:

<?php
    $led[1] = $_GET["1"];
    $led[2] = $_GET["2"];
    $led[3] = $_GET["3"];
    $led[4] = $_GET["4"];
    $led[5] = $_GET["5"];
    $led[6] = $_GET["6"];
    $led[7] = $_GET["7"];
    $led[8] = $_GET["8"];
    $led[9] = $_GET["9"];
    
    require_once("../scriptPHP/mysql_1.php");
    $db=connect_database("valori");
    for($i=1;$i<10;$i++){
      $query='UPDATE led SET stato="'.$led[$i].'" WHERE nled="'.$i.'"'; 
      mysql_query($query,$db);
    }
    
    mysql_close($db);
    
   echo '<html><head><meta http-equiv="refresh" content="0; url=loggato.php"/></head></html>';
?>

I valori di stato vengono salvati nel database, così poi su loggato.php me li posso gestire come voglio.
loggato.php è una pagina abbastanza complicata e lunga (tra cui controllo delle sessioni di accesso etc etc) ma quello che ci interessa qui è il form che invia le istruzioni ad arduino ovvero:

                    <form action="http://192.168.1.110" method="get">
                       LED1 OFF<input type="radio" name="1" value="OFF" checked/>
                            ON <input type="radio" name="1" value="ON" />
                       LED2 OFF<input type="radio" name="2" value="OFF" checked/>
                            ON <input type="radio" name="2" value="ON" />

                       LED3 OFF<input type="radio" name="3" value="OFF" checked/>
                            ON <input type="radio" name="3" value="ON" />
                       LED4 OFF<input type="radio" name="4" value="OFF" checked/>
                            ON <input type="radio" name="4" value="ON" />

                       LED5 OFF<input type="radio" name="5" value="OFF" checked/>
                            ON <input type="radio" name="5" value="ON" />
                       LED6 OFF<input type="radio" name="6" value="OFF" checked/>
                            ON <input type="radio" name="6" value="ON" />
                   
                       LED7 OFF<input type="radio" name="7" value="OFF" checked/>
                            ON <input type="radio" name="7" value="ON" />
                       LED8 OFF<input type="radio" name="8" value="OFF" checked/>
                            ON <input type="radio" name="8" value="ON" />

                       LED9 OFF<input type="radio" name="9" value="OFF" checked/>
                            ON <input type="radio" name="9" value="ON" />
 
                               <input type="submit" value="submit">
                     </form>

Per questo vi sto chiedendo come fare per togliere tutti quegli "if" di controllo su arduino li trovo eccessivi, mi basterebbe crearmi 2 stringhe di appoggio del tipo "NUMERO=ON" e "NUMERO=OFF" per il controllo, che poi utilizzeri all'interno di un ciclo for cambiando il primo carattere (cioè NUMERO) così da poter fare la indexOf di volta in volta così: cmd[i] = msg.indexOf(app) E poi giusto una precisazione, sto vedendo gli esempi della indexOf, come parametri accetta solo caratteri singoli oppure più caratteri. Si può fare una cosa del genere?

app = "1=0N";
cmd = msg.indexOf(app)

cioè passare "app" tra i parametri?

In sintesi se riesco a farmi il confronto con una stringa di appoggio creata di volta in volta, gli if me li riduco grazie ad un vettore cmd di interi, così:

                    for(i = 1; i < 10; i++){
                       if(cmd[i] > 0){
                          digitalWrite(i, HIGH);
                       }else{
                          digitalWrite(i, LOW);
                       }
                    }

Scusate se ho risposto 3 volte ma non mi bastavano i caratteri, vi ringrazio tanto non pensavo che la comunità di arduino potesse essere così utile.7
E scusate se vi stia ossessionando :slight_smile:

perche invece di 1=ON o OFF non ti fai spedire 2 numeri

sostituisci le stringhe

1=ON con comand = 11
1=OFF con comand = 01
2=ON con comand = 12
2=OFF con comand = 02
3=ON con comand = 13
3=OFF con comand = 03
...
...
quando ti arriva questa stringa estrai il numero dopo "comand=" e la dividi in 2 A e B
A sarà il primo carattere 0 oppure 1
B sarà il numero della porta da commutare

if A==1 digitalWrite(B, HIGH);
if A==0 digitalWrite(B, LOW);

semplificando ancora
digitalWrite(B, A);

fine

ciao

pablos:
perche invece di 1=ON o OFF non ti fai spedire 2 numeri

:fearful: perchè non c'avevo pensato!
Grazie mille!!! Veramente!!! Devo mettere [risolto] ???

Ma non è vero in onselected o nel' id dell'elemento puoi passare quello che vuoi
ciao

pablos:
Ma non è vero in onselect o nel' id dell'elemento puoi passare quello che vuoi

...è proprio vero non si finisce mai di imparare :wink: grazie ancora :grin:

Ciao tuxj, ho visto in questa sezione tu chiedevi quello che sto cercando di fare anch'io...Io utilizzo Arduino Uno e ethernet shield con l'aggiunta di shift register per l'aumento delle uscite digitali (per adesso utilizzo 2 shift register ma conto di metterne in cascata un totale di 7-8). Per questo motivo ridurre al minimo lo sketch e quindi limitare gli "IF" è un mio obiettivo.
Non ho molto capito come hai fatto dal suggerimento di Pablos a risolvere il tuo problema. Hai la cortesia di scrivermi un pezzo di sketch derivato da quello che ti posto qui sotto? In questo modo come già detto in altri thread riesco a capire un po' alla volta dato gli esempi.
Grazie in anticipo a te o a chiunque risponderà

#include <Shifter.h>
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x3A, 0x06 };
byte ip[] = { 192,168,1,100 };
EthernetServer server(80);
String query;
//Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 8;
//Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 6;
////Pin connected to Data in (DS) of 74HC595
const int dataPin = 7;

#define NUM_REGISTERS 2

Shifter shifter(dataPin, latchPin, clockPin, NUM_REGISTERS);

void setup()
{
  query = String("");
  Ethernet.begin(mac, ip);
  server.begin();
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}
void loop()
{

  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
	 if (client.available()) {
	  char c = client.read();
	  query.concat(c);
	  if (c == '\n') {
	    client.println("HTTP/1.1 200 OK");
	    client.println("Content-Type: text/html");
	    client.println();
  
//0///////////////////////////////////// 
  if (query.indexOf("accendi0") > 0) {

      shifter.setPin(0, HIGH);
      shifter.write();		 
      delay(1000);
      shifter.clear(); 
      shifter.write();
}

///////////////////////////////////////// 
  if (query.indexOf("accenditutto") > 0) {
      shifter.setAll(HIGH);
      shifter.write();		 
}
///////////////////////////////////////// 
  if (query.indexOf("spegnitutto") > 0) {
      shifter.setAll(LOW);
      shifter.write();	
  }
            client.print("<a href='/accenditutto'>Accendi TUTTO </a>
<a href='/spegnitutto'>Spegni TUTTO </a>
");
	    client.print("<pre>");//DEBUG
	    client.print(query);// DEBUG
	    client.print("</pre>");//DEBUG
	    break;//fermo il ciclo
	  }
          }
}
    delay(1);
    client.stop();
    query = String("");
  }
}

In realtà io devo per adesso solo accendere i led con un delay di 1 sec...quindi non mi interessa per adesso lo spegnimento. Ma credo che una volta capito come hai fatto tu spero mi sarà tutto più chiaro.
Grazie
Ciao

Credevo fosse più di facile utilizzo a prima vista, dovrò veramente mettermi giù a fare delle prove...Grazie mille intanto.
Ma dato che io devo solo gestire le accensioni e i nomi delle accensioni dei singoli registi sono numeri, non potrei utilizzare in qualche modo ancora più semplice una funzione...che ne so tipo un esmpio di questo tipo (non è di sicuro giusto, ma se avete la possibilità di correggerlo nel modo giusto:

for(int i = 0; i < 15; i++){

if (query.indexOf(i) > 0) {
shifter.setPin(i, HIGH);
shifter.write();

}
}

Non è poi così complicato, a me serviva per decifrare una svariata parte di comandi inviata via web.

Se devi mandare solo un numero dovresti dire quale range ha questo numero con 2 esempi, meglio dire cosa vuoi fare e cosa vuoi ottenere. Non conosco la libreria shifter, quindi dovresti tu che la usi dire che informazioni vuole questa lib

ciao

la libreiria shifter non fa altro che indirizzare il pin che vuoi portare alto o basso in una serie di integrati 74hc595 messi in cascata; con un semplice comando tu puoi portare alto o basso un pin o addirittura tutti contemporaneamente.

shifter.setPin(i, HIGH); --> dove i è il numero di pin che voglio portare alto o basso (sapendo che il primo pin del primo shift register è 0, l'ultimo è il 7, il primo del secondo shift register è 8 e così via in base a quanti shift register hai in cascata
shifter.write(); --> manda il comando

Io vorrei dare un comando via web portando alto un pin ma vorrei evitare se possibile di avere tantissimi "if" . Quando usavo i tanti "if" il comando da attribuire era di questo tipo:

if (query.indexOf("Accendi0") > 0) {
** shifter.setPin(0,HIGH);**
** shifter.write();**

e così via, e da browser potevo scrivere nella barra indirizzi http://192.168.1.100/Accendi0 perchè comunque so che questo comando poi lo potrò utilizzare quando mi creerò il sito web su scheda sd da attribuire ad un pulsante virtuale. Ora volevo sapere se c'è un modo più semplice possibile per evitare i tanti "if" e rendere più snello il tutto.
Spero di essermi spiegato. Scusate ma sono veramente alle prime armi e ho una confusione in testa :stuck_out_tongue:
Grazie ancora a tutti.
Ciao