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: 2,987
Last edited:

sfsameer

Well-Known Member
Licensed User
Longtime User
We have a modified SDK that prints to WIFI + Bluetooth + USB (English, Arabic or any language you send to the printer) in the project below :

 

Urishev

Member
Licensed User
Longtime User
Dear Sir Agraham
Thanks for your reply. I did as you advised and everything worked out. Strange ESC / POS protocol. It can print images and cannot print primitive lines.
I would be glad to receive one more piece of advice from you. How do I print an image rotated 90 degrees?
bmp = bmp.Rotate (90) - doesn't work
 

Urishev

Member
Licensed User
Longtime User
In your code, I inserted bmp = bmp.Rotate (90) and it doesn't work:
bmp.InitializeResize(File.DirAssets, "F-35Brefuel.jpg", 576, 512, True) 'ignore
bmp = bmp.Rotate(90)'
' Convert the RGB image to one with luminance values
Dim myimage As AnImage = Printer1.ImageToBWIMage(bmp)
 

mmanso

Active Member
Licensed User
Longtime User
We have a modified SDK that prints to WIFI + Bluetooth + USB (English, Arabic or any language you send to the printer) in the project below :


It that code "sharable"?

Thanks.
 

sfsameer

Well-Known Member
Licensed User
Longtime User
It that code "sharable"?

Thanks.
unfortunately not for free :(
because it took us a really long time to develop it (3 months) so we are selling the source code of the restaurant POS included the printing sdk :)
 

Urishev

Member
Licensed User
Longtime User
Thanks, the image is rotated thanks to your hint. However, the image was printed small, not the full width of the printer paper
Another problem arose how to print the image at the maximum size allowed by the printer.
 

agraham

Expert
Licensed User
Longtime User
how to print the image at the maximum size allowed by the printer
That's what this line in the demo does. You need to adjust the sizes to suit the printer and allow for rotation.
B4X:
    ' Load an image to print and resize it to the maximum mage dimensions for the printer
    bmp.InitializeResize(File.DirAssets, "F-35Brefuel.jpg", 576, 512, True) 'ignore
 

Urishev

Member
Licensed User
Longtime User
I tried to print the image "in length", after rotation by 90. The first button "Image" fails, the second button "Image" prints successfully. I noticed that the ratio of the width and height of the print corresponds to the ratio of the height and width of the image (1280 * 1024). Knowing the maximum print width = 576, we calculate the maximum length: 576 * (1280/1024) = 720.
bmp = bmp.Resize (576, 720, True)
And the image of the plane is printed in maximum dimensions (in length) in all its glory.
I am grateful to Mr. Agraham for his wonderful Bluetooth Class.
 

Inman

Well-Known Member
Licensed User
Longtime User
This class has been a blessing for me especially during Covid days when there was a sudden spike for delivery based apps where executives print the receipt on the spot. I develop my apps on a Sunmi V1s device which has a printer integrated along with a touchscreen and it works great. But my last couple of clients actually use a phone and an external Bluetooth printer and occasionally they are getting the error below.

escpos error2.jpg


The java code causing the error is below and line number 6 where the actual error is thrown is highlighted

Java:
public String  _serial1_connected(boolean _success) throws Exception{
 //BA.debugLineNum = 1198;BA.debugLine="Private Sub Serial1_Connected (Success As Boolean)";
 //BA.debugLineNum = 1199;BA.debugLine="If Success Then";
if (_success) {
 //BA.debugLineNum = 1200;BA.debugLine="Astream.Initialize(Serial1.InputStream, Serial1.";
_astream.Initialize(ba,_serial1.getInputStream(),_serial1.getOutputStream(),"astream");
 //BA.debugLineNum = 1201;BA.debugLine="Connected = True";
_connected = __c.True;
 //BA.debugLineNum = 1202;BA.debugLine="ConnectedError = \"\"";
_connectederror = "";
 //BA.debugLineNum = 1203;BA.debugLine="Serial1.Listen";
_serial1.Listen(ba);
 }else {
 //BA.debugLineNum = 1205;BA.debugLine="Connected = False";
_connected = __c.False;
 //BA.debugLineNum = 1206;BA.debugLine="ConnectedError = LastException.Message";
_connectederror = __c.LastException(getActivityBA()).getMessage();
 };
 //BA.debugLineNum = 1208;BA.debugLine="If SubExists(CallBack, EventName & \"_Connected\")";
if (__c.SubExists(ba,_callback,_eventname+"_Connected")) {
 //BA.debugLineNum = 1209;BA.debugLine="CallSub2(CallBack, EventName & \"_Connected\", Suc";
__c.CallSubNew2(ba,_callback,_eventname+"_Connected",(Object)(_success));
 };
 //BA.debugLineNum = 1211;BA.debugLine="End Sub";
return "";
}

This comes occasionally and they have to exit and come back to fix this. Any idea how we can prevent this?
 

agraham

Expert
Licensed User
Longtime User
Any idea how we can prevent this?
You can't I'm afraid. It looks like a low level device problem. If the Connected event is raised then the streams should be available. Perhaps it's a marginal timing thing. You could try catching the error, sleeping for 100mS or so then retry, or do an initial sleep on entry to the event and see if that makes a difference.
 

Inman

Well-Known Member
Licensed User
Longtime User
You can't I'm afraid. It looks like a low level device problem. If the Connected event is raised then the streams should be available. Perhaps it's a marginal timing thing. You could try catching the error, sleeping for 100mS or so then retry, or do an initial sleep on entry to the event and see if that makes a difference.

Thanks. I will try that.
 

Inman

Well-Known Member
Licensed User
Longtime User
Please let us know if you have found an working solution.

I will. I have sent the modified version to my clients yesterday, after adding the Sleep mentioned by agraham. Let's see how it goes.
 

Inman

Well-Known Member
Licensed User
Longtime User
Please let us know if you have found an working solution.

Just wanted to share an update here. I first tried adding a Sleep on entry to the function but my clients reported seeing the error again. So like agraham's other suggestion I added a Try Catch to detect the error, Sleep for 100ms and then try connecting again. It has been 3 days now and so far no one has reported any issues with printing. Fingers crossed. 🤞

Here is the modified code.
B4X:
Private Sub Serial1_Connected (Success As Boolean)
    If Success Then
        Try
            Astream.Initialize(Serial1.InputStream, Serial1.OutputStream, "astream")
            Connected = True
            ConnectedError = ""
            Serial1.Listen
        Catch
            Sleep(100)
            Connect
        End Try
    Else
        Connected = False
        ConnectedError = LastException.Message
    End If
    If SubExists(CallBack, EventName & "_Connected") Then
        CallSub2(CallBack, EventName & "_Connected", Success)
    End If
End Sub
 

lelelor

Member
Licensed User
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

hello, thanks for this very useful app, I didn't understand when and how to use "IBM437" or "UTF8" and the codepages.
I have to be able to print the "€" symbol I made 2 prints with CP858 (the "€" symbol is in position 213) and in one I put "UTF8" and in the other "IBM437".
in "UTF8" the "€" symbol is printed as circled in the other one is ignored.
question: what encoding should I set to get "€"?
Thank you
20210708_105552.jpg
 
Top