Integrando impressora térmica bluetooth portátil com aplicativos Delphi Multi-Device
Neste post iremos implementar um aplicativo mobile para efetuar a impressão diretamente em uma impressora térmica bluetooth sem utilização alguma de SDKs de terceiros, tudo 100% Delphi nativo. No exemplo iremos focar apenas nos métodos necessários para demonstrarmos a integração.
Postado a pouco tempo, foi visto como efetuar a integração de seu aplicativo mobile feito em Delphi com uma impressora bluetooth utilizando seu SDK feito em java. Esse modelo de integração é interessante quando precisamos utilizar alguma funcionalidade especifica do fabricante. http://community.embarcadero.com/blog-drafts?view=entry&id=8616
Em sua maioria estas impressoras trabalham da mesmo forma que a “moderníssima” Impressora Epson LX 300 (se você não conhece este modelo de impressora peça auxilio à um adulto).
Nesse passado não muito distante, a impressão poderia ser realizada através do envio de comandos ESC/POS para a porta paralela onde a impressora estava conectada. E é desta mesma forma que iremos proceder, mas ao invés de enviarmos comandos para a porta paralela iremos envia-los através de uma porta Bluetooth.
Como todo bom Delpheiro você deve estar pensando que o Delphi provavelmente já tenha um componente que fará a conexão Bluethooth para nós e depois só precisaremos enviar os comandos de impressão.
E como todo bom Delfeiro, você está certo!
O Delphi possui o componente TBluetooth, que encapsula todo o mecanismos de comunicação Bluetooth do seu dispositivo mobile. É ele por exemplo que é responsável por listar os dispositivos pareados em nosso mobile, alem de efetuar a conexão com os dispositivo bluetooth e enviar comandos para este dispositivo.
Então vamos por a mão massa:
Para nosso exemplo crie uma aplicação multi-device em branco. (File\New\Mult-Device Application\Bank Application).
Antes de tudo devemos configurar o projeto para que o aplicativo tenha permissão para acessar o Bluetooth do mobile, então no menu Project\Options\Uses Permissions, habilite as opções Bluetooth e Bluetooth admin.
Coloque um componente TBluetooth no formulário e altere sua propriedade Enable para True. Em nosso exemplo deixaremos o componente sempre ativo.
Coloque um ComboBox, no qual iremos listar os dispositivos Bluetooth pareados em nosso mobile.
O comando é bem simples, o método PairedDevices do componente TBluetooth retorna a lista de dispositivos pareados, desta forma só precisamos percorrer a lista e popular o nosso ComboBox.
procedure TfrmImpressora.ListarDispositivosPareadosNoCombo; var lDevice: TBluetoothDevice; begin ComboBox1.Clear; for lDevice in Bluetooth1.PairedDevices do begin ComboBox1.Items.Add(lDevice.DeviceName); end; end;
Coloque um botão para efetuar a chamada deste código.
Assim quando você clicar neste botão o ComboBox será atualizado com a lista de dispositivos pareados.
Vamos para nossa segunda funcionalidade, a conexão com o dispositivo.
Primeiramente é preciso selecionar o dispositivo que será conectado. Um dispositivo Bluetooth é encapsulado pela classe TBluetoothDevice. Criaremos uma função que nos retorne o dispositivo usando como parâmetro seu nome, que estará selecionado no ComboBox.
function TfrmImpressora.ObterDevicePeloNome(pNomeDevice: String): TBluetoothDevice; var lDevice: TBluetoothDevice; begin Result := nil; for lDevice in Bluetooth1.PairedDevices do begin if lDevice.DeviceName = pNomeDevice then begin Result := lDevice; end; end; end;
As conexões Bluetooth são encapsuladas por uma classe Socket, a TBluetoothSocket. Esta classe é instanciada por um TBluetoothDevice. Executando o método ObterDevicePeloNome, teremos como retorno um TBluetoothDevice. E este objeto possui o método CreateClientSocket que irá criar nosso objeto Socket.
FSocket := lDevice.CreateClientSocket...
Cada tipo de dispositivo Bluetooth pode utilizar um tipo de Socket diferente. Por exemplo, um fone se comunica de uma forma diferente que uma impressora, mas ambos são Bluetooth, e estas configurações são dadas por um parâmetro UUID no método de criação do Socket.
O UUID é um identificador único universal, por exemplo, seja qual for o fabricante de fones Bluetooth eles irão utilizar o mesmo UUID para esta comunicação. (https://en.wikipedia.org/wiki/Universally_unique_identifier)
As Impressoras BT usam uma SerialPortServiceClass, que é definida pelo UUID 00001101-0000-1000-8000-00805F9B34FB.
const UUID = '{00001101-0000-1000-8000-00805F9B34FB}';
Defina uma variável global FSocket: TBluetoothSocket para armazenar o objeto de conexão, e assim poder ser utilizados em outros métodos, como no de impressão.
function TfrmImpressora.ConectarImpressora(pNomeDevice: String): boolean; var lDevice: TBluetoothDevice; begin Result := False; lDevice := ObterDevicePeloNome(pNomeDevice); if lDevice <> nil then begin FSocket := lDevice.CreateClientSocket(StringToGUID(UUID), False); if FSocket <> nil then begin FSocket.Connect; Result := FSocket.Connected end; end; end;
Em um TButton chame o método ConectarImpressora passando como parãmetro o dispositivo selecionado no ComboBox, como no exemplo abaixo:
procedure TfrmImpressora.btnConectarClick(Sender: TObject); begin if (ComboBox1.Selected <> nil) and (ComboBox1.Selected.Text <> '') then begin if ConectarImpressora(ComboBox1.Selected.Text) then begin Label1.Text := 'Conectado'; end else begin Label1.Text := 'Desconectado'; end; end else begin ShowMessage('Selecione um dispositivo'); end; end;
Para finalizar basta enviarmos através do método SendData do Socket os comandos da impressora (A lista de comandos geralmente acompanham o manual do produto).
procedure TfrmImpressora.btnImprimirClick(Sender: TObject); begin if (FSocket <> nil) and (FSocket.Connected) then begin FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(64))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(97) + chr(1))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(33) + chr(8))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(33) + chr(16))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(33) + chr(32))); FSocket.SendData(TEncoding.UTF8.GetBytes('Delphi Berlin' + chr(13))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(100) + chr(1))); FSocket.SendData(TEncoding.UTF8.GetBytes('Delphi Berlin' + chr(13))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(100) + chr(1))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(33) + chr(0))); FSocket.SendData(TEncoding.UTF8.GetBytes('Utilizando TBluetooth ')); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(100) + chr(1))); FSocket.SendData(TEncoding.UTF8.GetBytes('Utilizando TBluetooth ')); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(100) + chr(1))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(97) + chr(0))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(100) + chr(5))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(29) + chr(107) + chr(2) + '7896006259701' + chr(0))); FSocket.SendData(TEncoding.UTF8.GetBytes(chr(27) + chr(100) + chr(5))); end; end;
Neste método fizemos o envio de diversos comandos de impressão como, quebra de linha, mudança de fontes e impressão de um código de barras.
A partir deste momento seu aplicativo já está integrado com nossa impressora Bluetooth, e sem utilizar qualquer outra biblioteca que não acompanhe a instalação básica do Delphi.
Segue abaixo uma lista de UUID de vários tipos de conexões bluetooth:
ServiceDiscoveryServerServiceClassID= ‘{00001000-0000-1000-8000-00805F9B34FB}’;
BrowseGroupDescriptorServiceClassID = ‘{00001001-0000-1000-8000-00805F9B34FB}’;
PublicBrowseGroupServiceClass = ‘{00001002-0000-1000-8000-00805F9B34FB}’;
SerialPortServiceClass = ‘{00001101-0000-1000-8000-00805F9B34FB}’;
LANAccessUsingPPPServiceClass = ‘{00001102-0000-1000-8000-00805F9B34FB}’;
DialupNetworkingServiceClas = ‘{00001103-0000-1000-8000-00805F9B34FB}’;
IrMCSyncServiceClass = ‘{00001104-0000-1000-8000-00805F9B34FB}’;
OBEXObjectPushServiceClass= ‘{00001105-0000-1000-8000-00805F9B34FB}’;
OBEXFileTransferServiceClass = ‘{00001106-0000-1000-8000-00805F9B34FB}’;
IrMCSyncCommandServiceClass= ‘{00001107-0000-1000-8000-00805F9B34FB}’;
HeadsetServiceClass = ‘{00001108-0000-1000-8000-00805F9B34FB}’;
CordlessTelephonyServiceClass = ‘{00001109-0000-1000-8000-00805F9B34FB}’;
AudioSourceServiceClass = ‘{0000110A-0000-1000-8000-00805F9B34FB}’;
AudioSinkServiceClass= ‘{0000110B-0000-1000-8000-00805F9B34FB}’;
AVRemoteControlTargetServiceClass = ‘{0000110C-0000-1000-8000-00805F9B34FB}’;
AdvancedAudioDistributionServiceClass = ‘{0000110D-0000-1000-8000-00805F9B34FB}’;
AVRemoteControlServiceClass= ‘{0000110E-0000-1000-8000-00805F9B34FB}’;
VideoConferencingServiceClass = ‘{0000110F-0000-1000-8000-00805F9B34FB}’;
IntercomServiceClass = ‘{00001110-0000-1000-8000-00805F9B34FB}’;
FaxServiceClass = ‘{00001111-0000-1000-8000-00805F9B34FB}’;
HeadsetAudioGatewayServiceClass= ‘{00001112-0000-1000-8000-00805F9B34FB}’;
WAPServiceClass = ‘{00001113-0000-1000-8000-00805F9B34FB}’;
WAPClientServiceClass = ‘{00001114-0000-1000-8000-00805F9B34FB}’;
PANUServiceClass = ‘{00001115-0000-1000-8000-00805F9B34FB}’;
NAPServiceClass = ‘{00001116-0000-1000-8000-00805F9B34FB}’;
GNServiceClass = ‘{00001117-0000-1000-8000-00805F9B34FB}’;
DirectPrintingServiceClass = ‘{00001118-0000-1000-8000-00805F9B34FB}’;
ReferencePrintingServiceClass = ‘{00001119-0000-1000-8000-00805F9B34FB}’;
ImagingServiceClass= ‘{0000111A-0000-1000-8000-00805F9B34FB}’;
ImagingResponderServiceClass = ‘{0000111B-0000-1000-8000-00805F9B34FB}’;
ImagingAutomaticArchiveServiceClass = ‘{0000111C-0000-1000-8000-00805F9B34FB}’;
ImagingReferenceObjectsServiceClass = ‘{0000111D-0000-1000-8000-00805F9B34FB}’;
HandsfreeServiceClass = ‘{0000111E-0000-1000-8000-00805F9B34FB}’;
HandsfreeAudioGatewayServiceClass = ‘{0000111F-0000-1000-8000-00805F9B34FB}’;
DirectPrintingReferenceObjectsServiceClass = ‘{00001120-0000-1000-8000-00805F9B34FB}’;
ReflectedUIServiceClass = ‘{00001121-0000-1000-8000-00805F9B34FB}’;
BasicPringingServiceClass = ‘{00001122-0000-1000-8000-00805F9B34FB}’;
PrintingStatusServiceClass= ‘{00001123-0000-1000-8000-00805F9B34FB}’;
HumanInterfaceDeviceServiceClass = ‘{00001124-0000-1000-8000-00805F9B34FB}’;
HardcopyCableReplacementServiceClass = ‘{00001125-0000-1000-8000-00805F9B34FB}’;
HCRPrintServiceClas = ‘{00001126-0000-1000-8000-00805F9B34FB}’;
HCRScanServiceClass= ‘{00001127-0000-1000-8000-00805F9B34FB}’;
CommonISDNAccessServiceClass = ‘{00001128-0000-1000-8000-00805F9B34FB}’;
VideoConferencingGWServiceClass = ‘{00001129-0000-1000-8000-00805F9B34FB}’;
UDIMTServiceClass = ‘{0000112A-0000-1000-8000-00805F9B34FB}’;
UDITAServiceClass = ‘{0000112B-0000-1000-8000-00805F9B34FB}’;
AudioVideoServiceClass = ‘{0000112C-0000-1000-8000-00805F9B34FB}’;
SIMAccessServiceClass = ‘{0000112D-0000-1000-8000-00805F9B34FB}’;
PnPInformationServiceClass= ‘{00001200-0000-1000-8000-00805F9B34FB}’;
GenericNetworkingServiceClass = ‘{00001201-0000-1000-8000-00805F9B34FB}’;
GenericFileTransferServiceClass = ‘{00001202-0000-1000-8000-00805F9B34FB}’;
GenericAudioServiceClass= ‘{00001203-0000-1000-8000-00805F9B34FB}’;
GenericTelephonyServiceClass = ‘{00001204-0000-1000-8000-00805F9B34FB}’;
Qual modelo de impressora posso usar esse código?
Qualquer impressora Bluetooth que funcione com comandos ESC/POS
onde compro uma impressora igual do video?
Esse eu comprei no aliexpress.com
Este exemplo funcionaria com comandos EPL ou ZPL?
Vai depender da sua impressora… Ok!
Muito bom o material, parabens.
O tutorial é bem bacana e dá um grande ponta-pé inicial, mas seria possível, colocar como comentário, na parte em que faz o envio dos dados para a impressora, o que faz cada conjunto de comandos que estão sendo utilizados?? Tentei isolar cada bloco, mas o resultado é um pouco confuso e não consegui decifrar… o manual da impressora então (Datec DPP-250) tem todos os códigos, mas entender como usá-los está bem complicado….
Agradeço sua ajuda.
Excelente Alan, show de bola, parabéns mais uma vez.
Opa funcionou que é uma maravilha. Agora estou com problema na impressão de caracteres especiais, já tentei acho que todos os comandos esc, mas não consegui resolver. Teve esse problema?
parabens Allan…. coloquei outra impressora bluetooth seguindo sua dica e funcionou….
Não imprime nada, rodei tanto com o projeto para download quanto com meu próprio projeto, mesmo assim não imprime nada, pisca os leds azuis na impressora mas não sai impressão. Alguém pode me ajudar?
Se estiver utilizando a impressora DPP-250 veja se as configurações da mesma estão conforme essas do vídeo: https://www.youtube.com/watch?v=mxLrfto0_oE
Otimo artigo parabéns!
Aqui na minha impressora não saiu o código de barras e após a impressão do texto eu preciso reiniciá-la para utilizá-la novamente!
O que pode ser?
Obrigado!
Qual o modelo da sua impressora?
Parabéns pelo artigo, muito didático e preciso. Fiz o teu exemplo, utilizei uma DPP250, pareou e conectou, porém não imprime nada. Falta alguma coisa?
Veja se sua impressora está configurada conforme este vídeo: https://www.youtube.com/watch?v=mxLrfto0_oE
Qual comando para a impressora aceitar o QR CODE ?
Isso depende da impressora, tem que olhar no manual da mesma…
Alguem conseguiu fazer a comunicação coma impressora DPP 250, estou a dias tentando fazer essa comunicação mas nada…
Está listando normal e conecnado com a impressora. mas, quando eu tento imprimir seguindo esses comandos esc pos aí. Nao imprime de jeito nenhum ,… nao sei nem mais o que faço …
me ajudem aí pessoal !!
Veja se sua impressora está configurada conforme o este vídeo: https://www.youtube.com/watch?v=mxLrfto0_oE
Boa tarde, preciso que ela imprima direto de um site, como faço?
Tem como? qual delphi utilizado no exemplo acima?
Quanto cobraria para desenvolver o app pra mim que imprima do site que tenho? 99 991385001 whats
vou te chamar no WhatsApp
Amigo, preciso de um app que abra meu site e dentro imprima, quanto faz???
Funcionou perfeitamente, parabéns
Qual seria o comando para imprimir um QRCODE ao invés do código de Barras?
Depende da impressora, teria que ver no manual dela…
Estou tentando imprimir seguindo este tutorial e a DPP-250 não imprime, conecta Bluetooth mas não imprime (fica piscando azul, marcando conexão).
Alguém sabe o motivo?
Verifique se sua impressora está configurada conforme este vídeo: https://www.youtube.com/watch?v=mxLrfto0_oE
Seguindo todos os passos do vídeo, o meu só fica assim:
http://666kb.com/i/dqebocyddjgcvggns.jpg
Refiz umas 5 vezes (voltei p fábrica e tentei de nv), mas não fica igual ao do vídeo.
O do vídeo tem os 4 primeiros OFF, o meu fica 3 OFF e 1 ON
Esses 4 primeiros você deve ajustar manualmente, remove a bateria da impressora e ajusta eles ok!
Alangei, vc salvou essa etapa do meu projeto! Muito obrigado.
Tenho uma dica: coloque o link do vídeo e esse detalhe do Swicth no tutorial, será de grande ajuda para os futuros delpheiros.
Muito obrigado
Ola meu amigo, você teria um exemplo de como efetuar o ajuste do tamanho do código de barras e um exemplo de emissão de qrcode com esc/pos.
Algumas impressoras possuem a opção de QRCode, tem que ver no manual, mas também podemos mandar como imagem!!!
Para enviar código de barras existe um código usado, como o código para trocar de fonte, vc sabe qual o método utilizado para enviar imagem para a impressora?
Sim, para imprimir um código de barras deve usar comandos específicos para cada tipo de código… vou montar um exemplo simples de impressão de imagens e publicar ok!
Parabéns pelo tutorial. Baita ajuda, dá um norte gigante. Já estava pensando em adicionar SDK da impressora e etc e assim funcionou direto. Existe uma forma de imprimir usando comando de linha coluna?
Vou verificar se existe essa opção…
Oii, essas impressoras bluetooth corta o papel?
Nunca vi nenhum modelo com cortador automático.
Estou usando a impressora intermec pr2, ela conecta porém quando manda imprimir fica piscando a luz e não imprime nada. Já vi um vídeo que está no comentário porém não é o mesmo modelo da impressora que estou usando.
Com certeza deve ser configuração, no manual dela ou na impressão das configurações não tem nada mostrando?
Bom dia Alan!
Muito bom o material. Estou tentando realizar a impressão na vertical(boleto bancário) e não estou conseguindo. Tentei utilizar os comandos, segundo o manual, e mesmo assim não estou conseguindo.
Alguma dica?
Obrigado.
Bom dia!
Tenho um código que gera uma imagem do boleto e manda para impressora…