visit
flutter_blue: ^0.8.0
esc_pos_utils: ^1.1.0
FlutterBlue flutterBlue = FlutterBlue.instance;
// Start scanning
flutterBlue.startScan(timeout: Duration(seconds: 4));
// Listen to scan results
var subscription = flutterBlue.scanResults.listen((results) {
// do something with scan results
for (ScanResult r in results) {
print('${r.device.name} found! rssi: ${r.rssi}');
}
});
// Stop scanning
flutterBlue.stopScan();
import 'package:blue_thermal_printing/blue_print.dart';
import 'package:esc_pos_utils/esc_pos_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
FlutterBlue flutterBlue = FlutterBlue.instance;
class PrintingWidget extends StatefulWidget {
const PrintingWidget({Key? key}) : super(key: key);
@override
_PrintingWidgetState createState() => _PrintingWidgetState();
}
class _PrintingWidgetState extends State<PrintingWidget> {
List<ScanResult>? scanResult;
@override
void initState() {
super.initState();
findDevices();
}
void findDevices() {
flutterBlue.startScan(timeout: const Duration(seconds: 4));
flutterBlue.scanResults.listen((results) {
setState(() {
scanResult = results;
});
});
flutterBlue.stopScan();
}
void printWithDevice(BluetoothDevice device) async {
await device.connect();
final gen = Generator(PaperSize.mm58, await CapabilityProfile.load());
final printer = BluePrint();
printer.add(gen.qrcode('//altospos.com'));
printer.add(gen.text('Hello'));
printer.add(gen.text('World', styles: const PosStyles(bold: true)));
printer.add(gen.feed(1));
await printer.printData(device);
device.disconnect();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Bluetooth devices')),
body: ListView.separated(
itemBuilder: (context, index) {
return ListTile(
title: Text(scanResult![index].device.name),
subtitle: Text(scanResult![index].device.id.id),
onTap: () => printWithDevice(scanResult![index].device),
);
},
separatorBuilder: (context, index) => const Divider(),
itemCount: scanResult?.length ?? 0,
),
);
}
}
Let's look at the printWithDevice
method.
Generator
is a class of the esc_pos_utils
plugin. With the help of this class, we can create ESC/POS commands like this: generator.text('Hello')
.BluePrint
instance (we will create this class further).
void add(List<int> data)
- To add commands.List<List<int>> getChunks()
- If we need to print very large data like an image, we may encounter problems because some devices will fail because of the big package size. So we need to send the data in chunks.printData(BluetoothDevice device)
- Sends chunked data to the device via BluetoothCharacteristic.
import 'dart:math';
import 'package:flutter_blue/flutter_blue.dart';
class BluePrint {
BluePrint({this.chunkLen = 512});
final int chunkLen;
final _data = List<int>.empty(growable: true);
void add(List<int> data) {
_data.addAll(data);
}
List<List<int>> getChunks() {
final chunks = List<List<int>>.empty(growable: true);
for (var i = 0; i < _data.length; i += chunkLen) {
chunks.add(_data.sublist(i, min(i + chunkLen, _data.length)));
}
return chunks;
}
Future<void> printData(BluetoothDevice device) async {
final data = getChunks();
final characs = await _getCharacteristics(device);
for (var i = 0; i < characs.length; i++) {
if (await _tryPrint(characs[i], data)) {
break;
}
}
}
Future<bool> _tryPrint(
BluetoothCharacteristic charac,
List<List<int>> data,
) async {
for (var i = 0; i < data.length; i++) {
try {
await charac.write(data[i]);
} catch (e) {
return false;
}
}
return true;
}
Future<List<BluetoothCharacteristic>> _getCharacteristics(
BluetoothDevice device,
) async {
final services = await device.discoverServices();
final res = List<BluetoothCharacteristic>.empty(growable: true);
for (var i = 0; i < services.length; i++) {
res.addAll(services[i].characteristics);
}
return res;
}
}