niimprint

repository·main·Indexed 17 days ago

https://github.com/andbondstyle/niimprint

A Python-based client and CLI for Niimbot printers (models B1, B18, B21, D11, and D110) that enables printing images via USB or Bluetooth. It provides a PrinterClient API for hardware communication, support for BluetoothTransport and SerialTransport, and tools for managing NiimbotPacket data, retrieving device metadata via InfoEnum, and reading RFID label information.

Tokens
3.6K
Snippets
15
Records
19
Agent score
65%

What's inside niimprint

  1. Configure image orientation and resolution

    main

    Image Orientation

    Images generally print with the same orientation seen on screen. Use the -r <degrees> flag to rotate the image clockwise (0, 90, 180, or 270) if needed.

    Image Resolution

    Niimbot printers operate at approximately 8 pixels per mm (~203 dpi). The CLI prints the image as-is, but will check if the width exceeds the printer's maximum capacity.

    Maximum Pixel Widths:

    • B21, B1, B18: ~384 pixels
    • D11: ~96 pixels
  2. Connect to Niimbot via USB

    main

    For USB connections, you can omit the --addr argument to attempt auto-detection. However, if multiple serial ports are available, you must specify the correct device path using -a.

    • Linux: Paths typically look like /dev/ttyUSB*, /dev/ttyACM*, or /dev/serial/*.
    • Windows: Paths are named COM1, COM2, etc. (check Device Manager).
  3. Connect to Niimbot via Bluetooth

    main

    When using Bluetooth, use the -c bluetooth flag and provide the MAC address with -a.

    Identifying the correct MAC address: Some models (like B21 and B1) may show two different Bluetooth addresses. To find the correct one, run bluetoothctl info <address>.

    • The correct address will list UUID: Serial Port.
    • The incorrect address will list UUID: Generic Access Profile and UUID: Generic Attribute Profile.

    Note: You may see a org.bluez.Error.NotAvailable br-connection-profile-unavailable error during connection; printing should still work.

  4. Initialize a PrinterClient with a Transport

    main

    To use niimprint, you must first instantiate a transport layer to handle communication with the printer, then pass that transport to a PrinterClient.

    Supported transports:

    • BluetoothTransport(address): Connects via Bluetooth RFCOMM to the specified MAC address.
    • SerialTransport(port): Connects via a serial port. If port="auto", it attempts to detect a single available serial port. If multiple ports are found, it raises a RuntimeError.

    Once the client is initialized, you can use its methods to control the printer and print images.

    from niimprint.printer import PrinterClient, BluetoothTransport, SerialTransport
    from PIL import Image
    
    # For Bluetooth connection
    transport = BluetoothTransport("XX:XX:XX:XX:XX:XX")
    client = PrinterClient(transport)
    
    # For Serial/USB connection
    transport = SerialTransport(port="/dev/ttyUSB0") # or "auto"
    client = PrinterClient(transport)
  5. Print examples

    main

    B21, USB connection, 30x15 mm (240x120 px) label

    python niimprint -c usb -a /dev/ttyACM0 -r 90 -i examples/B21_30x15mm_240x120px.png

    B21, Bluetooth connection, 80x50 mm (640x384 px) label

    python niimprint -c bluetooth -a "E2:E1:08:03:09:87" -r 90 -i examples/B21_80x50mm_640x384px.png
  6. Reference the niimprint CLI options

    main

    The following options are available for the niimprint command:

    OptionLong FlagDescription
    -m--modelNiimbot printer model: [b1|b18|b21|d11|d110] (default: b21)
    -c--connConnection type: [usb|bluetooth] (default: usb)
    -a--addrBluetooth MAC address OR serial device path
    -d--densityPrint density: 1<=x<=5 (default: 5)
    -r--rotateImage rotation (clockwise): [0|90|180|270] (default: 0)
    -i--imagePath to the image file (required)
    -v--verboseEnable verbose logging
    --help--helpShow this message and exit
    Options:
      -m, --model [b1|b18|b21|d11|d110]     Niimbot printer model  [default: b21]
      -c, --conn [usb|bluetooth]   Connection type  [default: usb]
      -a, --addr TEXT              Bluetooth MAC address OR serial device path
      -d, --density INTEGER RANGE  Print density  [default: 5; 1<=x<=5]
      -r, --rotate [0|90|180|270]  Image rotation (clockwise)  [default: 0]
      -i, --image PATH             Image path  [required]
      -v, --verbose                Enable verbose logging
      --help                       Show this message and exit.
  7. Use the niimprint CLI

    main

    The niimprint CLI allows you to print images to Niimbot printers via USB or Bluetooth. You must provide an image path using the -i or --image flag.

    python niimprint --help
  8. Use NiimbotPacket for printer communication

    main

    The NiimbotPacket class is used to encapsulate data sent to or received from a Niimbot printer. It handles the framing required by the protocol, including the header (0x55 0x55), footer (0xAA 0xAA), and a checksum calculation based on the packet type, length, and data payload.

    from niimprint.packet import NiimbotPacket
    
    # Creating a packet from raw data
    # type_ is an integer, data is a bytes object
    packet = NiimbotPacket(type_=0x01, data=b'\x01\x02\x03')
    
    # Convert the packet to bytes for transmission over USB or Bluetooth
    raw_bytes = packet.to_bytes()
    
    # Reconstruct a packet from received bytes
    received_packet = NiimbotPacket.from_bytes(raw_bytes)
  9. Use PrinterClient to control Niimbot printers

    main

    The PrinterClient is the primary interface for interacting with Niimbot printers. To use it, you must provide a transport instance (either BluetoothTransport or SerialTransport) to the PrinterClient constructor. This client manages the communication lifecycle with the printer hardware.

    from niimprint import PrinterClient, BluetoothTransport
    
    # Example initialization with Bluetooth
    transport = BluetoothTransport(address='XX:XX:XX:XX:XX:XX')
    client = PrinterClient(transport)
  10. Print an image using print_image()

    main

    The print_image method is the primary high-level API for printing. It handles the full lifecycle of a print job: setting density, label type, starting the print session, defining dimensions, encoding the image data, and waiting for the printer to finish.

    Parameters:

    • image: A PIL.Image.Image object.
    • density: An integer (default 3). Valid values are typically 1 to 5 depending on the printer model.

    Note: This method internally calls set_label_density, set_label_type, start_print, start_page_print, set_dimension, end_page_print, and end_print.

    from niimprint.printer import PrinterClient, SerialTransport
    from PIL import Image
    
    transport = SerialTransport(port="auto")
    client = PrinterClient(transport)
    
    img = Image.open("label_design.png")
    client.print_image(img, density=3)
  11. Check printer status with heartbeat()

    main

    The heartbeat() method retrieves the current state of the printer, including power levels and paper status. The returned dictionary structure may vary depending on the specific printer model's response length.

    Returned keys (if available):

    • closingstate: The state of the printer lid/cover.
    • powerlevel: The current battery/power level.
    • paperstate: The status of the paper/label roll.
    • rfidreadstate: The status of the RFID reader.
    status = client.heartbeat()
    print(f"Power Level: {status.get('powerlevel')}")
    print(f"Paper State: {status.get('paperstate')}")