Skip to content

Latest commit

 

History

238 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hass-niimbot

HACS GitHub Release License integration usage

Niimbot Label Printer Home Assistant Integration

Gallery

B1 / B1 Pro B21 Pro D110
B1 / B1 Pro B21 Pro D110

Important

For all NIIMBOT users using Bluetooth proxies: Please update your proxy devices to ESPHome 2025.11.2 or later.

Benefits of updating:

  • Much faster printing (almost instant)
  • Greatly improved reliability
  • Reduced delays thanks to improved internal GATT handling

Feedback & Support


Stash can print labels via this Home Assistant integration.

Supported Models

Model Status
B1 confirmed
B1 Pro confirmed
B2 Pro confirmed
B21 Pro confirmed
D110 confirmed
Other models with Bluetooth may work

Installation

  1. Install with HACS (custom repository required), or copy this repo into custom_components/niimbot.
  2. Restart Home Assistant.
  3. Go to SettingsIntegrations and add Niimbot.
  4. Select a discovered printer from the list.

Important Notice

It is strongly recommended to use a Bluetooth proxy instead of a built-in Bluetooth adapter for more stable connections and better range.

When using a proxy, keep the scan interval reasonable. Example ESPHome config:

esp32_ble_tracker:
  scan_parameters:
    active: true

bluetooth_proxy:
  active: true

Options

Configure via SettingsDevices & ServicesNiimbotConfigure:

Option Default Range Description
Scan Interval 600 10–9999 s How often to poll printer status
Wait Between Each Print Line 10 0–1000 ms Delay between each line sent to the printer
Confirm Every Nth Print Line 16 1–512 Confirm every N lines (higher = faster, less reliable)
Keep Connection Off On/Off Keep the BLE link open between polls and prints

Connection beep is a Connection Sound switch entity (not an option). Auto shutdown is an Auto Shutdown select entity.

Tip

Defaults already favour speed. If prints fail or look corrupted, raise wait / lower confirm interval. See Increasing print speed.


Entities

Platform Entity Notes
Sensor Battery Prefer heartbeat; PrinterInfo charge bucket as fallback
Sensor Labels Remaining / Used / Total, Consumable Usage, Label SKU Label RFID models only
Sensor Ribbon Remaining / Used / Total, Ribbon Usage, Ribbon SKU Ribbon RFID models only
Sensor Label Type PrinterInfo, overridden by RFID tag type when present
Sensor Print Progress / Print Duration Live during niimbot.print
Sensor Last Error, Print Density, Print Speed, Protocol Version, Colour Support, Print Area Diagnostic (some disabled by default)
Binary sensor Cover Label bay cover — Open / Closed
Binary sensor Paper Loaded / Empty
Binary sensor RFID Tag readable / not readable
Binary sensor Connection BLE connectivity
Select Auto Shutdown Typical 15 / 30 / 45–60 / 60–never (model-dependent)
Switch Connection Sound Bluetooth connect beep
Image Last Label Made Updated on every print or preview

Payload & rendering (imagespec)

From version 2.0.0, labels are rendered with imagespec — a declarative YAML/JSON list of drawing elements that becomes a bitmap sent to the printer.

Documentation (maintained in imagespec, not duplicated here):

Topic Link
Element examples with preview images imagespec/docs/elements.md
All element fields & defaults imagespec README — Element Reference
Layout, palette, LLM authoring guide imagespec/docs/authoring.md
Dithering (per-element only) imagespec/docs/dithering.md

Niimbot-specific behaviour:

  • Palette: black & white only. Off-palette colors (e.g. red, orange) are quantized to the nearest supported color.
  • Rotation: rotate: 90/180/270 rotates the drawing and swaps output width/height (label-printer mode).
  • Default font: ppb.ttf in custom_components/niimbot/fonts/. Custom fonts also work from www/fonts/.
  • plot element: reads history from Home Assistant Recorder.
  • Dithering: not a service option. Put dither on photos and charts in the payload — dlimg, pie, diagram, plot, sparkline, progress_bar, gauge — when they use off-palette colors. Leave text/QR/barcodes without dither. See dithering.md.
  • Layout: prefer row / column / stack for stacked content instead of hand-calculated coordinates.

Service: niimbot.print

Parameters

Parameter Required Default Description
payload yes List of imagespec elements
rotate no 0 0, 90, 180, or 270
width no 400 Label width in pixels (10–1600)
height no 240 Label height in pixels (10–1600)
density no 3 Print density (model range, typically 1–5; some up to 20)
label_type no 1 Paper type code (1 WithGaps, 2 Black, 3 Continuous, …)
copies no 1 Number of copies in one print job
wait_between_print_lines no device option Seconds between lines (device default 10 ms)
print_line_batch_size no device option Lines per batch before confirmation (device default 16)
preview no false Render only; do not send to the printer

Use response_variable in scripts to receive the generated image as a data: URL when preview: true.

There is also niimbot.refresh_info to re-read cached printer settings (density, label type, auto shutdown, battery bucket, protocol/area).

Basic example

action: niimbot.print
target:
  device_id: <your device>
data:
  payload:
    - type: text
      value: Hello World!
      font: ppb.ttf
      x: 10
      y: 10
      size: 40
    - type: qrcode
      data: "https://www.home-assistant.io"
      x: 280
      y: 10
      width: 80
      height: 80
  width: 400
  height: 240

Per-element dither (photos / charts)

Do not dither the whole label. Add dither on chart/media elements that use off-palette colors (dlimg, pie, diagram, plot, sparkline, progress_bar, gauge):

action: niimbot.print
target:
  device_id: <your device>
data:
  payload:
    - type: text
      value: Product
      x: 10
      y: 8
      size: 28
    - type: dlimg
      url: "https://example.com/photo.jpg"
      x: 10
      y: 40
      xsize: 120
      ysize: 90
      dither: floyd
    - type: pie
      x: 150
      y: 40
      radius: 40
      values: "A,40,orange;B,60,blue"
      dither: atkinson
    - type: diagram
      x: 250
      y: 40
      width: 130
      height: 90
      bars:
        values: "Mon,10;Tue,25;Wed,15;Thu,30"
        color: orange
      dither: bayer8

Model-specific sizes

D110 (small label, often rotated):

action: niimbot.print
target:
  device_id: <your device>
data:
  payload:
    - type: text
      value: "Hello World!"
      font: ppb.ttf
      x: 10
      y: 10
      size: 30
  rotate: 90
  width: 240
  height: 96

B21 Pro (large label, high density):

action: niimbot.print
target:
  area_id: kitchen
data:
  payload:
    - type: rectangle
      x_start: 0
      x_end: 584
      y_start: 0
      y_end: 354
      fill: black
  width: 584
  height: 354
  density: 5

Preview without printing

Use preview: true while designing labels so nothing is sent to the printer. The Niimbot Payload Layout Editor can generate YAML via drag-and-drop — paste the result here and preview first.

action: niimbot.print
target:
  device_id: <your device>
data:
  preview: true
  payload:
    - type: text
      value: Preview Test
      x: 10
      y: 10
      size: 30
  width: 400
  height: 240

Every print or preview updates image.<device>_last_label_made (disable in entity settings if unwanted).


Script: multiline address label

new_multiline with fit: true shrinks text to fit the label box — useful for shipping addresses:

alias: Print label with multiple lines of text
fields:
  contents:
    selector:
      text:
        multiline: true
    name: Contents
    required: true
sequence:
  - action: niimbot.print
    target:
      area_id: kitchen
    data:
      payload:
        - type: new_multiline
          x: 0
          y: 20
          size: 100
          width: 520
          height: 300
          fit: true
          font: rbm.ttf
          value: "{{ contents }}"
      width: 584
      height: 350
      density: 5

See new_multiline in imagespec for fit_width, fit_height, and spacing options.


Increasing print speed

The printer receives data line by line. Over Bluetooth proxies, waiting for a response on every line adds up — especially on dense labels. From 3.0.0 the integration defaults are already 10 ms wait and confirm every 16 lines, plus indexed/empty-row packing and mid-transfer checkpoints.

Tune per call if needed:

action: niimbot.print
target:
  device_id: <your device>
data:
  payload:
    - type: rectangle
      x_start: 0
      x_end: 10
      y_start: 0
      y_end: 600
      fill: black
  width: 584
  height: 350
  density: 5
  wait_between_print_lines: 0.01
  print_line_batch_size: 16

Persist working values in Configure (wait_between_print_lines × 1000 → ms for Wait Between Each Print Line). Enabling Keep Connection also cuts reconnect overhead between jobs.

Anecdotally, B21 Pro on a busy network is reliable at 10 ms wait and batch size 16. Report what works for your setup in issues.


Preview on a dashboard

With preview: true and response_variable, a script can save the rendered image to disk and show it on a dashboard camera card.

  1. Add to configuration.yaml:
shell_command:
  update_label: >-
    bash -c 'set -o pipefail; echo "$0" | cut -d, -f2 | base64 -d >/config/www/label.png' {{ image_data }}
  1. Add a Local file camera pointing at /config/www/label.png.

  2. Script to preview and update the file:

alias: Iterate on a label
fields:
  payload:
    selector:
      object: {}
    name: Payload
sequence:
  - action: niimbot.print
    target:
      device_id: <your device id>
    data:
      payload: "{{ payload }}"
      width: 584
      height: 350
      density: 5
      preview: true
    response_variable: previewed
  - action: shell_command.update_label
    data:
      image_data: "{{ previewed.image }}"

Tools

Niimbot Payload Layout Editor — drag-and-drop layout designer; exports YAML for niimbot.print.


Examples

Example Description
examples/grocy/README.md Print a Grocy product label via webhook

Protocol documentation

Reverse-engineered reference for the printers' BLE protocol.

Document Contents
docs/protocol.md Transport, packet framing, full command ID tables, error codes
docs/device-info.md Connect handshake, printer info fields, heartbeat variants, print status
docs/printing.md Image encoding, page setup, per-generation print sequences, completion detection
docs/rfid.md Reading consumable info from label / ribbon RFID tags
docs/devices.md Model IDs, DPI, print widths, density ranges and RFID class per model
docs/app-gap-analysis.md What the official app does that this integration does not, and why some of it is deliberately out of scope
docs/improvement-plan.md Open work, with what shipped in 3.0.0 recorded for context
docs/work-plan.md Task orders for that open work — files, changes, tests, acceptance criteria

Custom fonts

Place .ttf files in custom_components/niimbot/fonts/ or config/www/fonts/ and reference by filename (e.g. ppb.ttf, rbm.ttf).


References

About

Niimbot Label Printer Home Assistant Integration

Topics

Resources

Stars

115 stars

Watchers

4 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages