@onekeyfe/hd-transport-lowlevel 1.2.2-alpha.6 → 1.2.2-alpha.8

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.
@@ -198,7 +198,7 @@ describe('LowlevelTransport protocol framing', () => {
198
198
  });
199
199
  });
200
200
 
201
- test('uses the Protocol V2 BLE writer with the lowlevel compatibility packet size', async () => {
201
+ test('uses 192-byte packets for Protocol V2 BLE writes', async () => {
202
202
  const plugin = createPlugin({ devices: [], responses: [] });
203
203
  const lowlevel = configureTransport(plugin);
204
204
  const context = {
@@ -209,10 +209,30 @@ describe('LowlevelTransport protocol framing', () => {
209
209
  signal: new AbortController().signal,
210
210
  };
211
211
 
212
- await lowlevel.writeProtocolV2Frame('pro2-id', new Uint8Array(130), context, jest.fn());
212
+ await lowlevel.writeProtocolV2Frame('pro2-id', new Uint8Array(386), context, jest.fn());
213
213
 
214
214
  expect(plugin.send).toHaveBeenCalledTimes(3);
215
- expect(plugin.send.mock.calls.map(([, hex]) => hex.length / 2)).toEqual([64, 64, 2]);
215
+ expect(plugin.send.mock.calls.map(([, hex]) => hex.length / 2)).toEqual([192, 192, 2]);
216
+ });
217
+
218
+ test('uses the packet capacity reported after BLE connection', async () => {
219
+ const plugin = createPlugin({ devices: [], responses: [] });
220
+ plugin.getProtocolV2PacketCapacity = jest.fn().mockResolvedValue(244);
221
+ const lowlevel = configureTransport(plugin);
222
+ lowlevel.detectProtocol = jest.fn().mockResolvedValue('V2');
223
+ const context = {
224
+ messageName: 'Ping',
225
+ timeoutMs: 1000,
226
+ highThroughput: false,
227
+ generation: 1,
228
+ signal: new AbortController().signal,
229
+ };
230
+
231
+ await lowlevel.acquire({ uuid: 'pro2-id', expectedProtocol: 'V2' });
232
+ await lowlevel.writeProtocolV2Frame('pro2-id', new Uint8Array(386), context, jest.fn());
233
+
234
+ expect(plugin.getProtocolV2PacketCapacity).toHaveBeenCalledWith('pro2-id');
235
+ expect(plugin.send.mock.calls.map(([, hex]) => hex.length / 2)).toEqual([244, 142]);
216
236
  });
217
237
 
218
238
  test('rejects calls before protocol detection', async () => {
package/dist/index.d.ts CHANGED
@@ -17,6 +17,7 @@ declare function shouldLogFirmwareUploadProgress({ percent, lastLoggedPercent, n
17
17
  declare function getProtocolV1SendOptions(name: string): {
18
18
  withoutResponse: boolean;
19
19
  } | undefined;
20
+ declare function resolveLowlevelProtocolV2PacketCapacity(capacity?: number | null): number;
20
21
  declare class LowlevelTransport {
21
22
  _messages: ReturnType<typeof transport__default.parseConfigure> | undefined;
22
23
  _messagesV2: ReturnType<typeof transport__default.parseConfigure> | undefined;
@@ -29,6 +30,7 @@ declare class LowlevelTransport {
29
30
  private protocolV2Assemblers;
30
31
  private protocolV2Generations;
31
32
  private connectedDevices;
33
+ private protocolV2PacketCapacities;
32
34
  private protocolV2Links;
33
35
  private protocolV2SchemaConfiguration;
34
36
  getProtocolType(path: string): ProtocolType | undefined;
@@ -57,10 +59,11 @@ declare class LowlevelTransport {
57
59
  private readProtocolV1Message;
58
60
  private readProtocolV2Frame;
59
61
  private writeProtocolV2Frame;
62
+ private refreshProtocolV2PacketCapacity;
60
63
  private callProtocolV2;
61
64
  private createProtocolV2Adapter;
62
65
  private advanceProtocolV2Generation;
63
66
  cancel(): void;
64
67
  }
65
68
 
66
- export { LowlevelTransport as default, getProtocolV1SendOptions, shouldLogFirmwareUploadProgress };
69
+ export { LowlevelTransport as default, getProtocolV1SendOptions, resolveLowlevelProtocolV2PacketCapacity, shouldLogFirmwareUploadProgress };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,SAYN,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EACV,6BAA6B,EAC7B,YAAY,EAEZ,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAUpD,wBAAgB,+BAA+B,CAAC,EAC9C,OAAO,EACP,iBAAiB,EACjB,GAAG,EACH,YAAY,GACb,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACtB,WAMA;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM;;cAEpD;AAUD,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC,SAAS,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAEnE,WAAW,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAErE,UAAU,UAAS;IAEnB,GAAG,CAAC,EAAE,GAAG,CAAC;IAEV,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,MAAM,EAAE,6BAA6B,CAAuC;IAE5E,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,mBAAmB,CAAwC;IAEnE,OAAO,CAAC,oBAAoB,CAAoD;IAEhF,OAAO,CAAC,qBAAqB,CAAkC;IAE/D,OAAO,CAAC,gBAAgB,CAA0B;IAElD,OAAO,CAAC,eAAe,CA6BpB;IAEH,OAAO,CAAC,6BAA6B,CAAqB;IAE1D,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIvD,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,6BAA6B;IAO9E,SAAS,CAAC,UAAU,EAAE,GAAG;IAMzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAiBnC,MAAM;IAIA,SAAS;IAKT,OAAO,CAAC,KAAK,EAAE,oBAAoB;;;;IAmDnC,OAAO,CAAC,IAAI,EAAE,MAAM;IAepB,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;IAoB1B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;YAatD,cAAc;IA6E5B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,kBAAkB;YAMZ,cAAc;YA2Cd,yBAAyB;YAiCzB,eAAe;YAgBf,eAAe;YA6Bf,UAAU;YAUV,qBAAqB;YAmBrB,mBAAmB;YAqBnB,oBAAoB;YAgBpB,cAAc;IAwB5B,OAAO,CAAC,uBAAuB;IAgC/B,OAAO,CAAC,2BAA2B;IAMnC,MAAM;CAGP"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,SAYN,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EACV,6BAA6B,EAC7B,YAAY,EAEZ,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAWpD,wBAAgB,+BAA+B,CAAC,EAC9C,OAAO,EACP,iBAAiB,EACjB,GAAG,EACH,YAAY,GACb,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACtB,WAMA;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM;;cAEpD;AAED,wBAAgB,uCAAuC,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,UAK/E;AAUD,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC,SAAS,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAEnE,WAAW,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAErE,UAAU,UAAS;IAEnB,GAAG,CAAC,EAAE,GAAG,CAAC;IAEV,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,MAAM,EAAE,6BAA6B,CAAuC;IAE5E,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,mBAAmB,CAAwC;IAEnE,OAAO,CAAC,oBAAoB,CAAoD;IAEhF,OAAO,CAAC,qBAAqB,CAAkC;IAE/D,OAAO,CAAC,gBAAgB,CAA0B;IAElD,OAAO,CAAC,0BAA0B,CAAkC;IAEpE,OAAO,CAAC,eAAe,CA8BpB;IAEH,OAAO,CAAC,6BAA6B,CAAqB;IAE1D,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIvD,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,6BAA6B;IAO9E,SAAS,CAAC,UAAU,EAAE,GAAG;IAMzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAiBnC,MAAM;IAIA,SAAS;IAKT,OAAO,CAAC,KAAK,EAAE,oBAAoB;;;;IAqDnC,OAAO,CAAC,IAAI,EAAE,MAAM;IAgBpB,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;IAoB1B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;YAatD,cAAc;IA6E5B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,kBAAkB;YAMZ,cAAc;YA2Cd,yBAAyB;YAkCzB,eAAe;YAgBf,eAAe;YA6Bf,UAAU;YAUV,qBAAqB;YAmBrB,mBAAmB;YAqBnB,oBAAoB;YAkBpB,+BAA+B;YAgB/B,cAAc;IAwB5B,OAAO,CAAC,uBAAuB;IAgC/B,OAAO,CAAC,2BAA2B;IAMnC,MAAM;CAGP"}
package/dist/index.js CHANGED
@@ -42,7 +42,8 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
42
42
  const { check, ProtocolV1, parseConfigure } = transport__default["default"];
43
43
  const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
44
44
  const PROTOCOL_V2_PROBE_TIMEOUT_MS = 5000;
45
- const LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH = 64;
45
+ const LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH_FALLBACK = 192;
46
+ const LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH_MAX = 244;
46
47
  const FIRMWARE_UPLOAD_LOG_PERCENT_STEP = 5;
47
48
  const FIRMWARE_UPLOAD_LOG_INTERVAL_MS = 10000;
48
49
  function shouldLogFirmwareUploadProgress({ percent, lastLoggedPercent, now, lastLoggedAt, }) {
@@ -53,6 +54,12 @@ function shouldLogFirmwareUploadProgress({ percent, lastLoggedPercent, now, last
53
54
  function getProtocolV1SendOptions(name) {
54
55
  return name === 'FirmwareUpload' ? { withoutResponse: false } : undefined;
55
56
  }
57
+ function resolveLowlevelProtocolV2PacketCapacity(capacity) {
58
+ if (typeof capacity !== 'number' || !Number.isFinite(capacity) || capacity <= 0) {
59
+ return LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH_FALLBACK;
60
+ }
61
+ return Math.min(Math.floor(capacity), LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH_MAX);
62
+ }
56
63
  function isProtocolV1TransportChunk(data) {
57
64
  return data.length >= 9 && data[0] === 0x3f && data[1] === 0x23 && data[2] === 0x23;
58
65
  }
@@ -68,6 +75,7 @@ class LowlevelTransport {
68
75
  this.protocolV2Assemblers = new Map();
69
76
  this.protocolV2Generations = new Map();
70
77
  this.connectedDevices = new Set();
78
+ this.protocolV2PacketCapacities = new Map();
71
79
  this.protocolV2Links = new transport.ProtocolV2LinkManager({
72
80
  getSchemas: () => {
73
81
  if (!this._messages || !this._messagesV2) {
@@ -94,6 +102,7 @@ class LowlevelTransport {
94
102
  }
95
103
  finally {
96
104
  this.connectedDevices.delete(uuid);
105
+ this.protocolV2PacketCapacities.delete(uuid);
97
106
  }
98
107
  }
99
108
  }),
@@ -141,6 +150,7 @@ class LowlevelTransport {
141
150
  const alreadyConnected = this.connectedDevices.has(input.uuid);
142
151
  try {
143
152
  yield this.plugin.connect(input.uuid);
153
+ yield this.refreshProtocolV2PacketCapacity(input.uuid);
144
154
  if (!alreadyConnected) {
145
155
  this.connectedDevices.add(input.uuid);
146
156
  this.advanceProtocolV2Generation(input.uuid);
@@ -176,6 +186,7 @@ class LowlevelTransport {
176
186
  this.connectedDevices.delete(input.uuid);
177
187
  this.deviceProtocol.delete(input.uuid);
178
188
  this.protocolV2Assemblers.delete(input.uuid);
189
+ this.protocolV2PacketCapacities.delete(input.uuid);
179
190
  this.advanceProtocolV2Generation(input.uuid);
180
191
  }
181
192
  throw error;
@@ -190,6 +201,7 @@ class LowlevelTransport {
190
201
  this.connectedDevices.delete(uuid);
191
202
  this.deviceProtocol.delete(uuid);
192
203
  this.protocolV2Assemblers.delete(uuid);
204
+ this.protocolV2PacketCapacities.delete(uuid);
193
205
  return true;
194
206
  }
195
207
  catch (error) {
@@ -353,6 +365,7 @@ class LowlevelTransport {
353
365
  }
354
366
  try {
355
367
  yield this.plugin.connect(uuid);
368
+ yield this.refreshProtocolV2PacketCapacity(uuid);
356
369
  this.connectedDevices.add(uuid);
357
370
  this.advanceProtocolV2Generation(uuid);
358
371
  }
@@ -462,7 +475,7 @@ class LowlevelTransport {
462
475
  return __awaiter(this, void 0, void 0, function* () {
463
476
  yield transport.writeProtocolV2BleFrame({
464
477
  frame,
465
- packetCapacity: LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH,
478
+ packetCapacity: resolveLowlevelProtocolV2PacketCapacity(this.protocolV2PacketCapacities.get(uuid)),
466
479
  assertActive: assertCurrentGeneration,
467
480
  signal: context.signal,
468
481
  abortMessage: `Protocol V2 BLE write aborted for ${context.messageName}`,
@@ -470,6 +483,19 @@ class LowlevelTransport {
470
483
  });
471
484
  });
472
485
  }
486
+ refreshProtocolV2PacketCapacity(uuid) {
487
+ var _a, _b, _c;
488
+ return __awaiter(this, void 0, void 0, function* () {
489
+ let reportedCapacity;
490
+ try {
491
+ reportedCapacity = yield ((_b = (_a = this.plugin).getProtocolV2PacketCapacity) === null || _b === void 0 ? void 0 : _b.call(_a, uuid));
492
+ }
493
+ catch (error) {
494
+ (_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug(`[LowlevelTransport] read Protocol V2 packet capacity failed: ${uuid}`, error);
495
+ }
496
+ this.protocolV2PacketCapacities.set(uuid, resolveLowlevelProtocolV2PacketCapacity(reportedCapacity));
497
+ });
498
+ }
473
499
  callProtocolV2(uuid, name, data, options) {
474
500
  return __awaiter(this, void 0, void 0, function* () {
475
501
  if (!this._messages || !this._messagesV2) {
@@ -528,4 +554,5 @@ class LowlevelTransport {
528
554
 
529
555
  exports["default"] = LowlevelTransport;
530
556
  exports.getProtocolV1SendOptions = getProtocolV1SendOptions;
557
+ exports.resolveLowlevelProtocolV2PacketCapacity = resolveLowlevelProtocolV2PacketCapacity;
531
558
  exports.shouldLogFirmwareUploadProgress = shouldLogFirmwareUploadProgress;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-lowlevel",
3
- "version": "1.2.2-alpha.6",
3
+ "version": "1.2.2-alpha.8",
4
4
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -20,8 +20,8 @@
20
20
  "lint:fix": "eslint . --fix"
21
21
  },
22
22
  "dependencies": {
23
- "@onekeyfe/hd-shared": "1.2.2-alpha.6",
24
- "@onekeyfe/hd-transport": "1.2.2-alpha.6"
23
+ "@onekeyfe/hd-shared": "1.2.2-alpha.8",
24
+ "@onekeyfe/hd-transport": "1.2.2-alpha.8"
25
25
  },
26
- "gitHead": "538d5371d9369747beabf68c5dc7a617531bace2"
26
+ "gitHead": "7a5d129ea1db0b3eb230e309ab29ed3e9e7f141e"
27
27
  }
package/src/index.ts CHANGED
@@ -26,7 +26,8 @@ const { check, ProtocolV1, parseConfigure } = transport;
26
26
 
27
27
  const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
28
28
  const PROTOCOL_V2_PROBE_TIMEOUT_MS = 5000;
29
- const LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH = 64;
29
+ const LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH_FALLBACK = 192;
30
+ const LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH_MAX = 244;
30
31
  const FIRMWARE_UPLOAD_LOG_PERCENT_STEP = 5;
31
32
  const FIRMWARE_UPLOAD_LOG_INTERVAL_MS = 10_000;
32
33
 
@@ -52,6 +53,13 @@ export function getProtocolV1SendOptions(name: string) {
52
53
  return name === 'FirmwareUpload' ? { withoutResponse: false } : undefined;
53
54
  }
54
55
 
56
+ export function resolveLowlevelProtocolV2PacketCapacity(capacity?: number | null) {
57
+ if (typeof capacity !== 'number' || !Number.isFinite(capacity) || capacity <= 0) {
58
+ return LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH_FALLBACK;
59
+ }
60
+ return Math.min(Math.floor(capacity), LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH_MAX);
61
+ }
62
+
55
63
  function isProtocolV1TransportChunk(data: Uint8Array) {
56
64
  return data.length >= 9 && data[0] === 0x3f && data[1] === 0x23 && data[2] === 0x23;
57
65
  }
@@ -83,6 +91,8 @@ export default class LowlevelTransport {
83
91
 
84
92
  private connectedDevices: Set<string> = new Set();
85
93
 
94
+ private protocolV2PacketCapacities: Map<string, number> = new Map();
95
+
86
96
  private protocolV2Links = new ProtocolV2LinkManager<string>({
87
97
  getSchemas: () => {
88
98
  if (!this._messages || !this._messagesV2) {
@@ -109,6 +119,7 @@ export default class LowlevelTransport {
109
119
  );
110
120
  } finally {
111
121
  this.connectedDevices.delete(uuid);
122
+ this.protocolV2PacketCapacities.delete(uuid);
112
123
  }
113
124
  }
114
125
  },
@@ -163,6 +174,7 @@ export default class LowlevelTransport {
163
174
  const alreadyConnected = this.connectedDevices.has(input.uuid);
164
175
  try {
165
176
  await this.plugin.connect(input.uuid);
177
+ await this.refreshProtocolV2PacketCapacity(input.uuid);
166
178
  if (!alreadyConnected) {
167
179
  this.connectedDevices.add(input.uuid);
168
180
  this.advanceProtocolV2Generation(input.uuid);
@@ -204,6 +216,7 @@ export default class LowlevelTransport {
204
216
  this.connectedDevices.delete(input.uuid);
205
217
  this.deviceProtocol.delete(input.uuid);
206
218
  this.protocolV2Assemblers.delete(input.uuid);
219
+ this.protocolV2PacketCapacities.delete(input.uuid);
207
220
  this.advanceProtocolV2Generation(input.uuid);
208
221
  }
209
222
  throw error;
@@ -218,6 +231,7 @@ export default class LowlevelTransport {
218
231
  this.deviceProtocol.delete(uuid);
219
232
  // Confirmed protocol stays on the device endpoint; BLE names are not a probe hint.
220
233
  this.protocolV2Assemblers.delete(uuid);
234
+ this.protocolV2PacketCapacities.delete(uuid);
221
235
  return true;
222
236
  } catch (error) {
223
237
  this.Log.debug('lowlelvel transport disconnect error: ', error);
@@ -428,6 +442,7 @@ export default class LowlevelTransport {
428
442
 
429
443
  try {
430
444
  await this.plugin.connect(uuid);
445
+ await this.refreshProtocolV2PacketCapacity(uuid);
431
446
  this.connectedDevices.add(uuid);
432
447
  this.advanceProtocolV2Generation(uuid);
433
448
  } catch (error) {
@@ -545,7 +560,9 @@ export default class LowlevelTransport {
545
560
  ) {
546
561
  await writeProtocolV2BleFrame({
547
562
  frame,
548
- packetCapacity: LOWLEVEL_PROTOCOL_V2_PACKET_LENGTH,
563
+ packetCapacity: resolveLowlevelProtocolV2PacketCapacity(
564
+ this.protocolV2PacketCapacities.get(uuid)
565
+ ),
549
566
  assertActive: assertCurrentGeneration,
550
567
  signal: context.signal,
551
568
  abortMessage: `Protocol V2 BLE write aborted for ${context.messageName}`,
@@ -553,6 +570,22 @@ export default class LowlevelTransport {
553
570
  });
554
571
  }
555
572
 
573
+ private async refreshProtocolV2PacketCapacity(uuid: string) {
574
+ let reportedCapacity: number | undefined;
575
+ try {
576
+ reportedCapacity = await this.plugin.getProtocolV2PacketCapacity?.(uuid);
577
+ } catch (error) {
578
+ this.Log?.debug(
579
+ `[LowlevelTransport] read Protocol V2 packet capacity failed: ${uuid}`,
580
+ error
581
+ );
582
+ }
583
+ this.protocolV2PacketCapacities.set(
584
+ uuid,
585
+ resolveLowlevelProtocolV2PacketCapacity(reportedCapacity)
586
+ );
587
+ }
588
+
556
589
  private async callProtocolV2(
557
590
  uuid: string,
558
591
  name: string,