rfid_ble_plugin 0.0.7
rfid_ble_plugin: ^0.0.7 copied to clipboard
A Flutter plugin for BLE RFID reader communication using Objective-C on iOS.
example/lib/main.dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:rfid_ble_plugin/rfid_ble_plugin.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
StreamSubscription? _scanSubscription;
StreamSubscription? _rfidSubscription;
StreamSubscription? _configSubscription;
StreamSubscription<bool>? _connectionSubscription;
bool _isConnected = false;
List<Map<String, String>> devices = [];
List<Map<String, dynamic>> tags = [];
Timer? _batteryTimer;
String? _batteryLevel;
@override
void initState() {
super.initState();
checkConnectionStatus();
}
//#region BLE Activities
Future<void> checkConnectionStatus() async {
_connectionSubscription?.cancel();
// Lắng nghe trạng thái kết nối BLE
_connectionSubscription = RfidBlePlugin.connectionState.listen((
isConnected,
) {
setState(() {
_isConnected = isConnected;
});
debugPrint(
"🔌 Trạng thái kết nối: ${isConnected ? "Đã kết nối" : "Mất kết nối"}",
);
});
}
void startScan() {
_scanSubscription?.cancel();
setState(() {
devices.clear();
});
RfidBlePlugin.startScan();
_scanSubscription = RfidBlePlugin.scanResults.listen((device) {
if (!devices.any((d) => d['uuid'] == device['uuid'])) {
setState(() {
devices.add(device);
});
debugPrint('📡 Found: ${device['name']} - ${device['uuid']}');
}
});
}
void stopScan() {
RfidBlePlugin.stopScan();
_scanSubscription?.cancel();
_scanSubscription = null;
}
Future<void> getBetteryLevel() async {
await _listenConfig();
}
void connectToDevice(Map<String, dynamic> device) async {
try {
checkConnectionStatus(); // recall stream, if die
final result = await RfidBlePlugin.connectToDevice(
device["uuid"],
device["mac"],
);
if (kDebugMode) {
print("✅ Connected: $result");
}
} catch (e) {
if (kDebugMode) {
print("❌ Failed to connect: $e");
}
}
}
void disconnectDevice() {
RfidBlePlugin.disconnectDevice();
}
void startSingleInventory() {
setState(() => tags.clear());
RfidBlePlugin.singleInventory();
_listenRfidTags();
}
void clearData() {
setState(() => tags.clear());
}
void startContinuousInventory() {
setState(() => tags.clear());
RfidBlePlugin.startInventory();
_listenRfidTags();
}
Future<void> _listenConfig() async {
_configSubscription?.cancel();
_configSubscription = RfidBlePlugin.configStream.listen((event) {
// Press scan key
if (event['event'] == 'press_key') {
debugPrint("🔘 Key pressed from native: ${event['value']}");
}
// PIN %
else if (event['event'] == 'battery') {
setState(() {
_batteryLevel = event['event'];
debugPrint("🔋 Battery (from config stream): $_batteryLevel%");
});
}
});
RfidBlePlugin.getBatteryLevel();
}
void _listenRfidTags() {
try {
_rfidSubscription?.cancel();
_rfidSubscription = RfidBlePlugin.rfidStream.listen((tag) {
if (tag['epc'] == null) return;
final epc = tag['epc'];
final index = tags.indexWhere((e) => e['epc'] == epc);
setState(() {
if (index != -1) {
final existing = tags[index];
tags[index] = {
...existing,
'count': ((existing['count'] as int) + 1),
};
} else {
tags.add({
'epc': epc,
'tid': tag['tid'] ?? '',
'user': tag['user'] ?? '',
'rssi': tag['rssi'] ?? '',
'count': tag['count'] ?? 1,
});
}
});
});
} catch (e) {
debugPrint("Error Continuous inventory !");
}
}
void stopContinuousInventory() {
RfidBlePlugin.stopInventory();
_rfidSubscription?.cancel();
_rfidSubscription = null;
}
//#endregion BLE Activities
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("BLE Scanner")),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: startScan,
child: const Text("🔍 Start Scan"),
),
ElevatedButton(
onPressed: stopScan,
child: const Text("🛑 Stop Scan"),
),
ElevatedButton(
onPressed: disconnectDevice,
child: const Text("Disconnect"),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: startSingleInventory,
child: const Text("Single"),
),
ElevatedButton(
onPressed: startContinuousInventory,
child: const Text("Auto"),
),
ElevatedButton(
onPressed: stopContinuousInventory,
child: const Text("Stop"),
),
ElevatedButton(onPressed: clearData, child: const Text("Clear")),
],
),
ElevatedButton(onPressed: getBetteryLevel, child: const Text("BAT")),
const Divider(),
// List BLE
Expanded(
flex: 1,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
const Text(
"📱 Devices",
style: TextStyle(fontWeight: FontWeight.bold),
),
if (_batteryLevel != null)
Text("🔋 Battery: $_batteryLevel%"),
],
),
),
Expanded(
child: ListView.builder(
itemCount: devices.length,
itemBuilder: (context, index) {
final device = devices[index];
return ListTile(
title: Text(device['name'] ?? 'Unknown'),
subtitle: Text(
"MAC: ${device['mac']}\nUUID: ${device['uuid']}",
),
onTap: () => connectToDevice(device),
);
},
),
),
],
),
),
const Divider(),
// List RFID Tag
Expanded(
flex: 1,
child: Column(
children: [
const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
"📦 RFID Tags",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Expanded(
child: ListView.builder(
itemCount: tags.length,
itemBuilder: (context, index) {
final tag = tags[index];
return ListTile(
title: Text("EPC: ${tag['epc']}"),
subtitle: Text(
"Count: ${tag['count']} | RSSI: ${tag['rssi']}",
),
);
},
),
),
],
),
),
],
),
);
}
@override
void dispose() {
_scanSubscription?.cancel();
_rfidSubscription?.cancel();
_configSubscription?.cancel();
_batteryTimer?.cancel();
_connectionSubscription?.cancel();
super.dispose();
}
}