Libreria SerialCmd ... commenti ed osservazioni

Sarebbe interessante aggiungere anche la possibilità di passare, in alternativa alla funzione di callback, anche il puntatore alla variabile in questione sfruttando il polimorfismo della classi.

... premesso che per me il C++ è quasi Arabo, lavorando al 99.9% in puro 'C' (e questa, in origine, era un semplicissimo .h scritto in ANSI C :grin:), comunque NON ho capito di che puntatore parli e a cosa servirebbe. Se mi spieghi esattamente ci faccio un pensierino ... :wink:

Guglielmo

Cerco di spiegarmi meglio.
Con questa libreria i passaggi sono essenzialmente 2:

  • definire una funzione di callback void nome_funzione (void)
  • associare la funzione su definita alla stringa che arriva sulla seriale
mySerCmd.AddCmd ( "DUMMY_FN" , SERIALCMD_FROMALL, nome_funzione );

Ho notato che molti "beginner" hanno qualche difficoltà con il concetto di funzione di callback.
Si potrebbe quindi fare la stessa cosa con una variabile, per poi valutarne il valore in qualsiasi altro punto dello sketch.

bool mia_var;
void setup()
  mySerCmd.AddCmd ( "DUMMY_VAR" , SERIALCMD_FROMALL, mia_var);
  ...
}

void loop() {
  mySerCmd.ReadSer();
  if (mia_var) {
    Serial.println("mia_var è true");
  }
.....

Per quanto riguarda il come si può fare l'override di

void SerialCmd::AddCmd ( const char *command, char allowedSource, void ( *function ) () ) per ciascun tipo di dati che si vogliono supportare, oppure sfruttare i template e qui è quasi arabo anche per me.
Ho fatto qualcosa con i template del C++, ma ammetto che faccio ancora un bel po' di fatica.

Magari provo a vedere cosa salta fuori ed eventualmente ti faccio un commit.

... si, ma in questo modo, se ho ben capito, si perde la possibilità di associare più di un comando a più di una funzione ... :roll_eyes:

Guglielmo

Guglielmo sei un genio.......
tu hai praticamente rifatto il mio "grep non vuol dire greppia" (beh, si lo so che non sei partito da zero)
però delegando la gestione di tutto il "cinema" (parole, riconoscimento, azioni) ad una libreria e un oggetto che si comporta come un "pacchetto finito" che non serve fare pressocchè nulla nella loop() a parte richiamare una sola volta una funzione

oltretutto delegando anche la lettura, inoltre passando un puntatore a Stream (sì, vero, usi un passaggio per riferimento, ma tradotto in C è puntatore a Stream)

sono roso dall'invidia...
se non fossi di buon cuore passerei il confine e ti verrei a cercare... per farti (la) festa :champagne:

Oh, nel senso buono, intendo

... la festa la possiamo fare quando vuoi :champagne: :champagne: :champagne: :clinking_glasses: :clinking_glasses: :clinking_glasses:

:grin: :grin: :grin:

Guglielmo

P.S.: è un lavoro vecchissimo, avevo preso spunto da quelle librerie del 2011 e 2012 e me l'ero rifatto in puro 'C' tutto in un .h ... ora l'ho ripreso in mano e fatta la piccola libreriola :wink:

No perché?
L'unico vero ostacolo è assegnare alla variabile "variant" il valore passato via seriale perché su Arduino mancano alcune funzionalità del C++ per identificare il tipo variabile.

... allora NON ho capito ... io li vedo solo un bool e un IF che verifica se è true o false ... come si fa a passare una serie di parametri e richiamare funzioni diverse ? ? ?

Guglielmo

Piu tardi se riesco provo ad abbozzare un proof of concept sul simulatore online

Ciao Guglielmo, ho 2 domande e 2 proposte:

  1. come mai nella ReadString() e Print() quando le usi metti (char*) ? Solo x ridondanza ? Oppure senza hai dei warning ?
  2. Non ho capito la ReadString () cosa fa. per me non è molto chiaro.
    Leggo: " It is used to send a command from the application as if it had been received from the serial line. The content of the string must be the same as it would have been sent through the serial port (including parameters )."
    Ma la lettura del comando ed eventuale exec della funzione callback non lo fa la readSer() ?

A. non servirà magari a nulla, ma hai messo privata SerialCmd_CmdCount, potrebbe essere utile una funzione che ne ritorna il valore
B. potrebbe essere utile una metodo con cui fai tu la begin della seriale (passando la velocità).
così potrei evitare la serial.begin e sfruttare la tua lib. (ma non obbligatorio usare la tua begin, solo x comodità)

  • 1 perché se passi una stringa tra apici NON stai passando un 'char *' ma un 'const char *' ed io, che ho i warning attivati a livello più alto che il default, me ne accorgo perché me lo segnala :wink:

  • 2 lo vedi bene nell'esempio, praticamente di permette di richiamare un comando che passeresti da seriale, da programma.

  • A è un mio contatore interno e NON voglio che sia toccabile. Non vedo l'utilità per l'utente ... lo sa da solo quanti comandi ha attivato.

  • B in origine era così, ma ho preferito la parte inizializzazione dello 'Stream' fatto dall'utente nell'applicatiovo come più gli piace.

Grazie :slight_smile:

Guglielmo

Così diventa complicato gestire core diversi, come la dichiari la variabile della seriale?
Stream è il giusto livello di astrazione che serve per comunicare, e funziona con tutte le seriali possibili, incluso la SoftwareSerial.

Ciao, Ale.

Io ho solo il simulatore wokwi e quindi non posso provare, chi ha arduini e coolterm o altro se riesce ad inviare un indirizzo (16-bit) il ricevente lo casta a puntatore e con questo si può accedere in lettura/scrittura a qualunque cella di ram dove vivono le variabili, quindi invece di associare una callback utente ad un comando si fa una associazione in base al tipo di dato (int int32 ecc) e con l'indirizzo si può fare tutto. Già provata una soluzione in passato ed è efficiente in quanto il parser si riduce notevolmente. Non scendo nei dettagli perché non posso produrre codice non avendo arduini.

Ciao.

... NO, aspetta, l'idea era nata perché ...

... ovvero per dei "beginner" che neanche capiscono il concetto di passare come parametro il nome di una funzione ... figuriamoci quello che proponi tu ... :joy:

Guglielmo

Guglielmo ti confermo i miei complimenti

L'unica cosa per la quale preferisco ancora il mio "grep non vuol dire greppia" è che tu fai riconoscere intere stringhe e io invece passo il singolo carattere mano a mano che viene ricevuto, riducendo al minimo il consumo di memoria per un buffer

Invece ho una domanda:
Visto che gli passi un puntatore a stream, hai provato invece di usare una seriale a passargli un file testuale contenente comandi e preventivamente aperto?

Risolverebbe un fracco di domande di un fracco di niubbi...

Si ovvio ma il C++ fa miracoli e fa apparire semplice ciò che è incomprensibile e questo non è l'ostacolo. Semmai cambia proprio paradigma, con la tua libreria arduino B deve conoscere il comando "LED5ON" che anche Arduino A conosce. Con i puntatori (sempre se il protocollo lo permette) i due arduini si scambiano un pool di indirizzi e arduinoA ha la variabile isTrue in ram ma ArduinoB ha l'indirizzo di isTrue, stessa cosa invertendo gli arduini. Detto in altri termini si tratta di condividere delle variabili. Comunque è un idea buttata li già sperimentata e purtroppo non ho codice.

Ciao.

emmm ... veramente NON è nata per questo scopo, ma per un Arduino ed un utente che invia, a manina, comandi via seriale :grin:

Guglielmo

... mmm ... no, NON ho provato, ma in teoria ... dovrebbe andare ... :roll_eyes:

Se si guarda il refernce, per "Stream" riporta:

Some of the libraries that rely on Stream include :

... e l'ultima è proprio SD. :slight_smile:

Guglielmo

A. Only una get, solo in lettura