HA 2026.2+ BLE Reverse Engineered BSD 2-Clause License
Custom Home Assistant integration for DYMO LetraTag 200B Bluetooth label printers.
BLE protocol fully reverse-engineered from the DYMO LetraTag Connect Android app.
- BLE auto-discovery - printers appear automatically in Home Assistant
- Lovelace card - responsive UI with live preview, font/size selectors, and banner mode toggle
- Text label printing - render and print text directly from service calls
- Banner mode - 90 degree rotated text for vertical/spine labels
- Image label printing - print any image file, auto-scaled to tape size
- Native resolution rendering - TrueType text rendered at 32px with column doubling for the printer's step rate
- Adaptive sensors - automatically uses whichever data the printer model exposes (advertisement or GATT)
- 21 built-in fonts - sans, serif, monospace, condensed and display faces, all tuned for the 32px tape (see the Text Rendering section)
- Multi-line support - split text across lines with
\n - Custom fonts - use any TrueType font via path
| Component | Version |
|---|---|
| Home Assistant | 2026.2+ |
| Python | 3.12+ |
| Bluetooth | BLE adapter (built-in or USB) |
| Hardware | DYMO LetraTag 200B |
| Tape | 12mm cassette |
Copy custom_components/letratag/ into your Home Assistant configuration directory:
<config>/
custom_components/
letratag/
__init__.py
config_flow.py
const.py
frontend.py
manifest.json
printer.py
protocol.py
render.py
sensor.py
services.yaml
strings.json
fonts/
*.ttf
translations/
en.json
www/
letratag-card.js
Restart Home Assistant.
Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.
- Click the button above (or open HACS > Integrations, three dots menu > Custom repositories, and enter
https://github.com/renaudallard/homeassistant_letratagwith category Integration) - Find DYMO LetraTag in the list and click Download
- Restart Home Assistant
The integration auto-discovers nearby LetraTag printers via BLE.
- Go to Settings > Devices & Services
- The printer appears as a discovered device
- Click Configure and confirm
Manual setup: Add Integration > search DYMO LetraTag > enter the Bluetooth address.
After adding the printer, click Configure on the integration to set:
| Option | Default | Description |
|---|---|---|
| Printer has a cutter | off | Enable only for cutter-equipped models (such as the LabelManager Connect) so the cut service option is honored. The LetraTag 200B has no cutter; leave this off and it uses FormFeed. |
A custom card is included for printing labels directly from the UI.
LetraTag Lovelace card LetraTag Lovelace card preview
The card JS is automatically registered as a Lovelace resource when the integration loads (served securely via StaticPathConfig and auto-added to the resource collection). No manual resource configuration needed.
Just add a card to your dashboard. All options can be set from the visual editor (the gear icon) or in YAML:
type: custom:letratag-card title: Label Printer # optional, defaults to "DYMO LetraTag" default_font: Roboto Bold # optional, defaults to "DejaVu Sans Bold" default_size: 32 # optional, 8-32 px, omit for auto
The resource is automatically removed when the last LetraTag config entry is unloaded.
- Live label preview - tape-shaped preview that updates as you type
- Text input - multi-line textarea, Ctrl+Enter to print
- Font selector - 21 built-in fonts optimized for 32px resolution
- Size slider - 8px to Auto (rightmost = biggest, auto-fills tape height)
- Configurable defaults - preset the starting font and size with
default_font/default_size - Visual editor - configure title, default font and default size from the dashboard card editor
- Normal / Banner toggle - switch between horizontal text and 90 degree banner mode
- Copies - print multiple copies of a label
- Sensor display - shows available sensors (unavailable sensors are hidden)
- Responsive - adapts to any column width, stacks controls on narrow screens
Four sensors are created per printer. Each sensor only becomes available when its data source provides data, so models that don't expose certain information will simply not show those sensors.
| Sensor | Data source | Description |
|---|---|---|
| Status | GATT status command / advertisement flags | Printer state: Ready, Busy, Tape jam, Cutter jam, Battery too low. Attributes include manufacturer, model, serial, firmware, hardware revision. |
| Firmware | GATT Device Information Service (0x2A26) | Firmware version string (e.g. RUTEP20220628) |
| Battery | Advertisement manufacturer data / extended GATT status | Battery percentage. Only available on models that broadcast battery level. |
| Cassette | Advertisement manufacturer data / extended GATT status | Tape type: Empty, 6mm, 9mm, 12mm, 19mm, 24mm. Only available on models that report cassette type. |
The printer auto-shuts down after approximately 5 minutes. Sensors are updated by watching for BLE advertisements:
- Printer powers on - BLE advertisement detected
- Advertisement data - if the model broadcasts manufacturer data (battery, cassette, errors), sensors update immediately from the advertisement
- GATT connection - the integration connects once to read device info (model, firmware, serial) and the status command reply
- Printer shuts down - sensors become unavailable
- Next power-on - cycle repeats
The LT200B (firmware RUTEP20220628, REV-E) exposes:
| Characteristic | Value |
|---|---|
| Manufacturer | Newell |
| Model | LT200B |
| Firmware | RUTEP20220628 |
| Hardware | REV-E |
| Status | ESC R reply (3 bytes) |
| Battery | Not available |
| Cassette | Not available |
Other models or firmware versions may expose additional data.
Print a text label. Font size is auto-calculated to fill the tape height, or can be set explicitly (minimum 8px).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
text |
string | yes | Label text. Use \n for multiple lines |
|
copies |
int | no | 1 |
Number of copies (1 - 255) |
cut |
bool | no | true |
Cut after printing (cutter-equipped models only; needs the cutter option) |
font_name |
string | no | One of the 21 built-in fonts (see below) | |
font_size |
int | no | auto | Font size in pixels (8 - 64) |
font_path |
string | no | Path to a custom .ttf file (used when font_name is not set) |
|
rotate |
bool | no | false |
Banner mode: rotate text 90 degrees |
# Simple label service: letratag.print_label data: text: "Hello World"
# Multi-line with font choice service: letratag.print_label data: text: "Kitchen\nShelf 3" copies: 2 font_name: "DejaVu Mono Bold"
# Banner label (rotated 90 degrees for vertical reading) service: letratag.print_label data: text: "OFFICE" rotate: true
Print an image file. The image is automatically resized to the tape height and converted to 1-bit monochrome. Image path must be under the Home Assistant configuration directory.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
image_path |
string | yes | Path to image file (PNG, BMP, JPG, etc.) | |
copies |
int | no | 1 |
Number of copies (1 - 255) |
cut |
bool | no | true |
Cut after printing (cutter-equipped models only; needs the cutter option) |
service: letratag.print_image data: image_path: "/config/labels/qr_wifi.png" copies: 1
Text is rendered directly at the printer's native resolution (32 pixels for 12mm tape) using Pillow TrueType font rendering. Each pixel column is doubled to match the printer's stepper motor cadence. No screenshots, no bitmap scaling.
Built-in fonts (selected for clarity at 32px):
| Name | Style | Best for |
|---|---|---|
| DejaVu Sans Bold | Sans-serif | General purpose, excellent hinting |
| Liberation Sans Bold | Sans-serif | Clean, compact |
| FreeSans Bold | Sans-serif | Wide language support |
| Roboto Bold | Sans-serif | Modern, rounded |
| Noto Sans Bold | Sans-serif | Highly legible, wide language support |
| Open Sans Bold | Sans-serif | Humanist, clear at small sizes |
| Source Sans 3 Bold | Sans-serif | Crisp UI sans |
| Inter Bold | Sans-serif | Tall x-height, sharp at 32px |
| Fira Sans Bold | Sans-serif | Friendly, very readable |
| Oswald Bold | Condensed sans | Fits more text on the tape |
| Archivo Narrow Bold | Condensed sans | Long labels |
| Bebas Neue | Condensed display | All-caps signage look |
| DejaVu Serif Bold | Serif | Formal labels |
| Noto Serif Bold | Serif | Formal labels, wide language support |
| Merriweather Bold | Serif | Reads well small |
| Roboto Slab Bold | Slab serif | Sturdy, pairs with Roboto |
| Courgette Bold | Script | Casual, handwritten look |
| Sancreek Bold | Display | Decorative western style |
| DejaVu Mono Bold | Monospace | Serial numbers, codes, aligned text |
| JetBrains Mono Bold | Monospace | Codes, clear 0/O and 1/l |
| IBM Plex Mono Bold | Monospace | Codes, even color |
DejaVu, Liberation and FreeSans are resolved from the host's system fonts;
the rest are bundled with the integration (unmodified, open-licensed copies;
see custom_components/letratag/fonts/ATTRIBUTION.md for licenses) so they
work on any host. If font_name is not specified, the system's first
available DejaVu font is used.
When rotate is true, each character is rendered at full tape width and placed sequentially along the tape. The result is a label that reads normally when the tape is turned 90 degrees, ideal for:
- File folder spines
- Cable markers viewed from the side
- Vertical shelf labels
- Equipment panel labels
Protocol reverse-engineered from the DYMO LetraTag Connect 2.1.0 APK (Genie variant).
| Role | UUID |
|---|---|
| Service | be3dd650-2b3d-42f1-99c1-f0f749dd0678 |
| Write (print request) | be3dd651-2b3d-42f1-99c1-f0f749dd0678 |
| Notify (print reply) | be3dd652-2b3d-42f1-99c1-f0f749dd0678 |
| Short command | be3dd653-2b3d-42f1-99c1-f0f749dd0678 |
The printer also exposes the standard Device Information Service (0x180A).
All commands are prefixed with ESC (0x1B):
| Command | Code | Bytes | Description |
|---|---|---|---|
| StartJob | s |
6 | Begin print job with 4-byte job ID |
| MediaType | M |
6 | Set cassette type |
| PrintDensity | C |
- | Set print density |
| PrintData | D |
12+N | Raster data: bpp, alignment, width(4), height(4), pixels(N) |
| FormFeed | E |
2 | Form feed (used by Genie variant after print data) |
| Status | A |
2 | Request printer status |
| Copies | # |
3 | Set number of copies |
| Cut | p |
3 | Cut tape (0x30) or skip (0x31), used by Avatar variant |
| EndJob | Q |
2 | End print job |
StartJob -> Copies -> PrintData -> FormFeed|Cut -> Status -> EndJob
The terminator is FormFeed on the LetraTag 200B (no cutter) or the Cut command on cutter-equipped models.
Commands are concatenated into a body, then wrapped:
Header (9 bytes):
[0] 0xFF preamble
[1] 0xF0 flags
[2:4] 0x12 0x34 magic
[4:8] uint32 LE body length
[8] uint8 checksum (sum of [0:8] & 0xFF)
Body: split into 500-byte chunks, each prefixed with a 1-byte sequence number (value 27 is skipped to avoid ESC collision). Magic bytes 0x12 0x34 are appended to the last chunk.
- 1 bit per pixel (
bpp = 0x81), monochrome - Image is stored column-by-column (each rasterline = one vertical column)
- 32 pixels per column for 12mm tape (4 bytes per column)
- Columns are byte-reversed in 8-bit groups (swapBits) then packed MSB-first
- Each column is doubled (enlarge) to match the printer's stepper motor cadence
Available on some models. Not broadcast by LT200B REV-E.
| Byte | Bits | Field |
|---|---|---|
| 0 | [7:4] | Hardware revision |
| 1 | [3:0] | Cassette ID (0=empty, 1=6mm, 2=9mm, 3=12mm, 4=19mm, 5=24mm) |
| 1 | [4] | Carbon type |
| 1 | [5] | Busy / locked |
| 2 | [0] | Tape jam |
| 2 | [1] | Cutter jam |
| 2 | [2] | Battery too low to print |
| 2 | [3] | Battery low |
| 2 | [5:4] | Battery level (0-3) |
| 2 | [6] | Charging indicator |
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Printing / ready for next label |
| 2, 5 | Failed |
| 3 | Success, battery low |
| 4 | Cancelled |
| 6 | Failed, battery low |
| 7 | No cassette |
| 8 | Bay open |
| 9 | Cutter jam |
If you find this integration useful, you can buy me a coffee:
BSD 2-Clause. See LICENSE.