flutter_zpl_printer 0.1.0 copy "flutter_zpl_printer: ^0.1.0" to clipboard
flutter_zpl_printer: ^0.1.0 copied to clipboard

Discover, connect to, and print on Zebra ZPL label printers over Bluetooth LE, Wi-Fi/TCP, and USB. Pure-Dart protocol stack, no Link-OS SDK required.

flutter_zpl_printer #

pub package

Discover, connect to, and print on Zebra ZPL label printers from Flutter over Bluetooth LE, Wi-Fi / TCP, and USB.

The plugin talks to the printer in Zebra's own protocols (SGD, ZPL ~HS status, Zebra BLE GATT services, USB printer class) from Dart. It does not depend on the Link-OS SDK, so there are no proprietary binaries to download or copy.

It pairs well with flutter_zpl_generator for building the ZPL you send.

Upgrading from 0.0.1? 0.1.0 is a full rewrite with a new API. See the migration table in the changelog.

๐Ÿ“˜ Integration guide: availability checks, discovery, transport fallback, printing, settings, error handling, and troubleshooting, based on a production app.


Platform support #

Transport iOS macOS Windows Android
Bluetooth LE โœ… โœ… โœ… โœ…
Wi-Fi / TCP โœ… โœ… โœ… โœ…
USB โž– not possible โšช not tested โŒ fails in testing โšช not tested, libusb not bundled

โœ… works in hardware testing ยท โŒ fails in hardware testing ยท โšช code exists, not verified on hardware ยท โž– platform limitation

USB, in short: experimental. It hasn't been confirmed working on any platform yet. It is untested on macOS and Android, it fails on Windows in our testing (cause not confirmed yet), and iOS doesn't allow it (USB calls throw UsbUnsupportedOnPlatformException). Use Bluetooth LE or Wi-Fi for production printing.


Installation #

dependencies:
  flutter_zpl_printer: ^0.1.0
import 'package:flutter_zpl_printer/flutter_zpl_printer.dart';

Platform setup #

iOS: ios/Runner/Info.plist
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Used to connect to Zebra printers over Bluetooth.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Used to discover Zebra printers on your local network.</string>

universal_ble (the BLE dependency) requires iOS 13.1 or later.

macOS: entitlements and Info.plist

macos/Runner/DebugProfile.entitlements and Release.entitlements:

<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>   <!-- needed to receive UDP discovery replies -->
<key>com.apple.security.device.bluetooth</key>
<true/>
<key>com.apple.security.device.usb</key>
<true/>

macos/Runner/Info.plist:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>Used to connect to Zebra printers over Bluetooth.</string>

The libusb dylib is bundled through the plugin's podspec. Nothing else to install.

Windows

Bluetooth LE and Wi-Fi need no extra setup. For USB, read Known issues โ†’ Windows USB first.

Android: AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

Request Bluetooth permissions at runtime (for example with permission_handler) before scanning.


Quick start #

1. Find a printer #

// USB + UDP broadcast/multicast + BLE, merged and de-duplicated.
await for (final printer in DiscoveryService.discoverAll()) {
  print('${printer.connectionType.displayName}: ${printer.friendlyName} @ ${printer.address}');
}

Or one transport at a time:

BleDiscovery.discoverZebra(timeout: const Duration(seconds: 10)); // Bluetooth LE
NetworkDiscovery.discover();                                       // UDP broadcast on port 4201
UsbDiscovery.enumerate();                                          // attached USB printers

2. Connect #

// From a discovery result: picks the right Connection type for you.
final printer = await ZebraPrinter.connect(discovered.createConnection());

// Or build a connection yourself:
final ble = BleConnection(deviceId);                                     // Bluetooth LE
final tcp = TcpConnection.zpl('192.168.1.50');                           // Wi-Fi, port 9100
final usb = UsbConnection(UsbDeviceAddress.parse('usb://0A5F:0027/XXSERIAL')); // USB

3. Print and query #

final status = await printer.getStatus();
if (status.isReadyToPrint) {
  await printer.printZpl('^XA^FO50,50^A0N,40,40^FDHello Zebra^FS^XZ');
} else if (status.isHeadOpen) {
  print('Close the print head');
} else if (status.isPaperOut) {
  print('Load labels');
}

final model = await printer.getSetting(PrinterSgdKey.deviceProductName.value);
final firmware = await printer.getSetting(PrinterSgdKey.applName.value);

await printer.calibrate();
await printer.printConfigurationLabel();

await printer.disconnect();

4. Handle errors #

Every transport throws ConnectionException or a subclass:

try {
  await printer.printZpl(zpl);
} on UsbDeviceBusyException catch (e) {
  showError(e.remediation ?? e.message); // tells the user how to fix it
} on ConnectionException catch (e) {
  showError(e.message);
}

The example app shows all three transports end to end. The integration guide covers the production details.


Features #

  • Connections: BleConnection, TcpConnection, UsbConnection, plus MultichannelBleConnection / MultichannelTcpConnection (separate print and status channels) and ReconnectableConnection (auto-reconnect with exponential backoff).
  • Discovery: UDP broadcast, directed broadcast, multicast, TCP subnet search, BLE scan, USB enumeration, and USB hot-plug events (UsbHotplugStream.events()).
  • Status: full ~HS parsing (isReadyToPrint, isPaperOut, isHeadOpen, isRibbonOut, isPaused, isHeadTooHot, labels remaining, and more).
  • SGD (Set/Get/Do): Sgd.get, Sgd.set, Sgd.doCommand, and a catalog of verified keys in PrinterSgdKey.
  • Files and formats: list, store, and delete files on E: / R:; store formats and print them with ^FN field data (FormatUtil.printStoredFormat).
  • Graphics: convert PNG/JPEG to GRF or compressed Z64 and print or store it (GraphicsUtil).
  • More utilities: FontUtil, AlertUtil, ProfileUtil (backup / restore), FirmwareUtil, ZplSanitizer.

SGD example #

final darkness = await Sgd.get(PrinterSgdKey.headDarknessSwitch.value, connection);
await Sgd.set(PrinterSgdKey.deviceFriendlyName.value, 'Warehouse-01', connection);

// Sgd.doCommand waits for a reply. Actions like device.reset never send one,
// so write those directly:
await connection.write(Uint8List.fromList(utf8.encode('! U1 do "device.reset" ""\r\n')));

USB details #

Check the platform table first. USB is part of DiscoveryService.discoverAll() by default, and USB failures there are swallowed, so other transports keep working.

// Plug/unplug events: macOS and Android. Not emitted on Windows yet.
UsbHotplugStream.events().listen((e) => print('${e.type} โ†’ ${e.address}'));

const cfg = ConnectionConfig(
  usbBulkTimeoutMs: 8000, // default 5000
  usbMaxChunkSize: 0,     // 0 = use the endpoint's wMaxPacketSize
  usbStallRetries: 3,
);
final conn = UsbConnection(address, config: cfg);

libusb 1.0.29 is bundled under third_party/libusb/ and linked dynamically (LGPL-2.1-or-later; see third_party/libusb/1.0.29/LICENSE).

Testing your app #

import 'package:flutter_zpl_printer/flutter_zpl_printer_testing.dart';

final fake = FakeUsbPlatform()..devices.add(UsbDeviceRecord(
  vendorId: 0x0A5F, productId: 0x0027, path: '/fake', hasPermission: true,
  serialNumber: 'XX1', interfaceNumber: 0, bulkInEndpoint: 0x81, bulkOutEndpoint: 0x01,
));
final conn = UsbConnection.withPlatform(UsbDeviceAddress.parse('usb://0A5F:0027/XX1'), fake);

Known issues #

Windows USB #

Status: USB printing on Windows failed when tested with Zebra printers. The cause is not confirmed yet. Bluetooth LE and Wi-Fi work on Windows. Until this is fixed, treat Windows USB as experimental and offer Wi-Fi or Bluetooth.

What the Windows USB code does in 0.1.0:

  • Lists printers with Windows SetupAPI.
  • Opens them through libusb (libusb-1.0.dll), assuming interface 0, bulk endpoints 0x01 / 0x81, and 64-byte packets. It doesn't read these from the printer yet.
  • Does not emit plug/unplug events. UsbHotplugStream.events() stays silent on Windows.

Possible causes we're investigating:

  1. libusb-1.0.dll is not bundled. If the build log says libusb-1.0.dll not found, opens fail with UsbLibLoadException. Workaround: put the official libusb 1.0.29 VS2022/MS64/dll/libusb-1.0.dll next to your app's .exe.
  2. The printer is bound to the Windows printer driver. With Zebra Setup Utilities / ZDesigner installed, Windows binds the printer to usbprint and libusb can't claim it. You get UsbDeviceBusyException; show its remediation text. Rebinding to WinUSB with Zadig gives libusb access, but then the Windows print queue can't use the printer.
  3. The assumed endpoints don't match the printer. That would show as a transfer timeout or stall on write.

If you try it, please report your printer model, Windows version, the driver shown in Device Manager, and the exception text on the issue tracker.

Android USB #

Android USB needs libusb-1.0.so built per ABI with the NDK. 0.1.0 does not ship those binaries, so Android USB calls fail with UsbLibLoadException. See tool/fetch_libusb.sh.

Other limitations #

  • Classic Bluetooth (iOS MFi, Android SPP) is not supported. Use Bluetooth LE.
  • Status parsing targets ZPL. CPCL printers connect and print, but status objects are ZPL-specific.
  • TLS connections are not supported. TCP is plaintext.

Contributing #

Issues and pull requests are welcome at github.com/minhtri1401/flutter_zpl_printer.

This package is not affiliated with or endorsed by Zebra Technologies. Zebra, Link-OS, and ZPL are trademarks of Zebra Technologies Corp.

License #

MIT for this package. Bundled libusb is LGPL-2.1-or-later.

1
likes
0
points
36
downloads

Documentation

Documentation

Publisher

verified publishertritoone.com

Weekly Downloads

Discover, connect to, and print on Zebra ZPL label printers over Bluetooth LE, Wi-Fi/TCP, and USB. Pure-Dart protocol stack, no Link-OS SDK required.

Repository (GitHub)
View/report issues

Topics

#zebra #zpl #printer #bluetooth #usb

License

unknown (license)

Dependencies

archive, ffi, flutter, image, meta, universal_ble

More

Packages that depend on flutter_zpl_printer

Packages that implement flutter_zpl_printer