taro-bluetooth-print 2.2.0 → 2.3.0

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +128 -22
  3. package/dist/index.cjs.js +1 -1
  4. package/dist/index.es.js +1 -6995
  5. package/dist/index.umd.js +1 -1
  6. package/dist/types/adapters/AdapterFactory.d.ts +0 -1
  7. package/dist/types/adapters/AlipayAdapter.d.ts +6 -34
  8. package/dist/types/adapters/BaiduAdapter.d.ts +6 -34
  9. package/dist/types/adapters/BaseAdapter.d.ts +112 -1
  10. package/dist/types/adapters/ByteDanceAdapter.d.ts +6 -34
  11. package/dist/types/adapters/TaroAdapter.d.ts +6 -34
  12. package/dist/types/adapters/WebBluetoothAdapter.d.ts +0 -1
  13. package/dist/types/config/PrinterConfig.d.ts +0 -1
  14. package/dist/types/core/BluetoothPrinter.d.ts +0 -1
  15. package/dist/types/drivers/EscPos.d.ts +0 -1
  16. package/dist/types/drivers/TsplDriver.d.ts +251 -0
  17. package/dist/types/encoding/gbk-data.d.ts +12 -0
  18. package/dist/types/encoding/gbk-table.d.ts +5 -1
  19. package/dist/types/index.d.ts +5 -0
  20. package/dist/types/plugins/PluginManager.d.ts +87 -0
  21. package/dist/types/plugins/builtin/LoggingPlugin.d.ts +14 -0
  22. package/dist/types/plugins/builtin/RetryPlugin.d.ts +18 -0
  23. package/dist/types/plugins/index.d.ts +7 -0
  24. package/dist/types/plugins/types.d.ts +97 -0
  25. package/dist/types/services/CommandBuilder.d.ts +6 -1
  26. package/dist/types/services/ConnectionManager.d.ts +0 -1
  27. package/dist/types/services/PrintJobManager.d.ts +6 -2
  28. package/dist/types/services/interfaces/index.d.ts +0 -1
  29. package/dist/types/template/TemplateEngine.d.ts +0 -1
  30. package/package.json +16 -18
  31. package/src/adapters/AlipayAdapter.ts +8 -314
  32. package/src/adapters/BaiduAdapter.ts +8 -312
  33. package/src/adapters/BaseAdapter.ts +366 -0
  34. package/src/adapters/ByteDanceAdapter.ts +8 -316
  35. package/src/adapters/TaroAdapter.ts +8 -367
  36. package/src/core/EventEmitter.ts +9 -6
  37. package/src/drivers/TsplDriver.ts +417 -0
  38. package/src/encoding/gbk-data.ts +1911 -0
  39. package/src/encoding/gbk-table.ts +22 -498
  40. package/src/index.ts +14 -0
  41. package/src/plugins/PluginManager.ts +193 -0
  42. package/src/plugins/builtin/LoggingPlugin.ts +97 -0
  43. package/src/plugins/builtin/RetryPlugin.ts +109 -0
  44. package/src/plugins/index.ts +10 -0
  45. package/src/plugins/types.ts +119 -0
  46. package/src/preview/PreviewRenderer.ts +7 -1
  47. package/src/queue/PrintQueue.ts +10 -6
  48. package/src/services/CommandBuilder.ts +30 -0
  49. package/src/services/PrintJobManager.ts +51 -35
@@ -3,77 +3,19 @@
3
3
  * Implements the IPrinterAdapter interface for ByteDance Mini Program
4
4
  */
5
5
 
6
- import { IAdapterOptions, PrinterState } from '@/types';
7
- import { BaseAdapter } from './BaseAdapter';
8
- import { BluetoothPrintError, ErrorCode } from '@/errors/BluetoothError';
6
+ import { MiniProgramAdapter, MiniProgramBLEApi } from './BaseAdapter';
9
7
 
10
8
  // Declare ByteDance global for TypeScript
11
- interface ByteDanceBLEService {
12
- uuid: string;
13
- }
14
-
15
- interface ByteDanceBLECharacteristicProperties {
16
- write?: boolean;
17
- writeWithoutResponse?: boolean;
18
- read?: boolean;
19
- notify?: boolean;
20
- indicate?: boolean;
21
- }
22
-
23
- interface ByteDanceBLECharacteristic {
24
- uuid: string;
25
- properties: ByteDanceBLECharacteristicProperties;
26
- }
27
-
28
- interface ByteDanceBLEDeviceServicesResult {
29
- services: ByteDanceBLEService[];
30
- }
31
-
32
- interface ByteDanceBLEDeviceCharacteristicsResult {
33
- characteristics: ByteDanceBLECharacteristic[];
34
- }
35
-
36
- interface ByteDanceBLEConnectionStateResult {
37
- connected: boolean;
38
- }
39
-
40
- interface ByteDanceBLEConnectionOptions {
41
- deviceId: string;
42
- }
43
-
44
- interface ByteDanceBLEWriteOptions {
45
- deviceId: string;
46
- serviceId: string;
47
- characteristicId: string;
48
- value: ArrayBuffer;
49
- }
50
-
51
- interface ByteDanceBLEConnectionStateChangeCallback {
52
- (res: { deviceId: string; connected: boolean }): void;
53
- }
54
-
55
- interface ByteDanceGlobal {
56
- createBLEConnection(options: ByteDanceBLEConnectionOptions): Promise<void>;
57
- closeBLEConnection(options: ByteDanceBLEConnectionOptions): Promise<void>;
58
- getBLEConnectionState(
59
- options: ByteDanceBLEConnectionOptions
60
- ): Promise<ByteDanceBLEConnectionStateResult>;
61
- writeBLECharacteristicValue(options: ByteDanceBLEWriteOptions): Promise<void>;
62
- getBLEDeviceServices(
63
- options: ByteDanceBLEConnectionOptions
64
- ): Promise<ByteDanceBLEDeviceServicesResult>;
65
- getBLEDeviceCharacteristics(options: {
66
- deviceId: string;
67
- serviceId: string;
68
- }): Promise<ByteDanceBLEDeviceCharacteristicsResult>;
69
- onBLEConnectionStateChange(callback: ByteDanceBLEConnectionStateChangeCallback): void;
70
- }
9
+ interface ByteDanceGlobal extends MiniProgramBLEApi {}
71
10
 
72
11
  declare const tt: ByteDanceGlobal;
73
12
 
74
13
  /**
75
14
  * ByteDance Bluetooth Low Energy adapter
76
15
  *
16
+ * Uses the ByteDance mini-program's BLE APIs (tt.xxx, for Douyin/TikTok etc).
17
+ * All connection, write, and service discovery logic is inherited from MiniProgramAdapter.
18
+ *
77
19
  * @example
78
20
  * ```typescript
79
21
  * const adapter = new ByteDanceAdapter();
@@ -82,258 +24,8 @@ declare const tt: ByteDanceGlobal;
82
24
  * await adapter.disconnect('device-id-123');
83
25
  * ```
84
26
  */
85
- export class ByteDanceAdapter extends BaseAdapter {
86
- /**
87
- * Connects to a Bluetooth device and discovers services
88
- *
89
- * @param deviceId - Bluetooth device ID
90
- * @throws {BluetoothPrintError} When connection fails
91
- */
92
- async connect(deviceId: string): Promise<void> {
93
- this.validateDeviceId(deviceId);
94
-
95
- // Check if already connected
96
- if (this.isDeviceConnected(deviceId)) {
97
- this.logger.warn('Device already connected:', deviceId);
98
- this.updateState(PrinterState.CONNECTED);
99
- return;
100
- }
101
-
102
- this.updateState(PrinterState.CONNECTING);
103
- this.logger.debug('Connecting to device:', deviceId);
104
-
105
- try {
106
- // Add connection timeout handling
107
- let timeoutId: NodeJS.Timeout | undefined;
108
- const connectionPromise = tt.createBLEConnection({
109
- deviceId,
110
- });
111
-
112
- const timeoutPromise = new Promise((_, reject) => {
113
- timeoutId = setTimeout(() => {
114
- reject(new Error('Connection timeout after 10 seconds'));
115
- }, 10000);
116
- });
117
-
118
- await Promise.race([connectionPromise, timeoutPromise]);
119
- if (timeoutId) {
120
- clearTimeout(timeoutId); // Clear timeout after successful connection
121
- }
122
- this.logger.info('BLE connection established');
123
-
124
- // Discover and cache services
125
- await this.discoverServices(deviceId);
126
-
127
- this.updateState(PrinterState.CONNECTED);
128
- this.logger.info('Device connected successfully');
129
-
130
- // Listen for connection state changes
131
- tt.onBLEConnectionStateChange((res: { deviceId: string; connected: boolean }) => {
132
- if (res.deviceId === deviceId && !res.connected) {
133
- this.logger.warn('Device disconnected unexpectedly');
134
- this.updateState(PrinterState.DISCONNECTED);
135
- this.cleanupDevice(deviceId);
136
- }
137
- });
138
- } catch (error) {
139
- this.updateState(PrinterState.DISCONNECTED);
140
- this.logger.error('Connection failed:', error);
141
-
142
- // Return more specific error codes based on error message
143
- const errorMessage = (error as Error).message || '';
144
- if (errorMessage.includes('timeout')) {
145
- throw new BluetoothPrintError(
146
- ErrorCode.CONNECTION_TIMEOUT,
147
- `Connection to device ${deviceId} timed out`,
148
- error as Error
149
- );
150
- } else if (errorMessage.includes('not found')) {
151
- throw new BluetoothPrintError(
152
- ErrorCode.DEVICE_NOT_FOUND,
153
- `Device ${deviceId} not found`,
154
- error as Error
155
- );
156
- }
157
-
158
- throw new BluetoothPrintError(
159
- ErrorCode.CONNECTION_FAILED,
160
- `Failed to connect to device ${deviceId}`,
161
- error as Error
162
- );
163
- }
164
- }
165
-
166
- /**
167
- * Disconnects from a Bluetooth device
168
- *
169
- * @param deviceId - Bluetooth device ID
170
- */
171
- async disconnect(deviceId: string): Promise<void> {
172
- this.validateDeviceId(deviceId);
173
- this.updateState(PrinterState.DISCONNECTING);
174
- this.logger.debug('Disconnecting from device:', deviceId);
175
-
176
- try {
177
- await tt.closeBLEConnection({
178
- deviceId,
179
- });
180
- this.cleanupDevice(deviceId);
181
- this.updateState(PrinterState.DISCONNECTED);
182
- this.logger.info('Device disconnected successfully');
183
- } catch (error) {
184
- // Ignore error on disconnect, but log it
185
- this.logger.warn('Disconnect error (ignored):', error);
186
- this.cleanupDevice(deviceId);
187
- this.updateState(PrinterState.DISCONNECTED);
188
- }
189
- }
190
-
191
- /**
192
- * Writes data to the Bluetooth device in chunks with retry logic
193
- *
194
- * @param deviceId - Bluetooth device ID
195
- * @param buffer - Data to write as ArrayBuffer
196
- * @param options - Write options (chunk size, delay, retries)
197
- * @throws {BluetoothPrintError} When write fails after retries
198
- */
199
- async write(deviceId: string, buffer: ArrayBuffer, options?: IAdapterOptions): Promise<void> {
200
- this.validateDeviceId(deviceId);
201
- this.validateBuffer(buffer);
202
- const serviceInfo = this.getServiceInfo(deviceId);
203
- const validatedOptions = this.validateOptions(options);
204
-
205
- // Validate device is still connected
206
- try {
207
- const state = await tt.getBLEConnectionState({
208
- deviceId,
209
- });
210
- if (!state.connected) {
211
- this.cleanupDevice(deviceId);
212
- throw new BluetoothPrintError(ErrorCode.DEVICE_DISCONNECTED, 'Device disconnected');
213
- }
214
- } catch (error) {
215
- this.cleanupDevice(deviceId);
216
- throw new BluetoothPrintError(
217
- ErrorCode.DEVICE_DISCONNECTED,
218
- 'Device disconnected',
219
- error as Error
220
- );
221
- }
222
-
223
- const { chunkSize, delay, retries } = validatedOptions;
224
- const data = new Uint8Array(buffer);
225
- const totalChunks = Math.ceil(data.length / chunkSize);
226
-
227
- this.logger.debug(`Writing ${data.length} bytes in ${totalChunks} chunks`);
228
-
229
- // If no data to write, return directly
230
- if (data.length === 0) {
231
- this.logger.warn('No data to write');
232
- return;
233
- }
234
-
235
- for (let i = 0; i < data.length; i += chunkSize) {
236
- const chunk = data.slice(i, i + chunkSize);
237
- const chunkNum = Math.floor(i / chunkSize) + 1;
238
-
239
- let attempt = 0;
240
- while (attempt <= retries) {
241
- try {
242
- // Add write timeout handling
243
- const writePromise = tt.writeBLECharacteristicValue({
244
- deviceId,
245
- serviceId: serviceInfo.serviceId,
246
- characteristicId: serviceInfo.characteristicId,
247
- value: chunk.buffer,
248
- });
249
-
250
- const timeoutPromise = new Promise((_, reject) => {
251
- setTimeout(() => {
252
- reject(new Error('Write timeout after 5 seconds'));
253
- }, 5000);
254
- });
255
-
256
- await Promise.race([writePromise, timeoutPromise]);
257
-
258
- this.logger.debug(`Chunk ${chunkNum}/${totalChunks} written successfully`);
259
- break; // Success
260
- } catch (error) {
261
- attempt++;
262
- if (attempt > retries) {
263
- this.logger.error(`Chunk ${chunkNum} failed after ${retries} retries`);
264
- throw new BluetoothPrintError(
265
- ErrorCode.WRITE_FAILED,
266
- `Failed to write chunk ${chunkNum}/${totalChunks}`,
267
- error as Error
268
- );
269
- }
270
- this.logger.warn(`Chunk ${chunkNum} write failed, retry ${attempt}/${retries}`);
271
- // Wait before retry
272
- await new Promise(r => setTimeout(r, delay * 2));
273
- }
274
- }
275
-
276
- // Small delay to prevent congestion
277
- if (i + chunkSize < data.length) {
278
- await new Promise(r => setTimeout(r, delay));
279
- }
280
- }
281
-
282
- this.logger.info(`Successfully wrote ${data.length} bytes`);
283
- }
284
-
285
- /**
286
- * Discovers services and characteristics for a device
287
- * Caches the writeable characteristic for future writes
288
- *
289
- * @param deviceId - Bluetooth device ID
290
- * @throws {BluetoothPrintError} When no writeable characteristic is found
291
- */
292
- private async discoverServices(deviceId: string): Promise<void> {
293
- this.logger.debug('Discovering services for device:', deviceId);
294
-
295
- try {
296
- const services = await tt.getBLEDeviceServices({
297
- deviceId,
298
- });
299
-
300
- for (const service of services.services) {
301
- const chars = await tt.getBLEDeviceCharacteristics({
302
- deviceId,
303
- serviceId: service.uuid,
304
- });
305
-
306
- const writeChar = chars.characteristics.find(
307
- (c: ByteDanceBLECharacteristic) => c.properties.write || c.properties.writeWithoutResponse
308
- );
309
-
310
- if (writeChar) {
311
- this.serviceCache.set(deviceId, {
312
- serviceId: service.uuid,
313
- characteristicId: writeChar.uuid,
314
- });
315
- this.logger.info('Found writeable characteristic:', {
316
- service: service.uuid,
317
- characteristic: writeChar.uuid,
318
- });
319
- return;
320
- }
321
- }
322
-
323
- // No writeable characteristic found
324
- throw new BluetoothPrintError(
325
- ErrorCode.CHARACTERISTIC_NOT_FOUND,
326
- 'No writeable characteristic found. Make sure the device is a supported printer.'
327
- );
328
- } catch (error) {
329
- if (error instanceof BluetoothPrintError) {
330
- throw error;
331
- }
332
- throw new BluetoothPrintError(
333
- ErrorCode.SERVICE_DISCOVERY_FAILED,
334
- 'Failed to discover device services',
335
- error as Error
336
- );
337
- }
27
+ export class ByteDanceAdapter extends MiniProgramAdapter {
28
+ protected getApi(): MiniProgramBLEApi {
29
+ return tt;
338
30
  }
339
31
  }