Flutter新手求助:如何通过蓝牙打印机打印购物小票?
Hey there! As someone who’s tackled Flutter Bluetooth receipt printing before, let me break this down for you clearly—since you’re already using flutter_blue, we’ll build directly on that.
Your workflow will look like this:
- Scan and connect to your Bluetooth receipt printer via flutter_blue
- Fetch order data from MySQL, calculate totals, and format it into a receipt layout
- Convert that receipt text into ESC/POS commands (the standard language most receipt printers understand)
- Send the formatted command data to the connected printer via Bluetooth
1. First: Get Bluetooth Connection Working
First, you need to discover the printer, connect to it, and find the correct BLE characteristic to send data to. Here’s a simplified code snippet for that:
import 'package:flutter_blue/flutter_blue.dart'; FlutterBlue flutterBlue = FlutterBlue.instance; BluetoothDevice? connectedPrinter; BluetoothCharacteristic? writeCharacteristic; // Scan for Bluetooth devices void scanForPrinters() { flutterBlue.startScan(timeout: Duration(seconds: 4)); flutterBlue.scanResults.listen((results) { for (ScanResult result in results) { // Replace with your printer's name or MAC address if (result.device.name.contains("ReceiptPrinter")) { connectToPrinter(result.device); flutterBlue.stopScan(); break; } } }); } // Connect to the printer and find writable characteristic Future<void> connectToPrinter(BluetoothDevice device) async { try { await device.connect(); connectedPrinter = device; // Discover services and characteristics List<BluetoothService> services = await device.discoverServices(); for (BluetoothService service in services) { for (BluetoothCharacteristic char in service.characteristics) { // Look for a characteristic that allows write operations if (char.properties.write || char.properties.writeWithoutResponse) { writeCharacteristic = char; print("Found writable characteristic!"); return; } } } } catch (e) { print("Connection error: $e"); } }
2. Format Receipt Data into ESC/POS Commands
Most receipt printers use ESC/POS (Escape/POS) commands to control formatting (bold, alignment, line breaks, cutting). You’ll need to convert your order data into this format. Here’s a helper function to do that:
// Convert order data to ESC/POS byte list Uint8List formatReceipt(Map<String, dynamic> orderData) { String receiptText = ""; // Header (bold, centered) receiptText += "\x1B\x45\x01"; // Turn bold on receiptText += "===== YOUR STORE NAME =====\n"; receiptText += "\x1B\x45\x00"; // Turn bold off receiptText += "Order ID: ${orderData['orderId']}\n"; receiptText += "Date: ${DateTime.now().toString().split(" ")[0]}\n"; receiptText += "-------------------------\n"; // Item list for (var item in orderData['items']) { receiptText += "${item['name']} x${item['quantity']}\n"; receiptText += " \$${item['price'].toStringAsFixed(2)}\n"; } // Total receiptText += "-------------------------\n"; receiptText += "\x1B\x45\x01"; // Bold for total receiptText += "TOTAL: \$${orderData['total'].toStringAsFixed(2)}\n"; receiptText += "\x1B\x45\x00"; receiptText += "-------------------------\n"; receiptText += "Thank you for your purchase!\n"; // Add cut paper command (adjust based on your printer) receiptText += "\x1B\x69"; // Full cut (some printers use \x1B\x4A\x00) // Convert string to Uint8List (printer expects bytes) return Uint8List.fromList(receiptText.codeUnits); }
3. Send Data to the Printer
Once you have the formatted receipt bytes and a connected printer, send the data:
// Print the receipt Future<void> printReceipt(Map<String, dynamic> orderData) async { if (connectedPrinter == null || writeCharacteristic == null) { print("No printer connected!"); return; } try { Uint8List receiptBytes = formatReceipt(orderData); await writeCharacteristic!.write(receiptBytes, withoutResponse: true); print("Receipt sent to printer!"); } catch (e) { print("Print error: $e"); } }
Quick Notes to Avoid Headaches
- Test ESC/POS Commands: Different printers might use slightly different commands (e.g., cut paper). Check your printer’s manual for exact codes.
- MySQL Data Fetch: You’ll need to add an API (like a Node.js/PHP backend) to fetch order data from MySQL—call this API from Flutter using
httpordiopackage, then pass the response toprintReceipt(). - Bluetooth Permissions: Don’t forget to add Bluetooth permissions in your
AndroidManifest.xmlandInfo.plist(for iOS).
Here’s how you’d tie it all together when the user submits an order:
// Example: After user submits order void onOrderSubmitted() async { // 1. Fetch order data from your MySQL-backed API // var orderData = await fetchOrderFromAPI(); // For testing, use sample data var sampleOrder = { 'orderId': 'ORD-1234', 'items': [ {'name': 'Coffee', 'quantity': 2, 'price': 3.50}, {'name': 'Croissant', 'quantity': 1, 'price': 2.00} ], 'total': 9.00 }; // 2. Ensure printer is connected if (connectedPrinter == null) { await scanForPrinters(); // Wait a bit for connection (better to use a state management solution in real app) await Future.delayed(Duration(seconds: 2)); } // 3. Print the receipt await printReceipt(sampleOrder); }
内容的提问来源于stack exchange,提问作者GNM

