Ricezione Dati da Seriale in PHP

Stato
Chiusa ad ulteriori risposte.

IK5NTH-Mauro

Nuovo Utente
11 Ott 2010
5
1
0
Salve a tutti,
Ho creato una funzione in PHP che legge i dati da porta seriale.
La funzione interagisce, sempre tramite seriale, con una scheda; invia un comando e si aspetta una risposta. Tutto funziona ok salvo il fatto che se la scheda non risponde la pagina web rimane in attesa fino all'esaurimento del time-out mostrando il fatidico messaggio "pagina inestitente.
Vorrei integrare un time-out nella mia funzione ma non riesco a farlo.Vi posto il codice della funzione così come è adesso.

function AttesaRisposta()
{


$filename = "/dev/ttyS2";
$fd = fopen($filename, "r" );

do{

$Char=fgetc($fd);
$Lettura = $Lettura . $Char;

}while($Char != "\n");

fclose($fd);

return $Lettura;

}
Per chiarezza: se non ricevo niente entro 2 secondi assegno a $Lettura = Errore ed esco
Grazie.
Mauro
 
Se il problema è che raggiungi il timeout nell'apertura del file, credo che l'unica sia inserire un
Codice:
set_time_limit (2);
che non ti da la possibilità di gestire l'errore, ma di ridurre il tempo di esecuzione dello script a 2 secondi.

Sinceramente è l'unica cosa che mi viene in mente.
 
Se il problema è che raggiungi il timeout nell'apertura del file, credo che l'unica sia inserire un
Codice:
set_time_limit (2);
che non ti da la possibilità di gestire l'errore, ma di ridurre il tempo di esecuzione dello script a 2 secondi.

Sinceramente è l'unica cosa che mi viene in mente.

Grazie del suggerimento, l'ho messo in pratica, ma la gestione dell'errore derivato sarebbe abbastanza importante. Sono abbastanza digiuno di PHP ed ho iniziato da poco, ma mi sembra strano che non ci sia una strada "semplice" per ottenere quanto richiesto da un linguaggio così potente. Sono evidenti tutte le mie lacune materia...
Grazie ancora.
Mauro
 
Si anche io ho ripreso col PHP da un paio di mesi, non sono ancora oliatissimo, comunque, mi sono venute in mente due cose:

1) cambiare il ciclo di while, anzi eliminarlo proprio e sostituire fgetc con file_get_contents($fp), poi eventualmente modificare la stringa con un explode() ed estrarre con un array_splice() i contenuti della stringa che effettivamente ti interessa vedere? In questo modo puoi mettere un errore nel caso in cui il risultato della funzione sia vuoto.

2) Inserire una sorta di timer nella funzione che hai ora, con due variabili:
Codice:
$timeout = $time() + 2;
$time = $time;
dove $time si aggiorna alla fine del ciclo di while ed un if ($time <= $timeout) all'interno del while come condizione all'esecuzione dello stesso.

Il problema dello script che hai è che il ciclo di while non ha un uscita nel caso in cui il file aperto sia vuoto, dunque il timeout error. Comunque, per aver maggiori informazioni sugli errori degli script, bisognerebbe avere x-debug attivo nel server php, altrimenti diventa dura :)

Ciao e buona giornata!
 
Grazie di nuovo per il suggerimento, stamani (tempo permettendo) cerco di metterlo in pratica. E' vero, il codice che ho non consente l'uscita dal ciclo se il file è vuoto (=se non arrivano caratteri). Le funzioni che mi stai suggerendo non le ho mai usate, quindi occorre che mi documenti leggendo il manuale, ben inteso che già lo sto facendo, ma azzeccare subito quelle giuste è dura se non altro per il fatto che ne esistono veramente un'infinità. Per inciso devo dire che la funzione che sto tentando di far funzionare l'ho già implementata anni fa in C (io provengo da lì...) usando dei micro della Atmel (ATMega128) e in questo caso non mai ha dato problemi di sorta. IL problema risiede propio nel fatto che la funzione resta in attesa di dati all'interno del while....
Grazie infinite per l'aiuto, ti terrò informato sull'esito.
Mauro
 
Guarda stamattina sono impegnato e oggi pomeriggio non so quando mi libero, ma se riesco faccio una prova in locale con un file vuoto per implementare il codice e passartelo per provare a vedere se riusciamo ad uscirne fuori :)

Un saluto e buona giornata!
 
Se il problema è la visualizzazione dell'errore puoi disabilitare completamente l'error reporting:
PHP:
error_reporting(0);
Oppure catturare l'errore:
PHP:
ob_start();

// tutto il ciclo che può generare errore

$contents = ob_get_contents();
ob_end_clean();

if($contents == 'testo di errore')
  echo 'Errore. Riprova in un altro momento.';
Ovviamente questo va gestito insieme al timeout.
 
Dopo averle provate tutte, questa funzione dovrebbe ... funzionare.

Codice:
function AttesaRisposta() {
	$filename = "/dev/ttyS2";
	$fd = fopen($filename, "r" );
	//definisce variabili
	$Lettura=NULL;
	$Char=NULL;
	$check_time = time();
	$timeout=time()+2; //tempo di esecuzione while loop 2 secondi
	
while($Char != "\n") {//inizio while loop exit: nuova linea
	if ($check_time <= $timeout) {//controlla durata loop
			$Char=fgetc($fd);
			$Lettura = $Lettura . $Char;
			$check_time = time();//aggiorna durata del loop
	} else {
		break;//se superiore a $timeout esci dal loop		
	}	
}
	fclose($fd);
	If ($Lettura) {//se $Lettura è presente
		return $Lettura;
	} else {
		$Lettura = 'errore di timeout'; //puoi cambiare il valore di lettura (es: $Lettura = false;) per poi usarlo in un condizionale e filtrare il risultato
		return $Lettura;
	}
}

per chiamare la funzione

Codice:
$lettura = AttesaRisposta();
echo $lettura;

Dovrebbe, e sottolineo dovrebbe, funzionare, magari personalizza l'uscita dell'errore a tuo piacere per completarla come preferisci.

Fammi sapere :)

P.S.
Chiedo scusa per il triplo edit carpiato, la fretta è una pessima consigliera :)

P.P.S
Commentato e cambiato il nome ad alcune variabili per chiarezza
 
Ultima modifica:
Eccomi, dopo una giornata di lavoro intensa,
Vi ringrazio per gli aiuti, comunque, nonostante gli svariati tentativi lo script contina a bloccarsi nel caso la seriale non risponda (per es. cavo scollegato).
Ieri notte mi ci sono incaponito, ma non sono riuscito a risolvere, Ho provato il codice che ho trovato nella risposta, effettivamente con il nome del file al posto di /dev/ttyS2 sembra che vada, probabilmente il vero problema è la maniera di gestione a basso livello della funzione PHP di lettura della porta. A questo punto credo che tenterò la strada del "C", nel senso che compilerò un pezzo di codice per poi richiamarlo con il comando exec.
Questo metodo già lo utilizzo per gestire alcuni I/O della scheda interfaccia (quella che risponde in seriale per intenderci), naturalmente ciò mi comporterà il problema di reimportare il risultato di queste chiamate dentro il PHP, ma esiste sempre la possibilità di scrivere e leggere file...
Vi terrò informati.
Grazie per iltempo che mi avete dedicato, se a qualcuno interesserà potrò mettere a disposizione il codice "C" dopo averlo testato.
Mauro
 
Quello è un discorso che infatti non fa testo, lo script l'ho infatti testato su un file bianco e poi popolato, non ho tenuto in conto del resto perchè non ho proprio i mezzi per testare il tutto.

Se quello che devi leggere è un file, puoi eventualmente aggiungere un condizionale per vedere se il file è presente o meno, in tal caso dovresti riuscire a controllare anche quell'evenienza.

PHP:
if (file_exists($filename)){
                 //do this
            } else {
                 //dothat
            }

In ogni caso buona fortuna!
 
Alla fine l'ho smazzata a modo mio!
Ho creato uno script in C che gestisce la ricezione seriale dove, ovviamente, il time-out funziona.
Questo script, una volta compilato, viene chiamato dal codice php tramite la funzione exec. A questo punto il compilato C ascolta la seriale e - in caso di traffico dati su quest'ultima - popola, con questi, una stringa che viene salvata su un file.
Se non ci sono caratteri da ricevere dopo 5 secondi scatta il time-out e la stringa viene popolata con un opportuno messaggio di errore. Ho anche inserito un carattere di controllo (<cr>) usato come terminatore di stringa in caso di ricezione.
Al termine di questo giochetto il controllo ritorna al php che lagge il file creato dalla funzione, usando la stringa per visualizzarla sulla pagina HTML.
Non credo che questo sia il miglior modo di gestire la cosa, ma non sono riuscito a fare di meglio. Mi sarebbe certamente piaciuto molto di più realizzare tutto in PHP.
Un altro (piccolo) problema è rappresentato dal recupero del dato creato dal compilato C. Sono dovuto passare attraverso la creazione e lettura di un file che non rappresenta certo il max. Vorrei percorrere altre strade, ma non so quali, infatti le funzioni exec o passthru gestiscono anche dati di "ritorno", ma nel caso del C non so come sia possibile restituire a queste una stringa...
Se avete suggerimenti sono veramente ben accetti, se a qualcuno interessa il compilato C o il sorgente non ha che da farsi avanti.
Mauro
 
  • Like
Reactions: filibertomariani
@filibertomariani
Non ti accodare a discussioni di altri con quesiti tuoi!
Apri una discussione tutta tua nella sezione idonea!
Ti prego inoltre di leggere attentamente il regolamento del forum
Grazie
 
@filibertomariani
Non ti accodare a discussioni di altri con quesiti tuoi!
Apri una discussione tutta tua nella sezione idonea!
Ti prego inoltre di leggere attentamente il regolamento del forum
Grazie
Chiedo scusa, non ho letto attentamente il regolamento del forum, ma temo neanche tu abbia letto il mio post, altrimenti ti saresti accorto che non mi asono accodato con "quesiti miei" ma avevo esattamente lo stesso problema discusso nel topic, inoltre non ponevo proprio quesiti, né "miei" nédi altri, semplicemente facevo seguito all'invito dell'utente di "farsi avanti" se si aveva bisogno del compliato C o del sorgente.
Comunque, il capo sei tu, fai come credi. :)
 
Stato
Chiusa ad ulteriori risposte.

Discussioni simili