taro-bluetooth-print 2.9.2 → 2.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/types/adapters/BaseAdapter.d.ts +5 -0
- package/dist/types/adapters/WebBluetoothAdapter.d.ts +5 -0
- package/dist/types/core/BluetoothPrinter.d.ts +10 -0
- package/dist/types/services/interfaces/IConnectionManager.d.ts +5 -0
- package/dist/types/types.d.ts +5 -0
- package/package.json +1 -1
- package/src/adapters/BaseAdapter.ts +10 -0
- package/src/adapters/WebBluetoothAdapter.ts +45 -4
- package/src/core/BluetoothPrinter.ts +40 -19
- package/src/core/di/Container.ts +1 -1
- package/src/services/ConnectionManager.ts +18 -20
- package/src/services/interfaces/IConnectionManager.ts +6 -0
- package/src/types.ts +6 -0
|
@@ -147,6 +147,11 @@ export declare abstract class BaseAdapter implements IPrinterAdapter {
|
|
|
147
147
|
* @param deviceId - Device ID
|
|
148
148
|
*/
|
|
149
149
|
protected cleanupDevice(deviceId: string): void;
|
|
150
|
+
/**
|
|
151
|
+
* Cleanup resources and destroy the adapter instance
|
|
152
|
+
* Removes all event listeners and releases resources
|
|
153
|
+
*/
|
|
154
|
+
destroy(): void;
|
|
150
155
|
}
|
|
151
156
|
/**
|
|
152
157
|
* Base adapter for mini-program platforms (Taro/WeChat, Alipay, Baidu, ByteDance).
|
|
@@ -173,4 +173,9 @@ export declare class WebBluetoothAdapter extends BaseAdapter {
|
|
|
173
173
|
* Uses device name + first seen timestamp as identifier
|
|
174
174
|
*/
|
|
175
175
|
private generateFallbackDeviceId;
|
|
176
|
+
/**
|
|
177
|
+
* Cleanup resources and destroy the adapter instance
|
|
178
|
+
* Removes all event listeners and releases resources
|
|
179
|
+
*/
|
|
180
|
+
destroy(): void;
|
|
176
181
|
}
|
|
@@ -338,4 +338,14 @@ export declare class BluetoothPrinter extends EventEmitter<PrinterEvents> {
|
|
|
338
338
|
* @returns Command builder instance
|
|
339
339
|
*/
|
|
340
340
|
getCommandBuilder(): ICommandBuilder;
|
|
341
|
+
/**
|
|
342
|
+
* Cleanup resources and destroy the printer instance
|
|
343
|
+
* Removes all event listeners and releases resources
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```typescript
|
|
347
|
+
* printer.destroy();
|
|
348
|
+
* ```
|
|
349
|
+
*/
|
|
350
|
+
destroy(): void;
|
|
341
351
|
}
|
|
@@ -46,4 +46,9 @@ export interface IConnectionManager {
|
|
|
46
46
|
* @returns IPrinterAdapter - Printer adapter
|
|
47
47
|
*/
|
|
48
48
|
getAdapter(): IPrinterAdapter;
|
|
49
|
+
/**
|
|
50
|
+
* Cleanup resources and destroy the connection manager
|
|
51
|
+
* Stops heartbeat, clears timers, and removes event listeners
|
|
52
|
+
*/
|
|
53
|
+
destroy(): void;
|
|
49
54
|
}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -67,6 +67,11 @@ export interface IPrinterAdapter {
|
|
|
67
67
|
* @param callback - Function to call when the state changes
|
|
68
68
|
*/
|
|
69
69
|
onStateChange?(callback: (state: PrinterState) => void): void;
|
|
70
|
+
/**
|
|
71
|
+
* Cleanup resources and destroy the adapter instance
|
|
72
|
+
* Removes all event listeners and releases resources
|
|
73
|
+
*/
|
|
74
|
+
destroy?(): void;
|
|
70
75
|
}
|
|
71
76
|
/**
|
|
72
77
|
* Interface for printer drivers
|
package/package.json
CHANGED
|
@@ -185,6 +185,16 @@ export abstract class BaseAdapter implements IPrinterAdapter {
|
|
|
185
185
|
protected cleanupDevice(deviceId: string): void {
|
|
186
186
|
this.serviceCache.delete(deviceId);
|
|
187
187
|
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Cleanup resources and destroy the adapter instance
|
|
191
|
+
* Removes all event listeners and releases resources
|
|
192
|
+
*/
|
|
193
|
+
destroy(): void {
|
|
194
|
+
this.logger.debug('Destroying BaseAdapter');
|
|
195
|
+
this.serviceCache.clear();
|
|
196
|
+
this.stateCallback = undefined;
|
|
197
|
+
}
|
|
188
198
|
}
|
|
189
199
|
|
|
190
200
|
/**
|
|
@@ -10,6 +10,14 @@ import { IAdapterOptions, PrinterState } from '@/types';
|
|
|
10
10
|
import { BaseAdapter } from './BaseAdapter';
|
|
11
11
|
import { BluetoothPrintError, ErrorCode } from '@/errors/BluetoothError';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Extended Bluetooth device interface with RSSI support
|
|
15
|
+
* This is a vendor-specific extension not part of the standard Web Bluetooth API
|
|
16
|
+
*/
|
|
17
|
+
interface BluetoothDeviceWithRssi extends BluetoothDevice {
|
|
18
|
+
readRemoteRssi(): Promise<number>;
|
|
19
|
+
}
|
|
20
|
+
|
|
13
21
|
/**
|
|
14
22
|
* Web Bluetooth device information
|
|
15
23
|
*/
|
|
@@ -210,10 +218,9 @@ export class WebBluetoothAdapter extends BaseAdapter {
|
|
|
210
218
|
// Get RSSI if available (may not be available on all devices)
|
|
211
219
|
let rssi: number | undefined;
|
|
212
220
|
try {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
rssi = await
|
|
216
|
-
/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment */
|
|
221
|
+
const deviceWithRssi = characteristic.service.device as BluetoothDeviceWithRssi;
|
|
222
|
+
if ('readRemoteRssi' in deviceWithRssi && typeof deviceWithRssi.readRemoteRssi === 'function') {
|
|
223
|
+
rssi = await deviceWithRssi.readRemoteRssi();
|
|
217
224
|
}
|
|
218
225
|
} catch {
|
|
219
226
|
this.logger.debug('RSSI reading not supported on this device');
|
|
@@ -681,4 +688,38 @@ export class WebBluetoothAdapter extends BaseAdapter {
|
|
|
681
688
|
const timestamp = Date.now().toString(36);
|
|
682
689
|
return `fallback_${name}_${timestamp}`;
|
|
683
690
|
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Cleanup resources and destroy the adapter instance
|
|
694
|
+
* Removes all event listeners and releases resources
|
|
695
|
+
*/
|
|
696
|
+
destroy(): void {
|
|
697
|
+
this.logger.debug('Destroying WebBluetoothAdapter');
|
|
698
|
+
|
|
699
|
+
// Clear any pending connection cleanup timeout
|
|
700
|
+
if (this.connectionCleanupTimeout) {
|
|
701
|
+
clearTimeout(this.connectionCleanupTimeout);
|
|
702
|
+
this.connectionCleanupTimeout = null;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// Disconnect all devices
|
|
706
|
+
for (const [deviceId, deviceInfo] of this.devices) {
|
|
707
|
+
try {
|
|
708
|
+
if (deviceInfo.server.connected) {
|
|
709
|
+
deviceInfo.server.disconnect();
|
|
710
|
+
}
|
|
711
|
+
} catch (error) {
|
|
712
|
+
this.logger.warn(`Error disconnecting device ${deviceId}:`, error);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
// Clear all device caches
|
|
717
|
+
this.devices.clear();
|
|
718
|
+
this.discoveredDevices.clear();
|
|
719
|
+
|
|
720
|
+
// Call parent destroy
|
|
721
|
+
super.destroy();
|
|
722
|
+
|
|
723
|
+
this.logger.info('WebBluetoothAdapter destroyed');
|
|
724
|
+
}
|
|
684
725
|
}
|
|
@@ -131,19 +131,12 @@ export class BluetoothPrinter extends EventEmitter<PrinterEvents> {
|
|
|
131
131
|
* Updates the current state based on the connection manager and print job manager states
|
|
132
132
|
*/
|
|
133
133
|
private updateState(): void {
|
|
134
|
-
//
|
|
135
|
-
const connectionState =
|
|
136
|
-
typeof this.connectionManager.getState === 'function'
|
|
137
|
-
? this.connectionManager.getState()
|
|
138
|
-
: PrinterState.CONNECTED;
|
|
134
|
+
// All interface methods are guaranteed to exist
|
|
135
|
+
const connectionState = this.connectionManager.getState();
|
|
139
136
|
|
|
140
|
-
const isPrinting =
|
|
141
|
-
typeof this.printJobManager.isInProgress === 'function'
|
|
142
|
-
? this.printJobManager.isInProgress()
|
|
143
|
-
: false;
|
|
137
|
+
const isPrinting = this.printJobManager.isInProgress();
|
|
144
138
|
|
|
145
|
-
const isPaused =
|
|
146
|
-
typeof this.printJobManager.isPaused === 'function' ? this.printJobManager.isPaused() : false;
|
|
139
|
+
const isPaused = this.printJobManager.isPaused();
|
|
147
140
|
|
|
148
141
|
// Determine the final state
|
|
149
142
|
if (isPaused) {
|
|
@@ -425,10 +418,7 @@ export class BluetoothPrinter extends EventEmitter<PrinterEvents> {
|
|
|
425
418
|
* ```
|
|
426
419
|
*/
|
|
427
420
|
async print(): Promise<void> {
|
|
428
|
-
const isConnected =
|
|
429
|
-
typeof this.connectionManager.isConnected === 'function'
|
|
430
|
-
? this.connectionManager.isConnected()
|
|
431
|
-
: true; // Default to true for mock objects
|
|
421
|
+
const isConnected = this.connectionManager.isConnected();
|
|
432
422
|
|
|
433
423
|
if (!isConnected) {
|
|
434
424
|
throw new BluetoothPrintError(
|
|
@@ -453,10 +443,7 @@ export class BluetoothPrinter extends EventEmitter<PrinterEvents> {
|
|
|
453
443
|
try {
|
|
454
444
|
await this.printJobManager.start(buffer);
|
|
455
445
|
|
|
456
|
-
const isPaused =
|
|
457
|
-
typeof this.printJobManager.isPaused === 'function'
|
|
458
|
-
? this.printJobManager.isPaused()
|
|
459
|
-
: false;
|
|
446
|
+
const isPaused = this.printJobManager.isPaused();
|
|
460
447
|
|
|
461
448
|
if (isPaused) {
|
|
462
449
|
// Print job was paused
|
|
@@ -607,4 +594,38 @@ export class BluetoothPrinter extends EventEmitter<PrinterEvents> {
|
|
|
607
594
|
getCommandBuilder(): ICommandBuilder {
|
|
608
595
|
return this.commandBuilder;
|
|
609
596
|
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Cleanup resources and destroy the printer instance
|
|
600
|
+
* Removes all event listeners and releases resources
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```typescript
|
|
604
|
+
* printer.destroy();
|
|
605
|
+
* ```
|
|
606
|
+
*/
|
|
607
|
+
destroy(): void {
|
|
608
|
+
this.printerLogger.info('Destroying BluetoothPrinter instance');
|
|
609
|
+
|
|
610
|
+
// Cancel any pending print job
|
|
611
|
+
this.printJobManager.cancel();
|
|
612
|
+
|
|
613
|
+
// Clear command buffer
|
|
614
|
+
this.commandBuilder.clear();
|
|
615
|
+
|
|
616
|
+
// Disconnect if connected
|
|
617
|
+
if (this.connectionManager.isConnected()) {
|
|
618
|
+
this.connectionManager.disconnect().catch(error => {
|
|
619
|
+
this.printerLogger.warn('Error during disconnect in destroy:', error);
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Cleanup connection manager resources (IConnectionManager now has destroy())
|
|
624
|
+
this.connectionManager.destroy();
|
|
625
|
+
|
|
626
|
+
// Remove all event listeners
|
|
627
|
+
this.removeAllListeners();
|
|
628
|
+
|
|
629
|
+
this.printerLogger.info('BluetoothPrinter instance destroyed');
|
|
630
|
+
}
|
|
610
631
|
}
|
package/src/core/di/Container.ts
CHANGED
|
@@ -311,7 +311,7 @@ export const rootContainer = new Container();
|
|
|
311
311
|
export function injectable<T extends Constructor<object>>(constructor: T): T {
|
|
312
312
|
// 标记类为可注入
|
|
313
313
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
314
|
-
(constructor as
|
|
314
|
+
(constructor as unknown as { __injectable: boolean }).__injectable = true;
|
|
315
315
|
return constructor;
|
|
316
316
|
}
|
|
317
317
|
|
|
@@ -310,7 +310,7 @@ export class ConnectionManager
|
|
|
310
310
|
/**
|
|
311
311
|
* Attempt to reconnect
|
|
312
312
|
*/
|
|
313
|
-
private attemptReconnect(): void {
|
|
313
|
+
private async attemptReconnect(): Promise<void> {
|
|
314
314
|
if (!this.deviceId) {
|
|
315
315
|
this.isReconnecting = false;
|
|
316
316
|
return;
|
|
@@ -345,27 +345,25 @@ export class ConnectionManager
|
|
|
345
345
|
this.state = PrinterState.CONNECTING;
|
|
346
346
|
this.emit('state-change', PrinterState.CONNECTING);
|
|
347
347
|
|
|
348
|
-
|
|
349
|
-
.connect(deviceId)
|
|
350
|
-
.
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
this.emit('reconnected', deviceId);
|
|
348
|
+
try {
|
|
349
|
+
await this.adapter.connect(deviceId);
|
|
350
|
+
this.connLogger.info('Reconnected successfully');
|
|
351
|
+
this.isReconnecting = false;
|
|
352
|
+
this.reconnectAttempts = 0;
|
|
353
|
+
this.state = PrinterState.CONNECTED;
|
|
354
|
+
this.emit('state-change', PrinterState.CONNECTED);
|
|
355
|
+
this.emit('reconnected', deviceId);
|
|
357
356
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
.
|
|
363
|
-
this.connLogger.warn(`Reconnect attempt ${this.reconnectAttempts} failed:`, error);
|
|
357
|
+
if (this.config.heartbeatEnabled) {
|
|
358
|
+
this.startHeartbeat();
|
|
359
|
+
}
|
|
360
|
+
} catch (error) {
|
|
361
|
+
this.connLogger.warn(`Reconnect attempt ${this.reconnectAttempts} failed:`, error);
|
|
364
362
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
363
|
+
this.reconnectTimer = setTimeout(() => {
|
|
364
|
+
this.attemptReconnect();
|
|
365
|
+
}, this.config.reconnectInterval);
|
|
366
|
+
}
|
|
369
367
|
}
|
|
370
368
|
|
|
371
369
|
/**
|
|
@@ -55,4 +55,10 @@ export interface IConnectionManager {
|
|
|
55
55
|
* @returns IPrinterAdapter - Printer adapter
|
|
56
56
|
*/
|
|
57
57
|
getAdapter(): IPrinterAdapter;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Cleanup resources and destroy the connection manager
|
|
61
|
+
* Stops heartbeat, clears timers, and removes event listeners
|
|
62
|
+
*/
|
|
63
|
+
destroy(): void;
|
|
58
64
|
}
|
package/src/types.ts
CHANGED
|
@@ -75,6 +75,12 @@ export interface IPrinterAdapter {
|
|
|
75
75
|
* @param callback - Function to call when the state changes
|
|
76
76
|
*/
|
|
77
77
|
onStateChange?(callback: (state: PrinterState) => void): void;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Cleanup resources and destroy the adapter instance
|
|
81
|
+
* Removes all event listeners and releases resources
|
|
82
|
+
*/
|
|
83
|
+
destroy?(): void;
|
|
78
84
|
}
|
|
79
85
|
|
|
80
86
|
/**
|