Code readingHow-to

Print barcode labels from a vision application without an HMI add-on

Print barcode labels from your vision application: send the decoded string to a network label printer on TCP port 9100 as ZPL, with no HMI printing add-on.

LumaSpec Vision9 min read Share on LinkedIn

On this page 10 sections
  1. 01The decision: one socket, no HMI add-on
  2. 02Where the decoded string comes from
  3. 03The label: ZPL with one placeholder
  4. 04Prove the barcode fits before you order labels
  5. 05Step by step: from accepted read to printed label
  6. 06Who opens the socket: three architectures
  7. 07Checks before the line runs
  8. 08When raw 9100 is the wrong answer
  9. 09Close the loop: prove the label, not just the print
  10. 10Questions

You took the HMI package out of the project — or it never had a printing function — and the line still needs a barcode label for every part the vision system accepts. The fix is not an HMI option. A network label printer that speaks ZPL runs a raw TCP print service, conventionally on port 9100, and prints exactly the bytes you send it. Your vision application, a code reader, or a PLC can open that socket and send a complete label in under 200 bytes. This guide gives you the ZPL job, the arithmetic that proves the barcode fits the printhead, three wiring architectures, and the checks to run before a shift starts.

The decision: one socket, no HMI add-on

Raw TCP printing — the printer world calls it direct-socket printing — hands your bytes to the printer's network service directly: no Windows driver, no spooler, and no Line Printer Daemon in the path. On the printer side the raw print port appears as the documented ip.port setting, shipped on 9100, and the number can be changed there; print-server hardware exposes 9100 for the first printer and 9101 for a second. Your application therefore owns a short ZPL text template, substitutes the decoded string into one placeholder, and writes the result to the printer's address on port 9100.

The HMI stops being a requirement. Panels that can open a socket print their own labels, so printing QR sample labels from an HMI panel remains a valid route where an operator already works from a screen. The raw socket is the route you take when the vision application is the host, because the label format then travels with your code and survives every HMI revision.

Where the decoded string comes from

Anything on the network that produces a decoded string can feed the printer. For code reading at line rate, the fixed code readers catalog covers it: the LS-CRD-0028 reads up to 60 codes/s and delivers its results over Fast Ethernet.

Fixed code readers2560 x 2048 fixed code reader, 30 fps, 60 codes/s, 8 mm lens (LS-CRD-0028)LS-CRD-0028
Interface
Fast Ethernet
Resolution
5 MP
Sensor format
1/1.7"
Shutter
Global
$920.00View part

At bench scale, the MV-ID3013PM-12M-WBN, a compact reader with a 12 mm focal length and a 1.3 MP sensor, hands over the same kind of string.

Fixed code readersHikrobot MV-ID3013PM-12M-WBN 12mm focal length 1.3 MP Compact Industrial Code ReaderMV-ID3013PM-12M-WBN
Interface
Fast Ethernet
Resolution
Up to 3 MP
Shutter
Global
Lens mount
M12
$1,979.00View part

When the printed value comes from inspection rather than a code — an OCR result, a measured dimension formatted as text — smart cameras such as the MV-SC5060XM-08M-WBN, a 6 MP mono camera with an 8 mm focal length on GigE, generate the payload on the device. If that string arrives over the network, the same wrapping applies; see smart camera OCR string output over TCP. Strip the string to exactly what you print — truncate the reader output to the digits you need — before it touches the template.

Smart cameras & vision sensorsHikrobot MV-SC5060XM-08M-WBN SC5000X series Smart Camera, 6 MP, Mono, 8 mm focal length, M12-mountMV-SC5060XM-08M-WBN
Interface
GigE
Resolution
6-10 MP
Sensor format
1/2.4"
Shutter
Rolling
$1,629.00View part

The label: ZPL with one placeholder

A complete label is a small text job. This one prints a header, a Code 128 barcode carrying the decoded string, and a date line on a 104 mm wide, 203 dpi printhead:

^XA
^PW832
^LL600
^BY3,3,72
^FO50,50^A0N,28,28^FDWork order label^FS
^FO50,100^BCN,72,Y,N,N^FDABC-123456789^FS
^FO50,200^A0N,28,28^FD2026-11-05^FS
^PQ1
^XZ

Read it as three groups. ^XA and ^XZ open and close the format; ^PW832 sets the print width in dots (832 dots is the 104 mm head at 203 dpi, which works out to 8 dots per millimetre) and ^LL600 the label length. ^BY3,3,72 sets 3-dot barcode modules; ^FO positions each field and ^A0N,28,28 selects a text font. ^BCN,72,Y,N,N is the Code 128 field with a 72-dot bar height and the interpretation line switched on, ^FD carries the data, ^FS ends the field, and ^PQ1 prints one label.

Your code keeps everything except the payload of the middle ^FD as constant strings.

Prove the barcode fits before you order labels

Code 128 width is fixed arithmetic, so run it before committing to a printhead or label stock:

modules = 11 x (data characters + 2) + 13 symbol modules = modules + 20 (quiet zones, 10 each side) width_dots = symbol modules x module width in dots width_mm = width_dots / 8 (203 dpi = 8 dots/mm)

Worked example, using the payload from the job above, ABC-123456789 — 13 characters:

  • modules: 11 x (13 + 2) + 13 = 178
  • with quiet zones: 178 + 20 = 198 modules
  • at 3-dot modules: 198 x 3 = 594 dots, and 594 / 8 = 74 mm of symbol
  • against the 832-dot (104 mm) head: 594 fits with 238 dots, about 30 mm, to spare

The whole job, including the fixed text, is under 200 bytes — one TCP write. If a second station reads the label back, the printed module is 3 dots / 8 dots per mm = 0.375 mm wide, so a camera resolving 2 pixels per module needs pixels no larger than 0.19 mm on the label; the reading-distance side of that trade is covered in Code 128 module size, reading angle and reader distance.

Step by step: from accepted read to printed label

  1. Fix the printer's address. Give it a static IP or a DHCP reservation, confirm the raw print port (9100 unless someone changed ip.port), and open the firewall for host-to-printer TCP on that port.

  2. Prove the path before touching the vision code. From any laptop on that subnet, send the test job above and watch one label come out:

    import socket
    
    PRINTER_IP: str = "192.0.2.50"    # example address; use yours
    PRINTER_PORT: int = 9100          # raw print service
    payload: str = "ABC-123456789"    # example decoded string
    
    job: str = ("^XA^PW832^LL600^BY3,3,72"
                "^FO50,100^BCN,72,Y,N,N^FD" + payload + "^FS^XZ")
    
    with socket.create_connection((PRINTER_IP, PRINTER_PORT), timeout=2.0) as sock:
        sock.sendall(job.encode("ascii"))
    # Test: one label prints with the interpretation line ABC-123456789.
    
  3. Choose who owns the socket — reader, host application, or PLC — and give the job to exactly one of them; the raw print service takes one connection at a time.

  4. Validate the string before substitution: expected length, allowed characters, the prefix-character escaping above, and trimming of line endings.

  5. Trigger one label per accepted read. On a failed read, print nothing — or a deliberately different reject label, never a copy of the last good one. The no-read side is its own problem; see abort a serial read when the scanner returns nothing.

  6. Hold the connection open for the line's rate and reuse it; reconnect on failure with a timeout, and queue the last few labels while the printer answers ping but refuses the port.

  7. Run the acceptance test: N accepted parts produce N labels, and every interpretation line matches the decode log for a full shift.

Who opens the socket: three architectures

Socket owner Template lives in Choose it when Watch for
Code reader or smart camera (TCP client output) the device's output format configuration one reader, one printer, no PC allowed on the line output formatting varies by series; still one connection at a time
Host application (PC) your application code templates change often, you log and retry the app must stay running; guard against duplicate sends
PLC PLC string logic reader and printer both live on the plant network string length limits and framing in the controller

On the PLC row, raw sockets to port 9100 work with no industrial protocol on top; barcode reader to PLC over raw TCP sockets shows the controller side and wiring your PLC as the client when the reader is the TCP server the reader side. Whole projects run this way — printing barcode labels from scanner data with a PLC is the same architecture with the controller as the socket owner.

Checks before the line runs

  • Printer language: a ZPL job prints nothing usable on a printer that only speaks another label language. Confirm ZPL support before writing any code.
  • Address and port static, firewall open host-to-printer on TCP 9100.
  • One writer: one socket owner, or one port per writer on a print server (9100 and 9101).
  • Width arithmetic done, with the symbol plus quiet zones inside both the printhead and the label stock.
  • ^LL matches the stock length, or labels tear mid-print.
  • No-read policy chosen and tested, including a printer-offline retry path.
  • A test job sent from the actual socket owner, not from a laptop.
  • Label count reconciled against read count over one shift.

When raw 9100 is the wrong answer

The printer has no network port. A USB-only printer needs a network print server with a raw port in front of it, or a network-equipped model; sharing it through a PC drags the driver and spooler back into the path you just removed.

You need proof of print. The raw socket is one-way: no acknowledgement ever comes back, so a dropped label stays silent. The engineering answer is not socket status but a read-back station — see below.

IT forbids direct sockets to printers. Route through a print-server appliance or an LPD queue instead; raw printing avoids LPD, it does not forbid it.

You are already committed to the Windows driver route, for instance to print from an existing desktop application. Then the pitfalls move into page setup and silent printing, covered in fixing page setup before hiding the print dialog.

Close the loop: prove the label, not just the print

If the label matters enough to print, read it back. A second code reader — or the same model, mounted at a verification station — confirms the printed symbol decodes to the string you sent; standalone barcode verification of model labels without a PC runs exactly that arrangement, and date code print quality inspection grades the print itself. Glossy label stock glares under the reading light; a semi-polarizing lens cover such as the MV-SC3000-C-HP on the smart camera tames it.

Code readers & vision sensorsCode reader accessories

Lens covers, light boards, I/O boxes and modules

30 models · from $39.00

Pick the reader that feeds your printer in the code reader finder, and if the printing side fights you — escaping, framing, rate — tell us the printer model and reader series on the contact page.

Questions

Can the code reader send the print job itself, with no PC?

Yes, whenever the reader's Ethernet output includes a TCP client mode whose payload format you can edit. Put the fixed ZPL before and after the data field in the output template and point the client at the printer's address on port 9100. If the device only emits the bare decoded string, a host script of a few lines does the wrapping. Remember the one-connection rule: with the reader holding the socket, nothing else may print to that port.

Why TCP port 9100, and can it be changed?

9100 is the conventional raw-print socket across network label printers, and print servers expose 9100 and 9101 for a first and second device. The number is a setting, not a law: the printer's ip.port value can be set to another port, and one documented setvar writes ip.port to 9100. Whatever it reads, point your socket at it and match the firewall rule.

Will the printer confirm that the label printed?

No. The raw print socket is one-way and the printer sends no acknowledgement, so a jammed or out-of-stock printer stays silent while your host believes the job succeeded. Handle printer-side failure the engineering way: retry on connect failure, alarm when the port refuses a connection, and prove physical output with a read-back station that decodes each printed label.

My label printer has only USB. What are my options?

Two. Put a network print server with a raw port in front of the printer, which restores the socket path unchanged, or move to a printer with its own network port. Sharing the USB printer from a PC also works, but it reintroduces the driver and spooler you removed by going raw, and ties printing to that PC staying up.

How do I print a QR code instead of Code 128?

Swap the barcode field for the printer's QR field command and keep everything else, including the socket and the substitution point. The width arithmetic changes: a QR symbol is square and its size follows the version, error-correction level and magnification you set, not the linear module count used for Code 128. Run the symbol size against the label stock the same way before committing.