@onekeyfe/hd-transport-react-native 1.1.27-alpha.37 → 1.1.27-alpha.38

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.
@@ -1 +1 @@
1
- {"version":3,"file":"BleManager.d.ts","sourceRoot":"","sources":["../src/BleManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAWnE,eAAO,MAAM,qBAAqB,iBAAkB,MAAM,EAAE,0BACZ,CAAC;AAEjD,eAAO,MAAM,gBAAgB,6BAAwC,CAAC;AAEtE,eAAO,MAAM,UAAU,eAAgB,MAAM;;;EAAoC,CAAC;AAElF,eAAO,MAAM,iBAAiB,kBAAmB,MAAM,KAAG,QAAQ,UAAU,GAAG,SAAS,CAmCpF,CAAC"}
1
+ {"version":3,"file":"BleManager.d.ts","sourceRoot":"","sources":["../src/BleManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAWnE,eAAO,MAAM,qBAAqB,iBAAkB,MAAM,EAAE,0BACZ,CAAC;AAEjD,eAAO,MAAM,gBAAgB,6BAAwC,CAAC;AAEtE,eAAO,MAAM,UAAU,eAAgB,MAAM;;;EAAoC,CAAC;AAElF,eAAO,MAAM,iBAAiB,kBAAmB,MAAM,KAAG,QAAQ,UAAU,GAAG,SAAS,CAkCpF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"BleTransport.d.ts","sourceRoot":"","sources":["../src/BleTransport.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAMjF,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,EAAE,EAAE,MAAM,CAAC;IAEX,IAAI,SAA6B;IAEjC,MAAM,EAAE,MAAM,CAAC;IAEf,OAAO,SAAM;IAEb,mBAAmB,EAAE,cAAc,CAAC;IAEpC,oBAAoB,EAAE,cAAc,CAAC;IAErC,kBAAkB,CAAC,EAAE,YAAY,CAAC;IAElC,sBAAsB,CAAC,EAAE,YAAY,CAAC;IAEtC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,MAAM,CAAC,WAAW,SAAK;IAEvB,MAAM,CAAC,WAAW,SAAQ;gBAGxB,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,cAAc,EACnC,oBAAoB,EAAE,cAAc;IAehC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,SAA2B,GAAG,OAAO,CAAC,IAAI,CAAC;CA2BzF"}
1
+ {"version":3,"file":"BleTransport.d.ts","sourceRoot":"","sources":["../src/BleTransport.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAMjF,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,EAAE,EAAE,MAAM,CAAC;IAEX,IAAI,SAA6B;IAEjC,MAAM,EAAE,MAAM,CAAC;IAEf,OAAO,SAAM;IAEb,mBAAmB,EAAE,cAAc,CAAC;IAEpC,oBAAoB,EAAE,cAAc,CAAC;IAErC,kBAAkB,CAAC,EAAE,YAAY,CAAC;IAElC,sBAAsB,CAAC,EAAE,YAAY,CAAC;IAEtC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,MAAM,CAAC,WAAW,SAAK;IAEvB,MAAM,CAAC,WAAW,SAAQ;gBAGxB,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,cAAc,EACnC,oBAAoB,EAAE,cAAc;IAchC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,SAA2B,GAAG,OAAO,CAAC,IAAI,CAAC;CA2BzF"}
@@ -0,0 +1,15 @@
1
+ export type BlePlatform = 'ios' | 'android' | string;
2
+ export type BleWriteCapability = {
3
+ isWritableWithResponse?: boolean | null;
4
+ isWritableWithoutResponse?: boolean | null;
5
+ };
6
+ export type BleWriteMode = 'withResponse' | 'withoutResponse';
7
+ export declare function hasWritableCapability(characteristic: BleWriteCapability): boolean;
8
+ export declare function resolveBleWriteMode(characteristic: BleWriteCapability, preferredMode?: BleWriteMode): BleWriteMode;
9
+ export declare function resolveProtocolV2PacketCapacity({ platform, iosPacketLength, androidPacketLength, mtu, }: {
10
+ platform: BlePlatform;
11
+ iosPacketLength?: number;
12
+ androidPacketLength?: number;
13
+ mtu?: number | null;
14
+ }): number;
15
+ //# sourceMappingURL=bleStrategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bleStrategy.d.ts","sourceRoot":"","sources":["../src/bleStrategy.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;AAErD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,sBAAsB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACxC,yBAAyB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,iBAAiB,CAAC;AAE9D,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,kBAAkB,WAIvE;AAED,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,kBAAkB,EAClC,aAAa,GAAE,YAAgC,GAC9C,YAAY,CAkBd;AAED,wBAAgB,+BAA+B,CAAC,EAC9C,QAAQ,EACR,eAAmC,EACnC,mBAA2C,EAC3C,GAAG,GACJ,EAAE;IACD,QAAQ,EAAE,WAAW,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,UAWA"}
@@ -1,5 +1,6 @@
1
1
  export declare const IOS_PACKET_LENGTH = 128;
2
2
  export declare const ANDROID_PACKET_LENGTH = 192;
3
+ export declare const ANDROID_DEFAULT_MTU = 23;
3
4
  export declare const getBluetoothServiceUuids: () => string[];
4
5
  export declare const getInfosForServiceUuid: (serviceUuid: string, deviceType: 'classic') => {
5
6
  serviceUuid: string;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AA8BzC,eAAO,MAAM,wBAAwB,gBAA0B,CAAC;AAChE,eAAO,MAAM,sBAAsB,gBAAiB,MAAM,cAAc,SAAS;iBA1BhE,MAAM;;;QAyCtB,CAAC;AAEF,eAAO,MAAM,gBAAgB,UAAW,MAAM,GAAG,IAAI,WACP,CAAC;AAE/C,eAAO,MAAM,aAAa,UAAW,MAAM,GAAG,IAAI,WAGjD,CAAC;AAEF,eAAO,MAAM,aAAa,UAAW,MAAM,GAAG,IAAI,UAAU,MAAM,GAAG,IAAI,YAQxE,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AA8BtC,eAAO,MAAM,wBAAwB,gBAA0B,CAAC;AAChE,eAAO,MAAM,sBAAsB,gBAAiB,MAAM,cAAc,SAAS;iBA1BhE,MAAM;;;QAyCtB,CAAC;AAEF,eAAO,MAAM,gBAAgB,UAAW,MAAM,GAAG,IAAI,WACP,CAAC;AAE/C,eAAO,MAAM,aAAa,UAAW,MAAM,GAAG,IAAI,WAGjD,CAAC;AAEF,eAAO,MAAM,aAAa,UAAW,MAAM,GAAG,IAAI,UAAU,MAAM,GAAG,IAAI,YAQxE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAIL,UAAU,IAAI,aAAa,EAE5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,SAAS,EAAE,EAEhB,KAAK,oBAAoB,EAGzB,KAAK,YAAY,EAGjB,KAAK,oBAAoB,EAE1B,MAAM,wBAAwB,CAAC;AAuBhC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAsBjE,MAAM,MAAM,mBAAmB,GAAG;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC,CAAC;AAqBF,wBAAgB,4BAA4B,CAAC,MAAM,GAAE,mBAAwB,QA0B5E;AAED,wBAAgB,wBAAwB,SAGvC;AAED,wBAAgB,sBAAsB;;;;;;;EAErC;AA0BD,MAAM,MAAM,aAAa,GAAG,oBAAoB,GAAG,MAAM,CAAC;AA2C1D,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAC1C,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;IAEzC,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,IAAI,SAA6B;IAEjC,UAAU,UAAS;IAEnB,OAAO,UAAS;IAEhB,WAAW,SAA0B;IAErC,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAExC,OAAO,CAAC,EAAE,YAAY,CAAC;IAGvB,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,mBAAmB,CAAwC;IAEnE,OAAO,CAAC,oBAAoB,CAAoD;IAEhF,OAAO,CAAC,qBAAqB,CAAwC;IAErE,OAAO,CAAC,uBAAuB,CAAgD;IAE/E,OAAO,CAAC,oBAAoB,CAAgD;IAE5E,OAAO,CAAC,uBAAuB,CAAK;IAEpC,OAAO,CAAC,aAAa,CAAkC;IAEvD,OAAO,CAAC,gBAAgB,CAAK;gBAEjB,OAAO,EAAE,gBAAgB;IAIrC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY;IAKvC,SAAS,CAAC,UAAU,EAAE,GAAG;IAMzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAKnC,MAAM;IAIN,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;IAWjC,SAAS;IAkIT,OAAO,CAAC,KAAK,EAAE,eAAe;;;;IAuRpC,sBAAsB,CACpB,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,mBAAmB,EAAE,MAAM,GAC1B,YAAY;IAwGT,OAAO,CAAC,IAAI,EAAE,MAAM;IAwDpB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIjE,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;YAoDlB,cAAc;IA6H5B,IAAI;IAIE,UAAU,CAAC,OAAO,EAAE,MAAM;IAiFhC,MAAM;IAQN,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,kBAAkB;YAMZ,cAAc;YAwDd,iCAAiC;YAmDjC,eAAe;YAgBf,eAAe;IAwB7B,OAAO,CAAC,4BAA4B;IA0BpC,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,sBAAsB;YAIhB,mBAAmB;YAiBnB,oBAAoB;YA4DpB,cAAc;IAyG5B,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAGxD"}
package/dist/index.js CHANGED
@@ -61,84 +61,41 @@ const getConnectedDeviceIds = (serviceUuids) => BleUtils__default["default"].get
61
61
  const pairDevice = (macAddress) => BleUtils__default["default"].pairDevice(macAddress);
62
62
  const onDeviceBondState = (bleMacAddress) => new Promise((resolve, reject) => {
63
63
  let timeout;
64
- const cleanup = (cleanupListener) => {
64
+ let cleanupListener;
65
+ const cleanup = () => {
65
66
  if (timeout) {
66
67
  clearTimeout(timeout);
67
68
  }
68
69
  if (cleanupListener)
69
70
  cleanupListener();
70
71
  };
71
- const cleanupListener = BleUtils__default["default"].onDeviceBondState(peripheral => {
72
+ timeout = setTimeout(() => {
73
+ cleanup();
74
+ reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, 'device is not bonded'));
75
+ }, 60 * 1000);
76
+ cleanupListener = BleUtils__default["default"].onDeviceBondState(peripheral => {
72
77
  var _a;
73
78
  if (((_a = peripheral.id) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== bleMacAddress.toLowerCase()) {
74
79
  return;
75
80
  }
76
81
  const { bondState } = peripheral;
77
- if (bondState.preState === 'BOND_NONE' && bondState.state === 'BOND_BONDING') {
78
- timeout = setTimeout(() => {
79
- cleanup(cleanupListener);
80
- reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, 'device is not bonded'));
81
- }, 60 * 1000);
82
- }
83
82
  const hasBonded = bondState.preState === 'BOND_BONDING' && bondState.state === 'BOND_BONDED';
84
83
  const hasCanceled = bondState.preState === 'BOND_BONDING' && bondState.state === 'BOND_NONE';
85
84
  Logger.debug('onDeviceBondState bondState:', bondState);
86
85
  if (hasBonded) {
87
- cleanup(cleanupListener);
86
+ cleanup();
88
87
  resolve(peripheral);
89
88
  }
90
89
  else if (hasCanceled) {
91
- cleanup(cleanupListener);
90
+ cleanup();
92
91
  reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceBondedCanceled, 'bonding canceled'));
93
92
  }
94
93
  });
95
94
  });
96
95
 
97
- const timer = process.env.NODE_ENV === 'development'
98
- ? {
99
- timeout: (fn, ms) => {
100
- const startTime = Date.now();
101
- const interval = setInterval(() => {
102
- if (Date.now() - startTime >= ms) {
103
- clearInterval(interval);
104
- fn();
105
- }
106
- }, 100);
107
- return () => {
108
- clearInterval(interval);
109
- };
110
- },
111
- }
112
- : {
113
- timeout: (fn, ms) => {
114
- const timeout = setTimeout(fn, ms);
115
- return () => clearTimeout(timeout);
116
- },
117
- };
118
-
119
- const subscribeBleOn = (bleManager, ms = 1000) => new Promise((resolve, reject) => {
120
- let done = false;
121
- const subscription = bleManager.onStateChange(state => {
122
- console.log('ble state -> ', state);
123
- if (state === 'PoweredOn') {
124
- if (done)
125
- return;
126
- clearTimeout();
127
- done = true;
128
- subscription.remove();
129
- resolve();
130
- }
131
- }, true);
132
- const clearTimeout = timer.timeout(() => {
133
- if (done)
134
- return;
135
- subscription.remove();
136
- reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError));
137
- }, ms);
138
- });
139
-
140
96
  const IOS_PACKET_LENGTH = 128;
141
97
  const ANDROID_PACKET_LENGTH = 192;
98
+ const ANDROID_DEFAULT_MTU = 23;
142
99
  const ClassicServiceUUID = '00000001-0000-1000-8000-00805f9b34fb';
143
100
  const OneKeyServices = {
144
101
  classic: {
@@ -180,6 +137,78 @@ const isSameBleUuid = (left, right) => {
180
137
  (getBleUuidKey(left) !== '' && getBleUuidKey(left) === getBleUuidKey(right)));
181
138
  };
182
139
 
140
+ function hasWritableCapability(characteristic) {
141
+ return !!(characteristic.isWritableWithResponse || characteristic.isWritableWithoutResponse);
142
+ }
143
+ function resolveBleWriteMode(characteristic, preferredMode = 'withoutResponse') {
144
+ if (preferredMode === 'withoutResponse' && characteristic.isWritableWithoutResponse) {
145
+ return 'withoutResponse';
146
+ }
147
+ if (preferredMode === 'withResponse' && characteristic.isWritableWithResponse) {
148
+ return 'withResponse';
149
+ }
150
+ if (characteristic.isWritableWithoutResponse) {
151
+ return 'withoutResponse';
152
+ }
153
+ if (characteristic.isWritableWithResponse) {
154
+ return 'withResponse';
155
+ }
156
+ return preferredMode;
157
+ }
158
+ function resolveProtocolV2PacketCapacity({ platform, iosPacketLength = IOS_PACKET_LENGTH, androidPacketLength = ANDROID_PACKET_LENGTH, mtu, }) {
159
+ if (platform === 'ios') {
160
+ return iosPacketLength;
161
+ }
162
+ if (platform === 'android') {
163
+ const payloadLength = Math.max((mtu !== null && mtu !== void 0 ? mtu : ANDROID_DEFAULT_MTU) - 3, 1);
164
+ return Math.min(androidPacketLength, payloadLength);
165
+ }
166
+ return androidPacketLength;
167
+ }
168
+
169
+ const timer = process.env.NODE_ENV === 'development'
170
+ ? {
171
+ timeout: (fn, ms) => {
172
+ const startTime = Date.now();
173
+ const interval = setInterval(() => {
174
+ if (Date.now() - startTime >= ms) {
175
+ clearInterval(interval);
176
+ fn();
177
+ }
178
+ }, 100);
179
+ return () => {
180
+ clearInterval(interval);
181
+ };
182
+ },
183
+ }
184
+ : {
185
+ timeout: (fn, ms) => {
186
+ const timeout = setTimeout(fn, ms);
187
+ return () => clearTimeout(timeout);
188
+ },
189
+ };
190
+
191
+ const subscribeBleOn = (bleManager, ms = 1000) => new Promise((resolve, reject) => {
192
+ let done = false;
193
+ const subscription = bleManager.onStateChange(state => {
194
+ console.log('ble state -> ', state);
195
+ if (state === 'PoweredOn') {
196
+ if (done)
197
+ return;
198
+ clearTimeout();
199
+ done = true;
200
+ subscription.remove();
201
+ resolve();
202
+ }
203
+ }, true);
204
+ const clearTimeout = timer.timeout(() => {
205
+ if (done)
206
+ return;
207
+ subscription.remove();
208
+ reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError));
209
+ }, ms);
210
+ });
211
+
183
212
  const isHeaderChunk = (chunk) => {
184
213
  if (chunk.length < 9)
185
214
  return false;
@@ -196,12 +225,11 @@ const Log$1 = bleLogger;
196
225
  class BleTransport {
197
226
  constructor(device, writeCharacteristic, notifyCharacteristic) {
198
227
  this.name = 'ReactNativeBleTransport';
199
- this.mtuSize = 20;
228
+ this.mtuSize = 23;
200
229
  this.id = device.id;
201
230
  this.device = device;
202
231
  this.writeCharacteristic = writeCharacteristic;
203
232
  this.notifyCharacteristic = notifyCharacteristic;
204
- console.log(`BleTransport(${String(this.id)}) new instance`);
205
233
  }
206
234
  writeWithRetry(data, retryCount = BleTransport.MAX_RETRIES) {
207
235
  return __awaiter(this, void 0, void 0, function* () {
@@ -240,9 +268,10 @@ const Log = bleLogger;
240
268
  const transportCache = {};
241
269
  const BLE_RESPONSE_TIMEOUT_MS = 30000;
242
270
  const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
243
- const PROTOCOL_V2_PROBE_TIMEOUT_MS = 5000;
271
+ const PROTOCOL_V2_PROBE_TIMEOUT_MS = 10000;
244
272
  const DEVICE_SCAN_TIMEOUT_MS = 8000;
245
273
  const IOS_NOTIFY_READY_DELAY_MS = 150;
274
+ const ANDROID_NOTIFY_READY_DELAY_MS = 300;
246
275
  const HIGH_VOLUME_WRITE_BURST_SIZE = reactNative.Platform.OS === 'ios' ? 4 : 6;
247
276
  const HIGH_VOLUME_WRITE_PAUSE_MS = reactNative.Platform.OS === 'ios' ? 6 : 2;
248
277
  const HIGH_VOLUME_WRITE_FLUSH_DELAY_MS = reactNative.Platform.OS === 'ios' ? 20 : 8;
@@ -296,7 +325,7 @@ function hasKnownOneKeyService(device) {
296
325
  var _a;
297
326
  return ((_a = device === null || device === void 0 ? void 0 : device.serviceUUIDs) !== null && _a !== void 0 ? _a : []).some(serviceUuid => getInfosForServiceUuid(serviceUuid, 'classic'));
298
327
  }
299
- let connectOptions = {
328
+ const connectOptions = {
300
329
  requestMTU: 256,
301
330
  timeout: 3000,
302
331
  refreshGatt: 'OnConnected',
@@ -508,6 +537,9 @@ class ReactNativeBleTransport {
508
537
  if (bondState.bonding) {
509
538
  yield onDeviceBondState(uuid);
510
539
  }
540
+ else if (!bondState.bonded) {
541
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, 'device is not bonded');
542
+ }
511
543
  }
512
544
  if (!device) {
513
545
  const devices = yield blePlxManager.devices([uuid]);
@@ -528,7 +560,6 @@ class ReactNativeBleTransport {
528
560
  Log === null || Log === void 0 ? void 0 : Log.debug('try to connect to device has error: ', e);
529
561
  if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
530
562
  e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
531
- connectOptions = {};
532
563
  Log === null || Log === void 0 ? void 0 : Log.debug('first try to reconnect without params');
533
564
  device = yield blePlxManager.connectToDevice(uuid);
534
565
  }
@@ -553,7 +584,6 @@ class ReactNativeBleTransport {
553
584
  Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device has error: ', e);
554
585
  if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
555
586
  e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
556
- connectOptions = {};
557
587
  Log === null || Log === void 0 ? void 0 : Log.debug('second try to reconnect without params');
558
588
  try {
559
589
  device = yield device.connect();
@@ -639,7 +669,7 @@ class ReactNativeBleTransport {
639
669
  if (!notifyCharacteristic) {
640
670
  throw hdShared.ERRORS.TypedError('BLECharacteristicNotFound: notify characteristic not found');
641
671
  }
642
- if (!writeCharacteristic.isWritableWithResponse) {
672
+ if (!hasWritableCapability(writeCharacteristic)) {
643
673
  throw hdShared.ERRORS.TypedError('BLECharacteristicNotWritable: write characteristic not writable');
644
674
  }
645
675
  if (!notifyCharacteristic.isNotifiable) {
@@ -653,6 +683,9 @@ class ReactNativeBleTransport {
653
683
  this.deviceProtocolHints.set(uuid, protocolHint);
654
684
  }
655
685
  const transport$1 = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
686
+ if (reactNative.Platform.OS === 'android') {
687
+ transport$1.mtuSize = typeof device.mtu === 'number' ? device.mtu : transport$1.mtuSize;
688
+ }
656
689
  const monitorToken = this.nextMonitorToken;
657
690
  this.nextMonitorToken += 1;
658
691
  const notifyTransactionId = `${uuid}:notify:${monitorToken}`;
@@ -667,6 +700,9 @@ class ReactNativeBleTransport {
667
700
  setTimeout(resolve, IOS_NOTIFY_READY_DELAY_MS);
668
701
  });
669
702
  }
703
+ else if (reactNative.Platform.OS === 'android') {
704
+ yield delay(ANDROID_NOTIFY_READY_DELAY_MS);
705
+ }
670
706
  const protocolType = yield this.detectProtocol(uuid, expectedProtocol, protocolHint);
671
707
  (_f = this.emitter) === null || _f === void 0 ? void 0 : _f.emit('device-connect', {
672
708
  name: device.name,
@@ -1091,10 +1127,13 @@ class ReactNativeBleTransport {
1091
1127
  }
1092
1128
  throw this.createProtocolMismatchError(expectedProtocol);
1093
1129
  }
1094
- if (protocolHint === 'V2' && (yield this.probeProtocolV2(uuid))) {
1095
- this.deviceProtocol.set(uuid, 'V2');
1096
- Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V2 (hint)`);
1097
- return 'V2';
1130
+ if (protocolHint === 'V2') {
1131
+ if (yield this.probeProtocolV2(uuid)) {
1132
+ this.deviceProtocol.set(uuid, 'V2');
1133
+ Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V2 (hint)`);
1134
+ return 'V2';
1135
+ }
1136
+ throw this.createProtocolMismatchError('V2');
1098
1137
  }
1099
1138
  if (this.deviceProtocol.get(uuid) === 'V2' && (yield this.probeProtocolV2(uuid))) {
1100
1139
  this.deviceProtocol.set(uuid, 'V2');
@@ -1282,15 +1321,21 @@ class ReactNativeBleTransport {
1282
1321
  writeProtocolV2Frame(transport, frame, options) {
1283
1322
  return __awaiter(this, void 0, void 0, function* () {
1284
1323
  const tuning = getProtocolV2BleTuning();
1285
- const packetCapacity = reactNative.Platform.OS === 'ios' ? tuning.iosPacketLength : tuning.androidPacketLength;
1324
+ const packetCapacity = resolveProtocolV2PacketCapacity({
1325
+ platform: reactNative.Platform.OS,
1326
+ iosPacketLength: tuning.iosPacketLength,
1327
+ androidPacketLength: tuning.androidPacketLength,
1328
+ mtu: reactNative.Platform.OS === 'android' ? transport.mtuSize : undefined,
1329
+ });
1286
1330
  const writeWithResponse = !!(options === null || options === void 0 ? void 0 : options.writeWithResponse) || (!!(options === null || options === void 0 ? void 0 : options.highVolume) && tuning.highVolumeWriteWithResponse);
1287
- const shouldThrottle = !!(options === null || options === void 0 ? void 0 : options.highVolume) && !writeWithResponse;
1331
+ const writeMode = resolveBleWriteMode(transport.writeCharacteristic, writeWithResponse ? 'withResponse' : 'withoutResponse');
1332
+ const shouldThrottle = !!(options === null || options === void 0 ? void 0 : options.highVolume) && writeMode === 'withoutResponse';
1288
1333
  let packetsWritten = 0;
1289
1334
  try {
1290
1335
  for (let offset = 0; offset < frame.length; offset += packetCapacity) {
1291
1336
  const chunk = frame.slice(offset, offset + packetCapacity);
1292
1337
  const base64 = buffer.Buffer.from(chunk).toString('base64');
1293
- if (writeWithResponse) {
1338
+ if (writeMode === 'withResponse') {
1294
1339
  yield transport.writeCharacteristic.writeWithResponse(base64);
1295
1340
  }
1296
1341
  else {
@@ -1365,7 +1410,11 @@ class ReactNativeBleTransport {
1365
1410
  protocolV2: this._messagesV2,
1366
1411
  },
1367
1412
  router: transport.PROTOCOL_V2_CHANNEL_BLE_UART,
1368
- writeFrame: (frame) => this.writeProtocolV2Frame(transport$1, frame, { highVolume: highVolumeWrite }),
1413
+ writeFrame: (frame) => __awaiter(this, void 0, void 0, function* () {
1414
+ yield this.writeProtocolV2Frame(transport$1, frame, {
1415
+ highVolume: highVolumeWrite,
1416
+ });
1417
+ }),
1369
1418
  readFrame: () => __awaiter(this, void 0, void 0, function* () {
1370
1419
  const rxFrame = yield this.readProtocolV2Frame(uuid);
1371
1420
  if (!(rxFrame instanceof Uint8Array)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-react-native",
3
- "version": "1.1.27-alpha.37",
3
+ "version": "1.1.27-alpha.38",
4
4
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -19,11 +19,11 @@
19
19
  "lint:fix": "eslint . --fix"
20
20
  },
21
21
  "dependencies": {
22
- "@onekeyfe/hd-core": "1.1.27-alpha.37",
23
- "@onekeyfe/hd-shared": "1.1.27-alpha.37",
24
- "@onekeyfe/hd-transport": "1.1.27-alpha.37",
22
+ "@onekeyfe/hd-core": "1.1.27-alpha.38",
23
+ "@onekeyfe/hd-shared": "1.1.27-alpha.38",
24
+ "@onekeyfe/hd-transport": "1.1.27-alpha.38",
25
25
  "@onekeyfe/react-native-ble-utils": "^0.1.4",
26
26
  "react-native-ble-plx": "3.5.1"
27
27
  },
28
- "gitHead": "ff58ceb1249ba3f3f673b39f1c175093fab40a8b"
28
+ "gitHead": "71f3b20e3ec0d2c4b21b444501115dc8c0eba20b"
29
29
  }
package/src/BleManager.ts CHANGED
@@ -21,36 +21,35 @@ export const pairDevice = (macAddress: string) => BleUtils.pairDevice(macAddress
21
21
 
22
22
  export const onDeviceBondState = (bleMacAddress: string): Promise<Peripheral | undefined> =>
23
23
  new Promise((resolve, reject) => {
24
- let timeout: any | undefined;
24
+ let timeout: ReturnType<typeof setTimeout> | undefined;
25
+ let cleanupListener: (() => void) | undefined;
25
26
 
26
- const cleanup = (cleanupListener: (() => void) | undefined) => {
27
+ const cleanup = () => {
27
28
  if (timeout) {
28
29
  clearTimeout(timeout);
29
30
  }
30
31
  if (cleanupListener) cleanupListener();
31
32
  };
32
33
 
33
- const cleanupListener = BleUtils.onDeviceBondState(peripheral => {
34
+ timeout = setTimeout(() => {
35
+ cleanup();
36
+ reject(ERRORS.TypedError(HardwareErrorCode.BleDeviceNotBonded, 'device is not bonded'));
37
+ }, 60 * 1000);
38
+
39
+ cleanupListener = BleUtils.onDeviceBondState(peripheral => {
34
40
  if (peripheral.id?.toLowerCase() !== bleMacAddress.toLowerCase()) {
35
41
  return;
36
42
  }
37
43
  const { bondState } = peripheral;
38
44
 
39
- if (bondState.preState === 'BOND_NONE' && bondState.state === 'BOND_BONDING') {
40
- timeout = setTimeout(() => {
41
- cleanup(cleanupListener);
42
- reject(ERRORS.TypedError(HardwareErrorCode.BleDeviceNotBonded, 'device is not bonded'));
43
- }, 60 * 1000);
44
- }
45
-
46
45
  const hasBonded = bondState.preState === 'BOND_BONDING' && bondState.state === 'BOND_BONDED';
47
46
  const hasCanceled = bondState.preState === 'BOND_BONDING' && bondState.state === 'BOND_NONE';
48
47
  Logger.debug('onDeviceBondState bondState:', bondState);
49
48
  if (hasBonded) {
50
- cleanup(cleanupListener);
49
+ cleanup();
51
50
  resolve(peripheral);
52
51
  } else if (hasCanceled) {
53
- cleanup(cleanupListener);
52
+ cleanup();
54
53
  reject(ERRORS.TypedError(HardwareErrorCode.BleDeviceBondedCanceled, 'bonding canceled'));
55
54
  }
56
55
  });
@@ -14,7 +14,7 @@ export default class BleTransport {
14
14
 
15
15
  device: Device;
16
16
 
17
- mtuSize = 20;
17
+ mtuSize = 23;
18
18
 
19
19
  writeCharacteristic: Characteristic;
20
20
 
@@ -41,7 +41,6 @@ export default class BleTransport {
41
41
  this.device = device;
42
42
  this.writeCharacteristic = writeCharacteristic;
43
43
  this.notifyCharacteristic = notifyCharacteristic;
44
- console.log(`BleTransport(${String(this.id)}) new instance`);
45
44
  }
46
45
 
47
46
  /**
@@ -0,0 +1,47 @@
1
+ import {
2
+ hasWritableCapability,
3
+ resolveBleWriteMode,
4
+ resolveProtocolV2PacketCapacity,
5
+ } from '../bleStrategy';
6
+
7
+ describe('React Native BLE strategy', () => {
8
+ test('accepts writeWithoutResponse-only characteristics', () => {
9
+ const characteristic = {
10
+ isWritableWithResponse: false,
11
+ isWritableWithoutResponse: true,
12
+ };
13
+
14
+ expect(hasWritableCapability(characteristic)).toBe(true);
15
+ expect(resolveBleWriteMode(characteristic)).toBe('withoutResponse');
16
+ });
17
+
18
+ test('falls back to Android default ATT payload when MTU is unavailable', () => {
19
+ expect(
20
+ resolveProtocolV2PacketCapacity({
21
+ platform: 'android',
22
+ androidPacketLength: 192,
23
+ mtu: null,
24
+ })
25
+ ).toBe(20);
26
+ });
27
+
28
+ test('caps Android packet length by negotiated MTU payload', () => {
29
+ expect(
30
+ resolveProtocolV2PacketCapacity({
31
+ platform: 'android',
32
+ androidPacketLength: 192,
33
+ mtu: 100,
34
+ })
35
+ ).toBe(97);
36
+ });
37
+
38
+ test('keeps iOS packet length controlled by tuning profile', () => {
39
+ expect(
40
+ resolveProtocolV2PacketCapacity({
41
+ platform: 'ios',
42
+ iosPacketLength: 244,
43
+ mtu: 256,
44
+ })
45
+ ).toBe(244);
46
+ });
47
+ });
@@ -0,0 +1,62 @@
1
+ import { ANDROID_DEFAULT_MTU, ANDROID_PACKET_LENGTH, IOS_PACKET_LENGTH } from './constants';
2
+
3
+ export type BlePlatform = 'ios' | 'android' | string;
4
+
5
+ export type BleWriteCapability = {
6
+ isWritableWithResponse?: boolean | null;
7
+ isWritableWithoutResponse?: boolean | null;
8
+ };
9
+
10
+ export type BleWriteMode = 'withResponse' | 'withoutResponse';
11
+
12
+ export function hasWritableCapability(characteristic: BleWriteCapability) {
13
+ return !!(
14
+ characteristic.isWritableWithResponse || characteristic.isWritableWithoutResponse
15
+ );
16
+ }
17
+
18
+ export function resolveBleWriteMode(
19
+ characteristic: BleWriteCapability,
20
+ preferredMode: BleWriteMode = 'withoutResponse'
21
+ ): BleWriteMode {
22
+ if (preferredMode === 'withoutResponse' && characteristic.isWritableWithoutResponse) {
23
+ return 'withoutResponse';
24
+ }
25
+
26
+ if (preferredMode === 'withResponse' && characteristic.isWritableWithResponse) {
27
+ return 'withResponse';
28
+ }
29
+
30
+ if (characteristic.isWritableWithoutResponse) {
31
+ return 'withoutResponse';
32
+ }
33
+
34
+ if (characteristic.isWritableWithResponse) {
35
+ return 'withResponse';
36
+ }
37
+
38
+ return preferredMode;
39
+ }
40
+
41
+ export function resolveProtocolV2PacketCapacity({
42
+ platform,
43
+ iosPacketLength = IOS_PACKET_LENGTH,
44
+ androidPacketLength = ANDROID_PACKET_LENGTH,
45
+ mtu,
46
+ }: {
47
+ platform: BlePlatform;
48
+ iosPacketLength?: number;
49
+ androidPacketLength?: number;
50
+ mtu?: number | null;
51
+ }) {
52
+ if (platform === 'ios') {
53
+ return iosPacketLength;
54
+ }
55
+
56
+ if (platform === 'android') {
57
+ const payloadLength = Math.max((mtu ?? ANDROID_DEFAULT_MTU) - 3, 1);
58
+ return Math.min(androidPacketLength, payloadLength);
59
+ }
60
+
61
+ return androidPacketLength;
62
+ }
package/src/constants.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export const IOS_PACKET_LENGTH = 128;
2
2
  export const ANDROID_PACKET_LENGTH = 192;
3
+ export const ANDROID_DEFAULT_MTU = 23;
3
4
 
4
5
  type BluetoothServices = Record<
5
6
  string,
package/src/index.ts CHANGED
@@ -22,6 +22,11 @@ import transport, {
22
22
  import { ERRORS, HardwareErrorCode, createDeferred, isOnekeyDevice } from '@onekeyfe/hd-shared';
23
23
 
24
24
  import { getConnectedDeviceIds, onDeviceBondState, pairDevice } from './BleManager';
25
+ import {
26
+ hasWritableCapability,
27
+ resolveBleWriteMode,
28
+ resolveProtocolV2PacketCapacity,
29
+ } from './bleStrategy';
25
30
  import { subscribeBleOn } from './subscribeBleOn';
26
31
  import {
27
32
  ANDROID_PACKET_LENGTH,
@@ -48,9 +53,10 @@ const Log = bleLogger;
48
53
  const transportCache: Record<string, BleTransport> = {};
49
54
  const BLE_RESPONSE_TIMEOUT_MS = 30_000;
50
55
  const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
51
- const PROTOCOL_V2_PROBE_TIMEOUT_MS = 5000;
56
+ const PROTOCOL_V2_PROBE_TIMEOUT_MS = 10_000;
52
57
  const DEVICE_SCAN_TIMEOUT_MS = 8000;
53
58
  const IOS_NOTIFY_READY_DELAY_MS = 150;
59
+ const ANDROID_NOTIFY_READY_DELAY_MS = 300;
54
60
  const HIGH_VOLUME_WRITE_BURST_SIZE = Platform.OS === 'ios' ? 4 : 6;
55
61
  const HIGH_VOLUME_WRITE_PAUSE_MS = Platform.OS === 'ios' ? 6 : 2;
56
62
  const HIGH_VOLUME_WRITE_FLUSH_DELAY_MS = Platform.OS === 'ios' ? 20 : 8;
@@ -143,7 +149,7 @@ function hasKnownOneKeyService(device?: Device | null) {
143
149
  );
144
150
  }
145
151
 
146
- let connectOptions: Record<string, unknown> = {
152
+ const connectOptions: Record<string, unknown> = {
147
153
  requestMTU: 256,
148
154
  timeout: 3000,
149
155
  refreshGatt: 'OnConnected',
@@ -430,11 +436,12 @@ export default class ReactNativeBleTransport {
430
436
  throw error;
431
437
  }
432
438
 
433
- // check device is bonded
434
439
  if (Platform.OS === 'android') {
435
440
  const bondState = await pairDevice(uuid);
436
441
  if (bondState.bonding) {
437
442
  await onDeviceBondState(uuid);
443
+ } else if (!bondState.bonded) {
444
+ throw ERRORS.TypedError(HardwareErrorCode.BleDeviceNotBonded, 'device is not bonded');
438
445
  }
439
446
  }
440
447
 
@@ -460,7 +467,6 @@ export default class ReactNativeBleTransport {
460
467
  e.errorCode === BleErrorCode.DeviceMTUChangeFailed ||
461
468
  e.errorCode === BleErrorCode.OperationCancelled
462
469
  ) {
463
- connectOptions = {};
464
470
  Log?.debug('first try to reconnect without params');
465
471
  device = await blePlxManager.connectToDevice(uuid);
466
472
  } else if (e.errorCode === BleErrorCode.DeviceAlreadyConnected) {
@@ -487,7 +493,6 @@ export default class ReactNativeBleTransport {
487
493
  e.errorCode === BleErrorCode.DeviceMTUChangeFailed ||
488
494
  e.errorCode === BleErrorCode.OperationCancelled
489
495
  ) {
490
- connectOptions = {};
491
496
  Log?.debug('second try to reconnect without params');
492
497
  try {
493
498
  device = await device.connect();
@@ -590,7 +595,7 @@ export default class ReactNativeBleTransport {
590
595
  throw ERRORS.TypedError('BLECharacteristicNotFound: notify characteristic not found');
591
596
  }
592
597
 
593
- if (!writeCharacteristic.isWritableWithResponse) {
598
+ if (!hasWritableCapability(writeCharacteristic)) {
594
599
  throw ERRORS.TypedError('BLECharacteristicNotWritable: write characteristic not writable');
595
600
  }
596
601
 
@@ -612,6 +617,9 @@ export default class ReactNativeBleTransport {
612
617
  }
613
618
 
614
619
  const transport = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
620
+ if (Platform.OS === 'android') {
621
+ transport.mtuSize = typeof device.mtu === 'number' ? device.mtu : transport.mtuSize;
622
+ }
615
623
  const monitorToken = this.nextMonitorToken;
616
624
  this.nextMonitorToken += 1;
617
625
  const notifyTransactionId = `${uuid}:notify:${monitorToken}`;
@@ -632,6 +640,8 @@ export default class ReactNativeBleTransport {
632
640
  await new Promise<void>(resolve => {
633
641
  setTimeout(resolve, IOS_NOTIFY_READY_DELAY_MS);
634
642
  });
643
+ } else if (Platform.OS === 'android') {
644
+ await delay(ANDROID_NOTIFY_READY_DELAY_MS);
635
645
  }
636
646
 
637
647
  const protocolType = await this.detectProtocol(uuid, expectedProtocol, protocolHint);
@@ -1164,10 +1174,13 @@ export default class ReactNativeBleTransport {
1164
1174
  throw this.createProtocolMismatchError(expectedProtocol);
1165
1175
  }
1166
1176
 
1167
- if (protocolHint === 'V2' && (await this.probeProtocolV2(uuid))) {
1168
- this.deviceProtocol.set(uuid, 'V2');
1169
- Log?.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V2 (hint)`);
1170
- return 'V2';
1177
+ if (protocolHint === 'V2') {
1178
+ if (await this.probeProtocolV2(uuid)) {
1179
+ this.deviceProtocol.set(uuid, 'V2');
1180
+ Log?.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V2 (hint)`);
1181
+ return 'V2';
1182
+ }
1183
+ throw this.createProtocolMismatchError('V2');
1171
1184
  }
1172
1185
 
1173
1186
  if (this.deviceProtocol.get(uuid) === 'V2' && (await this.probeProtocolV2(uuid))) {
@@ -1370,18 +1383,26 @@ export default class ReactNativeBleTransport {
1370
1383
  options?: { highVolume?: boolean; writeWithResponse?: boolean }
1371
1384
  ) {
1372
1385
  const tuning = getProtocolV2BleTuning();
1373
- const packetCapacity =
1374
- Platform.OS === 'ios' ? tuning.iosPacketLength : tuning.androidPacketLength;
1386
+ const packetCapacity = resolveProtocolV2PacketCapacity({
1387
+ platform: Platform.OS,
1388
+ iosPacketLength: tuning.iosPacketLength,
1389
+ androidPacketLength: tuning.androidPacketLength,
1390
+ mtu: Platform.OS === 'android' ? transport.mtuSize : undefined,
1391
+ });
1375
1392
  const writeWithResponse =
1376
1393
  !!options?.writeWithResponse || (!!options?.highVolume && tuning.highVolumeWriteWithResponse);
1377
- const shouldThrottle = !!options?.highVolume && !writeWithResponse;
1394
+ const writeMode = resolveBleWriteMode(
1395
+ transport.writeCharacteristic,
1396
+ writeWithResponse ? 'withResponse' : 'withoutResponse'
1397
+ );
1398
+ const shouldThrottle = !!options?.highVolume && writeMode === 'withoutResponse';
1378
1399
  let packetsWritten = 0;
1379
1400
 
1380
1401
  try {
1381
1402
  for (let offset = 0; offset < frame.length; offset += packetCapacity) {
1382
1403
  const chunk = frame.slice(offset, offset + packetCapacity);
1383
1404
  const base64 = Buffer.from(chunk).toString('base64');
1384
- if (writeWithResponse) {
1405
+ if (writeMode === 'withResponse') {
1385
1406
  await transport.writeCharacteristic.writeWithResponse(base64);
1386
1407
  } else {
1387
1408
  await transport.writeCharacteristic.writeWithoutResponse(base64);
@@ -1476,8 +1497,11 @@ export default class ReactNativeBleTransport {
1476
1497
  protocolV2: this._messagesV2,
1477
1498
  },
1478
1499
  router: PROTOCOL_V2_CHANNEL_BLE_UART,
1479
- writeFrame: (frame: Uint8Array) =>
1480
- this.writeProtocolV2Frame(transport, frame, { highVolume: highVolumeWrite }),
1500
+ writeFrame: async (frame: Uint8Array) => {
1501
+ await this.writeProtocolV2Frame(transport, frame, {
1502
+ highVolume: highVolumeWrite,
1503
+ });
1504
+ },
1481
1505
  readFrame: async () => {
1482
1506
  const rxFrame = await this.readProtocolV2Frame(uuid);
1483
1507
  if (!(rxFrame instanceof Uint8Array)) {