chiarimenti sui puntatori

salve…
nuovo quesito:
la libreria Ethercard rileva che si sia una connessione http, verificando nel loop così:

 word len = ether.packetReceive(); //Serial.print(len);Serial.print("\n");
   word pos = ether.packetLoop(len);
    if (pos) {
                char *data = (char *) Ethernet::buffer + pos;// Serial.print(data);

poi analizzo la stringa useragent (mi pare si chiami così) per recuperare i parametri passati in questo modo:

if (data[5] == '?') {
                if (getIntArg(data, "mn")){ mn = getIntArg(data, "mn");} else {mn=1;}
                if (getIntArg(data, "up")){ up = getIntArg(data, "up");} else {mn=1;}
                if (getIntArg(data, "az")){ az = getIntArg(data, "az");} else {mn=1;}

la funzione getIntArg è fatta così:

static int getIntArg(const char* data, const char* key, int value =-1) {
    char temp[10];
    if ( ether.findKeyVal(data + 6, temp, sizeof temp, key) > 0 ){value = atoi(temp);}
    return value;
};

e funziona benissimo quando la invoco dal loop …
se invece la metto in un’altra funzione non va e basta …

la prima domanda e’:
questa char *data = (char *) Ethernet::buffer + pos; cosa dice?

definisce un puntatore come uguale ad un altro???

se è così perche passando il puntatore ad un’altra funzione non riesce a leggere i valori?

provo a spiegarmi meglio…

se in una funzione scrivo
Serial.print(data) … funziona benissimo
se invece faccio
az = getIntArg(data, "az"); … non funziona e basta
eppure gli sto passando il puntatore …

la funzione getIntArg si basa sulla seguente funzione facente parte della libreria ethercard…
ether.findKeyVal(data + 6, temp, sizeof temp, key)

suggerimenti?
riflessioni?

… perche se esco dal loop, in un’altra fuznione, stampa bene tutta la stringa con serial.print … ma la funzione che cerca il parametro non trova mai???

Visto che ci dai solo pezzettini non so dirtelo.
Secondo me potrebbe essere un problema di visibilitá delle variabili (variabili locali e globali)
Ciao Uwe

paolosanna:
se in una funzione scrivo
Serial.print(data) .... funziona benissimo
se invece faccio
az = getIntArg(data, "az"); ... non funziona e basta
eppure gli sto passando il puntatore ...

Scusa ma "non funziona e basta" cosa significa?
E poi hai fatto un poco di debug? Se dentro la getIntArg() metti un Serial.println(data) cosa vedi?

paolosanna:
la prima domanda e':
questa

char *data = (char *) Ethernet::buffer + pos;

cosa dice?

A data viene assegnato l'indirizzo di memoria di buffer + un certo numero di byte in più (dati da pos)

Meglio se con delle serial.print fai debug. Ma banalmente quel +6 su data dentro la funzione, non è che ti fa saltare qualcosa (vai troppo avanti) nella stringa ?

@uwe

scusa … ma il codice è grande … cmq lo allego qui se puo servire …

ad ogni buon conto intendevo dire che le funzioni chiamate nel loop restituiscono benissimo i parametri richiesti …

se invece la funzione la richiamo da dentro un’altra funzione (come io vorrei fare) … allora non mi restitusce nulla … cioe la funzione funziona (scusate il gioco di parole) ma non trova nulla … la cosa strana e che se scrivo queste istruzioni dentro una funzione
per esempio se in una fuznione scrivo queste tre istruzioni …

Serial.print (data); // stampa bene il contenuto del buffer
mn = getIntArg(data, “mn”); // non trova il valore cercato, anche se nel buffer cè
Serial.print(data) // ancora stmpa bene il contenuto del buffer

quindi la funzione getInteArg(Data, “”) … non mi trova il parametro anche se cè nel buffer …

anche io ho pensato a questioni di variabili locali o globali ma non lo conciliavo con il fatto che passandogli un puntatore dovrebbe trovare lo stesso il contenuto del buffer… d’altra parte esso non viene distrutto o vuotato perchè anche il serial print successivo stampa benissimo tutto il contenuto del buffer …

@docdoc
non funziona intendo che non mi trova ciò che cerco nel buffer, mentre se lo stampo viene stampato correttamente … In realtà la fuznione sta funzionando bene (mi restiuisce NULL) è come se agisce su un buffer vuoto … quindi non trova nulla …

credo che il problema sia in questa fuznione della libreria ethercard
ether.findKeyVal(data + 6, temp, sizeof temp, key)

secondo voi in quale file dovrei cercarla?

… invece se queste cose le faccio nel loop funge tutto bene …

LAN_test_05_10_2017.zip (7.75 KB)

LAN_test_05_10_2017.zip (7.75 KB)

Si, beh, se la Serial.print() la metti fuori già immaginavo che nel chiamante la variabile fosse sempre la stessa visto che nessuno la cambia, ma per “vedere” cosa legge la getIntArg() se la Serial.print() la metti DENTRO cosa ottieni?

Intendo questo:

static int getIntArg(const char* data, const char* key, int value =-1) {
    char temp[10];
    // SOLO DEBUG
    Serial.print("getIntArg(");
    Serial.print(data);
    Serial.println(")");
    // ---
    if ( ether.findKeyVal(data + 6, temp, sizeof temp, key) > 0 ){value = atoi(temp);}
    return value;
};

EDIT: per la cronaca, la findKeyVal mi pare molto lineare e semplice;

uint8_t EtherCard::findKeyVal (const char *str,char *strbuf, uint8_t maxlen,const char *key)
{
    byte found = false;
    uint8_t i=0;
    const char *kp;
    kp=key;
    while(*str &&  *str!=' ' && *str!='\n' && !found) {
        if (*str == *kp) {
            kp++;
            if (*kp == '\0') {
                str++;
                kp=key;
                if (*str == '=') {
                    found = true;
                }
            }
        } else {
            kp=key;
        }
        str++;
    }
    if (found) {
        // copy the value to a buffer and terminate it with '\0'
        while(*str &&  *str!=' ' && *str!='\n' && *str!='&' && i<maxlen-1) {
            *strbuf=*str;
            i++;
            str++;
            strbuf++;
        }
        *strbuf='\0';
    }
    // return the length of the value
    return(i);
}

nid69ita:
A data viene assegnato l'indirizzo di memoria di buffer + un certo numero di byte in più (dati da pos)

Meglio se con delle serial.print fai debug. Ma banalmente quel +6 su data dentro la funzione, non è che ti fa saltare qualcosa (vai troppo avanti) nella stringa ?

no nid .. guarda questo è il tipico contenuto del buffer

GET /?mn=7&az=26 HTTP/1.1
Host: 192.168.1.208
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.208/?mn=7
Connection: keep-alive
Upgrade-Insecure-Requests: 1

come vedi ciò che cerco io inizia dal 6 carattere in poi..
eppoi ripeto... nel loop fizniona tutto benissimo... e che io voglio toggliere dal loop il richiamo della fuznione che mi recupera i parametri per metterla là dove mi sta costruendo la pagina da iviare al client .. così da fare solo le letture che mi servono ...

docdoc:
Si, beh, se la Serial.print() la metti fuori già immaginavo che nel chiamante la variabile fosse sempre la stessa visto che nessuno la cambia, ma per “vedere” cosa legge la getIntArg() se la Serial.print() la metti DENTRO cosa ottieni?

Intendo questo:

static int getIntArg(const char* data, const char* key, int value =-1) {

char temp[10];
    // SOLO DEBUG
    Serial.print(“getIntArg(”);
    Serial.print(data);
    Serial.println(")");
    // —
    if ( ether.findKeyVal(data + 6, temp, sizeof temp, key) > 0 ){value = atoi(temp);}
    return value;
};




EDIT: per la cronaca, la findKeyVal mi pare molto lineare e semplice;


uint8_t EtherCard::findKeyVal (const char *str,char *strbuf, uint8_t maxlen,const char *key)
{
    byte found = false;
    uint8_t i=0;
    const char *kp;
    kp=key;
    while(*str &&  *str!=’ ’ && *str!=’\n’ && !found) {
        if (*str == *kp) {
            kp++;
            if (*kp == ‘\0’) {
                str++;
                kp=key;
                if (*str == ‘=’) {
                    found = true;
                }
            }
        } else {
            kp=key;
        }
        str++;
    }
    if (found) {
        // copy the value to a buffer and terminate it with ‘\0’
        while(*str &&  *str!=’ ’ && *str!=’\n’ && *str!=’&’ && i<maxlen-1) {
            *strbuf=*str;
            i++;
            str++;
            strbuf++;
        }
        *strbuf=’\0’;
    }
    // return the length of the value
    return(i);
}

ci siamo sovrapposti … aspetta che provo …
aiutami a trovare la findKeyVal

sono in tilt .. domani riprovo. :confused:

Mi pare errato:
GET /?mn=7&az=26
La prima volta salti 6 caratteri e va bene per mn (scavalchi "GET /?")
Ma per az, se ti sei portato il puntatore alla & o ad a di az allora se salti di nuovo 6 caratteri è errato.

nid69ita:
Mi pare errato:
GET /?mn=7&az=26
La prima volta salti 6 caratteri e va bene per mn (scavalchi "GET /?")
Ma per az, se ti sei portato il puntatore alla & o ad a di az allora se salti di nuovo 6 caratteri è errato.

no Nid ...

rincomincia sempre da zero ... nel loop funziona benissimo e se chiamo da altre parti che non funziona..

se estraggo prima una variabile .. poi l'altra, oppure in ordine inverso, se lo interrogo più volte va sempre bene .. purchè sia nel loop

paolosanna:
rincomincia sempre da zero ... nel loop funziona benissimo e se chiamo da altre parti che non funziona..

No, scusa, qui sono d'accordo con nid. Primo, se tu metti nella getIntArg quei Serial.print() che ti ho consigliato (ma LO HAI FATTO O NO?) probabilmente se la data contiene la GET che hai scritto, lì ti scriverà correttamente:

mn=7&az=26

Quindi quando tu poi vai a fare:

if ( ether.findKeyVal(data + 6, temp, sizeof temp, key) > 0 ){value = atoi(temp);}

dato che "data + 6" punta alla stringa "z=26" no troverà MAI né "mn" né "az" a meno che tu con il parametro "data" non passi il puntatore all'intera GET ossia punta alla 'G' (e questo non lo sappiamo perché non ci hai detto cosa contiene esattamente).

Se ti si dà dei consigli e delle prove da fare e non le fai o non dai le risposte, è veramente difficile e uno si stanca.. Se ci dici quindi cosa "vede" la getIntArg possiamo andare avanti, fino a quel momento non avendo dati certi non possiamo aiutarti.

@doc
Scusa ma ieri non ero in grado di fare prove o scrivere qui… troppo stanco dopo il lavoro … quindi umilmente chiedo scusa se ho dato l’ìimpressione di fregarmente della Vs autorevolissima opinione …

oggi ho provato e mi sono fatto un’idea ben precisa della situazione.

Preciso subito che non è problema di indici … il codice va benissimo, puoi usarlo tutte le volte che vuoi e nell’ordine che preferisci per estrarre i parametri … funziona sempre perchè l’indice viene reinizializzato ogni volta che richiami la funzione … ed il contenuto che mi interessa (i parametri) sono sempre oltre il 6 carattere …

allora facendo la prova di debug che dici tu (

static int getIntArg(const char* data, const char* key, int value =-1) {
    char temp[10];
    // SOLO DEBUG
    Serial.print("getIntArg(");
    Serial.print(data);
    Serial.println(")");
    // ---
    if ( ether.findKeyVal(data + 6, temp, sizeof temp, key) > 0 ){value = atoi(temp);}
    return value;
};

nella funzione che costruisce la pagina 5, faccio cos’

 case 5: // pg 5  ********************************************************************************************
  int mn;
      Serial.print("data 1 ("); Serial.print(pt_data); Serial.println(")");
  mn = getIntArg(pt_data, "mn");
      Serial.print("data 2 ("); Serial.print(pt_data); Serial.println(")");

ed il risultato è questo:

data 1 (<hr>
<table>
<tr><td>Menu</td><td><a href='?mn=1'>1</a></td><td><a href='?mn=2'>2</a></td><td><a href='?mn=3'>3</a></td><td><a href='?mn=4'>4</a></td></td><td><a href='?mn=5'>5</a></td></tr>
</table>
<hr>
 ff; background-color: #FFCC66; background-position: center;} 
h1 {color: #FFFFFF; background-color: #FC9804; font-family: 'courier'; text-align: left;} 
h2 {color: #FFFFFF; background-color: #FC9804; font-family: 'courier'; text-align: center;} 
h3 {color: #FFFFFF; background-color: #FC9804; font-family: 'courier';} 
h4 {color: #000000; background-color: #BBBBBB; font-family: 'courier';} 
td {font-family: courier;}
td.1 {width: 50px;} 
td.2 {width: 150px;} 
th {font-family: courier; text-align: right;}
p  {font-family: courier;}
a  {font-family: courier; color: blue;}
</style> 
</head> 
<body> 
<h2>COR configuration page</h2> 
)
getIntArg(<hr>
<table>
<tr><td>Menu</td><td><a href='?mn=1'>1</a></td><td><a href='?mn=2'>2</a></td><td><a href='?mn=3'>3</a></td><td><a href='?mn=4'>4</a></td></td><td><a href='?mn=5'>5</a></td></tr>
</table>
<hr>
 ff; background-color: #FFCC66; background-position: center;} 
h1 {color: #FFFFFF; background-color: #FC9804; font-family: 'courier'; text-align: left;} 
h2 {color: #FFFFFF; background-color: #FC9804; font-family: 'courier'; text-align: center;} 
h3 {color: #FFFFFF; background-color: #FC9804; font-family: 'courier';} 
h4 {color: #000000; background-color: #BBBBBB; font-family: 'courier';} 
td {font-family: courier;}
td.1 {width: 50px;} 
td.2 {width: 150px;} 
th {font-family: courier; text-align: right;}
p  {font-family: courier;}
a  {font-family: courier; color: blue;}
</style> 
</head> 
<body> 
<h2>COR configuration page</h2> 
)
data 2 (<hr>
<table>
<tr><td>Menu</td><td><a href='?mn=1'>1</a></td><td><a href='?mn=2'>2</a></td><td><a href='?mn=3'>3</a></td><td><a href='?mn=4'>4</a></td></td><td><a href='?mn=5'>5</a></td></tr>
</table>
<hr>
 ff; background-color: #FFCC66; background-position: center;} 
h1 {color: #FFFFFF; background-color: #FC9804; font-family: 'courier'; text-align: left;} 
h2 {color: #FFFFFF; background-color: #FC9804; font-family: 'courier'; text-align: center;} 
h3 {color: #FFFFFF; background-color: #FC9804; font-family: 'courier';} 
h4 {color: #000000; background-color: #BBBBBB; font-family: 'courier';} 
td {font-family: courier;}
td.1 {width: 50px;} 
td.2 {width: 150px;} 
th {font-family: courier; text-align: right;}
p  {font-family: courier;}
a  {font-family: courier; color: blue;}
</style> 
</head> 
<body> 
<h2>COR configuration page</h2> 
)

Da qui la conclusione:

Il buffer è già stato distrutto e parzialmente ricostruito con il pacchetto di dati (pagina che sto costruendo) per inviarla al client … ecco perchè non ci trovo più dentro i parametri che cerco …
io pretendevo di cercare i parametri per discriminare ciò che dovevo scrivere nella pagina in costruzione … ma non cè più nulla!! ecco perchè non trovavo …

Nella libreria ethercard (non so le altre) il buffer è lo stesso che viene usato in entrata ed in uscita (almeno così mi pare di avere capito) …

Se è così ho inquadrato il problema e la soluzione… credo che duplichero’ il primo pezzo del buffer e lo utilizzero quello per recuperare i parametri che ci sono dentro … da qualsiasi parte dello script mi occorrano …

cosa mi dite???

paolosanna:
Nella libreria ethercard (non so le altre) il buffer è lo stesso che viene usato in entrata ed in uscita (almeno così mi pare di avere capito) ..

Stando a quello che si vede, si, è così, nel buffer non hai più la GET. Se ci pensi, è anche logico che in una piccola MCU non si possa sprecare molta RAM per due buffer, d'altronde poi la GET è solamente una riga, parsatela quando è presente e memorizzala in una tua variabile.

Comunque qui non ci sono "autorevolissime" opinioni, ti prego di non fare sarcasmo inutile, grazie.

docdoc:
....
Comunque qui non ci sono "autorevolissime" opinioni, ti prego di non fare sarcasmo inutile, grazie.
....

Ciao doc ..
Scusami non era certo mia intenzione fare sarcasmo .... il sarcasmo è una forma di derisione e di non rispetto dell'interlocutore che è lontanissimo da me ...

molto più semplicemente intendevo:

  1. chiedere scusa per non avere risposto velocemente;
  2. riconoscere il valore dei tuoi interventi come quelli di un esperto ... perchè leggo spesso i tuoi interventi nel forum ..

magari quando ho scritto quello che a te è sembrato "sarcastico", l'ho scritto sorridendo, ma con un sorriso amichevole, non sarcastico, e mi aspettavo venisse letto con lo stesso spirito ..
ciao
Grazie comunque degli interventi ..

PS per la cronaca ho risolto come dicevo poco più su .. cioe memorizzo 40 caratteri del buffer su un'altra variabile e la utilizzo quando mi serve recuperare i parametri ..

qui in cosda metto il lavoro fatto... credo sia ormai al 70/80 % ... riesco a leggere ed aggiornare tutti i parametri di funzionamento del "device" scritti sulla eeprom .... per completarlo mi manca:

  • impostare una fuznione di reset che riport tutte le configurazioni allo stato di fabbrica;
  • defininere una fuznione che generi il reset e la ripartenza del micro (per applicare le correzioni apportate alla eeprom) ..
  • l'impostazione di un RTC per gestire un orologio..
  • l'ottimizzazione finale
  • la fusione dello script (di gestione web qio allegato ) con quello di normale funzionamento del "device" ...

una volta finito pubblico qui script (o sketch), schemi e circuiti stampati .. saluti

… a un altra cosa …

sto pensando di definire una sessione di collegamento http, . in modo da poter associare una connessione dopo il login con user e password ad un dato costante ricavato dalla stringa trasmessa dal browser

cioe:

GET /?mn=7&az=26 HTTP/1.1
Host: 192.168.1.208
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.208/?mn=7
Connection: keep-alive
Upgrade-Insecure-Requests: 1

cioè usare il contenuto della seconda e della terza riga per individuare in modo quasi certo l’utente (dopo loggato) per evitare di dover ripetere il login entro un dato intrevallo di tempo e continuare con la configurazione dei parametri fino alla conclusione.

Un’altra cosa che mi occorrerebbe fare e quella di far si che il server web su micro mi invii un file di testo con tutti i parametri di configurazione in modo che possa essere salvato sul pc e riutilizzato all’occorrenza …

Chiaramente la connessione è riservata ad un solo amministratore.

che ne pensi doc?

LAN_test_08_10_2017_2.zip (9.49 KB)

paolosanna:
magari quando ho scritto quello che a te è sembrato "sarcastico", l'ho scritto sorridendo, ma con un sorriso amichevole, non sarcastico, e mi aspettavo venisse letto con lo stesso spirito ..

Ok ok, non preoccuparti. Sai, qui siamo tutti appassionati ed abbiamo sempre qualcosa di nuovo da imparare TUTTI, io per primo.
Ma magari bastava una faccina e non mettere la parola in grassetto, no? :slight_smile:

PS per la cronaca ho risolto come dicevo poco più su .. cioe memorizzo 40 caratteri del buffer su un'altra variabile e la utilizzo quando mi serve recuperare i parametri ..

Bene!

sto pensando di definire una sessione di collegamento http, . in modo da poter associare una connessione dopo il login con user e password ad un dato costante ricavato dalla stringa trasmessa dal browser

Hm non ho mai implementato su Arduino autenticazioni, ma in genere questa cosa si fa con un cookie di sessione, ossia dopo l'autenticazione con user/pw il server genera un numero random e lo manda come cookie al client il quale lo rimanderà ad ogni nuova richiesta, e con la quale riconosci l'utente.

Ma in questo caso la soluzione che pensavi potrebbe essere valida, ma se non hai problemi di sicurezza particolari, non devi gestire sessioni concorrenti, e quindi l'utente si logga da una sola postazione per volta, e questa è nella tua rete locale. In tal caso ti basta anche solo l'indirizzo IP: se da quell'IP è stata fatta la login gli consenti l'accesso senza richiedere le credenziali, se l'IP è diverso dall'ultimo allora torni alla richiesta di login.

Un'altra cosa che mi occorrerebbe fare e quella di far si che il server web su micro mi invii un file di testo con tutti i parametri di configurazione in modo che possa essere salvato sul pc e riutilizzato all'occorrenza

Beh questa la fai con una GET apposita (es. "GET /showcfg") alla quale risponderà con il testo che desideri (non è obbligatorio rispondere in HTML).