sendDataToPrinter method
Future<Map<String, dynamic>>
sendDataToPrinter(
- int vendorId,
- int productId,
- Uint8List data, {
- int interfaceNumber = 0,
- int endpointAddress = 0x01,
- int readEndpointAddress = 0x81,
- int timeout = 10000,
- bool expectResponse = false,
- int maxResponseLength = 256,
})
Implementation
Future<Map<String, dynamic>> sendDataToPrinter(
int vendorId,
int productId,
Uint8List data, {
int interfaceNumber = 0,
int endpointAddress = 0x01,
int readEndpointAddress = 0x81,
int timeout = 10000,
bool expectResponse = false,
int maxResponseLength = 256,
}) async {
// Abre el dispositivo
final Pointer<libusb_device_handle>? handleNullable =
openDevice(vendorId, productId);
if (handleNullable == nullptr || handleNullable == null) {
return {'success': false, 'error': 'No se pudo abrir el dispositivo'};
}
// Aquí convertimos de Pointer? a Pointer, ahora que sabemos que no es nulo
final handle = handleNullable;
try {
// Verificar si hay un kernel driver activo y desconectarlo si es necesario
int hasKernelDriver = 0;
if (Platform.isLinux || Platform.isMacOS) {
try {
hasKernelDriver =
_bindings.libusb_kernel_driver_active(handle, interfaceNumber);
if (hasKernelDriver == 1) {
log("Desconectando el driver del kernel...");
final detachResult =
_bindings.libusb_detach_kernel_driver(handle, interfaceNumber);
if (detachResult < 0) {
log("No se pudo desconectar el driver del kernel: $detachResult");
} else {
log("Driver del kernel desconectado con éxito");
}
}
} catch (e) {
log("Error al verificar/desconectar el driver del kernel: $e");
}
}
// Configurar el dispositivo si es necesario
final configResult = _bindings.libusb_set_configuration(handle, 1);
if (configResult < 0) {
log("Advertencia: No se pudo establecer la configuración: $configResult");
// Continuamos a pesar del error, ya que algunas impresoras funcionan sin esto
}
// Reclamar la interfaz con múltiples intentos
int claimResult = -1;
int attempts = 0;
const maxAttempts = 3;
while (attempts < maxAttempts) {
claimResult = _bindings.libusb_claim_interface(handle, interfaceNumber);
if (claimResult == 0) break;
log("Intento ${attempts + 1} fallido con error $claimResult. Reintentando...");
// Esperar un poco antes de reintentar
await Future.delayed(Duration(milliseconds: 500));
attempts++;
}
if (claimResult < 0) {
return {
'success': false,
'error':
'No se pudo reclamar la interfaz después de $maxAttempts intentos',
'errorCode': claimResult,
'errorDescription': _getUsbErrorDescription(claimResult)
};
}
// Enviar datos a la impresora
final buffer = calloc<Uint8>(data.length);
final bufferList = buffer.asTypedList(data.length);
bufferList.setAll(0, data);
final transferredPtr = calloc<Int>();
log("Enviando ${data.length} bytes al endpoint $endpointAddress...");
int transferResult = _bindings.libusb_bulk_transfer(
handle,
endpointAddress,
buffer.cast<UnsignedChar>(),
data.length,
transferredPtr,
timeout);
await Future.delayed(Duration(milliseconds: 5000));
final bytesSent = transferredPtr.value;
calloc.free(buffer);
calloc.free(transferredPtr);
if (transferResult < 0) {
return {
'success': false,
'error': 'Error en la transferencia de datos',
'errorCode': transferResult,
'errorDescription': _getUsbErrorDescription(transferResult)
};
}
log("Transferencia exitosa: $bytesSent bytes enviados");
// Si se espera una respuesta, leer los datos de la impresora
Map<String, dynamic> result = {
'success': true,
'bytesSent': bytesSent,
};
if (expectResponse) {
// Crear buffer para la respuesta
final responseBuffer = calloc<Uint8>(maxResponseLength);
final responseTransferredPtr = calloc<Int>();
// Pequeña espera para dar tiempo a la impresora a procesar y preparar la respuesta
await Future.delayed(Duration(milliseconds: 800));
log("Leyendo respuesta desde el endpoint $readEndpointAddress...");
final responseResult = _bindings.libusb_bulk_transfer(
handle,
readEndpointAddress,
responseBuffer.cast<UnsignedChar>(),
maxResponseLength,
responseTransferredPtr,
timeout);
await Future.delayed(Duration(milliseconds: 100));
if (responseResult >= 0) {
final bytesReceived = responseTransferredPtr.value;
log("Respuesta recibida: $bytesReceived bytes");
if (bytesReceived > 0) {
// Convertir la respuesta a List<int>
final responseList = List<int>.filled(bytesReceived, 0);
for (var i = 0; i < bytesReceived; i++) {
responseList[i] = responseBuffer[i];
}
// Añadir la respuesta al resultado
result['responseData'] = responseList;
result['bytesReceived'] = bytesReceived;
} else {
result['responseData'] = [];
result['bytesReceived'] = 0;
}
} else {
log("Error al leer la respuesta: $responseResult");
result['responseError'] = _getUsbErrorDescription(responseResult);
}
calloc.free(responseBuffer);
calloc.free(responseTransferredPtr);
}
// Liberar la interfaz
_bindings.libusb_release_interface(handle, interfaceNumber);
// Reconectar el driver del kernel si lo desconectamos
if (hasKernelDriver == 1 && (Platform.isLinux || Platform.isMacOS)) {
_bindings.libusb_attach_kernel_driver(handle, interfaceNumber);
}
return result;
} catch (e) {
return {
'success': false,
'error': 'Error al comunicarse con la impresora',
'exception': e.toString()
};
} finally {
closeDevice(handle);
}
}