B4A Library SD: BT Printer (Bluetooth)

(No WRAP, No Java Only B4A)

BT_Printer
library allows you to print text and image to a bluetooth thermal printers with ESC/POS language
(Here for B4J, Here for B4i)

To print the QR CODES with your BT thermal printer you can create an image containing the QR code with the help of the @Erel library (here) or can use library of @Johan Schoeman (here)

Required: B4A 8.8+ and Serial Library 1.30+
Make sure the library meets all your needs, is compatible with the printer you need to use.


To try print with the demo version you can only use the FlushAndClose command which lasts 14 days and then disables.
The full version of the library will be issued to those making a donation (Contact me in private before making a donation). In the donation indicate the library you want and your NickName. Those requesting the full version will receive updates for 3 months.


Video1.gif
upload_2018-9-2_17-24-41.png



SD_BT_Printer

Author:
Star-Dust
Version: 0.21
  • BT_Printer
    Note: AddPermission(android.permission.ACCESS_COARSE_LOCATION)
    • Events:
      • BluetoothIsDisabled
      • ConnectedToPrint (Success As Boolean)
      • DataReceived (Buffer() As Byte)
      • DisconnectToPrint (Mac As String)
      • DiscoveryComplete (Printers As Map)
      • DiscoveryFinished
      • DiscoveryNewPrinter (PrintedFound As Map, DeviceClass As Int)
      • DiscoveryNoDeviceFound
      • ErrorDiscovery
      • ListPrinterAssociated (ListNameAndMac As Map)
      • SendingError (Mac As String)
      • SendTerminated
    • Fields:
      • Const_AUDIO_VIDEO As Int
      • Const_COMPUTER As Int
      • Const_HEALTH As Int
      • Const_IMAGING As Int
      • Const_MISC As Int
      • Const_NETWORKING As Int
      • Const_PERIPHERAL As Int
      • Const_PHONE As Int
      • Const_TOY As Int
      • Const_UNCATEGORIZED As Int
      • Const_WEARABLE As Int
    • Functions:
      • AddBuffer_ArrayByte (B As Byte()) As String
      • AddBuffer_BarCode (Code As String) As String
      • AddBuffer_Bitmap (Bmp As Bitmap, ShiftLeft As Int) As String
      • AddBuffer_BitmapAlternativeCoding (Bmp As Bitmap) As String
      • AddBuffer_List_Write (list As List) As String
      • AddBuffer_List_WriteLine (list As List) As String
      • AddBuffer_Tab (ArrayTab As Int()) As String
      • AddBuffer_Write (Text As String) As String
      • AddBuffer_WriteLine (Text As String) As String
      • AddPrintDefineImage As String
      • CenterJustify As String
        after this command calls SendBufferToPrinter
      • ChangeEncoding (EncodingType As String) As String
      • Class_Globals As String
      • ClearBuffer As String
      • Close As String
      • Connected As Boolean
      • DefineImage (Image As Bitmap)
      • flushAllAndClose
      • Initialize (CallBack As Object, EventName As String, EncodingType As String) As String
        Initializes the object. You can add parameters to this method if needed.
      • InitializePrinter As String
      • IsInitialized As Boolean
        Verifica se l'oggetto sia stato inizializzato.
      • LeftJustify As String
        after this command calls SendBufferToPrinter
      • Preview As Bitmap
      • ResetPreViewWidth (NewWidth As Int) As String
      • RightJustify As String
        after this command calls SendBufferToPrinter
      • SearchNewPrinter As String
        select --------------------------------------------
      • SelectFromAssociatedPrinter As String
      • SelectFromMac (Mac As String) As String
      • SendBufferToPrinter
      • SetCodePage (Code As Byte) As String
        es. Printer.SetCodePage(06) for umlauts char
    • Properties:
      • CodeTable
        es. printer.setCodeTable(Ecoding.Code_WPC1252)
        aftet this command calls SendBufferToPrinter
      • Spacing
        after setSpacing command calls SendBufferToPrinter
  • ESC_POS
    Code module
    Subs in this code module will be accessible from all modules.
    • Fields:
      • BoldOff As String
      • BoldOn As String
      • DoubleOff As String
      • DoubleOn As String
      • FontA_Bold As String
      • FontA_DoubleHight As String
      • FontA_DoubleWide As String
      • FontA_DoubleWideHeight As String
      • FontA_Normal As String
      • FontB_Bold As String
      • FontB_DoubleHeight As String
      • FontB_DoubleWide As String
      • FontB_DoubleWideHeight As String
      • FontB_Normal As String
      • Horizzontal As String
      • InitializePrinter As String
      • ItalicFontOff As String
      • ItalicFontOn As String
      • NoUnderline As String
      • QueryErrorCauses As String
      • QueryOfflineCauses As String
      • QueryPaperStatus As String
      • QueryPrinterStatus As String
      • Underline1 As String
      • Underline2 As String
      • Vertical As String
    • Functions:
      • Process_Globals As String
  • Encoding
    Code module
    Subs in this code module will be accessible from all modules.
    • Fields:
      • Chinese As String
      • ChineseS As String
      • Code_PC437 As Int
      • Code_PC850 As Int
      • Code_PC857 As Int
      • Code_PC858 As Int
      • Code_PC860 As Int
      • Code_PC863 As Int
      • Code_WPC1252 As Int
      • DOS_Latin_1 As String
      • IBM_PC As String
      • ISO8859 As String
      • UTF8 As String
      • Windows1252 As String
    • Functions:
      • Process_Globals As String
 

Attachments

  • Sample1.zip
    10.2 KB · Views: 1,372
  • SD_BT_Printer DEMO 0.21.zip
    21.8 KB · Views: 5
Last edited:

Star-Dust

Expert
Licensed User
Some Explanations on the new version
In the previous version of the library I used only FlushAndClose and each print required the connection. This is because the SendBufferToPrinter command in different printers fails with the second sending of data. So if you send data on several occasions you had to reconnect

Now I have created a system that allows you to use SendBufferToPrinter, in case the printer disconnects or goes into error, automatically try again to connect and print for another 2 attempts.

I always suggest waiting a few seconds between the first and the second. The bluetooth printer (and the BT connection) takes a few seconds to synchronize​

New property
Connected
This property is used to know the connection status with the printer​
New Event
DisconnectToPrint (Mac AsString)
This event is raised if a print submission fails and the connection is compromised. But only after trying twice reconnection and printing​
 
Last edited:

Star-Dust

Expert
Licensed User
Updated examples for Android 7 (With RuntimePermissions request )
 

Lello1964

Well-Known Member
Licensed User
Longtime User
i'm using SearchNewPrinter function, but if no printer is found i see only "No device found" toast message, but havn't an Event to know thath.
Can you help me ?
 

Star-Dust

Expert
Licensed User

Star-Dust

Expert
Licensed User
Use the FlushAndClose command to print instead of SendBufferToPrinter. The flushAllAndClose command lasts for 7 days and then is disabled. Send to the printer and close the connection
 

acidorus

Member
Licensed User
Longtime User
Hello .. Good evening..
is there any way I can tell if the printer has finished printing the entire buffer?
because I give the command 'flushAllAndClose'. and it activates the SendTerminated event even without having finished printing the entire buffer
sorry the English. I used google translator.

ex:

Sub bt_priter_functions_ConnectedToPrint
ToastMessageShow(mensagens.content_msg_conect_success_bt, True)
bt_priter_functions.Connected
For Each mp_modalit As Map In Main.lst_print_infos
Dim r As Map = mp_modalit.Get("r")
' Log( r.Get("dados"))
bt_priter_functions.AddBuffer_WriteLine( r.Get("dados"))
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
Next
bt_priter_functions.AddBuffer_WriteLine(mutil.Align_miniPrinters(mensagens.system_version & mensagens.update_version,mutil.ALING_CENTER))
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
bt_priter_functions.AddBuffer_WriteLine(mutil.Align_miniPrinters(Main.current_date &" "& DateTime.Time(DateTime.Now),mutil.ALING_CENTER))
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
bt_priter_functions.AddBuffer_WriteLine(CRLF & CRLF & CRLF)
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
' Log(bt_priter_functions)
' bt_priter_functions
bt_priter_functions.flushAllAndClose
End Sub

Sub bt_priter_functions_SendTerminated
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
bt_priter_functions.Close
bluetooth_functions.TurnBluetoothOff
' Log(bt_priter_functions.Preview.Height)
pnl_option_send_print_poule.Visible = False
' Activity_Pause (True)
Activity.Finish
StartActivity(Main)
End Sub
 

Star-Dust

Expert
Licensed User
Hello .. Good evening..
is there any way I can tell if the printer has finished printing the entire buffer?
because I give the command 'flushAllAndClose'. and it activates the SendTerminated event even without having finished printing the entire buffer
sorry the English. I used google translator.

ex:

Sub bt_priter_functions_ConnectedToPrint
ToastMessageShow(mensagens.content_msg_conect_success_bt, True)
bt_priter_functions.Connected
For Each mp_modalit As Map In Main.lst_print_infos
Dim r As Map = mp_modalit.Get("r")
' Log( r.Get("dados"))
bt_priter_functions.AddBuffer_WriteLine( r.Get("dados"))
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
Next
bt_priter_functions.AddBuffer_WriteLine(mutil.Align_miniPrinters(mensagens.system_version & mensagens.update_version,mutil.ALING_CENTER))
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
bt_priter_functions.AddBuffer_WriteLine(mutil.Align_miniPrinters(Main.current_date &" "& DateTime.Time(DateTime.Now),mutil.ALING_CENTER))
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
bt_priter_functions.AddBuffer_WriteLine(CRLF & CRLF & CRLF)
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
' Log(bt_priter_functions)
' bt_priter_functions
bt_priter_functions.flushAllAndClose
End Sub

Sub bt_priter_functions_SendTerminated
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
bt_priter_functions.Close
bluetooth_functions.TurnBluetoothOff
' Log(bt_priter_functions.Preview.Height)
pnl_option_send_print_poule.Visible = False
' Activity_Pause (True)
Activity.Finish
StartActivity(Main)
End Sub
Unfortunately, the printer's bluetooth channel only receives but not answers like the print end.
So the SendTerminate event refers to the completion of the submission.
Otherwise it would be called PrintingTerminated

I'm so sorry
 

acidorus

Member
Licensed User
Longtime User
Good morning ..
when I make several prints in a row, it shows this message in Log "sending message to waiting queue (btconnection_connected)" and does not print

B4X:
Sub Class_Globals
    Private bluetooth_functions   As Toggle
    Private bt_priter_functions      As BT_Printer
    Private retono_print     As Int
    
    Private int_count_time_window As Int = 0
    Private tempo_visualiza_impressao  As Timer
    Private time_finish  As Int
        
    Dim qr As QRcode
    Dim bm As Bitmap
End Sub

Public Sub Initialize(temp_milisecon As Int)
    tempo_visualiza_impressao.Initialize("tempo_visualiza_impressao",10000)
    tempo_visualiza_impressao.Enabled = True
    
    time_finish = temp_milisecon
    int_count_time_window = 0
    retono_print = 0
    bt_priter_functions.Initialize(Me,"bt_priter_functions",Encoding.UTF8)
    bt_priter_functions.Close
    
    Dim ImpPadrao As String
    If File.Exists(File.DirDefaultExternal,"ConfImp.cfg") Then
        ImpPadrao = File.GetText(File.DirDefaultExternal, "ConfImp.cfg") ' default printer mac
        bt_priter_functions.ClearBuffer
        bt_priter_functions.SelectFromMac(ImpPadrao)
        bt_priter_functions.Connected
        qr.Initialize
        bm = qr.drawQRCode(Main.str_url_link)
    End If
End Sub

Sub tempo_visualiza_impressao_Tick
    If  retono_print > 0 Then
        int_count_time_window = int_count_time_window + 1
        Log(int_count_time_window)
        If int_count_time_window > time_finish Then
            bt_priter_functions.flushAllAndClose
        End If
    End If
End Sub

Sub bt_priter_functions_ListPrinterAssociated (ListNameAndMac As List)
End Sub

Sub bt_priter_functions_DiscoveryNewPrinter (Print As NameAndMac)
End Sub

Sub bt_priter_functions_DiscoveryFinished
End Sub

Sub bt_priter_functions_DiscoveryNoDeviceFound
    ToastMessageShow("Device not found",True)
End Sub

Sub bt_priter_functions_ConnectedToPrint
    Dim is_qr_code As Boolean = False
    retono_print = 1
    bt_priter_functions.Connected
    Log(Main.lst_print_infos.Size)
    For Each mp_modalit As Map In Main.lst_print_infos
        Dim r As Map = mp_modalit.Get("r")
        If IsNumber( r.Get("dados")) Then
            Dim int_dados As Int = r.Get("dados")
            If int_dados = -11 Then
                is_qr_code = True
            End If
        Else
            is_qr_code = False
        End If
        
        If is_qr_code = True Then
            bt_priter_functions.AddBuffer_Bitmap(bm,95)
            bt_priter_functions.SendBufferToPrinter
            bt_priter_functions.ClearBuffer
        Else
            bt_priter_functions.AddBuffer_WriteLine( r.Get("dados"))
            bt_priter_functions.SendBufferToPrinter
            bt_priter_functions.ClearBuffer
        End If
    Next
    bt_priter_functions.AddBuffer_WriteLine(mutil.Align_miniPrinters(mensagens.system_version & mensagens.update_version,mutil.ALING_CENTER))
    bt_priter_functions.SendBufferToPrinter
    bt_priter_functions.ClearBuffer
    bt_priter_functions.AddBuffer_WriteLine(CRLF  & CRLF & CRLF)
    bt_priter_functions.SendBufferToPrinter
    bt_priter_functions.ClearBuffer
End Sub

Sub bt_priter_functions_SendTerminated
    bt_priter_functions.SendBufferToPrinter
    bt_priter_functions.ClearBuffer
End Sub
 

Star-Dust

Expert
Licensed User
Why empty the buffer immediately after sending the print?
It is not necessary, it will be emptied automatically, but if you want to do it you have to wait a few seconds (maybe with the command Sleep)

B4X:
bt_priter_functions.SendBufferToPrinter
bt_priter_functions.ClearBuffer
 

acidorus

Member
Licensed User
Longtime User
I did this because of a printer buffer problem. if I send a lot of things sometimes it would not print .. I'll try to use sleep, and see if it solves ..
Thank you for your attention
 

Star-Dust

Expert
Licensed User
Often if they have trouble with the printer buffer, in addition to the fact that it is not possible to know when it has received all the data nor when it has completed printing.

Not having these feedback we usually use pauses and a few seconds to make sure that the buffer has all been transferred now that the print has already been done
 

Star-Dust

Expert
Licensed User
Update rel 0.12
Required Serial library 1.30+

DiscoveryNewPrinter (Print As NameAndMac, DeviceClass As Int)
When it raises the DiscoveryNewprinter event it also identifies the class of the found device.
You also find a list of constants that represent a specific type of device
B4X:
Sub BTPrinter_DiscoveryNewPrinter (Print As NameAndMac, DeviceClass As Int)
    ' Find new printer
    If DeviceClass=Printer.Const_PERIPHERAL Then
        ListView1.AddSingleLine2(Print.Name,Print.Mac)
    End If
End Sub

Those who have purchased the complete library can ask for an update
 
Last edited:

rkmoray

Active Member
Licensed User
Longtime User
Your library is working great, thank you.
I do have 1 more question however.
The receipt I am printing on has a left perforation, and I want to print something vertically (receipt # to be torn off) between the left edge and the perf.
How do I print something vertically?
 

Star-Dust

Expert
Licensed User
Your library is working great, thank you.
I do have 1 more question however.
The receipt I am printing on has a left perforation, and I want to print something vertically (receipt # to be torn off) between the left edge and the perf.
How do I print something vertically?
Unfortunately, the Bluetooth printer does not provide vertical printing.

The BTs do not work like the Ink-Jet or Laser printers that the text is transformed into graphics and then sent, but it works like the Needles printers, ie the text is sent as UTF-8 (or other text encoding formats)

So the only way to have text vertically and convert the text into a bitmap and send it to the printer, but this will understand how complicated and lengthens transmission and printing times.
 
Top