Com todo o oba-oba ao redor do Wi-Fi, do Bluetooth e de outras tecnologias sem-fio, é fácil esquecer a um das formas mais simples e comuns de comunicação sem fio: a infravermelha. Qualquer um que já usou um controle remoto usou o infravermelho! Como usa-se a luz como meio de transporte, é necessário que um ponto “enxergue” o outro, mas mesmo com essa limitação, o infravermelho está cada vez mais popular em aparelhos como câmeras digitais, Celulares, PDA's  e NoteBooks.

Neste artigo mostrarei como usar a porta infravermelha de seu Smartphone (funciona também para PocketPC's) para transferir informações entre esses dispositivos. Iremos criar uma simples aplicação de Chat usando a classe IrDAClient do Compact Framework. Essa aplicação pode ser bastante útil em reuniões tediosas.

Construindo a aplicação

Para começar, rode o Visual Studio .NET 2003 e crie um projeto “Smart Device Application” usando o C#. Chame o projeto de IrdaChat.

Agora vamos construir a interface da aplicação do Chat. Baixe os seguintes controles no Form1:

  • Dois TextBoxes;
  • MainMenu (já é criado automaticamente);
  • Dois Labels.

O controle do menu tem um sub-item chamado “Nome do Serviço” dentro do menu “Configurações”.

O TextBox maior deve se chamar txtMessagesArchive e ter a propriedade MultiLine setada como true. O outro TextBox deve se chamar txtMessage.

Agora você precisa declarar o uso de alguns namespaces, como na Listagem 1:

Listagem 1: NameSpaces adicionais necessários ao projeto.

using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;

Para usar a classe IrDAClient no Compact Framework, que fornece os serviços de comunicação infravermelha, você vai precisar adicionar uma referência ao assembly System.Net.IrDA. Para fazê-lo, clique com o botão direito no nome do projeto na Solution e selecione “Add Reference”.

Clique 2 vezes sob o item System.Net.IrDa e clique OK.

Declare também estes objetos e constantes da classe Form1, da Listagem 2.

Listagem 2: Membros adicionais da classe Form1

private const int MAX_MESSAGE_SIZE = 128;
private const int MAX_TRIES = 3;
private string ServiceName = "default";
private IrDAClient irdaClient = new IrDAClient();
private Stream irStream;

A constante MAX_MESSAGE_SIZE é o tamanho máximo da mensagem trocada e a MAX_TRIES é o número máximo de tentativas para enviar uma mensagem antes de desistir e avisar um erro no envio.

O atributo ServiceName é usada para identificar a sessão de uso do Chat. O objeto irdaClient contém os serviços da comunicação infravermelho e o irStream serve para conter os dados recebidos e enviados.

Recebendo Mensagens

Quando a aplicação está carregada, ela precisa começar a “ouvir” as mensagens que possam chegar. Para fazer isso, coloque o código da Listagem 3 no evento OnLoad() do formulário.

 

Listagem 3: Evento OnLoad() do form1

private void Form1_Load(object sender, System.EventArgs e)
{
Thread t1 = new Thread(new ThreadStart(receiveLoop));
        t1.Start();
} 

Basicamente esse evento cria um thread para invocar o método receiveLoop(). O objetivo aqui é “ouvir” as mensagens em background, para que você possa enviar mensagens a qualquer momento.

Na Listagem 4 temos o código do receiveLoop().

Listagem 4: Método receiveLopp()

private void receiveLoop()
{
        string strReceived; 
        strReceived = receiveMessage(MAX_MESSAGE_SIZE); 
        while (true) 
        { 
                if (strReceived != "") 
                { 
                        UpdateTextBox(strReceived); 
                        strReceived = receiveMessage(MAX_MESSAGE_SIZE); 
                } 
        }
}

A principal função deste método é invocar repetidamente o método receiveMessage(). Este método retorna a mensagem recebida pela porta infravermelha e seu código é o da Listagem 5.

Listagem 5: Método que recebe as mensagens

private string receiveMessage(int BufferLen)
{        
int bytesRead = 0; 
        IrDAListener listener = new IrDAListener(ServiceName); 
        IrDAClient client = null; 
        System.IO.Stream stream = null; 
        byte[] Buffer = new byte[MAX_MESSAGE_SIZE]; 
        string str = ""; 
        try 
        { 
                listener.Start(); 
                client = listener.AcceptIrDAClient(); 
                stream = client.GetStream(); 
                bytesRead = stream.Read(Buffer, 0, BufferLen); 
                str = client.RemoteMachineName + "->";
      str += Encoding.ASCII.GetString (Buffer, 0, bytesRead); 
        } 
        catch (Exception e) 
        { 
                MessageBox.Show ("Erro obtendo a mensagem"); 
        } 
        finally 
        { 
                if ((!(stream == null))) 
                { 
                        stream.Close(); 
                } 
                if ((!(client == null))) 
                { 
                        client.Close(); 
                } 
                listener.Stop(); 
        } 
        return str; 
}
 

Vou explicar melhor o funcionamento deste método. Primeiro estabelecemos os objetos relevantes para este método. Em particular, criamos um objeto IrDAListener que é usado para escutar os dados recebidos pela porta infravermelha e contém o Nome do Serviço. Dois dispositivos conversando entre si pela porta infravermelha devem ter o mesmo nome de serviço.

Criamos também um objeto IrDACliente para enviar e receber dados de outro dispositivo.

O objeto IrDAListener começa ouvindo dados de entrada e retorna um objeto IrDACliente quando dados são recebidos. Então usamos um objeto stream para ler o fluxo de dados. Finalmente o método receiveMessage() retorna os dados formatados já prontos para serem exibidos no formulário.

Enviando mensagens

Agora que nosso programa já está pronto para receber as mensagens, só temos que enviá-las! Então, quando a opção “Enviar” do menu principal é selecionada, o seguinte código é executado:

 

Listagem 6: Evento da opção “Enviar” do menu principal

private void menuItem3_Click(object sender, System.EventArgs e)
{
sendMessage(MAX_TRIES, 
Encoding.ASCII.GetBytes(txtMessage.Text),   
txtMessage.Text.Length); 
}

O método sendMessage() primeiro tenta estabelecer uma conexão com o outro aparelho até que o número de novas tentativas seja excedido. Uma vez que a conexão seja estabelecida, ele escreve a mensagem usando o objeto de io stream e finalmente fecha o fluxo de dados e a conexão.

Listagem 7: Método para enviar mensagens

private void sendMessage(int NumRetries, byte[]Buffer, int BufferLen) 
{ 
        IrDAClient client = null; 
        int CurrentTries = 0; 
        do 
        { 
                try 
                { 
                        client = new IrDAClient(ServiceName); 
                } 
                catch (SocketException se) 
                { 
                        if ((CurrentTries >= NumRetries)) 
                        { 
                               throw se; 
                        } 
                } 
                CurrentTries = CurrentTries + 1; 
        } while (client == null & CurrentTries < NumRetries); 
        if ((client == null)) 
        { 
                MessageBox.Show("Erro estabelecendo conexão"); 
                return; 
        } 
        System.IO.Stream stream = null; 
        try 
        { 
                stream = client.GetStream(); 
                stream.Write(Buffer, 0, BufferLen); 
        } 
        catch (Exception e) 
        { 
                MessageBox.Show("Erro enviando"); 
        } 
        finally 
        { 
                if ((!(stream == null))) 
                { 
                        stream.Close(); 
                } 
                if ((!(client == null))) 
                { 
                        client.Close(); 
                } 
        } 
}

Mudando o Nome do Serviço

Por default, o nome do serviço dos dois aparelhos que se comunicam é setado para ser ‘default'. No entanto o usuário pode mudar esse nome usando a opção do menu ‘Nome do Serviço'. Neste artigo, esta função apenas troca o nome do serviço para “default2”. Você pode posteriormente criar um formulário para pedir este novo nome.

Listagem 8: Mudando o nome do serviço

private void menuItem2_Click(object sender, System.EventArgs e)
{
        ServiceName = “default2”; 
}

Conclusão

Com este artigo você adquiriu o conhecimento necessário para desenvolver aplicações que transfiram informações através da porta infravermelha usando o .NET Compact Framework. Agora você pode incluir em suas aplicações recursos para troca de dados sem necessariamente precisar de infra-estruturas caras, como wi-fi, para a transferência de dados sem fio. Divirta-se!