Code readingHow-to

Generate a barcode from the gateway script without a UI component

The UI barcode component never loads in a gateway script. Generate the Code 128 bitmap headlessly or print from printer-native commands on a tag change.

LumaSpec Vision10 min read Share on LinkedIn

On this page 10 sections
  1. 01Why the UI barcode component fails on the gateway
  2. 02Choose the path: bitmap or printer-native commands
  3. 03Path A: render the Code 128 bitmap headlessly
  4. 04Worked example: a 10-character serial at 300 dpi
  5. 05Path B: send printer-native Code 128 commands
  6. 06Trigger the print from a gateway tag change
  7. 07Prove the label reads with a fixed code reader
  8. 08Common mistakes that cost a shift
  9. 09The decision, and the parts to order
  10. 10Questions

Your print trigger belongs on the gateway: the tag value changes, the label printer sits by the line, and no client has to be open. The first attempt imports the desktop barcode component, builds the symbol, and throws, because the gateway never loads that UI library. The fix is to stop treating the symbol as a UI object at all. A barcode is a drawing governed by four numbers: module width in printer dots, quiet zone in module widths, bar height, and a check character. Render it headlessly into a bitmap, or let a thermal label printer draw it from its own command language, and fire the job from a tag-change script. This how-to gives you those numbers, a worked example at 300 dpi, the trigger wiring, and the fixed-reader test that proves the label reads.

Why the UI barcode component fails on the gateway

A UI barcode component is part of the desktop toolkit. The client loads its component library when the session starts, paints the symbol on screen, and talks to the operating system print dialog. The gateway is a headless service: it runs scripts, tag events and database calls with no display, and it does not carry the client's component classes at all. The same import line that works in a client script therefore throws in a gateway tag-change script. No configuration adds those classes to the gateway, because the process is built to run without a GUI.

Confirm which scope a script actually runs in before you move it: a guide to detecting gateway versus client script execution context walks the checks. Scope also changes how the script finds its project: gateway script project context guide covers how a default project is selected there. A reporting module is one server-side route, but you do not need it for one symbol: the drawing is a few lines of script and costs no new module.

Choose the path: bitmap or printer-native commands

Route Where the bars are drawn Best when Watch for
A: render a bitmap your script, on the gateway an ordinary network or office printer, or a label design you already build as an image dot rounding, lossy formats
B: printer-native commands the label printer's firmware a thermal label printer that exposes its command language command dialect, stock settings

Commit now: thermal label printer on the line, take route B. The firmware draws the bars on the head's own dot grid, so the rounding problem disappears. Take route A when you must feed an office or network printer, or when the artwork pipeline already produces images. For a Code 39 label rendered the route-A way, printing a readable Code 39 from your own program walks the same draw.

Path A: render the Code 128 bitmap headlessly

  1. Count the modules. Code 128 draws every character in 11 modules; the start character, the mandatory modulo-103 check character and the 13-module stop character add 35. A payload of N characters is 11N + 35 modules wide.
  2. Fix the module width X as a whole number of printer dots: 2, 3 or 4. At 300 dpi one dot measures 25.4 / 300 = 0.0847 mm, so X = 3 dots = 0.254 mm, the common 10-mil module. A fractional width such as 2.5 dots rounds bar by bar, the wide and narrow elements drift, and decode rate falls with them.
  3. Reserve the quiet zones. ISO/IEC 15417 sets the minimum at 10X of clear space on each side of the bars: 10 x 3 = 30 dots per side, 60 dots total, before any label margin. The same integer-module logic that keeps 2D codes crisp is covered in QR code quiet zone and integer module scaling.
  4. Set bar height between 15X and 30X, which is 45 to 90 dots at X = 3. A fixed-mount reader frames the whole symbol at once, so it reads short bars well; go taller, near one third of the symbol length, when handheld scanners also sweep the label.
  5. Draw the bars into an image buffer at final size, 1 pixel = 1 dot, black on white, and save PNG. Put the human-readable text in the same buffer below the bars: the EAN-13 bitmap walkthrough shows that buffer layout for a numeric code. Never save JPEG, whose compression blurs bar edges, and never scale the image after rendering.
  6. Hand the file to a printer: the platform print service pointed at the network queue, or a file drop into a folder a small spooler watches.
modules = 11N + 35 width_dots = (modules + 20) x X X_mm = X x 25.4 / dpi

Worked example: a 10-character serial at 300 dpi

Payload: a 10-character serial, letters and digits, so N = 10. Long all-digit payloads shrink under subset C; Code 128 codeset B length limits explains when that matters.

  • Modules: 11 x 10 + 35 = 145.
  • Add two 10X quiet zones: 145 + 20 = 165 modules across.
  • X = 3 dots at 300 dpi: 3 x 25.4 / 300 = 0.254 mm (10 mil).
  • Width: 165 x 3 = 495 dots = 495 / 300 in = 1.65 in = 41.9 mm.
  • Bar height at 30X: 90 dots = 90 x 0.0847 = 7.6 mm. Text zone 60 dots = 5.1 mm. Bitmap: 495 x 150 pixels, 12.7 mm tall printed.
  • Label: a 60 x 25 mm label leaves 9 mm clear on each side and about 6 mm above and below, both past the 10X minimum of 2.5 mm.

Let the library append the modulo-103 check character; the formula already counts it. The printed job is the PNG at actual size, nothing scaled.

Path B: send printer-native Code 128 commands

  1. Find the printer's command language in its manual and its Code 128 command. One line carries field position, module width in head dots, bar height in dots, a human-readable-text switch and the payload; the firmware expands the bar pattern itself.
  2. Command X as whole head dots: 203 dpi gives 2 dots = 0.25 mm; 300 dpi gives 3 dots = 0.254 mm; 600 dpi gives 6 dots = 0.254 mm. The head can only place whole dots, so an integer is not optional here either.
  3. Send the line through a raw channel: a raw TCP print port, a raw print queue, or serial. A rasterizing driver in the path re-renders your command as a bitmap at its own resolution, and the rounding problem is back.
  4. Keep one writer: a persistent socket with reconnect-on-failure, or connect per job, plus a queue so two rapid tag changes print two labels in order.

The command language lives in the printer's firmware, so the same script serves any printer of that class; only the field syntax changes. The printer-native idea also runs without a gateway at all: printing a barcode label straight from a PLC without a PC drives it from the controller.

Trigger the print from a gateway tag change

  1. Hang the print function on a tag-change event for the value tag, gateway scope. It is the same pattern as triggering a barcode decode from a PLC tag instead of a UI button: the event source is data, not a screen.
  2. Debounce. Fire only when the value actually changed, and push jobs through a single writer thread so labels keep their order when two changes land in the same second.
  3. Keep the job self-contained: payload, path and stock all in the script. Rotate the bitmap in the renderer if the label prints landscape; a job-level orientation switch is a desktop feature.

Prove the label reads with a fixed code reader

Size the reader's field in pixels per module. A fixed reader decodes a 1D symbol comfortably at 3 pixels per module, and 2 pixels per module is the practical floor when contrast is strong. For X = 0.254 mm, 3 px per module means the field can be at most sensor pixels x (0.254 / 3) = sensor pixels x 0.0847 mm wide.

Camera resolution for the smallest feature
Units
Pixels needed
–
Sensor size
– MP
Smallest sensor that fits
–
Pixel on the part
– mm
Pixels across the feature, that sensor
–

Pixels needed = field / feature × pixels per feature on each axis (field incl. margin). The lens must resolve the pixels too: Nyquist = 1000 / (2 × pixel µm) lp/mm.

Find cameras with enough pixels Open the full calculator

The fixed code readers category filters by resolution, mount and interface, and the camera finder narrows by pixel count. The LS-CRD-0028 has a 2560 x 2048 sensor and an 8 mm lens. Over a 200 mm field, 200 / 2560 = 0.078 mm sits under each pixel, so the 0.254 mm module spans 0.254 / 0.078 = 3.3 pixels, above the floor with margin.

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

For a mount where the label passes at a set distance, the LS-CRD-0047 reads at 60-120 mm and drops straight over the label. MV-ID3013PM-12M-WBN is a 1.3 MP compact reader with a 12 mm focal length, the short-lens pick when the code passes close beneath the head.

Fixed code readersCompact fixed industrial barcode reader, 1.2 MP, USB 2.0, 60-120 mm reading distance (LS-CRD-0047)LS-CRD-0047
Resolution
Up to 3 MP
Shutter
Global
$559.00View part
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
$1,979.00View part

How module size, reading angle and distance trade off on the reader side is worked through in Code 128 module size, reading angle and reader distance. For the loop that reports each read back to the controller, bottle label verification with a fixed reader and a PLC serial link shows one worked line. Mounting hardware, light boards and protective covers for these readers sit in the accessories finder.

Common mistakes that cost a shift

  • Red bars. Most readers illuminate in red, which red ink reflects, so the bars wash out against white. Print black on white.
  • A code wrapped around a curve. Curvature tilts the bar edges across the field; keep the symbol on a flat face or step X up a dot.
  • Hand-drawn patterns with a wrong modulo-103 check. The reader rejects the whole symbol with no explanation. Let the library compute it.
  • Command files routed through a rasterizing driver. The driver re-renders the job at its own dot grid; send printer-native jobs through a raw port or raw queue.
  • Direct-thermal stock for labels that must survive months of heat or sunlight. The paper fades; use thermal transfer with a resin ribbon for long-lived labels.

The decision, and the parts to order

Commit: thermal label printer, take route B with X = 2 or 3 head dots, one raw queue, one writer thread, fired from the tag change. Ordinary network printer or an image-built label, take route A with X = 3 dots at 300 dpi (0.254 mm), 10X quiet zones, PNG at 1 pixel per dot, printed at actual size. Either route, order or assign one fixed reader sized to 3 pixels per module before the first production label runs. More printed-code material sits on the code-reading topic page. If you want your printer, label and reader numbers checked together before ordering, send both datasheets through the contact page.

Questions

What module width should I use on a 203 dpi label printer?

A 203 dpi head places a dot every 0.125 mm, so 2 dots give a 0.25 mm module, the common 10-mil size. Command the width as 2 in the printer's native language, or render the bitmap at 2 pixels per module. Three dots on that head gives 0.375 mm, which also decodes but stretches the symbol: 165 modules then need 62 mm of label.

Does Code 128 need a check character, and does it change the length?

Yes, the modulo-103 check is mandatory and the decoder rejects a symbol whose final pattern does not match it, so let your library compute it. It adds one 11-module character to the length, which the width formula already counts. If the payload is all digits, subset C packs two digits per character: a 12-digit serial drops from 12 characters to 6, about 66 modules shorter.

The label printer hangs off a client PC's USB port. Can the gateway still print?

Not directly: a printer attached to a client belongs to that desktop session. Share the printer on the network so the gateway can open a raw queue to it, move it to the gateway machine or a print server, or pass the job to the client over a message channel and let a small client script hand it to the local queue. The first two keep printing alive with no client open.

Can one tag-change script feed two label printers?

Yes. Give each printer its own raw endpoint and its own writer thread so a jam on one line never holds the other line's labels. Decide the failure rule up front: retry a fixed number of times, then write the payload to an error tag so an operator reprints instead of the line waiting on a dead socket.