Address Datamax via USB VID:PID/Serial through libusb, like brother_ql_web does
deploy / deploy (push) Successful in 39s

This commit is contained in:
randy committed 2026-09-12 16:55:38 +02:00
1 parent f1304206d7
commit 7583d820f4
2 files changed
+29 -4

No files matched your search

+28 -4
View File
@@ -3,6 +3,7 @@ require 'sinatra'
require "sinatra/reloader"
require 'tmpdir'
require 'net/http'
require 'libusb'
set :protection, :except => :frame_options
set :environment, :production
@@ -13,7 +14,14 @@ if !File.exist?('config.json') || !File.readable?('config.json')
raise RuntimeException, 'Could not read config.json'
end
PRINTER_DEVICE = '/dev/usb/lp_datamax' # stable udev symlink, see /etc/udev/rules.d/99-datamax.rules
# Addressed the same way as the Brother QL printers (usb://VID:PID/Serial via
# brother_ql_web) instead of a udev symlink -- self-contained, no reliance on
# OS device naming/ordering.
DATAMAX_VENDOR_ID = 0x0b0b
DATAMAX_PRODUCT_ID = 0x106e
DATAMAX_SERIAL = '24624'
DATAMAX_ENDPOINT = 0x02 # bulk OUT, interface 0
PRINTER_DPI = 203 # DatamaxONeil E4204B Mark III native head resolution
PRINTER_DARKNESS = 8 # lower than factory default to stop thermal dot-gain from fusing barcode bars
TEST_LABEL_PDF = File.join(File.dirname(__FILE__), 'test-label.pdf')
@@ -81,6 +89,22 @@ helpers do
"^XA\n^MD#{PRINTER_DARKNESS}\n^PW#{width}\n^LL#{height}\n^FO0,0^GFA,#{total_bytes},#{total_bytes},#{bytes_per_row},#{hexdata}\n^XZ\n"
end
def print_to_datamax(data)
usb = LIBUSB::Context.new
device = usb.devices(idVendor: DATAMAX_VENDOR_ID, idProduct: DATAMAX_PRODUCT_ID)
.find { |d| d.serial_number == DATAMAX_SERIAL }
unless device
raise format('Datamax printer not found (USB %04x:%04x/%s)',
DATAMAX_VENDOR_ID, DATAMAX_PRODUCT_ID, DATAMAX_SERIAL)
end
device.open do |handle|
handle.claim_interface(0) do
handle.bulk_transfer(endpoint: DATAMAX_ENDPOINT, dataOut: data)
end
end
end
# Transparently reverse-proxies the current request to one of the
# brother_ql_web instances, so all three printers are reachable through
# this single sinatra port instead of their own dedicated ports.
@@ -148,13 +172,13 @@ post '/upload' do
when ".pdf"
begin
zpl = pdf_to_zpl(filepath)
File.open(PRINTER_DEVICE, 'wb') { |f| f.write(zpl) }
print_to_datamax(zpl)
flash "PDF: Upload successful (#{filename})", "success"
rescue => e
flash "PDF: Failed to print (#{e.message})", "danger"
end
when ".zpl"
File.open(PRINTER_DEVICE, 'wb') { |f| f.write(File.binread(filepath)) }
print_to_datamax(File.binread(filepath))
flash "ZPL: Upload successful (#{filename})", "success"
else
flash "#{filetype} is not supported. Only .pdf and .zpl!", "false"
@@ -171,7 +195,7 @@ end
post '/test-print' do
begin
zpl = pdf_to_zpl(TEST_LABEL_PDF)
File.open(PRINTER_DEVICE, 'wb') { |f| f.write(zpl) }
print_to_datamax(zpl)
flash 'Test label sent to printer', 'success'
rescue => e
flash "Test print failed (#{e.message})", 'danger'