@robotical/webapp-types 3.17.51 → 3.17.52

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 (37) hide show
  1. package/dist-types/src/application/ApplicationManager/ApplicationManager.d.ts +13 -10
  2. package/dist-types/src/application/ApplicationManager/ApplicationManager.js +147 -76
  3. package/dist-types/src/application/RAFTs/Cog/Cog.d.ts +1 -1
  4. package/dist-types/src/application/RAFTs/Cog/Cog.js +1 -1
  5. package/dist-types/src/application/RAFTs/Marty/CalibrationManager.d.ts +1 -1
  6. package/dist-types/src/application/RAFTs/Marty/CalibrationManager.js +1 -1
  7. package/dist-types/src/application/RAFTs/Marty/Marty.d.ts +1 -1
  8. package/dist-types/src/application/RAFTs/Marty/Marty.js +1 -1
  9. package/dist-types/src/application/RAFTs/Marty/MartyWifiManager.d.ts +1 -1
  10. package/dist-types/src/application/RAFTs/Marty/MartyWifiManager.js +1 -1
  11. package/dist-types/src/application/RAFTs/Marty/notifications-manager/ReportedWarningsState.js +1 -1
  12. package/dist-types/src/application/RAFTs/RAFT.d.ts +1 -1
  13. package/dist-types/src/application/RAFTs/RAFT.js +2 -2
  14. package/dist-types/src/application/RAFTs/RAFTInterface.d.ts +1 -1
  15. package/dist-types/src/application/RAFTs/RaftObserver.d.ts +1 -1
  16. package/dist-types/src/application/RAFTs/raft-subscription-helpers.js +1 -1
  17. package/dist-types/src/components/modals/LEDLightsOrQRVerificationModal/index.js +1 -2
  18. package/dist-types/src/components/modals/VerificationModal/index.js +0 -8
  19. package/dist-types/src/components/modals/VerificationModalPhoneApp/index.js +17 -32
  20. package/dist-types/src/components/oneoffs/LEDs/index.js +1 -1
  21. package/dist-types/src/types/raft.d.ts +1 -1
  22. package/dist-types/src/utils/helpers/wifi-configuration-subtitle-gen.d.ts +1 -1
  23. package/dist-types/src/utils/helpers/wifi-configuration-subtitle-gen.js +1 -1
  24. package/dist-types/src/wrapper-app/WrapperAppManager.d.ts +16 -7
  25. package/dist-types/src/wrapper-app/WrapperAppManager.js +225 -55
  26. package/dist-types/src/wrapper-app/communicators/WebAppCommunicator.js +3 -6
  27. package/dist-types/src/wrapper-app/connectors/CogConnector/CogConnector.d.ts +1 -1
  28. package/dist-types/src/wrapper-app/connectors/CogConnector/CogConnector.js +1 -1
  29. package/dist-types/src/wrapper-app/connectors/Connector.d.ts +14 -2
  30. package/dist-types/src/wrapper-app/connectors/Connector.js +25 -1
  31. package/dist-types/src/wrapper-app/connectors/ConnectorFactory.d.ts +1 -1
  32. package/dist-types/src/wrapper-app/connectors/ConnectorFactory.js +24 -3
  33. package/dist-types/src/wrapper-app/connectors/ConnectorInterface.d.ts +1 -1
  34. package/dist-types/src/wrapper-app/connectors/MartyConnector/MartyConnector.d.ts +1 -1
  35. package/dist-types/src/wrapper-app/connectors/MartyConnector/MartyConnector.js +1 -1
  36. package/dist-types/src/wrapper-app/utils/ColourSensorManualCalibratorMarty.d.ts +1 -1
  37. package/package.json +10 -1
@@ -69,11 +69,8 @@ import { raftConnectingSubscriptionHelper, raftDiscoveryFinishedSubscriptionHelp
69
69
  import isPhoneApp from "../../../utils/phone-app-communication/is-phone-app";
70
70
  import LoadingSpinner from "../../disposables/LoadingSpinner";
71
71
  import { RaftConnectionMethod } from "../../../types/raft";
72
- import { useConnectedRafts } from "../../../store/SelectedRaftContext";
73
72
  import { ConnManager } from "@robotical/roboticaljs";
74
73
  import { useTranslation } from "react-i18next";
75
- var SHOW_LOGS = true;
76
- var TAG = "VerificationModalPhone";
77
74
  function VerificationModalPhoneApp(_a) {
78
75
  var _this = this;
79
76
  var foundRICs = _a.foundRICs;
@@ -84,7 +81,6 @@ function VerificationModalPhoneApp(_a) {
84
81
  var _e = useState(false), isLoading = _e[0], setIsLoading = _e[1];
85
82
  var _f = useState(isPhoneApp()), isScanning = _f[0], setIsScanning = _f[1];
86
83
  var _g = useState(), connectedRaft = _g[0], setConnectedRaft = _g[1];
87
- var removeConnectedRaft = useConnectedRafts().removeConnectedRaft;
88
84
  useEffect(function () {
89
85
  raftDiscoveryFinishedSubscriptionHelper().subscribe(function () { return setIsScanning(false); });
90
86
  raftDiscoveryStartedSubscriptionHelper().subscribe(function () { return setIsScanning(true); });
@@ -112,20 +108,16 @@ function VerificationModalPhoneApp(_a) {
112
108
  return __generator(this, function (_a) {
113
109
  switch (_a.label) {
114
110
  case 0:
115
- if (!connectedRaft) return [3 /*break*/, 3];
111
+ if (!connectedRaft) return [3 /*break*/, 2];
116
112
  return [4 /*yield*/, window.applicationManager.stopVerifyingRaft(connectedRaft.id, false)];
117
113
  case 1:
118
114
  _a.sent();
119
- return [4 /*yield*/, window.applicationManager.disconnectFromRaft(connectedRaft.id)];
120
- case 2:
115
+ return [3 /*break*/, 4];
116
+ case 2: return [4 /*yield*/, window.applicationManager.stopDiscovery()];
117
+ case 3:
121
118
  _a.sent();
122
- removeConnectedRaft(connectedRaft.id);
123
- return [3 /*break*/, 5];
124
- case 3: return [4 /*yield*/, window.applicationManager.stopDiscovery()];
119
+ _a.label = 4;
125
120
  case 4:
126
- _a.sent();
127
- _a.label = 5;
128
- case 5:
129
121
  raftFoundSubscriptionHelper().unsubscribe();
130
122
  modalState.closeModal();
131
123
  return [2 /*return*/];
@@ -137,23 +129,20 @@ function VerificationModalPhoneApp(_a) {
137
129
  switch (_a.label) {
138
130
  case 0:
139
131
  modalState.closeModalWithoutAnimation();
140
- if (!connectedRaft) return [3 /*break*/, 3];
132
+ if (!connectedRaft) return [3 /*break*/, 2];
141
133
  return [4 /*yield*/, window.applicationManager.stopVerifyingRaft(connectedRaft.id, false)];
142
134
  case 1:
143
135
  _a.sent();
144
- return [4 /*yield*/, window.applicationManager.disconnectFromRaft(connectedRaft.id)];
136
+ _a.label = 2;
145
137
  case 2:
146
- _a.sent();
147
- _a.label = 3;
148
- case 3:
149
138
  setSelectedRICIdx(-1);
150
139
  setConnectedRaft(undefined);
151
- if (!window.applicationManager.ricSelectedCb) return [3 /*break*/, 5];
140
+ if (!window.applicationManager.ricSelectedCb) return [3 /*break*/, 4];
152
141
  return [4 /*yield*/, window.applicationManager.startDiscovery(window.applicationManager.ricSelectedCb, window.applicationManager.lastUUIDsUsed ? window.applicationManager.lastUUIDsUsed : [ConnManager.COGUUID, ConnManager.RICUUID])];
153
- case 4:
142
+ case 3:
154
143
  _a.sent();
155
- _a.label = 5;
156
- case 5: return [2 /*return*/];
144
+ _a.label = 4;
145
+ case 4: return [2 /*return*/];
157
146
  }
158
147
  });
159
148
  }); };
@@ -186,28 +175,24 @@ function VerificationModalPhoneApp(_a) {
186
175
  switch (_a.label) {
187
176
  case 0:
188
177
  setIsLoading(true);
189
- if (!connectedRaft) return [3 /*break*/, 3];
178
+ if (!connectedRaft) return [3 /*break*/, 2];
190
179
  return [4 /*yield*/, window.applicationManager.stopVerifyingRaft(connectedRaft.id, false)];
191
180
  case 1:
192
181
  _a.sent();
193
- return [4 /*yield*/, window.applicationManager.disconnectFromRaft(connectedRaft.id)];
182
+ _a.label = 2;
194
183
  case 2:
195
- _a.sent();
196
- removeConnectedRaft(connectedRaft.id);
197
- _a.label = 3;
198
- case 3:
199
184
  setSelectedRICIdx(raftIdx);
200
185
  raftFoundSubscriptionHelper().unsubscribe();
201
- if (!foundRICsState) return [3 /*break*/, 5];
186
+ if (!foundRICsState) return [3 /*break*/, 4];
202
187
  foundRaft = foundRICsState[raftIdx];
203
188
  return [4 /*yield*/, window.applicationManager.selectRaft(foundRaft, RaftConnectionMethod.PHONE_BLE)];
204
- case 4:
189
+ case 3:
205
190
  newRaft = _a.sent();
206
191
  if (!newRaft)
207
192
  return [2 /*return*/];
208
193
  setConnectedRaft(newRaft);
209
- _a.label = 5;
210
- case 5:
194
+ _a.label = 4;
195
+ case 4:
211
196
  setIsLoading(false);
212
197
  return [2 /*return*/];
213
198
  }
@@ -10,7 +10,7 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { RaftUtils } from "@robotical/raftjs";
13
+ import { RaftUtils } from "@robdobsn/raftjs";
14
14
  import "./styles.css";
15
15
  import { RaftTypeE } from "../../../types/raft";
16
16
  export default function LEDs(_a) {
@@ -1,4 +1,4 @@
1
- import type { RaftSystemInfo } from "@robotical/raftjs";
1
+ import type { RaftSystemInfo } from "@robdobsn/raftjs";
2
2
  export declare enum RaftConnectionMethod {
3
3
  WEB_SOCKET = "WebSocket",
4
4
  WEB_BLE = "WebBLE",
@@ -1,4 +1,4 @@
1
1
  import RAFT from "../../application/RAFTs/RAFT";
2
- import { RaftWifiConnStatus } from "@robotical/raftjs";
2
+ import { RaftWifiConnStatus } from "@robdobsn/raftjs";
3
3
  export declare const FW_VERSION_RSSI_WIFI = "1.2.0";
4
4
  export default function wifiConfigSub(raft: RAFT | undefined, cachedStatus: RaftWifiConnStatus | undefined): string | undefined;
@@ -1,5 +1,5 @@
1
1
  import isVersionGreater from "./compare-version";
2
- import { RaftWifiConnState } from "@robotical/raftjs";
2
+ import { RaftWifiConnState } from "@robdobsn/raftjs";
3
3
  export var FW_VERSION_RSSI_WIFI = "1.2.0"; // greater versions than this (1.1.17) have the wifi rssi logic
4
4
  export default function wifiConfigSub(raft, cachedStatus) {
5
5
  if (!raft) {
@@ -2,12 +2,16 @@ import { RaftInfoEvents } from "../types/events/raft-info";
2
2
  import type { RestMessageOptions } from "../types/communication-between-apps/wrapper-communication";
3
3
  import { ConnectionAttemptResults, RaftConnectionMethod } from "../types/raft";
4
4
  import Connector from "./connectors/Connector";
5
- import { RaftConnEvent, RaftPublishEvent, RaftUpdateEvent } from "@robotical/raftjs";
5
+ import { RaftConnEvent, RaftPublishEvent, RaftUpdateEvent } from "@robdobsn/raftjs";
6
6
  import { RICLedLcdColours } from "@robotical/roboticaljs";
7
7
  import { CustomBluetoothItem, UserDeviceInfo } from "../types/userDeviceInfo";
8
8
  import { ColourSensorCalibrationStage } from "../types/colour-sensor-calibration";
9
9
  export declare class WrapperAppManager {
10
10
  private connectors;
11
+ private _connectPromise;
12
+ private _disconnectOperations;
13
+ private _pendingConnManagers;
14
+ private _pageUnloadStarted;
11
15
  private _observers;
12
16
  constructor();
13
17
  /**
@@ -23,6 +27,7 @@ export declare class WrapperAppManager {
23
27
  *
24
28
  */
25
29
  connect(method: RaftConnectionMethod, uuids: string[]): Promise<ConnectionAttemptResults>;
30
+ private _connect;
26
31
  /**
27
32
  * Gets user's device info
28
33
  */
@@ -66,6 +71,13 @@ export declare class WrapperAppManager {
66
71
  * Disconnect from a RAFT
67
72
  */
68
73
  disconnect(raftId: string): Promise<boolean>;
74
+ /**
75
+ * Best-effort terminal cleanup. Page lifecycle events cannot reliably await
76
+ * async Bluetooth work, so each connector forwards to RaftJS synchronously.
77
+ */
78
+ disconnectAllForPageUnload(): void;
79
+ private _disconnectConnManagerForPageUnload;
80
+ isConnected(raftId: string): boolean;
69
81
  /**
70
82
  * Audio streaming
71
83
  */
@@ -78,12 +90,9 @@ export declare class WrapperAppManager {
78
90
  /**
79
91
  * Send a REST message to the RAFT
80
92
  */
81
- sendRestMessage(msg: string, params: object | undefined, raftId: string, options?: RestMessageOptions): Promise<import("@robotical/raftjs").RaftOKFail>;
82
- /**
83
- * Removes marty after a certain time
84
- * Removes from the martys list after x seconds so that we can still get the last event
85
- */
86
- _removeRICConnector(connectorId: string, timeout: number): void;
93
+ sendRestMessage(msg: string, params: object | undefined, raftId: string, options?: RestMessageOptions): Promise<import("@robdobsn/raftjs").RaftOKFail>;
94
+ private _removeConnectorIfCurrent;
95
+ private _handleDisconnectedEvent;
87
96
  /**
88
97
  * Warranty Service bluetooth scan for device
89
98
  * It scans for a device and gets the device object
@@ -45,7 +45,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
45
45
  };
46
46
  import { WrapperSentMessage } from "../types/communication-between-apps/wrapper-communication";
47
47
  import Logger from "../services/logger/Logger";
48
- import { RaftConnEvent } from "@robotical/raftjs";
48
+ import { RaftConnEvent } from "@robdobsn/raftjs";
49
49
  import { ConnManager } from "@robotical/roboticaljs";
50
50
  import ConnectorFactory from "./connectors/ConnectorFactory";
51
51
  import ColourSensorManualCalibratorMarty from "./utils/ColourSensorManualCalibratorMarty";
@@ -56,6 +56,10 @@ var WrapperAppManager = /** @class */ (function () {
56
56
  function WrapperAppManager() {
57
57
  // Connectors
58
58
  this.connectors = {};
59
+ this._connectPromise = null;
60
+ this._disconnectOperations = {};
61
+ this._pendingConnManagers = new Set();
62
+ this._pageUnloadStarted = false;
59
63
  // Observers
60
64
  this._observers = {};
61
65
  }
@@ -74,35 +78,120 @@ var WrapperAppManager = /** @class */ (function () {
74
78
  *
75
79
  */
76
80
  WrapperAppManager.prototype.connect = function (method, uuids) {
81
+ var _this = this;
82
+ if (this._pageUnloadStarted) {
83
+ return Promise.resolve({ success: false, reason: "failed" });
84
+ }
85
+ if (this._connectPromise) {
86
+ return this._connectPromise;
87
+ }
88
+ if (Object.values(this._disconnectOperations).some(Boolean)) {
89
+ Logger.warn(SHOW_LOGS, TAG, "Refusing to start a connection while Bluetooth teardown is in progress");
90
+ return Promise.resolve({ success: false, reason: "failed" });
91
+ }
92
+ var connectPromise = this._connect(method, uuids);
93
+ this._connectPromise = connectPromise;
94
+ var clearConnectPromise = function () {
95
+ if (_this._connectPromise === connectPromise) {
96
+ _this._connectPromise = null;
97
+ }
98
+ };
99
+ void connectPromise.then(clearConnectPromise, clearConnectPromise);
100
+ return connectPromise;
101
+ };
102
+ WrapperAppManager.prototype._connect = function (method, uuids) {
77
103
  return __awaiter(this, void 0, void 0, function () {
78
- var connector, connectionResults, raftSystemUtils, systemInfo, raftName;
104
+ var connector, pendingConnManager, committed, disconnectedBeforeCommit, ownedConnector_1, connectionResults, existingConnector, raftSystemUtils, systemInfo, raftName, error_1;
105
+ var _this = this;
79
106
  return __generator(this, function (_a) {
80
107
  switch (_a.label) {
81
- case 0: return [4 /*yield*/, ConnectorFactory.connectToRaftHelper(method, uuids)];
108
+ case 0:
109
+ connector = null;
110
+ pendingConnManager = null;
111
+ committed = false;
112
+ disconnectedBeforeCommit = false;
113
+ _a.label = 1;
82
114
  case 1:
115
+ _a.trys.push([1, , 4, 11]);
116
+ return [4 /*yield*/, ConnectorFactory.connectToRaftHelper(method, uuids, function (connManager) {
117
+ pendingConnManager = connManager;
118
+ _this._pendingConnManagers.add(connManager);
119
+ if (_this._pageUnloadStarted) {
120
+ _this._disconnectConnManagerForPageUnload(connManager);
121
+ }
122
+ })];
123
+ case 2:
83
124
  connector = _a.sent();
84
- if (!connector) {
125
+ if (!connector || this._pageUnloadStarted) {
85
126
  Logger.warn(SHOW_LOGS, TAG, "Failed to connect to RAFT with method: ".concat(method));
86
127
  return [2 /*return*/, { success: false, reason: "failed" }];
87
128
  }
88
- return [4 /*yield*/, connector.connect()];
89
- case 2:
90
- connectionResults = _a.sent();
91
- if (connectionResults.success) {
92
- this.connectors[connector.id] = connector;
93
- raftSystemUtils = connector.connManager.getConnector().getRaftSystemUtils();
94
- systemInfo = raftSystemUtils.getCachedSystemInfo() || undefined;
95
- raftName = raftSystemUtils.getCachedRaftName() || raftSystemUtils.getFriendlyName();
96
- if (systemInfo && (raftName === null || raftName === void 0 ? void 0 : raftName.friendlyName)) {
97
- systemInfo.Friendly = raftName.friendlyName;
129
+ ownedConnector_1 = connector;
130
+ connector.setOnDisconnected(function () {
131
+ if (!committed) {
132
+ disconnectedBeforeCommit = true;
98
133
  }
99
- connectionResults.data = { raftId: connector.id, raftType: connector.type, systemInfo: systemInfo };
134
+ _this._handleDisconnectedEvent(ownedConnector_1);
135
+ });
136
+ if (disconnectedBeforeCommit || !connector.connManager.isConnected()) {
137
+ return [2 /*return*/, { success: false, reason: "failed" }];
100
138
  }
101
- else {
139
+ return [4 /*yield*/, connector.connect()];
140
+ case 3:
141
+ connectionResults = _a.sent();
142
+ if (!connectionResults.success) {
102
143
  Logger.warn(SHOW_LOGS, TAG, "Failed to connect to RAFT with id: ".concat(connector.id, " and type: ").concat(connector.type));
144
+ return [2 /*return*/, connectionResults];
145
+ }
146
+ if (this._pageUnloadStarted ||
147
+ disconnectedBeforeCommit ||
148
+ !connector.connManager.isConnected()) {
149
+ Logger.warn(SHOW_LOGS, TAG, "RAFT disconnected before setup completed: ".concat(connector.id));
150
+ return [2 /*return*/, { success: false, reason: "failed" }];
151
+ }
152
+ existingConnector = this.connectors[connector.id];
153
+ if (existingConnector && existingConnector !== connector) {
154
+ Logger.warn(SHOW_LOGS, TAG, "Refusing to replace active RAFT connector with id: ".concat(connector.id));
155
+ return [2 /*return*/, { success: false, reason: "failed" }];
156
+ }
157
+ raftSystemUtils = connector.connManager.getConnector().getRaftSystemUtils();
158
+ systemInfo = raftSystemUtils.getCachedSystemInfo() || undefined;
159
+ raftName = raftSystemUtils.getCachedRaftName() || raftSystemUtils.getFriendlyName();
160
+ if (systemInfo && (raftName === null || raftName === void 0 ? void 0 : raftName.friendlyName)) {
161
+ systemInfo.Friendly = raftName.friendlyName;
103
162
  }
163
+ if (this._pageUnloadStarted ||
164
+ disconnectedBeforeCommit ||
165
+ !connector.connManager.isConnected()) {
166
+ return [2 /*return*/, { success: false, reason: "failed" }];
167
+ }
168
+ connectionResults.data = { raftId: connector.id, raftType: connector.type, systemInfo: systemInfo };
169
+ this.connectors[connector.id] = connector;
170
+ committed = true;
104
171
  Logger.info(SHOW_LOGS, TAG, "Connected to RAFT with id: ".concat(connector.id, " and type: ").concat(connector.type));
105
172
  return [2 /*return*/, connectionResults];
173
+ case 4:
174
+ _a.trys.push([4, , 9, 10]);
175
+ if (!(connector && !committed)) return [3 /*break*/, 8];
176
+ _a.label = 5;
177
+ case 5:
178
+ _a.trys.push([5, 7, , 8]);
179
+ return [4 /*yield*/, connector.disconnect()];
180
+ case 6:
181
+ _a.sent();
182
+ return [3 /*break*/, 8];
183
+ case 7:
184
+ error_1 = _a.sent();
185
+ Logger.warn(SHOW_LOGS, TAG, "Failed to clean up uncommitted connector ".concat(connector.id, ": ").concat(error_1));
186
+ return [3 /*break*/, 8];
187
+ case 8: return [3 /*break*/, 10];
188
+ case 9:
189
+ if (pendingConnManager) {
190
+ this._pendingConnManagers.delete(pendingConnManager);
191
+ }
192
+ return [7 /*endfinally*/];
193
+ case 10: return [7 /*endfinally*/];
194
+ case 11: return [2 /*return*/];
106
195
  }
107
196
  });
108
197
  });
@@ -273,17 +362,75 @@ var WrapperAppManager = /** @class */ (function () {
273
362
  * Stop verifying RAFT
274
363
  */
275
364
  WrapperAppManager.prototype.stopVerifyingRaft = function (isCorrectRIC, raftId) {
276
- if (!isCorrectRIC) {
277
- this._removeRICConnector(raftId, 3000);
278
- }
279
- return this.connectors[raftId].stopVerifyingRaft(isCorrectRIC);
365
+ var _a, _b;
366
+ return (_b = (_a = this.connectors[raftId]) === null || _a === void 0 ? void 0 : _a.stopVerifyingRaft(isCorrectRIC)) !== null && _b !== void 0 ? _b : Promise.resolve(false);
280
367
  };
281
368
  /**
282
369
  * Disconnect from a RAFT
283
370
  */
284
371
  WrapperAppManager.prototype.disconnect = function (raftId) {
285
- this._removeRICConnector(raftId, 3000);
286
- return this.connectors[raftId].disconnect();
372
+ var _this = this;
373
+ var connector = this.connectors[raftId];
374
+ if (!connector) {
375
+ return Promise.resolve(true);
376
+ }
377
+ var inFlightDisconnect = this._disconnectOperations[raftId];
378
+ if ((inFlightDisconnect === null || inFlightDisconnect === void 0 ? void 0 : inFlightDisconnect.connector) === connector) {
379
+ return inFlightDisconnect.promise;
380
+ }
381
+ var operation = Promise.resolve().then(function () { return connector.disconnect(); });
382
+ var disconnectPromise;
383
+ disconnectPromise = operation.finally(function () {
384
+ _this._removeConnectorIfCurrent(connector);
385
+ var trackedOperation = _this._disconnectOperations[raftId];
386
+ if ((trackedOperation === null || trackedOperation === void 0 ? void 0 : trackedOperation.connector) === connector &&
387
+ trackedOperation.promise === disconnectPromise) {
388
+ delete _this._disconnectOperations[raftId];
389
+ }
390
+ });
391
+ // Register ownership before connector code runs. A connector may emit a
392
+ // terminal event synchronously while disconnect() is being invoked.
393
+ this._disconnectOperations[raftId] = { connector: connector, promise: disconnectPromise };
394
+ return disconnectPromise;
395
+ };
396
+ /**
397
+ * Best-effort terminal cleanup. Page lifecycle events cannot reliably await
398
+ * async Bluetooth work, so each connector forwards to RaftJS synchronously.
399
+ */
400
+ WrapperAppManager.prototype.disconnectAllForPageUnload = function () {
401
+ this._pageUnloadStarted = true;
402
+ var pendingConnManagers = Array.from(this._pendingConnManagers);
403
+ for (var _i = 0, pendingConnManagers_1 = pendingConnManagers; _i < pendingConnManagers_1.length; _i++) {
404
+ var connManager = pendingConnManagers_1[_i];
405
+ this._disconnectConnManagerForPageUnload(connManager);
406
+ }
407
+ var connectors = Object.values(this.connectors);
408
+ for (var _a = 0, connectors_1 = connectors; _a < connectors_1.length; _a++) {
409
+ var connector = connectors_1[_a];
410
+ try {
411
+ connector.disconnectForPageUnload();
412
+ }
413
+ catch (error) {
414
+ Logger.warn(SHOW_LOGS, TAG, "Failed page-unload cleanup for connector ".concat(connector.id, ": ").concat(error));
415
+ }
416
+ }
417
+ };
418
+ WrapperAppManager.prototype._disconnectConnManagerForPageUnload = function (connManager) {
419
+ var connManagerWithPageUnload = connManager;
420
+ try {
421
+ if (typeof connManagerWithPageUnload.disconnectForPageUnload === "function") {
422
+ connManagerWithPageUnload.disconnectForPageUnload();
423
+ return;
424
+ }
425
+ connManager.getConnector().disconnectForPageUnload();
426
+ }
427
+ catch (error) {
428
+ Logger.warn(SHOW_LOGS, TAG, "Failed pending page-unload cleanup: ".concat(error));
429
+ }
430
+ };
431
+ WrapperAppManager.prototype.isConnected = function (raftId) {
432
+ var _a, _b;
433
+ return (_b = (_a = this.connectors[raftId]) === null || _a === void 0 ? void 0 : _a.connManager.isConnected()) !== null && _b !== void 0 ? _b : false;
287
434
  };
288
435
  /**
289
436
  * Audio streaming
@@ -314,16 +461,18 @@ var WrapperAppManager = /** @class */ (function () {
314
461
  });
315
462
  });
316
463
  };
317
- /**
318
- * Removes marty after a certain time
319
- * Removes from the martys list after x seconds so that we can still get the last event
320
- */
321
- WrapperAppManager.prototype._removeRICConnector = function (connectorId, timeout) {
322
- var _this = this;
323
- var martyRemovalTimeout = setTimeout(function () {
324
- delete _this.connectors[connectorId];
325
- clearTimeout(martyRemovalTimeout);
326
- }, timeout);
464
+ WrapperAppManager.prototype._removeConnectorIfCurrent = function (connector) {
465
+ if (this.connectors[connector.id] === connector) {
466
+ delete this.connectors[connector.id];
467
+ }
468
+ };
469
+ WrapperAppManager.prototype._handleDisconnectedEvent = function (connector) {
470
+ var _a;
471
+ // A requested disconnect keeps ownership until its Promise settles. An
472
+ // unsolicited terminal event has no such Promise, so release immediately.
473
+ if (((_a = this._disconnectOperations[connector.id]) === null || _a === void 0 ? void 0 : _a.connector) !== connector) {
474
+ this._removeConnectorIfCurrent(connector);
475
+ }
327
476
  };
328
477
  /**
329
478
  * Warranty Service bluetooth scan for device
@@ -334,17 +483,19 @@ var WrapperAppManager = /** @class */ (function () {
334
483
  */
335
484
  WrapperAppManager.prototype.scanForPotentialWarrantyDevice = function (existingDevices) {
336
485
  return __awaiter(this, void 0, void 0, function () {
337
- var namesToIgnore, device_1, connector, isConnected, ricSystem, systemInfo, serialNumber, raftType, newDevice, error_1;
486
+ var namesToIgnore, warrantyConnManager, ownsTemporaryConnection, device_1, isConnected, connector, ricSystem, systemInfo, serialNumber, raftType, newDevice, error_2, error_3;
338
487
  return __generator(this, function (_a) {
339
488
  switch (_a.label) {
340
489
  case 0:
341
490
  namesToIgnore = __spreadArray([], existingDevices.map(function (item) {
342
491
  return { name: item.name || "" };
343
492
  }), true).filter(function (item) { return item.name; });
493
+ warrantyConnManager = new ConnManager();
494
+ ownsTemporaryConnection = false;
344
495
  _a.label = 1;
345
496
  case 1:
346
- _a.trys.push([1, 9, , 10]);
347
- return [4 /*yield*/, ConnManager.getInstance().getBleDevicesWithGivenNamesToIgnore(namesToIgnore)];
497
+ _a.trys.push([1, 7, 8, 14]);
498
+ return [4 /*yield*/, warrantyConnManager.getBleDevicesWithGivenNamesToIgnore(namesToIgnore)];
348
499
  case 2:
349
500
  device_1 = _a.sent();
350
501
  if (!device_1) {
@@ -353,40 +504,59 @@ var WrapperAppManager = /** @class */ (function () {
353
504
  }
354
505
  if (!!existingDevices.find(function (deviceInList) {
355
506
  return deviceInList.id === device_1.id;
356
- })) return [3 /*break*/, 7];
357
- connector = ConnManager.getInstance().getConnector();
358
- return [4 /*yield*/, connector.initializeChannel("WebBLE")];
507
+ })) return [3 /*break*/, 5];
508
+ if (this._pageUnloadStarted) {
509
+ return [2 /*return*/, existingDevices];
510
+ }
511
+ // The selected device remains outside the lease registry until
512
+ // this connection attempt. ConnManager then atomically rejects an
513
+ // ID already owned by the app instead of stealing its GATT server.
514
+ this._pendingConnManagers.add(warrantyConnManager);
515
+ ownsTemporaryConnection = true;
516
+ return [4 /*yield*/, warrantyConnManager.connect("WebBLE", device_1, [ConnManager.RICUUID, ConnManager.COGUUID])];
359
517
  case 3:
360
- _a.sent();
361
- return [4 /*yield*/, connector.connect(device_1)];
362
- case 4:
363
518
  isConnected = _a.sent();
364
519
  if (!isConnected) {
365
520
  Logger.warn(SHOW_LOGS, TAG, "Failed to connect to device: ".concat(device_1.name));
366
521
  return [2 /*return*/, existingDevices];
367
522
  }
523
+ connector = warrantyConnManager.getConnector();
368
524
  ricSystem = connector.getRaftSystemUtils();
369
525
  return [4 /*yield*/, ricSystem.getSystemInfo()];
370
- case 5:
526
+ case 4:
371
527
  systemInfo = _a.sent();
372
528
  serialNumber = systemInfo.SerialNo || "";
373
529
  raftType = systemInfo.SystemName;
374
- return [4 /*yield*/, connector.disconnect()];
375
- case 6:
376
- _a.sent();
377
530
  newDevice = { id: device_1.id, name: device_1.name || "", serialNumber: serialNumber, type: raftType };
378
531
  existingDevices.push(newDevice);
379
532
  Logger.info(SHOW_LOGS, TAG, "".concat(device_1.name, " added to the list of robots."));
380
533
  return [2 /*return*/, existingDevices];
381
- case 7:
534
+ case 5:
382
535
  Logger.warn(SHOW_LOGS, TAG, "".concat(device_1.name, " is already in the list of robots."));
383
- _a.label = 8;
384
- case 8: return [3 /*break*/, 10];
385
- case 9:
386
- error_1 = _a.sent();
387
- Logger.error(SHOW_LOGS, TAG, JSON.stringify(error_1));
536
+ _a.label = 6;
537
+ case 6: return [3 /*break*/, 14];
538
+ case 7:
539
+ error_2 = _a.sent();
540
+ Logger.error(SHOW_LOGS, TAG, JSON.stringify(error_2));
388
541
  return [2 /*return*/, existingDevices];
389
- case 10: return [2 /*return*/, existingDevices];
542
+ case 8:
543
+ if (!ownsTemporaryConnection) return [3 /*break*/, 13];
544
+ _a.label = 9;
545
+ case 9:
546
+ _a.trys.push([9, 11, 12, 13]);
547
+ return [4 /*yield*/, warrantyConnManager.disconnect()];
548
+ case 10:
549
+ _a.sent();
550
+ return [3 /*break*/, 13];
551
+ case 11:
552
+ error_3 = _a.sent();
553
+ Logger.warn(SHOW_LOGS, TAG, "Failed warranty connection cleanup: ".concat(error_3));
554
+ return [3 /*break*/, 13];
555
+ case 12:
556
+ this._pendingConnManagers.delete(warrantyConnManager);
557
+ return [7 /*endfinally*/];
558
+ case 13: return [7 /*endfinally*/];
559
+ case 14: return [2 /*return*/, existingDevices];
390
560
  }
391
561
  });
392
562
  });
@@ -396,7 +566,7 @@ var WrapperAppManager = /** @class */ (function () {
396
566
  */
397
567
  WrapperAppManager.prototype.sendAtomicReadOperationToMarty = function (raftId) {
398
568
  return __awaiter(this, void 0, void 0, function () {
399
- var raftConnector, systemType, error_2;
569
+ var raftConnector, systemType, error_4;
400
570
  return __generator(this, function (_a) {
401
571
  switch (_a.label) {
402
572
  case 0:
@@ -412,8 +582,8 @@ var WrapperAppManager = /** @class */ (function () {
412
582
  _a.sent();
413
583
  return [2 /*return*/, true];
414
584
  case 3:
415
- error_2 = _a.sent();
416
- Logger.error(SHOW_LOGS, TAG, "Failed to send atomic read operation to Marty: ".concat(error_2));
585
+ error_4 = _a.sent();
586
+ Logger.error(SHOW_LOGS, TAG, "Failed to send atomic read operation to Marty: ".concat(error_4));
417
587
  return [3 /*break*/, 4];
418
588
  case 4: return [3 /*break*/, 6];
419
589
  case 5:
@@ -116,7 +116,7 @@ var WebAppCommunicator = /** @class */ (function () {
116
116
  }());
117
117
  export default WebAppCommunicator;
118
118
  var receivedMessageHandler = function (receivedMessage, data, messagePromiseId) { return __awaiter(void 0, void 0, void 0, function () {
119
- var _a, connectionResults, error_1, ricName, error_2, verifyResults, error_3, confirmVerifiedResults, error_4, stopVerifyResults, error_5, disconnectResults, error_6, restResults, error_7, missedConnEventResults, streamAudioResults, commsStats, calibrateColourSensorResults, error_8, resetColourSensorResults, error_9, deviceInfoResults, wasSaved, wasSaved, fileContents, existingDevices, devices, error_10, wasSent, error_11;
119
+ var _a, isConnected, connectionResults, error_1, ricName, error_2, verifyResults, error_3, confirmVerifiedResults, error_4, stopVerifyResults, error_5, disconnectResults, error_6, restResults, error_7, missedConnEventResults, streamAudioResults, commsStats, calibrateColourSensorResults, error_8, resetColourSensorResults, error_9, deviceInfoResults, wasSaved, wasSaved, fileContents, existingDevices, devices, error_10, wasSent, error_11;
120
120
  return __generator(this, function (_b) {
121
121
  switch (_b.label) {
122
122
  case 0:
@@ -146,11 +146,8 @@ var receivedMessageHandler = function (receivedMessage, data, messagePromiseId)
146
146
  return [3 /*break*/, 54];
147
147
  case 1:
148
148
  try {
149
- console.log("3");
150
- // const connectionResults = await wrapperAppManager.isConnected();
151
- console.log("12");
152
- // console.log("raft is connected results", connectionResults);
153
- window.wrapperCommunicator.onMessageResponse({ success: true, error: "", results: { log: "13" }, messagePromiseId: messagePromiseId });
149
+ isConnected = wrapperAppManager.isConnected(data.raftId);
150
+ window.wrapperCommunicator.onMessageResponse({ success: true, error: "", results: isConnected, messagePromiseId: messagePromiseId });
154
151
  }
155
152
  catch (error) {
156
153
  window.wrapperCommunicator.onMessageResponse({ success: false, error: error.message, messagePromiseId: messagePromiseId });
@@ -2,7 +2,7 @@ import { RaftInfoEvents } from "../../../types/events/raft-info";
2
2
  import { ConnectionAttemptResults, RaftTypeE } from "../../../types/raft";
3
3
  import Connector from "../Connector";
4
4
  import ConnectorInterface from "../ConnectorInterface";
5
- import { RaftConnEvent, RaftPublishEvent, RaftUpdateEvent } from "@robotical/raftjs";
5
+ import { RaftConnEvent, RaftPublishEvent, RaftUpdateEvent } from "@robdobsn/raftjs";
6
6
  import { ConnManager } from "@robotical/roboticaljs";
7
7
  declare class CogConnector extends Connector implements ConnectorInterface {
8
8
  type: RaftTypeE;
@@ -53,7 +53,7 @@ import { RaftInfoEvents } from "../../../types/events/raft-info";
53
53
  import Logger from "../../../services/logger/Logger";
54
54
  import { RaftTypeE } from "../../../types/raft";
55
55
  import Connector from "../Connector";
56
- import { RaftConnEvent, RaftPublishEvent, RaftUpdateEvent } from "@robotical/raftjs";
56
+ import { RaftConnEvent, RaftPublishEvent, RaftUpdateEvent } from "@robdobsn/raftjs";
57
57
  import { CogPublishedDataGetter } from "@robotical/roboticaljs";
58
58
  import { WrapperSentMessage } from "../../../types/communication-between-apps/wrapper-communication";
59
59
  var SHOW_LOGS = true;