- pricegod-urovo-daemon: C# :7790 HTTP service, drives the Urovo D812R+ via the GTSPL SDK; prints a label AND encodes the UHF chip in one pass. Drop-in for the PriceGod extension's daemon.js (same :7790, CORS *). - chafcheck: Chafon H-102 UHFPrimeReader P/Invoke probe. - ASSESSMENT.md: everything done + learned this session -- the ribbon-latch fix, PET-labels-are-not-direct-thermal finding, unreliable-status-byte quirk, SKU->EPC scheme, the Chafon HID-mode dead end, and how to port the print+encode recipe to the Mac (GTSPL Java SDK / raw TSPL). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
12 KiB
Urovo D812R+ RFID print+encode — full assessment & handover
Session date: 2026-07-22 (Windows 11 bench machine). Goal: make the Urovo D812R+ (RFID) print a record label and program the UHF chip in one pass, driven from the PriceGod browser extension — replacing the current two-step flow (Chafon gun programs a chip → Dymo 450 prints a paper label → stick paper over chip).
TL;DR
- ✅ Built a working Windows daemon (
pricegod-urovo-daemon, C#/.NET Framework,http://localhost:7790) that drives the Urovo via the GTSPL SDK and does print + RFID-encode in one pass. Drop-in for the extension'sdaemon.js(same port, same JSON, CORS*). - ✅ Printing works — dark, correct, on real thermal stock, at the right size (54×24). The daemon even auto-clears the recurring "out of ribbon" latch on every print.
- ✅ RFID read/encode path proven — the Urovo reads UCODE-9 chips and the
writeUHF+printlabelencode sequence is wired and fires cleanly. - ⛔ The blocker to the actual one-pass dream is the LABELS, not the printer: the shop's glossy "U9 65×35mm PET" RFID labels are not direct-thermal — a direct-thermal printer can't mark them (only a faint emboss). Need direct-thermal UHF RFID paper labels.
- ⛔ Chafon H-102 on Windows is a dead end for writing — it outputs as an HID keyboard, not serial; the SDK can't reach it to program tags without a chronically-unreliable device-side mode flip. Recommend: Chafon = scanner (reads/looks-up), Urovo = all writing.
1. What was built (in this repo)
| File | What |
|---|---|
daemon.cs |
The service. HttpListener on :7790, CORS *, drives the Urovo via GTSPL_SDK.dll. |
chafcheck.cs |
Probe for the Chafon reader via native UHFPrimeReader.dll (P/Invoke). |
start-daemon.cmd / build.cmd |
Run / rebuild (rebuild uses the always-present .NET Framework csc.exe — no .NET SDK needed). |
README.md |
How to run + routes. |
PROGRESS.md |
Running log. |
*.dll |
Vendor binaries needed to build/run on Windows: GTSPL_SDK.dll, GTSPL_SDK_C.dll, zlib.net.dll (Urovo), UHFPrimeReader.dll, hidapi.dll (Chafon). |
Build with build.cmd (rebuilds pricegod-urovo-daemon.exe; .exes are git-ignored). Run with
start-daemon.cmd.
Daemon routes (:7790, JSON)
| method | path | body | returns |
|---|---|---|---|
| GET | /status |
— | {ok,ready,status,statusText,printer} |
| POST | /print-encode |
{sku,releaseId,artist?,title?,genre?,style?,info?,price?,condition?,w?,h?,gap?,dir?} |
{ok,epc,status,note,...} |
| POST | /write-tag |
alias of /print-encode (the daemon.js name) |
same |
| POST | /print-test |
same body, prints only, no RFID (safe on plain thermal) | — |
| GET | /read-tag / /read-raw |
— | tag EPC / all memory banks |
| POST | /calibrate / /recover |
— | RFID auto-cal / ribbon-off+feed clear |
2. The proven Urovo print+encode recipe (⭐ portable — this is what transfers to the Mac)
Every step below is the exact GTSPL SDK call sequence the daemon uses. Almost all of them are
plain TSPL commands (sendcommand) — the only special one is the RFID write. This recipe is
device knowledge, not language knowledge; it should replicate on any GTSPL binding (Windows .NET,
Java/GTSPL-1.1.8.jar, Android, etc.):
detectUSB / openport # connect to "Urovo D812Riplus(RFID)"
SET RIBBON OFF # direct thermal (no ribbon). REQUIRED, repeatedly (see §3)
<if status != "00">: formfeed; SET RIBBON OFF # clear a latched "out of ribbon"
SET TEAR ON
GAP 2 mm,0 mm # gapped die-cut labels (Dymo 54×24). For RFID rolls that
# blind the gap sensor: GAP 0 mm,0 mm (continuous)
SIZE 54 mm,24 mm # label size (was 65×35 for the PET RFID stock)
DENSITY 15 # MAX darkness — needed; lower barely marks
DIRECTION 1 # flip to 0 if the label prints rotated
CLS (clearbuffer)
writeUHF("H", 2, 12, "E", <24-hex EPC>) # ⭐ THE RFID ENCODE: hex, EPC bank ("E"), word 2, 12 bytes (96-bit EPC)
TEXT/QRCODE ... (printerfont/qrcode) # the visible label
SET RIBBON OFF # re-assert immediately before printing
printlabel("1","1") # fires PRINT + ENCODE together, one pass
<wait for status to return to "00"> # RFID+feed leaves it "busy" for ~1–3s (see §3)
readUHF("H",2,12,"E") / query_UHF # optional verify (note: the encoded tag has fed past the
# antenna by now, so on-printer read-back is unreliable —
# verify with a separate reader / Chafon scan instead)
SKU ↔ EPC scheme (v1, in the Epc class): the 96-bit EPC (12 bytes) = 6 bytes 14-digit
timestamp SKU + 4 bytes release_id + 2 bytes 0xEC01 marker. ⚠️ Unverified against the
Mac/Chafon scheme — if existing tags use a different layout, change ONLY the Epc class; nothing
else depends on the byte order. (Best check: scan an existing Chafon-written tag and compare.)
3. Hard-won gotchas (the Urovo D812R+ specifically)
- PET labels aren't direct-thermal. The glossy "U9 65×35mm PET" RFID labels only emboss — they will never print dark on a direct-thermal printer. This cost hours (looked like a density/ribbon/printer fault; it was the media). Scratch test: drag a nail across a blank label — direct-thermal paper leaves a gray streak, PET/plain leaves nothing. Buy direct-thermal RFID paper labels (see §5).
- "Out of ribbon" (status
08) is a latch. The printer defaults to thermal-transfer (expects a ribbon).SET RIBBON OFFswitches to direct thermal — but a latched08(e.g. after opening the head / pulling the roll back) is NOT cleared bySET RIBBON OFFalone; it needs a power cycle, OR a formfeed + SET RIBBON OFF (which the daemon now does automatically on a non-00start). - The status byte lies right after a print. During the RFID-encode + feed the reader returns
garbage codes (
20,31,45,FC) for 1–3s, then settles to00. Do not judge success on the immediate post-print byte — poll until00(the daemon'sWaitReady), and verify the actual result by eye / a separate tag read. - USB drops on power-off. Powering the printer off removes it from the USB bus; it re-enumerates
a few seconds after power-on. If
detectUSBreturns null/no printer, wait or replug. (COM4/COM5 on this laptop are the Urovo's Bluetooth SPP links — ignore them.) - Label-size calibration is on the printer: hold the FEED button while powering on, wait for 5 beeps — it auto-calibrates gap/label size. Needed after changing stock.
- Talk to it via the GTSPL SDK, not the Windows spooler. Raw TSPL through the Seagull print
driver/spooler did not reliably deliver commands (esp.
SET RIBBON OFF); the SDK's direct USB path does. Build without a .NET SDK usingFramework64\v4.0.30319\csc.exe.
4. The Chafon H-102 situation (why it's parked)
The two CF-H102 guns, on Windows, put their tag reads on the HID keyboard channel (USB-HID, or
BLE "LE GATT HID device" when paired) — not the CH340 serial the SDK needs. Proven: chafcheck
(OpenDevice+GetTagUii) returns 0xFFFFFF12 (COMM_TIMEOUT, "reader not answering") at every
baud on both guns; a raw serial read with DTR+RTS asserted got 0 bytes while triggering.
To write tags via the SDK the gun must be in serial/command mode, flipped device-side (config barcode / the sideloaded Android app) — which the user reports is chronically flaky (Mac too). The Windows Chafon SDK has serial / USB-HID / network paths only — no BLE — so Bluetooth isn't a path for the gun here either.
Recommendation: stop fighting it. Use the Chafon as a keyboard scanner (trigger → types the EPC → focus a search box to look up a tag; 100% reliable in the mode it's already in) and let the Urovo do all writing. Once direct-thermal RFID labels arrive, the Chafon isn't needed to program anything.
5. What to buy (unblocks the one-pass dream)
Direct-thermal UHF RFID paper labels, all of:
- Direct thermal (⚠ not "thermal transfer", not "PET/PP") — search "direct thermal RFID label"
- Paper face (direct-thermal coated paper)
- UHF RFID inlay, EPC Gen2, chip NXP UCODE 9 (matches existing tags/reader)
- 54×24 mm (or 55×25 — the Dymo size), roll compatible with the D812R
- Ask the seller: "compatible with Urovo/TSC D812R RFID printer"
The existing PET tags aren't wasted — a reader can still program them; you'd just keep printing+sticking paper for those. New DT-RFID paper labels are what enable single-pass.
6. Two-mode design (agreed)
- Mode A — "Separate" (today's flow, existing stock): program chip + print Dymo separately, stick paper on top. On Windows the encode step is the flaky Chafon (see §4) — recommend leaning on the Urovo instead where possible.
- Mode B — "Combined / one-pass" (the goal): one button → Urovo prints + encodes together on
DT-RFID labels. Daemon path (
/print-encode) is built.
A Settings toggle picks the mode; the extension change is tiny (same daemon.js contract). Wiring the
PriceGod buttons → :7790 was not done yet (next step).
7. ⭐ For the Mac: getting the Urovo to program chips over there
The daemon.cs is Windows-bound — GTSPL_SDK.dll is a Windows DLL; it won't run on macOS. But the
recipe in §2 is portable. Options, best first:
- GTSPL Java SDK (most direct). The vendor SDK ships a cross-platform Java library:
Documents/Software V1.1.2/drive-download-.../20241129_GTSPL_Java_Library/lib/GTSPL-1.1.8.jar(alsogtspl_sdk.jarin the Android samples). Java runs on macOS — write a small program that mirrors §2 (openport/sendcommand/writeUHF/printlabel). ⚠ Verify the jar's USB transport works on macOS (the Android build assumes Android USB; desktop USB may need a native lib or a serial/USB-CDC path). This is the cleanest port becausewriteUHFdoes the RFID encoding for you. - Raw TSPL over USB (no SDK). ~90% of §2 is plain TSPL text you can send straight to the Urovo's
USB device on macOS (e.g. write to the raw printer device, or CUPS
-o raw). The one missing piece is the RFID-encode command —writeUHF("H",2,12,"E",epc)is an SDK helper wrapping the printer's TSPL RFID command, and its exact bytes weren't captured this session. To get them: sniff the USB writes whilewriteUHFruns on Windows (USBPcap/Wireshark), or check the Urovo/Gainscha TSPL RFID command reference. Once you have that command string, the whole thing is raw TSPL and trivially portable (even into the existing Noderfid-daemon). - Extend the existing Mac
rfid-daemon(Node) to open the Urovo and emit the §2 sequence (needs the RFID command bytes from option 2).
Reality check for "can the Urovo program chips on Mac?": yes, mechanically — it's the same USB
printer speaking TSPL. The only real work is the transport (get bytes to the printer on macOS) and the
RFID-encode command (use the Java writeUHF, or capture its bytes). Everything else — ribbon-off,
geometry, density, one-pass timing — is documented above and identical.
8. Open items / next steps
- Buy direct-thermal UHF RFID paper labels (§5) — the true unblock.
- Verify the SKU↔EPC scheme (§2) against an existing tag; adjust
Epcclass if needed. - Wire PriceGod buttons →
:7790+ the Mode A/B toggle. - Match the label layout to the extension's
labels.jsdesign more faithfully (current TSPL layout is functional, not pixel-perfect). - (Optional) On Windows, decide Chafon = scanner-only vs. chase command mode.
- (Mac) Try option 1 or 2 in §7 to program chips there.
See also the shop's memory notes: urovo-d812r-ribbon-fix, urovo-d812r-rfid-label-gap-issue,
urovo-d812r-pet-labels-not-thermal, urovo-windows-print-encode-daemon, chafon-h102-windows-hid-mode.