Go to file
type-two 3a741079d6 fix(daemon): move to 7791 so the label service and the gun daemon coexist
Four devices, two daemons, one front door. This service drives the Urovo D812R+
and the Dymo LabelWriter over raw USB; the Node rfid-daemon on 7790 drives the
Chafon H102 gun and the Dymo M25 scale, and is what the PriceGod extension is
pointed at. Both were binding 7790.

The port was not the whole problem. /status, /read-tag, /write-tag and /recover
exist on BOTH services and mean different things — the gun in your hand versus
the antenna inside the printer. Merging them into one flat namespace would let a
"read-tag" land on whichever daemon answered, which is how you get a tag written
by the wrong device. So this keeps its own names and the Node side proxies
/printer/* here, leaving the extension with a single endpoint on 7790.

They stay separate processes on purpose: this side needs libusb for a real
bidirectional pipe (UHF READ replies as raw bytes on the bulk-IN endpoint, which
is why CUPS 'lp -o raw' cannot drive it) and the other needs node-serialport and
node-hid. Merging would mean porting one language's device stack to the other
for no gain.

--port still wins, UROVO_PORT overrides the default, and neither the launchd
plist nor start-daemon.command pins a port, so install.sh needed no change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 10:32:42 +10:00
mac fix(daemon): move to 7791 so the label service and the gun daemon coexist 2026-09-04 10:32:42 +10:00
.gitignore macOS: raw-TSPL Urovo daemon — no vendor SDK needed 2026-07-22 16:07:12 +10:00
ASSESSMENT.md Add next-session handover notes 2026-07-22 16:53:18 +10:00
build.cmd Windows Urovo D812R+ print+encode daemon + full assessment 2026-07-22 15:18:39 +10:00
chafcheck.cs Windows Urovo D812R+ print+encode daemon + full assessment 2026-07-22 15:18:39 +10:00
daemon.cs Windows Urovo D812R+ print+encode daemon + full assessment 2026-07-22 15:18:39 +10:00
GTSPL_SDK_C.dll Windows Urovo D812R+ print+encode daemon + full assessment 2026-07-22 15:18:39 +10:00
GTSPL_SDK.dll Windows Urovo D812R+ print+encode daemon + full assessment 2026-07-22 15:18:39 +10:00
hidapi.dll Windows Urovo D812R+ print+encode daemon + full assessment 2026-07-22 15:18:39 +10:00
PROGRESS.md Windows Urovo D812R+ print+encode daemon + full assessment 2026-07-22 15:18:39 +10:00
README.md docs(mac): patched CUPS PPD for the DYMO 450's 24x55mm price stock 2026-07-24 13:40:30 +10:00
start-daemon.cmd Windows Urovo D812R+ print+encode daemon + full assessment 2026-07-22 15:18:39 +10:00
UHFPrimeReader.dll Windows Urovo D812R+ print+encode daemon + full assessment 2026-07-22 15:18:39 +10:00
zlib.net.dll Windows Urovo D812R+ print+encode daemon + full assessment 2026-07-22 15:18:39 +10:00

pricegod-urovo-daemon

The Windows counterpart to the Mac rfid-daemon. Instead of a Chafon gun writing a loose chip while a Dymo prints a separate sticker, this drives the Urovo D812R+ (RFID) to print the label AND encode the UHF chip in one pass on the composite (paper+chip) rolls.

It listens on http://localhost:7790/ with CORS *, so it's a drop-in for the PriceGod extension's existing daemon.js client — same port, same JSON shape.

Run it

Double-click start-daemon.cmd (leave the window open while you work). That's it — no Node, no .NET SDK, no gitea clone. It's a self-contained .exe.

To rebuild after editing daemon.cs: double-click build.cmd.

What's inside

  • daemon.cs — the service (C#, .NET Framework 4.x).
  • pricegod-urovo-daemon.exe — the compiled daemon.
  • GTSPL_SDK.dll, GTSPL_SDK_C.dll, zlib.net.dll — the Gainscha/Urovo print SDK (must sit beside the .exe). Copied from the vendor Windows SDK.

The print/encode sequence is a straight port of the proven gtcheck.cs rfidgo path: SET RIBBON OFF → continuous geometry (GAP 0, RFID rolls blind the optical gap sensor) → writeUHF → draw text + QR → printlabel → read-back verify.

Routes

method path body returns
GET /status {ok, ready, status, statusText, printer}
POST /print-encode {sku, releaseId, artist?, title?, price?, condition?, w?, h?, gap?} {ok, sku, releaseId, epc, verified, status}
POST /write-tag alias of /print-encode (the daemon.js name) same
GET /read-tag {ok, epc, sku, releaseId, recognized}
POST /calibrate RFID auto-calibration
POST /recover ribbon-off + one feed to clear a fault

Quick test (PowerShell):

Invoke-RestMethod http://localhost:7790/status

SKU ↔ EPC scheme (⚠ verify)

The 96-bit EPC (12 bytes) is packed as: 6 bytes 14-digit timestamp SKU · 4 bytes release_id · 2 bytes 0xEC01 marker. This lives in the Epc class in daemon.cs and is the only thing that needs to change if it must match a different (Mac/Chafon) layout — nothing else depends on the byte order. Confirm by reading an existing tag: put a Chafon-written record at the antenna and GET /read-tag.

DYMO LabelWriter 450 on macOS — the PPD you will need again

Not the daemon, but it lives here because mac/dymo.py drives the same printer.

macOS auto-adds a USB LabelWriter 450 with the generic CUPS driver (*PCFileName: "dymo.ppd", *ModelName: "DYMO Label Printer"). That PPD ships 10 fixed label sizes and no CustomPageSize/VariablePaperSize block — so a custom paper size made in the macOS page-setup dialog can never reach the printer. CUPS silently falls back to w81h252 (Address, 28.6 × 88.9 mm), and a 54×24 mm label design comes out rotated 90° and shrunk, with a big blank area. Nothing is wrong with the extension's labels.js.

mac/dymo-24x55.ppd is the generic PPD patched to add the shop's 24×55 mm price stock, in both feed orientations, so the right one can be picked in the print dialog:

PageSize pt mm roll
pg55x25 72 × 155 25.4 × 54.7 ~25 mm wide, label runs 55 mm along the feed
pg55x25L 155 × 72 54.7 × 25.4 ~55 mm wide, label runs 25 mm along the feed

John's price roll is the landscape-feed kind → use pg55x25L.

sudo lpadmin -p <queue> -P mac/dymo-24x55.ppd      # apply  (queue on JING5: make_it_soso)
sudo lpadmin -p <queue> -m drv:///sample.drv/dymo.ppd   # revert to stock

Re-apply after any macOS update or after re-adding the printer — both revert the queue to the generic driver and the symptom comes straight back.

Regenerate from the pristine driver PPD — once applied, the queue's own PPD is already patched and patch_ppd.py will refuse it:

ppdc -d /tmp/ppdout /usr/share/cups/drv/sample.drv
python3 mac/patch_ppd.py mac/dymo-24x55.ppd /tmp/ppdout/dymo.ppd   # byte-identical, PASSes cupstestppd

Two traps it handles: margins are set to 2 pt sides / 4 pt ends instead of the driver's stock 14.9 pt, which would eat 10.5 mm of a 55 mm label; and every one of the 31 languages in *cupsLanguages needs a translation string per new choice or cupstestppd FAILs.

Dead end for next time: LabelPrinter-*.pkg in ~/Documents is not the DYMO driver — it's the generic bundle for the PM-246S/Wagtail printers.

Notes / open items

  • Default label geometry is 65×37 mm, continuous (GAP 0). Adjust to your actual RFID roll via the w/h/gap fields, or change the DEF_* constants.
  • The label layout (text lines + QR) is functional, not yet pixel-matched to the 51×19 Dymo design in the extension's labels.js.
  • The Chafon gun is still needed for reading a loose tag off a shelf — the Urovo can only read/write a tag physically inside the printer.