B4A Class Bluetooth ESC/POS Printer Class

For the last couple of weeks I have been playing with an 80mm Bluetooth ESC/POS thermal printer I bought off eBay, new and delivered, for the ludicrously cheap price of £20. While the print quality, particularly of images with large areas of black (they are gray due to power supply or thermal dissipation limitations probably), is not great it is adequate. The printer itself seems to be a generic Chinese unit (no surprise there then!) which is re-badged by all and sundry and sold at a remarkably wide range of prices.

Here then is a Printer class that will connect by Bluetooth to the printer and enable access to most of the printer functions, including barcodes and image preparation and printing. The included demo shows the capabilities that are available. To run the demo you will need a paired Bluetooth printer that is switched on. The Printer class uses the BitmapCreator, RandomAccessFile and Serial libraries.

On my printer the only thing that doesn't seem to work properly is QR code generation. Small QR codes don't seem to be able to be decoded by scanners and larger ones look obviously wrong with part of the top of the code replicated at the bottom when printed.

The obvious capabilities missing (so far!) are user defined characters and non-volatile bit images. Also not implemented are some codes that are either duplicates of available commands or ones whose functions I don’t understand.

The class module is included as source code in the demo so you can add any missing capabilities you need. If you add a significant one then please post it for others to play with.

EDIT: Version 2 now posted includes support for creating custom characters. See post #5 for details
 

Attachments

  • BluetoothPrinter_v2.0.zip
    298.6 KB · Views: 3,194
Last edited:

vecino

Well-Known Member
Licensed User
Longtime User
How about:
B4X:
Wait For (printer1.Connect) Complete (Success As Boolean)
java.lang.NullPointerException: Attempt to write to field 'java.lang.Exception anywheresoftware.b4a.BA$SharedProcessBA.lastException' on a null object reference in method 'void anywheresoftware.b4a.BA.setLastException(java.lang.Exception)'
🤔
 

vecino

Well-Known Member
Licensed User
Longtime User
Why do you want to use a Wait For?

This sub is only executed when the printer actually connects or times out

I just need something that should be simple and straightforward but I can't get it, the steps are:

B4X:
Loop until the user answers that he doesn't want to print.
    if not retry then ask: Print?
    if it is retry then don't ask: Print?
    Connect printer
    if not Connection ok then ask "No connection, retry?"
    if connection ok then
        Print
        Disconnect printer
End of loop
 

vecino

Well-Known Member
Licensed User
Longtime User
I have come up with something like this, it looks like it might work for what I need.
I don't know if that loop can bring any problems.

B4X:
iConnected = -1
Printer1.Connect                  
Do While iConnected = -1
  Sleep(0)
Loop

If iConnected=1 Then
  PrintDocu
Else
  ToastMessageShow("Printer Not connected",False)
End If
         

Sub Printer1_Connected( Success As Boolean )
    If Success Then iConectada=1 Else iConectada=0
End Sub
 

Xfood

Expert
Licensed User
I believe if you have any problems, you may never get out of this cycle,
if you really want to use this method I would do something like this to establish a maximum time for the possible exit.

B4X:
iConnected = -1
Dim now As Long =DateTime.now
Printer1.Connect                 
Do While iConnected = -1
  Sleep(0)
If DateTime.now-now>=1000 Then Exit   ' whatever you want'
Loop
 

vecino

Well-Known Member
Licensed User
Longtime User
Hello, I have a question:
In the example program included with the library a reset (printer1.Reset) is done just before printing a text, before printing a barcode, before printing an image, etc.
Is that something necessary, why is it done?
Thank you very much.
 

agraham

Expert
Licensed User
Longtime User
[Name] Select cut mode and cut paper
[Format] ①ASCII GS V m ② ASCII GS V m

①ASCII GS V m
Hex 1D 56 m
Decimal 29 86 m

②ASCII GS V m n
Hex 1D 56 m n
Decimal 29 86 m n

[Range] ① m= 1,49 ② m=66 , 0 <= n <= 255
[Description] Selects a mode for cutting paper and executes paper cutting.

The value of m selects the mode as follows:
1, 49 Partial cut(one point center uncut)
66 Feeds paper(cutting position + [n x(vertical motion unit)]) , and cuts the paper partially(one point center uncut)

[Details for①and②]
·This command is effective only processed at the beginning of a line.

[Note for ①]
·Only the partial cut is available; there is no full cut.
 

f0raster0

Well-Known Member
Licensed User
Longtime User
Good morning, with what code could automatic paper cutting be carried out after a printing operation? Thank you
yes, if your printer support cutting the paper.
I use: Chr(48) = cut the paper
Printer1.WriteString(Chr(48)& CRLF)
 

cwt

Active Member
Licensed User
Longtime User
The example works fine for me - connects to the printer and prints as expected with no errors.

When I add the printer code to my app, I get the below error when attempting to connect to the printer, on same device and printer where the example works:

escposprinter_connect (java line: 247)
java.lang.NullPointerException: Attempt to invoke virtual method 'void anywheresoftware.b4a.BA.setLastException(java.lang.Exception)' on a null object reference
at ikonpro.android.escposprinter._connect(escposprinter.java:247)
at ikonpro.android.sale_new$ResumableSub_B4XPage_MenuClick.resume(sale_new.java:415)
at ikonpro.android.sale_new._b4xpage_menuclick(sale_new.java:304)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:221)
at anywheresoftware.b4a.BA$1.run(BA.java:360)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8376)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:640)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:982)

The crash happens on this line: PairedDevices = Serial1.GetPairedDevices

in the EscPosPrinter module sub: Public Sub Connect As Boolean

I can see no difference between the example app and my app, other than my app is B4XPages and not Activities.
 

cwt

Active Member
Licensed User
Longtime User
Actually, I am using your example almost verbatim in my own code. I call Connect from the title bar menu just as your example does. So the B4XPage has already loaded and displayed.
 

cwt

Active Member
Licensed User
Longtime User
I had not done Printer1.Initialize prior to calling Connect (stupidly). Now I just need to get Bluetooth permissions working but the permissions are not as easy as I expected.
 
Top