Newsgroup: it.comp.programmare.win32
Titolo: Domanda su porta seriale

Ciao,
sto scrivendo una applicazione che interroga una porta COM.Sto usando
Visual Studio 2005,scrivo in C# e sto impiegando il controllo SerialPort.
Praticamente uso vari comandi AT per interrogare il dispositivo,andando a
leggere il buffer di ricezione all'interno dell'event handler
"DataReceived",che semplicemente viene generato ogni qualvolta ho dei dati
pronti da leggere sul buffer di ricezione.
Il punto č che a seconda della lunghezza della risposta del
dispositivo,questo handler viene invocato un diverso numero di volte.Ci
sono comandi piů semplici la cui risposta č molto breve e tale da essere
giŕ analizzabile completamente in una sola occorrenza dell'evento
DataReceived.
Altri comandi invece producono risposte piů lunghe,che fanno triggerare piů
volte l'evento DataReceived (quindi la stringa che conterrŕ la risposta
sarŕ il risultato di un append delle varie sottostringhe ricevute).
La mia domanda č:per evitare di dover analizzare le stringhe ricevute,al
fine di capire se sono complete o meno,c'č un modo di capire se sto
ricevendo i dati e (soprattutto) se la ricezione si č conclusa?
Grazie anticipatamente :))

 conclusa?
Se stai utilizzando un protocollo AT, quasi tutte le risposte 
del dispositivo DCE cominciano e terminano con la coppia di byte 
<CR><LF>, per esempio <CR><LF>OK<CR><LF>. Quindi ti basta 
verificare quello per sapere se hai ricevuto una risposta 
completa (da analizzare). Altrimenti devi controllare in base al 
protocollo specifico.
HTH,
-- 
Stefano Frosio
www.esse-effe.com

 protocollo specifico.
Ciao e grazie mille!
Ti chiedo solo un'altra cosa...un consiglio su come procedere nell'analisi
delle risposte del modem,dato che non sono un programmatore esperto e
vorrei evitare un approccio che poi si riveli sbagliato:
io penserei di realizzare la gestione della risposta del modem tramite una
funzione che,una volta appurato che la risposta sia completa,affidi la
gestione di essa ad una istruzione switch,il cui argomento sarà l'ultimo
comando inviato.Quindi avrò tanti rami "case" quanti i comandi che prevedo
di impiegare (chiaramente a meno di comandi che prevedano risposte
identiche).
Onestamente mi sembra un pò rozzo....hai qualche suggerimento?

 Onestamente mi sembra un pò rozzo....hai qualche suggerimento?
Mah guarda, suggerimenti relativi al design non me la sento di 
darne poichè non conosco l'applicazione che stai realizzando, 
forse qualcun'altro oserà di più...
Per quanto riguarda la funzionalità specifica la soluzione che 
hai descritto è abbastanza classica, anche se non capisco perchè 
controllare in seguito a quale comando si riferisce la risposta. 
Immagino che per ogni comando tu attenderai la risposta, quindi, 
se arriva, lo sai già a quale comando si riferisce.
-- 
Stefano Frosio
www.esse-effe.com

 forse qualcun'altro oserà di più...
Sostanzialmente devo chiamare un modem remoto,interfacciandomi con quello
locale tramite i comandi AT.
Ancora grazie :)) Molto disponibile :)

gestione di essa ad una istruzione switch
E' il vecchio modo di procedere. In un approccio più object-oriented
(e maggiormente manutenibile, a mio parere) puoi ricorrere ad una
classe factory incaricata di costruire l'oggetto handler
corrispondente al tipo di risposta. In linea di massima, potresti
creare un thread a priorità alta incaricato solo di leggere dalla
seriale, il quale rimanda (mediante messaggi) i dati letti all'handler
specifico.

 specifico.
Beh,prima devo informarmi meglio sul factory pattern (non ne sospettavo
neanche l'esistenza.....sono un novellino :)  )
Ne approfitto per fare comunque una domanda.
La mia applicazione sostanzialmente archivierà dati in un database,con la
possibilità di fare grafici e quantaltro;la sorgente dei dati è un
dispositivo remoto,al quale mi connetto tramite il modem locale.
Dato che sto cercando di separare il codice in blocchi "logici",pensavo di
realizzare una classe ModemLocale che si occupa del colloquio col modem
locale:in sostanza un qualcosa che incapsula il componente SerialPort
(ossia l'oggetto che si occupa di parlare con la porta seriale).
L'applicazione principale,quando vorrà effettuare la chiamata,chiamerà il
metodo statico "ChiamaModemRemoto",che di fatto sarà l'unica interfaccia
che l'oggetto ModemLocale avrà.Ora,prima di far partire la chiamata,io devo
svolgere alcuni task preliminari,quindi la sequenza delle operazioni del
metodo ChiamaModemRemoto sarà:
1)Verifica che il modem è connesso
2)Verifica se il modem richiede la password di accesso o se è già stata
impostata
3)Imposta (o meno,se già impostata) la password per accedere al modem
4)Verifica che c'è segnale a sufficienza per chiamare
5)Chiama
Sono tutte operazioni che vorrei fare effettuare al metodo
ChiamaModemRemoto,per incapsulare il più possibile tutto quanto sta dietro
ad una chiamata in quell'unico metodo.
Dopo tutto 'sto preambolo,la mia domanda è:
io vorrei in sostanza scrivere la funzione ChiamaModemRemoto come
	string ChiamaModemRemoto()
	{
		VerificaConnModem();
		VerificaPassword();
		VerificaSegnale();
		Chiama();
	}
Gli step devono essere necessariamente sequenziali,e ognuno può essere
eseguito solo se i precedenti hanno avuto esito positivo.
Tuttavia VerificaConnModem ritorna immediatamente (dato che in sostanza
scrive una stringa sulla seriale e basta) e quindi il flusso di esecuzione
va subito a VerificaPassword.
Io però voglio esercitare il controllo qui,dicendo in sostanza al programma
che "VerificaPassword non può partire finchè la risposta non è stata
analizzata ed è stata ritenuta corretta".Ho quindi bisogno di stoppare il
thread dell'applicazione fino a quando non ricevo l'ok? 

thread dell'applicazione fino a quando non ricevo l'ok? 
E' facile che in applicazioni di questo tipo, i processi siano
asincroni, come nel tuo caso. Per trasformare un processo asincrono in
un processo sincrono o usi un thread secondario oppure usi un
approccio event-based con una macchina a stati finiti.
Mi spiego meglio. Supponi che il flusso della tua applicazione è:
Stato 0: verifico la connessione al modem;
         se la connessione è OK vai allo stato 1;
         se la connessione è KO vai allo stato 999;
Stato 1: verifico la password;
         se la password è OK vai allo stato 2;
         se la password è KO vai allo stato 998;
Stato 2: verifico il segnale;
         se il segnale è OK vai allo stato 3;
         se il segnale è KO vai allo stato 997;
Stato 3: chiama();
Stato 997: avvisa che il segnale è KO;
Stato 998: avvisa che la password è KO;
Stato 999: avvisa che la connessione al modem è KO;
Ogni operazione (verifica connessione modem, verifica password,
verifica segnale, etc..) avrà presumibilmente una callback, essendo un
processo asincrono. La classe ProcessController che gestisce il tutto,
aggancia la callback e in base allo stato dell'applicazione e al
successo della singola operazione, esegue il passaggio allo stato
corrispondente.

 corrispondente.
Ok ti sei spiegato perfettamente :)
La scelta tra i due approcci su quali elementi si potrebbe basare?Ci sono
controindicazioni nell'usare un metodo anzichè l'altro?
Inoltre sono un pò digiuno riguardo ai callback:ora studierò un pochino,ma
finora l'idea che mi sono fatto è che le funzioni callback sono funzioni
che vengono chiamate in automatico quando un processo è finito....del tipo
(con sintassi del tutto arbitraria :)  ):
callback AnalizzaRisultato;//funzione che verrà chiamata quando Processo01
			   //è conclusa
Processo01(AnalizzaRisultato);
E' così?
Grazie ancora :)

Eh eh,Olmo sono ovviamente io che ho risposto da un pc diverso :))

Inoltre sono un pň digiuno riguardo ai callback[...]
La callback č appunto una "call"-"back" nel senso che č normalmente
una funzione invocata alla fine o nel mezzo di un'operazione
asincrona. Per esempio, io potrei scrivere una funzione che scandaglia
un albero di directory e ogni volta che trova un file di un certo
tipo, invoca una callback che l'utente le ha passato come indirizzo,
in modo da processare quel file secondo le esigenze dell'utente. E'
solo un esempio, ovviamente. Nel tuo caso, il sistema che comunica col
modem sa che tipo di comunicazioen il modem sta compiendo e quindi al
ritorno delle informazioni sa quale callback, di quale specifica
operazione invocare.
Prendi i miei suggerimenti cum grano salis, ovviamente, perché non
conosco esattamente ciň che vuoi realizzare.

 meglio.
Ok,nel frattempo ho letto un articolo su BeginInvoke e EndInvoke,per
schiarirmi un pò le idee,ma confesso di essere forse ancora più confuso di
prima....passerà col tempo e con un pò di esperimenti :))
Al momento,affronterei il problema in questo modo (forse ciò che intendi tu
con "adottare logiche asincrone"?)
-------------------------------------------------
1)Lancio il comando di verifica connessione
... Aspetto che la risposta arrivi e sia completa....
2)Quando la risposta è completa faccio scattare l'evento
"RispostaCompleta",il cui handler analizza la risposta.Se è giusta lancio
il comando VerificaPassword,altrimenti interrompo l'operazione.
... Aspetto che la risposta al comando di verifica password sia completa...
3)Quando la risposta è completa faccio scattare l'evento
"RispostaCompleta".
Di nuovo,analizzo la risposta: se corretta lancio il comando
VerificaSegnale e così via....
---------------------------------------------------
Scusa l'ignoranza,ma è proprio la prima volta che mi trovo di fronte ad un
problema del genere....
Ti ringrazio ancora :)