zebra_rfid_plus 0.0.2 copy "zebra_rfid_plus: ^0.0.2" to clipboard
zebra_rfid_plus: ^0.0.2 copied to clipboard

PlatformAndroid

A Flutter plugin for Zebra RFID readers (RFD8500, RFD40, RFD90) using the Zebra RFID API3 SDK. Supports Bluetooth and USB transport, inventory scanning, tag access, pre-filters, and singulation control.

zebra_rfid_plus #

pub package Platform License: MIT

A Flutter plugin for Zebra RFID readers using the official Zebra RFID API3 SDK v2.0.5.238.

Supports inventory scanning, Impinj GEN2X extensions (Tag Focus, Tag Quiet, Tag Protect, Fast Tag), tag read/write/lock/kill, pre-filters, singulation control, USB Data Wedge mode, and a stateful ZebraRfidController for easy integration.

Android only. The Zebra RFID SDK does not support iOS.


Table of Contents #


Supported Devices #

Device Transport Min Android GEN2X
RFD8500 Bluetooth 8
RFD40 Bluetooth 10
RFD40 Premium Bluetooth 10
RFD40 Premium Plus Bluetooth 10
RFD90 Bluetooth / USB 10
FXR90 USB / ZIOTC 10
FXP20 USB 10
TC53e Integrated 11
EM45 Integrated 10
ET6X Integrated 10
TC22R Integrated 14
WS50 USB Data Wedge 10
MC33xR Integrated 11

Features #

  • 🔌 Connect via Bluetooth, USB, Serial, or USB Data Wedge (WS50)
  • 📡 Real-time tag read stream with EPC and RSSI
  • 🔘 Physical trigger button events (press / release)
  • 🔦 Barcode scan support (when in barcode trigger mode)
  • ⚙️ Antenna power, RF mode, singulation (S0–S3)
  • 🔍 Pre-filter by EPC pattern, TID, or User memory
  • 📝 Tag memory read / write / lock / kill
  • 🧬 Impinj GEN2X extensions (SDK v2.0.5.214+):
    • Tag Focus — inventory only unseen tags
    • Tag Quiet — suppress already-processed tags
    • Tag Visibility — hide from non-Impinj readers
    • Tag Protection — prevent unauthorised kill/lock
    • Fast Tag — dense population throughput (v2.0.5.238+)
  • 🧠 ZebraRfidController — ChangeNotifier with de-duplication + auto trigger linking
  • 📊 getReaderCapabilities — firmware version, max power index, GEN2X support flag
  • 🔔 Typed ZebraRfidException with ZebraRfidErrorCode constants

Installation #

1. Add dependency #

dependencies:
  zebra_rfid_plus: ^0.0.1

2. Place Zebra SDK AARs #

The Zebra RFID SDK is proprietary and must be obtained separately from Zebra. Download: https://www.zebra.com/ap/en/support-downloads/software/rfid-software/rfid-sdk-for-android.html

Copy all .aar files from the Zebra SDK zip into android/app/libs/:

android/app/libs/
  rfidhostlib.aar
  rfidseriallib.aar
  BarcodeScannerLibrary.aar
  API3_CMN-release-2.0.5.238.aar
  API3_TRANSPORT-release-2.0.5.238.aar
  API3_NGE-protocolrelease-2.0.5.238.aar
  API3_NGE-Transportrelease-2.0.5.238.aar
  API3_NGEUSB-Transportrelease-2.0.5.238.aar
  API3_LLRP-release-2.0.5.238.aar
  API3_ASCII-release-2.0.5.238.aar
  API3_INTERFACE-release-2.0.5.238.aar
  API3_READER-release-2.0.5.238.aar
  API3_ZIOTC-release-2.0.5.238.aar
  API3_ZIOTCTRANSPORT-release-2.0.5.238.aar

In android/app/build.gradle:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'])
}

3. Permissions #

Add to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
    android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

ZebraRfidController is a ChangeNotifier that manages connection state, tag de-duplication, trigger linking, and error state — ready to use directly with ListenableBuilder or setState.

import 'package:zebra_rfid_plus/zebra_rfid_plus.dart';

class _ScannerPageState extends State<ScannerPage> {
  final _controller = ZebraRfidController();

  @override
  void initState() {
    super.initState();
    _controller.init();
    _controller.addListener(() => setState(() {}));
    // Physical trigger press auto-starts/stops inventory
    _controller.linkTriggerToInventory(enabled: true);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Status: ${_controller.connectionStatus.name}'),
        Text('Tags found: ${_controller.tagCount}'),
        if (_controller.lastError != null)
          Text('Error: ${_controller.lastError}',
              style: const TextStyle(color: Colors.red)),
        ElevatedButton(
          onPressed: () => _controller.isConnected
              ? _controller.disconnect()
              : _controller.connect(),
          child: Text(_controller.isConnected ? 'Disconnect' : 'Connect'),
        ),
        ElevatedButton(
          onPressed: _controller.isConnected
              ? (_controller.isScanning
                  ? _controller.stopInventory
                  : _controller.startInventory)
              : null,
          child: Text(_controller.isScanning ? 'Stop' : 'Start Inventory'),
        ),
        ElevatedButton(
          onPressed: _controller.clearTags,
          child: const Text('Clear Tags'),
        ),
        Expanded(
          child: ListView.builder(
            itemCount: _controller.tags.length,
            itemBuilder: (_, i) {
              final tag = _controller.tags[i];
              return ListTile(
                title: Text(tag.tagId),
                subtitle: Text('RSSI: ${tag.peakRssi} dBm'),
              );
            },
          ),
        ),
      ],
    );
  }
}

Low-Level API — ZebraRfid static methods #

import 'package:zebra_rfid_plus/zebra_rfid_plus.dart';

// Initialise once
await ZebraRfid.initialize();

// Discover readers
final readers = await ZebraRfid.getAvailableReaders();

// Connect (uses first available reader if name is omitted)
await ZebraRfid.connect(readerName: readers.first.name);

// Configure antenna
await ZebraRfid.setAntennaConfig(
  const RfidAntennaConfig(transmitPowerIndex: 270),
);

// Listen to tag reads
ZebraRfid.onTagRead.listen((tag) {
  print('${tag.tagId}  RSSI=${tag.peakRssi}');
});

// Scan
await ZebraRfid.startInventory();
await Future.delayed(const Duration(seconds: 5));
await ZebraRfid.stopInventory();

// Read a memory bank
await ZebraRfid.readTagMemory(
  tagId: 'E28011C1A5000062F792696D',
  memoryBank: RfidMemoryBank.tid,
  wordCount: 6,
);
// Result arrives on onTagRead with tag.memoryBankData set

await ZebraRfid.disconnect();
await ZebraRfid.dispose();

API Reference #

Connection #

Method Returns Description
ZebraRfid.initialize() Future<void> Init SDK. Call once.
ZebraRfid.dispose() Future<void> Release all resources.
ZebraRfid.getAvailableReaders({transport}) Future<List<RfidReaderDevice>> Discover readers.
ZebraRfid.connect({readerName, transport}) Future<bool> Connect to reader.
ZebraRfid.disconnect() Future<void> Disconnect.
ZebraRfid.isConnected() Future<bool> Connection check.
ZebraRfid.getReaderCapabilities() Future<RfidReaderCapabilities> Firmware, power, GEN2X flag.

Inventory #

Method Description
ZebraRfid.startInventory() Begin scanning. Tags arrive on onTagRead.
ZebraRfid.stopInventory() Stop scanning.

Configuration #

Method Description
ZebraRfid.setAntennaConfig(config) Power index, RF mode, tari.
ZebraRfid.setSingulationConfig(config) Session S0–S3, inventory state A/B.
ZebraRfid.setTriggerMode({rfidMode}) RFID or barcode trigger.
ZebraRfid.resetToDefaults() Restore SDK defaults.

Pre-filters #

Method Description
ZebraRfid.addPreFilter(filter) Filter by EPC/TID/User pattern.
ZebraRfid.clearPreFilters() Remove all filters.
ZebraRfid.getPreFilterCount() Count active filters.

Tag Access #

Method Description
ZebraRfid.readTagMemory({tagId, memoryBank, ...}) Read memory bank. Result on onTagRead.
ZebraRfid.writeTagMemory({tagId, memoryBank, data, ...}) Write to memory bank.
ZebraRfid.lockTag({tagId, params}) Lock a memory field.
ZebraRfid.killTag({tagId, killPassword}) ⚠️ Permanently kill a tag.

Impinj GEN2X Extensions #

Requires RFD40 Premium Plus, RFD90, FXR90, MC33xR, TC53e, or TC22R. Always check RfidReaderCapabilities.supportsGen2x before calling these.

Method Description
ZebraRfid.setTagFocus(config) New-tags-only inventory.
ZebraRfid.setTagQuiet(config) Suppress already-processed tags.
ZebraRfid.setTagVisibility(config) Hide tags from non-Impinj readers.
ZebraRfid.setTagProtection(config) Prevent unauthorised kill/lock.
ZebraRfid.setFastTag(config) Dense population throughput mode (v2.0.5.238+).

Streams #

Stream Type Description
ZebraRfid.onTagRead Stream<RfidTag> Tag reads + memory bank access results.
ZebraRfid.onConnectionStatus Stream<RfidConnectionEvent> Connection state changes.
ZebraRfid.onTriggerEvent Stream<bool> true = pressed, false = released.
ZebraRfid.onBarcodeRead Stream<String> Barcode data (barcode mode only).

Models #

/// Tag read event — also used for memory bank access results.
class RfidTag {
  final String tagId;           // EPC identifier (hex string)
  final int peakRssi;           // Peak signal strength in dBm
  final DateTime timestamp;
  final int? seenCount;
  final int? firstSeenTime;
  final int? lastSeenTime;
  final String? memoryBankData; // Populated after readTagMemory()
}

/// Discovered reader.
class RfidReaderDevice {
  final String name;
  final RfidTransport transport;       // bluetooth | usb | serial | usbDataWedge
  final RfidDeviceType deviceType;     // Auto-detected from reader hostname
  bool get supportsGen2x;
}

/// Reader hardware capabilities.
class RfidReaderCapabilities {
  final String modelName;
  final String? serialNumber;
  final String? firmwareVersion;
  final int antennaCount;
  final int maxTransmitPowerIndex;
  final bool supportsGen2x;
  final bool hasTrigger;
}

/// Connection event delivered on onConnectionStatus.
class RfidConnectionEvent {
  final RfidConnectionStatus status; // connected | disconnected | connecting | error
  final String? readerName;
  final String? message;
}

Enums #

enum RfidTransport       { bluetooth, usb, serial, usbDataWedge }
enum RfidMemoryBank      { epc, tid, user, reserved }
enum RfidSession         { s0, s1, s2, s3 }
enum RfidInventoryState  { stateA, stateB }
enum RfidConnectionStatus{ connected, disconnected, connecting, error }
enum RfidLockField       { epcMemory, userMemory, tid, accessPassword, killPassword }
enum RfidLockPrivilege   { lock, unlock, permanentLock, permanentUnlock, securedLock }

Impinj GEN2X Extensions #

final caps = await ZebraRfid.getReaderCapabilities();

if (caps.supportsGen2x) {
  // Only inventory tags not seen before in this session
  await ZebraRfid.setTagFocus(
    const ImpinjTagFocusConfig(enable: true, antennaId: 1),
  );

  // Suppress tags already processed
  await ZebraRfid.setTagQuiet(
    const ImpinjTagQuietConfig(
      masks: [TagQuietMask.tid],
      target: ImpinjTarget.sl,
      action: ImpinjStateAwareAction.assertSl,
    ),
  );

  // High-throughput mode for dense tag populations (v2.0.5.238+)
  await ZebraRfid.setFastTag(
    const ImpinjFastTagConfig(enable: true),
  );
}

Error Handling #

All methods throw ZebraRfidException on failure.

try {
  await ZebraRfid.startInventory();
} on ZebraRfidException catch (e) {
  switch (e.code) {
    case ZebraRfidErrorCode.notConnected:
      print('Reader is not connected');
    case ZebraRfidErrorCode.gen2xNotSupported:
      print('This reader does not support GEN2X');
    default:
      print('RFID error ${e.code}: ${e.message}');
      if (e.detail != null) print('Detail: ${e.detail}');
  }
}

Error Codes #

Constant Value When thrown
notConnected NOT_CONNECTED Operation called without a connected reader
connectFailed CONNECT_FAILED Connection attempt failed
noReader NO_READER No reader discovered
inventoryFailed INVENTORY_FAILED startInventory / stopInventory failed
configFailed CONFIG_FAILED Antenna or singulation config failed
filterFailed FILTER_FAILED Pre-filter operation failed
readFailed READ_FAILED readTagMemory failed
writeFailed WRITE_FAILED writeTagMemory failed
lockFailed LOCK_FAILED lockTag failed
killFailed KILL_FAILED killTag failed
notInitialized NOT_INITIALIZED Plugin channel not set up (missing SDK AARs)
tagFocusFailed TAG_FOCUS_FAILED setTagFocus failed
tagQuietFailed TAG_QUIET_FAILED setTagQuiet failed
tagVisibilityFailed TAG_VISIBILITY_FAILED setTagVisibility failed
tagProtectionFailed TAG_PROTECTION_FAILED setTagProtection failed
fastTagFailed FAST_TAG_FAILED setFastTag failed
gen2xNotSupported GEN2X_NOT_SUPPORTED GEN2X called on non-capable reader

Device Compatibility Notes #

  • RFD8500: Bluetooth only. Android 8–14. Validated on TC56, TC52, MC33xR, TC26, TC53, TC73, EC50, TC52AX, TC22R.
  • WS50: USB Data Wedge mode added in SDK v2.0.5.238. Use RfidTransport.usbDataWedge.
  • FXR90: Supports ZIOTC transport in addition to standard API3.
  • GEN2X features: Require EU-RED GEN2X compliant firmware (SDK v2.0.5.226+).
  • Fast Tag: Requires SDK v2.0.5.238+ and compatible reader firmware.

SDK Reference #


Contributing #

See CONTRIBUTING.md for guidelines.


License #

MIT — see LICENSE.


Disclaimer #

Unofficial community wrapper. Not affiliated with Zebra Technologies Corporation. The Zebra RFID API3 SDK is proprietary software — obtain it separately and comply with Zebra's licence terms.

2
likes
150
points
13
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for Zebra RFID readers (RFD8500, RFD40, RFD90) using the Zebra RFID API3 SDK. Supports Bluetooth and USB transport, inventory scanning, tag access, pre-filters, and singulation control.

Repository (GitHub)
View/report issues
Contributing

Topics

#rfid #zebra #bluetooth #hardware #nfc

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on zebra_rfid_plus

Packages that implement zebra_rfid_plus