Utilizando comandos do modem
Autor/fonte: Victory Fernandes
Atualmente, existem diversas opções de como se realizar ligações a partir de um computador utilizando o modem.
A mais simples seria fazer com que seu aplicativo chamasse o discador que acompanha o Windows, o que não seria, por assim dizer, uma solução, visto que todas as ligações não seriam realizadas pelo seu aplicativo e futuramente nenhum tipo de relatório poderia ser extraído.
Uma segunda opção possível seria a utilização da TAPI (Interface de Programação de Aplicativos de Telefonia), que é uma API específica para desenvolvimento de aplicações telefônicas. Apesar desta ser a opção mais recomendada, ela exige muitas linhas de código e uma maior experiência do programador.
Vamos então nos deter em realizar ligações utilizando os velhos e conhecidos comandos do modem ("modem commands"), acessando, diretamente via um Handle, a porta onde está instalado o modem, e enviando strings de comando para o mesmo, utilizando a função WriteFile.
Neste artigo utilizamos as funções CreateFile e WriteFile que são descritas ao final. Maiores informações podem ser obtidas no arquivo Microsoft Windows Developers Guide - "C:\Arquivos de programas\Arquivos comuns\Borland Shared\MSHelp\guide.hlp" que acompanha o instalação do Delphi 5.
Os comandos do modem
Os modems obedecem a tabelas de comandos que podem sofrer variações de acordo com o fabricante. Alguns dos comandos mais usados são:
. AT - Atenção;
. A - Atender;
. D - Discar;
. H - Desligar ("hangup");
. T - Discagem de tom;
. P - Discagem de pulso;
. , - Pausa;
. &F - Configurações de fábrica;
. <cr> - Terminador.
Esses comandos são combinados de forma a criar a string de comando desejada. Por exemplo, para realizar uma ligação, devemos enviar para o modem a seguinte string:
ATDT1234567
A string acima passa ao modem as seguintes informações:
. AT - Atenção, comandos serão enviados;
. D - Discar;
. T - Utilizar discagem tipo tom
. 1234567 - Número que se deseja discar;
. <cr> - Terminador informando o fim da string.
Criando o programa discador
Vamos agora criar um pequeno projeto que usa comandos do modem para realizar ligações. Inicie um novo projeto, adicione um TButton, um TEdit, um TComboBox, um TMemo e dois TRadioButton. A Figura 1 mostra o formulário pronto.
Na propriedade Items do ComboBox, adicione os nomes das portas do seu computador (COM1;COM2;COM3;COM4). Logo após a declaração do seu formulário declare as seguintes variáveis globais (mostradas em negrito):
var
Form1: TForm1;
hCommFile: THandle;
Status: LongBool;
NumberWritten: DWORD;
Buf : array [0..1023] of Byte;
s : string;
No evento OnClick do botão adicione o seguinte código:
procedure TForm1.Button1Click(Sender: TObject);
begin
//Testa os valores necessários
if (combobox1.text <> '') and (edit1.text<>'') then
begin
//Abre a porta de comunicação
s:=Combobox1.text;
hCommFile :=CreateFile(PChar(s), GENERIC_WRITE,
0, // não compartilhado
nil, // sem segurança
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
// Verifica a abertura da porta
if hCommFile = INVALID_HANDLE_VALUE then
begin
memo1.lines.clear;
memo1.lines.add('Não foi possível abrir a porta selecionada.');
memo1.lines.add('Discagem não efetuada');
CloseHandle(hCommFile);
end
else
begin
memo1.lines.clear;
memo1.lines.add('Discando...');
//Cria a string de comando
if radiobutton1.checked then
s:='ATDT'
else s:='ATDP';
s := s + edit1.text + #13#10;
memo1.lines.add(s);
//Envia a String de Comando
NumberWritten:=0;
Status:= WriteFile( hCommFile,PChar(s)[0],Length(s), NumberWritten, nil);
memo1.lines.add('Aguardando Atendimento ...');
MessageDlg('Retire o telefone do gancho e clique OK para desligar o modem',
mtInformation,[mbok],0);
//Desconecta a ligação
WriteFile(hCommFile,'ATH',5,NumberWritten,nil);
//Fecha a porta de comunicação
CloseHandle(hCommFile);
memo1.lines.add('Modem Desconectado.'#13#10);
end;
end;
end;
Pronto, está criado o programa discador, que pode ainda ser incrementado com diversas facilidades, mas que por hora cumpre seu objetivo: realizar ligações!
As funções createFile e writeFile
CreateFile e WriteFile são funções 32-bit da API do Windows para comunicação Síncrona ou Assíncrona com portas seriais e diversos outros dispositivos. Veja abaixo a sintaxe das funções e alguns dos seu principais parâmetros:
A função createFile
Cria e abre um arquivo ou acesso a porta, retornando um operador (Handle) por onde serão realizadas as operações desejadas.
HANDLE CreateFile(
LPCTSTR lpFileName, // Ponteiro para o Nome do Arquivo
DWORD dwDesiredAccess, // Tipo de Acesso
DWORD dwShareMode, // Tipo de Compartilhamento
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // Atributos de Segurança
DWORD dwCreationDistribution, // Forma de criação do objeto
DWORD dwFlagsAndAttributes, // Atributos do Arquivo
HANDLE hTemplateFile // Operador para o arquivo
);
Principais parâmetros:
. lpFileName - Especifica o tipo de objeto para Criar ou Abrir, alguns objetos possíveis são:
.. Arquivos;
.. Programas console;
.. Portas seriais.
. dwDesiredAccess - Especifica o tipo de acesso ao objeto que podem ser: Acesso de leitura, escrita e leitura-escrita.
A função writeFile
Utiliza o operador retornado pela função CreateFile para escrever no arquivo ou porta recém criada e aberta.
BOOL WriteFile(
HANDLE hFile, // Operador para o objeto
LPCVOID lpBuffer, // Ponteiro para os dados a escrever
DWORD nNumberOfBytesToWrite, // Número de bytes para escrever
LPDWORD lpNumberOfBytesWritten, // Ponteiro para número de bytes escritos
LPOVERLAPPED lpOverlapped // Ponteiro para estrutura I/O
);
Principais parâmetros:
. hFile - Operador retornado pela função CreateFile através do qual é possível se realizar as operações desejadas;
. lpBuffer - Ponteiro indicando o buffer que contém os dados a serem escritos.
Notas finais
Para saber em que porta o seu modem está instalado consulte as propriedades do seu modem no painel de controle do Windows
Realizando testes, percebi que alguns modems tais como o HSP56 Micro Modem não realizam a ligações com a função mostrada anteriormente, isso porque, por default, a opção "Aguardar sinal antes de discar" não está selecionada. Para selecioná-la, envie para o modem a seguinte string de comando, antes da string com o número a ser discado.
s:='ATS7=60S30=0M1\N3%C3&K3B0N1X1'+#13#10;
Caso possua uma central telefônica entre a linha e o PC, na maioria das vezes é necessário enviar o número para requisitar a linha externa e uma pausa. Isso altera um pouco a string de comando:
S:='ATDT0, 1234567'+#13#10;
Este artigo foi testado para os modems HSP56 Micro Modem, Genius GM56PCI-L Modem Card, USRobotics 33 e 56, e não deve apresentar defeitos para outros modems diversos.
A mais simples seria fazer com que seu aplicativo chamasse o discador que acompanha o Windows, o que não seria, por assim dizer, uma solução, visto que todas as ligações não seriam realizadas pelo seu aplicativo e futuramente nenhum tipo de relatório poderia ser extraído.
Uma segunda opção possível seria a utilização da TAPI (Interface de Programação de Aplicativos de Telefonia), que é uma API específica para desenvolvimento de aplicações telefônicas. Apesar desta ser a opção mais recomendada, ela exige muitas linhas de código e uma maior experiência do programador.
Vamos então nos deter em realizar ligações utilizando os velhos e conhecidos comandos do modem ("modem commands"), acessando, diretamente via um Handle, a porta onde está instalado o modem, e enviando strings de comando para o mesmo, utilizando a função WriteFile.
Neste artigo utilizamos as funções CreateFile e WriteFile que são descritas ao final. Maiores informações podem ser obtidas no arquivo Microsoft Windows Developers Guide - "C:\Arquivos de programas\Arquivos comuns\Borland Shared\MSHelp\guide.hlp" que acompanha o instalação do Delphi 5.
Os comandos do modem
Os modems obedecem a tabelas de comandos que podem sofrer variações de acordo com o fabricante. Alguns dos comandos mais usados são:
. AT - Atenção;
. A - Atender;
. D - Discar;
. H - Desligar ("hangup");
. T - Discagem de tom;
. P - Discagem de pulso;
. , - Pausa;
. &F - Configurações de fábrica;
. <cr> - Terminador.
Esses comandos são combinados de forma a criar a string de comando desejada. Por exemplo, para realizar uma ligação, devemos enviar para o modem a seguinte string:
ATDT1234567
A string acima passa ao modem as seguintes informações:
. AT - Atenção, comandos serão enviados;
. D - Discar;
. T - Utilizar discagem tipo tom
. 1234567 - Número que se deseja discar;
. <cr> - Terminador informando o fim da string.
Criando o programa discador
Vamos agora criar um pequeno projeto que usa comandos do modem para realizar ligações. Inicie um novo projeto, adicione um TButton, um TEdit, um TComboBox, um TMemo e dois TRadioButton. A Figura 1 mostra o formulário pronto.
Na propriedade Items do ComboBox, adicione os nomes das portas do seu computador (COM1;COM2;COM3;COM4). Logo após a declaração do seu formulário declare as seguintes variáveis globais (mostradas em negrito):
var
Form1: TForm1;
hCommFile: THandle;
Status: LongBool;
NumberWritten: DWORD;
Buf : array [0..1023] of Byte;
s : string;
No evento OnClick do botão adicione o seguinte código:
procedure TForm1.Button1Click(Sender: TObject);
begin
//Testa os valores necessários
if (combobox1.text <> '') and (edit1.text<>'') then
begin
//Abre a porta de comunicação
s:=Combobox1.text;
hCommFile :=CreateFile(PChar(s), GENERIC_WRITE,
0, // não compartilhado
nil, // sem segurança
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
// Verifica a abertura da porta
if hCommFile = INVALID_HANDLE_VALUE then
begin
memo1.lines.clear;
memo1.lines.add('Não foi possível abrir a porta selecionada.');
memo1.lines.add('Discagem não efetuada');
CloseHandle(hCommFile);
end
else
begin
memo1.lines.clear;
memo1.lines.add('Discando...');
//Cria a string de comando
if radiobutton1.checked then
s:='ATDT'
else s:='ATDP';
s := s + edit1.text + #13#10;
memo1.lines.add(s);
//Envia a String de Comando
NumberWritten:=0;
Status:= WriteFile( hCommFile,PChar(s)[0],Length(s), NumberWritten, nil);
memo1.lines.add('Aguardando Atendimento ...');
MessageDlg('Retire o telefone do gancho e clique OK para desligar o modem',
mtInformation,[mbok],0);
//Desconecta a ligação
WriteFile(hCommFile,'ATH',5,NumberWritten,nil);
//Fecha a porta de comunicação
CloseHandle(hCommFile);
memo1.lines.add('Modem Desconectado.'#13#10);
end;
end;
end;
Pronto, está criado o programa discador, que pode ainda ser incrementado com diversas facilidades, mas que por hora cumpre seu objetivo: realizar ligações!
As funções createFile e writeFile
CreateFile e WriteFile são funções 32-bit da API do Windows para comunicação Síncrona ou Assíncrona com portas seriais e diversos outros dispositivos. Veja abaixo a sintaxe das funções e alguns dos seu principais parâmetros:
A função createFile
Cria e abre um arquivo ou acesso a porta, retornando um operador (Handle) por onde serão realizadas as operações desejadas.
HANDLE CreateFile(
LPCTSTR lpFileName, // Ponteiro para o Nome do Arquivo
DWORD dwDesiredAccess, // Tipo de Acesso
DWORD dwShareMode, // Tipo de Compartilhamento
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // Atributos de Segurança
DWORD dwCreationDistribution, // Forma de criação do objeto
DWORD dwFlagsAndAttributes, // Atributos do Arquivo
HANDLE hTemplateFile // Operador para o arquivo
);
Principais parâmetros:
. lpFileName - Especifica o tipo de objeto para Criar ou Abrir, alguns objetos possíveis são:
.. Arquivos;
.. Programas console;
.. Portas seriais.
. dwDesiredAccess - Especifica o tipo de acesso ao objeto que podem ser: Acesso de leitura, escrita e leitura-escrita.
A função writeFile
Utiliza o operador retornado pela função CreateFile para escrever no arquivo ou porta recém criada e aberta.
BOOL WriteFile(
HANDLE hFile, // Operador para o objeto
LPCVOID lpBuffer, // Ponteiro para os dados a escrever
DWORD nNumberOfBytesToWrite, // Número de bytes para escrever
LPDWORD lpNumberOfBytesWritten, // Ponteiro para número de bytes escritos
LPOVERLAPPED lpOverlapped // Ponteiro para estrutura I/O
);
Principais parâmetros:
. hFile - Operador retornado pela função CreateFile através do qual é possível se realizar as operações desejadas;
. lpBuffer - Ponteiro indicando o buffer que contém os dados a serem escritos.
Notas finais
Para saber em que porta o seu modem está instalado consulte as propriedades do seu modem no painel de controle do Windows
Realizando testes, percebi que alguns modems tais como o HSP56 Micro Modem não realizam a ligações com a função mostrada anteriormente, isso porque, por default, a opção "Aguardar sinal antes de discar" não está selecionada. Para selecioná-la, envie para o modem a seguinte string de comando, antes da string com o número a ser discado.
s:='ATS7=60S30=0M1\N3%C3&K3B0N1X1'+#13#10;
Caso possua uma central telefônica entre a linha e o PC, na maioria das vezes é necessário enviar o número para requisitar a linha externa e uma pausa. Isso altera um pouco a string de comando:
S:='ATDT0, 1234567'+#13#10;
Este artigo foi testado para os modems HSP56 Micro Modem, Genius GM56PCI-L Modem Card, USRobotics 33 e 56, e não deve apresentar defeitos para outros modems diversos.

Enviado por xKuRt em 27/09/2006 às 09:37
Avaliação
Esta publicação ainda não foi avaliada!
A avaliação de publicações é restrita a membros cadastrados e logados no nosso site.
Comentários
Este artigo ainda não foi comentado ou o(s) comentário(s) que foi(ram) enviado(s) a ele ainda não foi(ram) publicado(s).
Envio de comentário:
Quinta, 02 de Setembro de 2010
Área restrita
Leitura recomendada
Últimas publicações
Top 5 membros
- dddweb213 pts
- Jotah191 pts
- fbinasco165 pts
- andersonop153 pts
- fredbcn117 pts
Últimos membros cadastrados
- reniltonem 02/09
- baixehdem 02/09
- danilocarlosem 02/09



