Algum tempo atrás me deparei com um problema que até então nunca tinha sido apresentado. Entrei em um projeto que necessitava do desenvolvimento de um sistema que fosse capaz de capturar e responder a estímulos oriundos da porta serial utilizando padrão de comunicação EIA-232 (mais conhecido como “RS-232”. Saliento que esta API, não apenas realiza comunicação pela porta serial, mas também proporciona comunicação pela porta paralela, porém não faz parte do escopo desse artigo).

Como eu estava encarregado em disponibilizar essa interface do sistema com um dispositivo externo, comecei a procurar, e descobri que a SUN já dispunha de uma API para este tipo de comunicação. Neste momento tinha achado a solução para o problema, mas ainda estava preocupado com questões de como trabalhar com o RS-232, ou seja, eu não entendia como o padrão funcionava, como deveria tratar os sinais que chegariam (por se tratar de uma comunicação por tensão que variam de +12 volts à -12 volts). A API Java Comunications, juntamente com a Java Virtual Machine(JVM) abstrai para o programador final tais particularidades. A API está disponível na URL: http://java.sun.com/products/javacomm/.

Diante desta nova realidade comecei a estudar mais a API e descobri que ela está idealizada sobre a classe abstrata CommPort e duas subclasses, SerialPort e ParallelPort, e como você deve ter percebido ela descreve os dois tipos de comunicação possibilitados, que se tratam das portas mais encontradas em Desktops atualmente.

Sabemos que essas portas estão perdendo espaço muito rapidamente para o USB(“Universal Serial Bus”), mas ainda há uma grande variedade de equipamentos que utilizam a comunicação serial e paralela. A SUN ainda não confirma se irá integrar essa característica à API, mas, com um pouco de “achismo” da minha parte, é difícil imaginar que a SUN não irá portar este padrão de comunicação.

Figura 1
 

Figura 1

Não há a possibilidade de se instanciar uma dessas classes diretamente, pois os seus construtores são intencionalmente não-públicos. Para obtê-las é preciso usar o método estático CommPortIdentifier.getPortIdentifier() para capturar as portas disponíveis, dando ao usuário a oportunidade de escolher qual porta usar. Dessa forma, através do CommPortIdentifier, pode-se chamar o método open() para receber uma instância do objeto CommPort. Para utilizar o objeto como uma porta serial, é necessário apenas

realizar um cast para qualquer uma das subclasses derivadas da CommPort.

Cada uma dessas subclasses possuem suas características e métodos que possibilitam ao usuário usar eventos padrão do Java para receber notificação de dados disponíveis, ou até mesmo tipos específicos de eventos como indicador de sinal (na comunicação de dados), sinalização do modem (DCE) para o computador (DTE), etc.

Alguns exemplos que irei demonstrar foram desenvolvidos na IDE Eclipse (disponível para download em www.eclipse.org). Em primeiro lugar devemos configurar a IDE, que é um processo bastante simples. Segue abaixo um passo a passo.

Figura 2

Figura 2: Project -> Properties

Figura 3

Figura 3: Java Build Path -> Libraries

Figura 4

Figura 4: Add External JARs e selecionar a biblioteca comm.jar que vem dentro do pacote da API que deve ser baixado diretamente do site da SUN, como mostrado anteriormente.

  Figura 5
 

Figura 5

Feito isso, é preciso realizar algumas configurações necessárias para que a API fique integrada ao Sistema Operacional. Ao baixar o arquivo compactado, será necessário descompactá-lo, abrir o arquivo Readme.html e localizar as instruções para a instalação (não entrarei em detalhes sobre isso, por se tratar de uma tarefa simples e dependente do Sistema Operacional).

Como saber quais portas estão disponíveis e como escolher uma?

Para realizar essa tarefa deveremos utilizar, como mencionado no texto anteriormente, o método CommPortIdentifier.getPortIdentifiers() que retornará todas as portas de comunicação serial e/ou paralelas disponíveis no computador.

É claro que você poderia dizer que sabe quais portas estão disponíveis no seu PC. Isso é perfeitamente possível de ser feito, apenas devendo passar como parâmetro do método a porta que você sabe que está disponível, procedendo da seguinte forma:

import javax.comm.*;
import java.io.*;
import java.util.*;
...
int timeout = 1000; // Tempo de espera.
String tipoPorta = "/dev/ttyS1"; //Porta serial no linux Fedora
CommIdentifier cp = CommPortIdentifier.getPortIdentifier(tipoPorta);
SerialPort porta = (SerialPort)cp.open(“titulo”, timeout);
...

Ou se caso preferirem, e dependendo da necessidade, poderia ser possível escolher uma das portas disponíveis no PC, como temos a seguir:

// captura a lista de portas disponíveis,
// pelo método estético em CommPortIdentifier.
Enumeration pList = CommPortIdentifier.getPortIdentifiers();
// Um mapping de nomes para CommPortIdentifiers.
HashMap map = new HashMap();
// Procura pela porta desejada
while (pList.hasMoreElements()) {
        CommPortIdentifier cpi = (CommPortIdentifier)pList.nextElement();
        map.put(cpi.getName(), cpi);
        if (cpi.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                // fazer alguma tarefa
        }
}

O trecho acima demonstra como fazer a consulta ao sistema, capturar as portas disponíveis e escolher a que deverá ser utilizada. Dessa forma, dependendo do caso, poderemos ter a certeza que a porta está realmente disponível, uma vez que sabemos que a porta existe, mas, por algum motivo, não está acessível por está sendo utilizado por outro programa, ou até mesmo falha no equipamento.

Nos próximos artigos entraremos mais a fundo na API e encontrar respostas para algumas perguntas que provavelmente surgem, como por exemplo:

  • Como configurar e abrir uma porta serial?
  • Como resolver conflitos de porta?
  • Como ler e escrever em uma porta?

Espero que tenham gostado desse primeiro artigo e nas próximas semanas estarei dando prosseguimento, obrigado a todos e até a próxima.

Referências

Leia também