trasformare byte in stringa

Salve a tutti mi permetto di chiedere a voi un aiuto per una cosa per la quale non riesco a trovare soluzione. Ho girato in lungo ed in largo ma non c'è nulla che mi possa aver aiutato a risolvere. Certo è che anche la mia non eccelsa conoscenza del linguaggio non mi aiuta, ma per altre cose forse egualmente difficili sono riuscito sempre a barcamenarmi e a definire. stavolta no :-(

SCENARIO : Connesso ad un arduino mega c'è un modulo ethernet enc28j60 che lavora in TCP senza problemi con la libreria UIPEthernet. Per leggere dati che arrivano dal server una stringa, viene utilizzato questo codice

   int size;
   while((size = client.available()) > 0)
   {
       uint8_t* msg = (uint8_t*)malloc(size);
       size = client.read(msg,size);
       Serial.write(msg,size);
       Serial.println();
       free(msg);
    }

e fin qui nulla-questio. sul monitor seriale leggo tutto alla perfezione

PROBLEMA; ho necessità che il pacchetto in arrivo non sia solo visualizzato, ma che finisca in una variabile stringa per poi poter essere utilizzato per decodifiche, controlli etc. Insomma ... ho necessità di un valore tangibile da dare in pasto alle altre routines.

Ho provato con char - word, ho cercato di usare loop per prendere i singoli caratteri, ho usato altre mille alchimie anche basandomi su pseudo esempi presi in giro per il web ma mai nessuno che abbia risolto perché in effetti gli esempi basavano le loro fondamento su serial.print (un byte alla volta) mentre qui in pratica arriva una serie intera. Non lapidatemi se sto dicendo eresie e se forse la soluzione è semplice . Io non l'ho trovata...

vi ringrazio

peppe

Prima di tutto, essendo il tuo primo post, ti chiedo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione) e di leggere con attenzione il REGOLAMENTO ...

... poi, molto semplicemente tu hai in msg il numero di caratteri che è memorizzato in size, tanto è vero che:

  1. allochi uno spazio di memoria pari a "size"
  2. ci metti dentro i caratteri
  3. li stampi (... dicendo alla write di stampare "size" caratteri che si trovano in "msg")
  4. liberi la meoria (... e quindi li cancelli)

Ora, [u]prima della free(msg)[/u], in cui rilasci la memoria e perdi tutto, semplicemente devi copiati "size" caratteri (... ovvero N caratteri dove N è scritto dentro size) da msg in un tuo array di char che avrai precedentemente definito.

Guglielmo

ciao Guglielmo
grazie per aver risposto in modo così immediato.
ho provveduto a presentarmi e chiedo scusa se non l’ho fatto prima. spero di aver recuperato.
purtroppo non ho l’arduino in questione qui a casa ed una prova pratica la potrò fare solo domattina.
intanto mi “preparo” …
per quanto riguarda il problema in pratica tu mi dici di fare una cosa del genere

   int size;
   char    testoChar[100]; 
   String  testoStringa;                         

   while((size = client.available()) > 0)
   {
       uint8_t* msg = (uint8_t*)malloc(size);
       size = client.read(msg,size);
       Serial.write(msg,size);
       Serial.println();

       for(int i = 0; i <= size; i++)      
       {                                             
           testoChar[i] = msg[i];                 
       }                                             

       free(msg);
    }

    testoStringa = String(testoChar);

Ribadisco che ora non posso provare il codice, ma dimmi se ho scritto tutto in modo esatto o in ogni caso se sono sulla giusta strada (anche se mi sembra che questo tipo di prova l’ho già fatta e non ha dato esito positivo).

grazie
peppe

… mmm, sai perché così io credo ti dia problemi? Perché non è detto che i caratteri arrivino tutti assieme e quindi il ciclo while viene ripetuto più volte e tu sovrascrivi ogni volta testoChar con il pezzetto ricevuto.

Io userei due indici e occhio al for, come lo hai scritto tu vai oltre il limite dei caratteri ricevuti (ricorda che l’elemento 0 è comunque un elemento), inoltre, essendo il for seguito da un singolo statement, puoi evitare le graffe :

  int size;
  char    testoChar[100];
  byte    indiceTesto;
  String  testoStringa;
  ...
  ...
  ...
  indiceTesto = 0;
  while((size = client.available()) > 0)
  {
      uint8_t* msg = (uint8_t*)malloc(size);
      size = client.read(msg,size);
      Serial.write(msg,size);
      Serial.println();

      for(int i = 0; i < size; i++) testoChar[indiceTesto + i] = msg[i];
      indiceTesto += size;

      free(msg);
   }
   ...
   ...

Un ultima cosa … sei su una piccola MCU con soli 2KB di SRAM … per quanto possibile NON usare la classe String(), ma impara ad usare sempre le stringhe fatte come array di char, molto più veloci e sotto il tuo completo controllo.

Guglielmo

Quanto è lungo il pacchetto? ha un carattere che delimita la sua terminazione?

vb ... una cosa per volta ... non tutti gli utenti sono "Unix Guru" e le cose meglio farle passo passo senza complicargli la vita ;)

Guglielmo

@gbp01 penso sia difficile complicargliela piu di cosi, si usa un buffer di 100 elementi senza nemmeno sapere quanto possa essere grande il pacchetto dunque alta possibilità di buffer overflow, in piu si utilizzano due buffer (di cui uno ridicolo con malloc) per eseguire praticamente la stessa operazione.
Informare che prima di fare qualsiasi operazione è meglio sapere la sua dimensione ed il suo formato è piu educativo di un codice (probabilmente) buggato. :wink:

vb, con te sempre i soliti discorsi ... ::)

Come avrai notato ... quella NON è farina del suo sacco, ma è un pezzo di codice copiato da chissà dove. Intanto è bene che capisca perché probabilmente non riusciva a recuperare il messaggio tutto assieme, poi, il passo successivo che dovrà fare, è sicuramente eliminare le inutili malloc() e free(), ristrutturando e snellendo tutto il codice ... ... ma, come sempre, "se si mette troppa carne al fuoco" ... conosci il risultato ... ;)

Guglielmo

@gbp01 sai anche cosa succede a cotruire una casa senza fondamenta? :wink:
finisco qui l O.T. invitandoti a comunicarmi via pm i tuoi giudizi personali in modo da non affogare il thread di risposte non pertinenti.

vbextreme: @gbp01 sai anche cosa succede a cotruire una casa senza fondamenta? ;)

... guarda, io debbo assentarmi per qualche giorno ... continua ad aiutare tu peppe e buona continuazione :)

Guglielmo

vbextreme: @gbp01 sai anche cosa succede a cotruire una casa senza fondamenta? ;)

Che levita sul vuoto ? :D

// — ON lieve off topic necessario —
allora …
premesso che non volevo in modo più assoluto creare guerre intestine qui nel forum e mi sono trovato ahimè in mezzo ad una sparatoria in modo incolpevole, credo che la migliore situazione sia sempre quella di risolvere i problemi partecipando e creando contenziosi costruttivi, dai quali si può imparare molto dalle esperienze di tutti gli attori.
Sono dell’idea che il proverbio “tutte le strade portano a roma” sia quanto di più idoneo e calzante in situazioni di programmazione … e non solo.
ci sono mille modi per risolvere i problemi ed ognuno di noi, in base alle esperienze pregresse che formano un background assolutamente soggettivo, arriva a destinazione in modo differente.
detto questo, io vengo da 30 anni di programmazione in basic e vb6 e, per motivi di età e di lavoro, mi son dovuto fermare.
apprendere il linguaggio di arduino per me, ripeto alla mia età (ormai coi neuroni in part-time), mi ha creato non pochi problemi, soprattutto con le stringhe.
in vb6 gestire le stringhe è un gioco da ragazzi. con due istruzioni si fanno cose da circo.
qui ho notato che ci vuole la laurea in ingegneria termonucleare globale … ma ripeto. ho una esperienza da ragazzotto visualbasic, non da esperto in c.
nonostante tutto cerco di capire e di imparare ed arrivo a fare domande al forum - e quindi a scocciare la community - solo se su Google non ho trovato nulla, neanche in turco aramaico antico …
ciò è successo per questa routine.
trovata in rete in mille posti, sempre identica, senza ulteriori spiegazioni, ma funzionante.
è parte integrante ed essenziale dello sketch TCPSERVER.INO dentro la libreria arduino_uip-master che gestisce il modulo ethernet ENC28J16
quindi in un certo senso ritengo (ripeto : ritengo) sia solida …
nulla vieta di modificarla ed eliminare cose inutili o doppie che possono portare ad uno snellimento del programma.
// — OFF lieve off topic necessario —

a questo punto, basandomi sulle info e gli esempi che Guglielmo mi ha proposto, mi sono adoperato per vedere se tutto funzionasse.
la risposta è NI, in quanto finalmente ho avuto nella variabile char da lui creata i dati necessari
ma proprio perché il buffer era di 100 (dato da me come in vb6 : metti di più se non sai, tanto non succede nulla), spesso comparivano caratteri spuri anche se SIZE era di 16 caratteri.
da ricordare che i dati in arrivo NON sono sempre fissi e non so se hanno terminazione tipo CR o altro.
mi direte : ma tu vuoi fare programmazione difficile senza avere pieno possesso di ciò che stai smanettando …
forse è così … ma cerco di imparare e capire al meglio
ho quindi spostato la definizione del buffer dentro il ciclo while, definendolo di eguale misura a SIZE
così pare funzionare

          int size;
          // char    testoChar[100];     <-----dimensionamento levato da qui ....
          byte    indiceTesto;
        
          indiceTesto = 0;
          
          while((size = client.available()) > 0)
          {
              uint8_t* msg = (uint8_t*)malloc(size);
              size = client.read(msg,size);
              Serial.write(msg,size);
              Serial.println();
           
              char testoChar[size];      <---------- e messo qui 
               
              for(int i = 0; i < size; i++) testoChar[indiceTesto + i] = msg[i];
              indiceTesto += size;
              
              Serial.print(testoChar);
              Serial.println();

              
              free(msg);
           }

concludendo e forse ripetendomi : partendo dalle essenziali info che Guglielmo mi ha dato in modo quasi real-time e passando per quelle di vbesxtreme che mi hanno accesso la lampadina dell’oversize, invito - tutti coloro che possano farlo - a darmi una mano per snellire il codice, in modo da evitare rallentamenti inutili.
in C, ribadisco, non sono una cima …

Basandomi su quanto detto una riga più su, mi permetto di dire quello che un utente vorrebbe sempre trovare in un forum : la possibilità di unire alla propria esperienza soggettiva tutte le altre presenti, in una sinergia di conoscenza che, in questo modo, produrrebbe di certo risultati vettoriali.
Una tavola rotonda, insomma, nella quale si possa discutere affermando il proprio background come alternativa a quello di altri, in un clima di costruttivo, collettivo e gioviale interagire.
saluti

peppe

Tranquillo peppe, assolutamente nessuna guerra intestina
… io debbo veramente allontanarmi qualche giorno :grin: :grin: :grin:

Ora, il problema che riscontri è dovuto al fatto che, sempre, le strighe di caratteri in C (array di char) vanno terminate con il valore 0x00 quindi, per risolvere il problemino che avevi, bastava correggere il codice in :

  for(int i = 0; i < size; i++) testoChar[indiceTesto + i] = msg[i];
  indiceTesto += size;
  testoChar[indiceTesto] = 0x00;

e lasciando la dichiarazione dove l’avevi messa, dimensionando l’array in modo che, SICURAMENTE, possa contenere la stringa massima che ti aspetti di ricevere + 1 char … il terminatore 0x00 :wink:

Guglielmo

nonostante mi piaccia l'idea della casa che fluttua forse bisogna iniziare a leggere qualcosa sulle stringhe, una ricerca quale "linguaggio c stringhe" puo portare a dei bei tutorial una volta che si ha una buona infarinata sulle stringhe o meglio vettori di caratteri si può procedere con il programma. Per poter salvare i dati in arrivo dentro ad un buffer devi conoscere la dimensione massima che può assumere e il terminatore, altrimenti il codice se mai funzionerà lo farà per puro caso e anche un minimo cambiamento farebbe smettere di funzionare la tua applicazione. Hai tuttavia altre possibili implementazioni, tipo analizzare in realtime i dati in arrivo senza cosi appoggiarti ad un secondo buffer.Per far cio devi però spiegare che dati ricevi e come li devi interpretare. prova comunque a spiegare bene che pacchetti ricevi, ad esempio prava a postarne alcuni tramite gli appositi tag code.

grazie Guglielmo per avermi dato il codice definitivo ed avermi aperto nuovi orizzonti ... e cioè : peppe leggiti le regole di programmazione sennò fai confusione !

in effetti un valido studio di tutto (nel caso specifico delle stringhe) è presupposto essenziale per poter arrivare ad una soluzione del mio problema. e per questo ringrazio VB che ha postato un link (appena intravisto per motivi di tempo) che stasera stessa sarò oggetto di attenta lettura, quando moglie e figli creeranno quel silenzio tipico da studio profondo.

la gestione delle stringhe qui è (al momento per me) difficile perché ho la mentalità della gestione stringhe del vb6 et similia, che sono linguaggi praticamente "policombustibile" ... qualunque cosa gli dai in pasto funziona, mentre qui in C se metti una variabile con la lettera maiuscola anziché minuscola arriva uno tsunami.... :o

di seguito mi riservo di postare gli esempi di pacchetti per poter capire dove si può migliorare evitando ripetizioni o rallentamenti inutili

salutissimi

peppe

bene... letto con attenzione il "facile" ma necessario documento sulle stringhe dato da vb, ho capito che se non approfondisco bene tutto finirò per gestire le situazioni scopiazzando qui e la creando solo una accozzaglia di codice, capendo con difficoltà quello che sto facendo (e soprattutto buttando sangue per ore per fare cose che magari necessitano di due minuti). ho la mentalità troppo facilona del vb6, nella quale string e char poco si differenziano e non importa se sono di 2000 caratteri... tanto funziona lo stesso. qui non è così . quindi, venendo al dunque, chiedo a vb o a chi per lui voglia aiutarmi la seguente cosa: quale è un testo, anche in formato cartaceo, dal quale posso imparare in modo lineare il C ? mi dirai : ce ne sono duemila e se cerchi su Google ne trovi a iosa. vorrei però il consiglio di un esperto, che già sa che in me c'è di certo una infarinatura appiccicata del linguaggio di arduino (con discenzenza plebee del visualbasic) , ma che in fondo necessito di due belli e sani schiaffoni di scolarizzazione ... per ora grazie ....

salutissimi

peppe

Quale miglior manuale di quello scritto da colui che il C lo ha inventato. Il linguaggio C di Brian Kernighan Manuale eccelente, anche se il C si è comunque leggermente evoluto sia con lo standard C99 e C11 che con lo sviluppo del piu libero C++. Inizia lo studio buttando via tutto quello che sai sul VB6, linguaggio oramai abbandonato perfino da Microsoft. Quando si parla di VB ora mai ci si riferisce alla versione .NET non più al 6.

il k&r non è proprio per novizi.... ma un programmatore c dovrebbe aver letto almeno tutti questi

RobertoBochet: Inizia lo studio buttando via tutto quello che sai sul VB6, linguaggio oramai abbandonato perfino da Microsoft. Quando si parla di VB ora mai ci si riferisce alla versione .NET non più al 6.

credimi ... col vb6 ancora oggi faccio in 10 minuti programmi da draghi fiammeggianti con pochissimi componenti aggiuntivi... forse perchè lo conosco benino. con micro accorgimenti gira benissimo a 64 bit .... non è il massimo per la grafica e gli oggetti ma ... per averne un po' occorre il c++, giusto ? con una istruzione faccio cose che col c c'è bisogno di 5 istruzioni da professore ben messe ... soprattutto con le stringhe. ecco il motivo della mia defaiance di questo post... non parliamo del. net .... installato e disinstallato dopo 10 minuti. 1 gb di cose assurde con un linguaggio praticamente nuovo, in definitiva differente dal vb6 e megacomplicato rispetto al suo predecessore. tanto è vero che su Google si trovano ancor oggi ed molto più in abbondanza post sul vb6 e non su .net ... in ogni caso si sa : il miglior programma è quello che si sa usare. forse imparando ben il C dirò "ma come ho fatto finora a viverci senza ?" lo spero ... ma a 55 anni imparare l'ennesimo linguaggio è un po' pesante .... però debbo ... sennò me lo posso sognare arduino che faccia qualcosa di più del blink del led sull'uscita digitale 13 ... :) grazie dei consigli ... corro a vedere i links

salutissimi

peppe

vbextreme: il k&r non è proprio per novizi....

Con un po' di volontà... diciamo che non insegna a programmare, insegna il C!

bellopapo: credimi ... col vb6 ancora oggi faccio in 10 minuti programmi da draghi fiammeggianti con pochissimi componenti aggiuntivi... forse perchè lo conosco benino.

Non è un discorso del tipo "è un brutto linguaggio" o altro, è un discorso del genere è un linguaggio abbandonato perfino da chi lo sviluppò, non ha piu alcun supporto, non credo sia piu assolutamente garantita la sua affidabilità. C'è rispetto per i linguaggi passati, ma esattamente come non useresti piu un Apple II per lo sviluppo software non si usano piu certi linguaggi. VB .NET e VB6 non possono essere messi a confronto, parliamo di linguaggi totalmente diversi, condividono tra loro solo parte della sintassi, fine. Sarebbe come confrontare C e C#.

Concludendo l'OT, il C è un linguaggio fondamentale nell'ambiente, che va (per fortuna) a """sostituire""" l'assembly. Il wiring è una semplificazione ulteriore del C++.