Java ottiene il supporto seriale con il nuovo pacchetto javax.comm

L'API Java Communications (aka javax.comm) è un'estensione standard proposta che consente agli autori di applicazioni di comunicazione di scrivere software Java che accede alle porte di comunicazione in modo indipendente dalla piattaforma. Questa API può essere utilizzata per scrivere software di emulazione terminale, software fax, software per lettori di smart card e così via.

Sviluppare un buon software di solito significa avere alcune interfacce chiaramente definite. In questa figura è mostrato il diagramma di alto livello dei livelli dell'interfaccia API.

In questo articolo ti mostreremo come utilizzare javax.comm per comunicare con un dispositivo seriale basato su RS-232. Discuteremo anche cosa fornisce l'API javax.comm e cosa non fornisce. Presenteremo un piccolo programma di esempio che mostra come comunicare con la porta seriale utilizzando questa API. Alla fine dell'articolo descriveremo brevemente come funzionerà questa API javax.comm con altri driver di dispositivo e esamineremo i requisiti per eseguire una porta nativa di questa API su un sistema operativo specifico.

A differenza dei driver classici, forniti con i propri modelli di comunicazione di eventi asincroni, l'API javax.comm fornisce un'interfaccia in stile evento basata sul modello di eventi Java (pacchetto java.awt.event). Supponiamo di voler sapere se sono presenti nuovi dati nel buffer di input. Possiamo scoprirlo in due modi: sondando o ascoltando . Con il polling, il processore controlla periodicamente il buffer per vedere se sono presenti nuovi dati nel buffer. Con l'ascolto, il processore attende che si verifichi un evento sotto forma di nuovi dati nel buffer di input. Non appena arrivano nuovi dati nel buffer, invia una notifica o un evento al processore.

Tra le varie interfacce seriali disponibili, due delle più diffuse sono gli standard RS-232C e RS-422, che definiscono i livelli di segnale elettrico e il significato delle varie linee di segnale. Le interfacce seriali a bassa velocità tipicamente eseguono il clock dei dati come un'onda quadra, con il coordinamento del clock fornito dai bit di avvio e di arresto.

RS-232 è l'acronimo di Recommend Standard 232 ; la C si riferisce semplicemente all'ultima revisione della norma. Le porte seriali sulla maggior parte dei computer utilizzano un sottoinsieme dello standard RS-232C. Lo standard RS-232C completo specifica un connettore "D" a 25 pin, di cui vengono utilizzati 22 pin. La maggior parte di questi pin non è necessaria per le normali comunicazioni con il PC e, in effetti, la maggior parte dei nuovi PC è dotata di connettori di tipo D maschio con solo 9 pin. Per ulteriori informazioni su RS-232, vedere la sezione Risorse.

Nota: per una comprensione di ciò che altri driver hanno fatto in passato, dai un'occhiata alla termiopagina di manuale di Unix o OpenBSD Unix, una variazione del sorgente del driver Unix BSD. Questo è disponibile gratuitamente su Internet. Si prega di consultare la sezione Risorse per ulteriori informazioni.

L'API javax.comm: cosa viene fornito

L'API javax.comm fornisce le seguenti funzionalità agli sviluppatori:

  • Una specifica API completa per porte di comunicazione seriale e parallela. (In questo articolo consideriamo solo le porte seriali.) Senza un'API comune nei tuoi sforzi di sviluppo, il carico di lavoro aumenterà perché dovrai fornire supporto ai dispositivi seriali.

  • Controllo completo di tutti i parametri di frame seriale (bit di stop baud, parità, bit / frame) nonché controllo manuale o automatico delle linee di controllo del flusso. Normalmente, in RS-232, ci sono due linee di segnale e il resto è destinato alle linee di controllo. A seconda del tipo di comunicazione (sincrona o asincrona), il numero di linee di controllo selezionate può variare. Questa API fornisce l'accesso ai segnali di controllo sottostanti.

    Un breve diversivo qui può aiutarti a capire qualcosa sulla parità e sui bit di inizio e fine. La parità è stata aggiunta a RS-232 perché le linee di comunicazione possono essere rumorose. Supponiamo di inviare ASCII 0 , che in esadecimale è uguale a 0x30 (o 00110000 in binario), ma lungo il percorso qualcuno passa tenendo in mano un magnete, facendo cambiare uno dei bit. Di conseguenza, invece di inviare 8 bit come previsto, viene aggiunto un bit aggiuntivo alla prima stringa di bit inviati, rendendo la somma totale dei bit inviati pari o dispari. voilà ! Hai la parità.

    I bit di inizio e fine sono stati aggiunti al protocollo di comunicazione seriale per consentire ai ricevitori di sincronizzarsi sui caratteri inviati. La parità a un bit non consente la correzione degli errori, ma solo il rilevamento. Le soluzioni a questo problema provengono dai protocolli che sono sovrapposti alle API seriali. La maggior parte della comunicazione seriale oggigiorno utilizza protocolli a blocchi con checksum (una funzione matematica che può essere generata sul ricevitore e confrontata con il checksum trasmesso) che consentono di rilevare errori su gruppi di bit più grandi. Quando si comunica con l'ISP tramite PPP, i pacchetti possono essere 128 byte per pacchetto con un checksum. Se corrispondono, sei sicuro al 99,999% che i dati siano corretti.

    Ci sono casi in cui questo schema non funziona. Ad esempio, quando si inviano comandi critici a dispositivi che sono molto lontani nel sistema solare, è possibile utilizzare protocolli di correzione diretta . I protocolli di correzione in avanti sono necessari perché potrebbe non esserci tempo per una ritrasmissione e lo spazio ha molto rumore elettromagnetico.

    Ok, torniamo all'elenco delle funzionalità fornite dall'API javax.comm!

  • L'I / O di base tramite una sottoclasse di flussi IO Java. Per l'input e l'output, l'API javax.comm utilizza i flussi; il concetto di stream dovrebbe essere familiare a tutti i programmatori Java. È importante riutilizzare i concetti Java quando si creano nuove funzionalità, altrimenti le API diventeranno ingombranti.

  • Flussi che possono essere estesi per fornire controllo del flusso client e controlli di soglia. Ad esempio, potresti volere un avviso quando ci sono 10 caratteri nel buffer o quando sono rimaste solo 10 posizioni per i caratteri. Il controllo del flusso è importante quando i due dispositivi collegati tramite un'interfaccia non riescono a stare al passo l'uno con l'altro. Senza controllo del flusso, puoi avere overrun o underrun . Nella condizione di sovraccarico, hai ricevuto i dati prima che venissero elaborati, quindi sono andati persi; nel sottocarico, eri pronto per i dati ma non erano disponibili. Di solito queste condizioni si verificano presso l'USART (Universal Synchronous Asynchronous Receiver Transmitter), che è l'hardware che converte i byte in una forma d'onda seriale con temporizzazione per abbinare la velocità di trasmissione.

    L'API javax.comm utilizza il modello di eventi Java per fornire la notifica di vari cambiamenti della linea di segnale e dello stato del buffer. I cambiamenti di stato si riferiscono a segnali ben definiti specificati nello standard RS-232. Ad esempio, il rilevamento della portante viene utilizzato da un modem per segnalare che ha effettuato una connessione con un altro modem o che ha rilevato un tono di portante. Effettuare la connessione o rilevare un tono di portante è un evento. Il rilevamento degli eventi e la notifica delle modifiche sono implementati in questa API.

Cosa non viene fornito

L'API javax.comm non fornisce:

  • Elaborazione del tipo di disciplina di linea, gestione del dialer o gestione del modem. La disciplina di linea si riferisce all'ulteriore elaborazione dei caratteri di input o output. Ad esempio, un'opzione di post-elaborazione comune è la conversione di CR in CR LF. Questi termini hanno le loro origini nei primi giorni dei teletipi. CR (ritorno a capo) significa semplicemente riportare il carrello al margine sinistro; nel mondo arabo, questo sarebbe il giusto margine. LF (avanzamento riga) fa avanzare l'area di stampa di uno. Quando sono arrivati ​​gli schermi bitmap e le stampanti laser, questi termini sono diventati meno importanti.

    La gestione del dialer e la gestione del modem sono applicazioni aggiuntive che possono essere scritte utilizzando l'API javax.comm. La gestione del dialer fornisce in genere un'interfaccia all'interfaccia di comando AT della gestione del modem. Quasi tutti i modem hanno un'interfaccia di comando AT. Questa interfaccia è documentata nei manuali del modem.

    Forse un piccolo esempio chiarirà questo concetto. Supponiamo di avere un modem su COM1 e di voler comporre un numero di telefono. Un'applicazione di gestione del dialer Java richiederà il numero di telefono e interrogherà il modem. Questi comandi sono forniti da javax.comm, che non fornisce alcuna interpretazione. Per comporre il numero 918003210288, ad esempio, la gestione del dialer invia probabilmente un "AT", sperando di ricevere un "OK" seguito da ATDT918003210288. Uno dei compiti più importanti della gestione del dialer e del modem è la gestione degli errori e dei timeout.

  • GUI per la gestione della porta seriale. Normalmente, le porte seriali hanno una finestra di dialogo che configura le porte seriali, consentendo agli utenti di impostare parametri come velocità di trasmissione, parità e così via. Il diagramma seguente illustra gli oggetti coinvolti nella lettura e / o scrittura di dati su una porta seriale da Java.

  • Support for X, Y, and Z modem protocols. These protocols provide support error detection and correction.

The programming basics

Too often, programmers dive right into a project and code interactively with an API on the screen without giving any thought to the problem they are trying to solve. To avoid confusion and potential problems, gather the following information before you start a project. Remember, programming devices usually requires that you consult a manual.

  1. Get the manual for the device and read the section on the RS-232 interface and RS-232 protocol. Most devices have a protocol that must be followed. This protocol will be carried by the javax.comm API and delivered to the device. The device will decode the protocol, and you will have to pay close attention to sending data back and forth. Not getting the initial set-up correct can mean your application won't start, so take the time to test things out with a simple application. In other words, create an application that can simply write data onto the serial port and then read data from the serial port using the javax.comm API.

  2. Try to get some code samples from the manufacturer. Even if they are in another language, these examples can be quite useful.

  3. Find and code the smallest example you can to verify that you can communicate with the device. In the case of serial devices, this can be very painful -- you send data to a device connected to the serial port and nothing happens. This is often the result of incorrect conditioning of the line. The number one rule of device programming (unless you are writing a device driver) is to make sure you can communicate with the device. Do this by finding the simplest thing you can do with your device and getting that to work.

  4. If the protocol is very complicated, consider getting some RS-232 line analyzer software. This software allows you to look at the data moving between the two devices on the RS-232 connection without interfering with the transmission.

Using the javax.comm API successfully in an application requires you to provide some type of interface to the device protocol using the serial API as the transport mechanism. In other words, with the exception of the simplest devices, there is usually another layer required to format the data for the device. Of course the simplest protocol is "vanilla" -- meaning there is no protocol. You send and receive data with no interpretation.

Overview of suggested steps for using javax.comm

In addition to providing a protocol, the ISO layering model used for TCP/IP also applies here in that we have an electrical layer, followed by a very simple byte transport layer. On top of this byte transport layer you could put your transport layer. For example, your PPP stack could use the javax.comm API to transfer bytes back and forth to the modem. The role of the javax.comm layer is quite small when looked at in this context:

  1. Give the javax.comm API control of some of the devices. Before you use a device, the javax.comm API has to know about it.

  2. Open the device and condition the line. You may have a device that requires a baud rate of 115 kilobits with no parity.

  3. Write some data and/or read data following whatever protocol the device you are communicating with requires. For example, if you connect to a printer, you may have to send a special code to start the printer and/or end the job. Some PostScript printers require you to end the job by sending CTRL-D 0x03.

  4. Close the port.

Initializing the javax.comm API registry with serial interface ports

The javax.comm API can only manage ports that it is aware of. The latest version of the API does not require any ports to be initialized. On start-up, the javax.comm API scans for ports on the particular host and adds them automatically.

You can initialize the serial ports your javax.comm API can use. For devices that do not follow the standard naming convention, you can add them explicitly using the code segment below.

// Register the device CommPort ttya = new javax.comm.solaris.SolarisSerial("ttya","/dev/ttya"); CommPortIdentifier.addPort(ttya,CommPortIdentifier.PORT_SERIAL); CommPort ttyb = new javax.comm.solaris.SolarisSerial("ttyb","/dev/ttyb"); CommPortIdentifier.addPort(ttyb,CommPortIdentifier.PORT_SERIAL); 

Opening and conditioning devices

This next code sample demonstrates how to add, condition, and open a device. Details on the specific method calls are in the API pages for javax.comm. This example sets the device called XYZSerialDevice to be accessible with name GenericSerialReader. The device connected on this line has a baud rate of 9600, 1 stop bit, a character of 8 bits (yes, they can be smaller), and no parity. The result of all of this is to provide two streams -- one for reading and another for writing.