Java obtiene soporte en serie con el nuevo paquete javax.comm

La API de Java Communications (también conocida como javax.comm) es una extensión estándar propuesta que permite a los autores de aplicaciones de comunicaciones escribir software Java que acceda a los puertos de comunicaciones de una manera independiente de la plataforma. Esta API se puede utilizar para escribir software de emulación de terminal, software de fax, software de lector de tarjetas inteligentes, etc.

Desarrollar un buen software generalmente significa tener algunas interfaces claramente definidas. En esta figura se muestra el diagrama de alto nivel de las capas de la interfaz API.

En este artículo, le mostraremos cómo utilizar javax.comm para comunicarse con un dispositivo serie basado en RS-232. También discutiremos lo que proporciona la API javax.comm y lo que no proporciona. Presentaremos un pequeño programa de ejemplo que le muestra cómo comunicarse con el puerto serie usando esta API. Al final del artículo, detallaremos brevemente cómo funcionará esta API javax.comm con otros controladores de dispositivo y repasaremos los requisitos para realizar un puerto nativo de esta API a un sistema operativo específico.

A diferencia de los controladores clásicos, que vienen con sus propios modelos de comunicación de eventos asincrónicos, la API javax.comm proporciona una interfaz de estilo de eventos basada en el modelo de eventos de Java (paquete java.awt.event). Digamos que queremos saber si hay datos nuevos en el búfer de entrada. Podemos averiguarlo de dos maneras: votando o escuchando . Con el sondeo, el procesador comprueba el búfer periódicamente para ver si hay datos nuevos en el búfer. Al escuchar, el procesador espera que ocurra un evento en forma de nuevos datos en el búfer de entrada. Tan pronto como llegan nuevos datos al búfer, envía una notificación o evento al procesador.

Entre las diversas interfaces seriales disponibles, dos de las más populares son los estándares RS-232C y RS-422, que definen los niveles de señal eléctrica y el significado de varias líneas de señal. Las interfaces seriales de baja velocidad normalmente registran los datos como una onda cuadrada, con la coordinación del reloj proporcionada por los bits de inicio y parada.

RS-232 son las siglas de Recommend Standard 232 ; la C simplemente se refiere a la última revisión de la norma. Los puertos seriales de la mayoría de las computadoras utilizan un subconjunto del estándar RS-232C. El estándar completo RS-232C especifica un conector "D" de 25 pines, de los cuales se utilizan 22 pines. La mayoría de estos pines no son necesarios para las comunicaciones normales de PC y, de hecho, la mayoría de los PC nuevos están equipados con conectores macho tipo D que tienen solo 9 pines. Para obtener más información sobre RS-232, consulte la sección Recursos.

Nota: Para comprender lo que han hecho otros controladores en el pasado, consulte la termiopágina del manual de Unix o OpenBSD Unix, una variación de la fuente del controlador BSD Unix. Esto está disponible gratis en Internet. Consulte la sección Recursos para obtener más información.

API javax.comm: lo que se proporciona

La API javax.comm proporciona la siguiente funcionalidad a los desarrolladores:

  • Una especificación API completa para puertos de comunicación en serie y paralelo. (En este artículo solo consideramos los puertos seriales). Sin una API común en sus esfuerzos de desarrollo, la carga de trabajo aumentará porque tendrá que brindar soporte a los dispositivos seriales.

  • Control total de todos los parámetros de trama en serie (bits de parada en baudios, paridad, bits / trama), así como el control manual o automático de las líneas de control de flujo. Normalmente, en RS-232, hay dos líneas de señal y el resto están destinadas a líneas de control. Dependiendo del tipo de comunicación (síncrona o asíncrona), el número de líneas de control seleccionadas puede variar. Esta API proporciona acceso a las señales de control subyacentes.

    Una breve desviación aquí puede ayudarlo a comprender algo sobre la paridad y los bits de inicio y parada. Se agregó paridad a RS-232 porque las líneas de comunicación pueden ser ruidosas. Digamos que enviamos ASCII 0 , que en hexadecimal es igual a 0x30 (o 00110000 en binario), pero en el camino alguien pasa sosteniendo un imán, lo que hace que uno de los bits cambie. Como resultado, en lugar de enviar 8 bits como se esperaba, se agrega un bit adicional a la primera cadena de bits enviados, haciendo que la suma total de bits enviados sea par o impar. voilà ! Tienes paridad.

    Se agregaron bits de inicio y parada al protocolo de comunicación en serie para permitir que los receptores se sincronicen con los caracteres que se envían. La paridad de un bit no permite la corrección de errores, solo la detección. Las soluciones a este problema provienen de protocolos que se superponen a las API seriales. En la actualidad, la mayoría de las comunicaciones en serie utilizan protocolos de bloque con sumas de comprobación (una función matemática que se puede generar en el receptor y comparar con la suma de comprobación transmitida) que permiten detectar errores en grupos de bits más grandes. Cuando se comunica con su ISP a través de PPP, los paquetes pueden tener 128 bytes por paquete con una suma de comprobación. Si coinciden, está 99,999% seguro de que los datos son correctos.

    Hay casos en los que este esquema no funciona. Por ejemplo, al enviar comandos críticos a dispositivos que están muy lejos en el sistema solar, se pueden utilizar protocolos de corrección directa . Se necesitan protocolos de corrección directa porque puede que no haya tiempo para una retransmisión y el espacio tiene mucho ruido electromagnético.

    ¡Bien, volvamos a la lista de funcionalidades proporcionadas por la API javax.comm!

  • La E / S básica a través de una subclase de flujos de E / S de Java. Para entrada y salida, la API javax.comm usa secuencias; el concepto de secuencias debería resultar familiar para todos los programadores de Java. Es importante reutilizar los conceptos de Java al crear nuevas funciones o las API se volverán difíciles de manejar.

  • Secuencias que se pueden ampliar para proporcionar control de flujo de cliente y controles de umbral. Por ejemplo, es posible que desee una alerta cuando hay 10 caracteres en el búfer o cuando solo quedan 10 ubicaciones para los caracteres. El control de flujo es importante cuando los dos dispositivos conectados a través de una interfaz no pueden mantenerse al día. Sin control de flujo, puede tener excesos o insuficiencias . En la condición de desbordamiento, recibió datos antes de que se procesaran, por lo que se perdieron; en el underrun, estaba listo para los datos, pero no estaban disponibles. Por lo general, estas condiciones ocurren en el USART (Transmisor de receptor asíncrono síncrono universal), que es un hardware que convierte bytes en una forma de onda en serie con una sincronización para coincidir con la velocidad en baudios.

    La API javax.comm utiliza el modelo de eventos de Java para proporcionar notificaciones de varios cambios en la línea de señal, así como el estado del búfer. Los cambios de estado se refieren a señales bien definidas especificadas en el estándar RS-232. Por ejemplo, un módem utiliza la detección de portadora para indicar que ha realizado una conexión con otro módem o que ha detectado un tono de portadora. Hacer la conexión o detectar un tono de portadora es un evento. La detección de eventos y la notificación de cambios se implementa en esta API.

Lo que no se proporciona

La API javax.comm no proporciona:

  • Procesamiento de tipo de disciplina de línea, administración de marcador o administración de módem. La disciplina de línea se refiere al procesamiento adicional de caracteres de entrada o salida. Por ejemplo, una opción común de procesamiento posterior es la conversión de CR a CR LF. Estos términos tienen su origen en los primeros días de los teletipos. CR (retorno de carro) significa devolver el carro al margen izquierdo; en el mundo árabe, este sería el margen derecho. LF (avance de línea) avanza el área de impresión hacia arriba en uno. Cuando aparecieron las pantallas de mapa de bits y las impresoras láser, estos términos se volvieron menos importantes.

    La gestión del marcador y la gestión del módem son aplicaciones adicionales que se pueden escribir utilizando la API javax.comm. La administración del marcador generalmente proporciona una interfaz a la interfaz de comando AT de la administración del módem. Casi todos los módems tienen una interfaz de comando AT. Esta interfaz está documentada en los manuales del módem.

    Quizás un pequeño ejemplo aclare este concepto. Supongamos que tenemos un módem en COM1 y queremos marcar un número de teléfono. Una aplicación de gestión de marcadores Java solicitará el número de teléfono e interrogará al módem. Estos comandos los lleva javax.comm, que no realiza ninguna interpretación. Para marcar el número 918003210288, por ejemplo, la administración del marcador probablemente envía un "AT", con la esperanza de obtener un "OK", seguido de ATDT918003210288. Una de las tareas más importantes de la gestión del marcador y la gestión del módem es tratar los errores y los tiempos de espera.

  • GUI para la gestión de puertos serie. Normalmente, los puertos seriales tienen un cuadro de diálogo que configura los puertos seriales, lo que permite a los usuarios configurar parámetros como velocidad en baudios, paridad, etc. El siguiente diagrama muestra los objetos involucrados en la lectura y / o escritura de datos en un puerto serie desde 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.