El API de comunicaciones es una extensión standard que nos permite realizar comunicaciones con los puertos serie RS-232 y el paralelo IEEE-1284, esto nos permitirá realizar aplicaciones de comunicaciones que utilizan los puertos de comunicaciones (tarjetas inteligentes, fax) independientes de la plataforma.
El API de comunicaciones no se encuentra incluido en el JDK y es una extensión de este, así que antes de empezar a trabajar deberemos instalar este nuevo API en las maquinas que vayamos a realizar el desarrollo y que vayan a ejecutar programas realizados con este API.
Lo primero que haremos es obtener el API de comunicaciones, este se puede bajar fácilmente de Internet ya que no ocupa más de 300 Kb.
Una vez que desempaquetemos el fichero procederemos a realizar los siguientes pasos:
Copiamos el fichero Win32com.dll a
La nomenclatura
En el paquete de comunicaciones javax.comm tenemos una serié de clases que nos permiten tratar varios niveles de programación, estos niveles son los siguientes:
Los servicios que nos proporciona este paquete son:
Disponemos de métodos para el control de los puertos de entrada/salida a bajo nivel, de esta forma no solo nos limitamos a enviar y recibir datos sino que podemos saber en que estado esta el puerto. Así en un puerto serie podremos no solo cambiar los estados sino que podemos programar un evento que nos notifique el cambio de cualquier estado.
Para esta programación contamos con la clase CommPortIdentifier. Nos encontramos ante la clase principal del paquete ya que lo primero que debemos hacer antes de empezar a utilizar un puerto es descubrir si esta libre para su utilización. El primer programa que nos servirá como ejemplo lo encontramos en el Listado 1, este programa nos enseña la disponibilidad de los puertos. En la Figura A podemos ver el resultado del mismo, el puerto COM2 se encuentra ocupado por el programa "Una aplicación ocupa".
/*********************************************************************
* P1.java
*
* Descripción: Este programa nos permite analizar la disponibilidad de
* todos los puertos soportados en nuestra maquina. Tambien
* nos informara del tipo del puerto así como el propietario
* de este en caso de que se encuentre ocupado.
*
* Autor: Fco. Javier Rodriguez Navarro (c) Junio 2000
**********************************************************************/
import java.io.*;
import java.util.*;
import javax.comm.*;
public class P1
{
static Enumeration listaPort;
static CommPortIdentifier idPort;
public static void main(String[] args)
{
listaPort = CommPortIdentifier.getPortIdentifiers();
ListaPuertos();
}
private static void ListaPuertos()
{
System.out.println("Los puertos disponibles son:");
while (listaPort.hasMoreElements())
{
idPort = (CommPortIdentifier) listaPort.nextElement();
System.out.print("PUERTO: " + idPort.getName() + " ");
if (idPort.getPortType() == CommPortIdentifier.PORT_SERIAL)
{
System.out.println("RS-232 (" + idPort.getPortType() + ")");
} else if (idPort.getPortType() == CommPortIdentifier.PORT_PARALLEL)
{
System.out.println("IEEE 1284 (" + idPort.getPortType() + ")");
} else System.out.println("Tipo de puerto desconocido");
// Describimos si esta disponible.
if (idPort.isCurrentlyOwned())
System.out.println("OCUPADO por: " +
idPort.getCurrentOwner());
else
System.out.println("DISPONIBLE");
System.out.println("---------------------------------------------");
}
}
}
Lo primero que debemos hacer antes de intentar intentar abrir un puerto será ver si ya tiene o no un propietario y para obtener la información de esto debemos obtener el objeto de CommPortIdentifier correspondiente al puerto que se realizara con alguno de los siguientes métodos:
Un ejemplo de esto esta en el Listado 2, en la Figura B podemos ver un prototipo de clase que realiza la escucha de cambio de propietarios en el puerto, como se puede ver son tres valores tipos: abrir un puerto, cerrar un puerto e intentar abrir un puerto en uso. Si una vez que tenemos registrado un oyente de eventos lo queremos eliminar deberemos de utilizar removePortOwnershipListener(CommPortOwnershipListerner).
/*********************************************************************
* Escritor.java
*
* Descripción: Este programa escribe una frase por el puerto
* que le pasemos como parametro.
*
* Autor: Fco. Javier Rodriguez Navarro (c) Junio 2000
**********************************************************************/
import java.io.*;
import java.util.*;
import javax.comm.*;
public class Escritor
{
static CommPortIdentifier idPort;
static SerialPort sPort;
static ParallelPort pPort;
static OutputStream salida;
static String datos = new String("HOLA! esto es una prueba");
static evProp ev = new evProp();
public static void main(String[] args)
{
// Lo primero que hacemos es abrir el puerto
try
{
idPort = CommPortIdentifier.getPortIdentifier(args[0]);
idPort.addPortOwnershipListener(ev);
} catch (NoSuchPortException e)
{System.err.println("ERROR al identificar puerto");}
// Abre el puerto necesario.
try
{
if (idPort.getPortType() == CommPortIdentifier.PORT_SERIAL)
{
sPort = (SerialPort) idPort.open("Escritor en serie", 30000);
try
{
salida = sPort.getOutputStream();
} catch (IOException e) {}
}
else
{
pPort = (ParallelPort) idPort.open("Escritor en paralelo", 30000);
try
{
salida = pPort.getOutputStream();
} catch (IOException e) { }
}
} catch (PortInUseException e)
{ System.err.println("ERROR al abrir puerto");}
try
{
salida.write(datos.getBytes());
} catch (IOException e) { System.err.println("Error escritura"); }
}
}
class evProp implements CommPortOwnershipListener
{
public void ownershipChange(int tipo)
{
System.out.print("Valor: " + tipo);
if (tipo == CommPortOwnershipListener.PORT_OWNED)
System.out.println(" Se abre el puerto");
else if (tipo == CommPortOwnershipListener.PORT_UNOWNED)
System.out.println(" Se cierra el puerto");
else if (tipo == CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED)
System.out.println(" Requerido puerto usado");
}
}
Esta es una clase abstracta que describe los métodos comunes de comunicación y serán las clases que hereden de ellas (SerialPort y ParallelPort) la que añadan métodos y variables propias del tipo del puerto. Entre los métodos que nos interesa conocer tenemos:
Una vez que hemos visto los principales métodos de la clase abstracta de la que heredan (ParallelPort y SerialPort) pasamos a ver con detenimiento las características de estas.
En esta clase encontramos el interfaces de bajo nivel del puerto paralelo que cumple el standard RS-232. En la Tabla A podemos ver la descripción de las patillas del conector de 25 contactos, ver la Figura C conector tipo A, y su equivalente con el de 9 contactos. En la emisión de un carácter se realizarán las siguientes comprobaciones:
En la figura D podemos ver distintas conexiones que nos podemos encontrar en los enlaces punto a punto.
PIN (DB25) PIN (DB9) Descripción
2 2 TD: Canal de transmisión.
3 3 RD: Canal de recepción.
4 7 RTS: Petición para transmitir.
5 8 CTS: Preparado para emitir.
6 6 DSR: Equipo preparado.
7 5 Masa
8 1 DCD: Conexión establecida.
20 4 DTR: Terminal preparado.
22 9 RI: Indicador de llamada.
La clase SerialPort hereda de la clase abstracta CommPort y por lo tanto cuenta con sus métodos pero ademas de estos dispones de otros métodos y variables especificas para el tratamiento de los puertos serie. En el Listado 3 podemos ver el uso de los métodos y eventos que se exponen a continuación
La clase oyente deberá de tener el método serialEvent(SerialPortEvent) que recibirá un objeto que trata los eventos del puerto serie con tres métodos importante:
/*************************************************************
* Serie.java
*
* Descripción: Ejemplo de información de puerto con
* tratamiento de eventos.
*
* Autor: Fco. Javier Rodriguez Navarro (c) Julio 2000
*************************************************************/
import java.io.*;
import java.util.*;
import javax.comm.*;
public class Serie
{
static CommPortIdentifier idPort;
static SerialPort sPort;
static OutputStream salida;
static String datos = new String("Una linea que deseamos escribir ");
static evSerie ev = new evSerie();
public static void main(String[] args)
{
try
{
idPort = CommPortIdentifier.getPortIdentifier("COM2");
} catch (NoSuchPortException e)
{System.err.println("ERROR al identificar puerto");}
try
{
sPort = (SerialPort) idPort.open("Observador1(COM2)", 30000);
informa();
try
{
salida = sPort.getOutputStream();
} catch (IOException e) { }
try
{
sPort.addEventListener(ev);
sPort.notifyOnDataAvailable(true);
sPort.notifyOnOutputEmpty(true);
sPort.notifyOnCTS(true);
sPort.notifyOnDSR(true);
sPort.notifyOnRingIndicator(true);
sPort.notifyOnCarrierDetect(true);
sPort.notifyOnParityError(true);
sPort.notifyOnOverrunError(true);
sPort.notifyOnBreakInterrupt(true);
} catch (TooManyListenersException e) { }
} catch (PortInUseException e)
{ System.err.println("ERROR al abrir puerto");}
try
{
while (true) {salida.write(datos.getBytes());}
} catch (IOException e) { System.err.println("Error escritura"); }
}
// Metodo informa: Nos dara información del estado del puerto
private static void informa()
{
System.out.println("Información del puerto: " + sPort.getName());
System.out.println("Buffer entrada: " + sPort.getInputBufferSize());
System.out.println("Buffer salida: " + sPort.getOutputBufferSize());
System.out.println("Baudios: " + sPort.getBaudRate());
System.out.print("Bits de datos: ");
switch (sPort.getDataBits())
{
case SerialPort.DATABITS_5:
System.out.println("cinco ");
break;
case SerialPort.DATABITS_6:
System.out.println("seis ");
break;
case SerialPort.DATABITS_7:
System.out.println("siete ");
break;
case SerialPort.DATABITS_8:
System.out.println("ocho ");
break;
}
System.out.print("Bits de parada: ");
switch (sPort.getStopBits())
{
case SerialPort.STOPBITS_1:
System.out.println("uno ");
break;
case SerialPort.STOPBITS_2:
System.out.println("dos ");
break;
case SerialPort.STOPBITS_1_5:
System.out.println("uno y medio ");
break;
}
System.out.print("Paridad: ");
switch (sPort.getParity())
{
case SerialPort.PARITY_NONE:
System.out.println("ninguna ");
break;
case SerialPort.PARITY_ODD:
System.out.println("impar ");
break;
case SerialPort.PARITY_EVEN:
System.out.println("par ");
break;
case SerialPort.PARITY_MARK:
System.out.println("por marca ");
break;
case SerialPort.PARITY_SPACE:
System.out.println("por espacio ");
break;
}
System.out.print("Control de flujo: ");
switch (sPort.getFlowControlMode())
{
case SerialPort.FLOWCONTROL_NONE:
System.out.println("ninguno ");
break;
case SerialPort.FLOWCONTROL_RTSCTS_IN:
case SerialPort.FLOWCONTROL_RTSCTS_OUT:
System.out.println("hardware ");
break;
case SerialPort.FLOWCONTROL_XONXOFF_IN:
case SerialPort.FLOWCONTROL_XONXOFF_OUT:
System.out.println("software ");
}
}
}
class evSerie implements SerialPortEventListener
{
public void serialEvent(SerialPortEvent evento)
{
switch (evento.getEventType())
{
case SerialPortEvent.DATA_AVAILABLE:
System.out.println("Datos disponibles");
break;
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
System.out.println("Buffer vacio");
break;
case SerialPortEvent.CTS:
System.out.print("CTS pasa a ");
if (evento.getNewValue()) System.out.println("cierto");
else System.out.println("falso");
break;
case SerialPortEvent.DSR:
System.out.print("DSR pasa a ");
if (evento.getNewValue()) System.out.println("cierto");
else System.out.println("falso");
break;
case SerialPortEvent.RI:
System.out.print("RI pasa a ");
if (evento.getNewValue()) System.out.println("cierto");
else System.out.println("falso");
break;
case SerialPortEvent.CD:
System.out.print("CD pasa a ");
if (evento.getNewValue()) System.out.println("cierto");
else System.out.println("falso");
break;
}
}
}
En esta clase tenemos el interfaces de bajo nivel del puerto paralelo que cumple la norma IEEE-1284. El standard IEEE-1284 cuenta con 8 lineas de datos, 5 entrada de estado y 4 salidas de control, en la figura C se pueden ver los tres tipos de conectores que podemos encontrar en este tipo de interfaces. Los contactos del conector tipo A es el más utilizado en los ordenadores y se definen en la Tabla B con sus funciones en el modo SPP que es el modo compatible de trabajo para la impresora.
PIN NOMBRE Descripción 1 STROBE Indica que existen datos validos en la lineas de datos D0-7 2 D0 Dato bit 0 3 D1 Dato bit 1 4 D2 Dato bit 2 5 D3 Dato bit 3 6 D4 Dato bit 4 7 D5 Dato bit 5 8 D6 Dato bit 6 9 D7 Dato bit 7 10 ACK* Indica que el ultimo carácter se recibió. 11 BUSY* Indica que la impresora esta ocupada y no puede recoger datos. 12 PE* Sin papel. 13 SLCT* Indica que la impresora esta en linea. 14 AUTO FD Indica a la impresora que realice una alimentación de linea. 15 ERROR* Existe algún error en la impresora. 16 INIT* Pide a la impresora que se inicie. 17 SLCT* IN Indica a la impresora que esta seleccionada.
Nota: Los nombres con * indican señal negada.
Este standard podemos trabajar con 5 modos de funcionamiento:
La clase ParallelPort como dijimos es una clase que hereda de CommPort. Esta clase cuenta con una serie de métodos que nos facilitan el uso del puerto paralelo y los exponemos a continuación:
Aunque de momento solo se dispone de esta API para unix (de Sun) y Windows, se esta desarrollando una versión para linux.
|
Etiquetas: j2se
Saludos a todo los Programadores de Java y A los creadores y colaboradores de este articulo, esta muy bueno!....
Despues de seguir los pasos de la configuracion del API de comunicaciones en Windows XP, y despues de haber compliado y ejecutado el primer codigo que sale en este articulo, no me ejecuta lo que sale en la foto. solo me sale:
Los puertos disponibles son:
Y mas nada.... Me gusatria que me ayudaran a saber que pasa. Mil gracias por adelantado!
Ely Vera desde Venezuela
aver ely vera la verdad yo hace tiempo probe este codigo y nole he encontrado ningun error. este programa usa java.util por lo que su funcionamiento es bastante rapido y funciona sin supervicion. las ultimas verciones de java y y algnos generadores de codigo java usan MSDOS en el caso de windows algunos otros generadores de codigo como Jcreator por ejemplo no usan MSDOS si no que el mismo programa te genera la interfaz que permite la comunicacion del usuario con el programa
si quieres intenta hacer lo siguiente:
puedes usar javax.swing que es una te proporciona una interfaz mas elegante. si quieres usa el codigo que esta a continuacion
import java.io.*;
import java.util.*;
import javax.comm.*;
import javax.swing.*;
public class P1
{
static Enumeration listaPort;
static CommPortIdentifier idPort;
public static void main(String[] args)
{
listaPort = CommPortIdentifier.getPortIdentifiers();
ListaPuertos();
}
private static void ListaPuertos()
{
String lista="";
lista +="Los puertos disponibles son:";
while (listaPort.hasMoreElements())
{
idPort = (CommPortIdentifier) listaPort.nextElement();
lista +="PUERTO: " + idPort.getName() + " ";
if (idPort.getPortType() == CommPortIdentifier.PORT_SERIAL)
{
lista +="RS-232 (" + idPort.getPortType() + ")";
} else if (idPort.getPortType() == CommPortIdentifier.PORT_PARALLEL)
{
lista +="IEEE 1284 (" + idPort.getPortType() + ")";
} else lista +="Tipo de puerto desconocido";
// Describimos si esta disponible.
if (idPort.isCurrentlyOwned())
lista +="OCUPADO por: " +
idPort.getCurrentOwner();
else
lista +="DISPONIBLE";
lista +="\n---------------------------------------------\n";
}
JOptionPane.showMessageDialog(null,lista);
}
}
es el mismo programa pero usando una interfaz javax.swing
ojala y te sirva
hasta luego
Hola necesito que auyda, necesito hacer una aplicion que me detecte el numero de telefono(telefonia fija) que esta llamando pero desde la targeta de fax modem, quiero hacer esta aplicaccion en java, he leido sobre javax.comm perono se por donde comenzar muchas gracias
biejo lo que pasa es que estoy intentado pero me sale el siguiente error que devo aser
Error loading SolarisSerial: java.lang.UnsatisfiedLinkError: no SolarisSerialParallel in java.library.pathCaught java.lang.UnsatisfiedLinkError: readRegistrySerial while loading driver com.sun.comm.SolarisDriverError loading SolarisSerial: java.lang.UnsatisfiedLinkError: no SolarisSerialParallel in java.library.pathCaught java.lang.UnsatisfiedLinkError: readRegistrySerial while loading driver com.sun.comm.SolarisDriver
Press any key to continue...
Javier te agradezco que hayas escrito este artículo.
Acabo de realizar las indicaciones que en él mencionas y no me despliega los puertos
la instrucción "listaPort.hasMoreElements()" me regresa falso, es el mismo problema de Eli, tambien ejecute el código que le envias a Eli, meda el mismo resultado, no los despliega.
¿Tienes alguna idea del por qué no se obtienen los puertos?
Bueno, espero me puedas ayudar, si no deja ver que puedo investigar
Saludos
David Sánchez
Cuando no les muestra los puertos seguramente el problema se a de configuración de la commapi.
Tenía el mismo problema y radica en que no tienen el archivo javax.comm.properties en el /lib de su jre, además hay que copiar una dll.
En el archivo PlatformSpecific.html que está adentro del zip de la commapi están las instrucciones de instalación de la api. siganlas al pie de la letra. Además si están utilizando la JDK copien tambien el .properties al jre/lib que está dentro de su jdk.
Espero ser de ayuda
Luis Sánchez
lstsoft@hotmail.com por cualquier cosa.
oye endonde bajaron el API java de COMM, ??
Y Cómo se instala en windows este API?
Hola
MI nombre es Ivan y yo eh hecho la aplicacion para mandar y recibir datos, mi problema consiste en que yo quiero correr las dos aplicaciones al mismo tiempo, es decir en cuanto abra el formulario que se quede esperando si hay datos disponibles para recibir, pero si quiero mandar datos poderlo hacer,el problema es que cuando lo hago y creo el arreglo de tipo bytes me manda cuadros por ejemplo si pongo el arreglo de bytes del tamaño de 20 me manda 20 cuadros.
Hola
Mi nombre es ivan y bueno yo estoy actualmente creando una aplicacion para envio y recepcion de datos por puerto com, mi problema es que cuando recibo datos y los recibo con una configuracion de 7 bits los recibo completos ejemplo: me envian esto: ""esto es una prueba"" y lo recibo completo pero cuando lo pongo a 8 bits de recepcion, me los manda cortados, ejemplo:""" esto es una prueba """y me los envia asi:
mensaje_1:""esto es un""
mensaje_2:"""a prueba""
alguien me podria aydar porfavor darme alguna idea que me oriente
Muchas gracias por su atencion
Saludos
Para manejar el puerto serial necesitas las librerias de sun el Javaxcomm, las puedes descargar de la direccion
http://www.sun.com/download/index.jsp?cat=Application20Development&tab=3
una vez que las tengas instaladas, debes hacer uso de un modo de lectura, el puerto COM generalmente se maneja en 8 canales, como sea necesitas una funcion para leer y otra para enviar datos a traves de este puerto. Un buen concejo que puedo darte al respecto es que uses Threads("HILOS"), es una muy buena solucion para el problema que planteas, si no sabes como se usan o necesitas algun ejeplo visita este link
http://www.itapizaco.edu.mx/paginas/JavaTut/froufe/parte19/cap19-3.html
Encontraras dos ejemplos muy bueno, uno el java 1901 de envio de datos y el otro java1902 de lectura, son muy buenos a mi me ayudaron bastante.
espero que esta informacion te sirva SUERTE.......:)
Ervin
Hola
estoy desarrollando una aplicacion que envia datos por el puerto serial, pero solo lo hace la primera vez que la ejecuto y luego me dice que el puerto esta ocupado por el api de escritura. Cómo puedo cerrar el puerto serial luego de realizar la transmision?
DiegoFer
Escribe tu comentario