@microbit/microbit-connection 0.1.0 → 0.9.0-apps.alpha.1
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/README.md +4 -4
- package/build/cjs/accelerometer-service.d.ts +5 -5
- package/build/cjs/accelerometer-service.js +41 -42
- package/build/cjs/accelerometer-service.js.map +1 -1
- package/build/cjs/async-util.d.ts +9 -0
- package/build/cjs/async-util.js +27 -7
- package/build/cjs/async-util.js.map +1 -1
- package/build/cjs/bluetooth-device-wrapper.d.ts +61 -27
- package/build/cjs/bluetooth-device-wrapper.js +285 -266
- package/build/cjs/bluetooth-device-wrapper.js.map +1 -1
- package/build/cjs/bluetooth-profile.d.ts +43 -35
- package/build/cjs/bluetooth-profile.js +35 -29
- package/build/cjs/bluetooth-profile.js.map +1 -1
- package/build/cjs/bluetooth.d.ts +10 -6
- package/build/cjs/bluetooth.js +286 -100
- package/build/cjs/bluetooth.js.map +1 -1
- package/build/cjs/button-service.d.ts +5 -5
- package/build/cjs/button-service.js +31 -45
- package/build/cjs/button-service.js.map +1 -1
- package/build/cjs/device-information-service.d.ts +6 -0
- package/build/cjs/device-information-service.js +34 -0
- package/build/cjs/device-information-service.js.map +1 -0
- package/build/cjs/device.d.ts +65 -8
- package/build/cjs/device.js +16 -2
- package/build/cjs/device.js.map +1 -1
- package/build/cjs/dfu-service.d.ts +9 -0
- package/build/cjs/dfu-service.js +26 -0
- package/build/cjs/dfu-service.js.map +1 -0
- package/build/cjs/flashing/flashing-full.d.ts +14 -0
- package/build/cjs/flashing/flashing-full.js +87 -0
- package/build/cjs/flashing/flashing-full.js.map +1 -0
- package/build/cjs/flashing/flashing-makecode.d.ts +6 -0
- package/build/cjs/flashing/flashing-makecode.js +48 -0
- package/build/cjs/flashing/flashing-makecode.js.map +1 -0
- package/build/cjs/flashing/flashing-partial.d.ts +9 -0
- package/build/cjs/flashing/flashing-partial.js +98 -0
- package/build/cjs/flashing/flashing-partial.js.map +1 -0
- package/build/cjs/flashing/flashing-v1.d.ts +11 -0
- package/build/cjs/flashing/flashing-v1.js +24 -0
- package/build/cjs/flashing/flashing-v1.js.map +1 -0
- package/build/cjs/flashing/nordic-dfu.d.ts +3 -0
- package/build/cjs/flashing/nordic-dfu.js +214 -0
- package/build/cjs/flashing/nordic-dfu.js.map +1 -0
- package/build/cjs/flashing/zip.d.ts +12 -0
- package/build/cjs/flashing/zip.js +177 -0
- package/build/cjs/flashing/zip.js.map +1 -0
- package/build/cjs/index.d.ts +3 -3
- package/build/cjs/index.js +2 -1
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/led-service.d.ts +5 -7
- package/build/cjs/led-service.js +13 -44
- package/build/cjs/led-service.js.map +1 -1
- package/build/cjs/logging.d.ts +1 -1
- package/build/cjs/logging.js +3 -3
- package/build/cjs/logging.js.map +1 -1
- package/build/cjs/magnetometer-service.d.ts +5 -9
- package/build/cjs/magnetometer-service.js +30 -65
- package/build/cjs/magnetometer-service.js.map +1 -1
- package/build/cjs/partial-flashing-service.d.ts +45 -0
- package/build/cjs/partial-flashing-service.js +110 -0
- package/build/cjs/partial-flashing-service.js.map +1 -0
- package/build/cjs/uart-service.d.ts +4 -5
- package/build/cjs/uart-service.js +19 -40
- package/build/cjs/uart-service.js.map +1 -1
- package/build/cjs/usb-device-wrapper.js +33 -8
- package/build/cjs/usb-device-wrapper.js.map +1 -1
- package/build/cjs/usb-partial-flashing.d.ts +1 -3
- package/build/cjs/usb-partial-flashing.js +4 -3
- package/build/cjs/usb-partial-flashing.js.map +1 -1
- package/build/cjs/usb-radio-bridge.js +1 -2
- package/build/cjs/usb-radio-bridge.js.map +1 -1
- package/build/cjs/usb.d.ts +4 -2
- package/build/cjs/usb.js +31 -16
- package/build/cjs/usb.js.map +1 -1
- package/build/esm/accelerometer-service.d.ts +5 -5
- package/build/esm/accelerometer-service.js +42 -43
- package/build/esm/accelerometer-service.js.map +1 -1
- package/build/esm/async-util.d.ts +9 -0
- package/build/esm/async-util.js +22 -6
- package/build/esm/async-util.js.map +1 -1
- package/build/esm/bluetooth-device-wrapper.d.ts +61 -27
- package/build/esm/bluetooth-device-wrapper.js +284 -265
- package/build/esm/bluetooth-device-wrapper.js.map +1 -1
- package/build/esm/bluetooth-profile.d.ts +43 -35
- package/build/esm/bluetooth-profile.js +35 -29
- package/build/esm/bluetooth-profile.js.map +1 -1
- package/build/esm/bluetooth.d.ts +10 -6
- package/build/esm/bluetooth.js +263 -103
- package/build/esm/bluetooth.js.map +1 -1
- package/build/esm/button-service.d.ts +5 -5
- package/build/esm/button-service.js +32 -46
- package/build/esm/button-service.js.map +1 -1
- package/build/esm/device-information-service.d.ts +6 -0
- package/build/esm/device-information-service.js +30 -0
- package/build/esm/device-information-service.js.map +1 -0
- package/build/esm/device.d.ts +65 -8
- package/build/esm/device.js +15 -1
- package/build/esm/device.js.map +1 -1
- package/build/esm/dfu-service.d.ts +9 -0
- package/build/esm/dfu-service.js +22 -0
- package/build/esm/dfu-service.js.map +1 -0
- package/build/esm/flashing/flashing-full.d.ts +14 -0
- package/build/esm/flashing/flashing-full.js +84 -0
- package/build/esm/flashing/flashing-full.js.map +1 -0
- package/build/esm/flashing/flashing-makecode.d.ts +6 -0
- package/build/esm/flashing/flashing-makecode.js +44 -0
- package/build/esm/flashing/flashing-makecode.js.map +1 -0
- package/build/esm/flashing/flashing-partial.d.ts +9 -0
- package/build/esm/flashing/flashing-partial.js +95 -0
- package/build/esm/flashing/flashing-partial.js.map +1 -0
- package/build/esm/flashing/flashing-v1.d.ts +11 -0
- package/build/esm/flashing/flashing-v1.js +20 -0
- package/build/esm/flashing/flashing-v1.js.map +1 -0
- package/build/esm/flashing/nordic-dfu.d.ts +3 -0
- package/build/esm/flashing/nordic-dfu.js +211 -0
- package/build/esm/flashing/nordic-dfu.js.map +1 -0
- package/build/esm/flashing/zip.d.ts +12 -0
- package/build/esm/flashing/zip.js +174 -0
- package/build/esm/flashing/zip.js.map +1 -0
- package/build/esm/index.d.ts +3 -3
- package/build/esm/index.js +2 -2
- package/build/esm/index.js.map +1 -1
- package/build/esm/led-service.d.ts +5 -7
- package/build/esm/led-service.js +13 -44
- package/build/esm/led-service.js.map +1 -1
- package/build/esm/logging.d.ts +1 -1
- package/build/esm/logging.js +1 -1
- package/build/esm/logging.js.map +1 -1
- package/build/esm/magnetometer-service.d.ts +5 -9
- package/build/esm/magnetometer-service.js +31 -66
- package/build/esm/magnetometer-service.js.map +1 -1
- package/build/esm/partial-flashing-service.d.ts +45 -0
- package/build/esm/partial-flashing-service.js +106 -0
- package/build/esm/partial-flashing-service.js.map +1 -0
- package/build/esm/uart-service.d.ts +4 -5
- package/build/esm/uart-service.js +19 -40
- package/build/esm/uart-service.js.map +1 -1
- package/build/esm/usb-device-wrapper.js +33 -8
- package/build/esm/usb-device-wrapper.js.map +1 -1
- package/build/esm/usb-partial-flashing.d.ts +1 -3
- package/build/esm/usb-partial-flashing.js +4 -3
- package/build/esm/usb-partial-flashing.js.map +1 -1
- package/build/esm/usb-radio-bridge.js +2 -3
- package/build/esm/usb-radio-bridge.js.map +1 -1
- package/build/esm/usb.d.ts +4 -2
- package/build/esm/usb.js +33 -18
- package/build/esm/usb.js.map +1 -1
- package/package.json +7 -3
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BleClient } from "@capacitor-community/bluetooth-le";
|
|
2
|
+
import { profile } from "./bluetooth-profile.js";
|
|
3
|
+
export class DeviceInformationService {
|
|
4
|
+
constructor(deviceId) {
|
|
5
|
+
Object.defineProperty(this, "deviceId", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
writable: true,
|
|
9
|
+
value: deviceId
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
async getBoardVersion() {
|
|
13
|
+
const serviceMeta = profile.deviceInformation;
|
|
14
|
+
try {
|
|
15
|
+
const modelNumberBytes = await BleClient.read(this.deviceId, serviceMeta.id, serviceMeta.characteristics.modelNumber.id);
|
|
16
|
+
const modelNumber = new TextDecoder().decode(modelNumberBytes);
|
|
17
|
+
if (modelNumber.toLowerCase() === "BBC micro:bit".toLowerCase()) {
|
|
18
|
+
return "V1";
|
|
19
|
+
}
|
|
20
|
+
if (modelNumber.toLowerCase().includes("BBC micro:bit v2".toLowerCase())) {
|
|
21
|
+
return "V2";
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`Unexpected model number ${modelNumber}`);
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
throw new Error(`Could not read model number: ${e instanceof Error ? e.message : e}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=device-information-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-information-service.js","sourceRoot":"","sources":["../../lib/device-information-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEjD,MAAM,OAAO,wBAAwB;IACnC,YAAoB,QAAgB;QAAxB;;;;mBAAQ,QAAQ;WAAQ;IAAG,CAAC;IAExC,KAAK,CAAC,eAAe;QACnB,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC;QAC9C,IAAI,CAAC;YACH,MAAM,gBAAgB,GAAG,MAAM,SAAS,CAAC,IAAI,CAC3C,IAAI,CAAC,QAAQ,EACb,WAAW,CAAC,EAAE,EACd,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE,CAC3C,CAAC;YACF,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAC/D,IAAI,WAAW,CAAC,WAAW,EAAE,KAAK,eAAe,CAAC,WAAW,EAAE,EAAE,CAAC;gBAChE,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IACE,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC,EACpE,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,2BAA2B,WAAW,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CACb,gCAAgC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CACrE,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
package/build/esm/device.d.ts
CHANGED
|
@@ -41,7 +41,56 @@ export type DeviceErrorCode =
|
|
|
41
41
|
/**
|
|
42
42
|
* Bluetooth service is missing on device.
|
|
43
43
|
*/
|
|
44
|
-
| "service-missing"
|
|
44
|
+
| "service-missing"
|
|
45
|
+
/**
|
|
46
|
+
* Failed to establish Bluetooth connection.
|
|
47
|
+
*/
|
|
48
|
+
| "bluetooth-connection-failed"
|
|
49
|
+
/**
|
|
50
|
+
* Bluetooth is disabled on the device.
|
|
51
|
+
*/
|
|
52
|
+
| "bluetooth-disabled"
|
|
53
|
+
/**
|
|
54
|
+
* Missing required Bluetooth permissions.
|
|
55
|
+
*/
|
|
56
|
+
| "bluetooth-missing-permissions"
|
|
57
|
+
/**
|
|
58
|
+
* Partial flash operation failed.
|
|
59
|
+
*/
|
|
60
|
+
| "flash-partial-failed"
|
|
61
|
+
/**
|
|
62
|
+
* Full flash operation failed.
|
|
63
|
+
*/
|
|
64
|
+
| "flash-full-failed"
|
|
65
|
+
/**
|
|
66
|
+
* Flash operation was cancelled.
|
|
67
|
+
*/
|
|
68
|
+
| "flash-cancelled";
|
|
69
|
+
export declare enum ProgressStage {
|
|
70
|
+
Initializing = "Initializing",
|
|
71
|
+
FindingDevice = "FindingDevice",
|
|
72
|
+
Connecting = "Connecting",
|
|
73
|
+
PartialFlashing = "PartialFlashing",
|
|
74
|
+
FullFlashing = "FullFlashing"
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Progress callback for tracking operation stages (connection and flashing).
|
|
78
|
+
*
|
|
79
|
+
* @param stage - The current stage of the operation
|
|
80
|
+
* @param progress - Optional progress value (0-1) for PartialFlashing and FullFlashing stages.
|
|
81
|
+
* Initializing, FindingDevice, and Connecting stages are called once
|
|
82
|
+
* without progress values to indicate stage entry.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* const progressCallback = (stage, progress) => {
|
|
86
|
+
* if (progress !== undefined) {
|
|
87
|
+
* console.log(`${stage}: ${Math.round(progress * 100)}%`);
|
|
88
|
+
* } else {
|
|
89
|
+
* console.log(`Stage: ${stage}`);
|
|
90
|
+
* }
|
|
91
|
+
* };
|
|
92
|
+
*/
|
|
93
|
+
export type ProgressCallback = (stage: ProgressStage, progress?: number) => void;
|
|
45
94
|
/**
|
|
46
95
|
* Error type used for all interactions with this module.
|
|
47
96
|
*
|
|
@@ -96,19 +145,26 @@ export declare enum ConnectionStatus {
|
|
|
96
145
|
*/
|
|
97
146
|
RECONNECTING = "RECONNECTING"
|
|
98
147
|
}
|
|
148
|
+
export interface ConnectOptions {
|
|
149
|
+
/**
|
|
150
|
+
* Optional progress callback for tracking connection stages.
|
|
151
|
+
*/
|
|
152
|
+
progress?: ProgressCallback;
|
|
153
|
+
}
|
|
99
154
|
export interface FlashOptions {
|
|
100
155
|
/**
|
|
101
156
|
* True to use a partial flash where possible, false to force a full flash.
|
|
157
|
+
* Default: true.
|
|
102
158
|
*/
|
|
103
|
-
partial
|
|
159
|
+
partial?: boolean;
|
|
104
160
|
/**
|
|
105
|
-
*
|
|
161
|
+
* Optional progress callback for tracking connection and flash stages.
|
|
106
162
|
*
|
|
107
163
|
* Requesting a partial flash doesn't guarantee one is performed. Partial flashes are avoided
|
|
108
164
|
* if too many blocks have changed and failed partial flashes are retried as full flashes.
|
|
109
165
|
* The partial parameter reports the flash type currently in progress.
|
|
110
166
|
*/
|
|
111
|
-
progress
|
|
167
|
+
progress?: ProgressCallback;
|
|
112
168
|
/**
|
|
113
169
|
* Smallest possible progress increment to limit callback rate.
|
|
114
170
|
*/
|
|
@@ -130,7 +186,8 @@ export declare class AfterRequestDevice extends Event {
|
|
|
130
186
|
}
|
|
131
187
|
export declare class BackgroundErrorEvent extends Event {
|
|
132
188
|
readonly errorMessage: string;
|
|
133
|
-
|
|
189
|
+
readonly error?: unknown | undefined;
|
|
190
|
+
constructor(errorMessage: string, error?: unknown | undefined);
|
|
134
191
|
}
|
|
135
192
|
export declare class DeviceConnectionEventMap {
|
|
136
193
|
"status": ConnectionStatusEvent;
|
|
@@ -150,11 +207,11 @@ export interface DeviceConnection<M extends ValueIsEvent<M>> extends TypedEventT
|
|
|
150
207
|
dispose(): void;
|
|
151
208
|
/**
|
|
152
209
|
* Connects to a currently paired device or requests pairing.
|
|
153
|
-
* Throws on error.
|
|
154
210
|
*
|
|
155
|
-
* @
|
|
211
|
+
* @param options Optional connection options including progress callback.
|
|
212
|
+
* @throws {DeviceError} On connection failure. The error.code property indicates the failure type.
|
|
156
213
|
*/
|
|
157
|
-
connect(): Promise<
|
|
214
|
+
connect(options?: ConnectOptions): Promise<void>;
|
|
158
215
|
/**
|
|
159
216
|
* Get the board version.
|
|
160
217
|
*
|
package/build/esm/device.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export var ProgressStage;
|
|
2
|
+
(function (ProgressStage) {
|
|
3
|
+
ProgressStage["Initializing"] = "Initializing";
|
|
4
|
+
ProgressStage["FindingDevice"] = "FindingDevice";
|
|
5
|
+
ProgressStage["Connecting"] = "Connecting";
|
|
6
|
+
ProgressStage["PartialFlashing"] = "PartialFlashing";
|
|
7
|
+
ProgressStage["FullFlashing"] = "FullFlashing";
|
|
8
|
+
})(ProgressStage || (ProgressStage = {}));
|
|
1
9
|
/**
|
|
2
10
|
* Error type used for all interactions with this module.
|
|
3
11
|
*
|
|
@@ -82,7 +90,7 @@ export class AfterRequestDevice extends Event {
|
|
|
82
90
|
}
|
|
83
91
|
}
|
|
84
92
|
export class BackgroundErrorEvent extends Event {
|
|
85
|
-
constructor(errorMessage) {
|
|
93
|
+
constructor(errorMessage, error) {
|
|
86
94
|
super("backgrounderror");
|
|
87
95
|
Object.defineProperty(this, "errorMessage", {
|
|
88
96
|
enumerable: true,
|
|
@@ -90,6 +98,12 @@ export class BackgroundErrorEvent extends Event {
|
|
|
90
98
|
writable: true,
|
|
91
99
|
value: errorMessage
|
|
92
100
|
});
|
|
101
|
+
Object.defineProperty(this, "error", {
|
|
102
|
+
enumerable: true,
|
|
103
|
+
configurable: true,
|
|
104
|
+
writable: true,
|
|
105
|
+
value: error
|
|
106
|
+
});
|
|
93
107
|
}
|
|
94
108
|
}
|
|
95
109
|
export class DeviceConnectionEventMap {
|
package/build/esm/device.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device.js","sourceRoot":"","sources":["../../lib/device.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"device.js","sourceRoot":"","sources":["../../lib/device.ts"],"names":[],"mappings":"AAsEA,MAAM,CAAN,IAAY,aAMX;AAND,WAAY,aAAa;IACvB,8CAA6B,CAAA;IAC7B,gDAA+B,CAAA;IAC/B,0CAAyB,CAAA;IACzB,oDAAmC,CAAA;IACnC,8CAA6B,CAAA;AAC/B,CAAC,EANW,aAAa,KAAb,aAAa,QAMxB;AAwBD;;;;;;;;GAQG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAEpC,YAAY,EAAE,IAAI,EAAE,OAAO,EAA+C;QACxE,KAAK,CAAC,OAAO,CAAC,CAAC;QAFjB;;;;;WAAsB;QAGpB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,CAAN,IAAY,gBAkCX;AAlCD,WAAY,gBAAgB;IAC1B;;;OAGG;IACH,2DAAuC,CAAA;IACvC;;OAEG;IACH,mDAA+B,CAAA;IAC/B;;;;;OAKG;IACH,iEAA6C,CAAA;IAC7C;;OAEG;IACH,iDAA6B,CAAA;IAC7B;;OAEG;IACH,2CAAuB,CAAA;IACvB;;OAEG;IACH,6CAAyB,CAAA;IACzB;;;OAGG;IACH,iDAA6B,CAAA;AAC/B,CAAC,EAlCW,gBAAgB,KAAhB,gBAAgB,QAkC3B;AA6BD,MAAM,OAAO,cAAe,SAAQ,KAAK;CAAG;AAQ5C,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAA4B,MAAwB;QAClD,KAAK,CAAC,QAAQ,CAAC,CAAC;QADN;;;;mBAAgB,MAAM;WAAkB;IAEpD,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C;QACE,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C;QACE,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YACkB,YAAoB,EACpB,KAAe;QAE/B,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAHzB;;;;mBAAgB,YAAY;WAAQ;QACpC;;;;mBAAgB,KAAK;WAAU;IAGjC,CAAC;CACF;AAED,MAAM,OAAO,wBAAwB;IAArC;QACE,4BAAA,QAAQ;;;;;WAAwB;QAChC,4BAAA,iBAAiB;;;;;WAAuB;QACxC,4BAAA,qBAAqB;;;;;WAAQ;QAC7B,4BAAA,oBAAoB;;;;;WAAQ;IAC9B,CAAC;CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BleClient, numbersToDataView, } from "@capacitor-community/bluetooth-le";
|
|
2
|
+
import { profile } from "./bluetooth-profile.js";
|
|
3
|
+
// This is the service that should be available on V1 after the reboot.
|
|
4
|
+
// We don't use it directly (the Nordic DFU library does) but we check it's there.
|
|
5
|
+
export const NORDIC_DFU_SERVICE = "00001530-1212-EFDE-1523-785FEABCD123";
|
|
6
|
+
export class DfuService {
|
|
7
|
+
constructor(deviceId) {
|
|
8
|
+
Object.defineProperty(this, "deviceId", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
configurable: true,
|
|
11
|
+
writable: true,
|
|
12
|
+
value: deviceId
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* We do this for V1 only.
|
|
17
|
+
*/
|
|
18
|
+
async requestRebootToBootloader() {
|
|
19
|
+
await BleClient.write(this.deviceId, profile.dfuControl.id, profile.dfuControl.characteristics.control.id, numbersToDataView([0x01]));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=dfu-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dfu-service.js","sourceRoot":"","sources":["../../lib/dfu-service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,iBAAiB,GAClB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEjD,uEAAuE;AACvE,kFAAkF;AAClF,MAAM,CAAC,MAAM,kBAAkB,GAAG,sCAAsC,CAAC;AAEzE,MAAM,OAAO,UAAU;IACrB,YAAoB,QAAgB;QAAxB;;;;mBAAQ,QAAQ;WAAQ;IAAG,CAAC;IAExC;;OAEG;IACH,KAAK,CAAC,yBAAyB;QAC7B,MAAM,SAAS,CAAC,KAAK,CACnB,IAAI,CAAC,QAAQ,EACb,OAAO,CAAC,UAAU,CAAC,EAAE,EACrB,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,EAC7C,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,CAC1B,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import MemoryMap from "nrf-intel-hex";
|
|
2
|
+
import { BoardVersion, ProgressCallback } from "../device.js";
|
|
3
|
+
import { BluetoothDeviceWrapper } from "../bluetooth-device-wrapper.js";
|
|
4
|
+
/**
|
|
5
|
+
* Perform a full flash via Nordic's DFU service.
|
|
6
|
+
*
|
|
7
|
+
* The connection is closed before handing off to Nordic's service which will
|
|
8
|
+
* connect again.
|
|
9
|
+
*
|
|
10
|
+
* The device is assumed to be bonded.
|
|
11
|
+
*
|
|
12
|
+
* @throws {DeviceError} On flash failure.
|
|
13
|
+
*/
|
|
14
|
+
export declare function fullFlash(connection: BluetoothDeviceWrapper, boardVersion: BoardVersion, memoryMap: MemoryMap, progress: ProgressCallback): Promise<void>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { DeviceError, FlashDataError, ProgressStage, } from "../device.js";
|
|
2
|
+
import { DfuService, NORDIC_DFU_SERVICE } from "../dfu-service.js";
|
|
3
|
+
import { refreshServicesForV1IfDesiredServiceMissing } from "./flashing-v1.js";
|
|
4
|
+
import { flashDfu } from "./nordic-dfu.js";
|
|
5
|
+
import { delay } from "../async-util.js";
|
|
6
|
+
/**
|
|
7
|
+
* Perform a full flash via Nordic's DFU service.
|
|
8
|
+
*
|
|
9
|
+
* The connection is closed before handing off to Nordic's service which will
|
|
10
|
+
* connect again.
|
|
11
|
+
*
|
|
12
|
+
* The device is assumed to be bonded.
|
|
13
|
+
*
|
|
14
|
+
* @throws {DeviceError} On flash failure.
|
|
15
|
+
*/
|
|
16
|
+
export async function fullFlash(connection, boardVersion, memoryMap, progress) {
|
|
17
|
+
connection.log("Full flash");
|
|
18
|
+
progress(ProgressStage.FullFlashing);
|
|
19
|
+
const { deviceId } = connection.device;
|
|
20
|
+
try {
|
|
21
|
+
if (boardVersion === "V1") {
|
|
22
|
+
connection.log("Rebooting V1 to bootloader");
|
|
23
|
+
const dfuService = new DfuService(deviceId);
|
|
24
|
+
try {
|
|
25
|
+
await dfuService.requestRebootToBootloader();
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
connection.error("Failed to request reboot to bootloader", e);
|
|
29
|
+
throw new DeviceError({
|
|
30
|
+
code: "flash-full-failed",
|
|
31
|
+
message: e instanceof Error ? e.message : "Failed to reboot to bootloader",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// Wait for device to automatically disconnect as it reboots into bootloader
|
|
35
|
+
connection.log("Waiting for device to reboot and disconnect");
|
|
36
|
+
try {
|
|
37
|
+
await connection.waitForDisconnect(3000);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
connection.log("Device did not disconnect automatically, disconnecting manually");
|
|
41
|
+
await connection.disconnect();
|
|
42
|
+
}
|
|
43
|
+
// Give device time to disconnect and reboot into bootloader mode
|
|
44
|
+
await delay(2500);
|
|
45
|
+
// Reconnect to device now in bootloader mode
|
|
46
|
+
progress(ProgressStage.Connecting);
|
|
47
|
+
await connection.connect();
|
|
48
|
+
await refreshServicesForV1IfDesiredServiceMissing(deviceId, NORDIC_DFU_SERVICE);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
// The Nordic code opens its own connection.
|
|
53
|
+
await connection.disconnect();
|
|
54
|
+
// If we've previously been connected, maybe this helps???
|
|
55
|
+
await delay(3000);
|
|
56
|
+
}
|
|
57
|
+
const appBin = createAppBin(memoryMap, boardVersion);
|
|
58
|
+
if (appBin === null) {
|
|
59
|
+
connection.log("Invalid hex (app bin case)");
|
|
60
|
+
throw new FlashDataError("Invalid hex data: could not extract app binary");
|
|
61
|
+
}
|
|
62
|
+
connection.log(`Extracted app bin: ${appBin.length} bytes`);
|
|
63
|
+
await flashDfu(connection, boardVersion, appBin, progress);
|
|
64
|
+
}
|
|
65
|
+
const createAppBin = (memoryMap, boardVersion) => {
|
|
66
|
+
const appRegionBoundaries = {
|
|
67
|
+
V1: { start: 0x18000, end: 0x3c000 },
|
|
68
|
+
V2: { start: 0x1c000, end: 0x77000 },
|
|
69
|
+
}[boardVersion];
|
|
70
|
+
// Calculate data size within the app region
|
|
71
|
+
let maxAddress = appRegionBoundaries.start;
|
|
72
|
+
for (const [blockAddr, block] of memoryMap) {
|
|
73
|
+
const blockEnd = blockAddr + block.length;
|
|
74
|
+
if (blockEnd > appRegionBoundaries.start &&
|
|
75
|
+
blockAddr < appRegionBoundaries.end) {
|
|
76
|
+
maxAddress = Math.max(maxAddress, Math.min(blockEnd, appRegionBoundaries.end));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
let size = maxAddress - appRegionBoundaries.start;
|
|
80
|
+
// 4-byte alignment required by DFU
|
|
81
|
+
size = Math.ceil(size / 4) * 4;
|
|
82
|
+
return memoryMap.slicePad(appRegionBoundaries.start, size);
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=flashing-full.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flashing-full.js","sourceRoot":"","sources":["../../../lib/flashing/flashing-full.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import MemoryMap from "nrf-intel-hex";
|
|
2
|
+
import { RegionInfo } from "../partial-flashing-service";
|
|
3
|
+
/**
|
|
4
|
+
* Find the MakeCode code region in a MemoryMap (typically from a hex file).
|
|
5
|
+
*/
|
|
6
|
+
export declare const findMakeCodeRegionInMemoryMap: (memoryMap: MemoryMap, deviceCodeRegion: RegionInfo) => RegionInfo | null;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const PXT_MAGIC_HEX = "708E3B92C615A841C49866C975EE5197";
|
|
2
|
+
/**
|
|
3
|
+
* Find the MakeCode code region in a MemoryMap (typically from a hex file).
|
|
4
|
+
*/
|
|
5
|
+
export const findMakeCodeRegionInMemoryMap = (memoryMap, deviceCodeRegion) => {
|
|
6
|
+
for (const [blockAddr, block] of memoryMap) {
|
|
7
|
+
const offset = findByteSequence(block, PXT_MAGIC_HEX);
|
|
8
|
+
if (offset >= 0) {
|
|
9
|
+
const start = blockAddr + offset;
|
|
10
|
+
const hashOffset = start + PXT_MAGIC_HEX.length / 2;
|
|
11
|
+
const hashBytes = memoryMap.slicePad(hashOffset, 8);
|
|
12
|
+
const hash = bytesToHex(hashBytes);
|
|
13
|
+
// Find the highest address with data in the memory map within the code region
|
|
14
|
+
let end = start;
|
|
15
|
+
for (const [blockAddr, block] of memoryMap) {
|
|
16
|
+
const blockEnd = blockAddr + block.length;
|
|
17
|
+
if (blockEnd > start && blockAddr < deviceCodeRegion.end) {
|
|
18
|
+
end = Math.max(end, Math.min(blockEnd, deviceCodeRegion.end));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Round up to next 64-byte boundary
|
|
22
|
+
end = Math.ceil(end / 64) * 64;
|
|
23
|
+
return { start, end, hash };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
};
|
|
28
|
+
const bytesToHex = (bytes) => {
|
|
29
|
+
return Array.from(bytes)
|
|
30
|
+
.map((byte) => byte.toString(16).padStart(2, "0").toUpperCase())
|
|
31
|
+
.join("");
|
|
32
|
+
};
|
|
33
|
+
function findByteSequence(data, hexTarget) {
|
|
34
|
+
const target = new Uint8Array(hexTarget.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
|
|
35
|
+
outer: for (let i = 0; i <= data.length - target.length; i++) {
|
|
36
|
+
for (let j = 0; j < target.length; j++) {
|
|
37
|
+
if (data[i + j] !== target[j])
|
|
38
|
+
continue outer;
|
|
39
|
+
}
|
|
40
|
+
return i;
|
|
41
|
+
}
|
|
42
|
+
return -1;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=flashing-makecode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flashing-makecode.js","sourceRoot":"","sources":["../../../lib/flashing/flashing-makecode.ts"],"names":[],"mappings":"AAGA,MAAM,aAAa,GAAG,kCAAkC,CAAC;AAEzD;;GAEG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAC3C,SAAoB,EACpB,gBAA4B,EACT,EAAE;IACrB,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QACtD,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;YACjC,MAAM,UAAU,GAAG,KAAK,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;YAEnC,8EAA8E;YAC9E,IAAI,GAAG,GAAG,KAAK,CAAC;YAChB,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC3C,MAAM,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;gBAC1C,IAAI,QAAQ,GAAG,KAAK,IAAI,SAAS,GAAG,gBAAgB,CAAC,GAAG,EAAE,CAAC;oBACzD,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;gBAChE,CAAC;YACH,CAAC;YACD,oCAAoC;YACpC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;YAE/B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAU,EAAE;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;SACrB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;SAC/D,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC,CAAC;AAEF,SAAS,gBAAgB,CAAC,IAAgB,EAAE,SAAiB;IAC3D,MAAM,MAAM,GAAG,IAAI,UAAU,CAC3B,SAAS,CAAC,KAAK,CAAC,SAAS,CAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAC9D,CAAC;IAEF,KAAK,EAAE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC;gBAAE,SAAS,KAAK,CAAC;QAChD,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import MemoryMap from "nrf-intel-hex";
|
|
2
|
+
import { BluetoothDeviceWrapper } from "../bluetooth-device-wrapper.js";
|
|
3
|
+
import { ProgressCallback } from "../device.js";
|
|
4
|
+
export declare enum PartialFlashResult {
|
|
5
|
+
Success = "Success",
|
|
6
|
+
AttemptFullFlash = "AttemptFullFlash"
|
|
7
|
+
}
|
|
8
|
+
declare const partialFlash: (connection: BluetoothDeviceWrapper, memoryMap: MemoryMap, progress: ProgressCallback) => Promise<PartialFlashResult>;
|
|
9
|
+
export default partialFlash;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { PacketState, PartialFlashingService, RegionId, } from "../partial-flashing-service.js";
|
|
2
|
+
import { findMakeCodeRegionInMemoryMap } from "./flashing-makecode.js";
|
|
3
|
+
import { delay, DisconnectError } from "../async-util.js";
|
|
4
|
+
import { DeviceError, ProgressStage } from "../device.js";
|
|
5
|
+
export var PartialFlashResult;
|
|
6
|
+
(function (PartialFlashResult) {
|
|
7
|
+
PartialFlashResult["Success"] = "Success";
|
|
8
|
+
PartialFlashResult["AttemptFullFlash"] = "AttemptFullFlash";
|
|
9
|
+
})(PartialFlashResult || (PartialFlashResult = {}));
|
|
10
|
+
const partialFlash = async (connection, memoryMap, progress) => {
|
|
11
|
+
const pf = new PartialFlashingService(connection);
|
|
12
|
+
await pf.startNotifications();
|
|
13
|
+
const result = await connection.raceDisconnectAndTimeout(partialFlashInternal(connection, pf, memoryMap, progress), { timeout: 30_000, actionName: "partial flash" });
|
|
14
|
+
try {
|
|
15
|
+
await pf.stopNotifications();
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
// V1 disconnects quickly after a partial flash.
|
|
19
|
+
if (!(e instanceof DisconnectError)) {
|
|
20
|
+
connection.error("Error stopping notifications", e);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
const partialFlashInternal = async (connection, pf, memoryMap, progress) => {
|
|
26
|
+
connection.log("Partial flash");
|
|
27
|
+
progress(ProgressStage.PartialFlashing);
|
|
28
|
+
try {
|
|
29
|
+
const deviceCodeRegion = await pf.getRegionInfo(RegionId.MakeCode);
|
|
30
|
+
if (deviceCodeRegion === null) {
|
|
31
|
+
connection.log("Could not read code region");
|
|
32
|
+
return PartialFlashResult.AttemptFullFlash;
|
|
33
|
+
}
|
|
34
|
+
const deviceDalRegion = await pf.getRegionInfo(RegionId.Dal);
|
|
35
|
+
if (deviceDalRegion === null) {
|
|
36
|
+
connection.log("Could not read DAL region");
|
|
37
|
+
return PartialFlashResult.AttemptFullFlash;
|
|
38
|
+
}
|
|
39
|
+
progress(ProgressStage.PartialFlashing);
|
|
40
|
+
const fileCodeRegion = findMakeCodeRegionInMemoryMap(memoryMap, deviceCodeRegion);
|
|
41
|
+
if (fileCodeRegion === null) {
|
|
42
|
+
connection.log("No partial flash data");
|
|
43
|
+
return PartialFlashResult.AttemptFullFlash;
|
|
44
|
+
}
|
|
45
|
+
if (fileCodeRegion.hash !== deviceDalRegion.hash) {
|
|
46
|
+
connection.log(`DAL hash comparison failed. Hex: ${fileCodeRegion.hash} vs device: ${deviceDalRegion.hash}`);
|
|
47
|
+
return PartialFlashResult.AttemptFullFlash;
|
|
48
|
+
}
|
|
49
|
+
if (deviceCodeRegion.start !== fileCodeRegion.start) {
|
|
50
|
+
connection.log("Code start address doesn't match");
|
|
51
|
+
return PartialFlashResult.AttemptFullFlash;
|
|
52
|
+
}
|
|
53
|
+
let nextPacketNumber = 0;
|
|
54
|
+
outer: for (let offset = fileCodeRegion.start; offset < fileCodeRegion.end;) {
|
|
55
|
+
const batchStartAddress = offset;
|
|
56
|
+
for (let packetInBatch = 0; packetInBatch < 4; ++packetInBatch) {
|
|
57
|
+
const packetNumber = nextPacketNumber++;
|
|
58
|
+
const packetDataOffset = offset + packetInBatch * 16;
|
|
59
|
+
if (packetInBatch < 3) {
|
|
60
|
+
await pf.writeFlash(memoryMap, batchStartAddress, packetDataOffset, packetNumber, packetInBatch);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const result = await pf.writeFlashForNotification(memoryMap, batchStartAddress, packetDataOffset, packetNumber, packetInBatch);
|
|
64
|
+
if (result === PacketState.Retransmit) {
|
|
65
|
+
// Retry the whole 64 bytes.
|
|
66
|
+
connection.log(`Retransmit requested at offset ${offset}`);
|
|
67
|
+
continue outer;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
progress(ProgressStage.PartialFlashing, (offset - fileCodeRegion.start) /
|
|
71
|
+
(fileCodeRegion.end - fileCodeRegion.start));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
offset += 64;
|
|
76
|
+
}
|
|
77
|
+
await delay(100); // allow time for write to complete
|
|
78
|
+
await pf.writeEndOfFlashPacket();
|
|
79
|
+
await delay(100); // allow time for write to complete
|
|
80
|
+
progress(ProgressStage.PartialFlashing, 1);
|
|
81
|
+
return PartialFlashResult.Success;
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
connection.error("Partial flash failed", e);
|
|
85
|
+
if (e instanceof DeviceError) {
|
|
86
|
+
throw e;
|
|
87
|
+
}
|
|
88
|
+
throw new DeviceError({
|
|
89
|
+
code: "flash-partial-failed",
|
|
90
|
+
message: e instanceof Error ? e.message : String(e),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
export default partialFlash;
|
|
95
|
+
//# sourceMappingURL=flashing-partial.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flashing-partial.js","sourceRoot":"","sources":["../../../lib/flashing/flashing-partial.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1 changes the service it offers in application/bootloader mode.
|
|
3
|
+
*
|
|
4
|
+
* We don't trust Android to have an up-to-date copy of services so will fall back
|
|
5
|
+
* to calling internal API via reflection if the desired/expected service is not
|
|
6
|
+
* listed.
|
|
7
|
+
*
|
|
8
|
+
* It might be that this is only needed for older versions of Android where we
|
|
9
|
+
* can't get service changed indications.
|
|
10
|
+
*/
|
|
11
|
+
export declare const refreshServicesForV1IfDesiredServiceMissing: (deviceId: string, desiredServiceUuid: string) => Promise<void>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BleClient } from "@capacitor-community/bluetooth-le";
|
|
2
|
+
/**
|
|
3
|
+
* V1 changes the service it offers in application/bootloader mode.
|
|
4
|
+
*
|
|
5
|
+
* We don't trust Android to have an up-to-date copy of services so will fall back
|
|
6
|
+
* to calling internal API via reflection if the desired/expected service is not
|
|
7
|
+
* listed.
|
|
8
|
+
*
|
|
9
|
+
* It might be that this is only needed for older versions of Android where we
|
|
10
|
+
* can't get service changed indications.
|
|
11
|
+
*/
|
|
12
|
+
export const refreshServicesForV1IfDesiredServiceMissing = async (deviceId, desiredServiceUuid) => {
|
|
13
|
+
const services = await BleClient.getServices(deviceId);
|
|
14
|
+
const deviceHasService = services.some((s) => s.uuid === desiredServiceUuid);
|
|
15
|
+
if (!deviceHasService) {
|
|
16
|
+
// On Android this does use the refresh reflection hack.
|
|
17
|
+
await BleClient.discoverServices(deviceId);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=flashing-v1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flashing-v1.js","sourceRoot":"","sources":["../../../lib/flashing/flashing-v1.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,2CAA2C,GAAG,KAAK,EAC9D,QAAgB,EAChB,kBAA0B,EAC1B,EAAE;IACF,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACvD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;IAC7E,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,wDAAwD;QACxD,MAAM,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { BluetoothDeviceWrapper } from "../bluetooth-device-wrapper.js";
|
|
2
|
+
import { BoardVersion, ProgressCallback } from "../device";
|
|
3
|
+
export declare function flashDfu(connection: BluetoothDeviceWrapper, boardVersion: BoardVersion, appBin: Uint8Array, progress: ProgressCallback): Promise<void>;
|