Skip to main content

HELLO MY NODE IS

Meshtastic contact-QR nametag kiosk for a Raspberry Pi + a Niimbot label printer. DM the kiosk node the word print over the mesh and it prints your nametag: a black HELLO-MY-NODE-IS header, your short/long name (emoji included), node ID, a shared-contact QR (https://meshtastic.org/v/#...) that anyone can scan in the Meshtastic app (>= 2.6) to add you as a contact, PKC public key included, and the Meshtastic M-PWRD mark.

Built at DEFCON 34. 🦞

Two printed nametags resting on a Niimbot label printer: the landscape card layout on 50x30 mm stock above, showing the M-PWRD mark, a caterpillar emoji, the short name WPG, the long name Wandering Packet Goblin, the node ID !deadbeef and a contact QR; the compact layout below, with its QR on the left and the mark bottom-right

Hardware

  • Raspberry Pi with a Meshtastic node attached (USB serial radio, or meshtasticd with a LoRa hat — use --tcp localhost for the latter)

  • A Niimbot label printer, USB-C cable strongly recommended (2.4 GHz at DEFCON is a war zone). Pick yours with --printer:

    --printer head labels layout
    d110 (default) 12 mm / 96 dots continuous roll, or --die-cut 30x15 mm dynamic-length banner, or a compact QR-left card
    b1 48 mm / 384 dots 50x30 mm die-cut landscape card: header band, name block, QR right

    The 50x30 mm stock is 50 mm across the roll and 30 mm along the feed, so the B1 card is laid out across the head instead of along it. Its QR gets 3 printer dots per module against the D110's 2, which means full long names survive into the QR payload instead of being truncated.

Close-up of the card layout as printed, showing the header band, emoji, names, node ID and QR at full detail

Setup

On the Pi:

sudo apt install -y python3-venv fonts-dejavu-core git
python3 -m venv ~/badge
~/badge/bin/pip install git+https://github.com/meshtastic/labeltastic

That puts a labeltastic command in ~/badge/bin/. The emoji font ships with the package; fonts-dejavu-core is the text font and comes from the system. Python 3.11 or newer.

labeltastic sorts out which USB serial port is the radio and which is the printer by USB vendor/product IDs (the D110 is a CH340; radios are CP210x/CH9102/ESP32/nRF52/RP2040) and prints its port table at startup. Just run it:

~/badge/bin/labeltastic --sample --dry-run          # render only, no radio needed
~/badge/bin/labeltastic --test                      # one real test print
~/badge/bin/labeltastic                             # run the kiosk
~/badge/bin/labeltastic --printer b1 --die-cut      # kiosk on a B1

--sample renders a canned node, so --sample --dry-run works with nothing plugged in at all. It writes the PNG (--out to redirect) and then runs the real bitmap encoder over it, reporting packet count and per-third pixel counts — the only check on the wire format you can make without the printer in front of you.

If it can't tell the ports apart, it exits with the table and tells you what to pass — use the stable names in /dev/serial/by-id/ for --serial / --printer-port so a replug can't shuffle them. The B1's USB IDs aren't known here, so pass --printer-port explicitly for one.

If labels come out flipped, add --flip (the old --rotate 270 still works).

Development

uv sync --extra dev
ruff check . && mypy && python scripts/check_spdx.py && pytest

None of it needs a printer or a radio. CONTRIBUTING.md has the details, AGENTS.md the module map and the invariants that will bite you (starting with: head_px must be a multiple of 24, or the printer prints blank and reports success).

Notes

  • DM-triggered only, with a per-node cooldown — broadcast triggers would melt the label roll on a con mesh.
  • Long names are truncated inside the QR payload (not on the printed label) to keep QR modules >= 2 printer dots (3 on the B1's roomier card), or phones can't scan the thermal print.
  • Print density is capped per model (--density): 3 on the D110, 5 on the B1.
  • src/labeltastic/assets/NotoEmoji-Regular.ttf is Google's monochrome Noto Emoji, vendored from google/fonts under the SIL Open Font License 1.1 (assets/OFL.txt).
  • niimprint is vendored under src/labeltastic/_vendor/ (MIT, © kjy00302 — AndBondStyle's repo is the maintained fork of that original) because upstream's packaging pins Python to 3.11.x, which modern Pi OS is way past, while the code itself runs fine on 3.14. See its README for the two local changes.
  • The M-PWRD mark is redrawn with PIL primitives from M-PWRD_BW_Border.svg in meshtastic/design — the geometry is a dozen coordinates, which beats putting an SVG rasteriser (and native cairo) on the Pi for one 40-dot glyph. It is supersampled and hard thresholded rather than left anti-aliased, because niimprint dithers any grey it is handed and that turns a mark this small into noise. Only the banner prints the whole logo, in a column of its own — it can just grow. The B1 card and the compact 30x15 layout print the bare Ms, no border and no wordmark: PWRD is a fifth of the frame's height, so a logo sized to fit the space those two had spare sets it under a millimetre.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

labeltastic-0.1.0.tar.gz (1.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

labeltastic-0.1.0-py3-none-any.whl (1.3 MB view details)

Uploaded Python 3

File details

Details for the file labeltastic-0.1.0.tar.gz.

File metadata

  • Download URL: labeltastic-0.1.0.tar.gz
  • Upload date:
  • Size: 1.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for labeltastic-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1458405bf529fc4658189b7ed5d02367f57e497bb8b21de9683871c2b4b09210
MD5 28d59706667c188aef6c017852530700
BLAKE2b-256 ff9880f68c47778aebb1321f04f72897524f650f10341229d231a2141a203417

See more details on using hashes here.

Provenance

The following attestation bundles were made for labeltastic-0.1.0.tar.gz:

Publisher: release.yml on meshtastic/labeltastic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file labeltastic-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: labeltastic-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for labeltastic-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9b636cc059031125020bb8ebb28b422026ae73cc58f3ed7c8bd4f2dc3e4b7339
MD5 c344abf3e27f6b11b710e06dee36cffe
BLAKE2b-256 162457fdb87a6d9552f6d5c6049f48697345d742080b1ecb6195381057649e94

See more details on using hashes here.

Provenance

The following attestation bundles were made for labeltastic-0.1.0-py3-none-any.whl:

Publisher: release.yml on meshtastic/labeltastic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page