Supporting label/barcode printers?

Currently with the OpenMRS distribution of PIH we are able to print stickers/labels through dedicated label printers, e.g. to print barcodes. This is done through network-enabled printer that receive print commands from the OpenMRS server running a custom module. These printers are usually located at various points of care.

Do you have a similar setup somewhere? If yes, how does the actual printing technically work?

Hi @cine,

We have not used any label printers yet in any of our implementations.

Can you please share the details (github link?) of custom module which you have used for printing labels.


Hi Vinkesh,

Generically, we have added support for “printing” via the printer module:

We have then added in our own printer implementations on top of this in our distribution modules:

We then have extensions within our registration workflow and actions available from our patient dashboard that enable printing ID cards, Labels, and Wristbands based on these.

@mgoodrich has led most of the work on this and might be able to describe a bit more.

Thanks, Mike

1 Like

We use server-side printing, where the server sends the print commands to a networked printer. Generally, we are operating on a fairly low level: we use Zebra ( printers, and for label and wristband printing we connect with the printer via a socket and send print commands to the printer in it’s native language. Our ID card printing solutions used to work the same way, but for newer ID card printer models, Zebra has provided a Java SDK, so although we still use server-side printing, we use the SDK instead of opening a raw socket.

Re: the links above, the Printer module handles setting up printers, configuring their IP addresses, matching them with specific locations, etc, as well providing the low-level print via socket functionality. In the second link, you can see the printer-specific files that generate the printer-specific commands.

Feel free to take a look and shoot any more questions my way.

Take care! Mark

1 Like

Our label printers provide a HTTP interface which could be use to print label right from JavaScript. Bahmni’s printing part is already based on HTML templates, so I think this could be used to integrate the printer. However when I invoke a Bahmni print job, it already comes up with the (browser) print preview.

This makes perfect sense with “traditional printers”, but I wonder if I could use/reuse/misuse this to also easily hook up our label printer.

But instead of having the print preview popping up, I ideally get a new browser window/tab coming up simply rendering the print template with the current data. As part of the print template I could add the JavaScript required to directly print via HTTP.

Do you see any easy chance so that I could achieve this?

Hi @cine,

Right now there is no easy way (without changing bahmniapps code) to print using ‘untraditional’ printers.


OK. Is there a way to add a custom (HTML) button somewhere in the header? Or at other positions within the forms?

Please take a look at this -

Thanks. I couldn’t find the notion of a ‘custom button’ (either through Bahmni’s printing system or somewhere else), so I assume this doesn’t exist.

I figured out a maybe not-so-good workaround, but this is enough for me as a proof of concept: When I add an window.onload handler in the HTML template, the print preview is not invoked and my custom javascript code to print the label is executed.

1 Like

Cool. So, you are using HTTP post for this? Requirements would be that the printer is on the network, has an IP, and is “visible” to the client? Are you just hardcoding the printer IP into the template, or getting it some other way?


Yes. HTTP POST via Javascript. With hardcoded ZPL code (label printer commands) and hardcoded printer IP. This was mainly to see if it is worthwhile to include such an approach to the list of possible ‘real’ solutions.

1 Like

I just saw this thread. We’re looking into rolling out label printers for printing lab test labels. Ideally, this would print a bar code from the webapp. Can anyone share code that achieves this? Also, what external libraries are you using and what hardware?



I have only limited knowledge in label printing. And within this limited scope I only know printers from Zebra. The good thing is that you don’t need any additional runtime libraries to get them running.

The ‘traditional Zebra way’ to print is through a dedicated and direct communication between (OpenMRS) server and printer. The server opens a socket to the printers IP address (therefore requiring server-to-printer TCP communication) and sends a bunch of ZPL commands. ZPL is the Zebra Printing/programming Language and is made of text-based commands to ‘render’ a certain print job (look here and on the Zebra page itself). Zebra offers a couple of additional tools for design/layout, but I don’t know them. A barcode within ZPL is also just a custom text-based command.

This is how the OpenMRS installation I know do their printing. It shouldn’t be too hard to include this server-side printing approach into the server-component of Bahmni/OpenMRS. But it didn’t look any further than this.

Additionally I’ve seen that newer printers from Zebra offer an HTTP interface. So instead of opening a socket to the printer you could speak HTTP to the embedded web server of each printer and send the ZPL commands over. Just as an evaluation I’ve written the following JavaScript lines which invokes a hard-coded print job on a specific printer (identified by its IP address) straight from the browser:

function wba_demo_print() { var zpl = “^XA^CI28^PW1300^MTT^FO080,40^AUN^FDtest name^FS^FO080,120^AUN^FDWBA100001^FS^FO080,190^ATN^FD20000101M^FS^FO680,40^FB520,1,0,R,0^AUN,140,110^FD123456^FS^FO780,160^ATN^BY4^BCN,150,N^F123456^FS^XZ”; print_this(zpl, “”); }

function print_this(zpl, ip_addr) { var output = document.getElementById(“output”); var url = “http://”+ip_addr+"/pstprnt"; var method = “POST”; var async = true; var request = new XMLHttpRequest();

    request.onload = function () {
            var status = request.status; // HTTP response status, e.g., 200 for "200 OK"
            var data = request.responseText; // Returned data, e.g., an HTML document.
            output.innerHTML = "Status: " + status + "<br>" + data;
    }, url, async);
    request.setRequestHeader("Content-Length", zpl.length);

    // Actually sends the request to the server.


However I’m not sure if such direct client/web browser to printer communication is the best idea (in terms of network topology, stability/reliability and potential abuse). Still: Assuming the WiFi allows client-to-client communication (aka client isolation disabled), it might the simplest thing to get it up and running in smallish installations with only very few printers.


This is a really useful thread. I have linked this to the feature around label and barcode printing in Bahmni. Looks like it is a basic feature needed hence I have upped the priority for this.

Thanks @vsingh - great news! This would be a huge help in getting Bahmni implemented for us at PIH facilities.

For what it’s worth, for the newer ID Card printers from Zebra, instead of sending a command via socket in the printer’s native language, Zebra provides a new Java SDK & API. We have started using this with the Zebra’s latest ID card printers (the label printers still use the old method, though I assume Zebra plans to migrate newer models of the label printers to the SDK as well).

However, although we’d gotten the SDK to work, there have been some issues with it, specifically around graceful error handling–Zebra has been looking into this for us, and recently issued a new version of the SDK with some fixes (we haven’t tested yet thought). So I can’t fully recommend it.

(Also note that we can’t 100% recommend the ID card printers because they tend to jam/break easily, at least under high load. \But the label printers work quite well, and, as Christian mentions, bar code generation is built directly into all the printers)

Take care, Mark

At Ampath we have come up a setup that uses Gnome glabels to create label templates and the uses glabels-batch and a csv to mail merge. glabels-batch produces a pdf file which we send to any cups capable print using the lpr command. This allows us to support any printer for which a cups driver exists without much hustle. We provide a simple api that takes in a json payload and uses it to create the csv to be use by glabels for mail merge. The server also provides and endpoint to query the active printers.Check it out poc-print-server

To add to Emmanuel’s comment, we chose this route for two main reasons.

  1. We are currently implementing a cloud based approach to OpenMRS. Our remote sites are connecting to a central server through a 3G connection. As a result, it seemed less practical to build the print server as a module within OpenMRS given that printing happens locally. Instead, we’ll deploy a node base print server using Hapi as a rest library on the local server at each site. The rest server will contain endpoints for each label (or other document) we would need to print.

  2. As Emmanuel writes, rather than using raw code for a particular printer brand, we are using CUPS which allows us to send pdfs to any cups supported printer. We have so far tested this with a Dymo Turbo 450 with good results. We will soon be testing with a Brother QL 700 series.