feat(uno-q): fleet provisioner + printable QR sticker sheet
Two host-side helpers that close the operational gap between minting kit codes and boards-in-hand. - provision-fleet.sh: provision a whole fleet from fleet.csv (kit,serial). Per board it pushes the per-kit apess-node.env + apess-selfregister.sh over adb and enables the boot/refresh systemd timer (MODE=systemd, root) or an equivalent cron (@reboot + every 5 min; the no-root default). fleet.csv.example is the assignment template. - gen-qr-sheet.sh: render the sticker CSV into a self-contained, printable QR sheet (A4, ~9/page). QRs are baked in as inline SVG via qrencode, so the HTML has zero external refs — prints offline. Each sticker: kit id, QR of the claim URL (/workshop?kit=..&code=..), and the 6-digit code. - .gitignore: never commit kit-codes/ (env files hold FLEET_SECRET + claim codes) or fleet.csv. - README: documents both, plus the one-command fleet path. Verified: provision-fleet loop logic (header/comment/missing skips) and a 4-kit end-to-end sheet build (4 inline SVGs, 0 external refs). Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
a26185d47b
commit
19593a637c
Executable
+73
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build a printable QR sticker sheet from gen-kit-codes.sh output. Each sticker
|
||||
# shows the kit id, a QR of the claim URL, and the 6-digit code — scanning it
|
||||
# opens /workshop?kit=..&code=.. with both pre-filled. QRs are baked in as inline
|
||||
# SVG, so the output HTML is fully self-contained (no fonts/scripts/network).
|
||||
#
|
||||
# ./gen-qr-sheet.sh [kit-codes.csv] [out.html]
|
||||
#
|
||||
# Requires qrencode at build time (brew install qrencode). Open the HTML and
|
||||
# print it (A4, ~9 stickers/page); the dashed borders are cut lines.
|
||||
set -euo pipefail
|
||||
|
||||
CSV="${1:-kit-codes/kit-codes.csv}"
|
||||
OUT="${2:-kit-codes/qr-sheet.html}"
|
||||
|
||||
command -v qrencode >/dev/null || { echo "need qrencode — brew install qrencode" >&2; exit 1; }
|
||||
[ -r "$CSV" ] || { echo "no CSV at $CSV (run gen-kit-codes.sh first)" >&2; exit 1; }
|
||||
|
||||
esc() { sed -e 's/&/\&/g; s/</\</g; s/>/\>/g'; }
|
||||
|
||||
{
|
||||
cat <<'HEAD'
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>APESS 2026 — kit claim stickers</title>
|
||||
<style>
|
||||
@page { size: A4; margin: 10mm; }
|
||||
* { box-sizing: border-box; }
|
||||
body { font-family: system-ui, -apple-system, sans-serif; color: #111; margin: 0; }
|
||||
h1 { font-size: 13pt; margin: 0 0 2mm; }
|
||||
.lead { font-size: 9pt; color: #555; margin: 0 0 6mm; }
|
||||
.sheet { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5mm; }
|
||||
.sticker {
|
||||
border: 1px dashed #999; border-radius: 8px; padding: 5mm 4mm;
|
||||
text-align: center; break-inside: avoid; display: flex; flex-direction: column;
|
||||
align-items: center; gap: 2mm;
|
||||
}
|
||||
.kit { font: 700 13pt ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: 1px; }
|
||||
.qr { width: 34mm; height: 34mm; }
|
||||
.qr svg { width: 34mm; height: 34mm; display: block; }
|
||||
.code { font: 700 17pt ui-monospace, Menlo, monospace; letter-spacing: 3px; }
|
||||
.code small { display: block; font: 400 7pt sans-serif; letter-spacing: 1px; color: #777; text-transform: uppercase; }
|
||||
.hint { font-size: 7.5pt; color: #666; }
|
||||
@media print { .noprint { display: none; } }
|
||||
</style>
|
||||
<h1>APESS 2026 · Uno Q kit claim stickers</h1>
|
||||
<p class="lead">One sticker per kit. Scan the QR (or open the code manually) to claim your board to your team.</p>
|
||||
<p class="lead noprint">Tip: print at 100% scale. The dashed borders are cut lines.</p>
|
||||
<div class="sheet">
|
||||
HEAD
|
||||
|
||||
n=0
|
||||
while IFS=',' read -r kit code url || [ -n "$kit" ]; do
|
||||
kit="$(printf '%s' "$kit" | tr -d ' \r')"
|
||||
code="$(printf '%s' "$code" | tr -d ' \r')"
|
||||
url="$(printf '%s' "$url" | tr -d ' \r')"
|
||||
[ -z "$kit" ] && continue
|
||||
[ "$kit" = "kit" ] && continue
|
||||
case "$kit" in \#*) continue ;; esac
|
||||
svg="$(qrencode -t SVG -m 1 -s 4 -o - "$url" | sed -n '/<svg/,$p')"
|
||||
printf ' <div class="sticker">\n'
|
||||
printf ' <div class="kit">%s</div>\n' "$(printf '%s' "$kit" | esc)"
|
||||
printf ' <div class="qr">%s</div>\n' "$svg"
|
||||
printf ' <div class="code">%s<small>claim code</small></div>\n' "$(printf '%s' "$code" | esc)"
|
||||
printf ' <div class="hint">apess.redclaw.dev · claim to your team</div>\n'
|
||||
printf ' </div>\n'
|
||||
n=$((n + 1))
|
||||
done < "$CSV"
|
||||
|
||||
printf '</div>\n'
|
||||
} > "$OUT"
|
||||
|
||||
echo "wrote $n sticker(s) to $OUT — open it and print (A4, 100% scale)" >&2
|
||||
Reference in New Issue
Block a user