sunmi_external_cloud_printer

A Flutter plugin for Sunmi external cloud printers — NT21x, NT31x, and NT32x series — over USB, LAN, and Bluetooth. Android only.

Features

  • Scan for nearby Sunmi cloud printers (USB, LAN, Bluetooth)
  • Connect and disconnect by printer ID
  • Query printer status (isReady, description)
  • Build and commit rich print jobs with a fluent PrintJob API:
    • Text alignment (left / center / right)
    • Character size multiplier (width × height, 1–4)
    • Bold text
    • Line feeds
    • Full or partial paper cut
    • QR code printing (size 1–16, four error-correction levels)

Getting started

Prerequisites

  • Android only (iOS is not supported by Sunmi hardware)
  • Flutter >=3.3.0, Dart SDK >=3.8.1
  • A physical Sunmi NT21x, NT31x, or NT32x device

Add the dependency

dependencies:
  sunmi_external_cloud_printer: ^0.2.0

Then run:

flutter pub get

No additional Android permissions are required beyond those already declared by the plugin.

Usage

1 — Scan for printers

import 'package:sunmi_external_cloud_printer/sunmi_external_cloud_printer.dart';

final printer = SunmiExternalCloudPrinter();

final printers = await printer.scan(timeoutSeconds: 5);
for (final p in printers) {
  print('${p.name} [${p.connectionType}] — ${p.id}');
}

2 — Connect

final connected = await printer.connect(printers.first.id);
if (!connected) {
  print('Connection failed');
  return;
}

3 — Build and commit a print job

final result = await printer.commit(
  PrintJob()
    ..initStyle()
    ..setAlignment(SunmiPrintAlignment.center)
    ..setCharacterSize(2, 2)
    ..appendText('RECEIPT\n')
    ..setCharacterSize(1, 1)
    ..setAlignment(SunmiPrintAlignment.left)
    ..appendText('Item 1 ............... 10.00\n')
    ..appendText('Item 2 ............... 25.00\n')
    ..setBold(enabled: true)
    ..appendText('Total ................ 35.00\n')
    ..setBold(enabled: false)
    ..printQrCode('https://example.com/order/123', size: 6)
    ..lineFeed(3)
    ..cutPaper(),
);

if (result.success) {
  print('Printed: ${result.message}');
} else {
  print('Error: ${result.message}');
}

4 — Check status and disconnect

final status = await printer.getStatus();
print('Ready: ${status.isReady} — ${status.description}');

await printer.disconnect();

A full working example is available in the /example folder.

Connection types

The plugin supports three physical connection modes. When scan() is called, all three are probed simultaneously. Each discovered printer exposes its type via SunmiDiscoveredPrinter.connectionType ("USB", "LAN", or "Bluetooth").

USB

  • Plug the printer into the Android device's USB-A or USB-C (OTG) port.
  • No pairing or network configuration is required.
  • SunmiDiscoveredPrinter.vid and .pid hold the USB vendor ID and product ID respectively (useful for filtering specific hardware).
  • The plugin holds a USB device claim for the duration of the connection; call disconnect() to release it before the app goes to the background if you need to share the port.
  • Priority: USB connections are preferred when auto-selecting (USB → LAN → Bluetooth).

LAN (Local Area Network)

  • Printer and device must be on the same Wi-Fi or Ethernet segment.
  • SunmiDiscoveredPrinter.address contains the printer's IPv4 address and .port contains the TCP port (default 9100).
  • Static IP assignment on the printer is recommended for production deployments to avoid address changes between scans.
  • Discovery uses UDP broadcast; ensure the network does not block broadcast traffic between subnets.
  • The connection is a persistent TCP socket; if the socket drops (e.g. DHCP lease renewal), call disconnect() then connect() again.

Bluetooth

  • Supports Bluetooth Classic (SPP profile). Bluetooth LE is not supported.
  • Pair the printer with the Android device via Settings → Bluetooth before scanning — the plugin does not handle the pairing handshake.
  • SunmiDiscoveredPrinter.mac holds the Bluetooth MAC address (e.g. "AA:BB:CC:DD:EE:FF").
  • Bluetooth range is typically 5–10 m; signal drops will cause the connection to time out. Add retry logic in production apps.
  • Android 12+ requires the BLUETOOTH_CONNECT and BLUETOOTH_SCAN runtime permissions. Declare and request them in your app before calling scan().

API reference

SunmiExternalCloudPrinter

Method Returns Description
scan({int timeoutSeconds}) Future<List<SunmiDiscoveredPrinter>> Scans for nearby printers
connect(String id) Future<bool> Connects to a printer by ID
isConnected() Future<bool> Whether a printer is currently connected
disconnect() Future<void> Disconnects and releases the connection
getStatus() Future<SunmiPrinterStatus> Returns current printer status
commit(PrintJob job) Future<SunmiPrintResult> Executes all job commands and flushes to printer

PrintJob commands

Method Description
initStyle() Resets all style settings to defaults
setAlignment(SunmiPrintAlignment) left, center, or right
setCharacterSize(int w, int h) Width and height multiplier 1–4
setBold({required bool enabled}) Bold on/off
appendText(String text) Appends text; use \n for line breaks
lineFeed([int lines]) Feeds blank lines (default 1)
cutPaper({bool partial}) Full cut (default) or partial cut
printQrCode(String data, {int size, SunmiQrErrorLevel errorLevel}) Prints a QR code

Additional information