• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

M6

[C#] Bluetooth

9 mensagens neste tópico

Neste pequeno artigo vou explicar como se pode fazer uso do Bluetooth, uma tecnologia sem fios cujo alcance, dividido em classes, pode ir, actualmente, até aos 100m.

Este tipo de tecnologia está maioritariamente presente em dispositivos móveis facilitando a comunicação, uma vez que normalmente esse tipo de dispositivos não possui muitas interfaces de comunicação.

Este artigo torna-se mais interessante quando aplicado em dispositivos móveis, por isso irei falar na .Net Compact Framework (.Net CF) sobre Windows Compact Edition (Windows CE), ou semelhante.

Urge dizer que o desenvolvimento pode ser feito usando o Visual Studio com o módulo de dispositivos móveis que contempla um emulador de PDA com Windows CE. Para mais informação sobre como usar o Visual Studio para executar a aplicação no emulador e fazer o deploy no PDA há que consultar a documentação.

Urge também dizer que o desenvolvimento sobre o emulador não permite tirar partido de todas as funcionalidades que se tem disponíveis no PDA. Em particular, não é possível usar o bluetooth dentro do emulador, mesmo que o PC onde se está a desenvolver a aplicação possua essa tecnologia. Para tal, aconselho que se use um PDA ligado ao Visual Studio para se fazer debug, de novo, é favor consultar a documentação sobre este tópico em caso de dúvida.

O artigo possui informação suficiente para, no final, se poder fazer uma pequena aplicação usando esta tecnologia. Assim, deixo como exercício a construção de um chat simples para dispositivos que correm Windows CE usando os conhecimentos aqui expostos.

Introdução

O Bluetooth é uma tecnologia que permite a comunicação entre dispositivos sem recurso a qualquer tipo de cabos e que disponibiliza um conjunto de serviços do próprio dispositivo que podem ser usados por outro dispositivo.

Descoberta

Um dispositivo com Bluetooth possui um processo de descoberta permite aos dispositivos interrogarem outros dispositivos para descobrir que serviços estes oferecem. Se um dispositivo oferece mais do que um serviço, o utilizador pode seleccionar qual o serviço que pretende utilizar desse dispositivo em particular.

Dado que o Windows CE não dispõe de uma API dedicada para comunicações por Bluetooth, torna-se necessário utilizar outros métodos, como programação de sockets ou a utilização de portas série.

Para consultar quais os portos COM que estão atribuídos para comunicação Bluetooth é necessário aceder à configuração do Bluetooth ("Bluetooth Settings" —> "Serial Port"), onde se pode ver qual o porto utilizado para receber informação, e qual o porto utilizado para enviar informação.

A .Net CF não possui classes especificas para comunicação série, pelo que se torna necessário utilizar chamadas ao sistema operativo para que este forneça essa capacidade. Em particular, teremos de utilizar a biblioteca coredll.dll do Windows CE.

Chamadas ao sistema operativo

Da biblioteca coredll.dll utilizam-se as seguintes funções:

  • CreateFile - Abre uma ligação a uma porta COM.
  • ReadFile - Lê informação de uma porta COM.
  • WriteFile - Escreve informação para uma porta COM.
  • CloseHandle - Fecha uma ligação a uma porta COM.

Para se chamar estas funções dentro do código da aplicação é necessário recorrer à biblioteca System.Runtime.InteropServices.DllImport. É assuim necessário especificar as funções com as respectivas assinaturas dessa biblioteca:

[system.Runtime.InteropServices.DllImport("coredll.dll")]
private extern static int CreateFile(String lpFileName, // nome do ficheiro, ou neste caso da porta COM
								 uint dwDesiredAccess, // modo de acesso: pode ser leitura (0x80000000),
								 escrita (0x40000000), ou ambos (0xC0000000)
								 int dwShareMode,
								 int lpSecurityAttributes,
								 int dwCreationDisposition,
								 int dwFlagsAndAttributes,
								 int hTemplateFile);

[system.Runtime.InteropServices.DllImport("coredll.dll")]
private extern static int ReadFile(int hFile, // handler do ficheiro que vai ser lido
							   byte[] Buffer, // array de bytes para onde vai ser lida a informação
							   int nNumberOfBytesToRead,
							   ref int lpNumberOfBytesRead, // inteiro passado por referência, retorna os bytes lidos
							   ref int lpOverlapped);

[system.Runtime.InteropServices.DllImport("coredll.dll")]
private extern static int WriteFile(int hFile, // handler do ficheiro que vai ser escrito
								byte[] Buffer, // array de bytes com a informação que vai ser escrita
								int nNumberOfBytesToWrite,
								ref int lpNumberOfBytesWritten, // inteiro passado por referência, retorna os bytes escritos
								int lpOverlapped);								  

[system.Runtime.InteropServices.DllImport("coredll.dll")]
private static extern int CloseHandle(int hObject);

É de salientar a presença de variáveis passadas por referência, que irão corresponder a apontadores nas funções definidas na biblioteca coredll.dll. A informação é lida e escrita usando um array de bytes, que também é implementado com apontadores na biblioteca coredll.dll.

Abrir portos COM

O primeiro passo para estabelecer comunicação entre dois dispositivos é a abertura das portas COM. Para tal, uza-se a função CreateFile. Supondo que as variáveis inPort e outPort armazenam o número dos portos de entrada e saída, a abertura dos portos pode ser efectuada da seguinte forma:

infileHandler = CreateFile("COM" + inPort + ":", 0xC0000000, 0, 0, 3, 0, 0);
Application.DoEvents();

outfileHandler = CreateFile("COM" + outPort + ":",  0xC0000000, 0, 0, 3, 0, 0);
Application.DoEvents();

Esta função retorna um handler, inteiro, que identifica o ficheiro, neste caso a porta COM, e que será igual a zero em caso de insucesso na abertura da porta.

A utilização do método Application.DoEvents() prende-se com a necessidade de garantir que a aplicação continue a responder a eventos, com origem na interface ou noutra fonte, enquanto processa as chamadas a outros métodos, neste caso à função CreateFile.

Como a função ReadFile, que será usada para ler as mensagens que chegam, é bloqueante, é necessário invocar uma System.Threading.Thread para escutar continuamente a informação que possa estar a chegar, garantindo que a aplicação continua a responder aos comandos do utilizador.

t1 = new System.Threading.Thread(new System.Threading.ThreadStart(receiveLoop));
t1.Start();

receiveLoop é o nome do método onde a escuta irá ser feita.

Escrever num porto COM

Para escrever num porto COM utiliza-se a função WriteFile.

int retCode = WriteFile(outfileHandler, stringToByteArray(message), message.Length, ref n, 0);

No código anterior message é uma variável do tipo String que armazena a mensagem que se pretende enviar. n é um int passado por referência, que irá ficar com o número de bytes escritos. O método stringToByteArray é responsável por converter uma String num array de bytes. Esta função retorna um inteiro, que será igual a zero em caso de insucesso.

public byte[] stringToByteArray(String str)
{
 char[] s;
 s = str.ToCharArray();
 byte[] b = new byte[s.Length];
 for (int i = 0; i < (s.Length); i++)
 {
b[i] = System.Convert.ToByte(s[i]);
 }
 return b;
}

Ler de um porto COM

A leitura é feita recorrendo à função ReadFile, normalmente colocada dentro de um ciclo noutra thread, para poder estar continuamente a escutar novas mensagens. Como aceder a controlos não é seguro quando estes estão noutra thread, recorre-se a um delegate para chamar uma função na thread dos controlos, responsável por processar a informação recebida.

public delegate void myDelegate(String str);

public void processMessage(String str)
{
 // processar a mensagem recebida
}

public void receiveLoop()
{
 int n = 0; // variaveis passadas por referencia na chamada a ReadFile
 int n1 = 0;
 byte[] inbuff = new byte[300]; // array de bytes que vai conter a informacao recebida

 int retCode = ReadFile(infileHandler, inbuff, inbuff.Length, ref n, ref n1);
 Application.DoEvents();
 while ( !((retCode == 0) || stopThread ) ) // nao parar enquanto nao houver um erro de leitura ou uma indicacao para parar a thread
 {
myDelegate processDelegate = new myDelegate(processMessage); // criar um delegate para chamar a funcao processMessage
processDelegate(byteArrayToString(inbuff)); // chamar a funcao processMessage passando a mensagem como parametro
inbuff = new byte[300]; // reinicializar o array de bytes
retCode = ReadFile(infileHandler, inbuff, inbuff.Length, ref n, ref n1);
Application.DoEvents();
 }
}

É de realçar mais uma vez a necessidade da utilização do método Application.DoEvents(), de modo a evitar bloquear a aplicação durante o processo de escuta. Esta função retorna um inteiro, que será igual a zero em caso de insucesso. O método byteArrayToString é responsável por converter o array de bytes recebido numa String.

public String byteArrayToString(byte[] b)
{
 String str;
 System.Text.ASCIIEncoding enc;
 enc = new System.Text.ASCIIEncoding();
 str = enc.GetString(b, 0, b.Length);
 return str;
}

Fechar as ligações

Para fechar as ligações às portas COM utiliza-se a função CloseHandler que recebe como parâmetro o handler do ficheiro, ou a porta COM neste caso.

CloseHandle(infileHandler);
CloseHandle(outfileHandler);

[Artigo no Wiki]

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Grande tutorial!!  :(

Grande em quantidade e qualidade! ;)

Obrigado. :D

Já fizeste o chat como exercício?  :P

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Obrigado. Smiley

Já fizeste o chat como exercício?  Cheesy

Ainda não... :P

Eu tenho estado a iniciar-me nesta linguagem, mas agora começaram as aulas tenho menos tempo para isto. Mas sempre que tenho tempo pego no código dos teus tutoriais e faço o programa. ;)

Continua, os teus tutoriais são mesmo muito bons para quem se inicia porque estão muito bem explicados.  :(

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

experimenta ligar o bluetooth no teu pc (se tiver bluetooth) configuras para uma porta COM 'x', depois Menu Iniciar - Acessorios - Comunicações - HyperTerminal! Cria uma nova ligação e diz que esta vai estar ligada na porta COM 'x' que escolheste anteriormente.

Se reparares a informação vai passar por ai. ex: Liga uma antena GPS bluetooth ao computador e ves as coordenadas e os restantes valores e comandos.

Ou seja... para usares bluetooth no pc so tens de configurar a porta com que pretendes utiliizar. Se tivere o Visual Studio 2005 ja tens um controlo chamado COM Port se não estou em erro ;)

Boas Experiencias

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Grande Post  ;)

Eu queria desenvolver algo do gero mas a correr no PC para enviar SMS directamente do PC usando o bluetooh do telemovel

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

    Boa noite,

    A solução para a tua questão é relativamente simples... Um telemóvel basicamente funciona como um modem. Assim basta usares o exemplo acima, para abrires a comunicação com o telemóvel (depois de emparelhado), e usas os comandos AT para enviar o sms.

Cordiais cumprimentos,

Apocsantos

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora