2025-07-30 22:38:44 +07:00
|
|
|
import 'dart:developer';
|
2025-09-19 13:52:29 +07:00
|
|
|
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
2025-07-30 22:38:44 +07:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
import 'package:flutter_esc_pos_network/flutter_esc_pos_network.dart';
|
|
|
|
|
import 'package:print_bluetooth_thermal/print_bluetooth_thermal.dart';
|
|
|
|
|
import 'package:enaklo_pos/data/models/response/print_model.dart';
|
|
|
|
|
|
|
|
|
|
class PrinterService {
|
|
|
|
|
static final PrinterService _instance = PrinterService._internal();
|
|
|
|
|
factory PrinterService() => _instance;
|
|
|
|
|
PrinterService._internal();
|
|
|
|
|
|
|
|
|
|
/// Connect to Bluetooth printer
|
|
|
|
|
Future<bool> connectBluetoothPrinter(String macAddress) async {
|
|
|
|
|
try {
|
|
|
|
|
// Check if already connected
|
|
|
|
|
bool isConnected = await PrintBluetoothThermal.connectionStatus;
|
|
|
|
|
if (isConnected) {
|
|
|
|
|
log("Already connected to Bluetooth printer");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Connect to the printer
|
2025-09-19 13:52:29 +07:00
|
|
|
bool connected =
|
|
|
|
|
await PrintBluetoothThermal.connect(macPrinterAddress: macAddress);
|
|
|
|
|
|
2025-07-30 22:38:44 +07:00
|
|
|
if (connected) {
|
|
|
|
|
log("Successfully connected to Bluetooth printer: $macAddress");
|
|
|
|
|
} else {
|
2025-09-19 13:52:29 +07:00
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
'Failed to connect to Bluetooth printer',
|
|
|
|
|
null,
|
|
|
|
|
reason: 'Failed to connect to Bluetooth printe',
|
|
|
|
|
information: [
|
|
|
|
|
'function: connectBluetoothPrinter(String macAddress)',
|
|
|
|
|
'macAddress: $macAddress',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
log("Failed to connect to Bluetooth printer: $macAddress");
|
|
|
|
|
}
|
2025-09-19 13:52:29 +07:00
|
|
|
|
2025-07-30 22:38:44 +07:00
|
|
|
return connected;
|
2025-09-19 13:52:29 +07:00
|
|
|
} catch (e, stackTrace) {
|
|
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
e,
|
|
|
|
|
stackTrace,
|
|
|
|
|
reason: 'Error connecting to Bluetooth printer',
|
|
|
|
|
information: [
|
|
|
|
|
'function: connectBluetoothPrinter(String macAddress)',
|
|
|
|
|
'Printer: Bluetooth printer',
|
|
|
|
|
'macAddress: $macAddress',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
log("Error connecting to Bluetooth printer: $e");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Print using Bluetooth printer
|
|
|
|
|
Future<bool> printBluetooth(List<int> printData) async {
|
|
|
|
|
try {
|
|
|
|
|
bool isConnected = await PrintBluetoothThermal.connectionStatus;
|
|
|
|
|
if (!isConnected) {
|
|
|
|
|
log("Not connected to Bluetooth printer");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool printResult = await PrintBluetoothThermal.writeBytes(printData);
|
|
|
|
|
if (printResult) {
|
|
|
|
|
log("Successfully printed via Bluetooth");
|
|
|
|
|
} else {
|
2025-09-19 13:52:29 +07:00
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
'Failed to print via Bluetooth',
|
|
|
|
|
null,
|
|
|
|
|
reason: 'Failed to print via Bluetooth',
|
|
|
|
|
information: [
|
|
|
|
|
'function: printBluetooth(List<int> printData)',
|
|
|
|
|
'printData: $printData',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
log("Failed to print via Bluetooth");
|
|
|
|
|
}
|
2025-09-19 13:52:29 +07:00
|
|
|
|
2025-07-30 22:38:44 +07:00
|
|
|
return printResult;
|
2025-09-19 13:52:29 +07:00
|
|
|
} catch (e, stackTrace) {
|
|
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
e,
|
|
|
|
|
stackTrace,
|
|
|
|
|
reason: 'Error printing via Bluetooth',
|
|
|
|
|
information: [
|
|
|
|
|
'function: printBluetooth(List<int> printData)',
|
|
|
|
|
'Printer: Bluetooth printer',
|
|
|
|
|
'printData: $printData',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
log("Error printing via Bluetooth: $e");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Print using Network printer
|
|
|
|
|
Future<bool> printNetwork(String ipAddress, List<int> printData) async {
|
|
|
|
|
try {
|
|
|
|
|
final printer = PrinterNetworkManager(ipAddress);
|
|
|
|
|
PosPrintResult connect = await printer.connect();
|
2025-09-19 13:52:29 +07:00
|
|
|
|
2025-07-30 22:38:44 +07:00
|
|
|
if (connect == PosPrintResult.success) {
|
|
|
|
|
PosPrintResult printing = await printer.printTicket(printData);
|
|
|
|
|
printer.disconnect();
|
2025-09-19 13:52:29 +07:00
|
|
|
|
2025-07-30 22:38:44 +07:00
|
|
|
if (printing == PosPrintResult.success) {
|
|
|
|
|
log("Successfully printed via Network printer: $ipAddress");
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
2025-09-19 13:52:29 +07:00
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
'Failed to print via Network printer: ${printing.msg}',
|
|
|
|
|
null,
|
|
|
|
|
reason: 'Failed to print via Network printer',
|
|
|
|
|
information: [
|
|
|
|
|
'function: printNetwork(String ipAddress, List<int> printData)',
|
|
|
|
|
'Printer: Network printer',
|
|
|
|
|
'ipAddress: $ipAddress',
|
|
|
|
|
'printData: $printData',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
log("Failed to print via Network printer: ${printing.msg}");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2025-09-19 13:52:29 +07:00
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
'Failed to connect to Network printer: ${connect.msg}',
|
|
|
|
|
null,
|
|
|
|
|
reason: 'Failed to connectNetwork printer',
|
|
|
|
|
information: [
|
|
|
|
|
'function: printNetwork(String ipAddress, List<int> printData)',
|
|
|
|
|
'Printer: Network printer',
|
|
|
|
|
'ipAddress: $ipAddress',
|
|
|
|
|
'printData: $printData',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
log("Failed to connect to Network printer: ${connect.msg}");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2025-09-19 13:52:29 +07:00
|
|
|
} catch (e, stackTrace) {
|
|
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
e,
|
|
|
|
|
stackTrace,
|
|
|
|
|
reason: 'Error printing via Network',
|
|
|
|
|
information: [
|
|
|
|
|
'function: printNetwork(String ipAddress, List<int> printData)',
|
|
|
|
|
'Printer: Network printer',
|
|
|
|
|
'ipAddress: $ipAddress',
|
|
|
|
|
'printData: $printData',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
log("Error printing via Network: $e");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Print with automatic printer type detection
|
2025-09-19 13:52:29 +07:00
|
|
|
Future<bool> printWithPrinter(
|
|
|
|
|
PrintModel printer, List<int> printData, BuildContext context) async {
|
2025-07-30 22:38:44 +07:00
|
|
|
try {
|
|
|
|
|
if (printer.type == 'Bluetooth') {
|
|
|
|
|
bool connected = await connectBluetoothPrinter(printer.address);
|
|
|
|
|
if (!connected) {
|
2025-09-19 13:52:29 +07:00
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
'Failed to connect to Bluetooth printer',
|
|
|
|
|
null,
|
|
|
|
|
reason: 'Failed to connect to Bluetooth printe',
|
|
|
|
|
information: [
|
|
|
|
|
'function: connectBluetoothPrinter(String macAddress)',
|
|
|
|
|
'Printer: ${printer.name}',
|
|
|
|
|
'macAddress: ${printer.address}',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
|
|
|
SnackBar(content: Text('Failed to connect to ${printer.name}')),
|
|
|
|
|
);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2025-09-19 13:52:29 +07:00
|
|
|
|
2025-07-30 22:38:44 +07:00
|
|
|
bool printResult = await printBluetooth(printData);
|
|
|
|
|
if (!printResult) {
|
2025-09-19 13:52:29 +07:00
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
'Failed to print to ${printer.name}',
|
|
|
|
|
null,
|
|
|
|
|
information: [
|
|
|
|
|
'function: await printBluetooth(printData);',
|
|
|
|
|
'print: $printData',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
|
|
|
SnackBar(content: Text('Failed to print to ${printer.name}')),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return printResult;
|
|
|
|
|
} else {
|
|
|
|
|
bool printResult = await printNetwork(printer.address, printData);
|
|
|
|
|
if (!printResult) {
|
2025-09-19 13:52:29 +07:00
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
'Failed to connect to Network Printer',
|
|
|
|
|
null,
|
|
|
|
|
reason: 'Failed to connect to Network Printer',
|
|
|
|
|
information: [
|
|
|
|
|
'function: await printNetwork(printer.address, printData);',
|
|
|
|
|
'Printer: ${printer.name}',
|
|
|
|
|
'ipAddress: ${printer.address}',
|
|
|
|
|
'print: $printData',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
|
|
|
SnackBar(content: Text('Failed to print to ${printer.name}')),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return printResult;
|
|
|
|
|
}
|
2025-09-19 13:52:29 +07:00
|
|
|
} catch (e, stackTrace) {
|
|
|
|
|
FirebaseCrashlytics.instance.recordError(
|
|
|
|
|
e,
|
|
|
|
|
stackTrace,
|
|
|
|
|
reason: 'Error printing with printer ${printer.name}',
|
|
|
|
|
information: [
|
|
|
|
|
'Printer: ${printer.name}',
|
|
|
|
|
],
|
|
|
|
|
);
|
2025-07-30 22:38:44 +07:00
|
|
|
log("Error printing with printer ${printer.name}: $e");
|
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
|
|
|
SnackBar(content: Text('Error printing to ${printer.name}: $e')),
|
|
|
|
|
);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Disconnect from Bluetooth printer
|
|
|
|
|
Future<bool> disconnectBluetooth() async {
|
|
|
|
|
try {
|
|
|
|
|
bool result = await PrintBluetoothThermal.disconnect;
|
|
|
|
|
log("Bluetooth printer disconnected: $result");
|
|
|
|
|
return result;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log("Error disconnecting Bluetooth printer: $e");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Check if Bluetooth is enabled
|
|
|
|
|
Future<bool> isBluetoothEnabled() async {
|
|
|
|
|
try {
|
|
|
|
|
return await PrintBluetoothThermal.bluetoothEnabled;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log("Error checking Bluetooth status: $e");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get paired Bluetooth devices
|
|
|
|
|
Future<List<BluetoothInfo>> getPairedBluetoothDevices() async {
|
|
|
|
|
try {
|
|
|
|
|
return await PrintBluetoothThermal.pairedBluetooths;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log("Error getting paired Bluetooth devices: $e");
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-19 13:52:29 +07:00
|
|
|
}
|